aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c1028
1 files changed, 545 insertions, 483 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 75e8b137580c..89e36526d7f2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -48,39 +48,32 @@
48#include <linux/nfs4.h> 48#include <linux/nfs4.h>
49#include <linux/nfsd/state.h> 49#include <linux/nfsd/state.h>
50#include <linux/nfsd/xdr4.h> 50#include <linux/nfsd/xdr4.h>
51#include <linux/namei.h>
51 52
52#define NFSDDBG_FACILITY NFSDDBG_PROC 53#define NFSDDBG_FACILITY NFSDDBG_PROC
53 54
54/* Globals */ 55/* Globals */
55static time_t lease_time = 90; /* default lease time */ 56static time_t lease_time = 90; /* default lease time */
56static time_t old_lease_time = 90; /* past incarnation lease time */ 57static time_t user_lease_time = 90;
57static u32 nfs4_reclaim_init = 0; 58static time_t boot_time;
58time_t boot_time; 59static int in_grace = 1;
59static time_t grace_end = 0;
60static u32 current_clientid = 1; 60static u32 current_clientid = 1;
61static u32 current_ownerid = 1; 61static u32 current_ownerid = 1;
62static u32 current_fileid = 1; 62static u32 current_fileid = 1;
63static u32 current_delegid = 1; 63static u32 current_delegid = 1;
64static u32 nfs4_init; 64static u32 nfs4_init;
65stateid_t zerostateid; /* bits all 0 */ 65static stateid_t zerostateid; /* bits all 0 */
66stateid_t onestateid; /* bits all 1 */ 66static stateid_t onestateid; /* bits all 1 */
67 67
68/* debug counters */ 68#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
69u32 list_add_perfile = 0; 69#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
70u32 list_del_perfile = 0;
71u32 add_perclient = 0;
72u32 del_perclient = 0;
73u32 alloc_file = 0;
74u32 free_file = 0;
75u32 vfsopen = 0;
76u32 vfsclose = 0;
77u32 alloc_delegation= 0;
78u32 free_delegation= 0;
79 70
80/* forward declarations */ 71/* forward declarations */
81struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); 72static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
82static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); 73static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
83static void release_stateid_lockowners(struct nfs4_stateid *open_stp); 74static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
75static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
76static void nfs4_set_recdir(char *recdir);
84 77
85/* Locking: 78/* Locking:
86 * 79 *
@@ -90,6 +83,11 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
90 */ 83 */
91static DECLARE_MUTEX(client_sema); 84static DECLARE_MUTEX(client_sema);
92 85
86static kmem_cache_t *stateowner_slab = NULL;
87static kmem_cache_t *file_slab = NULL;
88static kmem_cache_t *stateid_slab = NULL;
89static kmem_cache_t *deleg_slab = NULL;
90
93void 91void
94nfs4_lock_state(void) 92nfs4_lock_state(void)
95{ 93{
@@ -118,16 +116,36 @@ opaque_hashval(const void *ptr, int nbytes)
118/* forward declarations */ 116/* forward declarations */
119static void release_stateowner(struct nfs4_stateowner *sop); 117static void release_stateowner(struct nfs4_stateowner *sop);
120static void release_stateid(struct nfs4_stateid *stp, int flags); 118static void release_stateid(struct nfs4_stateid *stp, int flags);
121static void release_file(struct nfs4_file *fp);
122 119
123/* 120/*
124 * Delegation state 121 * Delegation state
125 */ 122 */
126 123
127/* recall_lock protects the del_recall_lru */ 124/* recall_lock protects the del_recall_lru */
128spinlock_t recall_lock; 125static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
129static struct list_head del_recall_lru; 126static struct list_head del_recall_lru;
130 127
128static void
129free_nfs4_file(struct kref *kref)
130{
131 struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
132 list_del(&fp->fi_hash);
133 iput(fp->fi_inode);
134 kmem_cache_free(file_slab, fp);
135}
136
137static inline void
138put_nfs4_file(struct nfs4_file *fi)
139{
140 kref_put(&fi->fi_ref, free_nfs4_file);
141}
142
143static inline void
144get_nfs4_file(struct nfs4_file *fi)
145{
146 kref_get(&fi->fi_ref);
147}
148
131static struct nfs4_delegation * 149static struct nfs4_delegation *
132alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) 150alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
133{ 151{
@@ -136,13 +154,14 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
136 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback; 154 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
137 155
138 dprintk("NFSD alloc_init_deleg\n"); 156 dprintk("NFSD alloc_init_deleg\n");
139 if ((dp = kmalloc(sizeof(struct nfs4_delegation), 157 dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
140 GFP_KERNEL)) == NULL) 158 if (dp == NULL)
141 return dp; 159 return dp;
142 INIT_LIST_HEAD(&dp->dl_del_perfile); 160 INIT_LIST_HEAD(&dp->dl_perfile);
143 INIT_LIST_HEAD(&dp->dl_del_perclnt); 161 INIT_LIST_HEAD(&dp->dl_perclnt);
144 INIT_LIST_HEAD(&dp->dl_recall_lru); 162 INIT_LIST_HEAD(&dp->dl_recall_lru);
145 dp->dl_client = clp; 163 dp->dl_client = clp;
164 get_nfs4_file(fp);
146 dp->dl_file = fp; 165 dp->dl_file = fp;
147 dp->dl_flock = NULL; 166 dp->dl_flock = NULL;
148 get_file(stp->st_vfs_file); 167 get_file(stp->st_vfs_file);
@@ -160,9 +179,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
160 current_fh->fh_handle.fh_size); 179 current_fh->fh_handle.fh_size);
161 dp->dl_time = 0; 180 dp->dl_time = 0;
162 atomic_set(&dp->dl_count, 1); 181 atomic_set(&dp->dl_count, 1);
163 list_add(&dp->dl_del_perfile, &fp->fi_del_perfile); 182 list_add(&dp->dl_perfile, &fp->fi_delegations);
164 list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt); 183 list_add(&dp->dl_perclnt, &clp->cl_delegations);
165 alloc_delegation++;
166 return dp; 184 return dp;
167} 185}
168 186
@@ -171,8 +189,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
171{ 189{
172 if (atomic_dec_and_test(&dp->dl_count)) { 190 if (atomic_dec_and_test(&dp->dl_count)) {
173 dprintk("NFSD: freeing dp %p\n",dp); 191 dprintk("NFSD: freeing dp %p\n",dp);
174 kfree(dp); 192 put_nfs4_file(dp->dl_file);
175 free_delegation++; 193 kmem_cache_free(deleg_slab, dp);
176 } 194 }
177} 195}
178 196
@@ -193,15 +211,14 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
193 if (dp->dl_flock) 211 if (dp->dl_flock)
194 setlease(filp, F_UNLCK, &dp->dl_flock); 212 setlease(filp, F_UNLCK, &dp->dl_flock);
195 nfsd_close(filp); 213 nfsd_close(filp);
196 vfsclose++;
197} 214}
198 215
199/* Called under the state lock. */ 216/* Called under the state lock. */
200static void 217static void
201unhash_delegation(struct nfs4_delegation *dp) 218unhash_delegation(struct nfs4_delegation *dp)
202{ 219{
203 list_del_init(&dp->dl_del_perfile); 220 list_del_init(&dp->dl_perfile);
204 list_del_init(&dp->dl_del_perclnt); 221 list_del_init(&dp->dl_perclnt);
205 spin_lock(&recall_lock); 222 spin_lock(&recall_lock);
206 list_del_init(&dp->dl_recall_lru); 223 list_del_init(&dp->dl_recall_lru);
207 spin_unlock(&recall_lock); 224 spin_unlock(&recall_lock);
@@ -220,8 +237,8 @@ unhash_delegation(struct nfs4_delegation *dp)
220 237
221#define clientid_hashval(id) \ 238#define clientid_hashval(id) \
222 ((id) & CLIENT_HASH_MASK) 239 ((id) & CLIENT_HASH_MASK)
223#define clientstr_hashval(name, namelen) \ 240#define clientstr_hashval(name) \
224 (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK) 241 (opaque_hashval((name), 8) & CLIENT_HASH_MASK)
225/* 242/*
226 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot 243 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
227 * used in reboot/reset lease grace period processing 244 * used in reboot/reset lease grace period processing
@@ -331,11 +348,11 @@ expire_client(struct nfs4_client *clp)
331 348
332 INIT_LIST_HEAD(&reaplist); 349 INIT_LIST_HEAD(&reaplist);
333 spin_lock(&recall_lock); 350 spin_lock(&recall_lock);
334 while (!list_empty(&clp->cl_del_perclnt)) { 351 while (!list_empty(&clp->cl_delegations)) {
335 dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt); 352 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
336 dprintk("NFSD: expire client. dp %p, fp %p\n", dp, 353 dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
337 dp->dl_flock); 354 dp->dl_flock);
338 list_del_init(&dp->dl_del_perclnt); 355 list_del_init(&dp->dl_perclnt);
339 list_move(&dp->dl_recall_lru, &reaplist); 356 list_move(&dp->dl_recall_lru, &reaplist);
340 } 357 }
341 spin_unlock(&recall_lock); 358 spin_unlock(&recall_lock);
@@ -347,26 +364,26 @@ expire_client(struct nfs4_client *clp)
347 list_del(&clp->cl_idhash); 364 list_del(&clp->cl_idhash);
348 list_del(&clp->cl_strhash); 365 list_del(&clp->cl_strhash);
349 list_del(&clp->cl_lru); 366 list_del(&clp->cl_lru);
350 while (!list_empty(&clp->cl_perclient)) { 367 while (!list_empty(&clp->cl_openowners)) {
351 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient); 368 sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
352 release_stateowner(sop); 369 release_stateowner(sop);
353 } 370 }
354 put_nfs4_client(clp); 371 put_nfs4_client(clp);
355} 372}
356 373
357static struct nfs4_client * 374static struct nfs4_client *
358create_client(struct xdr_netobj name) { 375create_client(struct xdr_netobj name, char *recdir) {
359 struct nfs4_client *clp; 376 struct nfs4_client *clp;
360 377
361 if (!(clp = alloc_client(name))) 378 if (!(clp = alloc_client(name)))
362 goto out; 379 goto out;
380 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
363 atomic_set(&clp->cl_count, 1); 381 atomic_set(&clp->cl_count, 1);
364 atomic_set(&clp->cl_callback.cb_set, 0); 382 atomic_set(&clp->cl_callback.cb_set, 0);
365 clp->cl_callback.cb_parsed = 0;
366 INIT_LIST_HEAD(&clp->cl_idhash); 383 INIT_LIST_HEAD(&clp->cl_idhash);
367 INIT_LIST_HEAD(&clp->cl_strhash); 384 INIT_LIST_HEAD(&clp->cl_strhash);
368 INIT_LIST_HEAD(&clp->cl_perclient); 385 INIT_LIST_HEAD(&clp->cl_openowners);
369 INIT_LIST_HEAD(&clp->cl_del_perclnt); 386 INIT_LIST_HEAD(&clp->cl_delegations);
370 INIT_LIST_HEAD(&clp->cl_lru); 387 INIT_LIST_HEAD(&clp->cl_lru);
371out: 388out:
372 return clp; 389 return clp;
@@ -392,11 +409,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
392 get_group_info(target->cr_group_info); 409 get_group_info(target->cr_group_info);
393} 410}
394 411
395static int 412static inline int
396cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) { 413same_name(const char *n1, const char *n2) {
397 if (!n1 || !n2) 414 return 0 == memcmp(n1, n2, HEXDIR_LEN);
398 return 0;
399 return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
400} 415}
401 416
402static int 417static int
@@ -446,7 +461,7 @@ check_name(struct xdr_netobj name) {
446 return 1; 461 return 1;
447} 462}
448 463
449void 464static void
450add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval) 465add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
451{ 466{
452 unsigned int idhashval; 467 unsigned int idhashval;
@@ -458,7 +473,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
458 clp->cl_time = get_seconds(); 473 clp->cl_time = get_seconds();
459} 474}
460 475
461void 476static void
462move_to_confirmed(struct nfs4_client *clp) 477move_to_confirmed(struct nfs4_client *clp)
463{ 478{
464 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id); 479 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
@@ -468,8 +483,7 @@ move_to_confirmed(struct nfs4_client *clp)
468 list_del_init(&clp->cl_strhash); 483 list_del_init(&clp->cl_strhash);
469 list_del_init(&clp->cl_idhash); 484 list_del_init(&clp->cl_idhash);
470 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); 485 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
471 strhashval = clientstr_hashval(clp->cl_name.data, 486 strhashval = clientstr_hashval(clp->cl_recdir);
472 clp->cl_name.len);
473 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); 487 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
474 renew_client(clp); 488 renew_client(clp);
475} 489}
@@ -500,6 +514,30 @@ find_unconfirmed_client(clientid_t *clid)
500 return NULL; 514 return NULL;
501} 515}
502 516
517static struct nfs4_client *
518find_confirmed_client_by_str(const char *dname, unsigned int hashval)
519{
520 struct nfs4_client *clp;
521
522 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
523 if (same_name(clp->cl_recdir, dname))
524 return clp;
525 }
526 return NULL;
527}
528
529static struct nfs4_client *
530find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
531{
532 struct nfs4_client *clp;
533
534 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
535 if (same_name(clp->cl_recdir, dname))
536 return clp;
537 }
538 return NULL;
539}
540
503/* a helper function for parse_callback */ 541/* a helper function for parse_callback */
504static int 542static int
505parse_octet(unsigned int *lenp, char **addrp) 543parse_octet(unsigned int *lenp, char **addrp)
@@ -534,7 +572,7 @@ parse_octet(unsigned int *lenp, char **addrp)
534} 572}
535 573
536/* parse and set the setclientid ipv4 callback address */ 574/* parse and set the setclientid ipv4 callback address */
537int 575static int
538parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp) 576parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
539{ 577{
540 int temp = 0; 578 int temp = 0;
@@ -570,7 +608,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
570 return 1; 608 return 1;
571} 609}
572 610
573void 611static void
574gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se) 612gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
575{ 613{
576 struct nfs4_callback *cb = &clp->cl_callback; 614 struct nfs4_callback *cb = &clp->cl_callback;
@@ -584,14 +622,12 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
584 goto out_err; 622 goto out_err;
585 cb->cb_prog = se->se_callback_prog; 623 cb->cb_prog = se->se_callback_prog;
586 cb->cb_ident = se->se_callback_ident; 624 cb->cb_ident = se->se_callback_ident;
587 cb->cb_parsed = 1;
588 return; 625 return;
589out_err: 626out_err:
590 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " 627 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
591 "will not receive delegations\n", 628 "will not receive delegations\n",
592 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 629 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
593 630
594 cb->cb_parsed = 0;
595 return; 631 return;
596} 632}
597 633
@@ -638,59 +674,43 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
638 }; 674 };
639 nfs4_verifier clverifier = setclid->se_verf; 675 nfs4_verifier clverifier = setclid->se_verf;
640 unsigned int strhashval; 676 unsigned int strhashval;
641 struct nfs4_client * conf, * unconf, * new, * clp; 677 struct nfs4_client *conf, *unconf, *new;
642 int status; 678 int status;
679 char dname[HEXDIR_LEN];
643 680
644 status = nfserr_inval; 681 status = nfserr_inval;
645 if (!check_name(clname)) 682 if (!check_name(clname))
646 goto out; 683 goto out;
647 684
685 status = nfs4_make_rec_clidname(dname, &clname);
686 if (status)
687 goto out;
688
648 /* 689 /*
649 * XXX The Duplicate Request Cache (DRC) has been checked (??) 690 * XXX The Duplicate Request Cache (DRC) has been checked (??)
650 * We get here on a DRC miss. 691 * We get here on a DRC miss.
651 */ 692 */
652 693
653 strhashval = clientstr_hashval(clname.data, clname.len); 694 strhashval = clientstr_hashval(dname);
654 695
655 conf = NULL;
656 nfs4_lock_state(); 696 nfs4_lock_state();
657 list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) { 697 conf = find_confirmed_client_by_str(dname, strhashval);
658 if (!cmp_name(&clp->cl_name, &clname)) 698 if (conf) {
659 continue;
660 /* 699 /*
661 * CASE 0: 700 * CASE 0:
662 * clname match, confirmed, different principal 701 * clname match, confirmed, different principal
663 * or different ip_address 702 * or different ip_address
664 */ 703 */
665 status = nfserr_clid_inuse; 704 status = nfserr_clid_inuse;
666 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) { 705 if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
667 printk("NFSD: setclientid: string in use by client" 706 || conf->cl_addr != ip_addr) {
668 "(clientid %08x/%08x)\n",
669 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
670 goto out;
671 }
672 if (clp->cl_addr != ip_addr) {
673 printk("NFSD: setclientid: string in use by client" 707 printk("NFSD: setclientid: string in use by client"
674 "(clientid %08x/%08x)\n", 708 "(clientid %08x/%08x)\n",
675 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 709 conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
676 goto out; 710 goto out;
677 } 711 }
678
679 /*
680 * cl_name match from a previous SETCLIENTID operation
681 * XXX check for additional matches?
682 */
683 conf = clp;
684 break;
685 }
686 unconf = NULL;
687 list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
688 if (!cmp_name(&clp->cl_name, &clname))
689 continue;
690 /* cl_name match from a previous SETCLIENTID operation */
691 unconf = clp;
692 break;
693 } 712 }
713 unconf = find_unconfirmed_client_by_str(dname, strhashval);
694 status = nfserr_resource; 714 status = nfserr_resource;
695 if (!conf) { 715 if (!conf) {
696 /* 716 /*
@@ -699,7 +719,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
699 */ 719 */
700 if (unconf) 720 if (unconf)
701 expire_client(unconf); 721 expire_client(unconf);
702 if (!(new = create_client(clname))) 722 new = create_client(clname, dname);
723 if (new == NULL)
703 goto out; 724 goto out;
704 copy_verf(new, &clverifier); 725 copy_verf(new, &clverifier);
705 new->cl_addr = ip_addr; 726 new->cl_addr = ip_addr;
@@ -722,12 +743,16 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
722 * nfs4_client, but with the new callback info and a 743 * nfs4_client, but with the new callback info and a
723 * new cl_confirm 744 * new cl_confirm
724 */ 745 */
725 if ((unconf) && 746 if (unconf) {
726 cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) && 747 /* Note this is removing unconfirmed {*x***},
727 cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) { 748 * which is stronger than RFC recommended {vxc**}.
728 expire_client(unconf); 749 * This has the advantage that there is at most
750 * one {*x***} in either list at any time.
751 */
752 expire_client(unconf);
729 } 753 }
730 if (!(new = create_client(clname))) 754 new = create_client(clname, dname);
755 if (new == NULL)
731 goto out; 756 goto out;
732 copy_verf(new,&conf->cl_verifier); 757 copy_verf(new,&conf->cl_verifier);
733 new->cl_addr = ip_addr; 758 new->cl_addr = ip_addr;
@@ -745,7 +770,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
745 * using input clverifier, clname, and callback info 770 * using input clverifier, clname, and callback info
746 * and generate a new cl_clientid and cl_confirm. 771 * and generate a new cl_clientid and cl_confirm.
747 */ 772 */
748 if (!(new = create_client(clname))) 773 new = create_client(clname, dname);
774 if (new == NULL)
749 goto out; 775 goto out;
750 copy_verf(new,&clverifier); 776 copy_verf(new,&clverifier);
751 new->cl_addr = ip_addr; 777 new->cl_addr = ip_addr;
@@ -771,7 +797,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
771 * new cl_verifier and a new cl_confirm 797 * new cl_verifier and a new cl_confirm
772 */ 798 */
773 expire_client(unconf); 799 expire_client(unconf);
774 if (!(new = create_client(clname))) 800 new = create_client(clname, dname);
801 if (new == NULL)
775 goto out; 802 goto out;
776 copy_verf(new,&clverifier); 803 copy_verf(new,&clverifier);
777 new->cl_addr = ip_addr; 804 new->cl_addr = ip_addr;
@@ -807,7 +834,7 @@ int
807nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) 834nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
808{ 835{
809 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; 836 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
810 struct nfs4_client *clp, *conf = NULL, *unconf = NULL; 837 struct nfs4_client *conf, *unconf;
811 nfs4_verifier confirm = setclientid_confirm->sc_confirm; 838 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
812 clientid_t * clid = &setclientid_confirm->sc_clientid; 839 clientid_t * clid = &setclientid_confirm->sc_clientid;
813 int status; 840 int status;
@@ -820,102 +847,90 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
820 */ 847 */
821 848
822 nfs4_lock_state(); 849 nfs4_lock_state();
823 clp = find_confirmed_client(clid); 850
824 if (clp) { 851 conf = find_confirmed_client(clid);
825 status = nfserr_inval; 852 unconf = find_unconfirmed_client(clid);
826 /* 853
827 * Found a record for this clientid. If the IP addresses 854 status = nfserr_clid_inuse;
828 * don't match, return ERR_INVAL just as if the record had 855 if (conf && conf->cl_addr != ip_addr)
829 * not been found. 856 goto out;
830 */ 857 if (unconf && unconf->cl_addr != ip_addr)
831 if (clp->cl_addr != ip_addr) { 858 goto out;
832 printk("NFSD: setclientid: string in use by client" 859
833 "(clientid %08x/%08x)\n",
834 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
835 goto out;
836 }
837 conf = clp;
838 }
839 clp = find_unconfirmed_client(clid);
840 if (clp) {
841 status = nfserr_inval;
842 if (clp->cl_addr != ip_addr) {
843 printk("NFSD: setclientid: string in use by client"
844 "(clientid %08x/%08x)\n",
845 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
846 goto out;
847 }
848 unconf = clp;
849 }
850 /* CASE 1:
851 * unconf record that matches input clientid and input confirm.
852 * conf record that matches input clientid.
853 * conf and unconf records match names, verifiers
854 */
855 if ((conf && unconf) && 860 if ((conf && unconf) &&
856 (cmp_verf(&unconf->cl_confirm, &confirm)) && 861 (cmp_verf(&unconf->cl_confirm, &confirm)) &&
857 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && 862 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
858 (cmp_name(&conf->cl_name,&unconf->cl_name)) && 863 (same_name(conf->cl_recdir,unconf->cl_recdir)) &&
859 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { 864 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
865 /* CASE 1:
866 * unconf record that matches input clientid and input confirm.
867 * conf record that matches input clientid.
868 * conf and unconf records match names, verifiers
869 */
860 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 870 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
861 status = nfserr_clid_inuse; 871 status = nfserr_clid_inuse;
862 else { 872 else {
863 expire_client(conf); 873 /* XXX: We just turn off callbacks until we can handle
864 clp = unconf; 874 * change request correctly. */
865 move_to_confirmed(unconf); 875 atomic_set(&conf->cl_callback.cb_set, 0);
876 gen_confirm(conf);
877 expire_client(unconf);
866 status = nfs_ok; 878 status = nfs_ok;
879
867 } 880 }
868 goto out; 881 } else if ((conf && !unconf) ||
869 }
870 /* CASE 2:
871 * conf record that matches input clientid.
872 * if unconf record that matches input clientid, then unconf->cl_name
873 * or unconf->cl_verifier don't match the conf record.
874 */
875 if ((conf && !unconf) ||
876 ((conf && unconf) && 882 ((conf && unconf) &&
877 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || 883 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
878 !cmp_name(&conf->cl_name, &unconf->cl_name)))) { 884 !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
879 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) { 885 /* CASE 2:
886 * conf record that matches input clientid.
887 * if unconf record matches input clientid, then
888 * unconf->cl_name or unconf->cl_verifier don't match the
889 * conf record.
890 */
891 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
880 status = nfserr_clid_inuse; 892 status = nfserr_clid_inuse;
881 } else { 893 else
882 clp = conf;
883 status = nfs_ok; 894 status = nfs_ok;
884 } 895 } else if (!conf && unconf
885 goto out; 896 && cmp_verf(&unconf->cl_confirm, &confirm)) {
886 } 897 /* CASE 3:
887 /* CASE 3: 898 * conf record not found.
888 * conf record not found. 899 * unconf record found.
889 * unconf record found. 900 * unconf->cl_confirm matches input confirm
890 * unconf->cl_confirm matches input confirm 901 */
891 */
892 if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
893 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { 902 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
894 status = nfserr_clid_inuse; 903 status = nfserr_clid_inuse;
895 } else { 904 } else {
896 status = nfs_ok; 905 unsigned int hash =
897 clp = unconf; 906 clientstr_hashval(unconf->cl_recdir);
907 conf = find_confirmed_client_by_str(unconf->cl_recdir,
908 hash);
909 if (conf) {
910 nfsd4_remove_clid_dir(conf);
911 expire_client(conf);
912 }
898 move_to_confirmed(unconf); 913 move_to_confirmed(unconf);
914 conf = unconf;
915 status = nfs_ok;
899 } 916 }
900 goto out; 917 } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
901 } 918 && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
902 /* CASE 4: 919 &confirm)))) {
903 * conf record not found, or if conf, then conf->cl_confirm does not 920 /* CASE 4:
904 * match input confirm. 921 * conf record not found, or if conf, conf->cl_confirm does not
905 * unconf record not found, or if unconf, then unconf->cl_confirm 922 * match input confirm.
906 * does not match input confirm. 923 * unconf record not found, or if unconf, unconf->cl_confirm
907 */ 924 * does not match input confirm.
908 if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) && 925 */
909 (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
910 status = nfserr_stale_clientid; 926 status = nfserr_stale_clientid;
911 goto out; 927 } else {
928 /* check that we have hit one of the cases...*/
929 status = nfserr_clid_inuse;
912 } 930 }
913 /* check that we have hit one of the cases...*/
914 status = nfserr_inval;
915 goto out;
916out: 931out:
917 if (!status) 932 if (!status)
918 nfsd4_probe_callback(clp); 933 nfsd4_probe_callback(conf);
919 nfs4_unlock_state(); 934 nfs4_unlock_state();
920 return status; 935 return status;
921} 936}
@@ -961,60 +976,65 @@ alloc_init_file(struct inode *ino)
961 struct nfs4_file *fp; 976 struct nfs4_file *fp;
962 unsigned int hashval = file_hashval(ino); 977 unsigned int hashval = file_hashval(ino);
963 978
964 if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) { 979 fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
980 if (fp) {
981 kref_init(&fp->fi_ref);
965 INIT_LIST_HEAD(&fp->fi_hash); 982 INIT_LIST_HEAD(&fp->fi_hash);
966 INIT_LIST_HEAD(&fp->fi_perfile); 983 INIT_LIST_HEAD(&fp->fi_stateids);
967 INIT_LIST_HEAD(&fp->fi_del_perfile); 984 INIT_LIST_HEAD(&fp->fi_delegations);
968 list_add(&fp->fi_hash, &file_hashtbl[hashval]); 985 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
969 fp->fi_inode = igrab(ino); 986 fp->fi_inode = igrab(ino);
970 fp->fi_id = current_fileid++; 987 fp->fi_id = current_fileid++;
971 alloc_file++;
972 return fp; 988 return fp;
973 } 989 }
974 return NULL; 990 return NULL;
975} 991}
976 992
977static void 993static void
978release_all_files(void) 994nfsd4_free_slab(kmem_cache_t **slab)
979{ 995{
980 int i; 996 int status;
981 struct nfs4_file *fp;
982 997
983 for (i=0;i<FILE_HASH_SIZE;i++) { 998 if (*slab == NULL)
984 while (!list_empty(&file_hashtbl[i])) { 999 return;
985 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash); 1000 status = kmem_cache_destroy(*slab);
986 /* this should never be more than once... */ 1001 *slab = NULL;
987 if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) { 1002 WARN_ON(status);
988 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
989 }
990 release_file(fp);
991 }
992 }
993} 1003}
994 1004
995kmem_cache_t *stateowner_slab = NULL; 1005static void
1006nfsd4_free_slabs(void)
1007{
1008 nfsd4_free_slab(&stateowner_slab);
1009 nfsd4_free_slab(&file_slab);
1010 nfsd4_free_slab(&stateid_slab);
1011 nfsd4_free_slab(&deleg_slab);
1012}
996 1013
997static int 1014static int
998nfsd4_init_slabs(void) 1015nfsd4_init_slabs(void)
999{ 1016{
1000 stateowner_slab = kmem_cache_create("nfsd4_stateowners", 1017 stateowner_slab = kmem_cache_create("nfsd4_stateowners",
1001 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL); 1018 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
1002 if (stateowner_slab == NULL) { 1019 if (stateowner_slab == NULL)
1003 dprintk("nfsd4: out of memory while initializing nfsv4\n"); 1020 goto out_nomem;
1004 return -ENOMEM; 1021 file_slab = kmem_cache_create("nfsd4_files",
1005 } 1022 sizeof(struct nfs4_file), 0, 0, NULL, NULL);
1023 if (file_slab == NULL)
1024 goto out_nomem;
1025 stateid_slab = kmem_cache_create("nfsd4_stateids",
1026 sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
1027 if (stateid_slab == NULL)
1028 goto out_nomem;
1029 deleg_slab = kmem_cache_create("nfsd4_delegations",
1030 sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
1031 if (deleg_slab == NULL)
1032 goto out_nomem;
1006 return 0; 1033 return 0;
1007} 1034out_nomem:
1008 1035 nfsd4_free_slabs();
1009static void 1036 dprintk("nfsd4: out of memory while initializing nfsv4\n");
1010nfsd4_free_slabs(void) 1037 return -ENOMEM;
1011{
1012 int status = 0;
1013
1014 if (stateowner_slab)
1015 status = kmem_cache_destroy(stateowner_slab);
1016 stateowner_slab = NULL;
1017 BUG_ON(status);
1018} 1038}
1019 1039
1020void 1040void
@@ -1055,14 +1075,13 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
1055 INIT_LIST_HEAD(&sop->so_idhash); 1075 INIT_LIST_HEAD(&sop->so_idhash);
1056 INIT_LIST_HEAD(&sop->so_strhash); 1076 INIT_LIST_HEAD(&sop->so_strhash);
1057 INIT_LIST_HEAD(&sop->so_perclient); 1077 INIT_LIST_HEAD(&sop->so_perclient);
1058 INIT_LIST_HEAD(&sop->so_perfilestate); 1078 INIT_LIST_HEAD(&sop->so_stateids);
1059 INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */ 1079 INIT_LIST_HEAD(&sop->so_perstateid); /* not used */
1060 INIT_LIST_HEAD(&sop->so_close_lru); 1080 INIT_LIST_HEAD(&sop->so_close_lru);
1061 sop->so_time = 0; 1081 sop->so_time = 0;
1062 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]); 1082 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
1063 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]); 1083 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
1064 list_add(&sop->so_perclient, &clp->cl_perclient); 1084 list_add(&sop->so_perclient, &clp->cl_openowners);
1065 add_perclient++;
1066 sop->so_is_open_owner = 1; 1085 sop->so_is_open_owner = 1;
1067 sop->so_id = current_ownerid++; 1086 sop->so_id = current_ownerid++;
1068 sop->so_client = clp; 1087 sop->so_client = clp;
@@ -1080,10 +1099,10 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
1080{ 1099{
1081 struct nfs4_stateowner *lock_sop; 1100 struct nfs4_stateowner *lock_sop;
1082 1101
1083 while (!list_empty(&open_stp->st_perlockowner)) { 1102 while (!list_empty(&open_stp->st_lockowners)) {
1084 lock_sop = list_entry(open_stp->st_perlockowner.next, 1103 lock_sop = list_entry(open_stp->st_lockowners.next,
1085 struct nfs4_stateowner, so_perlockowner); 1104 struct nfs4_stateowner, so_perstateid);
1086 /* list_del(&open_stp->st_perlockowner); */ 1105 /* list_del(&open_stp->st_lockowners); */
1087 BUG_ON(lock_sop->so_is_open_owner); 1106 BUG_ON(lock_sop->so_is_open_owner);
1088 release_stateowner(lock_sop); 1107 release_stateowner(lock_sop);
1089 } 1108 }
@@ -1096,14 +1115,12 @@ unhash_stateowner(struct nfs4_stateowner *sop)
1096 1115
1097 list_del(&sop->so_idhash); 1116 list_del(&sop->so_idhash);
1098 list_del(&sop->so_strhash); 1117 list_del(&sop->so_strhash);
1099 if (sop->so_is_open_owner) { 1118 if (sop->so_is_open_owner)
1100 list_del(&sop->so_perclient); 1119 list_del(&sop->so_perclient);
1101 del_perclient++; 1120 list_del(&sop->so_perstateid);
1102 } 1121 while (!list_empty(&sop->so_stateids)) {
1103 list_del(&sop->so_perlockowner); 1122 stp = list_entry(sop->so_stateids.next,
1104 while (!list_empty(&sop->so_perfilestate)) { 1123 struct nfs4_stateid, st_perstateowner);
1105 stp = list_entry(sop->so_perfilestate.next,
1106 struct nfs4_stateid, st_perfilestate);
1107 if (sop->so_is_open_owner) 1124 if (sop->so_is_open_owner)
1108 release_stateid(stp, OPEN_STATE); 1125 release_stateid(stp, OPEN_STATE);
1109 else 1126 else
@@ -1125,14 +1142,14 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1125 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 1142 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
1126 1143
1127 INIT_LIST_HEAD(&stp->st_hash); 1144 INIT_LIST_HEAD(&stp->st_hash);
1128 INIT_LIST_HEAD(&stp->st_perfilestate); 1145 INIT_LIST_HEAD(&stp->st_perstateowner);
1129 INIT_LIST_HEAD(&stp->st_perlockowner); 1146 INIT_LIST_HEAD(&stp->st_lockowners);
1130 INIT_LIST_HEAD(&stp->st_perfile); 1147 INIT_LIST_HEAD(&stp->st_perfile);
1131 list_add(&stp->st_hash, &stateid_hashtbl[hashval]); 1148 list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
1132 list_add(&stp->st_perfilestate, &sop->so_perfilestate); 1149 list_add(&stp->st_perstateowner, &sop->so_stateids);
1133 list_add_perfile++; 1150 list_add(&stp->st_perfile, &fp->fi_stateids);
1134 list_add(&stp->st_perfile, &fp->fi_perfile);
1135 stp->st_stateowner = sop; 1151 stp->st_stateowner = sop;
1152 get_nfs4_file(fp);
1136 stp->st_file = fp; 1153 stp->st_file = fp;
1137 stp->st_stateid.si_boot = boot_time; 1154 stp->st_stateid.si_boot = boot_time;
1138 stp->st_stateid.si_stateownerid = sop->so_id; 1155 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1150,30 +1167,20 @@ release_stateid(struct nfs4_stateid *stp, int flags)
1150 struct file *filp = stp->st_vfs_file; 1167 struct file *filp = stp->st_vfs_file;
1151 1168
1152 list_del(&stp->st_hash); 1169 list_del(&stp->st_hash);
1153 list_del_perfile++;
1154 list_del(&stp->st_perfile); 1170 list_del(&stp->st_perfile);
1155 list_del(&stp->st_perfilestate); 1171 list_del(&stp->st_perstateowner);
1156 if (flags & OPEN_STATE) { 1172 if (flags & OPEN_STATE) {
1157 release_stateid_lockowners(stp); 1173 release_stateid_lockowners(stp);
1158 stp->st_vfs_file = NULL; 1174 stp->st_vfs_file = NULL;
1159 nfsd_close(filp); 1175 nfsd_close(filp);
1160 vfsclose++;
1161 } else if (flags & LOCK_STATE) 1176 } else if (flags & LOCK_STATE)
1162 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner); 1177 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1163 kfree(stp); 1178 put_nfs4_file(stp->st_file);
1179 kmem_cache_free(stateid_slab, stp);
1164 stp = NULL; 1180 stp = NULL;
1165} 1181}
1166 1182
1167static void 1183static void
1168release_file(struct nfs4_file *fp)
1169{
1170 free_file++;
1171 list_del(&fp->fi_hash);
1172 iput(fp->fi_inode);
1173 kfree(fp);
1174}
1175
1176void
1177move_to_close_lru(struct nfs4_stateowner *sop) 1184move_to_close_lru(struct nfs4_stateowner *sop)
1178{ 1185{
1179 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop); 1186 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
@@ -1183,11 +1190,10 @@ move_to_close_lru(struct nfs4_stateowner *sop)
1183 sop->so_time = get_seconds(); 1190 sop->so_time = get_seconds();
1184} 1191}
1185 1192
1186void 1193static void
1187release_state_owner(struct nfs4_stateid *stp, int flag) 1194release_state_owner(struct nfs4_stateid *stp, int flag)
1188{ 1195{
1189 struct nfs4_stateowner *sop = stp->st_stateowner; 1196 struct nfs4_stateowner *sop = stp->st_stateowner;
1190 struct nfs4_file *fp = stp->st_file;
1191 1197
1192 dprintk("NFSD: release_state_owner\n"); 1198 dprintk("NFSD: release_state_owner\n");
1193 release_stateid(stp, flag); 1199 release_stateid(stp, flag);
@@ -1196,12 +1202,8 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
1196 * released by the laundromat service after the lease period 1202 * released by the laundromat service after the lease period
1197 * to enable us to handle CLOSE replay 1203 * to enable us to handle CLOSE replay
1198 */ 1204 */
1199 if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) 1205 if (sop->so_confirmed && list_empty(&sop->so_stateids))
1200 move_to_close_lru(sop); 1206 move_to_close_lru(sop);
1201 /* unused nfs4_file's are releseed. XXX slab cache? */
1202 if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
1203 release_file(fp);
1204 }
1205} 1207}
1206 1208
1207static int 1209static int
@@ -1231,8 +1233,10 @@ find_file(struct inode *ino)
1231 struct nfs4_file *fp; 1233 struct nfs4_file *fp;
1232 1234
1233 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) { 1235 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1234 if (fp->fi_inode == ino) 1236 if (fp->fi_inode == ino) {
1237 get_nfs4_file(fp);
1235 return fp; 1238 return fp;
1239 }
1236 } 1240 }
1237 return NULL; 1241 return NULL;
1238} 1242}
@@ -1240,7 +1244,7 @@ find_file(struct inode *ino)
1240#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) 1244#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
1241#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) 1245#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
1242 1246
1243void 1247static void
1244set_access(unsigned int *access, unsigned long bmap) { 1248set_access(unsigned int *access, unsigned long bmap) {
1245 int i; 1249 int i;
1246 1250
@@ -1251,7 +1255,7 @@ set_access(unsigned int *access, unsigned long bmap) {
1251 } 1255 }
1252} 1256}
1253 1257
1254void 1258static void
1255set_deny(unsigned int *deny, unsigned long bmap) { 1259set_deny(unsigned int *deny, unsigned long bmap) {
1256 int i; 1260 int i;
1257 1261
@@ -1277,25 +1281,30 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
1277 * Called to check deny when READ with all zero stateid or 1281 * Called to check deny when READ with all zero stateid or
1278 * WRITE with all zero or all one stateid 1282 * WRITE with all zero or all one stateid
1279 */ 1283 */
1280int 1284static int
1281nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) 1285nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1282{ 1286{
1283 struct inode *ino = current_fh->fh_dentry->d_inode; 1287 struct inode *ino = current_fh->fh_dentry->d_inode;
1284 struct nfs4_file *fp; 1288 struct nfs4_file *fp;
1285 struct nfs4_stateid *stp; 1289 struct nfs4_stateid *stp;
1290 int ret;
1286 1291
1287 dprintk("NFSD: nfs4_share_conflict\n"); 1292 dprintk("NFSD: nfs4_share_conflict\n");
1288 1293
1289 fp = find_file(ino); 1294 fp = find_file(ino);
1290 if (fp) { 1295 if (!fp)
1296 return nfs_ok;
1297 ret = nfserr_share_denied;
1291 /* Search for conflicting share reservations */ 1298 /* Search for conflicting share reservations */
1292 list_for_each_entry(stp, &fp->fi_perfile, st_perfile) { 1299 list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
1293 if (test_bit(deny_type, &stp->st_deny_bmap) || 1300 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1294 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap)) 1301 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1295 return nfserr_share_denied; 1302 goto out;
1296 }
1297 } 1303 }
1298 return nfs_ok; 1304 ret = nfs_ok;
1305out:
1306 put_nfs4_file(fp);
1307 return ret;
1299} 1308}
1300 1309
1301static inline void 1310static inline void
@@ -1427,7 +1436,7 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
1427 return -EAGAIN; 1436 return -EAGAIN;
1428} 1437}
1429 1438
1430struct lock_manager_operations nfsd_lease_mng_ops = { 1439static struct lock_manager_operations nfsd_lease_mng_ops = {
1431 .fl_break = nfsd_break_deleg_cb, 1440 .fl_break = nfsd_break_deleg_cb,
1432 .fl_release_private = nfsd_release_deleg_cb, 1441 .fl_release_private = nfsd_release_deleg_cb,
1433 .fl_copy_lock = nfsd_copy_lock_deleg_cb, 1442 .fl_copy_lock = nfsd_copy_lock_deleg_cb,
@@ -1526,6 +1535,51 @@ out:
1526 return status; 1535 return status;
1527} 1536}
1528 1537
1538static inline int
1539nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1540{
1541 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1542 return nfserr_openmode;
1543 else
1544 return nfs_ok;
1545}
1546
1547static struct nfs4_delegation *
1548find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
1549{
1550 struct nfs4_delegation *dp;
1551
1552 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
1553 if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
1554 return dp;
1555 }
1556 return NULL;
1557}
1558
1559static int
1560nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
1561 struct nfs4_delegation **dp)
1562{
1563 int flags;
1564 int status = nfserr_bad_stateid;
1565
1566 *dp = find_delegation_file(fp, &open->op_delegate_stateid);
1567 if (*dp == NULL)
1568 goto out;
1569 flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
1570 RD_STATE : WR_STATE;
1571 status = nfs4_check_delegmode(*dp, flags);
1572 if (status)
1573 *dp = NULL;
1574out:
1575 if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
1576 return nfs_ok;
1577 if (status)
1578 return status;
1579 open->op_stateowner->so_confirmed = 1;
1580 return nfs_ok;
1581}
1582
1529static int 1583static int
1530nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp) 1584nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
1531{ 1585{
@@ -1533,7 +1587,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
1533 int status = nfserr_share_denied; 1587 int status = nfserr_share_denied;
1534 struct nfs4_stateowner *sop = open->op_stateowner; 1588 struct nfs4_stateowner *sop = open->op_stateowner;
1535 1589
1536 list_for_each_entry(local, &fp->fi_perfile, st_perfile) { 1590 list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
1537 /* ignore lock owners */ 1591 /* ignore lock owners */
1538 if (local->st_stateowner->so_is_open_owner == 0) 1592 if (local->st_stateowner->so_is_open_owner == 0)
1539 continue; 1593 continue;
@@ -1549,25 +1603,37 @@ out:
1549 return status; 1603 return status;
1550} 1604}
1551 1605
1606static inline struct nfs4_stateid *
1607nfs4_alloc_stateid(void)
1608{
1609 return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
1610}
1611
1552static int 1612static int
1553nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, 1613nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
1614 struct nfs4_delegation *dp,
1554 struct svc_fh *cur_fh, int flags) 1615 struct svc_fh *cur_fh, int flags)
1555{ 1616{
1556 struct nfs4_stateid *stp; 1617 struct nfs4_stateid *stp;
1557 int status;
1558 1618
1559 stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL); 1619 stp = nfs4_alloc_stateid();
1560 if (stp == NULL) 1620 if (stp == NULL)
1561 return nfserr_resource; 1621 return nfserr_resource;
1562 1622
1563 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file); 1623 if (dp) {
1564 if (status) { 1624 get_file(dp->dl_vfs_file);
1565 if (status == nfserr_dropit) 1625 stp->st_vfs_file = dp->dl_vfs_file;
1566 status = nfserr_jukebox; 1626 } else {
1567 kfree(stp); 1627 int status;
1568 return status; 1628 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
1629 &stp->st_vfs_file);
1630 if (status) {
1631 if (status == nfserr_dropit)
1632 status = nfserr_jukebox;
1633 kmem_cache_free(stateid_slab, stp);
1634 return status;
1635 }
1569 } 1636 }
1570 vfsopen++;
1571 *stpp = stp; 1637 *stpp = stp;
1572 return 0; 1638 return 0;
1573} 1639}
@@ -1628,6 +1694,7 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
1628 *status = nfserr_reclaim_bad; 1694 *status = nfserr_reclaim_bad;
1629 else { 1695 else {
1630 open->op_stateowner->so_confirmed = 1; 1696 open->op_stateowner->so_confirmed = 1;
1697 open->op_stateowner->so_client->cl_firststate = 1;
1631 open->op_stateowner->so_seqid--; 1698 open->op_stateowner->so_seqid--;
1632 } 1699 }
1633 } 1700 }
@@ -1646,14 +1713,30 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1646 int status, flag = 0; 1713 int status, flag = 0;
1647 1714
1648 flag = NFS4_OPEN_DELEGATE_NONE; 1715 flag = NFS4_OPEN_DELEGATE_NONE;
1649 if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL 1716 open->op_recall = 0;
1650 || !atomic_read(&cb->cb_set) || !sop->so_confirmed) 1717 switch (open->op_claim_type) {
1651 goto out; 1718 case NFS4_OPEN_CLAIM_PREVIOUS:
1652 1719 if (!atomic_read(&cb->cb_set))
1653 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 1720 open->op_recall = 1;
1654 flag = NFS4_OPEN_DELEGATE_WRITE; 1721 flag = open->op_delegate_type;
1655 else 1722 if (flag == NFS4_OPEN_DELEGATE_NONE)
1656 flag = NFS4_OPEN_DELEGATE_READ; 1723 goto out;
1724 break;
1725 case NFS4_OPEN_CLAIM_NULL:
1726 /* Let's not give out any delegations till everyone's
1727 * had the chance to reclaim theirs.... */
1728 if (nfs4_in_grace())
1729 goto out;
1730 if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
1731 goto out;
1732 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1733 flag = NFS4_OPEN_DELEGATE_WRITE;
1734 else
1735 flag = NFS4_OPEN_DELEGATE_READ;
1736 break;
1737 default:
1738 goto out;
1739 }
1657 1740
1658 dp = alloc_init_deleg(sop->so_client, stp, fh, flag); 1741 dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
1659 if (dp == NULL) { 1742 if (dp == NULL) {
@@ -1687,6 +1770,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1687 dp->dl_stateid.si_fileid, 1770 dp->dl_stateid.si_fileid,
1688 dp->dl_stateid.si_generation); 1771 dp->dl_stateid.si_generation);
1689out: 1772out:
1773 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
1774 && flag == NFS4_OPEN_DELEGATE_NONE
1775 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
1776 printk("NFSD: WARNING: refusing delegation reclaim\n");
1690 open->op_delegate_type = flag; 1777 open->op_delegate_type = flag;
1691} 1778}
1692 1779
@@ -1699,6 +1786,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1699 struct nfs4_file *fp = NULL; 1786 struct nfs4_file *fp = NULL;
1700 struct inode *ino = current_fh->fh_dentry->d_inode; 1787 struct inode *ino = current_fh->fh_dentry->d_inode;
1701 struct nfs4_stateid *stp = NULL; 1788 struct nfs4_stateid *stp = NULL;
1789 struct nfs4_delegation *dp = NULL;
1702 int status; 1790 int status;
1703 1791
1704 status = nfserr_inval; 1792 status = nfserr_inval;
@@ -1713,7 +1801,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1713 if (fp) { 1801 if (fp) {
1714 if ((status = nfs4_check_open(fp, open, &stp))) 1802 if ((status = nfs4_check_open(fp, open, &stp)))
1715 goto out; 1803 goto out;
1804 status = nfs4_check_deleg(fp, open, &dp);
1805 if (status)
1806 goto out;
1716 } else { 1807 } else {
1808 status = nfserr_bad_stateid;
1809 if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
1810 goto out;
1717 status = nfserr_resource; 1811 status = nfserr_resource;
1718 fp = alloc_init_file(ino); 1812 fp = alloc_init_file(ino);
1719 if (fp == NULL) 1813 if (fp == NULL)
@@ -1736,7 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1736 flags = MAY_WRITE; 1830 flags = MAY_WRITE;
1737 else 1831 else
1738 flags = MAY_READ; 1832 flags = MAY_READ;
1739 if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags))) 1833 status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
1834 if (status)
1740 goto out; 1835 goto out;
1741 init_stateid(stp, fp, open); 1836 init_stateid(stp, fp, open);
1742 status = nfsd4_truncate(rqstp, current_fh, open); 1837 status = nfsd4_truncate(rqstp, current_fh, open);
@@ -1759,10 +1854,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
1759 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid, 1854 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1760 stp->st_stateid.si_fileid, stp->st_stateid.si_generation); 1855 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1761out: 1856out:
1762 /* take the opportunity to clean up unused state */ 1857 if (fp)
1763 if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) 1858 put_nfs4_file(fp);
1764 release_file(fp);
1765
1766 /* CLAIM_PREVIOUS has different error returns */ 1859 /* CLAIM_PREVIOUS has different error returns */
1767 nfs4_set_claim_prev(open, &status); 1860 nfs4_set_claim_prev(open, &status);
1768 /* 1861 /*
@@ -1775,6 +1868,7 @@ out:
1775 return status; 1868 return status;
1776} 1869}
1777 1870
1871static struct workqueue_struct *laundry_wq;
1778static struct work_struct laundromat_work; 1872static struct work_struct laundromat_work;
1779static void laundromat_main(void *); 1873static void laundromat_main(void *);
1780static DECLARE_WORK(laundromat_work, laundromat_main, NULL); 1874static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1800,7 +1894,7 @@ nfsd4_renew(clientid_t *clid)
1800 } 1894 }
1801 renew_client(clp); 1895 renew_client(clp);
1802 status = nfserr_cb_path_down; 1896 status = nfserr_cb_path_down;
1803 if (!list_empty(&clp->cl_del_perclnt) 1897 if (!list_empty(&clp->cl_delegations)
1804 && !atomic_read(&clp->cl_callback.cb_set)) 1898 && !atomic_read(&clp->cl_callback.cb_set))
1805 goto out; 1899 goto out;
1806 status = nfs_ok; 1900 status = nfs_ok;
@@ -1809,7 +1903,15 @@ out:
1809 return status; 1903 return status;
1810} 1904}
1811 1905
1812time_t 1906static void
1907end_grace(void)
1908{
1909 dprintk("NFSD: end of grace period\n");
1910 nfsd4_recdir_purge_old();
1911 in_grace = 0;
1912}
1913
1914static time_t
1813nfs4_laundromat(void) 1915nfs4_laundromat(void)
1814{ 1916{
1815 struct nfs4_client *clp; 1917 struct nfs4_client *clp;
@@ -1823,6 +1925,8 @@ nfs4_laundromat(void)
1823 nfs4_lock_state(); 1925 nfs4_lock_state();
1824 1926
1825 dprintk("NFSD: laundromat service - starting\n"); 1927 dprintk("NFSD: laundromat service - starting\n");
1928 if (in_grace)
1929 end_grace();
1826 list_for_each_safe(pos, next, &client_lru) { 1930 list_for_each_safe(pos, next, &client_lru) {
1827 clp = list_entry(pos, struct nfs4_client, cl_lru); 1931 clp = list_entry(pos, struct nfs4_client, cl_lru);
1828 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) { 1932 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1833,6 +1937,7 @@ nfs4_laundromat(void)
1833 } 1937 }
1834 dprintk("NFSD: purging unused client (clientid %08x)\n", 1938 dprintk("NFSD: purging unused client (clientid %08x)\n",
1835 clp->cl_clientid.cl_id); 1939 clp->cl_clientid.cl_id);
1940 nfsd4_remove_clid_dir(clp);
1836 expire_client(clp); 1941 expire_client(clp);
1837 } 1942 }
1838 INIT_LIST_HEAD(&reaplist); 1943 INIT_LIST_HEAD(&reaplist);
@@ -1882,13 +1987,13 @@ laundromat_main(void *not_used)
1882 1987
1883 t = nfs4_laundromat(); 1988 t = nfs4_laundromat();
1884 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t); 1989 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1885 schedule_delayed_work(&laundromat_work, t*HZ); 1990 queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
1886} 1991}
1887 1992
1888/* search ownerid_hashtbl[] and close_lru for stateid owner 1993/* search ownerid_hashtbl[] and close_lru for stateid owner
1889 * (stateid->si_stateownerid) 1994 * (stateid->si_stateownerid)
1890 */ 1995 */
1891struct nfs4_stateowner * 1996static struct nfs4_stateowner *
1892find_openstateowner_id(u32 st_id, int flags) { 1997find_openstateowner_id(u32 st_id, int flags) {
1893 struct nfs4_stateowner *local = NULL; 1998 struct nfs4_stateowner *local = NULL;
1894 1999
@@ -1949,15 +2054,6 @@ out:
1949} 2054}
1950 2055
1951static inline int 2056static inline int
1952nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1953{
1954 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1955 return nfserr_openmode;
1956 else
1957 return nfs_ok;
1958}
1959
1960static inline int
1961check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) 2057check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
1962{ 2058{
1963 /* Trying to call delegreturn with a special stateid? Yuch: */ 2059 /* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2071,7 +2167,7 @@ out:
2071/* 2167/*
2072 * Checks for sequence id mutating operations. 2168 * Checks for sequence id mutating operations.
2073 */ 2169 */
2074int 2170static int
2075nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) 2171nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
2076{ 2172{
2077 int status; 2173 int status;
@@ -2230,6 +2326,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
2230 stp->st_stateid.si_stateownerid, 2326 stp->st_stateid.si_stateownerid,
2231 stp->st_stateid.si_fileid, 2327 stp->st_stateid.si_fileid,
2232 stp->st_stateid.si_generation); 2328 stp->st_stateid.si_generation);
2329
2330 nfsd4_create_clid_dir(sop->so_client);
2233out: 2331out:
2234 if (oc->oc_stateowner) 2332 if (oc->oc_stateowner)
2235 nfs4_get_stateowner(oc->oc_stateowner); 2333 nfs4_get_stateowner(oc->oc_stateowner);
@@ -2387,7 +2485,7 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
2387static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 2485static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
2388static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE]; 2486static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
2389 2487
2390struct nfs4_stateid * 2488static struct nfs4_stateid *
2391find_stateid(stateid_t *stid, int flags) 2489find_stateid(stateid_t *stid, int flags)
2392{ 2490{
2393 struct nfs4_stateid *local = NULL; 2491 struct nfs4_stateid *local = NULL;
@@ -2419,25 +2517,19 @@ find_stateid(stateid_t *stid, int flags)
2419static struct nfs4_delegation * 2517static struct nfs4_delegation *
2420find_delegation_stateid(struct inode *ino, stateid_t *stid) 2518find_delegation_stateid(struct inode *ino, stateid_t *stid)
2421{ 2519{
2422 struct nfs4_delegation *dp = NULL; 2520 struct nfs4_file *fp;
2423 struct nfs4_file *fp = NULL; 2521 struct nfs4_delegation *dl;
2424 u32 st_id;
2425 2522
2426 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n", 2523 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
2427 stid->si_boot, stid->si_stateownerid, 2524 stid->si_boot, stid->si_stateownerid,
2428 stid->si_fileid, stid->si_generation); 2525 stid->si_fileid, stid->si_generation);
2429 2526
2430 st_id = stid->si_stateownerid;
2431 fp = find_file(ino); 2527 fp = find_file(ino);
2432 if (fp) { 2528 if (!fp)
2433 list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) { 2529 return NULL;
2434 if(dp->dl_stateid.si_stateownerid == st_id) { 2530 dl = find_delegation_file(fp, stid);
2435 dprintk("NFSD: find_delegation dp %p\n",dp); 2531 put_nfs4_file(fp);
2436 return dp; 2532 return dl;
2437 }
2438 }
2439 }
2440 return NULL;
2441} 2533}
2442 2534
2443/* 2535/*
@@ -2457,7 +2549,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
2457 lock->fl_end = OFFSET_MAX; 2549 lock->fl_end = OFFSET_MAX;
2458} 2550}
2459 2551
2460int 2552static int
2461nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval) 2553nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
2462{ 2554{
2463 struct nfs4_stateowner *local = NULL; 2555 struct nfs4_stateowner *local = NULL;
@@ -2498,22 +2590,6 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
2498} 2590}
2499 2591
2500static struct nfs4_stateowner * 2592static struct nfs4_stateowner *
2501find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
2502{
2503 struct nfs4_stateowner *local = NULL;
2504 int i;
2505
2506 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2507 list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
2508 if (!cmp_owner_str(local, owner, clid))
2509 continue;
2510 return local;
2511 }
2512 }
2513 return NULL;
2514}
2515
2516static struct nfs4_stateowner *
2517find_lockstateowner_str(struct inode *inode, clientid_t *clid, 2593find_lockstateowner_str(struct inode *inode, clientid_t *clid,
2518 struct xdr_netobj *owner) 2594 struct xdr_netobj *owner)
2519{ 2595{
@@ -2548,13 +2624,13 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2548 INIT_LIST_HEAD(&sop->so_idhash); 2624 INIT_LIST_HEAD(&sop->so_idhash);
2549 INIT_LIST_HEAD(&sop->so_strhash); 2625 INIT_LIST_HEAD(&sop->so_strhash);
2550 INIT_LIST_HEAD(&sop->so_perclient); 2626 INIT_LIST_HEAD(&sop->so_perclient);
2551 INIT_LIST_HEAD(&sop->so_perfilestate); 2627 INIT_LIST_HEAD(&sop->so_stateids);
2552 INIT_LIST_HEAD(&sop->so_perlockowner); 2628 INIT_LIST_HEAD(&sop->so_perstateid);
2553 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */ 2629 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
2554 sop->so_time = 0; 2630 sop->so_time = 0;
2555 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]); 2631 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
2556 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]); 2632 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
2557 list_add(&sop->so_perlockowner, &open_stp->st_perlockowner); 2633 list_add(&sop->so_perstateid, &open_stp->st_lockowners);
2558 sop->so_is_open_owner = 0; 2634 sop->so_is_open_owner = 0;
2559 sop->so_id = current_ownerid++; 2635 sop->so_id = current_ownerid++;
2560 sop->so_client = clp; 2636 sop->so_client = clp;
@@ -2567,24 +2643,24 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
2567 return sop; 2643 return sop;
2568} 2644}
2569 2645
2570struct nfs4_stateid * 2646static struct nfs4_stateid *
2571alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp) 2647alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
2572{ 2648{
2573 struct nfs4_stateid *stp; 2649 struct nfs4_stateid *stp;
2574 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id); 2650 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
2575 2651
2576 if ((stp = kmalloc(sizeof(struct nfs4_stateid), 2652 stp = nfs4_alloc_stateid();
2577 GFP_KERNEL)) == NULL) 2653 if (stp == NULL)
2578 goto out; 2654 goto out;
2579 INIT_LIST_HEAD(&stp->st_hash); 2655 INIT_LIST_HEAD(&stp->st_hash);
2580 INIT_LIST_HEAD(&stp->st_perfile); 2656 INIT_LIST_HEAD(&stp->st_perfile);
2581 INIT_LIST_HEAD(&stp->st_perfilestate); 2657 INIT_LIST_HEAD(&stp->st_perstateowner);
2582 INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */ 2658 INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
2583 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]); 2659 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
2584 list_add(&stp->st_perfile, &fp->fi_perfile); 2660 list_add(&stp->st_perfile, &fp->fi_stateids);
2585 list_add_perfile++; 2661 list_add(&stp->st_perstateowner, &sop->so_stateids);
2586 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2587 stp->st_stateowner = sop; 2662 stp->st_stateowner = sop;
2663 get_nfs4_file(fp);
2588 stp->st_file = fp; 2664 stp->st_file = fp;
2589 stp->st_stateid.si_boot = boot_time; 2665 stp->st_stateid.si_boot = boot_time;
2590 stp->st_stateid.si_stateownerid = sop->so_id; 2666 stp->st_stateid.si_stateownerid = sop->so_id;
@@ -2598,7 +2674,7 @@ out:
2598 return stp; 2674 return stp;
2599} 2675}
2600 2676
2601int 2677static int
2602check_lock_length(u64 offset, u64 length) 2678check_lock_length(u64 offset, u64 length)
2603{ 2679{
2604 return ((length == 0) || ((length != ~(u64)0) && 2680 return ((length == 0) || ((length != ~(u64)0) &&
@@ -2611,7 +2687,7 @@ check_lock_length(u64 offset, u64 length)
2611int 2687int
2612nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock) 2688nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
2613{ 2689{
2614 struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL; 2690 struct nfs4_stateowner *open_sop = NULL;
2615 struct nfs4_stateid *lock_stp; 2691 struct nfs4_stateid *lock_stp;
2616 struct file *filp; 2692 struct file *filp;
2617 struct file_lock file_lock; 2693 struct file_lock file_lock;
@@ -2670,16 +2746,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2670 strhashval = lock_ownerstr_hashval(fp->fi_inode, 2746 strhashval = lock_ownerstr_hashval(fp->fi_inode,
2671 open_sop->so_client->cl_clientid.cl_id, 2747 open_sop->so_client->cl_clientid.cl_id,
2672 &lock->v.new.owner); 2748 &lock->v.new.owner);
2673 /* 2749 /* XXX: Do we need to check for duplicate stateowners on
2674 * If we already have this lock owner, the client is in 2750 * the same file, or should they just be allowed (and
2675 * error (or our bookeeping is wrong!) 2751 * create new stateids)? */
2676 * for asking for a 'new lock'.
2677 */
2678 status = nfserr_bad_stateid;
2679 lock_sop = find_lockstateowner(&lock->v.new.owner,
2680 &lock->v.new.clientid);
2681 if (lock_sop)
2682 goto out;
2683 status = nfserr_resource; 2752 status = nfserr_resource;
2684 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock))) 2753 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
2685 goto out; 2754 goto out;
@@ -2970,8 +3039,11 @@ int
2970nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) 3039nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
2971{ 3040{
2972 clientid_t *clid = &rlockowner->rl_clientid; 3041 clientid_t *clid = &rlockowner->rl_clientid;
2973 struct nfs4_stateowner *local = NULL; 3042 struct nfs4_stateowner *sop;
3043 struct nfs4_stateid *stp;
2974 struct xdr_netobj *owner = &rlockowner->rl_owner; 3044 struct xdr_netobj *owner = &rlockowner->rl_owner;
3045 struct list_head matches;
3046 int i;
2975 int status; 3047 int status;
2976 3048
2977 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", 3049 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -2987,22 +3059,32 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
2987 3059
2988 nfs4_lock_state(); 3060 nfs4_lock_state();
2989 3061
2990 status = nfs_ok; 3062 status = nfserr_locks_held;
2991 local = find_lockstateowner(owner, clid); 3063 /* XXX: we're doing a linear search through all the lockowners.
2992 if (local) { 3064 * Yipes! For now we'll just hope clients aren't really using
2993 struct nfs4_stateid *stp; 3065 * release_lockowner much, but eventually we have to fix these
2994 3066 * data structures. */
2995 /* check for any locks held by any stateid 3067 INIT_LIST_HEAD(&matches);
2996 * associated with the (lock) stateowner */ 3068 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2997 status = nfserr_locks_held; 3069 list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
2998 list_for_each_entry(stp, &local->so_perfilestate, 3070 if (!cmp_owner_str(sop, owner, clid))
2999 st_perfilestate) { 3071 continue;
3000 if (check_for_locks(stp->st_vfs_file, local)) 3072 list_for_each_entry(stp, &sop->so_stateids,
3001 goto out; 3073 st_perstateowner) {
3074 if (check_for_locks(stp->st_vfs_file, sop))
3075 goto out;
3076 /* Note: so_perclient unused for lockowners,
3077 * so it's OK to fool with here. */
3078 list_add(&sop->so_perclient, &matches);
3079 }
3002 } 3080 }
3003 /* no locks held by (lock) stateowner */ 3081 }
3004 status = nfs_ok; 3082 /* Clients probably won't expect us to return with some (but not all)
3005 release_stateowner(local); 3083 * of the lockowner state released; so don't release any until all
3084 * have been checked. */
3085 status = nfs_ok;
3086 list_for_each_entry(sop, &matches, so_perclient) {
3087 release_stateowner(sop);
3006 } 3088 }
3007out: 3089out:
3008 nfs4_unlock_state(); 3090 nfs4_unlock_state();
@@ -3010,39 +3092,38 @@ out:
3010} 3092}
3011 3093
3012static inline struct nfs4_client_reclaim * 3094static inline struct nfs4_client_reclaim *
3013alloc_reclaim(int namelen) 3095alloc_reclaim(void)
3014{ 3096{
3015 struct nfs4_client_reclaim *crp = NULL; 3097 return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
3098}
3016 3099
3017 crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL); 3100int
3018 if (!crp) 3101nfs4_has_reclaimed_state(const char *name)
3019 return NULL; 3102{
3020 crp->cr_name.data = kmalloc(namelen, GFP_KERNEL); 3103 unsigned int strhashval = clientstr_hashval(name);
3021 if (!crp->cr_name.data) { 3104 struct nfs4_client *clp;
3022 kfree(crp); 3105
3023 return NULL; 3106 clp = find_confirmed_client_by_str(name, strhashval);
3024 } 3107 return clp ? 1 : 0;
3025 return crp;
3026} 3108}
3027 3109
3028/* 3110/*
3029 * failure => all reset bets are off, nfserr_no_grace... 3111 * failure => all reset bets are off, nfserr_no_grace...
3030 */ 3112 */
3031static int 3113int
3032nfs4_client_to_reclaim(char *name, int namlen) 3114nfs4_client_to_reclaim(const char *name)
3033{ 3115{
3034 unsigned int strhashval; 3116 unsigned int strhashval;
3035 struct nfs4_client_reclaim *crp = NULL; 3117 struct nfs4_client_reclaim *crp = NULL;
3036 3118
3037 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name); 3119 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
3038 crp = alloc_reclaim(namlen); 3120 crp = alloc_reclaim();
3039 if (!crp) 3121 if (!crp)
3040 return 0; 3122 return 0;
3041 strhashval = clientstr_hashval(name, namlen); 3123 strhashval = clientstr_hashval(name);
3042 INIT_LIST_HEAD(&crp->cr_strhash); 3124 INIT_LIST_HEAD(&crp->cr_strhash);
3043 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]); 3125 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
3044 memcpy(crp->cr_name.data, name, namlen); 3126 memcpy(crp->cr_recdir, name, HEXDIR_LEN);
3045 crp->cr_name.len = namlen;
3046 reclaim_str_hashtbl_size++; 3127 reclaim_str_hashtbl_size++;
3047 return 1; 3128 return 1;
3048} 3129}
@@ -3053,13 +3134,11 @@ nfs4_release_reclaim(void)
3053 struct nfs4_client_reclaim *crp = NULL; 3134 struct nfs4_client_reclaim *crp = NULL;
3054 int i; 3135 int i;
3055 3136
3056 BUG_ON(!nfs4_reclaim_init);
3057 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3137 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3058 while (!list_empty(&reclaim_str_hashtbl[i])) { 3138 while (!list_empty(&reclaim_str_hashtbl[i])) {
3059 crp = list_entry(reclaim_str_hashtbl[i].next, 3139 crp = list_entry(reclaim_str_hashtbl[i].next,
3060 struct nfs4_client_reclaim, cr_strhash); 3140 struct nfs4_client_reclaim, cr_strhash);
3061 list_del(&crp->cr_strhash); 3141 list_del(&crp->cr_strhash);
3062 kfree(crp->cr_name.data);
3063 kfree(crp); 3142 kfree(crp);
3064 reclaim_str_hashtbl_size--; 3143 reclaim_str_hashtbl_size--;
3065 } 3144 }
@@ -3069,7 +3148,7 @@ nfs4_release_reclaim(void)
3069 3148
3070/* 3149/*
3071 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ 3150 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
3072struct nfs4_client_reclaim * 3151static struct nfs4_client_reclaim *
3073nfs4_find_reclaim_client(clientid_t *clid) 3152nfs4_find_reclaim_client(clientid_t *clid)
3074{ 3153{
3075 unsigned int strhashval; 3154 unsigned int strhashval;
@@ -3082,13 +3161,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
3082 if (clp == NULL) 3161 if (clp == NULL)
3083 return NULL; 3162 return NULL;
3084 3163
3085 dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n", 3164 dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
3086 clp->cl_name.len, clp->cl_name.data); 3165 clp->cl_name.len, clp->cl_name.data,
3166 clp->cl_recdir);
3087 3167
3088 /* find clp->cl_name in reclaim_str_hashtbl */ 3168 /* find clp->cl_name in reclaim_str_hashtbl */
3089 strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len); 3169 strhashval = clientstr_hashval(clp->cl_recdir);
3090 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) { 3170 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
3091 if (cmp_name(&crp->cr_name, &clp->cl_name)) { 3171 if (same_name(crp->cr_recdir, clp->cl_recdir)) {
3092 return crp; 3172 return crp;
3093 } 3173 }
3094 } 3174 }
@@ -3101,30 +3181,16 @@ nfs4_find_reclaim_client(clientid_t *clid)
3101int 3181int
3102nfs4_check_open_reclaim(clientid_t *clid) 3182nfs4_check_open_reclaim(clientid_t *clid)
3103{ 3183{
3104 struct nfs4_client_reclaim *crp; 3184 return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
3105
3106 if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
3107 return nfserr_reclaim_bad;
3108 return nfs_ok;
3109} 3185}
3110 3186
3187/* initialization to perform at module load time: */
3111 3188
3112/* 3189void
3113 * Start and stop routines 3190nfs4_state_init(void)
3114 */
3115
3116static void
3117__nfs4_state_init(void)
3118{ 3191{
3119 int i; 3192 int i;
3120 time_t grace_time;
3121 3193
3122 if (!nfs4_reclaim_init) {
3123 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3124 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3125 reclaim_str_hashtbl_size = 0;
3126 nfs4_reclaim_init = 1;
3127 }
3128 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 3194 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3129 INIT_LIST_HEAD(&conf_id_hashtbl[i]); 3195 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
3130 INIT_LIST_HEAD(&conf_str_hashtbl[i]); 3196 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
@@ -3146,26 +3212,46 @@ __nfs4_state_init(void)
3146 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]); 3212 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
3147 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]); 3213 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
3148 } 3214 }
3149 memset(&zerostateid, 0, sizeof(stateid_t));
3150 memset(&onestateid, ~0, sizeof(stateid_t)); 3215 memset(&onestateid, ~0, sizeof(stateid_t));
3151
3152 INIT_LIST_HEAD(&close_lru); 3216 INIT_LIST_HEAD(&close_lru);
3153 INIT_LIST_HEAD(&client_lru); 3217 INIT_LIST_HEAD(&client_lru);
3154 INIT_LIST_HEAD(&del_recall_lru); 3218 INIT_LIST_HEAD(&del_recall_lru);
3155 spin_lock_init(&recall_lock); 3219 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3220 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3221 reclaim_str_hashtbl_size = 0;
3222}
3223
3224static void
3225nfsd4_load_reboot_recovery_data(void)
3226{
3227 int status;
3228
3229 nfs4_lock_state();
3230 nfsd4_init_recdir(user_recovery_dirname);
3231 status = nfsd4_recdir_load();
3232 nfs4_unlock_state();
3233 if (status)
3234 printk("NFSD: Failure reading reboot recovery data\n");
3235}
3236
3237/* initialization to perform when the nfsd service is started: */
3238
3239static void
3240__nfs4_state_start(void)
3241{
3242 time_t grace_time;
3243
3156 boot_time = get_seconds(); 3244 boot_time = get_seconds();
3157 grace_time = max(old_lease_time, lease_time); 3245 grace_time = max(user_lease_time, lease_time);
3158 if (reclaim_str_hashtbl_size == 0) 3246 lease_time = user_lease_time;
3159 grace_time = 0; 3247 in_grace = 1;
3160 if (grace_time) 3248 printk("NFSD: starting %ld-second grace period\n", grace_time);
3161 printk("NFSD: starting %ld-second grace period\n", grace_time); 3249 laundry_wq = create_singlethread_workqueue("nfsd4");
3162 grace_end = boot_time + grace_time; 3250 queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
3163 INIT_WORK(&laundromat_work,laundromat_main, NULL);
3164 schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
3165} 3251}
3166 3252
3167int 3253int
3168nfs4_state_init(void) 3254nfs4_state_start(void)
3169{ 3255{
3170 int status; 3256 int status;
3171 3257
@@ -3174,7 +3260,8 @@ nfs4_state_init(void)
3174 status = nfsd4_init_slabs(); 3260 status = nfsd4_init_slabs();
3175 if (status) 3261 if (status)
3176 return status; 3262 return status;
3177 __nfs4_state_init(); 3263 nfsd4_load_reboot_recovery_data();
3264 __nfs4_state_start();
3178 nfs4_init = 1; 3265 nfs4_init = 1;
3179 return 0; 3266 return 0;
3180} 3267}
@@ -3182,14 +3269,7 @@ nfs4_state_init(void)
3182int 3269int
3183nfs4_in_grace(void) 3270nfs4_in_grace(void)
3184{ 3271{
3185 return get_seconds() < grace_end; 3272 return in_grace;
3186}
3187
3188void
3189set_no_grace(void)
3190{
3191 printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
3192 grace_end = get_seconds();
3193} 3273}
3194 3274
3195time_t 3275time_t
@@ -3236,21 +3316,11 @@ __nfs4_state_shutdown(void)
3236 unhash_delegation(dp); 3316 unhash_delegation(dp);
3237 } 3317 }
3238 3318
3239 release_all_files();
3240 cancel_delayed_work(&laundromat_work); 3319 cancel_delayed_work(&laundromat_work);
3241 flush_scheduled_work(); 3320 flush_workqueue(laundry_wq);
3321 destroy_workqueue(laundry_wq);
3322 nfsd4_shutdown_recdir();
3242 nfs4_init = 0; 3323 nfs4_init = 0;
3243 dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
3244 list_add_perfile, list_del_perfile);
3245 dprintk("NFSD: add_perclient %d del_perclient %d\n",
3246 add_perclient, del_perclient);
3247 dprintk("NFSD: alloc_file %d free_file %d\n",
3248 alloc_file, free_file);
3249 dprintk("NFSD: vfsopen %d vfsclose %d\n",
3250 vfsopen, vfsclose);
3251 dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
3252 alloc_delegation, free_delegation);
3253
3254} 3324}
3255 3325
3256void 3326void
@@ -3263,56 +3333,48 @@ nfs4_state_shutdown(void)
3263 nfs4_unlock_state(); 3333 nfs4_unlock_state();
3264} 3334}
3265 3335
3336static void
3337nfs4_set_recdir(char *recdir)
3338{
3339 nfs4_lock_state();
3340 strcpy(user_recovery_dirname, recdir);
3341 nfs4_unlock_state();
3342}
3343
3344/*
3345 * Change the NFSv4 recovery directory to recdir.
3346 */
3347int
3348nfs4_reset_recoverydir(char *recdir)
3349{
3350 int status;
3351 struct nameidata nd;
3352
3353 status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
3354 if (status)
3355 return status;
3356 status = -ENOTDIR;
3357 if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
3358 nfs4_set_recdir(recdir);
3359 status = 0;
3360 }
3361 path_release(&nd);
3362 return status;
3363}
3364
3266/* 3365/*
3267 * Called when leasetime is changed. 3366 * Called when leasetime is changed.
3268 * 3367 *
3269 * if nfsd is not started, simply set the global lease. 3368 * The only way the protocol gives us to handle on-the-fly lease changes is to
3270 * 3369 * simulate a reboot. Instead of doing that, we just wait till the next time
3271 * if nfsd(s) are running, lease change requires nfsv4 state to be reset. 3370 * we start to register any changes in lease time. If the administrator
3272 * e.g: boot_time is reset, existing nfs4_client structs are 3371 * really wants to change the lease time *now*, they can go ahead and bring
3273 * used to fill reclaim_str_hashtbl, then all state (except for the 3372 * nfsd down and then back up again after changing the lease time.
3274 * reclaim_str_hashtbl) is re-initialized.
3275 *
3276 * if the old lease time is greater than the new lease time, the grace
3277 * period needs to be set to the old lease time to allow clients to reclaim
3278 * their state. XXX - we may want to set the grace period == lease time
3279 * after an initial grace period == old lease time
3280 *
3281 * if an error occurs in this process, the new lease is set, but the server
3282 * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
3283 * which means OPEN/LOCK/READ/WRITE will fail during grace period.
3284 *
3285 * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
3286 * OPEN and LOCK reclaims.
3287 */ 3373 */
3288void 3374void
3289nfs4_reset_lease(time_t leasetime) 3375nfs4_reset_lease(time_t leasetime)
3290{ 3376{
3291 struct nfs4_client *clp; 3377 lock_kernel();
3292 int i; 3378 user_lease_time = leasetime;
3293 3379 unlock_kernel();
3294 printk("NFSD: New leasetime %ld\n",leasetime);
3295 if (!nfs4_init)
3296 return;
3297 nfs4_lock_state();
3298 old_lease_time = lease_time;
3299 lease_time = leasetime;
3300
3301 nfs4_release_reclaim();
3302
3303 /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
3304 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3305 list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
3306 if (!nfs4_client_to_reclaim(clp->cl_name.data,
3307 clp->cl_name.len)) {
3308 nfs4_release_reclaim();
3309 goto init_state;
3310 }
3311 }
3312 }
3313init_state:
3314 __nfs4_state_shutdown();
3315 __nfs4_state_init();
3316 nfs4_unlock_state();
3317} 3380}
3318