Print this page
4827 nfs4: slow file locking
4837 NFSv4 client lock retry delay upper limit should be shorter

*** 33,42 **** --- 33,46 ---- /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ + /* + * Copyright (c) 2014, STRATO AG. All rights reserved. + */ + #include <sys/param.h> #include <sys/types.h> #include <sys/systm.h> #include <sys/cred.h> #include <sys/time.h>
*** 288,299 **** * wait on pending writes. */ #define NFS4_WRITE_NOWAIT 0 #define NFS4_WRITE_WAIT 1 - #define NFS4_BASE_WAIT_TIME 1 /* 1 second */ - /* * Error flags used to pass information about certain special errors * which need to be handled specially. */ #define NFS_EOF -98 --- 292,301 ----
*** 360,369 **** --- 362,377 ---- void *lockt_denied_debug; #endif /* + * In milliseconds. Should be less than half of the lease time or better, + * less than one second. + */ + int nfs4_base_wait_time = 20; + + /* * How long to wait before trying again if OPEN_CONFIRM gets ETIMEDOUT * or NFS4ERR_RESOURCE. */ static int confirm_retry_sec = 30;
*** 12971,12984 **** flock64_t *flk, short *whencep, vnode_t *vp, cred_t *search_cr, cred_t **cred_otw) { /* * set tick_delay to the base delay time. ! * (NFS4_BASE_WAIT_TIME is in secs) */ ! *tick_delayp = drv_usectohz(NFS4_BASE_WAIT_TIME * 1000 * 1000); /* * If lock is relative to EOF, we need the newest length of the * file. Therefore invalidate the ATTR_CACHE. */ --- 12979,12992 ---- flock64_t *flk, short *whencep, vnode_t *vp, cred_t *search_cr, cred_t **cred_otw) { /* * set tick_delay to the base delay time. ! * (nfs4_base_wait_time is in msecs) */ ! *tick_delayp = drv_usectohz(nfs4_base_wait_time * 1000); /* * If lock is relative to EOF, we need the newest length of the * file. Therefore invalidate the ATTR_CACHE. */
*** 14745,14786 **** } /* * Wait for 'tick_delay' clock ticks. * Implement exponential backoff until hit the lease_time of this nfs4_server. ! * NOTE: lock_lease_time is in seconds. * * XXX For future improvements, should implement a waiting queue scheme. */ static int nfs4_block_and_wait(clock_t *tick_delay, rnode4_t *rp) { ! long milliseconds_delay; ! time_t lock_lease_time; /* wait tick_delay clock ticks or siginteruptus */ if (delay_sig(*tick_delay)) { return (EINTR); } NFS4_DEBUG(nfs4_client_lock_debug, (CE_NOTE, "nfs4_block_and_wait: " "reissue the lock request: blocked for %ld clock ticks: %ld " "milliseconds", *tick_delay, drv_hztousec(*tick_delay) / 1000)); ! /* get the lease time */ ! lock_lease_time = r2lease_time(rp); ! ! /* drv_hztousec converts ticks to microseconds */ ! milliseconds_delay = drv_hztousec(*tick_delay) / 1000; ! if (milliseconds_delay < lock_lease_time * 1000) { ! *tick_delay = 2 * *tick_delay; ! if (drv_hztousec(*tick_delay) > lock_lease_time * 1000 * 1000) ! *tick_delay = drv_usectohz(lock_lease_time*1000*1000); } return (0); } - void nfs4_vnops_init(void) { } --- 14753,14808 ---- } /* * Wait for 'tick_delay' clock ticks. * Implement exponential backoff until hit the lease_time of this nfs4_server. ! * ! * The client should retry to acquire the lock faster than the lease period. ! * We use roughly half of the lease time to use a similar calculation as it is ! * used in nfs4_renew_lease_thread(). * * XXX For future improvements, should implement a waiting queue scheme. */ static int nfs4_block_and_wait(clock_t *tick_delay, rnode4_t *rp) { ! long max_msec_delay = 1 * 1000; /* 1 sec */ ! nfs4_server_t *sp; ! mntinfo4_t *mi = VTOMI4(RTOV4(rp)); /* wait tick_delay clock ticks or siginteruptus */ if (delay_sig(*tick_delay)) { return (EINTR); } + NFS4_DEBUG(nfs4_client_lock_debug, (CE_NOTE, "nfs4_block_and_wait: " "reissue the lock request: blocked for %ld clock ticks: %ld " "milliseconds", *tick_delay, drv_hztousec(*tick_delay) / 1000)); ! /* ! * Get the current lease time and propagation time for the server ! * associated with the given file. Note that both times could ! * change immediately after this section. ! */ ! nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, 0); ! sp = find_nfs4_server(mi); ! if (sp != NULL) { ! if (!(mi->mi_vfsp->vfs_flag & VFS_UNMOUNTED)) { ! max_msec_delay = sp->s_lease_time * 1000 / 2 - ! (3 * sp->propagation_delay.tv_sec * ! 1000); } + mutex_exit(&sp->s_lock); + nfs4_server_rele(sp); + } + nfs_rw_exit(&mi->mi_recovlock); + + max_msec_delay = MAX(max_msec_delay, nfs4_base_wait_time); + *tick_delay = MIN(drv_usectohz(max_msec_delay * 1000), *tick_delay * 2); return (0); } void nfs4_vnops_init(void) { }