NFSd state containerization
Subsystems (2)
cover NFSd state containerization
This patch set is my first attempt to containerize NFSv4 state - i.e. make it works in networks namespace context.
I admit, that some of this new code could be partially rewritten during future NFSd containerization.
But the overall idea look more or less correct to me.
So, the main things here are:
1) making nfs4_client network 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(-)
PATCH 1/15 nfsd: use service net instead of hard-coded net where possible
--- fs/nfsd/nfs4state.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +5 -5
@@ -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);
PATCH 2/15 nfsd: make nfs4_client network namespace dependent
In reply to Stanislav KinsburskyAnd use it's net where possible.
--- fs/nfsd/nfs4callback.c | 2 +- fs/nfsd/nfs4recover.c | 9 +++------ fs/nfsd/nfs4state.c | 15 +++++++++------ fs/nfsd/state.h | 1 + 4 files changed, 14 insertions(+), 13 deletions(-)
fs/nfsd/nfs4callback.c +1 -1
@@ -663,7 +663,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c .to_retries = 0, };struct rpc_create_args args = { - .net = &init_net, + .net = clp->net, .address = (struct sockaddr *) &conn->cb_addr, .addrsize = conn->cb_addrlen, .saddress = (struct sockaddr *) &conn->cb_saddr,
fs/nfsd/nfs4recover.c +3 -6
@@ -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 */
fs/nfsd/nfs4state.c +9 -6
@@ -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_relse 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);
fs/nfsd/state.h +1 -0
@@ -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
PATCH 3/15 nfsd: make reclaim_str_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.
Note: this hash is used only by legacy tracker. So let's allocate hash in tracker init.
--- fs/nfsd/netns.h | 12 +++++++++ fs/nfsd/nfs4recover.c | 64 ++++++++++++++++++++++++++++++++++++++++--------- fs/nfsd/nfs4state.c | 32 ++++++++----------------- fs/nfsd/state.h | 4 ++- 4 files changed, 77 insertions(+), 35 deletions(-)
fs/nfsd/netns.h +12 -0
@@ -24,6 +24,11 @@#include <net/net_namespace.h> #include <net/netns/generic.h> +/* Hash tables for nfs4_clientid state */ +#define CLIENT_HASH_BITS 4 +#define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS) +#define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1) +struct cld_net ;struct nfsd_net {
@@ -38,6 +43,13 @@ struct nfsd_net {struct lock_manager nfsd4_manager;bool grace_ended;time_t boot_time; + +/* +* reclaim_str_hashtbl[] holds known client info from previous reset/reboot +* used in reboot/reset lease grace period processing +*/ +struct list_head *reclaim_str_hashtbl; +int reclaim_str_hashtbl_size; };extern int nfsd_net_id;
fs/nfsd/nfs4recover.c +52 -12
145 lines not on this page · raw message
fs/nfsd/nfs4state.c +11 -21
@@ -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 ; }/*
fs/nfsd/state.h +2 -2
@@ -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 *);
Re: [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net
Quoted 167 lines · On Tue, 13 Nov 2012 18:48:33 +0300 Stanislav Kinsbursky…
This hash holds
nfs4_clientsinfo, 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 <[email protected]>--- 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(-)fs/nfsd/netns.h +12
-0@@ -24,6 +24,11 @@#include <net/net_namespace.h> #include <net/netns/generic.h> +/* Hash tables for nfs4_clientid state */ +#define CLIENT_HASH_BITS 4 +#define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS) +#define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1) +struct cld_net ;struct nfsd_net {@@ -38,6 +43,13 @@ struct nfsd_net {struct lock_manager nfsd4_manager;bool grace_ended;time_t boot_time; + +/* +* reclaim_str_hashtbl[] holds known client info from previous reset/reboot +* used in reboot/reset lease grace period processing +*/ +struct list_head *reclaim_str_hashtbl; +int reclaim_str_hashtbl_size; };extern int nfsd_net_id;fs/nfsd/nfs4recover.c +38
-9@@ -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) {
fs/nfsd/nfs4recover.c nfsd4_load_reboot_recovery_data(struct net *net) · line 460
Quoted 7 lines
fs/nfsd/nfs4recover.c +4
-0@@ -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.
Quoted 158 lines
fs/nfsd/nfs4recover.c +10
-3nfs4_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); }/* fs/nfsd/nfs4state.c +11
-21@@ -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 ; }/* fs/nfsd/state.h +1
-1@@ -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 *);
fs/nfsd/state.h extern void nfsd4_destroy_callback_queue(void); · line 488
Quoted 8 lines
fs/nfsd/state.h +1
-1@@ -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.
Signature · 1 line
Jeff Layton <[email protected]>
Re: [PATCH 03/15] nfsd: make reclaim_str_hashtbl allocated per net
14.11.2012 17:02, Jeff Layton пишет:
Quoted 3 lines
On Tue, 13 Nov 2012 18:48:33 +0300
Stanislav Kinsbursky <[email protected]> wrote:
<snip>
Quoted 35 lines
Quoted 35 lines
fs/nfsd/nfs4recover.c +27
-0+ +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 ; }
Quoted 8 lines
fs/nfsd/nfs4recover.c nfsd4_load_reboot_recovery_data(struct net *net) · line 460
Quoted 4 lines
fs/nfsd/nfs4recover.c +4
-0+ 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_initand then load the recovery data.
Yep, sure.
Quoted 4 lines
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.
Signature · 2 lines
Best regards, Stanislav Kinsbursky
PATCH 4/15 nfsd: make conf_id_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 73 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 18 deletions(-)
fs/nfsd/netns.h +1 -0
@@ -50,6 +50,7 @@ struct nfsd_net {*/ struct list_head *reclaim_str_hashtbl;int reclaim_str_hashtbl_size; +struct list_head *conf_id_hashtbl; };extern int nfsd_net_id;
fs/nfsd/nfs4state.c +55 -18
192 lines not on this page · raw message
PATCH 5/15 nfsd: make conf_str_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 5 +++++ fs/nfsd/nfs4recover.c | 2 +- fs/nfsd/nfs4state.c | 40 ++++++++++++++++++++++++---------------- fs/nfsd/state.h | 2 +- 4 files changed, 31 insertions(+), 18 deletions(-)
fs/nfsd/netns.h +5 -0
@@ -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;
fs/nfsd/nfs4recover.c +1 -1
@@ -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);
fs/nfsd/nfs4state.c +24 -16
@@ -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); }
fs/nfsd/state.h +1 -1
@@ -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 *);
Re: [PATCH 05/15] nfsd: make conf_str_hashtbl allocated per net
Quoted 193 lines · On Tue, 13 Nov 2012 18:48:44 +0300 Stanislav Kinsbursky…
This hash holds
nfs4_clientsinfo, 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 <[email protected]>--- 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(-)fs/nfsd/netns.h +5
-0@@ -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;fs/nfsd/nfs4recover.c +1
-1@@ -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);fs/nfsd/nfs4state.c +24
-16@@ -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); }fs/nfsd/state.h +0
-0
fs/nfsd/state.h extern void nfsd4_shutdown_callback(struct nfs4_client *); · line 489
Quoted 8 lines
fs/nfsd/state.h +1
-1@@ -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.
Signature · 1 line
Jeff Layton <[email protected]>
PATCH 6/15 nfsd: make unconf_str_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-)
fs/nfsd/netns.h +1 -0
@@ -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;
fs/nfsd/nfs4state.c +19 -15
@@ -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) {
Re: [PATCH 06/15] nfsd: make unconf_str_hashtbl allocated per net
Quoted 135 lines · On Tue, 13 Nov 2012 18:48:49 +0300 Stanislav Kinsbursky…
This hash holds
nfs4_clientsinfo, 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 <[email protected]>--- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 34 +++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-)fs/nfsd/netns.h +1
-0@@ -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;fs/nfsd/nfs4state.c +19
-9@@ -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);
fs/nfsd/nfs4state.c out_recovery: · line 4859
Quoted 10 lines
fs/nfsd/nfs4state.c +0
-6-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.
Signature · 1 line
Jeff Layton <[email protected]>
PATCH 7/15 nfsd: make unconf_str_hastbl allocated per net
In reply to Stanislav KinsburskyThis hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 3 +++ fs/nfsd/nfs4state.c | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-)
fs/nfsd/netns.h +3 -0
@@ -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;
fs/nfsd/nfs4state.c +14 -13
@@ -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 *cstastruct 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);
PATCH 8/15 nfsd: make ownerstr_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds open owner state and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 15 deletions(-)
fs/nfsd/netns.h +1 -0
@@ -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;
fs/nfsd/nfs4state.c +26 -15
137 lines not on this page · raw message
PATCH 9/15 nfsd: make lockowner_ino_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds file lock owners and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 4 ++++ fs/nfsd/nfs4state.c | 27 ++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-)
fs/nfsd/netns.h +4 -0
@@ -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;
fs/nfsd/nfs4state.c +16 -11
@@ -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, cstatic 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, sstruct 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, sstruct 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);
PATCH 10/15 nfsd: make sessionid_hashtbl allocated per net
In reply to Stanislav KinsburskyThis hash holds established sessions state and closely associated with nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace too.
Note: this hash can be allocated in per-net operations. But it looks better to allocate it on nfsd state start and thus don't waste resources if server is not running.
--- fs/nfsd/netns.h | 3 +++ fs/nfsd/nfs4state.c | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-)
fs/nfsd/netns.h +3 -0
@@ -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;
fs/nfsd/nfs4state.c +17 -11
@@ -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 nfs4kref_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);
PATCH 11/15 nfsd: make client_lru list per net
In reply to Stanislav KinsburskyThis list holds nfs4 clients queue for lease renewal, which are network namespace aware. So let's make this list per network namespace too.
--- fs/nfsd/netns.h | 5 +++++ fs/nfsd/nfs4state.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-)
fs/nfsd/netns.h +5 -0
@@ -68,6 +68,11 @@ struct nfsd_net {struct list_head *ownerstr_hashtbl;struct list_head *lockowner_ino_hashtbl;struct list_head *sessionid_hashtbl; +/* +* client_lru holds client queue ordered by nfs4_client.cl_time +* for lease renewal. +*/ +struct list_head client_lru; };extern int nfsd_net_id;
fs/nfsd/nfs4state.c +8 -8
@@ -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 ;
PATCH 12/15 nfsd: make close_lru list per net
In reply to Stanislav KinsburskyThis list holds nfs4 clients (open) stateowner queue for last close replay, which are network namespace aware. So let's make this list per network namespace too.
--- fs/nfsd/netns.h | 4 ++++ fs/nfsd/nfs4state.c | 18 +++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-)
fs/nfsd/netns.h +4 -0
@@ -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;
fs/nfsd/nfs4state.c +7 -11
@@ -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 ;
PATCH 13/15 nfsd: use service net instead of hard-coded init_net
In reply to Stanislav KinsburskyThis patch replaces init_net by SVC_NET(), where possible and also passes proper context to nested functions where required.
--- fs/nfsd/nfs4proc.c | 13 +++++++---- fs/nfsd/nfs4state.c | 63 +++++++++++++++++++++++++++++++-------------------- fs/nfsd/state.h | 2 +- fs/nfsd/xdr4.h | 2 +- 4 files changed, 49 insertions(+), 31 deletions(-)
fs/nfsd/nfs4proc.c +9 -4
@@ -40,6 +40,7 @@#include "xdr4.h" #include "vfs.h" #include "current_stateid.h" +#include "netns.h" #define NFSDDBG_FACILITY NFSDDBG_PROC
@@ -304,6 +305,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, {__be32 status;struct nfsd4_compoundres *resp; +struct net *net =SVC_NET (rqstp); +struct nfsd_net *nn =net_generic (net, nfsd_net_id); dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n", (int)open->op_fname.len, open->op_fname.data,
@@ -331,7 +334,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,/* check seqid for replay. set nfs4_owner */ resp = rqstp->rq_resp; - status =nfsd4_process_open1 (&resp->cstate, open); + status =nfsd4_process_open1 (&resp->cstate, open, nn);if (status == nfserr_replay_me) {struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;fh_put (&cstate->current_fh);
@@ -354,10 +357,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,/* Openowner is now set, so sequence id will get bumped. Now we need * these checks before we do any creates: */ status = nfserr_grace; -if (locks_in_grace (SVC_NET (rqstp)) && open->op_claim_type !=NFS4_OPEN_CLAIM_PREVIOUS ) +if (locks_in_grace (net) && open->op_claim_type !=NFS4_OPEN_CLAIM_PREVIOUS ) goto out; status = nfserr_no_grace; -if (!locks_in_grace (SVC_NET (rqstp)) && open->op_claim_type ==NFS4_OPEN_CLAIM_PREVIOUS ) +if (!locks_in_grace (net) && open->op_claim_type ==NFS4_OPEN_CLAIM_PREVIOUS ) goto out;switch (open->op_claim_type) {
@@ -370,7 +373,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,break ;case NFS4_OPEN_CLAIM_PREVIOUS : open->op_openowner->oo_flags |=NFS4_OO_CONFIRMED ; - status =nfs4_check_open_reclaim (&open->op_clientid, cstate->minorversion); + status =nfs4_check_open_reclaim (&open->op_clientid, + cstate->minorversion, + nn);if (status) goto out;case NFS4_OPEN_CLAIM_FH :
fs/nfsd/nfs4state.c +38 -25
223 lines not on this page · raw message
fs/nfsd/state.h +1 -1
@@ -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 );
fs/nfsd/xdr4.h +1 -1
@@ -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);
PATCH 14/15 nfsd: pass nfsd_net instead of net to grace enders
In reply to Stanislav KinsburskyPassing net context looks as overkill.
--- fs/nfsd/nfs4recover.c | 12 +++++------- fs/nfsd/nfs4state.c | 8 +++----- fs/nfsd/state.h | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-)
fs/nfsd/nfs4recover.c +5 -7
@@ -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
fs/nfsd/nfs4state.c +3 -5
@@ -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) {
fs/nfsd/state.h +1 -1
@@ -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 */
PATCH 15/15 nfsd: make laundromat network namespace aware
In reply to Stanislav KinsburskyThis patch moves laundromat_work to nfsd per-net context, thus allowing to run multiple laundries.
--- fs/nfsd/netns.h | 2 ++ fs/nfsd/nfs4state.c | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-)
fs/nfsd/netns.h +2 -0
@@ -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;
fs/nfsd/nfs4state.c +13 -8
@@ -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 ();