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