--- old/usr/src/uts/common/fs/nfs/nfs4_rnode.c	2014-05-12 10:06:21.059836000 +0200
+++ new/usr/src/uts/common/fs/nfs/nfs4_rnode.c	2014-05-12 10:06:21.071804000 +0200
@@ -1612,44 +1612,6 @@
 }
 
 /*
- * Return the current lease time for the server associated with the given
- * file.  Note that the lease time could change immediately after this
- * call.
- */
-
-time_t
-r2lease_time(rnode4_t *rp)
-{
-	nfs4_server_t	*sp;
-	time_t		lease_time;
-	mntinfo4_t	*mi = VTOMI4(RTOV4(rp));
-
-	(void) nfs_rw_enter_sig(&mi->mi_recovlock, RW_READER, 0);
-
-	/* this locks down sp if it is found */
-	sp = find_nfs4_server(VTOMI4(RTOV4(rp)));
-
-	if (VTOMI4(RTOV4(rp))->mi_vfsp->vfs_flag & VFS_UNMOUNTED) {
-		if (sp != NULL) {
-			mutex_exit(&sp->s_lock);
-			nfs4_server_rele(sp);
-		}
-		nfs_rw_exit(&mi->mi_recovlock);
-		return (1);		/* 1 second */
-	}
-
-	ASSERT(sp != NULL);
-
-	lease_time = sp->s_lease_time;
-
-	mutex_exit(&sp->s_lock);
-	nfs4_server_rele(sp);
-	nfs_rw_exit(&mi->mi_recovlock);
-
-	return (lease_time);
-}
-
-/*
  * Return a list with information about all the known open instances for
  * a filesystem. The caller must call r4releopenlist() when done with the
  * list.
--- old/usr/src/uts/common/fs/nfs/nfs4_vnops.c	2014-05-12 10:06:21.364771000 +0200
+++ new/usr/src/uts/common/fs/nfs/nfs4_vnops.c	2014-05-12 10:06:21.377796000 +0200
@@ -35,6 +35,10 @@
  * 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>
@@ -290,8 +294,6 @@
 #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.
@@ -362,6 +364,12 @@
 #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.
  */
@@ -12973,10 +12981,10 @@
 {
 	/*
 	 * set tick_delay to the base delay time.
-	 * (NFS4_BASE_WAIT_TIME is in secs)
+	 * (nfs4_base_wait_time is in msecs)
 	 */
 
-	*tick_delayp = drv_usectohz(NFS4_BASE_WAIT_TIME * 1000 * 1000);
+	*tick_delayp = drv_usectohz(nfs4_base_wait_time * 1000);
 
 	/*
 	 * If lock is relative to EOF, we need the newest length of the
@@ -14747,38 +14755,52 @@
 /*
  * 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.
+ *
+ * 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 milliseconds_delay;
-	time_t lock_lease_time;
+	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 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);
+	/*
+	 * 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)
 {
--- old/usr/src/uts/common/nfs/rnode4.h	2014-05-12 10:06:22.102796000 +0200
+++ new/usr/src/uts/common/nfs/rnode4.h	2014-05-12 10:06:22.110782000 +0200
@@ -427,7 +427,6 @@
 extern int	nfs4_free_data_reclaim(rnode4_t *);
 extern void	nfs4_rnode_invalidate(struct vfs *);
 
-extern time_t	r2lease_time(rnode4_t *);
 extern int	nfs4_directio(vnode_t *, int, cred_t *);
 
 /* shadow vnode functions */
