All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/15] NFSd state containerization
@ 2012-11-13 15:48 Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 01/15] nfsd: use service net instead of hard-coded net where possible Stanislav Kinsbursky
                   ` (14 more replies)
  0 siblings, 15 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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 namesapce 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.

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_str_hashtbl allocated per net
      nfsd: make unconf_str_hashtbl allocated per net
      nfsd: make unconf_str_hastbl allocated 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        |   41 ++++
 fs/nfsd/nfs4callback.c |    2 
 fs/nfsd/nfs4proc.c     |   13 +
 fs/nfsd/nfs4recover.c  |   85 +++++++--
 fs/nfsd/nfs4state.c    |  441 ++++++++++++++++++++++++++++--------------------
 fs/nfsd/state.h        |   11 +
 fs/nfsd/xdr4.h         |    2 
 7 files changed, 377 insertions(+), 218 deletions(-)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/15] nfsd: use service net instead of hard-coded net where possible
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 02/15] nfsd: make nfs4_client network namespace dependent Stanislav Kinsbursky
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/nfs4state.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d6b602a..6a3661b 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2257,7 +2257,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;
@@ -3129,7 +3129,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", 
@@ -4082,7 +4082,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,
@@ -4255,7 +4255,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;
@@ -4431,7 +4431,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);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/15] nfsd: make nfs4_client network namespace dependent
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 01/15] nfsd: use service net instead of hard-coded net where possible Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net Stanislav Kinsbursky
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

And use it's net where possible.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 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(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 7bb187a..8bbe873 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -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,
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 151921b..83d2669 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -786,8 +786,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 */
@@ -824,8 +823,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 */
@@ -862,8 +860,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 */
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6a3661b..865a793 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1247,10 +1247,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++; 
@@ -1289,6 +1288,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
 	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)
@@ -1321,6 +1321,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
 	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
 	gen_confirm(clp);
 	clp->cl_cb_session = NULL;
+	clp->net = net;
 	return clp;
 }
 
@@ -1428,7 +1429,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));
@@ -1578,6 +1579,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 "
@@ -1667,7 +1669,7 @@ out_new:
 	}
 	new->cl_minorversion = 1;
 
-	gen_clid(new);
+	gen_clid(new, nn);
 	add_to_unconfirmed(new, strhashval);
 out_copy:
 	exid->clientid.cl_boot = new->cl_clientid.cl_boot;
@@ -2199,7 +2201,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct nfs4_client	*conf, *unconf, *new;
 	__be32 			status;
 	char                    dname[HEXDIR_LEN];
-	
+	struct nfsd_net		*nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
 	status = nfs4_make_rec_clidname(dname, &clname);
 	if (status)
 		return status;
@@ -2234,7 +2237,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, strhashval);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 8053b57..b064577 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -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


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 01/15] nfsd: use service net instead of hard-coded net where possible Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 02/15] nfsd: make nfs4_client network namespace dependent Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-14 13:02   ` Jeff Layton
  2012-11-13 15:48 ` [PATCH 04/15] nfsd: make conf_id_hashtbl " Stanislav Kinsbursky
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h       |   12 +++++++++
 fs/nfsd/nfs4recover.c |   64 ++++++++++++++++++++++++++++++++++++++++---------
 fs/nfsd/nfs4state.c   |   32 ++++++++-----------------
 fs/nfsd/state.h       |    4 ++-
 4 files changed, 77 insertions(+), 35 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 65c2431..49e5479 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -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;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 83d2669..fc782b5 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -193,7 +193,7 @@ out_unlock:
 	nfs4_reset_creds(original_cred);
 }
 
-typedef int (recdir_func)(struct dentry *, struct dentry *);
+typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
 
 struct name_list {
 	char name[HEXDIR_LEN];
@@ -219,7 +219,7 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
 }
 
 static int
-nfsd4_list_rec_dir(recdir_func *f)
+nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
 {
 	const struct cred *original_cred;
 	struct dentry *dir = rec_file->f_path.dentry;
@@ -248,7 +248,7 @@ nfsd4_list_rec_dir(recdir_func *f)
 				status = PTR_ERR(dentry);
 				break;
 			}
-			status = f(dir, dentry);
+			status = f(dir, dentry, nn);
 			dput(dentry);
 		}
 		list_del(&entry->list);
@@ -316,7 +316,7 @@ out:
 }
 
 static int
-purge_old(struct dentry *parent, struct dentry *child)
+purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
 	int status;
 
@@ -335,13 +335,14 @@ static void
 nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
 {
 	int status;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	if (!rec_file)
 		return;
 	status = mnt_want_write_file(rec_file);
 	if (status)
 		goto out;
-	status = nfsd4_list_rec_dir(purge_old);
+	status = nfsd4_list_rec_dir(purge_old, nn);
 	if (status == 0)
 		vfs_fsync(rec_file, 0);
 	mnt_drop_write_file(rec_file);
@@ -352,7 +353,7 @@ out:
 }
 
 static int
-load_recdir(struct dentry *parent, struct dentry *child)
+load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
 	if (child->d_name.len != HEXDIR_LEN - 1) {
 		printk("nfsd4: illegal name %s in recovery directory\n",
@@ -360,18 +361,19 @@ load_recdir(struct dentry *parent, struct dentry *child)
 		/* Keep trying; maybe the others are OK: */
 		return 0;
 	}
-	nfs4_client_to_reclaim(child->d_name.name);
+	nfs4_client_to_reclaim(child->d_name.name, nn);
 	return 0;
 }
 
 static int
-nfsd4_recdir_load(void) {
+nfsd4_recdir_load(struct net *net) {
 	int status;
+	struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
 
 	if (!rec_file)
 		return 0;
 
-	status = nfsd4_list_rec_dir(load_recdir);
+	status = nfsd4_list_rec_dir(load_recdir, nn);
 	if (status)
 		printk("nfsd4: failed loading clients from recovery"
 			" directory %s\n", rec_file->f_path.dentry->d_name.name);
@@ -413,6 +415,33 @@ nfsd4_init_recdir(void)
 	return status;
 }
 
+
+static int
+nfs4_legacy_state_init(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	int i;
+
+	nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
+					  CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->reclaim_str_hashtbl)
+		return -ENOMEM;
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
+	nn->reclaim_str_hashtbl_size = 0;
+
+	return 0;
+}
+
+static void
+nfs4_legacy_state_shutdown(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+	kfree(nn->reclaim_str_hashtbl);
+}
+
 static int
 nfsd4_load_reboot_recovery_data(struct net *net)
 {
@@ -425,13 +454,23 @@ nfsd4_load_reboot_recovery_data(struct net *net)
 		return -EINVAL;
 	}
 
+	status = nfs4_legacy_state_init(net);
+	if (status)
+		return status;
+
 	nfs4_lock_state();
 	status = nfsd4_init_recdir();
 	if (!status)
-		status = nfsd4_recdir_load();
+		status = nfsd4_recdir_load(net);
 	nfs4_unlock_state();
-	if (status)
+	if (status) {
 		printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
+		goto err;
+	}
+	return 0;
+
+err:
+	nfs4_legacy_state_shutdown(net);
 	return status;
 }
 
@@ -447,8 +486,9 @@ nfsd4_shutdown_recdir(void)
 static void
 nfsd4_legacy_tracking_exit(struct net *net)
 {
-	nfs4_release_reclaim();
+	nfs4_release_reclaim(net);
 	nfsd4_shutdown_recdir();
+	nfs4_legacy_state_shutdown(net);
 }
 
 /*
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 865a793..dc818f4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -393,11 +393,6 @@ unhash_delegation(struct nfs4_delegation *dp)
 /* client_lock protects the client lru list and session hash table */
 static DEFINE_SPINLOCK(client_lock);
 
-/* 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)
-
 static unsigned int clientid_hashval(u32 id)
 {
 	return id & CLIENT_HASH_MASK;
@@ -409,9 +404,6 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
- * used in reboot/reset lease grace period processing
- *
  * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
  * setclientid_confirmed info. 
  *
@@ -424,8 +416,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.
  */
-static struct list_head	reclaim_str_hashtbl[CLIENT_HASH_SIZE];
-static int reclaim_str_hashtbl_size = 0;
 static struct list_head	conf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
@@ -4502,7 +4492,7 @@ nfs4_has_reclaimed_state(const char *name)
  * failure => all reset bets are off, nfserr_no_grace...
  */
 int
-nfs4_client_to_reclaim(const char *name)
+nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
 {
 	unsigned int strhashval;
 	struct nfs4_client_reclaim *crp = NULL;
@@ -4513,28 +4503,29 @@ nfs4_client_to_reclaim(const char *name)
 		return 0;
 	strhashval = clientstr_hashval(name);
 	INIT_LIST_HEAD(&crp->cr_strhash);
-	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
+	list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
 	memcpy(crp->cr_recdir, name, HEXDIR_LEN);
-	reclaim_str_hashtbl_size++;
+	nn->reclaim_str_hashtbl_size++;
 	return 1;
 }
 
 void
-nfs4_release_reclaim(void)
+nfs4_release_reclaim(struct net *net)
 {
 	struct nfs4_client_reclaim *crp = NULL;
 	int i;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		while (!list_empty(&reclaim_str_hashtbl[i])) {
-			crp = list_entry(reclaim_str_hashtbl[i].next,
+		while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
+			crp = list_entry(nn->reclaim_str_hashtbl[i].next,
 			                struct nfs4_client_reclaim, cr_strhash);
 			list_del(&crp->cr_strhash);
 			kfree(crp);
-			reclaim_str_hashtbl_size--;
+			nn->reclaim_str_hashtbl_size--;
 		}
 	}
-	BUG_ON(reclaim_str_hashtbl_size);
+	BUG_ON(nn->reclaim_str_hashtbl_size);
 }
 
 /*
@@ -4544,6 +4535,7 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 {
 	unsigned int strhashval;
 	struct nfs4_client_reclaim *crp = NULL;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
 		            clp->cl_name.len, clp->cl_name.data,
@@ -4551,7 +4543,7 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 
 	/* find clp->cl_name in reclaim_str_hashtbl */
 	strhashval = clientstr_hashval(clp->cl_recdir);
-	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
+	list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
 		if (same_name(crp->cr_recdir, clp->cl_recdir)) {
 			return crp;
 		}
@@ -4711,7 +4703,6 @@ nfs4_state_init(void)
 		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
-		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
 	}
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
@@ -4726,7 +4717,6 @@ nfs4_state_init(void)
 	INIT_LIST_HEAD(&close_lru);
 	INIT_LIST_HEAD(&client_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
-	reclaim_str_hashtbl_size = 0;
 }
 
 /*
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index b064577..da78804 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -466,7 +466,7 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
 extern int nfs4_in_grace(void);
-extern void nfs4_release_reclaim(void);
+extern void nfs4_release_reclaim(struct net *net);
 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
 extern void nfs4_free_openowner(struct nfs4_openowner *);
@@ -482,7 +482,7 @@ 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 __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
-extern int nfs4_client_to_reclaim(const char *name);
+extern int nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn);
 extern int nfs4_has_reclaimed_state(const char *name);
 extern void release_session_client(struct nfsd4_session *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/15] nfsd: make conf_id_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (2 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 05/15] nfsd: make conf_str_hashtbl " Stanislav Kinsbursky
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   73 ++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 49e5479..0cc85e9 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -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;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index dc818f4..74d047e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -416,7 +416,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.
  */
-static struct list_head	conf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
@@ -1331,21 +1330,22 @@ move_to_confirmed(struct nfs4_client *clp)
 {
 	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
 	unsigned int strhashval;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
 	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
-	list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
+	list_move(&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);
 	strhashval = clientstr_hashval(clp->cl_recdir);
 	list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
 	renew_client(clp);
 }
 
 static struct nfs4_client *
-find_confirmed_client(clientid_t *clid, bool sessions)
+find_confirmed_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, &conf_id_hashtbl[idhashval], cl_idhash) {
+	list_for_each_entry(clp, &nn->conf_id_hashtbl[idhashval], cl_idhash) {
 		if (same_clid(&clp->cl_clientid, clid)) {
 			if ((bool)clp->cl_minorversion != sessions)
 				return NULL;
@@ -1753,6 +1753,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	struct nfsd4_conn *conn;
 	struct nfsd4_clid_slot *cs_slot = NULL;
 	__be32 status = 0;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
 		return nfserr_inval;
@@ -1768,7 +1769,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 
 	nfs4_lock_state();
 	unconf = find_unconfirmed_client(&cr_ses->clientid, true);
-	conf = find_confirmed_client(&cr_ses->clientid, true);
+	conf = find_confirmed_client(&cr_ses->clientid, true, nn);
 
 	if (conf) {
 		cs_slot = &conf->cl_cs_slot;
@@ -2110,10 +2111,11 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
 {
 	struct nfs4_client *conf, *unconf, *clp;
 	__be32 status = 0;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	nfs4_lock_state();
 	unconf = find_unconfirmed_client(&dc->clientid, true);
-	conf = find_confirmed_client(&dc->clientid, true);
+	conf = find_confirmed_client(&dc->clientid, true, nn);
 
 	if (conf) {
 		clp = conf;
@@ -2256,7 +2258,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 		return nfserr_stale_clientid;
 	nfs4_lock_state();
 
-	conf = find_confirmed_client(clid, false);
+	conf = find_confirmed_client(clid, false, nn);
 	unconf = find_unconfirmed_client(clid, false);
 	/*
 	 * We try hard to give out unique clientid's, so if we get an
@@ -2634,7 +2636,8 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
 	oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
 	open->op_openowner = oo;
 	if (!oo) {
-		clp = find_confirmed_client(clientid, cstate->minorversion);
+		clp = find_confirmed_client(clientid, cstate->minorversion,
+					    nn);
 		if (clp == NULL)
 			return nfserr_expired;
 		goto new_owner;
@@ -3130,7 +3133,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	status = nfserr_stale_clientid;
 	if (STALE_CLIENTID(clid, nn))
 		goto out;
-	clp = find_confirmed_client(clid, cstate->minorversion);
+	clp = find_confirmed_client(clid, cstate->minorversion, nn);
 	status = nfserr_expired;
 	if (clp == NULL) {
 		/* We assume the client took too long to RENEW. */
@@ -3406,7 +3409,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
 		return nfserr_bad_stateid;
 	if (STALE_STATEID(stateid, nn))
 		return nfserr_stale_stateid;
-	cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
+	cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions, nn);
 	if (!cl)
 		return nfserr_expired;
 	*s = find_stateid_by_type(cl, stateid, typemask);
@@ -4558,9 +4561,10 @@ __be32
 nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
 {
 	struct nfs4_client *clp;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	/* find clientid in conf_id_hashtbl */
-	clp = find_confirmed_client(clid, sessions);
+	clp = find_confirmed_client(clid, sessions, nn);
 	if (clp == NULL)
 		return nfserr_reclaim_bad;
 
@@ -4699,7 +4703,6 @@ nfs4_state_init(void)
 	int i;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&conf_id_hashtbl[i]);
 		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
@@ -4740,6 +4743,38 @@ set_max_delegations(void)
 	max_delegations = nr_free_buffer_pages() >> (20 - 2 - PAGE_SHIFT);
 }
 
+static int nfs4_state_start_net(struct net *net)
+{
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+	int i;
+
+	nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->conf_id_hashtbl)
+		return -ENOMEM;
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+
+	return 0;
+}
+
+static void
+__nfs4_state_shutdown_net(struct net *net)
+{
+	int i;
+	struct nfs4_client *clp = NULL;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
+		while (!list_empty(&nn->conf_id_hashtbl[i])) {
+			clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
+			destroy_client(clp);
+		}
+	}
+	kfree(nn->conf_id_hashtbl);
+}
+
 /* initialization to perform when the nfsd service is started: */
 
 int
@@ -4757,6 +4792,9 @@ nfs4_state_start(void)
 	 * basis.
 	 */
 	get_net(net);
+	ret = nfs4_state_start_net(net);
+	if (ret)
+		return ret;
 	nfsd4_client_tracking_init(net);
 	nn->boot_time = get_seconds();
 	locks_start_grace(net, &nn->nfsd4_manager);
@@ -4783,23 +4821,22 @@ out_free_laundry:
 	destroy_workqueue(laundry_wq);
 out_recovery:
 	nfsd4_client_tracking_exit(net);
+	__nfs4_state_shutdown_net(net);
 	put_net(net);
 	return ret;
 }
 
 static void
-__nfs4_state_shutdown(void)
+__nfs4_state_shutdown(struct net *net)
 {
 	int i;
 	struct nfs4_client *clp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	struct list_head *pos, *next, reaplist;
 
+	__nfs4_state_shutdown_net(net);
+
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		while (!list_empty(&conf_id_hashtbl[i])) {
-			clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
-			destroy_client(clp);
-		}
 		while (!list_empty(&unconf_str_hashtbl[i])) {
 			clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
 			destroy_client(clp);
@@ -4831,7 +4868,7 @@ nfs4_state_shutdown(void)
 	destroy_workqueue(laundry_wq);
 	locks_end_grace(&nn->nfsd4_manager);
 	nfs4_lock_state();
-	__nfs4_state_shutdown();
+	__nfs4_state_shutdown(net);
 	nfs4_unlock_state();
 	nfsd4_destroy_callback_queue();
 }


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/15] nfsd: make conf_str_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (3 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 04/15] nfsd: make conf_id_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-14 13:04   ` Jeff Layton
  2012-11-13 15:48 ` [PATCH 06/15] nfsd: make unconf_str_hashtbl " Stanislav Kinsbursky
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h       |    5 +++++
 fs/nfsd/nfs4recover.c |    2 +-
 fs/nfsd/nfs4state.c   |   40 ++++++++++++++++++++++++----------------
 fs/nfsd/state.h       |    2 +-
 4 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 0cc85e9..61f41c0 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -47,10 +47,15 @@ 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_str_hashtbl[] hold confirmed
+	 * setclientid_confirmed info.
+	 *
 	 */
 	struct list_head *reclaim_str_hashtbl;
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
+	struct list_head *conf_str_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index fc782b5..ac79dd7 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -320,7 +320,7 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
 {
 	int status;
 
-	if (nfs4_has_reclaimed_state(child->d_name.name))
+	if (nfs4_has_reclaimed_state(child->d_name.name, nn))
 		return 0;
 
 	status = vfs_rmdir(parent->d_inode, child);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 74d047e..a709dd2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -404,9 +404,6 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
- * setclientid_confirmed info. 
- *
  * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
  * setclientid info.
  *
@@ -416,7 +413,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.
  */
-static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head client_lru;
@@ -1335,7 +1331,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]);
 	strhashval = clientstr_hashval(clp->cl_recdir);
-	list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
+	list_move(&clp->cl_strhash, &nn->conf_str_hashtbl[strhashval]);
 	renew_client(clp);
 }
 
@@ -1378,11 +1374,12 @@ static bool clp_used_exchangeid(struct nfs4_client *clp)
 } 
 
 static struct nfs4_client *
-find_confirmed_client_by_str(const char *dname, unsigned int hashval)
+find_confirmed_client_by_str(const char *dname, unsigned int hashval,
+			     struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 
-	list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
+	list_for_each_entry(clp, &nn->conf_str_hashtbl[hashval], cl_strhash) {
 		if (same_name(clp->cl_recdir, dname))
 			return clp;
 	}
@@ -1601,7 +1598,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_str(dname, strhashval);
+	conf = find_confirmed_client_by_str(dname, strhashval, nn);
 	if (conf) {
 		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
 		bool verfs_match = same_verf(&verf, &conf->cl_verifier);
@@ -1797,7 +1794,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 			goto out_free_conn;
 		}
 		hash = clientstr_hashval(unconf->cl_recdir);
-		old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+		old = find_confirmed_client_by_str(unconf->cl_recdir, hash, nn);
 		if (old)
 			expire_client(old);
 		move_to_confirmed(unconf);
@@ -2203,7 +2200,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_str(dname, strhashval);
+	conf = find_confirmed_client_by_str(dname, strhashval, nn);
 	if (conf) {
 		/* case 0: */
 		status = nfserr_clid_inuse;
@@ -2287,7 +2284,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	} else { /* case 3: normal case; new or rebooted client */
 		unsigned int hash = clientstr_hashval(unconf->cl_recdir);
 
-		conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
+		conf = find_confirmed_client_by_str(unconf->cl_recdir, hash, nn);
 		if (conf)
 			expire_client(conf);
 		move_to_confirmed(unconf);
@@ -4480,12 +4477,12 @@ alloc_reclaim(void)
 }
 
 int
-nfs4_has_reclaimed_state(const char *name)
+nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
 {
 	unsigned int strhashval = clientstr_hashval(name);
 	struct nfs4_client *clp;
 
-	clp = find_confirmed_client_by_str(name, strhashval);
+	clp = find_confirmed_client_by_str(name, strhashval, nn);
 	if (!clp)
 		return 0;
 	return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -4703,7 +4700,6 @@ nfs4_state_init(void)
 	int i;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
 	}
@@ -4751,12 +4747,23 @@ 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;
+	nn->conf_str_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->conf_str_hashtbl)
+		goto err_conf_str;
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
+		INIT_LIST_HEAD(&nn->conf_str_hashtbl[i]);
+	}
 
 	return 0;
+
+err_conf_str:
+	kfree(nn->conf_id_hashtbl);
+err:
+	return -ENOMEM;
 }
 
 static void
@@ -4772,6 +4779,7 @@ __nfs4_state_shutdown_net(struct net *net)
 			destroy_client(clp);
 		}
 	}
+	kfree(nn->conf_str_hashtbl);
 	kfree(nn->conf_id_hashtbl);
 }
 
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index da78804..f350805 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -483,7 +483,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
 extern int nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn);
-extern int nfs4_has_reclaimed_state(const char *name);
+extern int nfs4_has_reclaimed_state(const char *name, struct nfsd_net *);
 extern void release_session_client(struct nfsd4_session *);
 extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
 


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/15] nfsd: make unconf_str_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (4 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 05/15] nfsd: make conf_str_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-14 13:20   ` Jeff Layton
  2012-11-13 15:48 ` [PATCH 07/15] nfsd: make unconf_str_hastbl " Stanislav Kinsbursky
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   34 +++++++++++++++++++---------------
 2 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 61f41c0..0577780 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -56,6 +56,7 @@ struct nfsd_net {
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
 	struct list_head *conf_str_hashtbl;
+	struct list_head *unconf_str_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a709dd2..7e44015 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -413,7 +413,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.
  */
-static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head client_lru;
 static struct list_head close_lru;
@@ -1314,8 +1313,9 @@ static void
 add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
 {
 	unsigned int idhashval;
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
+	list_add(&clp->cl_strhash, &nn->unconf_str_hashtbl[strhashval]);
 	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
 	list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
 	renew_client(clp);
@@ -1387,11 +1387,12 @@ find_confirmed_client_by_str(const char *dname, unsigned int hashval,
 }
 
 static struct nfs4_client *
-find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
+find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
+			       struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
 
-	list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
+	list_for_each_entry(clp, &nn->unconf_str_hashtbl[hashval], cl_strhash) {
 		if (same_name(clp->cl_recdir, dname))
 			return clp;
 	}
@@ -1643,7 +1644,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 		goto out;
 	}
 
-	unconf  = find_unconfirmed_client_by_str(dname, strhashval);
+	unconf  = find_unconfirmed_client_by_str(dname, strhashval, nn);
 	if (unconf) /* case 4, possible retry or client restart */
 		expire_client(unconf);
 
@@ -2215,7 +2216,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			goto out;
 		}
 	}
-	unconf = find_unconfirmed_client_by_str(dname, strhashval);
+	unconf = find_unconfirmed_client_by_str(dname, strhashval, nn);
 	if (unconf)
 		expire_client(unconf);
 	status = nfserr_jukebox;
@@ -4700,7 +4701,6 @@ nfs4_state_init(void)
 	int i;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
 	}
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
@@ -4752,14 +4752,21 @@ static int nfs4_state_start_net(struct net *net)
 			CLIENT_HASH_SIZE, GFP_KERNEL);
 	if (!nn->conf_str_hashtbl)
 		goto err_conf_str;
+	nn->unconf_str_hashtbl = kmalloc(sizeof(struct list_head) *
+			CLIENT_HASH_SIZE, GFP_KERNEL);
+	if (!nn->unconf_str_hashtbl)
+		goto err_unconf_str;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
 		INIT_LIST_HEAD(&nn->conf_str_hashtbl[i]);
+		INIT_LIST_HEAD(&nn->unconf_str_hashtbl[i]);
 	}
 
 	return 0;
 
+err_unconf_str:
+	kfree(nn->conf_str_hashtbl);
 err_conf_str:
 	kfree(nn->conf_id_hashtbl);
 err:
@@ -4778,7 +4785,12 @@ __nfs4_state_shutdown_net(struct net *net)
 			clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
 			destroy_client(clp);
 		}
+		while (!list_empty(&nn->unconf_str_hashtbl[i])) {
+			clp = list_entry(nn->unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
+			destroy_client(clp);
+		}
 	}
+	kfree(nn->unconf_str_hashtbl);
 	kfree(nn->conf_str_hashtbl);
 	kfree(nn->conf_id_hashtbl);
 }
@@ -4837,19 +4849,11 @@ out_recovery:
 static void
 __nfs4_state_shutdown(struct net *net)
 {
-	int i;
-	struct nfs4_client *clp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	struct list_head *pos, *next, reaplist;
 
 	__nfs4_state_shutdown_net(net);
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		while (!list_empty(&unconf_str_hashtbl[i])) {
-			clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
-			destroy_client(clp);
-		}
-	}
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	list_for_each_safe(pos, next, &del_recall_lru) {


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/15] nfsd: make unconf_str_hastbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (5 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 06/15] nfsd: make unconf_str_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-13 15:48 ` [PATCH 08/15] nfsd: make ownerstr_hashtbl " Stanislav Kinsbursky
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    3 +++
 fs/nfsd/nfs4state.c |   27 ++++++++++++++-------------
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 0577780..ad08208 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -51,12 +51,15 @@ struct nfsd_net {
 	 * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
 	 * setclientid_confirmed info.
 	 *
+	 * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed
+	 * setclientid info.
 	 */
 	struct list_head *reclaim_str_hashtbl;
 	int reclaim_str_hashtbl_size;
 	struct list_head *conf_id_hashtbl;
 	struct list_head *conf_str_hashtbl;
 	struct list_head *unconf_str_hashtbl;
+	struct list_head *unconf_id_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 7e44015..10ee3ec 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -404,16 +404,12 @@ static unsigned int clientstr_hashval(const char *name)
 }
 
 /*
- * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
- * setclientid info.
- *
  * 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.
  */
-static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head client_lru;
 static struct list_head close_lru;
 
@@ -1317,7 +1313,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
 
 	list_add(&clp->cl_strhash, &nn->unconf_str_hashtbl[strhashval]);
 	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);
 }
 
@@ -1353,12 +1349,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;
@@ -1766,7 +1762,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) {
@@ -2112,7 +2108,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) {
@@ -2257,7 +2253,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,
@@ -4700,9 +4696,6 @@ nfs4_state_init(void)
 {
 	int i;
 
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
-	}
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
@@ -4756,15 +4749,22 @@ static int nfs4_state_start_net(struct net *net)
 			CLIENT_HASH_SIZE, GFP_KERNEL);
 	if (!nn->unconf_str_hashtbl)
 		goto err_unconf_str;
+	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->conf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&nn->unconf_str_hashtbl[i]);
+		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
 	}
 
 	return 0;
 
+err_unconf_id:
+	kfree(nn->unconf_str_hashtbl);
 err_unconf_str:
 	kfree(nn->conf_str_hashtbl);
 err_conf_str:
@@ -4790,6 +4790,7 @@ __nfs4_state_shutdown_net(struct net *net)
 			destroy_client(clp);
 		}
 	}
+	kfree(nn->unconf_id_hashtbl);
 	kfree(nn->unconf_str_hashtbl);
 	kfree(nn->conf_str_hashtbl);
 	kfree(nn->conf_id_hashtbl);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/15] nfsd: make ownerstr_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (6 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 07/15] nfsd: make unconf_str_hastbl " Stanislav Kinsbursky
@ 2012-11-13 15:48 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 09/15] nfsd: make lockowner_ino_hashtbl " Stanislav Kinsbursky
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:48 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    1 +
 fs/nfsd/nfs4state.c |   41 ++++++++++++++++++++++++++---------------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index ad08208..70f28f1 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -60,6 +60,7 @@ struct nfsd_net {
 	struct list_head *conf_str_hashtbl;
 	struct list_head *unconf_str_hashtbl;
 	struct list_head *unconf_id_hashtbl;
+	struct list_head *ownerstr_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 10ee3ec..5fa1bde 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -176,8 +176,6 @@ static unsigned int ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
 	return ret & OWNER_HASH_MASK;
 }
 
-static struct list_head	ownerstr_hashtbl[OWNER_HASH_SIZE];
-
 /* hash table for nfs4_file */
 #define FILE_HASH_BITS                   8
 #define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
@@ -2407,7 +2405,9 @@ static inline void *alloc_stateowner(struct kmem_cache *slab, struct xdr_netobj
 
 static void hash_openowner(struct nfs4_openowner *oo, struct nfs4_client *clp, unsigned int strhashval)
 {
-	list_add(&oo->oo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+	list_add(&oo->oo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
 	list_add(&oo->oo_perclient, &clp->cl_openowners);
 }
 
@@ -2465,13 +2465,14 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
 }
 
 static struct nfs4_openowner *
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open,
+			bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_stateowner *so;
 	struct nfs4_openowner *oo;
 	struct nfs4_client *clp;
 
-	list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+	list_for_each_entry(so, &nn->ownerstr_hashtbl[hashval], so_strhash) {
 		if (!so->so_is_open_owner)
 			continue;
 		if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
@@ -2627,7 +2628,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
 		return nfserr_jukebox;
 
 	strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
-	oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
+	oo = find_openstateowner_str(strhashval, open, cstate->minorversion, nn);
 	open->op_openowner = oo;
 	if (!oo) {
 		clp = find_confirmed_client(clientid, cstate->minorversion,
@@ -3955,8 +3956,9 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s
 	struct inode *inode = open_stp->st_file->fi_inode;
 	unsigned int inohash = lockowner_ino_hashval(inode,
 			clp->cl_clientid.cl_id, &lo->lo_owner.so_owner);
+	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
 
-	list_add(&lo->lo_owner.so_strhash, &ownerstr_hashtbl[strhashval]);
+	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_perstateid, &open_stp->st_lockowners);
 }
@@ -4437,7 +4439,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
 	status = nfserr_locks_held;
 	INIT_LIST_HEAD(&matches);
 
-	list_for_each_entry(sop, &ownerstr_hashtbl[hashval], so_strhash) {
+	list_for_each_entry(sop, &nn->ownerstr_hashtbl[hashval], so_strhash) {
 		if (sop->so_is_open_owner)
 			continue;
 		if (!same_owner_str(sop, owner, clid))
@@ -4594,13 +4596,14 @@ static void release_openowner_sop(struct nfs4_stateowner *sop)
 }
 
 static int nfsd_release_n_owners(u64 num, bool is_open_owner,
-				void (*release_sop)(struct nfs4_stateowner *))
+				void (*release_sop)(struct nfs4_stateowner *),
+				struct nfsd_net *nn)
 {
 	int i, count = 0;
 	struct nfs4_stateowner *sop, *next;
 
 	for (i = 0; i < OWNER_HASH_SIZE; i++) {
-		list_for_each_entry_safe(sop, next, &ownerstr_hashtbl[i], so_strhash) {
+		list_for_each_entry_safe(sop, next, &nn->ownerstr_hashtbl[i], so_strhash) {
 			if (sop->so_is_open_owner != is_open_owner)
 				continue;
 			release_sop(sop);
@@ -4614,9 +4617,10 @@ static int nfsd_release_n_owners(u64 num, bool is_open_owner,
 void nfsd_forget_locks(u64 num)
 {
 	int count;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
-	count = nfsd_release_n_owners(num, false, release_lockowner_sop);
+	count = nfsd_release_n_owners(num, false, release_lockowner_sop, nn);
 	nfs4_unlock_state();
 
 	printk(KERN_INFO "NFSD: Forgot %d locks", count);
@@ -4625,9 +4629,10 @@ void nfsd_forget_locks(u64 num)
 void nfsd_forget_openowners(u64 num)
 {
 	int count;
+	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	nfs4_lock_state();
-	count = nfsd_release_n_owners(num, true, release_openowner_sop);
+	count = nfsd_release_n_owners(num, true, release_openowner_sop, nn);
 	nfs4_unlock_state();
 
 	printk(KERN_INFO "NFSD: Forgot %d open owners", count);
@@ -4701,9 +4706,6 @@ nfs4_state_init(void)
 	for (i = 0; i < FILE_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&file_hashtbl[i]);
 	}
-	for (i = 0; i < OWNER_HASH_SIZE; i++) {
-		INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
-	}
 	for (i = 0; i < LOCKOWNER_INO_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&lockowner_ino_hashtbl[i]);
 	INIT_LIST_HEAD(&close_lru);
@@ -4753,6 +4755,10 @@ static int nfs4_state_start_net(struct net *net)
 			CLIENT_HASH_SIZE, GFP_KERNEL);
 	if (!nn->unconf_id_hashtbl)
 		goto err_unconf_id;
+	nn->ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
+			OWNER_HASH_SIZE, GFP_KERNEL);
+	if (!nn->ownerstr_hashtbl)
+		goto err_ownerstr;
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
@@ -4760,9 +4766,13 @@ static int nfs4_state_start_net(struct net *net)
 		INIT_LIST_HEAD(&nn->unconf_str_hashtbl[i]);
 		INIT_LIST_HEAD(&nn->unconf_id_hashtbl[i]);
 	}
+	for (i = 0; i < OWNER_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&nn->ownerstr_hashtbl[i]);
 
 	return 0;
 
+err_ownerstr:
+	kfree(nn->unconf_id_hashtbl);
 err_unconf_id:
 	kfree(nn->unconf_str_hashtbl);
 err_unconf_str:
@@ -4790,6 +4800,7 @@ __nfs4_state_shutdown_net(struct net *net)
 			destroy_client(clp);
 		}
 	}
+	kfree(nn->ownerstr_hashtbl);
 	kfree(nn->unconf_id_hashtbl);
 	kfree(nn->unconf_str_hashtbl);
 	kfree(nn->conf_str_hashtbl);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/15] nfsd: make lockowner_ino_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (7 preceding siblings ...)
  2012-11-13 15:48 ` [PATCH 08/15] nfsd: make ownerstr_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 10/15] nfsd: make sessionid_hashtbl " Stanislav Kinsbursky
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    4 ++++
 fs/nfsd/nfs4state.c |   27 ++++++++++++++++-----------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 70f28f1..f7a6b87 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -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_str_hashtbl;
 	struct list_head *unconf_id_hashtbl;
 	struct list_head *ownerstr_hashtbl;
+	struct list_head *lockowner_ino_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5fa1bde..ddc5a9f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3841,8 +3841,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
@@ -3872,8 +3870,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
@@ -3939,12 +3935,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;
 	}
@@ -3959,7 +3955,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);
 }
 
@@ -4033,8 +4029,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;
@@ -4287,7 +4285,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;
@@ -4706,8 +4704,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);
@@ -4759,6 +4755,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]);
@@ -4768,9 +4768,13 @@ 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]);
 
 	return 0;
 
+err_lockowner_ino:
+	kfree(nn->ownerstr_hashtbl);
 err_ownerstr:
 	kfree(nn->unconf_id_hashtbl);
 err_unconf_id:
@@ -4800,6 +4804,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->unconf_str_hashtbl);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/15] nfsd: make sessionid_hashtbl allocated per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (8 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 09/15] nfsd: make lockowner_ino_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 11/15] nfsd: make client_lru list " Stanislav Kinsbursky
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    3 +++
 fs/nfsd/nfs4state.c |   28 +++++++++++++++++-----------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index f7a6b87..2c44f2b 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -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 list_head *unconf_id_hashtbl;
 	struct list_head *ownerstr_hashtbl;
 	struct list_head *lockowner_ino_hashtbl;
+	struct list_head *sessionid_hashtbl;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index ddc5a9f..f463d8f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -630,9 +630,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)
 {
@@ -926,6 +923,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);
@@ -939,7 +937,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);
@@ -961,15 +959,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;
@@ -1874,7 +1873,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) {
@@ -1923,7 +1922,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;
@@ -2019,7 +2018,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;
 
@@ -4699,8 +4698,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]);
 	}
@@ -4759,6 +4756,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]);
@@ -4770,9 +4771,13 @@ 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]);
 
 	return 0;
 
+err_sessionid:
+	kfree(nn->lockowner_ino_hashtbl);
 err_lockowner_ino:
 	kfree(nn->ownerstr_hashtbl);
 err_ownerstr:
@@ -4804,6 +4809,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);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/15] nfsd: make client_lru list per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (9 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 10/15] nfsd: make sessionid_hashtbl " Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 12/15] nfsd: make close_lru " Stanislav Kinsbursky
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    5 +++++
 fs/nfsd/nfs4state.c |   16 ++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 2c44f2b..e9f9a51 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -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;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f463d8f..1861016 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -402,13 +402,9 @@ 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.
  */
-static struct list_head client_lru;
 static struct list_head close_lru;
 
 /*
@@ -993,6 +989,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",
@@ -1005,7 +1003,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();
 }
 
@@ -3175,6 +3173,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();
 
@@ -3182,7 +3181,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;
@@ -4570,9 +4569,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;
@@ -4702,7 +4702,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);
 }
 
@@ -4773,6 +4772,7 @@ static int nfs4_state_start_net(struct net *net)
 		INIT_LIST_HEAD(&nn->lockowner_ino_hashtbl[i]);
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
+	INIT_LIST_HEAD(&nn->client_lru);
 
 	return 0;
 


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/15] nfsd: make close_lru list per net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (10 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 11/15] nfsd: make client_lru list " Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 13/15] nfsd: use service net instead of hard-coded init_net Stanislav Kinsbursky
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    4 ++++
 fs/nfsd/nfs4state.c |   18 +++++++-----------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index e9f9a51..f024fe2 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -71,8 +71,12 @@ 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.
 	 */
 	struct list_head client_lru;
+	struct list_head close_lru;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1861016..d55136e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -402,12 +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.
- */
-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
@@ -2444,11 +2438,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();
 }
 
@@ -3221,7 +3217,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;
@@ -3799,7 +3795,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:
@@ -4701,7 +4697,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);
 }
 
@@ -4773,6 +4768,7 @@ static int nfs4_state_start_net(struct net *net)
 	for (i = 0; i < SESSION_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
 	INIT_LIST_HEAD(&nn->client_lru);
+	INIT_LIST_HEAD(&nn->close_lru);
 
 	return 0;
 


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/15] nfsd: use service net instead of hard-coded init_net
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (11 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 12/15] nfsd: make close_lru " Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 14/15] nfsd: pass nfsd_net instead of net to grace enders Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 15/15] nfsd: make laundromat network namespace aware Stanislav Kinsbursky
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 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(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index f955176..1d2396b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -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:
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d55136e..1382ef0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2601,14 +2601,13 @@ static __be32 nfsd4_check_seqid(struct nfsd4_compound_state *cstate, struct nfs4
 
 __be32
 nfsd4_process_open1(struct nfsd4_compound_state *cstate,
-		    struct nfsd4_open *open)
+		    struct nfsd4_open *open, struct nfsd_net *nn)
 {
 	clientid_t *clientid = &open->op_clientid;
 	struct nfs4_client *clp = NULL;
 	unsigned int strhashval;
 	struct nfs4_openowner *oo = NULL;
 	__be32 status;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	if (STALE_CLIENTID(&open->op_clientid, nn))
 		return nfserr_stale_clientid;
@@ -3389,10 +3388,11 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 	return nfs_ok;
 }
 
-static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
+static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask,
+				   struct nfs4_stid **s, bool sessions,
+				   struct nfsd_net *nn)
 {
 	struct nfs4_client *cl;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
 		return nfserr_bad_stateid;
@@ -3420,6 +3420,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
 	struct nfs4_delegation *dp = NULL;
 	struct svc_fh *current_fh = &cstate->current_fh;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	__be32 status;
 
 	if (filpp)
@@ -3431,7 +3432,8 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
 	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
 		return check_special_stateids(net, current_fh, stateid, flags);
 
-	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID,
+				      &s, cstate->minorversion, nn);
 	if (status)
 		return status;
 	status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3572,7 +3574,8 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
 static __be32
 nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 			 stateid_t *stateid, char typemask,
-			 struct nfs4_ol_stateid **stpp)
+			 struct nfs4_ol_stateid **stpp,
+			 struct nfsd_net *nn)
 {
 	__be32 status;
 	struct nfs4_stid *s;
@@ -3581,7 +3584,8 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 		seqid, STATEID_VAL(stateid));
 
 	*stpp = NULL;
-	status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, typemask, &s,
+				      cstate->minorversion, nn);
 	if (status)
 		return status;
 	*stpp = openlockstateid(s);
@@ -3590,13 +3594,14 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
 	return nfs4_seqid_op_checks(cstate, stateid, seqid, *stpp);
 }
 
-static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid, stateid_t *stateid, struct nfs4_ol_stateid **stpp)
+static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
+						 stateid_t *stateid, struct nfs4_ol_stateid **stpp, struct nfsd_net *nn)
 {
 	__be32 status;
 	struct nfs4_openowner *oo;
 
 	status = nfs4_preprocess_seqid_op(cstate, seqid, stateid,
-						NFS4_OPEN_STID, stpp);
+						NFS4_OPEN_STID, stpp, nn);
 	if (status)
 		return status;
 	oo = openowner((*stpp)->st_stateowner);
@@ -3612,6 +3617,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	__be32 status;
 	struct nfs4_openowner *oo;
 	struct nfs4_ol_stateid *stp;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3625,7 +3631,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
 	status = nfs4_preprocess_seqid_op(cstate,
 					oc->oc_seqid, &oc->oc_req_stateid,
-					NFS4_OPEN_STID, &stp);
+					NFS4_OPEN_STID, &stp, nn);
 	if (status)
 		goto out;
 	oo = openowner(stp->st_stateowner);
@@ -3689,6 +3695,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 {
 	__be32 status;
 	struct nfs4_ol_stateid *stp;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3701,7 +3708,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
 
 	nfs4_lock_state();
 	status = nfs4_preprocess_confirmed_seqid_op(cstate, od->od_seqid,
-					&od->od_stateid, &stp);
+					&od->od_stateid, &stp, nn);
 	if (status)
 		goto out; 
 	status = nfserr_inval;
@@ -3764,6 +3771,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	__be32 status;
 	struct nfs4_openowner *oo;
 	struct nfs4_ol_stateid *stp;
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_close on file %.*s\n", 
 			(int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3773,7 +3782,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
 					&close->cl_stateid,
 					NFS4_OPEN_STID|NFS4_CLOSED_STID,
-					&stp);
+					&stp, nn);
 	if (status)
 		goto out; 
 	oo = openowner(stp->st_stateowner);
@@ -3812,12 +3821,14 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	stateid_t *stateid = &dr->dr_stateid;
 	struct nfs4_stid *s;
 	__be32 status;
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
 
 	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
 		return status;
 
 	nfs4_lock_state();
-	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
+	status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s,
+				      cstate->minorversion, nn);
 	if (status)
 		goto out;
 	dp = delegstateid(s);
@@ -4066,7 +4077,8 @@ 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(SVC_NET(rqstp), nfsd_net_id);
+	struct net *net = SVC_NET(rqstp);
+	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
 	dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
 		(long long) lock->lk_offset,
@@ -4100,7 +4112,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfs4_preprocess_confirmed_seqid_op(cstate,
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
-					&open_stp);
+					&open_stp, nn);
 		if (status)
 			goto out;
 		open_sop = openowner(open_stp->st_stateowner);
@@ -4114,7 +4126,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		status = nfs4_preprocess_seqid_op(cstate,
 				       lock->lk_old_lock_seqid,
 				       &lock->lk_old_lock_stateid,
-				       NFS4_LOCK_STID, &lock_stp);
+				       NFS4_LOCK_STID, &lock_stp, nn);
 	if (status)
 		goto out;
 	lock_sop = lockowner(lock_stp->st_stateowner);
@@ -4125,10 +4137,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 
 	status = nfserr_grace;
-	if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
+	if (locks_in_grace(net) && !lock->lk_reclaim)
 		goto out;
 	status = nfserr_no_grace;
-	if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
+	if (!locks_in_grace(net) && lock->lk_reclaim)
 		goto out;
 
 	file_lock = locks_alloc_lock();
@@ -4314,7 +4326,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct file_lock *file_lock = NULL;
 	__be32 status;
 	int err;
-						        
+	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+
 	dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
 		(long long) locku->lu_offset,
 		(long long) locku->lu_length);
@@ -4325,7 +4338,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	nfs4_lock_state();
 									        
 	status = nfs4_preprocess_seqid_op(cstate, locku->lu_seqid,
-					&locku->lu_stateid, NFS4_LOCK_STID, &stp);
+					&locku->lu_stateid, NFS4_LOCK_STID,
+					&stp, nn);
 	if (status)
 		goto out;
 	filp = find_any_file(stp->st_file);
@@ -4546,10 +4560,9 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
 * Called from OPEN. Look for clientid in reclaim list.
 */
 __be32
-nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
+nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn)
 {
 	struct nfs4_client *clp;
-	struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
 
 	/* find clientid in conf_id_hashtbl */
 	clp = find_confirmed_client(clid, sessions, nn);
@@ -4565,7 +4578,7 @@ 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);
+	struct nfsd_net *nn = net_generic(current->nsproxy->net_ns, nfsd_net_id);
 
 	nfs4_lock_state();
 	list_for_each_entry_safe(clp, next, &nn->client_lru, cl_lru) {
@@ -4885,8 +4898,8 @@ __nfs4_state_shutdown(struct net *net)
 		unhash_delegation(dp);
 	}
 
-	nfsd4_client_tracking_exit(&init_net);
-	put_net(&init_net);
+	nfsd4_client_tracking_exit(net);
+	put_net(net);
 }
 
 void
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index f350805..739b851 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -468,7 +468,7 @@ extern void nfs4_unlock_state(void);
 extern int nfs4_in_grace(void);
 extern void nfs4_release_reclaim(struct net *net);
 extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
-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);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 71c5c47..3c414c1 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -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);


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 14/15] nfsd: pass nfsd_net instead of net to grace enders
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (12 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 13/15] nfsd: use service net instead of hard-coded init_net Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  2012-11-13 15:49 ` [PATCH 15/15] nfsd: make laundromat network namespace aware Stanislav Kinsbursky
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

Passing net context looks as overkill.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/nfs4recover.c |   12 +++++-------
 fs/nfsd/nfs4state.c   |    8 +++-----
 fs/nfsd/state.h       |    2 +-
 3 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index ac79dd7..4e0f67a 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -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 */
@@ -332,10 +332,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);
 
 	if (!rec_file)
 		return;
@@ -930,11 +929,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);
@@ -1023,10 +1021,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
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1382ef0..4756176 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3138,17 +3138,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
@@ -3173,7 +3171,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) {
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 739b851..e1f55a6 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -493,5 +493,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 */


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 15/15] nfsd: make laundromat network namespace aware
  2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
                   ` (13 preceding siblings ...)
  2012-11-13 15:49 ` [PATCH 14/15] nfsd: pass nfsd_net instead of net to grace enders Stanislav Kinsbursky
@ 2012-11-13 15:49 ` Stanislav Kinsbursky
  14 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-13 15:49 UTC (permalink / raw)
  To: bfields; +Cc: linux-nfs, devel, Trond.Myklebust, linux-kernel, jlayton

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

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
 fs/nfsd/netns.h     |    2 ++
 fs/nfsd/nfs4state.c |   21 +++++++++++++--------
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index f024fe2..c135277 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -77,6 +77,8 @@ struct nfsd_net {
 	 */
 	struct list_head client_lru;
 	struct list_head close_lru;
+
+	struct delayed_work laundromat_work;
 };
 
 extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 4756176..bb109ae 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3157,7 +3157,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;
@@ -3166,7 +3166,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();
 
@@ -3232,16 +3231,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)
@@ -4781,6 +4783,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:
@@ -4864,7 +4868,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:
@@ -4906,7 +4911,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();


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net
  2012-11-13 15:48 ` [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net Stanislav Kinsbursky
@ 2012-11-14 13:02   ` Jeff Layton
  2012-11-14 13:22     ` Stanislav Kinsbursky
  0 siblings, 1 reply; 20+ messages in thread
From: Jeff Layton @ 2012-11-14 13:02 UTC (permalink / raw)
  To: Stanislav Kinsbursky
  Cc: bfields, linux-nfs, devel, Trond.Myklebust, linux-kernel

On Tue, 13 Nov 2012 18:48:33 +0300
Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:

> 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.
> 
> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
> ---
>  fs/nfsd/netns.h       |   12 +++++++++
>  fs/nfsd/nfs4recover.c |   64 ++++++++++++++++++++++++++++++++++++++++---------
>  fs/nfsd/nfs4state.c   |   32 ++++++++-----------------
>  fs/nfsd/state.h       |    4 ++-
>  4 files changed, 77 insertions(+), 35 deletions(-)
> 
> diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> index 65c2431..49e5479 100644
> --- a/fs/nfsd/netns.h
> +++ b/fs/nfsd/netns.h
> @@ -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;
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 83d2669..fc782b5 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -193,7 +193,7 @@ out_unlock:
>  	nfs4_reset_creds(original_cred);
>  }
>  
> -typedef int (recdir_func)(struct dentry *, struct dentry *);
> +typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
>  
>  struct name_list {
>  	char name[HEXDIR_LEN];
> @@ -219,7 +219,7 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
>  }
>  
>  static int
> -nfsd4_list_rec_dir(recdir_func *f)
> +nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
>  {
>  	const struct cred *original_cred;
>  	struct dentry *dir = rec_file->f_path.dentry;
> @@ -248,7 +248,7 @@ nfsd4_list_rec_dir(recdir_func *f)
>  				status = PTR_ERR(dentry);
>  				break;
>  			}
> -			status = f(dir, dentry);
> +			status = f(dir, dentry, nn);
>  			dput(dentry);
>  		}
>  		list_del(&entry->list);
> @@ -316,7 +316,7 @@ out:
>  }
>  
>  static int
> -purge_old(struct dentry *parent, struct dentry *child)
> +purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
>  {
>  	int status;
>  
> @@ -335,13 +335,14 @@ static void
>  nfsd4_recdir_purge_old(struct net *net, time_t boot_time)
>  {
>  	int status;
> +	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
>  
>  	if (!rec_file)
>  		return;
>  	status = mnt_want_write_file(rec_file);
>  	if (status)
>  		goto out;
> -	status = nfsd4_list_rec_dir(purge_old);
> +	status = nfsd4_list_rec_dir(purge_old, nn);
>  	if (status == 0)
>  		vfs_fsync(rec_file, 0);
>  	mnt_drop_write_file(rec_file);
> @@ -352,7 +353,7 @@ out:
>  }
>  
>  static int
> -load_recdir(struct dentry *parent, struct dentry *child)
> +load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
>  {
>  	if (child->d_name.len != HEXDIR_LEN - 1) {
>  		printk("nfsd4: illegal name %s in recovery directory\n",
> @@ -360,18 +361,19 @@ load_recdir(struct dentry *parent, struct dentry *child)
>  		/* Keep trying; maybe the others are OK: */
>  		return 0;
>  	}
> -	nfs4_client_to_reclaim(child->d_name.name);
> +	nfs4_client_to_reclaim(child->d_name.name, nn);
>  	return 0;
>  }
>  
>  static int
> -nfsd4_recdir_load(void) {
> +nfsd4_recdir_load(struct net *net) {
>  	int status;
> +	struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
>  
>  	if (!rec_file)
>  		return 0;
>  
> -	status = nfsd4_list_rec_dir(load_recdir);
> +	status = nfsd4_list_rec_dir(load_recdir, nn);
>  	if (status)
>  		printk("nfsd4: failed loading clients from recovery"
>  			" directory %s\n", rec_file->f_path.dentry->d_name.name);
> @@ -413,6 +415,33 @@ nfsd4_init_recdir(void)
>  	return status;
>  }
>  
> +
> +static int
> +nfs4_legacy_state_init(struct net *net)
> +{
> +	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
> +	int i;
> +
> +	nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
> +					  CLIENT_HASH_SIZE, GFP_KERNEL);
> +	if (!nn->reclaim_str_hashtbl)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < CLIENT_HASH_SIZE; i++)
> +		INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
> +	nn->reclaim_str_hashtbl_size = 0;
> +
> +	return 0;
> +}
> +
> +static void
> +nfs4_legacy_state_shutdown(struct net *net)
> +{
> +	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
> +
> +	kfree(nn->reclaim_str_hashtbl);
> +}
> +
>  static int
>  nfsd4_load_reboot_recovery_data(struct net *net)
>  {
> @@ -425,13 +454,23 @@ nfsd4_load_reboot_recovery_data(struct net *net)
>  		return -EINVAL;
>  	}
>  
> +	status = nfs4_legacy_state_init(net);
> +	if (status)
> +		return status;
> +

nit: might be clearer to create a new legacy ->init function and have
it call the state_init and then load the recovery data.

>  	nfs4_lock_state();
>  	status = nfsd4_init_recdir();
>  	if (!status)
> -		status = nfsd4_recdir_load();
> +		status = nfsd4_recdir_load(net);
>  	nfs4_unlock_state();
> -	if (status)
> +	if (status) {
>  		printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n");
> +		goto err;
> +	}
> +	return 0;
> +
> +err:
> +	nfs4_legacy_state_shutdown(net);
>  	return status;
>  }
>  
> @@ -447,8 +486,9 @@ nfsd4_shutdown_recdir(void)
>  static void
>  nfsd4_legacy_tracking_exit(struct net *net)
>  {
> -	nfs4_release_reclaim();
> +	nfs4_release_reclaim(net);
>  	nfsd4_shutdown_recdir();
> +	nfs4_legacy_state_shutdown(net);
>  }
>  
>  /*
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 865a793..dc818f4 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -393,11 +393,6 @@ unhash_delegation(struct nfs4_delegation *dp)
>  /* client_lock protects the client lru list and session hash table */
>  static DEFINE_SPINLOCK(client_lock);
>  
> -/* 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)
> -
>  static unsigned int clientid_hashval(u32 id)
>  {
>  	return id & CLIENT_HASH_MASK;
> @@ -409,9 +404,6 @@ static unsigned int clientstr_hashval(const char *name)
>  }
>  
>  /*
> - * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
> - * used in reboot/reset lease grace period processing
> - *
>   * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
>   * setclientid_confirmed info. 
>   *
> @@ -424,8 +416,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.
>   */
> -static struct list_head	reclaim_str_hashtbl[CLIENT_HASH_SIZE];
> -static int reclaim_str_hashtbl_size = 0;
>  static struct list_head	conf_id_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
> @@ -4502,7 +4492,7 @@ nfs4_has_reclaimed_state(const char *name)
>   * failure => all reset bets are off, nfserr_no_grace...
>   */
>  int
> -nfs4_client_to_reclaim(const char *name)
> +nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn)
>  {
>  	unsigned int strhashval;
>  	struct nfs4_client_reclaim *crp = NULL;
> @@ -4513,28 +4503,29 @@ nfs4_client_to_reclaim(const char *name)
>  		return 0;
>  	strhashval = clientstr_hashval(name);
>  	INIT_LIST_HEAD(&crp->cr_strhash);
> -	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
> +	list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
>  	memcpy(crp->cr_recdir, name, HEXDIR_LEN);
> -	reclaim_str_hashtbl_size++;
> +	nn->reclaim_str_hashtbl_size++;
>  	return 1;
>  }
>  
>  void
> -nfs4_release_reclaim(void)
> +nfs4_release_reclaim(struct net *net)
>  {
>  	struct nfs4_client_reclaim *crp = NULL;
>  	int i;
> +	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
>  
>  	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
> -		while (!list_empty(&reclaim_str_hashtbl[i])) {
> -			crp = list_entry(reclaim_str_hashtbl[i].next,
> +		while (!list_empty(&nn->reclaim_str_hashtbl[i])) {
> +			crp = list_entry(nn->reclaim_str_hashtbl[i].next,
>  			                struct nfs4_client_reclaim, cr_strhash);
>  			list_del(&crp->cr_strhash);
>  			kfree(crp);
> -			reclaim_str_hashtbl_size--;
> +			nn->reclaim_str_hashtbl_size--;
>  		}
>  	}
> -	BUG_ON(reclaim_str_hashtbl_size);
> +	BUG_ON(nn->reclaim_str_hashtbl_size);
>  }
>  
>  /*
> @@ -4544,6 +4535,7 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
>  {
>  	unsigned int strhashval;
>  	struct nfs4_client_reclaim *crp = NULL;
> +	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
>  
>  	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
>  		            clp->cl_name.len, clp->cl_name.data,
> @@ -4551,7 +4543,7 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
>  
>  	/* find clp->cl_name in reclaim_str_hashtbl */
>  	strhashval = clientstr_hashval(clp->cl_recdir);
> -	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
> +	list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
>  		if (same_name(crp->cr_recdir, clp->cl_recdir)) {
>  			return crp;
>  		}
> @@ -4711,7 +4703,6 @@ nfs4_state_init(void)
>  		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
>  		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
>  		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
> -		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
>  	}
>  	for (i = 0; i < SESSION_HASH_SIZE; i++)
>  		INIT_LIST_HEAD(&sessionid_hashtbl[i]);
> @@ -4726,7 +4717,6 @@ nfs4_state_init(void)
>  	INIT_LIST_HEAD(&close_lru);
>  	INIT_LIST_HEAD(&client_lru);
>  	INIT_LIST_HEAD(&del_recall_lru);
> -	reclaim_str_hashtbl_size = 0;
>  }
>  
>  /*
> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index b064577..da78804 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -466,7 +466,7 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net,
>  extern void nfs4_lock_state(void);
>  extern void nfs4_unlock_state(void);
>  extern int nfs4_in_grace(void);
> -extern void nfs4_release_reclaim(void);
> +extern void nfs4_release_reclaim(struct net *net);
>  extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
>  extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
>  extern void nfs4_free_openowner(struct nfs4_openowner *);
> @@ -482,7 +482,7 @@ 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 __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
> -extern int nfs4_client_to_reclaim(const char *name);
> +extern int nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn);
>  extern int nfs4_has_reclaimed_state(const char *name);
>  extern void release_session_client(struct nfsd4_session *);
>  extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
> 

Looks like a reasonable and good change, but may need reconciling with
the patches from me that Bruce merged recently into his for-next tree.

-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 05/15] nfsd: make conf_str_hashtbl allocated per net
  2012-11-13 15:48 ` [PATCH 05/15] nfsd: make conf_str_hashtbl " Stanislav Kinsbursky
@ 2012-11-14 13:04   ` Jeff Layton
  0 siblings, 0 replies; 20+ messages in thread
From: Jeff Layton @ 2012-11-14 13:04 UTC (permalink / raw)
  To: Stanislav Kinsbursky
  Cc: bfields, linux-nfs, devel, Trond.Myklebust, linux-kernel

On Tue, 13 Nov 2012 18:48:44 +0300
Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:

> 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.
> 
> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
> ---
>  fs/nfsd/netns.h       |    5 +++++
>  fs/nfsd/nfs4recover.c |    2 +-
>  fs/nfsd/nfs4state.c   |   40 ++++++++++++++++++++++++----------------
>  fs/nfsd/state.h       |    2 +-
>  4 files changed, 31 insertions(+), 18 deletions(-)
> 
> diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> index 0cc85e9..61f41c0 100644
> --- a/fs/nfsd/netns.h
> +++ b/fs/nfsd/netns.h
> @@ -47,10 +47,15 @@ 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_str_hashtbl[] hold confirmed
> +	 * setclientid_confirmed info.
> +	 *
>  	 */
>  	struct list_head *reclaim_str_hashtbl;
>  	int reclaim_str_hashtbl_size;
>  	struct list_head *conf_id_hashtbl;
> +	struct list_head *conf_str_hashtbl;
>  };
>  
>  extern int nfsd_net_id;
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index fc782b5..ac79dd7 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -320,7 +320,7 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
>  {
>  	int status;
>  
> -	if (nfs4_has_reclaimed_state(child->d_name.name))
> +	if (nfs4_has_reclaimed_state(child->d_name.name, nn))
>  		return 0;
>  
>  	status = vfs_rmdir(parent->d_inode, child);
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 74d047e..a709dd2 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -404,9 +404,6 @@ static unsigned int clientstr_hashval(const char *name)
>  }
>  
>  /*
> - * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
> - * setclientid_confirmed info. 
> - *
>   * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
>   * setclientid info.
>   *
> @@ -416,7 +413,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.
>   */
> -static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head client_lru;
> @@ -1335,7 +1331,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]);
>  	strhashval = clientstr_hashval(clp->cl_recdir);
> -	list_move(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
> +	list_move(&clp->cl_strhash, &nn->conf_str_hashtbl[strhashval]);
>  	renew_client(clp);
>  }
>  
> @@ -1378,11 +1374,12 @@ static bool clp_used_exchangeid(struct nfs4_client *clp)
>  } 
>  
>  static struct nfs4_client *
> -find_confirmed_client_by_str(const char *dname, unsigned int hashval)
> +find_confirmed_client_by_str(const char *dname, unsigned int hashval,
> +			     struct nfsd_net *nn)
>  {
>  	struct nfs4_client *clp;
>  
> -	list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
> +	list_for_each_entry(clp, &nn->conf_str_hashtbl[hashval], cl_strhash) {
>  		if (same_name(clp->cl_recdir, dname))
>  			return clp;
>  	}
> @@ -1601,7 +1598,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_str(dname, strhashval);
> +	conf = find_confirmed_client_by_str(dname, strhashval, nn);
>  	if (conf) {
>  		bool creds_match = same_creds(&conf->cl_cred, &rqstp->rq_cred);
>  		bool verfs_match = same_verf(&verf, &conf->cl_verifier);
> @@ -1797,7 +1794,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
>  			goto out_free_conn;
>  		}
>  		hash = clientstr_hashval(unconf->cl_recdir);
> -		old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
> +		old = find_confirmed_client_by_str(unconf->cl_recdir, hash, nn);
>  		if (old)
>  			expire_client(old);
>  		move_to_confirmed(unconf);
> @@ -2203,7 +2200,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_str(dname, strhashval);
> +	conf = find_confirmed_client_by_str(dname, strhashval, nn);
>  	if (conf) {
>  		/* case 0: */
>  		status = nfserr_clid_inuse;
> @@ -2287,7 +2284,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
>  	} else { /* case 3: normal case; new or rebooted client */
>  		unsigned int hash = clientstr_hashval(unconf->cl_recdir);
>  
> -		conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
> +		conf = find_confirmed_client_by_str(unconf->cl_recdir, hash, nn);
>  		if (conf)
>  			expire_client(conf);
>  		move_to_confirmed(unconf);
> @@ -4480,12 +4477,12 @@ alloc_reclaim(void)
>  }
>  
>  int
> -nfs4_has_reclaimed_state(const char *name)
> +nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
>  {
>  	unsigned int strhashval = clientstr_hashval(name);
>  	struct nfs4_client *clp;
>  
> -	clp = find_confirmed_client_by_str(name, strhashval);
> +	clp = find_confirmed_client_by_str(name, strhashval, nn);
>  	if (!clp)
>  		return 0;
>  	return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
> @@ -4703,7 +4700,6 @@ nfs4_state_init(void)
>  	int i;
>  
>  	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
> -		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
>  		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
>  		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
>  	}
> @@ -4751,12 +4747,23 @@ 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;
> +	nn->conf_str_hashtbl = kmalloc(sizeof(struct list_head) *
> +			CLIENT_HASH_SIZE, GFP_KERNEL);
> +	if (!nn->conf_str_hashtbl)
> +		goto err_conf_str;
>  
> -	for (i = 0; i < CLIENT_HASH_SIZE; i++)
> +	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
>  		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
> +		INIT_LIST_HEAD(&nn->conf_str_hashtbl[i]);
> +	}
>  
>  	return 0;
> +
> +err_conf_str:
> +	kfree(nn->conf_id_hashtbl);
> +err:
> +	return -ENOMEM;
>  }
>  
>  static void
> @@ -4772,6 +4779,7 @@ __nfs4_state_shutdown_net(struct net *net)
>  			destroy_client(clp);
>  		}
>  	}
> +	kfree(nn->conf_str_hashtbl);
>  	kfree(nn->conf_id_hashtbl);
>  }
>  
> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index da78804..f350805 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -483,7 +483,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *);
>  extern void nfs4_put_delegation(struct nfs4_delegation *dp);
>  extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
>  extern int nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn);
> -extern int nfs4_has_reclaimed_state(const char *name);
> +extern int nfs4_has_reclaimed_state(const char *name, struct nfsd_net *);
>  extern void release_session_client(struct nfsd4_session *);
>  extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
>  
> 

This too will need to be respun on top of the patches that I recently
sent to Bruce. This hash table has been turned into an rbtree as part
of a scheme to get rid of the need to do md5 hashing here. Shouldn't be
too hard to make those rbtrees per-net though.

-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 06/15] nfsd: make unconf_str_hashtbl allocated per net
  2012-11-13 15:48 ` [PATCH 06/15] nfsd: make unconf_str_hashtbl " Stanislav Kinsbursky
@ 2012-11-14 13:20   ` Jeff Layton
  0 siblings, 0 replies; 20+ messages in thread
From: Jeff Layton @ 2012-11-14 13:20 UTC (permalink / raw)
  To: Stanislav Kinsbursky
  Cc: bfields, linux-nfs, devel, Trond.Myklebust, linux-kernel

On Tue, 13 Nov 2012 18:48:49 +0300
Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:

> 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.
> 
> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
> ---
>  fs/nfsd/netns.h     |    1 +
>  fs/nfsd/nfs4state.c |   34 +++++++++++++++++++---------------
>  2 files changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> index 61f41c0..0577780 100644
> --- a/fs/nfsd/netns.h
> +++ b/fs/nfsd/netns.h
> @@ -56,6 +56,7 @@ struct nfsd_net {
>  	int reclaim_str_hashtbl_size;
>  	struct list_head *conf_id_hashtbl;
>  	struct list_head *conf_str_hashtbl;
> +	struct list_head *unconf_str_hashtbl;
>  };
>  
>  extern int nfsd_net_id;
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index a709dd2..7e44015 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -413,7 +413,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.
>   */
> -static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head	unconf_id_hashtbl[CLIENT_HASH_SIZE];
>  static struct list_head client_lru;
>  static struct list_head close_lru;
> @@ -1314,8 +1313,9 @@ static void
>  add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
>  {
>  	unsigned int idhashval;
> +	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
>  
> -	list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
> +	list_add(&clp->cl_strhash, &nn->unconf_str_hashtbl[strhashval]);
>  	idhashval = clientid_hashval(clp->cl_clientid.cl_id);
>  	list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
>  	renew_client(clp);
> @@ -1387,11 +1387,12 @@ find_confirmed_client_by_str(const char *dname, unsigned int hashval,
>  }
>  
>  static struct nfs4_client *
> -find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
> +find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
> +			       struct nfsd_net *nn)
>  {
>  	struct nfs4_client *clp;
>  
> -	list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
> +	list_for_each_entry(clp, &nn->unconf_str_hashtbl[hashval], cl_strhash) {
>  		if (same_name(clp->cl_recdir, dname))
>  			return clp;
>  	}
> @@ -1643,7 +1644,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
>  		goto out;
>  	}
>  
> -	unconf  = find_unconfirmed_client_by_str(dname, strhashval);
> +	unconf  = find_unconfirmed_client_by_str(dname, strhashval, nn);
>  	if (unconf) /* case 4, possible retry or client restart */
>  		expire_client(unconf);
>  
> @@ -2215,7 +2216,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  			goto out;
>  		}
>  	}
> -	unconf = find_unconfirmed_client_by_str(dname, strhashval);
> +	unconf = find_unconfirmed_client_by_str(dname, strhashval, nn);
>  	if (unconf)
>  		expire_client(unconf);
>  	status = nfserr_jukebox;
> @@ -4700,7 +4701,6 @@ nfs4_state_init(void)
>  	int i;
>  
>  	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
> -		INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
>  		INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
>  	}
>  	for (i = 0; i < SESSION_HASH_SIZE; i++)
> @@ -4752,14 +4752,21 @@ static int nfs4_state_start_net(struct net *net)
>  			CLIENT_HASH_SIZE, GFP_KERNEL);
>  	if (!nn->conf_str_hashtbl)
>  		goto err_conf_str;
> +	nn->unconf_str_hashtbl = kmalloc(sizeof(struct list_head) *
> +			CLIENT_HASH_SIZE, GFP_KERNEL);
> +	if (!nn->unconf_str_hashtbl)
> +		goto err_unconf_str;
>  
>  	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
>  		INIT_LIST_HEAD(&nn->conf_id_hashtbl[i]);
>  		INIT_LIST_HEAD(&nn->conf_str_hashtbl[i]);
> +		INIT_LIST_HEAD(&nn->unconf_str_hashtbl[i]);
>  	}
>  
>  	return 0;
>  
> +err_unconf_str:
> +	kfree(nn->conf_str_hashtbl);
>  err_conf_str:
>  	kfree(nn->conf_id_hashtbl);
>  err:
> @@ -4778,7 +4785,12 @@ __nfs4_state_shutdown_net(struct net *net)
>  			clp = list_entry(nn->conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
>  			destroy_client(clp);
>  		}
> +		while (!list_empty(&nn->unconf_str_hashtbl[i])) {
> +			clp = list_entry(nn->unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
> +			destroy_client(clp);
> +		}
>  	}
> +	kfree(nn->unconf_str_hashtbl);
>  	kfree(nn->conf_str_hashtbl);
>  	kfree(nn->conf_id_hashtbl);
>  }
> @@ -4837,19 +4849,11 @@ out_recovery:
>  static void
>  __nfs4_state_shutdown(struct net *net)
>  {
> -	int i;
> -	struct nfs4_client *clp = NULL;
>  	struct nfs4_delegation *dp = NULL;
>  	struct list_head *pos, *next, reaplist;
>  
>  	__nfs4_state_shutdown_net(net);
>  
> -	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
> -		while (!list_empty(&unconf_str_hashtbl[i])) {
> -			clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
> -			destroy_client(clp);
> -		}
> -	}
>  	INIT_LIST_HEAD(&reaplist);
>  	spin_lock(&recall_lock);
>  	list_for_each_safe(pos, next, &del_recall_lru) {
> 

This too will need to be rebased on top of nfsd-next tree. This
hashtable has also been turned into a rbtree for the same reasons as the
conf_str_hashtbl.

-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net
  2012-11-14 13:02   ` Jeff Layton
@ 2012-11-14 13:22     ` Stanislav Kinsbursky
  0 siblings, 0 replies; 20+ messages in thread
From: Stanislav Kinsbursky @ 2012-11-14 13:22 UTC (permalink / raw)
  To: Jeff Layton; +Cc: bfields, linux-nfs, devel, Trond.Myklebust, linux-kernel

14.11.2012 17:02, Jeff Layton пишет:
> On Tue, 13 Nov 2012 18:48:33 +0300
> Stanislav Kinsbursky <skinsbursky@parallels.com> wrote:
>
<snip>
>>
>> +
>> +static int
>> +nfs4_legacy_state_init(struct net *net)
>> +{
>> +     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
>> +     int i;
>> +
>> +     nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
>> +                                       CLIENT_HASH_SIZE, GFP_KERNEL);
>> +     if (!nn->reclaim_str_hashtbl)
>> +             return -ENOMEM;
>> +
>> +     for (i = 0; i < CLIENT_HASH_SIZE; i++)
>> +             INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
>> +     nn->reclaim_str_hashtbl_size = 0;
>> +
>> +     return 0;
>> +}
>> +
>> +static void
>> +nfs4_legacy_state_shutdown(struct net *net)
>> +{
>> +     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
>> +
>> +     kfree(nn->reclaim_str_hashtbl);
>> +}
>> +
>>   static int
>>   nfsd4_load_reboot_recovery_data(struct net *net)
>>   {
>> @@ -425,13 +454,23 @@ nfsd4_load_reboot_recovery_data(struct net *net)
>>                return -EINVAL;
>>        }
>>
>> +     status = nfs4_legacy_state_init(net);
>> +     if (status)
>> +             return status;
>> +
>
> nit: might be clearer to create a new legacy ->init function and have
> it call the state_init and then load the recovery data.
>

Yep, sure.

>
> Looks like a reasonable and good change, but may need reconciling with
> the patches from me that Bruce merged recently into his for-next tree.
>

Thanks. Already working on it.

-- 
Best regards,
Stanislav Kinsbursky

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-11-14 13:23 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-13 15:48 [RFC PATCH 00/15] NFSd state containerization Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 01/15] nfsd: use service net instead of hard-coded net where possible Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 02/15] nfsd: make nfs4_client network namespace dependent Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net Stanislav Kinsbursky
2012-11-14 13:02   ` Jeff Layton
2012-11-14 13:22     ` Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 04/15] nfsd: make conf_id_hashtbl " Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 05/15] nfsd: make conf_str_hashtbl " Stanislav Kinsbursky
2012-11-14 13:04   ` Jeff Layton
2012-11-13 15:48 ` [PATCH 06/15] nfsd: make unconf_str_hashtbl " Stanislav Kinsbursky
2012-11-14 13:20   ` Jeff Layton
2012-11-13 15:48 ` [PATCH 07/15] nfsd: make unconf_str_hastbl " Stanislav Kinsbursky
2012-11-13 15:48 ` [PATCH 08/15] nfsd: make ownerstr_hashtbl " Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 09/15] nfsd: make lockowner_ino_hashtbl " Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 10/15] nfsd: make sessionid_hashtbl " Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 11/15] nfsd: make client_lru list " Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 12/15] nfsd: make close_lru " Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 13/15] nfsd: use service net instead of hard-coded init_net Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 14/15] nfsd: pass nfsd_net instead of net to grace enders Stanislav Kinsbursky
2012-11-13 15:49 ` [PATCH 15/15] nfsd: make laundromat network namespace aware Stanislav Kinsbursky

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.