Skip to contentSkip to conversation

NFSd state containerization

RFC PATCH In review Stanislav Kinsbursky 3 participants 21 messages Nov 14, 2012 – Nov 22, 2012

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

v2 cover NFSd state containerization

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:
1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

v2:
1) Rebased on current nfsd-next.
2) Legacy tracker init become clearer.

The following series implements...

---

Stanislav Kinsbursky (15):
nfsd: use service net instead of hard-coded net where possible
nfsd: make nfs4_client network namespace dependent
nfsd: make reclaim_str_hashtbl allocated per net
nfsd: make conf_id_hashtbl allocated per net
nfsd: make conf_name_tree per net
nfsd: make unconf_id_hashtbl allocated per net
nfsd: make unconf_name_tree per net
nfsd: make ownerstr_hashtbl allocated per net
nfsd: make lockowner_ino_hashtbl allocated per net
nfsd: make sessionid_hashtbl allocated per net
nfsd: make client_lru list per net
nfsd: make close_lru list per net
nfsd: use service net instead of hard-coded init_net
nfsd: pass nfsd_net instead of net to grace enders
nfsd: make laundromat network namespace aware

 fs/nfsd/netns.h        |   43 +++++
 fs/nfsd/nfs4callback.c |    2 
 fs/nfsd/nfs4proc.c     |   13 +
 fs/nfsd/nfs4recover.c  |  102 ++++++++---
 fs/nfsd/nfs4state.c    |  450 +++++++++++++++++++++++++++---------------------
 fs/nfsd/state.h        |   17 +-
 fs/nfsd/xdr4.h         |    2 
 7 files changed, 389 insertions(+), 240 deletions(-)
#1 lore raw

PATCH v2 1/15 nfsd: use service net instead of hard-coded net where possible

---
 fs/nfsd/nfs4state.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +5 -5
index 37b19f7..743c622 100644
@@ -2281,7 +2281,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net	*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (STALE_CLIENTID(clid, nn))
 		return nfserr_stale_clientid;
@@ -3151,7 +3151,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
 	struct nfs4_client *clp;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	nfs4_lock_state();
 	dprintk("process_renew(%08x/%08x): starting\n", 
@@ -4104,7 +4104,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	bool new_state = false;
 	int lkflg;
 	int err;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
 		(long long) lock->lk_offset,
@@ -4277,7 +4277,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct file_lock *file_lock = NULL;
 	struct nfs4_lockowner *lo;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (locks_in_grace(SVC_NET(rqstp)))
 		return nfserr_grace;
@@ -4453,7 +4453,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
 	struct list_head matches;
 	unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
 		clid->cl_boot, clid->cl_id);
#2 lore raw

PATCH v2 2/15 nfsd: make nfs4_client network namespace dependent

In reply to Stanislav Kinsbursky

And use it's net where possible.

---
 fs/nfsd/nfs4callback.c |    2 +-
 fs/nfsd/nfs4recover.c  |    9 +++------
 fs/nfsd/nfs4state.c    |   15 +++++++++------
 fs/nfsd/state.h        |    1 +
 4 files changed, 14 insertions(+), 13 deletions(-)
fs/nfsd/nfs4callback.c +1 -1
index 7bb187a..8bbe873 100644
@@ -663,7 +663,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
 		.to_retries	= 0,
 	};
 	struct rpc_create_args args = {
-		.net		= &init_net,
+		.net		= clp->net,
 		.address	= (struct sockaddr *) &conn->cb_addr,
 		.addrsize	= conn->cb_addrlen,
 		.saddress	= (struct sockaddr *) &conn->cb_saddr,
fs/nfsd/nfs4recover.c +3 -6
index b03b6aa..9881bca 100644
@@ -859,8 +859,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if it's already stored */
@@ -897,8 +896,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if it's already removed */
@@ -935,8 +933,7 @@ nfsd4_cld_check(struct nfs4_client *clp)
 {
 	int ret;
 	struct cld_upcall *cup;
-	/* FIXME: determine net from clp */
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	/* Don't upcall if one was already stored during this grace pd */
fs/nfsd/nfs4state.c +9 -6
index 743c622..9b4df00 100644
@@ -1263,10 +1263,9 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
 	return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
 }
 
-static void gen_clid(struct nfs4_client *clp)
+static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
 {
 	static u32 current_clientid = 1;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	clp->cl_clientid.cl_boot = nn->boot_time;
 	clp->cl_clientid.cl_id = current_clientid++; 
@@ -1305,6 +1304,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
 	struct nfs4_client *clp;
 	struct sockaddr *sa = svc_addr(rqstp);
 	int ret;
+	struct net *net = SVC_NET(rqstp);
 
 	clp = alloc_client(name);
 	if (clp == NULL)
@@ -1335,6 +1335,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
 	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
 	gen_confirm(clp);
 	clp->cl_cb_session = NULL;
+	clp->net = net;
 	return clp;
 }
 
@@ -1471,7 +1472,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_r
 	else
 		goto out_err;
 
-	conn->cb_addrlen = rpc_uaddr2sockaddr(&init_net, se->se_callback_addr_val,
+	conn->cb_addrlen = rpc_uaddr2sockaddr(clp->net, se->se_callback_addr_val,
 					    se->se_callback_addr_len,
 					    (struct sockaddr *)&conn->cb_addr,
 					    sizeof(conn->cb_addr));
@@ -1619,6 +1620,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 	nfs4_verifier		verf = exid->verifier;
 	struct sockaddr		*sa = svc_addr(rqstp);
 	bool	update = exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A;
+	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	rpc_ntop(sa, addr_str, sizeof(addr_str));
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
@@ -1701,7 +1703,7 @@ out_new:
 	}
 	new->cl_minorversion = 1;
 
-	gen_clid(new);
+	gen_clid(new, nn);
 	add_to_unconfirmed(new);
 out_copy:
 	exid->clientid.cl_boot = new->cl_clientid.cl_boot;
@@ -2229,7 +2231,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	nfs4_verifier		clverifier = setclid->se_verf;
 	struct nfs4_client	*conf, *unconf, *new;
 	__be32 			status;
-	
+	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
 	/* Cases below refer to rfc 3530 section 14.2.33: */
 	nfs4_lock_state();
 	conf = find_confirmed_client_by_name(&clname);
@@ -2258,7 +2261,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		/* case 1: probable callback update */
 		copy_clid(new, conf);
 	else /* case 4 (new client) or cases 2, 3 (client reboot): */
-		gen_clid(new);
+		gen_clid(new, nn);
 	new->cl_minorversion = 0;
 	gen_callback(new, setclid, rqstp);
 	add_to_unconfirmed(new);
fs/nfsd/state.h +1 -0
index 029217a..ca8ee8c 100644
@@ -283,6 +283,7 @@ struct nfs4_client {
 	unsigned long		cl_cb_slot_busy;
 	struct rpc_wait_queue	cl_cb_waitq;	/* backchannel callers may */
 						/* wait here for slots */
+	struct net		*net;
 };
 
 static inline void
#3 lore raw

PATCH v2 3/15 nfsd: make reclaim_str_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.

Note: this hash is used only by legacy tracker. So let's allocate hash in tracker init.

---
 fs/nfsd/netns.h       |   12 ++++++
 fs/nfsd/nfs4recover.c |  100 ++++++++++++++++++++++++++++++++++++++-----------
 fs/nfsd/nfs4state.c   |   42 +++++++--------------
 fs/nfsd/state.h       |   12 +++---
 4 files changed, 111 insertions(+), 55 deletions(-)
fs/nfsd/netns.h +12 -0
index 65c2431..49e5479 100644
@@ -24,6 +24,11 @@
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
+/* Hash tables for nfs4_clientid state */
+#define CLIENT_HASH_BITS                 4
+#define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
+#define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
+
 struct cld_net;
 
 struct nfsd_net {
@@ -38,6 +43,13 @@ struct nfsd_net {
 	struct lock_manager nfsd4_manager;
 	bool grace_ended;
 	time_t boot_time;
+
+	/*
+	 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
+	 * used in reboot/reset lease grace period processing
+	 */
+	struct list_head *reclaim_str_hashtbl;
+	int reclaim_str_hashtbl_size;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4recover.c +77 -23

232 lines not on this page · raw message

fs/nfsd/nfs4state.c +15 -27

126 lines not on this page · raw message

fs/nfsd/state.h +7 -5
index ca8ee8c..26a912c 100644
@@ -466,9 +466,10 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
 		stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
-void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *);
-extern void nfs4_release_reclaim(void);
-extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir);
+void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
+extern void nfs4_release_reclaim(struct nfsd_net *);
+extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
+							struct nfsd_net *nn);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
@@ -482,8 +483,9 @@ extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
 extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
-extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name);
-extern bool nfs4_has_reclaimed_state(const char *name);
+extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
+							struct nfsd_net *nn);
+extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
 extern void release_session_client(struct nfsd4_session *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 
#4 lore raw

PATCH v2 4/15 nfsd: make conf_id_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.

Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.

---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   75 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 55 insertions(+), 21 deletions(-)
fs/nfsd/netns.h +1 -0
index 49e5479..0cc85e9 100644
@@ -50,6 +50,7 @@ struct nfsd_net {
 	 */
 	struct list_head *reclaim_str_hashtbl;
 	int reclaim_str_hashtbl_size;
+	struct list_head *conf_id_hashtbl;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +54 -21

194 lines not on this page · raw message

#5 lore raw

PATCH v2 5/15 nfsd: make conf_name_tree per net

In reply to Stanislav Kinsbursky

This tree holds nfs4_clients info, which are network namespace aware. So let's make it per network namespace.

---
 fs/nfsd/netns.h     |    4 ++++
 fs/nfsd/nfs4state.c |   31 ++++++++++++++++---------------
 2 files changed, 20 insertions(+), 15 deletions(-)
fs/nfsd/netns.h +4 -0
index 0cc85e9..afd9116 100644
@@ -47,10 +47,14 @@ struct nfsd_net {
 	/*
 	 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
 	 * used in reboot/reset lease grace period processing
+	 *
+	 * conf_id_hashtbl[], and conf_name_tree hold confirmed
+	 * setclientid_confirmed info.
 	 */
 	struct list_head *reclaim_str_hashtbl;
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
+	struct rb_root conf_name_tree;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +16 -15
index 7b02c47..ff03573 100644
@@ -404,9 +404,6 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * conf_id_hashtbl[], and conf_name_tree hold confirmed
- * setclientid_confirmed info.
- *
  * unconf_id_hashtbl[] and unconf_name_tree hold unconfirmed
  * setclientid info.
  *
@@ -419,7 +416,6 @@ static unsigned int clientstr_hashval(const char *name)
  * All of the above fields are protected by the client_mutex.
  */
 static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
-static struct rb_root conf_name_tree;
 static struct rb_root unconf_name_tree;
 static struct list_head client_lru;
 static struct list_head close_lru;
@@ -1114,6 +1110,7 @@ destroy_client(struct nfs4_client *clp)
 	struct nfs4_openowner *oo;
 	struct nfs4_delegation *dp;
 	struct list_head reaplist;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
@@ -1136,7 +1133,7 @@ destroy_client(struct nfs4_client *clp)
 		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
 	list_del(&clp->cl_idhash);
 	if (test_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags))
-		rb_erase(&clp->cl_namenode, &conf_name_tree);
+		rb_erase(&clp->cl_namenode, &nn->conf_name_tree);
 	else
 		rb_erase(&clp->cl_namenode, &unconf_name_tree);
 	spin_lock(&client_lock);
@@ -1389,7 +1386,7 @@ move_to_confirmed(struct nfs4_client *clp)
 	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
 	list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
 	rb_erase(&clp->cl_namenode, &unconf_name_tree);
-	add_clp_to_name_tree(clp, &conf_name_tree);
+	add_clp_to_name_tree(clp, &nn->conf_name_tree);
 	set_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
 	renew_client(clp);
 }
@@ -1433,9 +1430,9 @@ static bool clp_used_exchangeid(struct nfs4_client *clp)
 } 
 
 static struct nfs4_client *
-find_confirmed_client_by_name(struct xdr_netobj *name)
+find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn)
 {
-	return find_clp_in_name_tree(name, &conf_name_tree);
+	return find_clp_in_name_tree(name, &nn->conf_name_tree);
 }
 
 static struct nfs4_client *
@@ -1635,7 +1632,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 
 	/* Cases below refer to rfc 5661 section 18.35.4: */
 	nfs4_lock_state();
-	conf = find_confirmed_client_by_name(&exid->clname);
+	conf = find_confirmed_client_by_name(&exid->clname, nn);
 	if (conf) {
 		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
 		bool verfs_match = same_verf(&verf, &conf->cl_verifier);
@@ -1829,7 +1826,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 			status = nfserr_seq_misordered;
 			goto out_free_conn;
 		}
-		old = find_confirmed_client_by_name(&unconf->cl_name);
+		old = find_confirmed_client_by_name(&unconf->cl_name, nn);
 		if (old)
 			expire_client(old);
 		move_to_confirmed(unconf);
@@ -2227,7 +2224,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	/* Cases below refer to rfc 3530 section 14.2.33: */
 	nfs4_lock_state();
-	conf = find_confirmed_client_by_name(&clname);
+	conf = find_confirmed_client_by_name(&clname, nn);
 	if (conf) {
 		/* case 0: */
 		status = nfserr_clid_inuse;
@@ -2309,7 +2306,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 		nfsd4_probe_callback(conf);
 		expire_client(unconf);
 	} else { /* case 3: normal case; new or rebooted client */
-		conf = find_confirmed_client_by_name(&unconf->cl_name);
+		conf = find_confirmed_client_by_name(&unconf->cl_name, nn);
 		if (conf)
 			expire_client(conf);
 		move_to_confirmed(unconf);
@@ -4726,7 +4723,6 @@ nfs4_state_init(void)
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
 	}
-	conf_name_tree = RB_ROOT;
 	unconf_name_tree = RB_ROOT;
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
@@ -4772,12 +4768,17 @@ static int nfs4_state_start_net(struct net *net)
 	nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
 			CLIENT_HASH_SIZE, GFP_KERNEL);
 	if (!nn->conf_id_hashtbl)
-		return -ENOMEM;
+		goto err;
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+	}
+	nn->conf_name_tree = RB_ROOT;
 
 	return 0;
+
+err:
+	return -ENOMEM;
 }
 
 static void
#6 lore raw

PATCH v2 6/15 nfsd: make unconf_id_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.

Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.

---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   25 +++++++++++++++----------
 2 files changed, 16 insertions(+), 10 deletions(-)
fs/nfsd/netns.h +1 -0
index afd9116..1ff781f 100644
@@ -55,6 +55,7 @@ struct nfsd_net {
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
 	struct rb_root conf_name_tree;
+	struct list_head *unconf_id_hashtbl;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +15 -10
index ff03573..b967804 100644
@@ -415,7 +415,6 @@ static unsigned int clientstr_hashval(const char *name)
  *
  * All of the above fields are protected by the client_mutex.
  */
-static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct rb_root unconf_name_tree;
 static struct list_head client_lru;
 static struct list_head close_lru;
@@ -1369,11 +1368,12 @@ static void
 add_to_unconfirmed(struct nfs4_client *clp)
 {
 	unsigned int idhashval;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	clear_bit(NFSD4_CLIENT_CONFIRMED, &clp->cl_flags);
 	add_clp_to_name_tree(clp, &unconf_name_tree);
 	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
-	list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
+	list_add(&clp->cl_idhash, &nn->unconf_id_hashtbl[idhashval]);
 	renew_client(clp);
 }
 
@@ -1409,12 +1409,12 @@ find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 }
 
 static struct nfs4_client *
-find_unconfirmed_client(clientid_t *clid, bool sessions)
+find_unconfirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 	unsigned int idhashval = clientid_hashval(clid->cl_id);
 
-	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+	list_for_each_entry(clp, &nn->unconf_id_hashtbl[idhashval], cl_idhash) {
 		if (same_clid(&clp->cl_clientid, clid)) {
 			if ((bool)clp->cl_minorversion != sessions)
 				return NULL;
@@ -1799,7 +1799,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		goto out_free_session;
 
 	nfs4_lock_state();
-	unconf = find_unconfirmed_client(&cr_ses->clientid, true);
+	unconf = find_unconfirmed_client(&cr_ses->clientid, true, nn);
 	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
 
 	if (conf) {
@@ -2143,7 +2143,7 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	nfs4_lock_state();
-	unconf = find_unconfirmed_client(&dc->clientid, true);
+	unconf = find_unconfirmed_client(&dc->clientid, true, nn);
 	conf = find_confirmed_client(&dc->clientid, true, nn);
 
 	if (conf) {
@@ -2280,7 +2280,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	nfs4_lock_state();
 
 	conf = find_confirmed_client(clid, false, nn);
-	unconf = find_unconfirmed_client(clid, false);
+	unconf = find_unconfirmed_client(clid, false, nn);
 	/*
 	 * We try hard to give out unique clientid's, so if we get an
 	 * attempt to confirm the same clientid with a different cred,
@@ -4720,9 +4720,6 @@ nfs4_state_init(void)
 {
 	int i;
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
-	}
 	unconf_name_tree = RB_ROOT;
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
@@ -4769,14 +4766,21 @@ static int nfs4_state_start_net(struct net *net)
 			CLIENT_HASH_SIZE, GFP_KERNEL);
 	if (!nn->conf_id_hashtbl)
 		goto err;
+	nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->unconf_id_hashtbl)
+		goto err_unconf_id;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
 	}
 	nn->conf_name_tree = RB_ROOT;
 
 	return 0;
 
+err_unconf_id:
+	kfree(nn->conf_id_hashtbl);
 err:
 	return -ENOMEM;
 }
@@ -4794,6 +4798,7 @@ __nfs4_state_shutdown_net(struct net *net)
 			destroy_client(clp);
 		}
 	}
+	kfree(nn->unconf_id_hashtbl);
 	kfree(nn->conf_id_hashtbl);
 }
 
#7 lore raw

PATCH v2 7/15 nfsd: make unconf_name_tree per net

In reply to Stanislav Kinsbursky

This hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.

---
 fs/nfsd/netns.h     |    4 ++++
 fs/nfsd/nfs4state.c |   42 +++++++++++++++++++-----------------------
 2 files changed, 23 insertions(+), 23 deletions(-)
fs/nfsd/netns.h +4 -0
index 1ff781f..1e76030 100644
@@ -50,12 +50,16 @@ struct nfsd_net {
 	 *
 	 * conf_id_hashtbl[], and conf_name_tree hold confirmed
 	 * setclientid_confirmed info.
+	 *
+	 * unconf_str_hastbl[] and unconf_name_tree hold unconfirmed
+	 * setclientid info.
 	 */
 	struct list_head *reclaim_str_hashtbl;
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
 	struct rb_root conf_name_tree;
 	struct list_head *unconf_id_hashtbl;
+	struct rb_root unconf_name_tree;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +19 -23

126 lines not on this page · raw message

#8 lore raw

PATCH v2 8/15 nfsd: make ownerstr_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds open owner state and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.

Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.

---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   41 ++++++++++++++++++++++++++---------------
 2 files changed, 27 insertions(+), 15 deletions(-)
fs/nfsd/netns.h +1 -0
index 1e76030..46cca94 100644
@@ -60,6 +60,7 @@ struct nfsd_net {
 	struct rb_root conf_name_tree;
 	struct list_head *unconf_id_hashtbl;
 	struct rb_root unconf_name_tree;
+	struct list_head *ownerstr_hashtbl;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +26 -15

138 lines not on this page · raw message

#9 lore raw

PATCH v2 9/15 nfsd: make lockowner_ino_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds file lock owners and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.

Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.

---
 fs/nfsd/netns.h     |    4 ++++
 fs/nfsd/nfs4state.c |   27 ++++++++++++++++-----------
 2 files changed, 20 insertions(+), 11 deletions(-)
fs/nfsd/netns.h +4 -0
index 46cca94..2281f6d 100644
@@ -29,6 +29,9 @@
 #define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
 #define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
 
+#define LOCKOWNER_INO_HASH_BITS		8
+#define LOCKOWNER_INO_HASH_SIZE		(1 << LOCKOWNER_INO_HASH_BITS)
+
 struct cld_net;
 
 struct nfsd_net {
@@ -61,6 +64,7 @@ struct nfsd_net {
 	struct list_head *unconf_id_hashtbl;
 	struct rb_root unconf_name_tree;
 	struct list_head *ownerstr_hashtbl;
+	struct list_head *lockowner_ino_hashtbl;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +16 -11
index 2333d15..34006a4 100644
@@ -3862,8 +3862,6 @@ out:
 
 #define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))
 
-#define LOCKOWNER_INO_HASH_BITS 8
-#define LOCKOWNER_INO_HASH_SIZE (1 << LOCKOWNER_INO_HASH_BITS)
 #define LOCKOWNER_INO_HASH_MASK (LOCKOWNER_INO_HASH_SIZE - 1)
 
 static inline u64
@@ -3893,8 +3891,6 @@ static unsigned int lockowner_ino_hashval(struct inode *inode, u32 cl_id, struct
 		& LOCKOWNER_INO_HASH_MASK;
 }
 
-static struct list_head lockowner_ino_hashtbl[LOCKOWNER_INO_HASH_SIZE];
-
 /*
  * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
  * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
@@ -3960,12 +3956,12 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
 
 static struct nfs4_lockowner *
 find_lockowner_str(struct inode *inode, clientid_t *clid,
-		struct xdr_netobj *owner)
+		   struct xdr_netobj *owner, struct nfsd_net *nn)
 {
 	unsigned int hashval = lockowner_ino_hashval(inode, clid->cl_id, owner);
 	struct nfs4_lockowner *lo;
 
-	list_for_each_entry(lo, &lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
+	list_for_each_entry(lo, &nn->lockowner_ino_hashtbl[hashval], lo_owner_ino_hash) {
 		if (same_lockowner_ino(lo, inode, clid, owner))
 			return lo;
 	}
@@ -3980,7 +3976,7 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
 	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
-	list_add(&lo->lo_owner_ino_hash, &lockowner_ino_hashtbl[inohash]);
+	list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]);
 	list_add(&lo->lo_perstateid, &open_stp->st_lockowners);
 }
 
@@ -4054,8 +4050,10 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s
 	struct nfs4_client *cl = oo->oo_owner.so_client;
 	struct nfs4_lockowner *lo;
 	unsigned int strhashval;
+	struct nfsd_net *nn = net_generic(cl->net, nfsd_net_id);
 
-	lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner);
+	lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid,
+				&lock->v.new.owner, nn);
 	if (lo) {
 		if (!cstate->minorversion)
 			return nfserr_bad_seqid;
@@ -4308,7 +4306,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 	}
 
-	lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
+	lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner, nn);
 	if (lo)
 		file_lock->fl_owner = (fl_owner_t)lo;
 	file_lock->fl_pid = current->tgid;
@@ -4726,8 +4724,6 @@ nfs4_state_init(void)
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
-	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]);
 	INIT_LIST_HEAD(&close_lru);
 	INIT_LIST_HEAD(&client_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
@@ -4771,6 +4767,10 @@ static int nfs4_state_start_net(struct net *net)
 			OWNER_HASH_SIZE, GFP_KERNEL);
 	if (!nn->ownerstr_hashtbl)
 		goto err_ownerstr;
+	nn->lockowner_ino_hashtbl = kmalloc(sizeof(struct list_head) *
+			LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
+	if (!nn->lockowner_ino_hashtbl)
+		goto err_lockowner_ino;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
@@ -4778,11 +4778,15 @@ static int nfs4_state_start_net(struct net *net)
 	}
 	for (i = 0; i < OWNER_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
+	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
 	nn->conf_name_tree = RB_ROOT;
 	nn->unconf_name_tree = RB_ROOT;
 
 	return 0;
 
+err_lockowner_ino:
+	kfree(nn->ownerstr_hashtbl);
 err_ownerstr:
 	kfree(nn->unconf_id_hashtbl);
 err_unconf_id:
@@ -4815,6 +4819,7 @@ __nfs4_state_shutdown_net(struct net *net)
 		destroy_client(clp);
 	}
 
+	kfree(nn->lockowner_ino_hashtbl);
 	kfree(nn->ownerstr_hashtbl);
 	kfree(nn->unconf_id_hashtbl);
 	kfree(nn->conf_id_hashtbl);
#10 lore raw

PATCH v2 10/15 nfsd: make sessionid_hashtbl allocated per net

In reply to Stanislav Kinsbursky

This hash holds established sessions state and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.

Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.

---
 fs/nfsd/netns.h     |    3 +++
 fs/nfsd/nfs4state.c |   28 +++++++++++++++++-----------
 2 files changed, 20 insertions(+), 11 deletions(-)
fs/nfsd/netns.h +3 -0
index 2281f6d..da33d3f 100644
@@ -32,6 +32,8 @@
 #define LOCKOWNER_INO_HASH_BITS		8
 #define LOCKOWNER_INO_HASH_SIZE		(1 << LOCKOWNER_INO_HASH_BITS)
 
+#define SESSION_HASH_SIZE	512
+
 struct cld_net;
 
 struct nfsd_net {
@@ -65,6 +67,7 @@ struct nfsd_net {
 	struct rb_root unconf_name_tree;
 	struct list_head *ownerstr_hashtbl;
 	struct list_head *lockowner_ino_hashtbl;
+	struct list_head *sessionid_hashtbl;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +17 -11
index 34006a4..0de2844 100644
@@ -632,9 +632,6 @@ static void release_openowner(struct nfs4_openowner *oo)
 	nfs4_free_openowner(oo);
 }
 
-#define SESSION_HASH_SIZE	512
-static struct list_head sessionid_hashtbl[SESSION_HASH_SIZE];
-
 static inline int
 hash_sessionid(struct nfs4_sessionid *sessionid)
 {
@@ -928,6 +925,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
 void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
 {
 	int idx;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	new->se_client = clp;
 	gen_sessionid(new);
@@ -941,7 +939,7 @@ void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4
 	kref_init(&new->se_ref);
 	idx = hash_sessionid(&new->se_sessionid);
 	spin_lock(&client_lock);
-	list_add(&new->se_hash, &sessionid_hashtbl[idx]);
+	list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]);
 	spin_lock(&clp->cl_lock);
 	list_add(&new->se_perclnt, &clp->cl_sessions);
 	spin_unlock(&clp->cl_lock);
@@ -963,15 +961,16 @@ void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4
 
 /* caller must hold client_lock */
 static struct nfsd4_session *
-find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)
+find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid, struct net *net)
 {
 	struct nfsd4_session *elem;
 	int idx;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dump_sessionid(__func__, sessionid);
 	idx = hash_sessionid(sessionid);
 	/* Search in the appropriate list */
-	list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
+	list_for_each_entry(elem, &nn->sessionid_hashtbl[idx], se_hash) {
 		if (!memcmp(elem->se_sessionid.data, sessionid->data,
 			    NFS4_MAX_SESSIONID_LEN)) {
 			return elem;
@@ -1905,7 +1904,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
 	if (!nfsd4_last_compound_op(rqstp))
 		return nfserr_not_only_op;
 	spin_lock(&client_lock);
-	cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid);
+	cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid, SVC_NET(rqstp));
 	/* Sorta weird: we only need the refcnt'ing because new_conn acquires
 	 * client_lock iself: */
 	if (cstate->session) {
@@ -1954,7 +1953,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
 	}
 	dump_sessionid(__func__, &sessionid->sessionid);
 	spin_lock(&client_lock);
-	ses = find_in_sessionid_hashtbl(&sessionid->sessionid);
+	ses = find_in_sessionid_hashtbl(&sessionid->sessionid, SVC_NET(r));
 	if (!ses) {
 		spin_unlock(&client_lock);
 		goto out;
@@ -2050,7 +2049,7 @@ nfsd4_sequence(struct svc_rqst *rqstp,
 
 	spin_lock(&client_lock);
 	status = nfserr_badsession;
-	session = find_in_sessionid_hashtbl(&seq->sessionid);
+	session = find_in_sessionid_hashtbl(&seq->sessionid, SVC_NET(rqstp));
 	if (!session)
 		goto out;
 
@@ -4719,8 +4718,6 @@ nfs4_state_init(void)
 {
 	int i;
 
-	for (i = 0; i < SESSION_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
@@ -4771,6 +4768,10 @@ static int nfs4_state_start_net(struct net *net)
 			LOCKOWNER_INO_HASH_SIZE, GFP_KERNEL);
 	if (!nn->lockowner_ino_hashtbl)
 		goto err_lockowner_ino;
+	nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
+			SESSION_HASH_SIZE, GFP_KERNEL);
+	if (!nn->sessionid_hashtbl)
+		goto err_sessionid;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
@@ -4780,11 +4781,15 @@ static int nfs4_state_start_net(struct net *net)
 		INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
 	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
+	for (i = 0; i < SESSION_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
 	nn->conf_name_tree = RB_ROOT;
 	nn->unconf_name_tree = RB_ROOT;
 
 	return 0;
 
+err_sessionid:
+	kfree(nn->lockowner_ino_hashtbl);
 err_lockowner_ino:
 	kfree(nn->ownerstr_hashtbl);
 err_ownerstr:
@@ -4819,6 +4824,7 @@ __nfs4_state_shutdown_net(struct net *net)
 		destroy_client(clp);
 	}
 
+	kfree(nn->sessionid_hashtbl);
 	kfree(nn->lockowner_ino_hashtbl);
 	kfree(nn->ownerstr_hashtbl);
 	kfree(nn->unconf_id_hashtbl);
#11 lore raw

PATCH v2 11/15 nfsd: make client_lru list per net

In reply to Stanislav Kinsbursky

This list holds nfs4 clients queue for lease renewal, which are network namespace aware. So let's make this list per network namespace too.

---
 fs/nfsd/netns.h     |    5 +++++
 fs/nfsd/nfs4state.c |   16 ++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)
fs/nfsd/netns.h +5 -0
index da33d3f..9a98a0a 100644
@@ -68,6 +68,11 @@ struct nfsd_net {
 	struct list_head *ownerstr_hashtbl;
 	struct list_head *lockowner_ino_hashtbl;
 	struct list_head *sessionid_hashtbl;
+	/*
+	 * client_lru holds client queue ordered by nfs4_client.cl_time
+	 * for lease renewal.
+	 */
+	struct list_head client_lru;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +8 -8
index 0de2844..87868ae 100644
@@ -402,15 +402,11 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * client_lru holds client queue ordered by nfs4_client.cl_time
- * for lease renewal.
- *
  * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
  * for last close replay.
  *
  * All of the above fields are protected by the client_mutex.
  */
-static struct list_head client_lru;
 static struct list_head close_lru;
 
 /*
@@ -995,6 +991,8 @@ unhash_session(struct nfsd4_session *ses)
 static inline void
 renew_client_locked(struct nfs4_client *clp)
 {
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
 	if (is_client_expired(clp)) {
 		WARN_ON(1);
 		printk("%s: client (clientid %08x/%08x) already expired\n",
@@ -1007,7 +1005,7 @@ renew_client_locked(struct nfs4_client *clp)
 	dprintk("renewing client (clientid %08x/%08x)\n", 
 			clp->cl_clientid.cl_boot, 
 			clp->cl_clientid.cl_id);
-	list_move_tail(&clp->cl_lru, &client_lru);
+	list_move_tail(&clp->cl_lru, &nn->client_lru);
 	clp->cl_time = get_seconds();
 }
 
@@ -3196,6 +3194,7 @@ nfs4_laundromat(void)
 	time_t cutoff = get_seconds() - nfsd4_lease;
 	time_t t, clientid_val = nfsd4_lease;
 	time_t u, test_val = nfsd4_lease;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
 
@@ -3203,7 +3202,7 @@ nfs4_laundromat(void)
 	nfsd4_end_grace(&init_net);
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&client_lock);
-	list_for_each_safe(pos, next, &client_lru) {
+	list_for_each_safe(pos, next, &nn->client_lru) {
 		clp = list_entry(pos, struct nfs4_client, cl_lru);
 		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
 			t = clp->cl_time - cutoff;
@@ -4590,9 +4589,10 @@ void nfsd_forget_clients(u64 num)
 {
 	struct nfs4_client *clp, *next;
 	int count = 0;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
-	list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
+	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
 		expire_client(clp);
 		if (++count == num)
 			break;
@@ -4722,7 +4722,6 @@ nfs4_state_init(void)
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
 	INIT_LIST_HEAD(&close_lru);
-	INIT_LIST_HEAD(&client_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
 }
 
@@ -4785,6 +4784,7 @@ static int nfs4_state_start_net(struct net *net)
 		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
 	nn->conf_name_tree = RB_ROOT;
 	nn->unconf_name_tree = RB_ROOT;
+	INIT_LIST_HEAD(&nn->client_lru);
 
 	return 0;
 
#12 lore raw

PATCH v2 12/15 nfsd: make close_lru list per net

In reply to Stanislav Kinsbursky

This list holds nfs4 clients (open) stateowner queue for last close replay, which are network namespace aware. So let's make this list per network namespace too.

---
 fs/nfsd/netns.h     |    6 ++++++
 fs/nfsd/nfs4state.c |   20 +++++++-------------
 2 files changed, 13 insertions(+), 13 deletions(-)
fs/nfsd/netns.h +6 -0
index 9a98a0a..a356ea3 100644
@@ -71,8 +71,14 @@ struct nfsd_net {
 	/*
 	 * client_lru holds client queue ordered by nfs4_client.cl_time
 	 * for lease renewal.
+	 *
+	 * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
+	 * for last close replay.
+	 *
+	 * All of the above fields are protected by the client_mutex.
 	 */
 	struct list_head client_lru;
+	struct list_head close_lru;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +7 -13
index 87868ae..a281a18 100644
@@ -402,14 +402,6 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
- * for last close replay.
- *
- * All of the above fields are protected by the client_mutex.
- */
-static struct list_head close_lru;
-
-/*
  * We store the NONE, READ, WRITE, and BOTH bits separately in the
  * st_{access,deny}_bmap field of the stateid, in order to track not
  * only what share bits are currently in force, but also what
@@ -2465,11 +2457,13 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
 }
 
 static void
-move_to_close_lru(struct nfs4_openowner *oo)
+move_to_close_lru(struct nfs4_openowner *oo, struct net *net)
 {
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
 	dprintk("NFSD: move_to_close_lru nfs4_openowner %p\n", oo);
 
-	list_move_tail(&oo->oo_close_lru, &close_lru);
+	list_move_tail(&oo->oo_close_lru, &nn->close_lru);
 	oo->oo_time = get_seconds();
 }
 
@@ -3242,7 +3236,7 @@ nfs4_laundromat(void)
 		unhash_delegation(dp);
 	}
 	test_val = nfsd4_lease;
-	list_for_each_safe(pos, next, &close_lru) {
+	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)) {
 			u = oo->oo_time - cutoff;
@@ -3820,7 +3814,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			 * little while to handle CLOSE replay.
 			 */
 			if (list_empty(&oo->oo_owner.so_stateids))
-				move_to_close_lru(oo);
+				move_to_close_lru(oo, SVC_NET(rqstp));
 		}
 	}
 out:
@@ -4721,7 +4715,6 @@ nfs4_state_init(void)
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
-	INIT_LIST_HEAD(&close_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
 }
 
@@ -4785,6 +4778,7 @@ static int nfs4_state_start_net(struct net *net)
 	nn->conf_name_tree = RB_ROOT;
 	nn->unconf_name_tree = RB_ROOT;
 	INIT_LIST_HEAD(&nn->client_lru);
+	INIT_LIST_HEAD(&nn->close_lru);
 
 	return 0;
 
#13 lore raw

PATCH v2 13/15 nfsd: use service net instead of hard-coded init_net

In reply to Stanislav Kinsbursky

This patch replaces init_net by SVC_NET(), where possible and also passes proper context to nested functions where required.

---
 fs/nfsd/nfs4proc.c  |   13 +++++++----
 fs/nfsd/nfs4state.c |   63 +++++++++++++++++++++++++++++++--------------------
 fs/nfsd/state.h     |    2 +-
 fs/nfsd/xdr4.h      |    2 +-
 4 files changed, 49 insertions(+), 31 deletions(-)
fs/nfsd/nfs4proc.c +9 -4
index f955176..1d2396b 100644
@@ -40,6 +40,7 @@
 #include "xdr4.h"
 #include "vfs.h"
 #include "current_stateid.h"
+#include "netns.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -304,6 +305,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
 	__be32 status;
 	struct nfsd4_compoundres *resp;
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
 		(int)open->op_fname.len, open->op_fname.data,
@@ -331,7 +334,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	/* check seqid for replay. set nfs4_owner */
 	resp = rqstp->rq_resp;
-	status = nfsd4_process_open1(&resp->cstate, open);
+	status = nfsd4_process_open1(&resp->cstate, open, nn);
 	if (status == nfserr_replay_me) {
 		struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
 		fh_put(&cstate->current_fh);
@@ -354,10 +357,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	/* Openowner is now set, so sequence id will get bumped.  Now we need
 	 * these checks before we do any creates: */
 	status = nfserr_grace;
-	if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+	if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
 		goto out;
 	status = nfserr_no_grace;
-	if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+	if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
 		goto out;
 
 	switch (open->op_claim_type) {
@@ -370,7 +373,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			break;
 		case NFS4_OPEN_CLAIM_PREVIOUS:
 			open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
-			status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
+			status = nfs4_check_open_reclaim(&open->op_clientid,
+							 cstate->minorversion,
+							 nn);
 			if (status)
 				goto out;
 		case NFS4_OPEN_CLAIM_FH:
fs/nfsd/nfs4state.c +38 -25

223 lines not on this page · raw message

fs/nfsd/state.h +1 -1
index 26a912c..bfe0106 100644
@@ -470,7 +470,7 @@ void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *)
 extern void nfs4_release_reclaim(struct nfsd_net *);
 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
 							struct nfsd_net *nn);
-extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
+extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
 extern void nfs4_free_lockowner(struct nfs4_lockowner *);
 extern int set_callback_cred(void);
fs/nfsd/xdr4.h +1 -1
index 71c5c47..3c414c1 100644
@@ -581,7 +581,7 @@ extern __be32 nfsd4_destroy_session(struct svc_rqst *,
 extern __be32 nfsd4_destroy_clientid(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_destroy_clientid *);
 __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *);
 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
-		struct nfsd4_open *open);
+		struct nfsd4_open *open, struct nfsd_net *nn);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status);
#14 lore raw

PATCH v2 14/15 nfsd: pass nfsd_net instead of net to grace enders

In reply to Stanislav Kinsbursky

Passing net context looks as overkill.

---
 fs/nfsd/nfs4recover.c |   14 ++++++--------
 fs/nfsd/nfs4state.c   |    8 +++-----
 fs/nfsd/state.h       |    2 +-
 3 files changed, 10 insertions(+), 14 deletions(-)
fs/nfsd/nfs4recover.c +6 -8
index 376692a..b657b62 100644
@@ -58,7 +58,7 @@ struct nfsd4_client_tracking_ops {
 	void (*create)(struct nfs4_client *);
 	void (*remove)(struct nfs4_client *);
 	int (*check)(struct nfs4_client *);
-	void (*grace_done)(struct net *, time_t);
+	void (*grace_done)(struct nfsd_net *, time_t);
 };
 
 /* Globals */
@@ -391,10 +391,9 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 }
 
 static void
-nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
+nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
 {
 	int status;
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	in_grace = false;
 	if (!rec_file)
@@ -1017,11 +1016,10 @@ nfsd4_cld_check(struct nfs4_client *clp)
 }
 
 static void
-nfsd4_cld_grace_done(struct net *net, time_t boot_time)
+nfsd4_cld_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
 	int ret;
 	struct cld_upcall *cup;
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	struct cld_net *cn = nn->cld_net;
 
 	cup = alloc_cld_upcall(cn);
@@ -1241,7 +1239,7 @@ nfsd4_umh_cltrack_check(struct nfs4_client *clp)
 }
 
 static void
-nfsd4_umh_cltrack_grace_done(struct net __attribute__((unused)) *net,
+nfsd4_umh_cltrack_grace_done(struct nfsd_net __attribute__((unused)) *nn,
 				time_t boot_time)
 {
 	char *legacy;
@@ -1343,10 +1341,10 @@ nfsd4_client_record_check(struct nfs4_client *clp)
 }
 
 void
-nfsd4_record_grace_done(struct net *net, time_t boot_time)
+nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time)
 {
 	if (client_tracking_ops)
-		client_tracking_ops->grace_done(net, boot_time);
+		client_tracking_ops->grace_done(nn, boot_time);
 }
 
 static int
fs/nfsd/nfs4state.c +3 -5
index 6927031..07f10fb 100644
@@ -3157,17 +3157,15 @@ out:
 }
 
 static void
-nfsd4_end_grace(struct net *net)
+nfsd4_end_grace(struct nfsd_net *nn)
 {
-	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-
 	/* do nothing if grace period already ended */
 	if (nn->grace_ended)
 		return;
 
 	dprintk("NFSD: end of grace period\n");
 	nn->grace_ended = true;
-	nfsd4_record_grace_done(net, nn->boot_time);
+	nfsd4_record_grace_done(nn, nn->boot_time);
 	locks_end_grace(&nn->nfsd4_manager);
 	/*
 	 * Now that every NFSv4 client has had the chance to recover and
@@ -3192,7 +3190,7 @@ nfs4_laundromat(void)
 	nfs4_lock_state();
 
 	dprintk("NFSD: laundromat service - starting\n");
-	nfsd4_end_grace(&init_net);
+	nfsd4_end_grace(nn);
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&client_lock);
 	list_for_each_safe(pos, next, &nn->client_lru) {
fs/nfsd/state.h +1 -1
index bfe0106..2deb6a8 100644
@@ -495,5 +495,5 @@ extern void nfsd4_client_tracking_exit(struct net *net);
 extern void nfsd4_client_record_create(struct nfs4_client *clp);
 extern void nfsd4_client_record_remove(struct nfs4_client *clp);
 extern int nfsd4_client_record_check(struct nfs4_client *clp);
-extern void nfsd4_record_grace_done(struct net *net, time_t boot_time);
+extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time);
 #endif   /* NFSD4_STATE_H */
#15 lore raw

PATCH v2 15/15 nfsd: make laundromat network namespace aware

In reply to Stanislav Kinsbursky

This patch moves laundromat_work to nfsd per-net context, thus allowing to run multiple laundries.

---
 fs/nfsd/netns.h     |    2 ++
 fs/nfsd/nfs4state.c |   21 +++++++++++++--------
 2 files changed, 15 insertions(+), 8 deletions(-)
fs/nfsd/netns.h +2 -0
index a356ea3..227b93e 100644
@@ -79,6 +79,8 @@ struct nfsd_net {
 	 */
 	struct list_head client_lru;
 	struct list_head close_lru;
+
+	struct delayed_work laundromat_work;
 };
 
 extern int nfsd_net_id;
fs/nfsd/nfs4state.c +13 -8
index 07f10fb..18d2646 100644
@@ -3176,7 +3176,7 @@ nfsd4_end_grace(struct nfsd_net *nn)
 }
 
 static time_t
-nfs4_laundromat(void)
+nfs4_laundromat(struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 	struct nfs4_openowner *oo;
@@ -3185,7 +3185,6 @@ nfs4_laundromat(void)
 	time_t cutoff = get_seconds() - nfsd4_lease;
 	time_t t, clientid_val = nfsd4_lease;
 	time_t u, test_val = nfsd4_lease;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
 
@@ -3251,16 +3250,19 @@ nfs4_laundromat(void)
 
 static struct workqueue_struct *laundry_wq;
 static void laundromat_main(struct work_struct *);
-static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
 
 static void
-laundromat_main(struct work_struct *not_used)
+laundromat_main(struct work_struct *laundry)
 {
 	time_t t;
+	struct delayed_work *dwork = container_of(laundry, struct delayed_work,
+						  work);
+	struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
+					   laundromat_work);
 
-	t = nfs4_laundromat();
+	t = nfs4_laundromat(nn);
 	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
-	queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
+	queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
 }
 
 static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
@@ -4791,6 +4793,8 @@ static int nfs4_state_start_net(struct net *net)
 	INIT_LIST_HEAD(&nn->client_lru);
 	INIT_LIST_HEAD(&nn->close_lru);
 
+	INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);
+
 	return 0;
 
 err_sessionid:
@@ -4875,7 +4879,8 @@ nfs4_state_start(void)
 	ret = nfsd4_create_callback_queue();
 	if (ret)
 		goto out_free_laundry;
-	queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
+
+	queue_delayed_work(laundry_wq, &nn->laundromat_work, nfsd4_grace * HZ);
 	set_max_delegations();
 	return 0;
 out_free_laundry:
@@ -4918,7 +4923,7 @@ nfs4_state_shutdown(void)
 	struct net *net = &init_net;
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-	cancel_delayed_work_sync(&laundromat_work);
+	cancel_delayed_work_sync(&nn->laundromat_work);
 	destroy_workqueue(laundry_wq);
 	locks_end_grace(&nn->nfsd4_manager);
 	nfs4_lock_state();
#16 lore raw
In reply to Stanislav Kinsbursky
Quoted 6 lines · Stanislav Kinsbursky

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:

Quoted 8 lines

1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

These look OK and pass my tests. Jeff, do the revised recovery bits look OK?

Have you done any testing?

It'd be interesting, for example, to know if there are any pynfs that fail against the server in a non-init network namespace, but pass normally.

--b.

Quoted 36 lines

v2:
1) Rebased on current nfsd-next.
2) Legacy tracker init become clearer.

The following series implements...

---

Stanislav Kinsbursky (15):
nfsd: use service net instead of hard-coded net where possible
nfsd: make nfs4_client network namespace dependent
nfsd: make reclaim_str_hashtbl allocated per net
nfsd: make conf_id_hashtbl allocated per net
nfsd: make conf_name_tree per net
nfsd: make unconf_id_hashtbl allocated per net
nfsd: make unconf_name_tree per net
nfsd: make ownerstr_hashtbl allocated per net
nfsd: make lockowner_ino_hashtbl allocated per net
nfsd: make sessionid_hashtbl allocated per net
nfsd: make client_lru list per net
nfsd: make close_lru list per net
nfsd: use service net instead of hard-coded init_net
nfsd: pass nfsd_net instead of net to grace enders
nfsd: make laundromat network namespace aware

 fs/nfsd/netns.h        |   43 +++++
 fs/nfsd/nfs4callback.c |    2 
 fs/nfsd/nfs4proc.c     |   13 +
 fs/nfsd/nfs4recover.c  |  102 ++++++++---
 fs/nfsd/nfs4state.c    |  450 +++++++++++++++++++++++++++---------------------
 fs/nfsd/state.h        |   17 +-
 fs/nfsd/xdr4.h         |    2 
 7 files changed, 389 insertions(+), 240 deletions(-)
#17 lore raw

15.11.2012 02:00, J. Bruce Fields пишет:

Quoted 16 lines · Stanislav Kinsbursky
Quoted 6 lines

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:

Quoted 8 lines

1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

Quoted 4 lines

These look OK and pass my tests. Jeff, do the revised recovery bits look OK?

Have you done any testing?

I've done basic testing. I.e. NFS server start/stop in loop, export, share mount on another node and some activity, etc. NFS server is not ready yet to work on container, so no such testing has been done.

Quoted 7 lines

It'd be interesting, for example, to know if there are any pynfs that fail against the server in a non-init network namespace, but pass normally.

--b.

Signature · 2 lines
Best regards,
Stanislav Kinsbursky
#18 lore raw
In reply to J. Bruce Fields
Quoted 19 lines · On Wed, 14 Nov 2012 17:00:36 -0500 "J. Bruce Fields" <[email protected]>…
Quoted 6 lines · Stanislav Kinsbursky

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:

Quoted 8 lines

1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

These look OK and pass my tests. Jeff, do the revised recovery bits look OK?

Quoted 8 lines

Have you done any testing?

It'd be interesting, for example, to know if there are any pynfs that fail against the server in a non-init network namespace, but pass normally.

--b.

I looked over the patches and they look sane to me. I move that they go into your -next branch to soak for a bit.

Cheers,

Signature · 1 line
Jeff Layton <[email protected]>
#19 lore raw
Quoted 28 lines · Jeff Layton
Quoted 25 lines · On Wed, 14 Nov 2012 17:00:36 -0500 "J. Bruce Fields" <[email protected]>…
Quoted 6 lines · Stanislav Kinsbursky

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:

Quoted 8 lines

1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

These look OK and pass my tests. Jeff, do the revised recovery bits look OK?

Have you done any testing?

It'd be interesting, for example, to know if there are any pynfs that fail against the server in a non-init network namespace, but pass normally.

Quoted 5 lines
Quoted 2 lines

--b.

I looked over the patches and they look sane to me. I move that they go into your -next branch to soak for a bit.

Stanislav, actually, I'm unclear, since you labeled these "RFC": do you consider these patches ready?

--b.

#20 lore raw

22.11.2012 00:44, J. Bruce Fields пишет:

Quoted 29 lines · Jeff Layton
Quoted 28 lines
Quoted 25 lines · On Wed, 14 Nov 2012 17:00:36 -0500 "J. Bruce Fields" <[email protected]>…
Quoted 6 lines · Stanislav Kinsbursky

This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:

Quoted 8 lines

1) making nfs4_client network namespace aware.
2) Allocating all hashes (except file_hashtbl and reclaim_str_hashtbl) per network namespace context on NFSd start (not init) and destroying on NFSd state shutdown.
3) Allocating of reclaim_str_hashtbl on legacy tracker start and destroying on legacy tracker stop.
4) Moving of client_lru and close_lru lists to per-net data.
5) Making lundromat network namespace aware.

These look OK and pass my tests. Jeff, do the revised recovery bits look OK?

Have you done any testing?

It'd be interesting, for example, to know if there are any pynfs that fail against the server in a non-init network namespace, but pass normally.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

--b.

I looked over the patches and they look sane to me. I move that they go into your -next branch to soak for a bit.

Stanislav, actually, I'm unclear, since you labeled these "RFC": do you consider these patches ready?

Yes, I consider them ready.
I added the "RFC" mark, because I'm not completely sure, this this code wont' be partially rewritten in future.

Quoted 2 lines

--b.

Signature · 2 lines
Best regards,
Stanislav Kinsbursky