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)
{
}