* [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* 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 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@fieldses.org, linux-nfs@vger.kernel.org, devel@openvz.org,
Trond.Myklebust@netapp.com, linux-kernel@vger.kernel.org
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
* [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* 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
* [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* 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
* [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