2005-04-17 02:20:36 +04:00
/*
* fs / nfs / nfs4renewd . c
*
* Copyright ( c ) 2002 The Regents of the University of Michigan .
* All rights reserved .
*
* Kendrick Smith < kmsmith @ umich . edu >
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED
* WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
* BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* Implementation of the NFSv4 " renew daemon " , which wakes up periodically to
* send a RENEW , to keep state alive on the server . The daemon is implemented
* as an rpc_task , not a real kernel thread , so it always runs in rpciod ' s
* context . There is one renewd per nfs_server .
*
*/
# include <linux/mm.h>
# include <linux/pagemap.h>
# include <linux/sunrpc/sched.h>
# include <linux/sunrpc/clnt.h>
# include <linux/nfs.h>
# include <linux/nfs4.h>
# include <linux/nfs_fs.h>
2005-06-22 21:16:21 +04:00
# include "nfs4_fs.h"
2006-01-03 11:55:24 +03:00
# include "delegation.h"
2005-04-17 02:20:36 +04:00
2012-05-22 06:45:24 +04:00
# define NFSDBG_FACILITY NFSDBG_STATE
2005-04-17 02:20:36 +04:00
void
2006-11-22 17:55:48 +03:00
nfs4_renew_state ( struct work_struct * work )
2005-04-17 02:20:36 +04:00
{
2010-06-16 17:52:27 +04:00
const struct nfs4_state_maintenance_ops * ops ;
2006-11-22 17:55:48 +03:00
struct nfs_client * clp =
container_of ( work , struct nfs_client , cl_renewd . work ) ;
2006-01-03 11:55:25 +03:00
struct rpc_cred * cred ;
2010-02-05 14:45:04 +03:00
long lease ;
2005-04-17 02:20:36 +04:00
unsigned long last , now ;
2011-08-24 23:07:37 +04:00
unsigned renew_flags = 0 ;
2005-04-17 02:20:36 +04:00
2010-06-16 17:52:27 +04:00
ops = clp - > cl_mvops - > state_renewal_ops ;
2008-05-03 00:42:44 +04:00
dprintk ( " %s: start \n " , __func__ ) ;
2010-12-24 04:32:32 +03:00
2011-03-01 04:34:10 +03:00
if ( test_bit ( NFS_CS_STOP_RENEW , & clp - > cl_res_state ) )
2006-01-03 11:55:24 +03:00
goto out ;
2010-12-24 04:32:32 +03:00
2005-04-17 02:20:36 +04:00
spin_lock ( & clp - > cl_lock ) ;
lease = clp - > cl_lease_time ;
last = clp - > cl_last_renewal ;
now = jiffies ;
/* Are we close to a lease timeout? */
2011-08-24 23:07:37 +04:00
if ( time_after ( now , last + lease / 3 ) )
renew_flags | = NFS4_RENEW_TIMEOUT ;
if ( nfs_delegations_present ( clp ) )
renew_flags | = NFS4_RENEW_DELEGATION_CB ;
if ( renew_flags ! = 0 ) {
2009-04-01 17:22:46 +04:00
cred = ops - > get_state_renewal_cred_locked ( clp ) ;
2008-12-23 23:21:50 +03:00
spin_unlock ( & clp - > cl_lock ) ;
2006-01-03 11:55:25 +03:00
if ( cred = = NULL ) {
2011-08-24 23:07:37 +04:00
if ( ! ( renew_flags & NFS4_RENEW_DELEGATION_CB ) ) {
2008-12-23 23:21:50 +03:00
set_bit ( NFS4CLNT_LEASE_EXPIRED , & clp - > cl_state ) ;
goto out ;
}
2006-01-03 11:55:24 +03:00
nfs_expire_all_delegations ( clp ) ;
2008-12-23 23:21:50 +03:00
} else {
/* Queue an asynchronous RENEW. */
2011-08-24 23:07:37 +04:00
ops - > sched_state_renewal ( clp , cred , renew_flags ) ;
2008-12-23 23:21:50 +03:00
put_rpccred ( cred ) ;
2010-02-05 14:45:04 +03:00
goto out_exp ;
2006-01-03 11:55:24 +03:00
}
2010-02-05 14:45:04 +03:00
} else {
2005-04-17 02:20:36 +04:00
dprintk ( " %s: failed to call renewd. Reason: lease not expired \n " ,
2008-05-03 00:42:44 +04:00
__func__ ) ;
2010-02-05 14:45:04 +03:00
spin_unlock ( & clp - > cl_lock ) ;
}
nfs4_schedule_state_renewal ( clp ) ;
out_exp :
2008-12-23 23:21:52 +03:00
nfs_expire_unreferenced_delegations ( clp ) ;
2005-04-17 02:20:36 +04:00
out :
2008-05-03 00:42:44 +04:00
dprintk ( " %s: done \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
}
void
2006-08-23 04:06:08 +04:00
nfs4_schedule_state_renewal ( struct nfs_client * clp )
2005-04-17 02:20:36 +04:00
{
long timeout ;
spin_lock ( & clp - > cl_lock ) ;
timeout = ( 2 * clp - > cl_lease_time ) / 3 + ( long ) clp - > cl_last_renewal
- ( long ) jiffies ;
if ( timeout < 5 * HZ )
timeout = 5 * HZ ;
dprintk ( " %s: requeueing work. Lease period = %ld \n " ,
2008-05-03 00:42:44 +04:00
__func__ , ( timeout + HZ - 1 ) / HZ ) ;
2012-08-03 21:30:47 +04:00
mod_delayed_work ( system_wq , & clp - > cl_renewd , timeout ) ;
2006-08-24 09:03:05 +04:00
set_bit ( NFS_CS_RENEWD , & clp - > cl_res_state ) ;
2005-04-17 02:20:36 +04:00
spin_unlock ( & clp - > cl_lock ) ;
}
void
2006-08-23 04:06:08 +04:00
nfs4_kill_renewd ( struct nfs_client * clp )
2005-04-17 02:20:36 +04:00
{
2007-08-07 23:28:33 +04:00
cancel_delayed_work_sync ( & clp - > cl_renewd ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Local variables :
* c - basic - offset : 8
* End :
*/