summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorScott Mayhew <smayhew@redhat.com>2019-03-26 18:06:26 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-04-24 09:46:34 -0400
commit6b1891052a3f8e3c3217e8512bbed2fd6252977b (patch)
tree4968ba406e795b3e4cd9fd7d245f1aede666f303 /fs/nfsd
parent9d69338c8c5fc68e9ae3ab23d01356ca024b789e (diff)
nfsd: make nfs4_client_reclaim use an xdr_netobj instead of a fixed char array
This will allow the reclaim_str_hashtbl to store either the recovery directory names used by the legacy client tracking code or the full client strings used by the nfsdcld client tracking code. Signed-off-by: Scott Mayhew <smayhew@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4recover.c109
-rw-r--r--fs/nfsd/nfs4state.c30
-rw-r--r--fs/nfsd/state.h8
3 files changed, 110 insertions, 37 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5188f9f70c78..2243b909b407 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -170,12 +170,33 @@ legacy_recdir_name_error(struct nfs4_client *clp, int error)
170} 170}
171 171
172static void 172static void
173__nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
174 const char *dname, int len, struct nfsd_net *nn)
175{
176 struct xdr_netobj name;
177 struct nfs4_client_reclaim *crp;
178
179 name.data = kmemdup(dname, len, GFP_KERNEL);
180 if (!name.data) {
181 dprintk("%s: failed to allocate memory for name.data!\n",
182 __func__);
183 return;
184 }
185 name.len = len;
186 crp = nfs4_client_to_reclaim(name, nn);
187 if (!crp) {
188 kfree(name.data);
189 return;
190 }
191 crp->cr_clp = clp;
192}
193
194static void
173nfsd4_create_clid_dir(struct nfs4_client *clp) 195nfsd4_create_clid_dir(struct nfs4_client *clp)
174{ 196{
175 const struct cred *original_cred; 197 const struct cred *original_cred;
176 char dname[HEXDIR_LEN]; 198 char dname[HEXDIR_LEN];
177 struct dentry *dir, *dentry; 199 struct dentry *dir, *dentry;
178 struct nfs4_client_reclaim *crp;
179 int status; 200 int status;
180 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 201 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
181 202
@@ -221,11 +242,9 @@ out_put:
221out_unlock: 242out_unlock:
222 inode_unlock(d_inode(dir)); 243 inode_unlock(d_inode(dir));
223 if (status == 0) { 244 if (status == 0) {
224 if (nn->in_grace) { 245 if (nn->in_grace)
225 crp = nfs4_client_to_reclaim(dname, nn); 246 __nfsd4_create_reclaim_record_grace(clp, dname,
226 if (crp) 247 HEXDIR_LEN, nn);
227 crp->cr_clp = clp;
228 }
229 vfs_fsync(nn->rec_file, 0); 248 vfs_fsync(nn->rec_file, 0);
230 } else { 249 } else {
231 printk(KERN_ERR "NFSD: failed to write recovery record" 250 printk(KERN_ERR "NFSD: failed to write recovery record"
@@ -346,10 +365,29 @@ out_unlock:
346} 365}
347 366
348static void 367static void
368__nfsd4_remove_reclaim_record_grace(const char *dname, int len,
369 struct nfsd_net *nn)
370{
371 struct xdr_netobj name;
372 struct nfs4_client_reclaim *crp;
373
374 name.data = kmemdup(dname, len, GFP_KERNEL);
375 if (!name.data) {
376 dprintk("%s: failed to allocate memory for name.data!\n",
377 __func__);
378 return;
379 }
380 name.len = len;
381 crp = nfsd4_find_reclaim_client(name, nn);
382 kfree(name.data);
383 if (crp)
384 nfs4_remove_reclaim_record(crp, nn);
385}
386
387static void
349nfsd4_remove_clid_dir(struct nfs4_client *clp) 388nfsd4_remove_clid_dir(struct nfs4_client *clp)
350{ 389{
351 const struct cred *original_cred; 390 const struct cred *original_cred;
352 struct nfs4_client_reclaim *crp;
353 char dname[HEXDIR_LEN]; 391 char dname[HEXDIR_LEN];
354 int status; 392 int status;
355 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 393 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
@@ -374,12 +412,9 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
374 nfs4_reset_creds(original_cred); 412 nfs4_reset_creds(original_cred);
375 if (status == 0) { 413 if (status == 0) {
376 vfs_fsync(nn->rec_file, 0); 414 vfs_fsync(nn->rec_file, 0);
377 if (nn->in_grace) { 415 if (nn->in_grace)
378 /* remove reclaim record */ 416 __nfsd4_remove_reclaim_record_grace(dname,
379 crp = nfsd4_find_reclaim_client(dname, nn); 417 HEXDIR_LEN, nn);
380 if (crp)
381 nfs4_remove_reclaim_record(crp, nn);
382 }
383 } 418 }
384out_drop_write: 419out_drop_write:
385 mnt_drop_write_file(nn->rec_file); 420 mnt_drop_write_file(nn->rec_file);
@@ -393,14 +428,31 @@ static int
393purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 428purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
394{ 429{
395 int status; 430 int status;
431 struct xdr_netobj name;
396 432
397 if (nfs4_has_reclaimed_state(child->d_name.name, nn)) 433 if (child->d_name.len != HEXDIR_LEN - 1) {
434 printk("%s: illegal name %pd in recovery directory\n",
435 __func__, child);
436 /* Keep trying; maybe the others are OK: */
398 return 0; 437 return 0;
438 }
439 name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
440 if (!name.data) {
441 dprintk("%s: failed to allocate memory for name.data!\n",
442 __func__);
443 goto out;
444 }
445 name.len = HEXDIR_LEN;
446 if (nfs4_has_reclaimed_state(name, nn))
447 goto out_free;
399 448
400 status = vfs_rmdir(d_inode(parent), child); 449 status = vfs_rmdir(d_inode(parent), child);
401 if (status) 450 if (status)
402 printk("failed to remove client recovery directory %pd\n", 451 printk("failed to remove client recovery directory %pd\n",
403 child); 452 child);
453out_free:
454 kfree(name.data);
455out:
404 /* Keep trying, success or failure: */ 456 /* Keep trying, success or failure: */
405 return 0; 457 return 0;
406} 458}
@@ -430,13 +482,24 @@ out:
430static int 482static int
431load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 483load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
432{ 484{
485 struct xdr_netobj name;
486
433 if (child->d_name.len != HEXDIR_LEN - 1) { 487 if (child->d_name.len != HEXDIR_LEN - 1) {
434 printk("nfsd4: illegal name %pd in recovery directory\n", 488 printk("%s: illegal name %pd in recovery directory\n",
435 child); 489 __func__, child);
436 /* Keep trying; maybe the others are OK: */ 490 /* Keep trying; maybe the others are OK: */
437 return 0; 491 return 0;
438 } 492 }
439 nfs4_client_to_reclaim(child->d_name.name, nn); 493 name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
494 if (!name.data) {
495 dprintk("%s: failed to allocate memory for name.data!\n",
496 __func__);
497 goto out;
498 }
499 name.len = HEXDIR_LEN;
500 if (!nfs4_client_to_reclaim(name, nn))
501 kfree(name.data);
502out:
440 return 0; 503 return 0;
441} 504}
442 505
@@ -616,6 +679,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
616 char dname[HEXDIR_LEN]; 679 char dname[HEXDIR_LEN];
617 struct nfs4_client_reclaim *crp; 680 struct nfs4_client_reclaim *crp;
618 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 681 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
682 struct xdr_netobj name;
619 683
620 /* did we already find that this client is stable? */ 684 /* did we already find that this client is stable? */
621 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 685 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
@@ -628,13 +692,22 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
628 } 692 }
629 693
630 /* look for it in the reclaim hashtable otherwise */ 694 /* look for it in the reclaim hashtable otherwise */
631 crp = nfsd4_find_reclaim_client(dname, nn); 695 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
696 if (!name.data) {
697 dprintk("%s: failed to allocate memory for name.data!\n",
698 __func__);
699 goto out_enoent;
700 }
701 name.len = HEXDIR_LEN;
702 crp = nfsd4_find_reclaim_client(name, nn);
703 kfree(name.data);
632 if (crp) { 704 if (crp) {
633 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 705 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
634 crp->cr_clp = clp; 706 crp->cr_clp = clp;
635 return 0; 707 return 0;
636 } 708 }
637 709
710out_enoent:
638 return -ENOENT; 711 return -ENOENT;
639} 712}
640 713
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f056b1d3fecd..e601416aaf5f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1067,9 +1067,9 @@ static unsigned int clientid_hashval(u32 id)
1067 return id & CLIENT_HASH_MASK; 1067 return id & CLIENT_HASH_MASK;
1068} 1068}
1069 1069
1070static unsigned int clientstr_hashval(const char *name) 1070static unsigned int clientstr_hashval(struct xdr_netobj name)
1071{ 1071{
1072 return opaque_hashval(name, 8) & CLIENT_HASH_MASK; 1072 return opaque_hashval(name.data, 8) & CLIENT_HASH_MASK;
1073} 1073}
1074 1074
1075/* 1075/*
@@ -2048,11 +2048,6 @@ compare_blob(const struct xdr_netobj *o1, const struct xdr_netobj *o2)
2048 return memcmp(o1->data, o2->data, o1->len); 2048 return memcmp(o1->data, o2->data, o1->len);
2049} 2049}
2050 2050
2051static int same_name(const char *n1, const char *n2)
2052{
2053 return 0 == memcmp(n1, n2, HEXDIR_LEN);
2054}
2055
2056static int 2051static int
2057same_verf(nfs4_verifier *v1, nfs4_verifier *v2) 2052same_verf(nfs4_verifier *v1, nfs4_verifier *v2)
2058{ 2053{
@@ -6457,7 +6452,7 @@ alloc_reclaim(void)
6457} 6452}
6458 6453
6459bool 6454bool
6460nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn) 6455nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn)
6461{ 6456{
6462 struct nfs4_client_reclaim *crp; 6457 struct nfs4_client_reclaim *crp;
6463 6458
@@ -6467,20 +6462,24 @@ nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn)
6467 6462
6468/* 6463/*
6469 * failure => all reset bets are off, nfserr_no_grace... 6464 * failure => all reset bets are off, nfserr_no_grace...
6465 *
6466 * The caller is responsible for freeing name.data if NULL is returned (it
6467 * will be freed in nfs4_remove_reclaim_record in the normal case).
6470 */ 6468 */
6471struct nfs4_client_reclaim * 6469struct nfs4_client_reclaim *
6472nfs4_client_to_reclaim(const char *name, struct nfsd_net *nn) 6470nfs4_client_to_reclaim(struct xdr_netobj name, struct nfsd_net *nn)
6473{ 6471{
6474 unsigned int strhashval; 6472 unsigned int strhashval;
6475 struct nfs4_client_reclaim *crp; 6473 struct nfs4_client_reclaim *crp;
6476 6474
6477 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name); 6475 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", name.len, name.data);
6478 crp = alloc_reclaim(); 6476 crp = alloc_reclaim();
6479 if (crp) { 6477 if (crp) {
6480 strhashval = clientstr_hashval(name); 6478 strhashval = clientstr_hashval(name);
6481 INIT_LIST_HEAD(&crp->cr_strhash); 6479 INIT_LIST_HEAD(&crp->cr_strhash);
6482 list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]); 6480 list_add(&crp->cr_strhash, &nn->reclaim_str_hashtbl[strhashval]);
6483 memcpy(crp->cr_recdir, name, HEXDIR_LEN); 6481 crp->cr_name.data = name.data;
6482 crp->cr_name.len = name.len;
6484 crp->cr_clp = NULL; 6483 crp->cr_clp = NULL;
6485 nn->reclaim_str_hashtbl_size++; 6484 nn->reclaim_str_hashtbl_size++;
6486 } 6485 }
@@ -6491,6 +6490,7 @@ void
6491nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn) 6490nfs4_remove_reclaim_record(struct nfs4_client_reclaim *crp, struct nfsd_net *nn)
6492{ 6491{
6493 list_del(&crp->cr_strhash); 6492 list_del(&crp->cr_strhash);
6493 kfree(crp->cr_name.data);
6494 kfree(crp); 6494 kfree(crp);
6495 nn->reclaim_str_hashtbl_size--; 6495 nn->reclaim_str_hashtbl_size--;
6496} 6496}
@@ -6514,16 +6514,16 @@ nfs4_release_reclaim(struct nfsd_net *nn)
6514/* 6514/*
6515 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 6515 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
6516struct nfs4_client_reclaim * 6516struct nfs4_client_reclaim *
6517nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn) 6517nfsd4_find_reclaim_client(struct xdr_netobj name, struct nfsd_net *nn)
6518{ 6518{
6519 unsigned int strhashval; 6519 unsigned int strhashval;
6520 struct nfs4_client_reclaim *crp = NULL; 6520 struct nfs4_client_reclaim *crp = NULL;
6521 6521
6522 dprintk("NFSD: nfs4_find_reclaim_client for recdir %s\n", recdir); 6522 dprintk("NFSD: nfs4_find_reclaim_client for name %.*s\n", name.len, name.data);
6523 6523
6524 strhashval = clientstr_hashval(recdir); 6524 strhashval = clientstr_hashval(name);
6525 list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) { 6525 list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) {
6526 if (same_name(crp->cr_recdir, recdir)) { 6526 if (compare_blob(&crp->cr_name, &name) == 0) {
6527 return crp; 6527 return crp;
6528 } 6528 }
6529 } 6529 }
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 9d6cb246c6c5..0b74d371ed67 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -368,7 +368,7 @@ struct nfs4_client {
368struct nfs4_client_reclaim { 368struct nfs4_client_reclaim {
369 struct list_head cr_strhash; /* hash by cr_name */ 369 struct list_head cr_strhash; /* hash by cr_name */
370 struct nfs4_client *cr_clp; /* pointer to associated clp */ 370 struct nfs4_client *cr_clp; /* pointer to associated clp */
371 char cr_recdir[HEXDIR_LEN]; /* recover dir */ 371 struct xdr_netobj cr_name; /* recovery dir name */
372}; 372};
373 373
374/* A reasonable value for REPLAY_ISIZE was estimated as follows: 374/* A reasonable value for REPLAY_ISIZE was estimated as follows:
@@ -620,7 +620,7 @@ void nfs4_put_stid(struct nfs4_stid *s);
620void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid); 620void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
621void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *); 621void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *);
622extern void nfs4_release_reclaim(struct nfsd_net *); 622extern void nfs4_release_reclaim(struct nfsd_net *);
623extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, 623extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct xdr_netobj name,
624 struct nfsd_net *nn); 624 struct nfsd_net *nn);
625extern __be32 nfs4_check_open_reclaim(clientid_t *clid, 625extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
626 struct nfsd4_compound_state *cstate, struct nfsd_net *nn); 626 struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
@@ -635,9 +635,9 @@ extern void nfsd4_destroy_callback_queue(void);
635extern void nfsd4_shutdown_callback(struct nfs4_client *); 635extern void nfsd4_shutdown_callback(struct nfs4_client *);
636extern void nfsd4_shutdown_copy(struct nfs4_client *clp); 636extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
637extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp); 637extern void nfsd4_prepare_cb_recall(struct nfs4_delegation *dp);
638extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name, 638extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
639 struct nfsd_net *nn); 639 struct nfsd_net *nn);
640extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn); 640extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);
641 641
642struct nfs4_file *find_file(struct knfsd_fh *fh); 642struct nfs4_file *find_file(struct knfsd_fh *fh);
643void put_nfs4_file(struct nfs4_file *fi); 643void put_nfs4_file(struct nfs4_file *fi);