18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci *  fs/nfs/nfs4renewd.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci *  Copyright (c) 2002 The Regents of the University of Michigan.
58c2ecf20Sopenharmony_ci *  All rights reserved.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Kendrick Smith <kmsmith@umich.edu>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci *  Redistribution and use in source and binary forms, with or without
108c2ecf20Sopenharmony_ci *  modification, are permitted provided that the following conditions
118c2ecf20Sopenharmony_ci *  are met:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *  1. Redistributions of source code must retain the above copyright
148c2ecf20Sopenharmony_ci *     notice, this list of conditions and the following disclaimer.
158c2ecf20Sopenharmony_ci *  2. Redistributions in binary form must reproduce the above copyright
168c2ecf20Sopenharmony_ci *     notice, this list of conditions and the following disclaimer in the
178c2ecf20Sopenharmony_ci *     documentation and/or other materials provided with the distribution.
188c2ecf20Sopenharmony_ci *  3. Neither the name of the University nor the names of its
198c2ecf20Sopenharmony_ci *     contributors may be used to endorse or promote products derived
208c2ecf20Sopenharmony_ci *     from this software without specific prior written permission.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
238c2ecf20Sopenharmony_ci *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
248c2ecf20Sopenharmony_ci *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
258c2ecf20Sopenharmony_ci *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
268c2ecf20Sopenharmony_ci *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
298c2ecf20Sopenharmony_ci *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
308c2ecf20Sopenharmony_ci *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
318c2ecf20Sopenharmony_ci *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
328c2ecf20Sopenharmony_ci *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Implementation of the NFSv4 "renew daemon", which wakes up periodically to
358c2ecf20Sopenharmony_ci * send a RENEW, to keep state alive on the server.  The daemon is implemented
368c2ecf20Sopenharmony_ci * as an rpc_task, not a real kernel thread, so it always runs in rpciod's
378c2ecf20Sopenharmony_ci * context.  There is one renewd per nfs_server.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#include <linux/mm.h>
428c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
438c2ecf20Sopenharmony_ci#include <linux/sunrpc/sched.h>
448c2ecf20Sopenharmony_ci#include <linux/sunrpc/clnt.h>
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#include <linux/nfs.h>
478c2ecf20Sopenharmony_ci#include <linux/nfs4.h>
488c2ecf20Sopenharmony_ci#include <linux/nfs_fs.h>
498c2ecf20Sopenharmony_ci#include "nfs4_fs.h"
508c2ecf20Sopenharmony_ci#include "delegation.h"
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define NFSDBG_FACILITY		NFSDBG_STATE
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_civoid
558c2ecf20Sopenharmony_cinfs4_renew_state(struct work_struct *work)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	const struct nfs4_state_maintenance_ops *ops;
588c2ecf20Sopenharmony_ci	struct nfs_client *clp =
598c2ecf20Sopenharmony_ci		container_of(work, struct nfs_client, cl_renewd.work);
608c2ecf20Sopenharmony_ci	const struct cred *cred;
618c2ecf20Sopenharmony_ci	long lease;
628c2ecf20Sopenharmony_ci	unsigned long last, now;
638c2ecf20Sopenharmony_ci	unsigned renew_flags = 0;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	ops = clp->cl_mvops->state_renewal_ops;
668c2ecf20Sopenharmony_ci	dprintk("%s: start\n", __func__);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	if (test_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state))
698c2ecf20Sopenharmony_ci		goto out;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	lease = clp->cl_lease_time;
728c2ecf20Sopenharmony_ci	last = clp->cl_last_renewal;
738c2ecf20Sopenharmony_ci	now = jiffies;
748c2ecf20Sopenharmony_ci	/* Are we close to a lease timeout? */
758c2ecf20Sopenharmony_ci	if (time_after(now, last + lease/3))
768c2ecf20Sopenharmony_ci		renew_flags |= NFS4_RENEW_TIMEOUT;
778c2ecf20Sopenharmony_ci	if (nfs_delegations_present(clp))
788c2ecf20Sopenharmony_ci		renew_flags |= NFS4_RENEW_DELEGATION_CB;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (renew_flags != 0) {
818c2ecf20Sopenharmony_ci		cred = ops->get_state_renewal_cred(clp);
828c2ecf20Sopenharmony_ci		if (cred == NULL) {
838c2ecf20Sopenharmony_ci			if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) {
848c2ecf20Sopenharmony_ci				set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
858c2ecf20Sopenharmony_ci				goto out;
868c2ecf20Sopenharmony_ci			}
878c2ecf20Sopenharmony_ci			nfs_expire_all_delegations(clp);
888c2ecf20Sopenharmony_ci		} else {
898c2ecf20Sopenharmony_ci			int ret;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci			/* Queue an asynchronous RENEW. */
928c2ecf20Sopenharmony_ci			ret = ops->sched_state_renewal(clp, cred, renew_flags);
938c2ecf20Sopenharmony_ci			put_cred(cred);
948c2ecf20Sopenharmony_ci			switch (ret) {
958c2ecf20Sopenharmony_ci			default:
968c2ecf20Sopenharmony_ci				goto out_exp;
978c2ecf20Sopenharmony_ci			case -EAGAIN:
988c2ecf20Sopenharmony_ci			case -ENOMEM:
998c2ecf20Sopenharmony_ci				break;
1008c2ecf20Sopenharmony_ci			}
1018c2ecf20Sopenharmony_ci		}
1028c2ecf20Sopenharmony_ci	} else {
1038c2ecf20Sopenharmony_ci		dprintk("%s: failed to call renewd. Reason: lease not expired \n",
1048c2ecf20Sopenharmony_ci				__func__);
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci	nfs4_schedule_state_renewal(clp);
1078c2ecf20Sopenharmony_ciout_exp:
1088c2ecf20Sopenharmony_ci	nfs_expire_unreferenced_delegations(clp);
1098c2ecf20Sopenharmony_ciout:
1108c2ecf20Sopenharmony_ci	dprintk("%s: done\n", __func__);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_civoid
1148c2ecf20Sopenharmony_cinfs4_schedule_state_renewal(struct nfs_client *clp)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	long timeout;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	spin_lock(&clp->cl_lock);
1198c2ecf20Sopenharmony_ci	timeout = (2 * clp->cl_lease_time) / 3 + (long)clp->cl_last_renewal
1208c2ecf20Sopenharmony_ci		- (long)jiffies;
1218c2ecf20Sopenharmony_ci	if (timeout < 5 * HZ)
1228c2ecf20Sopenharmony_ci		timeout = 5 * HZ;
1238c2ecf20Sopenharmony_ci	dprintk("%s: requeueing work. Lease period = %ld\n",
1248c2ecf20Sopenharmony_ci			__func__, (timeout + HZ - 1) / HZ);
1258c2ecf20Sopenharmony_ci	mod_delayed_work(system_wq, &clp->cl_renewd, timeout);
1268c2ecf20Sopenharmony_ci	set_bit(NFS_CS_RENEWD, &clp->cl_res_state);
1278c2ecf20Sopenharmony_ci	spin_unlock(&clp->cl_lock);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_civoid
1318c2ecf20Sopenharmony_cinfs4_kill_renewd(struct nfs_client *clp)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&clp->cl_renewd);
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci/**
1378c2ecf20Sopenharmony_ci * nfs4_set_lease_period - Sets the lease period on a nfs_client
1388c2ecf20Sopenharmony_ci *
1398c2ecf20Sopenharmony_ci * @clp: pointer to nfs_client
1408c2ecf20Sopenharmony_ci * @lease: new value for lease period
1418c2ecf20Sopenharmony_ci */
1428c2ecf20Sopenharmony_civoid nfs4_set_lease_period(struct nfs_client *clp,
1438c2ecf20Sopenharmony_ci		unsigned long lease)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	spin_lock(&clp->cl_lock);
1468c2ecf20Sopenharmony_ci	clp->cl_lease_time = lease;
1478c2ecf20Sopenharmony_ci	spin_unlock(&clp->cl_lock);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/* Cap maximum reconnect timeout at 1/2 lease period */
1508c2ecf20Sopenharmony_ci	rpc_set_connect_timeout(clp->cl_rpcclient, lease, lease >> 1);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci/*
1548c2ecf20Sopenharmony_ci * Local variables:
1558c2ecf20Sopenharmony_ci *   c-basic-offset: 8
1568c2ecf20Sopenharmony_ci * End:
1578c2ecf20Sopenharmony_ci */
158