Skip to contentSkip to conversation

NFSd: NFSv4 state - lease and grace times per net

PATCH In review Stanislav Kinsbursky 2 participants 9 messages Nov 27, 2012 – Nov 28, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover NFSd: NFSv4 state - lease and grace times per net

This two variables are parts of NFSv4 state and should be containerized too.

The following series implements...

---

Stanislav Kinsbursky (2):
nfsd: make NFSv4 lease time per net
nfsd: make NFSv4 grace time per net

 fs/nfsd/netns.h        |    3 +++
 fs/nfsd/nfs4callback.c |    8 +++++---
 fs/nfsd/nfs4state.c    |   18 +++++++-----------
 fs/nfsd/nfs4xdr.c      |    4 +++-
 fs/nfsd/nfsctl.c       |    9 +++++++--
 fs/nfsd/nfsd.h         |    3 ---
 6 files changed, 25 insertions(+), 20 deletions(-)
#1 lore raw

PATCH 1/2 nfsd: make NFSv4 lease time per net

Lease time is a part of NFSv4 state engine, which is constructed per network namespace.

---
 fs/nfsd/netns.h        |    2 ++
 fs/nfsd/nfs4callback.c |    8 +++++---
 fs/nfsd/nfs4state.c    |   11 +++++------
 fs/nfsd/nfs4xdr.c      |    4 +++-
 fs/nfsd/nfsctl.c       |    5 ++++-
 fs/nfsd/nfsd.h         |    1 -
 6 files changed, 19 insertions(+), 12 deletions(-)
fs/nfsd/netns.h +2 -0
index 9047706..0c20be8 100644
@@ -87,6 +87,8 @@ struct nfsd_net {
 
 	struct file *rec_file;
 	bool in_grace;
+
+	time_t nfsd4_lease;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4callback.c +5 -3
index 826cc26..99bc85f 100644
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 #include "nfsd.h"
 #include "state.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -625,9 +626,10 @@ static const struct rpc_program cb_program = {
 	.pipe_dir_name		= "nfsd4_cb",
 };
 
-static int max_cb_time(void)
+static int max_cb_time(struct net *net)
 {
-	return max(nfsd4_lease/10, (time_t)1) * HZ;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
 }
 
 static struct rpc_cred *callback_cred;
@@ -659,7 +661,7 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
 	struct rpc_timeout	timeparms = {
-		.to_initval	= max_cb_time(),
+		.to_initval	= max_cb_time(clp->net),
 		.to_retries	= 0,
 	};
 	struct rpc_create_args args = {
fs/nfsd/nfs4state.c +5 -6
index 93c7882..56b0ebb 100644
@@ -51,7 +51,6 @@
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
 /* Globals */
-time_t nfsd4_lease = 90;     /* default lease time */
 time_t nfsd4_grace = 90;
 
 #define all_ones {{~0,~0},~0}
@@ -3184,7 +3183,7 @@ nfsd4_end_grace(struct nfsd_net *nn)
 	 * to see the (possibly new, possibly shorter) lease time, we
 	 * can safely set the next grace time to the current lease time:
 	 */
-	nfsd4_grace = nfsd4_lease;
+	nfsd4_grace = nn->nfsd4_lease;
 }
 
 static time_t
@@ -3194,9 +3193,9 @@ nfs4_laundromat(struct nfsd_net *nn)
 	struct nfs4_openowner *oo;
 	struct nfs4_delegation *dp;
 	struct list_head *pos, *next, reaplist;
-	time_t cutoff = get_seconds() - nfsd4_lease;
-	time_t t, clientid_val = nfsd4_lease;
-	time_t u, test_val = nfsd4_lease;
+	time_t cutoff = get_seconds() - nn->nfsd4_lease;
+	time_t t, clientid_val = nn->nfsd4_lease;
+	time_t u, test_val = nn->nfsd4_lease;
 
 	nfs4_lock_state();
 
@@ -3245,7 +3244,7 @@ nfs4_laundromat(struct nfsd_net *nn)
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
 		unhash_delegation(dp);
 	}
-	test_val = nfsd4_lease;
+	test_val = nn->nfsd4_lease;
 	list_for_each_safe(pos, next, &nn->close_lru) {
 		oo = container_of(pos, struct nfs4_openowner, oo_close_lru);
 		if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) {
fs/nfsd/nfs4xdr.c +3 -1
index 406d0c4..6a5ab39 100644
@@ -53,6 +53,7 @@
 #include "vfs.h"
 #include "state.h"
 #include "cache.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
@@ -2091,6 +2092,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 		.mnt	= exp->ex_path.mnt,
 		.dentry	= dentry,
 	};
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
 	BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
@@ -2251,7 +2253,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 	if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
 		if ((buflen -= 4) < 0)
 			goto out_resource;
-		WRITE32(nfsd4_lease);
+		WRITE32(nn->nfsd4_lease);
 	}
 	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
 		if ((buflen -= 4) < 0)
fs/nfsd/nfsctl.c +4 -1
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);
 }
 
 /**
@@ -1063,6 +1064,7 @@ int nfsd_net_id;
 static __net_init int nfsd_init_net(struct net *net)
 {
 	int retval;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	retval = nfsd_export_init(net);
 	if (retval)
@@ -1070,6 +1072,7 @@ static __net_init int nfsd_init_net(struct net *net)
 	retval = nfsd_idmap_init(net);
 	if (retval)
 		goto out_idmap_error;
+	nn->nfsd4_lease = 90;	/* default lease time */
 	return 0;
 
 out_idmap_error:
fs/nfsd/nfsd.h +0 -1
index d7b210b..a8f7325 100644
@@ -276,7 +276,6 @@ extern struct timeval	nfssvc_boot;
 
 #ifdef CONFIG_NFSD_V4
 
-extern time_t nfsd4_lease;
 extern time_t nfsd4_grace;
 
 /* before processing a COMPOUND operation, we have to check that there
#2 lore raw

Re: [PATCH 1/2] nfsd: make NFSv4 lease time per net

fs/nfsd/nfsctl.c static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_ · line 916

Quoted 11 lines · Stanislav Kinsbursky
fs/nfsd/nfsctl.c +2 -1
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);

This is called in the context of whatever process writes to nfsv4leasetime, so should be using its network namespace, right?

--b.

#3 lore raw

Re: [PATCH 1/2] nfsd: make NFSv4 lease time per net

28.11.2012 19:09, J. Bruce Fields пишет:

Quoted 7 lines · Stanislav Kinsbursky
Quoted 6 lines
fs/nfsd/nfsctl.c +0 -0
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
   */
Quoted 9 lines

fs/nfsd/nfsctl.c static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_ · line 916

Quoted 5 lines
fs/nfsd/nfsctl.c +2 -1
  static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);

This is called in the context of whatever process writes to nfsv4leasetime, so should be using its network namespace, right?

This is, actually, a interim solution to preserve existent logic.
I.e. I'm going to convert "nfsd" filesystem into per-net one (like rpc_pipefs). I, actually, already done it in my tree. Thus proper network namespace will be taken from nfsd superblock.

Quoted 2 lines

--b.

Signature · 2 lines
Best regards,
Stanislav Kinsbursky
#4 lore raw

Re: [PATCH 1/2] nfsd: make NFSv4 lease time per net

Quoted 18 lines · Stanislav Kinsbursky

28.11.2012 19:09, J. Bruce Fields пишет:

Quoted 7 lines · Stanislav Kinsbursky
Quoted 6 lines
fs/nfsd/nfsctl.c +0 -0
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
Quoted 9 lines

fs/nfsd/nfsctl.c static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_ · line 916

Quoted 5 lines
fs/nfsd/nfsctl.c +2 -1
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);

This is called in the context of whatever process writes to nfsv4leasetime, so should be using its network namespace, right?

Quoted 3 lines

This is, actually, a interim solution to preserve existent logic.
I.e. I'm going to convert "nfsd" filesystem into per-net one (like rpc_pipefs). I, actually, already done it in my tree. Thus proper network namespace will be taken from nfsd superblock.

OK, remind me how that works? It's mounted just once, but each network namespace gets a different view of the filesystem?

--b.

#5 lore raw

Re: [PATCH 1/2] nfsd: make NFSv4 lease time per net

28.11.2012 19:15, J. Bruce Fields пишет:

Quoted 19 lines · Stanislav Kinsbursky
Quoted 18 lines

28.11.2012 19:09, J. Bruce Fields пишет:

Quoted 16 lines · Stanislav Kinsbursky

fs/nfsd/nfsctl.c static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_ · line 916

Quoted 11 lines
fs/nfsd/nfsctl.c +2 -1
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
   */
  static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);

This is called in the context of whatever process writes to nfsv4leasetime, so should be using its network namespace, right?

Quoted 7 lines
Quoted 3 lines

This is, actually, a interim solution to preserve existent logic.
I.e. I'm going to convert "nfsd" filesystem into per-net one (like rpc_pipefs). I, actually, already done it in my tree. Thus proper network namespace will be taken from nfsd superblock.

OK, remind me how that works? It's mounted just once, but each network namespace gets a different view of the filesystem?

Nope. It's a single mount point, but per-namespace (network, in our case) - not globally. Pointer to namespace will be placed on sb->s_fs_info.

Quoted 2 lines

--b.

Signature · 2 lines
Best regards,
Stanislav Kinsbursky
#6 lore raw

Re: [PATCH 1/2] nfsd: make NFSv4 lease time per net

Quoted 24 lines · Stanislav Kinsbursky

28.11.2012 19:15, J. Bruce Fields пишет:

Quoted 23 lines · Stanislav Kinsbursky
Quoted 21 lines

28.11.2012 19:09, J. Bruce Fields пишет:

Quoted 7 lines · Stanislav Kinsbursky
Quoted 6 lines
fs/nfsd/nfsctl.c +0 -0
index dab350d..4930981 100644
@@ -912,7 +912,8 @@ static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_
  */
Quoted 9 lines

fs/nfsd/nfsctl.c static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_ · line 916

Quoted 5 lines
fs/nfsd/nfsctl.c +2 -1
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_lease);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease);

This is called in the context of whatever process writes to nfsv4leasetime, so should be using its network namespace, right?

This is, actually, a interim solution to preserve existent logic.
I.e. I'm going to convert "nfsd" filesystem into per-net one (like rpc_pipefs). I, actually, already done it in my tree. Thus proper network namespace will be taken from nfsd superblock.

Quoted 6 lines
Quoted 3 lines

OK, remind me how that works? It's mounted just once, but each network namespace gets a different view of the filesystem?

Nope. It's a single mount point, but per-namespace (network, in our case) - not globally. Pointer to namespace will be placed on sb->s_fs_info.

OK, anyway, applying these.

--b.

#7 lore raw

PATCH 2/2 nfsd: make NFSv4 grace time per net

In reply to Stanislav Kinsbursky

Grace time is a part of NFSv4 state engine, which is constructed per network namespace.

---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |    9 +++------
 fs/nfsd/nfsctl.c    |    4 +++-
 fs/nfsd/nfsd.h      |    2 --
 4 files changed, 7 insertions(+), 9 deletions(-)
fs/nfsd/netns.h +1 -0
index 0c20be8..2c4b2e2 100644
@@ -89,6 +89,7 @@ struct nfsd_net {
 	bool in_grace;
 
 	time_t nfsd4_lease;
+	time_t nfsd4_grace;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +3 -6
index 56b0ebb..36d3983 100644
@@ -50,9 +50,6 @@
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
-/* Globals */
-time_t nfsd4_grace = 90;
-
 #define all_ones {{~0,~0},~0}
 static const stateid_t one_stateid = {
 	.si_generation = ~0,
@@ -3183,7 +3180,7 @@ nfsd4_end_grace(struct nfsd_net *nn)
 	 * to see the (possibly new, possibly shorter) lease time, we
 	 * can safely set the next grace time to the current lease time:
 	 */
-	nfsd4_grace = nn->nfsd4_lease;
+	nn->nfsd4_grace = nn->nfsd4_lease;
 }
 
 static time_t
@@ -4880,8 +4877,8 @@ nfs4_state_start_net(struct net *net)
 	locks_start_grace(net, &nn->nfsd4_manager);
 	nn->grace_ended = false;
 	printk(KERN_INFO "NFSD: starting %ld-second grace period (net %p)\n",
-	       nfsd4_grace, net);
-	queue_delayed_work(laundry_wq, &nn->laundromat_work, nfsd4_grace * HZ);
+	       nn->nfsd4_grace, net);
+	queue_delayed_work(laundry_wq, &nn->laundromat_work, nn->nfsd4_grace * HZ);
 	return 0;
 }
 
fs/nfsd/nfsctl.c +3 -1
index 4930981..7e41bd1 100644
@@ -928,7 +928,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  */
 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_grace);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace);
 }
 
 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
@@ -1073,6 +1074,7 @@ static __net_init int nfsd_init_net(struct net *net)
 	if (retval)
 		goto out_idmap_error;
 	nn->nfsd4_lease = 90;	/* default lease time */
+	nn->nfsd4_grace = 90;
 	return 0;
 
 out_idmap_error:
fs/nfsd/nfsd.h +0 -2
index a8f7325..5eea0f5 100644
@@ -276,8 +276,6 @@ extern struct timeval	nfssvc_boot;
 
 #ifdef CONFIG_NFSD_V4
 
-extern time_t nfsd4_grace;
-
 /* before processing a COMPOUND operation, we have to check that there
  * is enough space in the buffer for XDR encode to succeed.  otherwise,
  * we might process an operation with side effects, and be unable to
#8 lore raw

Re: [PATCH 2/2] nfsd: make NFSv4 grace time per net

fs/nfsd/nfsctl.c static ssize_t write_leasetime(struct file *file, char *buf, size_t size) · line 933

Quoted 12 lines · Stanislav Kinsbursky
fs/nfsd/nfsctl.c +2 -1
index 4930981..7e41bd1 100644
@@ -928,7 +928,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  */
 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
 {
-	return nfsd4_write_time(file, buf, size, &nfsd4_grace);
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace);
 }

Same comment as for lease time.--b.