Branch data Line data Source code
1 : : /* 2 : : * fs/nfs/nfs4renewd.c 3 : : * 4 : : * Copyright (c) 2002 The Regents of the University of Michigan. 5 : : * All rights reserved. 6 : : * 7 : : * Kendrick Smith <kmsmith@umich.edu> 8 : : * 9 : : * Redistribution and use in source and binary forms, with or without 10 : : * modification, are permitted provided that the following conditions 11 : : * are met: 12 : : * 13 : : * 1. Redistributions of source code must retain the above copyright 14 : : * notice, this list of conditions and the following disclaimer. 15 : : * 2. Redistributions in binary form must reproduce the above copyright 16 : : * notice, this list of conditions and the following disclaimer in the 17 : : * documentation and/or other materials provided with the distribution. 18 : : * 3. Neither the name of the University nor the names of its 19 : : * contributors may be used to endorse or promote products derived 20 : : * from this software without specific prior written permission. 21 : : * 22 : : * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 : : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 : : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 : : * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 : : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 : : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 : : * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 : : * 34 : : * Implementation of the NFSv4 "renew daemon", which wakes up periodically to 35 : : * send a RENEW, to keep state alive on the server. The daemon is implemented 36 : : * as an rpc_task, not a real kernel thread, so it always runs in rpciod's 37 : : * context. There is one renewd per nfs_server. 38 : : * 39 : : */ 40 : : 41 : : #include <linux/mm.h> 42 : : #include <linux/pagemap.h> 43 : : #include <linux/sunrpc/sched.h> 44 : : #include <linux/sunrpc/clnt.h> 45 : : 46 : : #include <linux/nfs.h> 47 : : #include <linux/nfs4.h> 48 : : #include <linux/nfs_fs.h> 49 : : #include "nfs4_fs.h" 50 : : #include "delegation.h" 51 : : 52 : : #define NFSDBG_FACILITY NFSDBG_STATE 53 : : 54 : : void 55 : 0 : nfs4_renew_state(struct work_struct *work) 56 : : { 57 : : const struct nfs4_state_maintenance_ops *ops; 58 : : struct nfs_client *clp = 59 : 0 : container_of(work, struct nfs_client, cl_renewd.work); 60 : : const struct cred *cred; 61 : : long lease; 62 : : unsigned long last, now; 63 : : unsigned renew_flags = 0; 64 : : 65 : 0 : ops = clp->cl_mvops->state_renewal_ops; 66 : : dprintk("%s: start\n", __func__); 67 : : 68 : 0 : if (test_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state)) 69 : : goto out; 70 : : 71 : 0 : lease = clp->cl_lease_time; 72 : 0 : last = clp->cl_last_renewal; 73 : 0 : now = jiffies; 74 : : /* Are we close to a lease timeout? */ 75 : 0 : if (time_after(now, last + lease/3)) 76 : : renew_flags |= NFS4_RENEW_TIMEOUT; 77 : 0 : if (nfs_delegations_present(clp)) 78 : 0 : renew_flags |= NFS4_RENEW_DELEGATION_CB; 79 : : 80 : 0 : if (renew_flags != 0) { 81 : 0 : cred = ops->get_state_renewal_cred(clp); 82 : 0 : if (cred == NULL) { 83 : 0 : if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) { 84 : 0 : set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 85 : 0 : goto out; 86 : : } 87 : 0 : nfs_expire_all_delegations(clp); 88 : : } else { 89 : : int ret; 90 : : 91 : : /* Queue an asynchronous RENEW. */ 92 : 0 : ret = ops->sched_state_renewal(clp, cred, renew_flags); 93 : 0 : put_cred(cred); 94 : 0 : switch (ret) { 95 : : default: 96 : : goto out_exp; 97 : : case -EAGAIN: 98 : : case -ENOMEM: 99 : : break; 100 : : } 101 : : } 102 : : } else { 103 : : dprintk("%s: failed to call renewd. Reason: lease not expired \n", 104 : : __func__); 105 : : } 106 : 0 : nfs4_schedule_state_renewal(clp); 107 : : out_exp: 108 : 0 : nfs_expire_unreferenced_delegations(clp); 109 : : out: 110 : : dprintk("%s: done\n", __func__); 111 : 0 : } 112 : : 113 : : void 114 : 0 : nfs4_schedule_state_renewal(struct nfs_client *clp) 115 : : { 116 : : long timeout; 117 : : 118 : : spin_lock(&clp->cl_lock); 119 : 0 : timeout = (2 * clp->cl_lease_time) / 3 + (long)clp->cl_last_renewal 120 : 0 : - (long)jiffies; 121 : 0 : if (timeout < 5 * HZ) 122 : : timeout = 5 * HZ; 123 : : dprintk("%s: requeueing work. Lease period = %ld\n", 124 : : __func__, (timeout + HZ - 1) / HZ); 125 : 0 : mod_delayed_work(system_wq, &clp->cl_renewd, timeout); 126 : 0 : set_bit(NFS_CS_RENEWD, &clp->cl_res_state); 127 : : spin_unlock(&clp->cl_lock); 128 : 0 : } 129 : : 130 : : void 131 : 0 : nfs4_kill_renewd(struct nfs_client *clp) 132 : : { 133 : 0 : cancel_delayed_work_sync(&clp->cl_renewd); 134 : 0 : } 135 : : 136 : : /** 137 : : * nfs4_set_lease_period - Sets the lease period on a nfs_client 138 : : * 139 : : * @clp: pointer to nfs_client 140 : : * @lease: new value for lease period 141 : : */ 142 : 0 : void nfs4_set_lease_period(struct nfs_client *clp, 143 : : unsigned long lease) 144 : : { 145 : : spin_lock(&clp->cl_lock); 146 : 0 : clp->cl_lease_time = lease; 147 : : spin_unlock(&clp->cl_lock); 148 : : 149 : : /* Cap maximum reconnect timeout at 1/2 lease period */ 150 : 0 : rpc_set_connect_timeout(clp->cl_rpcclient, lease, lease >> 1); 151 : 0 : } 152 : : 153 : : /* 154 : : * Local variables: 155 : : * c-basic-offset: 8 156 : : * End: 157 : : */