MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / fs / nfsd / nfs4state.c
blob1ca8ce8f6680bb5b0741657473190d680ee2c574
1 /*
2 * linux/fs/nfsd/nfs4state.c
4 * Copyright (c) 2001 The Regents of the University of Michigan.
5 * All rights reserved.
7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <kandros@umich.edu>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include <linux/param.h>
38 #include <linux/major.h>
39 #include <linux/slab.h>
41 #include <linux/sunrpc/svc.h>
42 #include <linux/nfsd/nfsd.h>
43 #include <linux/nfsd/cache.h>
44 #include <linux/mount.h>
45 #include <linux/workqueue.h>
46 #include <linux/smp_lock.h>
47 #include <linux/nfs4.h>
48 #include <linux/nfsd/state.h>
49 #include <linux/nfsd/xdr4.h>
51 #define NFSDDBG_FACILITY NFSDDBG_PROC
53 /* Globals */
54 static time_t lease_time = 90; /* default lease time */
55 static time_t old_lease_time = 90; /* past incarnation lease time */
56 static u32 nfs4_reclaim_init = 0;
57 time_t boot_time;
58 static time_t grace_end = 0;
59 static u32 current_clientid = 1;
60 static u32 current_ownerid;
61 static u32 current_fileid;
62 static u32 nfs4_init;
63 stateid_t zerostateid; /* bits all 0 */
64 stateid_t onestateid; /* bits all 1 */
66 /* debug counters */
67 u32 list_add_perfile = 0;
68 u32 list_del_perfile = 0;
69 u32 add_perclient = 0;
70 u32 del_perclient = 0;
71 u32 alloc_file = 0;
72 u32 free_file = 0;
73 u32 alloc_sowner = 0;
74 u32 free_sowner = 0;
75 u32 vfsopen = 0;
76 u32 vfsclose = 0;
77 u32 alloc_lsowner= 0;
79 /* forward declarations */
80 struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
82 /* Locking:
84 * client_sema:
85 * protects clientid_hashtbl[], clientstr_hashtbl[],
86 * unconfstr_hashtbl[], uncofid_hashtbl[].
88 static DECLARE_MUTEX(client_sema);
90 void
91 nfs4_lock_state(void)
93 down(&client_sema);
97 * nfs4_unlock_state(); called in encode
99 void
100 nfs4_unlock_state(void)
102 up(&client_sema);
105 static inline u32
106 opaque_hashval(const void *ptr, int nbytes)
108 unsigned char *cptr = (unsigned char *) ptr;
110 u32 x = 0;
111 while (nbytes--) {
112 x *= 37;
113 x += *cptr++;
115 return x;
118 /* forward declarations */
119 static void release_stateowner(struct nfs4_stateowner *sop);
120 static void release_stateid(struct nfs4_stateid *stp, int flags);
121 static void release_file(struct nfs4_file *fp);
125 * SETCLIENTID state
128 /* Hash tables for nfs4_clientid state */
129 #define CLIENT_HASH_BITS 4
130 #define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS)
131 #define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1)
133 #define clientid_hashval(id) \
134 ((id) & CLIENT_HASH_MASK)
135 #define clientstr_hashval(name, namelen) \
136 (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
138 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
139 * used in reboot/reset lease grace period processing
141 * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
142 * setclientid_confirmed info.
144 * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed
145 * setclientid info.
147 * client_lru holds client queue ordered by nfs4_client.cl_time
148 * for lease renewal.
150 * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
151 * for last close replay.
153 static struct list_head reclaim_str_hashtbl[CLIENT_HASH_SIZE];
154 static int reclaim_str_hashtbl_size;
155 static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE];
156 static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE];
157 static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE];
158 static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
159 static struct list_head client_lru;
160 static struct list_head close_lru;
162 static inline void
163 renew_client(struct nfs4_client *clp)
166 * Move client to the end to the LRU list.
168 dprintk("renewing client (clientid %08x/%08x)\n",
169 clp->cl_clientid.cl_boot,
170 clp->cl_clientid.cl_id);
171 list_move_tail(&clp->cl_lru, &client_lru);
172 clp->cl_time = get_seconds();
175 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
176 static int
177 STALE_CLIENTID(clientid_t *clid)
179 if (clid->cl_boot == boot_time)
180 return 0;
181 dprintk("NFSD stale clientid (%08x/%08x)\n",
182 clid->cl_boot, clid->cl_id);
183 return 1;
187 * XXX Should we use a slab cache ?
188 * This type of memory management is somewhat inefficient, but we use it
189 * anyway since SETCLIENTID is not a common operation.
191 static inline struct nfs4_client *
192 alloc_client(struct xdr_netobj name)
194 struct nfs4_client *clp;
196 if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
197 memset(clp, 0, sizeof(*clp));
198 if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
199 memcpy(clp->cl_name.data, name.data, name.len);
200 clp->cl_name.len = name.len;
202 else {
203 kfree(clp);
204 clp = NULL;
207 return clp;
210 static inline void
211 free_client(struct nfs4_client *clp)
213 if (clp->cl_cred.cr_group_info)
214 put_group_info(clp->cl_cred.cr_group_info);
215 kfree(clp->cl_name.data);
216 kfree(clp);
219 static void
220 expire_client(struct nfs4_client *clp)
222 struct nfs4_stateowner *sop;
224 dprintk("NFSD: expire_client\n");
225 list_del(&clp->cl_idhash);
226 list_del(&clp->cl_strhash);
227 list_del(&clp->cl_lru);
228 while (!list_empty(&clp->cl_perclient)) {
229 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
230 release_stateowner(sop);
232 free_client(clp);
235 static struct nfs4_client *
236 create_client(struct xdr_netobj name) {
237 struct nfs4_client *clp;
239 if (!(clp = alloc_client(name)))
240 goto out;
241 INIT_LIST_HEAD(&clp->cl_idhash);
242 INIT_LIST_HEAD(&clp->cl_strhash);
243 INIT_LIST_HEAD(&clp->cl_perclient);
244 INIT_LIST_HEAD(&clp->cl_lru);
245 out:
246 return clp;
249 static void
250 copy_verf(struct nfs4_client *target, nfs4_verifier *source) {
251 memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data));
254 static void
255 copy_clid(struct nfs4_client *target, struct nfs4_client *source) {
256 target->cl_clientid.cl_boot = source->cl_clientid.cl_boot;
257 target->cl_clientid.cl_id = source->cl_clientid.cl_id;
260 static void
261 copy_cred(struct svc_cred *target, struct svc_cred *source) {
263 target->cr_uid = source->cr_uid;
264 target->cr_gid = source->cr_gid;
265 target->cr_group_info = source->cr_group_info;
266 get_group_info(target->cr_group_info);
269 static int
270 cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
271 if (!n1 || !n2)
272 return 0;
273 return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
276 static int
277 cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) {
278 return(!memcmp(v1->data,v2->data,sizeof(v1->data)));
281 static int
282 cmp_clid(clientid_t * cl1, clientid_t * cl2) {
283 return((cl1->cl_boot == cl2->cl_boot) &&
284 (cl1->cl_id == cl2->cl_id));
287 /* XXX what about NGROUP */
288 static int
289 cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){
290 return(cr1->cr_uid == cr2->cr_uid);
294 static void
295 gen_clid(struct nfs4_client *clp) {
296 clp->cl_clientid.cl_boot = boot_time;
297 clp->cl_clientid.cl_id = current_clientid++;
300 static void
301 gen_confirm(struct nfs4_client *clp) {
302 struct timespec tv;
303 u32 * p;
305 tv = CURRENT_TIME;
306 p = (u32 *)clp->cl_confirm.data;
307 *p++ = tv.tv_sec;
308 *p++ = tv.tv_nsec;
311 static int
312 check_name(struct xdr_netobj name) {
314 if (name.len == 0)
315 return 0;
316 if (name.len > NFS4_OPAQUE_LIMIT) {
317 printk("NFSD: check_name: name too long(%d)!\n", name.len);
318 return 0;
320 return 1;
323 void
324 add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
326 unsigned int idhashval;
328 list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
329 idhashval = clientid_hashval(clp->cl_clientid.cl_id);
330 list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
331 list_add_tail(&clp->cl_lru, &client_lru);
332 clp->cl_time = get_seconds();
335 void
336 move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
338 unsigned int strhashval;
340 dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
341 list_del_init(&clp->cl_strhash);
342 list_del_init(&clp->cl_idhash);
343 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
344 strhashval = clientstr_hashval(clp->cl_name.data,
345 clp->cl_name.len);
346 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
347 renew_client(clp);
351 /* a helper function for parse_callback */
352 static int
353 parse_octet(unsigned int *lenp, char **addrp)
355 unsigned int len = *lenp;
356 char *p = *addrp;
357 int n = -1;
358 char c;
360 for (;;) {
361 if (!len)
362 break;
363 len--;
364 c = *p++;
365 if (c == '.')
366 break;
367 if ((c < '0') || (c > '9')) {
368 n = -1;
369 break;
371 if (n < 0)
372 n = 0;
373 n = (n * 10) + (c - '0');
374 if (n > 255) {
375 n = -1;
376 break;
379 *lenp = len;
380 *addrp = p;
381 return n;
384 /* parse and set the setclientid ipv4 callback address */
386 parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
388 int temp = 0;
389 u32 cbaddr = 0;
390 u16 cbport = 0;
391 u32 addrlen = addr_len;
392 char *addr = addr_val;
393 int i, shift;
395 /* ipaddress */
396 shift = 24;
397 for(i = 4; i > 0 ; i--) {
398 if ((temp = parse_octet(&addrlen, &addr)) < 0) {
399 return 0;
401 cbaddr |= (temp << shift);
402 if (shift > 0)
403 shift -= 8;
405 *cbaddrp = cbaddr;
407 /* port */
408 shift = 8;
409 for(i = 2; i > 0 ; i--) {
410 if ((temp = parse_octet(&addrlen, &addr)) < 0) {
411 return 0;
413 cbport |= (temp << shift);
414 if (shift > 0)
415 shift -= 8;
417 *cbportp = cbport;
418 return 1;
421 void
422 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
424 struct nfs4_callback *cb = &clp->cl_callback;
426 if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
427 &cb->cb_addr, &cb->cb_port))) {
428 printk(KERN_INFO "NFSD: BAD callback address. client will not receive delegations\n");
429 cb->cb_parsed = 0;
430 return;
432 cb->cb_netid.len = se->se_callback_netid_len;
433 cb->cb_netid.data = se->se_callback_netid_val;
434 cb->cb_prog = se->se_callback_prog;
435 cb->cb_ident = se->se_callback_ident;
436 cb->cb_parsed = 1;
440 * RFC 3010 has a complex implmentation description of processing a
441 * SETCLIENTID request consisting of 5 bullets, labeled as
442 * CASE0 - CASE4 below.
444 * NOTES:
445 * callback information will be processed in a future patch
447 * an unconfirmed record is added when:
448 * NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record.
449 * CASE 1: confirmed record found with matching name, principal,
450 * verifier, and clientid.
451 * CASE 2: confirmed record found with matching name, principal,
452 * and there is no unconfirmed record with matching
453 * name and principal
455 * an unconfirmed record is replaced when:
456 * CASE 3: confirmed record found with matching name, principal,
457 * and an unconfirmed record is found with matching
458 * name, principal, and with clientid and
459 * confirm that does not match the confirmed record.
460 * CASE 4: there is no confirmed record with matching name and
461 * principal. there is an unconfirmed record with
462 * matching name, principal.
464 * an unconfirmed record is deleted when:
465 * CASE 1: an unconfirmed record that matches input name, verifier,
466 * and confirmed clientid.
467 * CASE 4: any unconfirmed records with matching name and principal
468 * that exist after an unconfirmed record has been replaced
469 * as described above.
473 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
475 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
476 struct xdr_netobj clname = {
477 .len = setclid->se_namelen,
478 .data = setclid->se_name,
480 nfs4_verifier clverifier = setclid->se_verf;
481 unsigned int strhashval;
482 struct nfs4_client * conf, * unconf, * new, * clp;
483 int status;
485 status = nfserr_inval;
486 if (!check_name(clname))
487 goto out;
490 * XXX The Duplicate Request Cache (DRC) has been checked (??)
491 * We get here on a DRC miss.
494 strhashval = clientstr_hashval(clname.data, clname.len);
496 conf = NULL;
497 nfs4_lock_state();
498 list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
499 if (!cmp_name(&clp->cl_name, &clname))
500 continue;
502 * CASE 0:
503 * clname match, confirmed, different principal
504 * or different ip_address
506 status = nfserr_clid_inuse;
507 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
508 printk("NFSD: setclientid: string in use by client"
509 "(clientid %08x/%08x)\n",
510 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
511 goto out;
513 if (clp->cl_addr != ip_addr) {
514 printk("NFSD: setclientid: string in use by client"
515 "(clientid %08x/%08x)\n",
516 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
517 goto out;
521 * cl_name match from a previous SETCLIENTID operation
522 * XXX check for additional matches?
524 conf = clp;
525 break;
527 unconf = NULL;
528 list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
529 if (!cmp_name(&clp->cl_name, &clname))
530 continue;
531 /* cl_name match from a previous SETCLIENTID operation */
532 unconf = clp;
533 break;
535 status = nfserr_resource;
536 if (!conf) {
538 * CASE 4:
539 * placed first, because it is the normal case.
541 if (unconf)
542 expire_client(unconf);
543 if (!(new = create_client(clname)))
544 goto out;
545 copy_verf(new, &clverifier);
546 new->cl_addr = ip_addr;
547 copy_cred(&new->cl_cred,&rqstp->rq_cred);
548 gen_clid(new);
549 gen_confirm(new);
550 gen_callback(new, setclid);
551 add_to_unconfirmed(new, strhashval);
552 } else if (cmp_verf(&conf->cl_verifier, &clverifier)) {
554 * CASE 1:
555 * cl_name match, confirmed, principal match
556 * verifier match: probable callback update
558 * remove any unconfirmed nfs4_client with
559 * matching cl_name, cl_verifier, and cl_clientid
561 * create and insert an unconfirmed nfs4_client with same
562 * cl_name, cl_verifier, and cl_clientid as existing
563 * nfs4_client, but with the new callback info and a
564 * new cl_confirm
566 if ((unconf) &&
567 cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
568 cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
569 expire_client(unconf);
571 if (!(new = create_client(clname)))
572 goto out;
573 copy_verf(new,&conf->cl_verifier);
574 new->cl_addr = ip_addr;
575 copy_cred(&new->cl_cred,&rqstp->rq_cred);
576 copy_clid(new, conf);
577 gen_confirm(new);
578 gen_callback(new, setclid);
579 add_to_unconfirmed(new,strhashval);
580 } else if (!unconf) {
582 * CASE 2:
583 * clname match, confirmed, principal match
584 * verfier does not match
585 * no unconfirmed. create a new unconfirmed nfs4_client
586 * using input clverifier, clname, and callback info
587 * and generate a new cl_clientid and cl_confirm.
589 if (!(new = create_client(clname)))
590 goto out;
591 copy_verf(new,&clverifier);
592 new->cl_addr = ip_addr;
593 copy_cred(&new->cl_cred,&rqstp->rq_cred);
594 gen_clid(new);
595 gen_confirm(new);
596 gen_callback(new, setclid);
597 add_to_unconfirmed(new, strhashval);
598 } else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
600 * CASE3:
601 * confirmed found (name, principal match)
602 * confirmed verifier does not match input clverifier
604 * unconfirmed found (name match)
605 * confirmed->cl_confirm != unconfirmed->cl_confirm
607 * remove unconfirmed.
609 * create an unconfirmed nfs4_client
610 * with same cl_name as existing confirmed nfs4_client,
611 * but with new callback info, new cl_clientid,
612 * new cl_verifier and a new cl_confirm
614 expire_client(unconf);
615 if (!(new = create_client(clname)))
616 goto out;
617 copy_verf(new,&clverifier);
618 new->cl_addr = ip_addr;
619 copy_cred(&new->cl_cred,&rqstp->rq_cred);
620 gen_clid(new);
621 gen_confirm(new);
622 gen_callback(new, setclid);
623 add_to_unconfirmed(new, strhashval);
624 } else {
625 /* No cases hit !!! */
626 status = nfserr_inval;
627 goto out;
630 setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
631 setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
632 memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
633 status = nfs_ok;
634 out:
635 nfs4_unlock_state();
636 return status;
641 * RFC 3010 has a complex implmentation description of processing a
642 * SETCLIENTID_CONFIRM request consisting of 4 bullets describing
643 * processing on a DRC miss, labeled as CASE1 - CASE4 below.
645 * NOTE: callback information will be processed here in a future patch
648 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
650 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
651 unsigned int idhashval;
652 struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
653 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
654 clientid_t * clid = &setclientid_confirm->sc_clientid;
655 int status;
657 status = nfserr_stale_clientid;
658 if (STALE_CLIENTID(clid))
659 goto out;
661 * XXX The Duplicate Request Cache (DRC) has been checked (??)
662 * We get here on a DRC miss.
665 idhashval = clientid_hashval(clid->cl_id);
666 nfs4_lock_state();
667 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
668 if (!cmp_clid(&clp->cl_clientid, clid))
669 continue;
671 status = nfserr_inval;
673 * Found a record for this clientid. If the IP addresses
674 * don't match, return ERR_INVAL just as if the record had
675 * not been found.
677 if (clp->cl_addr != ip_addr) {
678 printk("NFSD: setclientid: string in use by client"
679 "(clientid %08x/%08x)\n",
680 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
681 goto out;
683 conf = clp;
684 break;
686 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
687 if (!cmp_clid(&clp->cl_clientid, clid))
688 continue;
689 status = nfserr_inval;
690 if (clp->cl_addr != ip_addr) {
691 printk("NFSD: setclientid: string in use by client"
692 "(clientid %08x/%08x)\n",
693 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
694 goto out;
696 unconf = clp;
697 break;
699 /* CASE 1:
700 * unconf record that matches input clientid and input confirm.
701 * conf record that matches input clientid.
702 * conf and unconf records match names, verifiers
704 if ((conf && unconf) &&
705 (cmp_verf(&unconf->cl_confirm, &confirm)) &&
706 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
707 (cmp_name(&conf->cl_name,&unconf->cl_name)) &&
708 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
709 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
710 status = nfserr_clid_inuse;
711 else {
712 expire_client(conf);
713 move_to_confirmed(unconf, idhashval);
714 status = nfs_ok;
716 goto out;
718 /* CASE 2:
719 * conf record that matches input clientid.
720 * if unconf record that matches input clientid, then unconf->cl_name
721 * or unconf->cl_verifier don't match the conf record.
723 if ((conf && !unconf) ||
724 ((conf && unconf) &&
725 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
726 !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
727 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
728 status = nfserr_clid_inuse;
729 } else {
730 status = nfs_ok;
732 goto out;
734 /* CASE 3:
735 * conf record not found.
736 * unconf record found.
737 * unconf->cl_confirm matches input confirm
739 if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
740 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
741 status = nfserr_clid_inuse;
742 } else {
743 status = nfs_ok;
744 move_to_confirmed(unconf, idhashval);
746 goto out;
748 /* CASE 4:
749 * conf record not found, or if conf, then conf->cl_confirm does not
750 * match input confirm.
751 * unconf record not found, or if unconf, then unconf->cl_confirm
752 * does not match input confirm.
754 if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
755 (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
756 status = nfserr_stale_clientid;
757 goto out;
759 /* check that we have hit one of the cases...*/
760 status = nfserr_inval;
761 goto out;
762 out:
763 /* XXX if status == nfs_ok, probe callback path */
764 nfs4_unlock_state();
765 return status;
769 * Open owner state (share locks)
772 /* hash tables for nfs4_stateowner */
773 #define OWNER_HASH_BITS 8
774 #define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
775 #define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
777 #define ownerid_hashval(id) \
778 ((id) & OWNER_HASH_MASK)
779 #define ownerstr_hashval(clientid, ownername) \
780 (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
782 static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
783 static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
785 /* hash table for nfs4_file */
786 #define FILE_HASH_BITS 8
787 #define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
788 #define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
789 /* hash table for (open)nfs4_stateid */
790 #define STATEID_HASH_BITS 10
791 #define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
792 #define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
794 #define file_hashval(x) \
795 hash_ptr(x, FILE_HASH_BITS)
796 #define stateid_hashval(owner_id, file_id) \
797 (((owner_id) + (file_id)) & STATEID_HASH_MASK)
799 static struct list_head file_hashtbl[FILE_HASH_SIZE];
800 static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
802 /* OPEN Share state helper functions */
803 static inline struct nfs4_file *
804 alloc_init_file(unsigned int hashval, struct inode *ino) {
805 struct nfs4_file *fp;
806 if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
807 INIT_LIST_HEAD(&fp->fi_hash);
808 INIT_LIST_HEAD(&fp->fi_perfile);
809 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
810 fp->fi_inode = igrab(ino);
811 fp->fi_id = current_fileid++;
812 alloc_file++;
813 return fp;
815 return NULL;
818 static void
819 release_all_files(void)
821 int i;
822 struct nfs4_file *fp;
824 for (i=0;i<FILE_HASH_SIZE;i++) {
825 while (!list_empty(&file_hashtbl[i])) {
826 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
827 /* this should never be more than once... */
828 if (!list_empty(&fp->fi_perfile)) {
829 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
831 release_file(fp);
836 static inline struct nfs4_stateowner *
837 alloc_stateowner(struct xdr_netobj *owner)
839 struct nfs4_stateowner *sop;
841 if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
842 if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
843 memcpy(sop->so_owner.data, owner->data, owner->len);
844 sop->so_owner.len = owner->len;
845 return sop;
847 kfree(sop);
849 return NULL;
852 /* should use a slab cache */
853 static void
854 free_stateowner(struct nfs4_stateowner *sop) {
855 if (sop) {
856 kfree(sop->so_owner.data);
857 kfree(sop);
858 sop = NULL;
859 free_sowner++;
863 static struct nfs4_stateowner *
864 alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
865 struct nfs4_stateowner *sop;
866 struct nfs4_replay *rp;
867 unsigned int idhashval;
869 if (!(sop = alloc_stateowner(&open->op_owner)))
870 return NULL;
871 idhashval = ownerid_hashval(current_ownerid);
872 INIT_LIST_HEAD(&sop->so_idhash);
873 INIT_LIST_HEAD(&sop->so_strhash);
874 INIT_LIST_HEAD(&sop->so_perclient);
875 INIT_LIST_HEAD(&sop->so_perfilestate);
876 INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */
877 INIT_LIST_HEAD(&sop->so_close_lru);
878 sop->so_time = 0;
879 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
880 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
881 list_add(&sop->so_perclient, &clp->cl_perclient);
882 add_perclient++;
883 sop->so_is_open_owner = 1;
884 sop->so_id = current_ownerid++;
885 sop->so_client = clp;
886 sop->so_seqid = open->op_seqid;
887 sop->so_confirmed = 0;
888 rp = &sop->so_replay;
889 rp->rp_status = NFSERR_SERVERFAULT;
890 rp->rp_buflen = 0;
891 rp->rp_buf = rp->rp_ibuf;
892 alloc_sowner++;
893 return sop;
896 static void
897 release_stateid_lockowner(struct nfs4_stateid *open_stp)
899 struct nfs4_stateowner *lock_sop;
901 while (!list_empty(&open_stp->st_perlockowner)) {
902 lock_sop = list_entry(open_stp->st_perlockowner.next,
903 struct nfs4_stateowner, so_perlockowner);
904 /* list_del(&open_stp->st_perlockowner); */
905 BUG_ON(lock_sop->so_is_open_owner);
906 release_stateowner(lock_sop);
910 static void
911 unhash_stateowner(struct nfs4_stateowner *sop)
913 struct nfs4_stateid *stp;
915 list_del(&sop->so_idhash);
916 list_del(&sop->so_strhash);
917 list_del(&sop->so_perclient);
918 list_del(&sop->so_perlockowner);
919 del_perclient++;
920 while (!list_empty(&sop->so_perfilestate)) {
921 stp = list_entry(sop->so_perfilestate.next,
922 struct nfs4_stateid, st_perfilestate);
923 if (sop->so_is_open_owner)
924 release_stateid(stp, OPEN_STATE);
925 else
926 release_stateid(stp, LOCK_STATE);
930 static void
931 release_stateowner(struct nfs4_stateowner *sop)
933 unhash_stateowner(sop);
934 list_del(&sop->so_close_lru);
935 free_stateowner(sop);
938 static inline void
939 init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
940 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
942 INIT_LIST_HEAD(&stp->st_hash);
943 INIT_LIST_HEAD(&stp->st_perfilestate);
944 INIT_LIST_HEAD(&stp->st_perlockowner);
945 INIT_LIST_HEAD(&stp->st_perfile);
946 list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
947 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
948 list_add_perfile++;
949 list_add(&stp->st_perfile, &fp->fi_perfile);
950 stp->st_stateowner = sop;
951 stp->st_file = fp;
952 stp->st_stateid.si_boot = boot_time;
953 stp->st_stateid.si_stateownerid = sop->so_id;
954 stp->st_stateid.si_fileid = fp->fi_id;
955 stp->st_stateid.si_generation = 0;
956 stp->st_access_bmap = 0;
957 stp->st_deny_bmap = 0;
958 __set_bit(open->op_share_access, &stp->st_access_bmap);
959 __set_bit(open->op_share_deny, &stp->st_deny_bmap);
962 static void
963 release_stateid(struct nfs4_stateid *stp, int flags) {
965 list_del(&stp->st_hash);
966 list_del_perfile++;
967 list_del(&stp->st_perfile);
968 list_del(&stp->st_perfilestate);
969 if ((stp->st_vfs_set) && (flags & OPEN_STATE)) {
970 release_stateid_lockowner(stp);
971 nfsd_close(stp->st_vfs_file);
972 vfsclose++;
973 } else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
974 struct file *filp = stp->st_vfs_file;
976 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
978 kfree(stp);
979 stp = NULL;
982 static void
983 release_file(struct nfs4_file *fp)
985 free_file++;
986 list_del(&fp->fi_hash);
987 iput(fp->fi_inode);
988 kfree(fp);
991 void
992 move_to_close_lru(struct nfs4_stateowner *sop)
994 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
996 unhash_stateowner(sop);
997 list_add_tail(&sop->so_close_lru, &close_lru);
998 sop->so_time = get_seconds();
1001 void
1002 release_state_owner(struct nfs4_stateid *stp, struct nfs4_stateowner **sopp,
1003 int flag)
1005 struct nfs4_stateowner *sop = stp->st_stateowner;
1006 struct nfs4_file *fp = stp->st_file;
1008 dprintk("NFSD: release_state_owner\n");
1009 release_stateid(stp, flag);
1011 /* place unused nfs4_stateowners on so_close_lru list to be
1012 * released by the laundromat service after the lease period
1013 * to enable us to handle CLOSE replay
1015 if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
1016 move_to_close_lru(sop);
1017 /* unused nfs4_file's are releseed. XXX slab cache? */
1018 if (list_empty(&fp->fi_perfile)) {
1019 release_file(fp);
1023 static int
1024 cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
1025 return ((sop->so_owner.len == owner->len) &&
1026 !memcmp(sop->so_owner.data, owner->data, owner->len) &&
1027 (sop->so_client->cl_clientid.cl_id == clid->cl_id));
1030 /* search ownerstr_hashtbl[] for owner */
1031 static int
1032 find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
1033 struct nfs4_stateowner *local = NULL;
1035 list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
1036 if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
1037 continue;
1038 *op = local;
1039 return(1);
1041 return 0;
1044 /* see if clientid is in confirmed hash table */
1045 static int
1046 verify_clientid(struct nfs4_client **client, clientid_t *clid) {
1048 struct nfs4_client *clp;
1049 unsigned int idhashval = clientid_hashval(clid->cl_id);
1051 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
1052 if (!cmp_clid(&clp->cl_clientid, clid))
1053 continue;
1054 *client = clp;
1055 return 1;
1057 *client = NULL;
1058 return 0;
1061 /* search file_hashtbl[] for file */
1062 static int
1063 find_file(unsigned int hashval, struct inode *ino, struct nfs4_file **fp) {
1064 struct nfs4_file *local = NULL;
1066 list_for_each_entry(local, &file_hashtbl[hashval], fi_hash) {
1067 if (local->fi_inode == ino) {
1068 *fp = local;
1069 return(1);
1072 return 0;
1075 #define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
1076 #define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
1078 void
1079 set_access(unsigned int *access, unsigned long bmap) {
1080 int i;
1082 *access = 0;
1083 for (i = 1; i < 4; i++) {
1084 if (test_bit(i, &bmap))
1085 *access |= i;
1089 void
1090 set_deny(unsigned int *deny, unsigned long bmap) {
1091 int i;
1093 *deny = 0;
1094 for (i = 0; i < 4; i++) {
1095 if (test_bit(i, &bmap))
1096 *deny |= i ;
1100 static int
1101 test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
1102 unsigned int access, deny;
1104 set_access(&access, stp->st_access_bmap);
1105 set_deny(&deny, stp->st_deny_bmap);
1106 if ((access & open->op_share_deny) || (deny & open->op_share_access))
1107 return 0;
1108 return 1;
1112 * Called to check deny when READ with all zero stateid or
1113 * WRITE with all zero or all one stateid
1116 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1118 struct inode *ino = current_fh->fh_dentry->d_inode;
1119 unsigned int fi_hashval;
1120 struct nfs4_file *fp;
1121 struct nfs4_stateid *stp;
1123 dprintk("NFSD: nfs4_share_conflict\n");
1125 fi_hashval = file_hashval(ino);
1126 if (find_file(fi_hashval, ino, &fp)) {
1127 /* Search for conflicting share reservations */
1128 list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
1129 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1130 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1131 return nfserr_share_denied;
1134 return nfs_ok;
1137 static inline int
1138 nfs4_file_upgrade(struct file *filp, unsigned int share_access)
1140 int status;
1142 if (share_access & NFS4_SHARE_ACCESS_WRITE) {
1143 status = get_write_access(filp->f_dentry->d_inode);
1144 if (status)
1145 return nfserrno(status);
1146 filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
1148 return nfs_ok;
1151 static inline void
1152 nfs4_file_downgrade(struct file *filp, unsigned int share_access)
1154 if (share_access & NFS4_SHARE_ACCESS_WRITE) {
1155 put_write_access(filp->f_dentry->d_inode);
1156 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
1162 * nfsd4_process_open1()
1163 * lookup stateowner.
1164 * found:
1165 * check confirmed
1166 * confirmed:
1167 * check seqid
1168 * not confirmed:
1169 * delete owner
1170 * create new owner
1171 * notfound:
1172 * verify clientid
1173 * create new owner
1175 * called with nfs4_lock_state() held.
1178 nfsd4_process_open1(struct nfsd4_open *open)
1180 int status;
1181 clientid_t *clientid = &open->op_clientid;
1182 struct nfs4_client *clp = NULL;
1183 unsigned int strhashval;
1184 struct nfs4_stateowner *sop = NULL;
1186 status = nfserr_inval;
1187 if (!check_name(open->op_owner))
1188 goto out;
1190 status = nfserr_stale_clientid;
1191 if (STALE_CLIENTID(&open->op_clientid))
1192 return status;
1194 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1195 if (find_openstateowner_str(strhashval, open, &sop)) {
1196 open->op_stateowner = sop;
1197 /* check for replay */
1198 if (open->op_seqid == sop->so_seqid){
1199 if (!sop->so_replay.rp_buflen) {
1201 * The original OPEN failed in so spectacularly that we
1202 * don't even have replay data saved! Therefore, we
1203 * have no choice but to continue processing
1204 * this OPEN; presumably, we'll fail again for the same
1205 * reason.
1207 dprintk("nfsd4_process_open1: replay with no replay cache\n");
1208 status = NFS_OK;
1209 goto renew;
1211 /* replay: indicate to calling function */
1212 status = NFSERR_REPLAY_ME;
1213 return status;
1215 if (sop->so_confirmed) {
1216 if (open->op_seqid == sop->so_seqid + 1) {
1217 status = nfs_ok;
1218 goto renew;
1220 status = nfserr_bad_seqid;
1221 goto out;
1223 /* If we get here, we received and OPEN for an unconfirmed
1224 * nfs4_stateowner.
1225 * Since the sequid's are different, purge the
1226 * existing nfs4_stateowner, and instantiate a new one.
1228 clp = sop->so_client;
1229 release_stateowner(sop);
1230 goto instantiate_new_owner;
1232 /* nfs4_stateowner not found.
1233 * verify clientid and instantiate new nfs4_stateowner
1234 * if verify fails this is presumably the result of the
1235 * client's lease expiring.
1237 * XXX compare clp->cl_addr with rqstp addr?
1239 status = nfserr_expired;
1240 if (!verify_clientid(&clp, clientid))
1241 goto out;
1242 instantiate_new_owner:
1243 status = nfserr_resource;
1244 if (!(sop = alloc_init_open_stateowner(strhashval, clp, open)))
1245 goto out;
1246 open->op_stateowner = sop;
1247 status = nfs_ok;
1248 renew:
1249 renew_client(sop->so_client);
1250 out:
1251 if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
1252 status = nfserr_reclaim_bad;
1253 return status;
1256 * called with nfs4_lock_state() held.
1259 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
1261 struct iattr iattr;
1262 struct nfs4_stateowner *sop = open->op_stateowner;
1263 struct nfs4_file *fp = NULL;
1264 struct inode *ino;
1265 unsigned int fi_hashval;
1266 struct nfs4_stateid *stq, *stp = NULL;
1267 int status;
1269 status = nfserr_resource;
1270 if (!sop)
1271 return status;
1273 ino = current_fh->fh_dentry->d_inode;
1275 status = nfserr_inval;
1276 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
1277 goto out;
1279 fi_hashval = file_hashval(ino);
1280 if (find_file(fi_hashval, ino, &fp)) {
1281 /* Search for conflicting share reservations */
1282 status = nfserr_share_denied;
1283 list_for_each_entry(stq, &fp->fi_perfile, st_perfile) {
1284 if (stq->st_stateowner == sop) {
1285 stp = stq;
1286 continue;
1288 /* ignore lock owners */
1289 if (stq->st_stateowner->so_is_open_owner == 0)
1290 continue;
1291 if (!test_share(stq,open))
1292 goto out;
1294 } else {
1295 /* No nfs4_file found; allocate and init a new one */
1296 status = nfserr_resource;
1297 if ((fp = alloc_init_file(fi_hashval, ino)) == NULL)
1298 goto out;
1301 if (!stp) {
1302 int flags = 0;
1304 status = nfserr_resource;
1305 if ((stp = kmalloc(sizeof(struct nfs4_stateid),
1306 GFP_KERNEL)) == NULL)
1307 goto out;
1309 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1310 flags = MAY_WRITE;
1311 else
1312 flags = MAY_READ;
1313 if ((status = nfsd_open(rqstp, current_fh, S_IFREG,
1314 flags,
1315 &stp->st_vfs_file)) != 0)
1316 goto out_free;
1318 vfsopen++;
1320 init_stateid(stp, fp, sop, open);
1321 stp->st_vfs_set = 1;
1322 } else {
1323 /* This is an upgrade of an existing OPEN.
1324 * OR the incoming share with the existing
1325 * nfs4_stateid share */
1326 unsigned int share_access;
1328 set_access(&share_access, stp->st_access_bmap);
1329 share_access = ~share_access;
1330 share_access &= open->op_share_access;
1332 /* update the struct file */
1333 if ((status = nfs4_file_upgrade(stp->st_vfs_file, share_access)))
1334 goto out;
1335 /* remember the open */
1336 set_bit(open->op_share_access, &stp->st_access_bmap);
1337 set_bit(open->op_share_deny, &stp->st_deny_bmap);
1338 /* bump the stateid */
1339 update_stateid(&stp->st_stateid);
1341 dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n\n",
1342 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1343 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1345 if (open->op_truncate) {
1346 iattr.ia_valid = ATTR_SIZE;
1347 iattr.ia_size = 0;
1348 status = nfsd_setattr(rqstp, current_fh, &iattr, 0, (time_t)0);
1349 if (status)
1350 goto out;
1352 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
1354 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
1355 status = nfs_ok;
1356 out:
1357 if (fp && list_empty(&fp->fi_perfile))
1358 release_file(fp);
1360 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
1361 if (status)
1362 status = nfserr_reclaim_bad;
1363 else {
1364 /* successful reclaim. so_seqid is decremented because
1365 * it will be bumped in encode_open
1367 open->op_stateowner->so_confirmed = 1;
1368 open->op_stateowner->so_seqid--;
1372 * To finish the open response, we just need to set the rflags.
1374 open->op_rflags = 0;
1375 if (!open->op_stateowner->so_confirmed)
1376 open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
1378 return status;
1379 out_free:
1380 kfree(stp);
1381 goto out;
1384 static struct work_struct laundromat_work;
1385 static void laundromat_main(void *);
1386 static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
1388 int
1389 nfsd4_renew(clientid_t *clid)
1391 struct nfs4_client *clp;
1392 unsigned int idhashval;
1393 int status;
1395 nfs4_lock_state();
1396 dprintk("process_renew(%08x/%08x): starting\n",
1397 clid->cl_boot, clid->cl_id);
1398 status = nfserr_stale_clientid;
1399 if (STALE_CLIENTID(clid))
1400 goto out;
1401 status = nfs_ok;
1402 idhashval = clientid_hashval(clid->cl_id);
1403 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
1404 if (!cmp_clid(&clp->cl_clientid, clid))
1405 continue;
1406 renew_client(clp);
1407 goto out;
1409 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
1410 if (!cmp_clid(&clp->cl_clientid, clid))
1411 continue;
1412 renew_client(clp);
1413 goto out;
1416 * Couldn't find an nfs4_client for this clientid.
1417 * Presumably this is because the client took too long to
1418 * RENEW, so return NFS4ERR_EXPIRED.
1420 dprintk("nfsd4_renew: clientid not found!\n");
1421 status = nfserr_expired;
1422 out:
1423 nfs4_unlock_state();
1424 return status;
1427 time_t
1428 nfs4_laundromat(void)
1430 struct nfs4_client *clp;
1431 struct nfs4_stateowner *sop;
1432 struct list_head *pos, *next;
1433 time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
1434 time_t t, clientid_val = NFSD_LEASE_TIME;
1435 time_t u, close_val = NFSD_LEASE_TIME;
1437 nfs4_lock_state();
1439 dprintk("NFSD: laundromat service - starting, examining clients\n");
1440 list_for_each_safe(pos, next, &client_lru) {
1441 clp = list_entry(pos, struct nfs4_client, cl_lru);
1442 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
1443 t = clp->cl_time - cutoff;
1444 if (clientid_val > t)
1445 clientid_val = t;
1446 break;
1448 dprintk("NFSD: purging unused client (clientid %08x)\n",
1449 clp->cl_clientid.cl_id);
1450 expire_client(clp);
1452 list_for_each_safe(pos, next, &close_lru) {
1453 sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
1454 if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) {
1455 u = sop->so_time - cutoff;
1456 if (close_val > u)
1457 close_val = u;
1458 break;
1460 dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
1461 sop->so_id);
1462 list_del(&sop->so_close_lru);
1463 free_stateowner(sop);
1465 if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
1466 clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
1467 nfs4_unlock_state();
1468 return clientid_val;
1471 void
1472 laundromat_main(void *not_used)
1474 time_t t;
1476 t = nfs4_laundromat();
1477 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1478 schedule_delayed_work(&laundromat_work, t*HZ);
1481 /* search ownerid_hashtbl[] and close_lru for stateid owner
1482 * (stateid->si_stateownerid)
1484 struct nfs4_stateowner *
1485 find_openstateowner_id(u32 st_id, int flags) {
1486 struct nfs4_stateowner *local = NULL;
1488 dprintk("NFSD: find_openstateowner_id %d\n", st_id);
1489 if (flags & CLOSE_STATE) {
1490 list_for_each_entry(local, &close_lru, so_close_lru) {
1491 if (local->so_id == st_id)
1492 return local;
1495 return NULL;
1498 static inline int
1499 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
1501 return (stp->st_vfs_set == 0 ||
1502 fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode);
1505 static int
1506 STALE_STATEID(stateid_t *stateid)
1508 if (stateid->si_boot == boot_time)
1509 return 0;
1510 printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
1511 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
1512 stateid->si_generation);
1513 return 1;
1518 * Checks for stateid operations
1521 nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct nfs4_stateid **stpp)
1523 struct nfs4_stateid *stp;
1524 int status;
1526 dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
1527 stateid->si_boot, stateid->si_stateownerid,
1528 stateid->si_fileid, stateid->si_generation);
1530 *stpp = NULL;
1532 /* STALE STATEID */
1533 status = nfserr_stale_stateid;
1534 if (STALE_STATEID(stateid))
1535 goto out;
1537 /* BAD STATEID */
1538 status = nfserr_bad_stateid;
1539 if (!(stp = find_stateid(stateid, flags))) {
1540 dprintk("NFSD: preprocess_stateid_op: no open stateid!\n");
1541 goto out;
1543 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
1544 dprintk("NFSD: preprocess_stateid_op: fh-stateid mismatch!\n");
1545 stp->st_vfs_set = 0;
1546 goto out;
1548 if (!stp->st_stateowner->so_confirmed) {
1549 dprintk("preprocess_stateid_op: lockowner not confirmed yet!\n");
1550 goto out;
1552 if (stateid->si_generation > stp->st_stateid.si_generation) {
1553 dprintk("preprocess_stateid_op: future stateid?!\n");
1554 goto out;
1557 /* OLD STATEID */
1558 status = nfserr_old_stateid;
1559 if (stateid->si_generation < stp->st_stateid.si_generation) {
1560 dprintk("preprocess_stateid_op: old stateid!\n");
1561 goto out;
1563 *stpp = stp;
1564 status = nfs_ok;
1565 renew_client(stp->st_stateowner->so_client);
1566 out:
1567 return status;
1572 * Checks for sequence id mutating operations.
1575 nfs4_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)
1577 int status;
1578 struct nfs4_stateid *stp;
1579 struct nfs4_stateowner *sop;
1581 dprintk("NFSD: preprocess_seqid_op: seqid=%d "
1582 "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
1583 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
1584 stateid->si_generation);
1586 *stpp = NULL;
1587 *sopp = NULL;
1589 status = nfserr_bad_stateid;
1590 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
1591 printk("NFSD: preprocess_seqid_op: magic stateid!\n");
1592 goto out;
1595 status = nfserr_stale_stateid;
1596 if (STALE_STATEID(stateid))
1597 goto out;
1599 * We return BAD_STATEID if filehandle doesn't match stateid,
1600 * the confirmed flag is incorrecly set, or the generation
1601 * number is incorrect.
1602 * If there is no entry in the openfile table for this id,
1603 * we can't always return BAD_STATEID;
1604 * this might be a retransmitted CLOSE which has arrived after
1605 * the openfile has been released.
1607 if (!(stp = find_stateid(stateid, flags)))
1608 goto no_nfs4_stateid;
1610 status = nfserr_bad_stateid;
1612 /* for new lock stateowners:
1613 * check that the lock->v.new.open_stateid
1614 * refers to an open stateowner
1616 * check that the lockclid (nfs4_lock->v.new.clientid) is the same
1617 * as the open_stateid->st_stateowner->so_client->clientid
1619 if (lockclid) {
1620 struct nfs4_stateowner *sop = stp->st_stateowner;
1621 struct nfs4_client *clp = sop->so_client;
1623 if (!sop->so_is_open_owner)
1624 goto out;
1625 if (!cmp_clid(&clp->cl_clientid, lockclid))
1626 goto out;
1629 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
1630 printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
1631 stp->st_vfs_set = 0;
1632 goto out;
1635 *stpp = stp;
1636 *sopp = sop = stp->st_stateowner;
1639 * We now validate the seqid and stateid generation numbers.
1640 * For the moment, we ignore the possibility of
1641 * generation number wraparound.
1643 if (seqid != sop->so_seqid + 1)
1644 goto check_replay;
1646 if (sop->so_confirmed) {
1647 if (flags & CONFIRM) {
1648 printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
1649 goto out;
1652 else {
1653 if (!(flags & CONFIRM)) {
1654 printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
1655 goto out;
1658 if (stateid->si_generation > stp->st_stateid.si_generation) {
1659 printk("NFSD: preprocess_seqid_op: future stateid?!\n");
1660 goto out;
1663 status = nfserr_old_stateid;
1664 if (stateid->si_generation < stp->st_stateid.si_generation) {
1665 printk("NFSD: preprocess_seqid_op: old stateid!\n");
1666 goto out;
1668 /* XXX renew the client lease here */
1669 status = nfs_ok;
1671 out:
1672 return status;
1674 no_nfs4_stateid:
1677 * We determine whether this is a bad stateid or a replay,
1678 * starting by trying to look up the stateowner.
1679 * If stateowner is not found - stateid is bad.
1681 if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) {
1682 printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
1683 status = nfserr_bad_stateid;
1684 goto out;
1686 *sopp = sop;
1688 check_replay:
1689 if (seqid == sop->so_seqid) {
1690 printk("NFSD: preprocess_seqid_op: retransmission?\n");
1691 /* indicate replay to calling function */
1692 status = NFSERR_REPLAY_ME;
1693 } else {
1694 printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
1696 *sopp = NULL;
1697 status = nfserr_bad_seqid;
1699 goto out;
1703 * eventually, this will perform an upcall to the 'state daemon' as well as
1704 * set the cl_first_state field.
1706 void
1707 first_state(struct nfs4_client *clp)
1709 if (!clp->cl_first_state)
1710 clp->cl_first_state = get_seconds();
1714 * nfs4_unlock_state(); called in encode
1717 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
1719 int status;
1720 struct nfs4_stateowner *sop;
1721 struct nfs4_stateid *stp;
1723 dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
1724 (int)current_fh->fh_dentry->d_name.len,
1725 current_fh->fh_dentry->d_name.name);
1727 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
1728 goto out;
1730 oc->oc_stateowner = NULL;
1731 nfs4_lock_state();
1733 if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
1734 &oc->oc_req_stateid,
1735 CHECK_FH | CONFIRM | OPEN_STATE,
1736 &oc->oc_stateowner, &stp, NULL)))
1737 goto out;
1739 sop = oc->oc_stateowner;
1740 sop->so_confirmed = 1;
1741 update_stateid(&stp->st_stateid);
1742 memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
1743 dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d "
1744 "stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
1745 stp->st_stateid.si_boot,
1746 stp->st_stateid.si_stateownerid,
1747 stp->st_stateid.si_fileid,
1748 stp->st_stateid.si_generation);
1749 status = nfs_ok;
1750 first_state(sop->so_client);
1751 out:
1752 return status;
1757 * unset all bits in union bitmap (bmap) that
1758 * do not exist in share (from successful OPEN_DOWNGRADE)
1760 static void
1761 reset_union_bmap_access(unsigned long access, unsigned long *bmap)
1763 int i;
1764 for (i = 1; i < 4; i++) {
1765 if ((i & access) != i)
1766 __clear_bit(i, bmap);
1770 static void
1771 reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
1773 int i;
1774 for (i = 0; i < 4; i++) {
1775 if ((i & deny) != i)
1776 __clear_bit(i, bmap);
1781 * nfs4_unlock_state(); called in encode
1785 nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
1787 int status;
1788 struct nfs4_stateid *stp;
1789 unsigned int share_access;
1791 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
1792 (int)current_fh->fh_dentry->d_name.len,
1793 current_fh->fh_dentry->d_name.name);
1795 od->od_stateowner = NULL;
1796 status = nfserr_inval;
1797 if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
1798 goto out;
1800 nfs4_lock_state();
1801 if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
1802 &od->od_stateid,
1803 CHECK_FH | OPEN_STATE,
1804 &od->od_stateowner, &stp, NULL)))
1805 goto out;
1807 status = nfserr_inval;
1808 if (!test_bit(od->od_share_access, &stp->st_access_bmap)) {
1809 dprintk("NFSD:access not a subset current bitmap: 0x%lx, input access=%08x\n",
1810 stp->st_access_bmap, od->od_share_access);
1811 goto out;
1813 if (!test_bit(od->od_share_deny, &stp->st_deny_bmap)) {
1814 dprintk("NFSD:deny not a subset current bitmap: 0x%lx, input deny=%08x\n",
1815 stp->st_deny_bmap, od->od_share_deny);
1816 goto out;
1818 set_access(&share_access, stp->st_access_bmap);
1819 nfs4_file_downgrade(stp->st_vfs_file,
1820 share_access & ~od->od_share_access);
1822 reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
1823 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
1825 update_stateid(&stp->st_stateid);
1826 memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
1827 status = nfs_ok;
1828 out:
1829 return status;
1833 * nfs4_unlock_state() called after encode
1836 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
1838 int status;
1839 struct nfs4_stateid *stp;
1841 dprintk("NFSD: nfsd4_close on file %.*s\n",
1842 (int)current_fh->fh_dentry->d_name.len,
1843 current_fh->fh_dentry->d_name.name);
1845 close->cl_stateowner = NULL;
1846 nfs4_lock_state();
1847 /* check close_lru for replay */
1848 if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
1849 &close->cl_stateid,
1850 CHECK_FH | OPEN_STATE | CLOSE_STATE,
1851 &close->cl_stateowner, &stp, NULL)))
1852 goto out;
1854 * Return success, but first update the stateid.
1856 status = nfs_ok;
1857 update_stateid(&stp->st_stateid);
1858 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
1860 /* release_state_owner() calls nfsd_close() if needed */
1861 release_state_owner(stp, &close->cl_stateowner, OPEN_STATE);
1862 out:
1863 return status;
1867 * Lock owner state (byte-range locks)
1869 #define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start))
1870 #define LOCK_HASH_BITS 8
1871 #define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS)
1872 #define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1)
1874 #define lockownerid_hashval(id) \
1875 ((id) & LOCK_HASH_MASK)
1876 #define lock_ownerstr_hashval(x, clientid, ownername) \
1877 ((file_hashval(x) + (clientid) + opaque_hashval((ownername.data), (ownername.len))) & LOCK_HASH_MASK)
1879 static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
1880 static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
1881 static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
1883 struct nfs4_stateid *
1884 find_stateid(stateid_t *stid, int flags)
1886 struct nfs4_stateid *local = NULL;
1887 u32 st_id = stid->si_stateownerid;
1888 u32 f_id = stid->si_fileid;
1889 unsigned int hashval;
1891 dprintk("NFSD: find_stateid flags 0x%x\n",flags);
1892 if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
1893 hashval = stateid_hashval(st_id, f_id);
1894 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
1895 if ((local->st_stateid.si_stateownerid == st_id) &&
1896 (local->st_stateid.si_fileid == f_id))
1897 return local;
1900 if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
1901 hashval = stateid_hashval(st_id, f_id);
1902 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
1903 if ((local->st_stateid.si_stateownerid == st_id) &&
1904 (local->st_stateid.si_fileid == f_id))
1905 return local;
1907 } else
1908 printk("NFSD: find_stateid: ERROR: no state flag\n");
1909 return NULL;
1914 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
1915 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
1916 * byte, because of sign extension problems. Since NFSv4 calls for 64-bit
1917 * locking, this prevents us from being completely protocol-compliant. The
1918 * real solution to this problem is to start using unsigned file offsets in
1919 * the VFS, but this is a very deep change!
1921 static inline void
1922 nfs4_transform_lock_offset(struct file_lock *lock)
1924 if (lock->fl_start < 0)
1925 lock->fl_start = OFFSET_MAX;
1926 if (lock->fl_end < 0)
1927 lock->fl_end = OFFSET_MAX;
1931 nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
1933 struct nfs4_stateowner *local = NULL;
1934 int status = 0;
1936 if (hashval >= LOCK_HASH_SIZE)
1937 goto out;
1938 list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
1939 if (local == sop) {
1940 status = 1;
1941 goto out;
1944 out:
1945 return status;
1949 static inline void
1950 nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
1952 struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
1953 unsigned int hval = lockownerid_hashval(sop->so_id);
1955 deny->ld_sop = NULL;
1956 if (nfs4_verify_lock_stateowner(sop, hval))
1957 deny->ld_sop = sop;
1958 deny->ld_start = fl->fl_start;
1959 deny->ld_length = ~(u64)0;
1960 if (fl->fl_end != ~(u64)0)
1961 deny->ld_length = fl->fl_end - fl->fl_start + 1;
1962 deny->ld_type = NFS4_READ_LT;
1963 if (fl->fl_type != F_RDLCK)
1964 deny->ld_type = NFS4_WRITE_LT;
1967 static struct nfs4_stateowner *
1968 find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
1970 struct nfs4_stateowner *local = NULL;
1971 int i;
1973 for (i = 0; i < LOCK_HASH_SIZE; i++) {
1974 list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
1975 if (!cmp_owner_str(local, owner, clid))
1976 continue;
1977 return local;
1980 return NULL;
1983 static int
1984 find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid_t *clid, struct nfs4_stateowner **op) {
1985 struct nfs4_stateowner *local = NULL;
1987 list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
1988 if (!cmp_owner_str(local, owner, clid))
1989 continue;
1990 *op = local;
1991 return(1);
1993 *op = NULL;
1994 return 0;
1998 * Alloc a lock owner structure.
1999 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has
2000 * occured.
2002 * strhashval = lock_ownerstr_hashval
2003 * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode
2006 static struct nfs4_stateowner *
2007 alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_stateid *open_stp, struct nfsd4_lock *lock) {
2008 struct nfs4_stateowner *sop;
2009 struct nfs4_replay *rp;
2010 unsigned int idhashval;
2012 if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
2013 return NULL;
2014 idhashval = lockownerid_hashval(current_ownerid);
2015 INIT_LIST_HEAD(&sop->so_idhash);
2016 INIT_LIST_HEAD(&sop->so_strhash);
2017 INIT_LIST_HEAD(&sop->so_perclient);
2018 INIT_LIST_HEAD(&sop->so_perfilestate);
2019 INIT_LIST_HEAD(&sop->so_perlockowner);
2020 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
2021 sop->so_time = 0;
2022 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
2023 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
2024 list_add(&sop->so_perclient, &clp->cl_perclient);
2025 list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
2026 add_perclient++;
2027 sop->so_is_open_owner = 0;
2028 sop->so_id = current_ownerid++;
2029 sop->so_client = clp;
2030 sop->so_seqid = lock->lk_new_lock_seqid - 1;
2031 sop->so_confirmed = 1;
2032 rp = &sop->so_replay;
2033 rp->rp_status = NFSERR_SERVERFAULT;
2034 rp->rp_buflen = 0;
2035 rp->rp_buf = rp->rp_ibuf;
2036 alloc_lsowner++;
2037 return sop;
2040 struct nfs4_stateid *
2041 alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
2043 struct nfs4_stateid *stp;
2044 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
2046 if ((stp = kmalloc(sizeof(struct nfs4_stateid),
2047 GFP_KERNEL)) == NULL)
2048 goto out;
2049 INIT_LIST_HEAD(&stp->st_hash);
2050 INIT_LIST_HEAD(&stp->st_perfile);
2051 INIT_LIST_HEAD(&stp->st_perfilestate);
2052 INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
2053 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
2054 list_add(&stp->st_perfile, &fp->fi_perfile);
2055 list_add_perfile++;
2056 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2057 stp->st_stateowner = sop;
2058 stp->st_file = fp;
2059 stp->st_stateid.si_boot = boot_time;
2060 stp->st_stateid.si_stateownerid = sop->so_id;
2061 stp->st_stateid.si_fileid = fp->fi_id;
2062 stp->st_stateid.si_generation = 0;
2063 stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
2064 stp->st_vfs_set = open_stp->st_vfs_set;
2065 stp->st_access_bmap = open_stp->st_access_bmap;
2066 stp->st_deny_bmap = open_stp->st_deny_bmap;
2068 out:
2069 return stp;
2073 check_lock_length(u64 offset, u64 length)
2075 return ((length == 0) || ((length != ~(u64)0) &&
2076 LOFF_OVERFLOW(offset, length)));
2080 * LOCK operation
2082 * nfs4_unlock_state(); called in encode
2085 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
2087 struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
2088 struct nfs4_stateid *lock_stp;
2089 struct file *filp;
2090 struct file_lock file_lock;
2091 struct file_lock *conflock;
2092 int status = 0;
2093 unsigned int strhashval;
2095 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
2096 (long long) lock->lk_offset,
2097 (long long) lock->lk_length);
2099 if (nfs4_in_grace() && !lock->lk_reclaim)
2100 return nfserr_grace;
2101 if (!nfs4_in_grace() && lock->lk_reclaim)
2102 return nfserr_no_grace;
2104 if (check_lock_length(lock->lk_offset, lock->lk_length))
2105 return nfserr_inval;
2107 lock->lk_stateowner = NULL;
2108 nfs4_lock_state();
2110 if (lock->lk_is_new) {
2112 * Client indicates that this is a new lockowner.
2113 * Use open owner and open stateid to create lock owner and lock
2114 * stateid.
2116 struct nfs4_stateid *open_stp = NULL;
2117 struct nfs4_file *fp;
2119 status = nfserr_stale_clientid;
2120 if (STALE_CLIENTID(&lock->lk_new_clientid)) {
2121 printk("NFSD: nfsd4_lock: clientid is stale!\n");
2122 goto out;
2125 /* is the new lock seqid presented by the client zero? */
2126 status = nfserr_bad_seqid;
2127 if (lock->v.new.lock_seqid != 0)
2128 goto out;
2130 /* validate and update open stateid and open seqid */
2131 status = nfs4_preprocess_seqid_op(current_fh,
2132 lock->lk_new_open_seqid,
2133 &lock->lk_new_open_stateid,
2134 CHECK_FH | OPEN_STATE,
2135 &open_sop, &open_stp,
2136 &lock->v.new.clientid);
2137 if (status) {
2138 if (lock->lk_reclaim)
2139 status = nfserr_reclaim_bad;
2140 goto out;
2142 /* create lockowner and lock stateid */
2143 fp = open_stp->st_file;
2144 strhashval = lock_ownerstr_hashval(fp->fi_inode,
2145 open_sop->so_client->cl_clientid.cl_id,
2146 lock->v.new.owner);
2148 * If we already have this lock owner, the client is in
2149 * error (or our bookeeping is wrong!)
2150 * for asking for a 'new lock'.
2152 status = nfserr_bad_stateid;
2153 lock_sop = find_lockstateowner(&lock->v.new.owner,
2154 &lock->v.new.clientid);
2155 if (lock_sop)
2156 goto out;
2157 status = nfserr_resource;
2158 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
2159 goto out;
2160 if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner,
2161 fp, open_stp)) == NULL) {
2162 release_stateowner(lock->lk_stateowner);
2163 goto out;
2165 /* bump the open seqid used to create the lock */
2166 open_sop->so_seqid++;
2167 } else {
2168 /* lock (lock owner + lock stateid) already exists */
2169 status = nfs4_preprocess_seqid_op(current_fh,
2170 lock->lk_old_lock_seqid,
2171 &lock->lk_old_lock_stateid,
2172 CHECK_FH | LOCK_STATE,
2173 &lock->lk_stateowner, &lock_stp, NULL);
2174 if (status)
2175 goto out;
2177 /* lock->lk_stateowner and lock_stp have been created or found */
2178 filp = lock_stp->st_vfs_file;
2180 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2181 printk("NFSD: nfsd4_lock: permission denied!\n");
2182 goto out;
2185 locks_init_lock(&file_lock);
2186 switch (lock->lk_type) {
2187 case NFS4_READ_LT:
2188 case NFS4_READW_LT:
2189 file_lock.fl_type = F_RDLCK;
2190 break;
2191 case NFS4_WRITE_LT:
2192 case NFS4_WRITEW_LT:
2193 file_lock.fl_type = F_WRLCK;
2194 break;
2195 default:
2196 status = nfserr_inval;
2197 goto out;
2199 file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
2200 file_lock.fl_pid = current->tgid;
2201 file_lock.fl_file = filp;
2202 file_lock.fl_flags = FL_POSIX;
2204 file_lock.fl_start = lock->lk_offset;
2205 if ((lock->lk_length == ~(u64)0) ||
2206 LOFF_OVERFLOW(lock->lk_offset, lock->lk_length))
2207 file_lock.fl_end = ~(u64)0;
2208 else
2209 file_lock.fl_end = lock->lk_offset + lock->lk_length - 1;
2210 nfs4_transform_lock_offset(&file_lock);
2213 * Try to lock the file in the VFS.
2214 * Note: locks.c uses the BKL to protect the inode's lock list.
2217 status = posix_lock_file(filp, &file_lock);
2218 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2219 file_lock.fl_ops->fl_release_private(&file_lock);
2220 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
2221 switch (-status) {
2222 case 0: /* success! */
2223 update_stateid(&lock_stp->st_stateid);
2224 memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid,
2225 sizeof(stateid_t));
2226 goto out;
2227 case (EAGAIN):
2228 goto conflicting_lock;
2229 case (EDEADLK):
2230 status = nfserr_deadlock;
2231 default:
2232 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2233 goto out_destroy_new_stateid;
2236 conflicting_lock:
2237 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
2238 status = nfserr_denied;
2239 /* XXX There is a race here. Future patch needed to provide
2240 * an atomic posix_lock_and_test_file
2242 if (!(conflock = posix_test_lock(filp, &file_lock))) {
2243 status = nfserr_serverfault;
2244 goto out;
2246 nfs4_set_lock_denied(conflock, &lock->lk_denied);
2248 out_destroy_new_stateid:
2249 if (lock->lk_is_new) {
2250 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
2252 * An error encountered after instantiation of the new
2253 * stateid has forced us to destroy it.
2255 if (!seqid_mutating_err(status))
2256 open_sop->so_seqid--;
2258 release_state_owner(lock_stp, &lock->lk_stateowner, LOCK_STATE);
2260 out:
2261 return status;
2265 * LOCKT operation
2268 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
2270 struct inode *inode;
2271 struct file file;
2272 struct file_lock file_lock;
2273 struct file_lock *conflicting_lock;
2274 unsigned int strhashval;
2275 int status;
2277 if (nfs4_in_grace())
2278 return nfserr_grace;
2280 if (check_lock_length(lockt->lt_offset, lockt->lt_length))
2281 return nfserr_inval;
2283 lockt->lt_stateowner = NULL;
2284 nfs4_lock_state();
2286 status = nfserr_stale_clientid;
2287 if (STALE_CLIENTID(&lockt->lt_clientid)) {
2288 printk("NFSD: nfsd4_lockt: clientid is stale!\n");
2289 goto out;
2292 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
2293 printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
2294 if (status == nfserr_symlink)
2295 status = nfserr_inval;
2296 goto out;
2299 inode = current_fh->fh_dentry->d_inode;
2300 locks_init_lock(&file_lock);
2301 switch (lockt->lt_type) {
2302 case NFS4_READ_LT:
2303 case NFS4_READW_LT:
2304 file_lock.fl_type = F_RDLCK;
2305 break;
2306 case NFS4_WRITE_LT:
2307 case NFS4_WRITEW_LT:
2308 file_lock.fl_type = F_WRLCK;
2309 break;
2310 default:
2311 printk("NFSD: nfs4_lockt: bad lock type!\n");
2312 status = nfserr_inval;
2313 goto out;
2316 strhashval = lock_ownerstr_hashval(inode,
2317 lockt->lt_clientid.cl_id, lockt->lt_owner);
2319 find_lockstateowner_str(strhashval, &lockt->lt_owner,
2320 &lockt->lt_clientid,
2321 &lockt->lt_stateowner);
2322 if (lockt->lt_stateowner)
2323 file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
2324 file_lock.fl_pid = current->tgid;
2325 file_lock.fl_flags = FL_POSIX;
2327 file_lock.fl_start = lockt->lt_offset;
2328 if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
2329 file_lock.fl_end = ~(u64)0;
2330 else
2331 file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1;
2333 nfs4_transform_lock_offset(&file_lock);
2335 /* posix_test_lock uses the struct file _only_ to resolve the inode.
2336 * since LOCKT doesn't require an OPEN, and therefore a struct
2337 * file may not exist, pass posix_test_lock a struct file with
2338 * only the dentry:inode set.
2340 memset(&file, 0, sizeof (struct file));
2341 file.f_dentry = current_fh->fh_dentry;
2343 status = nfs_ok;
2344 conflicting_lock = posix_test_lock(&file, &file_lock);
2345 if (conflicting_lock) {
2346 status = nfserr_denied;
2347 nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied);
2349 out:
2350 nfs4_unlock_state();
2351 return status;
2355 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
2357 struct nfs4_stateid *stp;
2358 struct file *filp = NULL;
2359 struct file_lock file_lock;
2360 int status;
2362 dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
2363 (long long) locku->lu_offset,
2364 (long long) locku->lu_length);
2366 if (check_lock_length(locku->lu_offset, locku->lu_length))
2367 return nfserr_inval;
2369 locku->lu_stateowner = NULL;
2370 nfs4_lock_state();
2372 if ((status = nfs4_preprocess_seqid_op(current_fh,
2373 locku->lu_seqid,
2374 &locku->lu_stateid,
2375 CHECK_FH | LOCK_STATE,
2376 &locku->lu_stateowner, &stp, NULL)))
2377 goto out;
2379 filp = stp->st_vfs_file;
2380 BUG_ON(!filp);
2381 locks_init_lock(&file_lock);
2382 file_lock.fl_type = F_UNLCK;
2383 file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
2384 file_lock.fl_pid = current->tgid;
2385 file_lock.fl_file = filp;
2386 file_lock.fl_flags = FL_POSIX;
2387 file_lock.fl_start = locku->lu_offset;
2389 if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
2390 file_lock.fl_end = ~(u64)0;
2391 else
2392 file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
2393 nfs4_transform_lock_offset(&file_lock);
2396 * Try to unlock the file in the VFS.
2398 status = posix_lock_file(filp, &file_lock);
2399 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2400 file_lock.fl_ops->fl_release_private(&file_lock);
2401 if (status) {
2402 printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2403 goto out_nfserr;
2406 * OK, unlock succeeded; the only thing left to do is update the stateid.
2408 update_stateid(&stp->st_stateid);
2409 memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
2411 out:
2412 return status;
2414 out_nfserr:
2415 status = nfserrno(status);
2416 goto out;
2420 * returns
2421 * 1: locks held by lockowner
2422 * 0: no locks held by lockowner
2424 static int
2425 check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
2427 struct file_lock **flpp;
2428 struct inode *inode = filp->f_dentry->d_inode;
2429 int status = 0;
2431 lock_kernel();
2432 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
2433 if ((*flpp)->fl_owner == (fl_owner_t)lowner)
2434 status = 1;
2435 goto out;
2437 out:
2438 unlock_kernel();
2439 return status;
2443 nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
2445 clientid_t *clid = &rlockowner->rl_clientid;
2446 struct nfs4_stateowner *local = NULL;
2447 struct xdr_netobj *owner = &rlockowner->rl_owner;
2448 int status;
2450 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
2451 clid->cl_boot, clid->cl_id);
2453 /* XXX check for lease expiration */
2455 status = nfserr_stale_clientid;
2456 if (STALE_CLIENTID(clid)) {
2457 printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n");
2458 return status;
2461 nfs4_lock_state();
2463 status = nfs_ok;
2464 local = find_lockstateowner(owner, clid);
2465 if (local) {
2466 struct nfs4_stateid *stp;
2468 /* check for any locks held by any stateid
2469 * associated with the (lock) stateowner */
2470 status = nfserr_locks_held;
2471 list_for_each_entry(stp, &local->so_perfilestate,
2472 st_perfilestate) {
2473 if (stp->st_vfs_set) {
2474 if (check_for_locks(stp->st_vfs_file, local))
2475 goto out;
2478 /* no locks held by (lock) stateowner */
2479 status = nfs_ok;
2480 release_stateowner(local);
2482 out:
2483 nfs4_unlock_state();
2484 return status;
2487 static inline struct nfs4_client_reclaim *
2488 alloc_reclaim(int namelen)
2490 struct nfs4_client_reclaim *crp = NULL;
2492 crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
2493 if (!crp)
2494 return NULL;
2495 crp->cr_name.data = kmalloc(namelen, GFP_KERNEL);
2496 if (!crp->cr_name.data) {
2497 kfree(crp);
2498 return NULL;
2500 return crp;
2504 * failure => all reset bets are off, nfserr_no_grace...
2506 static int
2507 nfs4_client_to_reclaim(struct nfs4_client *clp)
2509 unsigned int strhashval;
2510 struct nfs4_client_reclaim *crp = NULL;
2512 crp = alloc_reclaim(clp->cl_name.len);
2513 if (!crp)
2514 return 0;
2515 strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
2516 INIT_LIST_HEAD(&crp->cr_strhash);
2517 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
2518 memcpy(crp->cr_name.data, clp->cl_name.data, clp->cl_name.len);
2519 crp->cr_name.len = clp->cl_name.len;
2520 crp->cr_first_state = clp->cl_first_state;
2521 crp->cr_expired = 0;
2522 return 1;
2525 static void
2526 nfs4_release_reclaim(void)
2528 struct nfs4_client_reclaim *crp = NULL;
2529 int i;
2531 BUG_ON(!nfs4_reclaim_init);
2532 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2533 while (!list_empty(&reclaim_str_hashtbl[i])) {
2534 crp = list_entry(reclaim_str_hashtbl[i].next,
2535 struct nfs4_client_reclaim, cr_strhash);
2536 list_del(&crp->cr_strhash);
2537 kfree(crp->cr_name.data);
2538 kfree(crp);
2539 reclaim_str_hashtbl_size--;
2542 BUG_ON(reclaim_str_hashtbl_size);
2546 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
2547 struct nfs4_client_reclaim *
2548 nfs4_find_reclaim_client(clientid_t *clid)
2550 unsigned int idhashval = clientid_hashval(clid->cl_id);
2551 unsigned int strhashval;
2552 struct nfs4_client *clp, *client = NULL;
2553 struct nfs4_client_reclaim *crp = NULL;
2556 /* find clientid in conf_id_hashtbl */
2557 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
2558 if (cmp_clid(&clp->cl_clientid, clid)) {
2559 client = clp;
2560 break;
2563 if (!client)
2564 return NULL;
2566 /* find clp->cl_name in reclaim_str_hashtbl */
2567 strhashval = clientstr_hashval(client->cl_name.data,
2568 client->cl_name.len);
2569 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
2570 if (cmp_name(&crp->cr_name, &client->cl_name)) {
2571 return crp;
2574 return NULL;
2578 * Called from OPEN. Look for clientid in reclaim list.
2581 nfs4_check_open_reclaim(clientid_t *clid)
2583 struct nfs4_client_reclaim *crp;
2585 if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
2586 return nfserr_reclaim_bad;
2587 if (crp->cr_expired)
2588 return nfserr_no_grace;
2589 return nfs_ok;
2594 * Start and stop routines
2597 void
2598 nfs4_state_init(void)
2600 int i;
2601 time_t grace_time;
2603 if (nfs4_init)
2604 return;
2605 if (!nfs4_reclaim_init) {
2606 for (i = 0; i < CLIENT_HASH_SIZE; i++)
2607 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
2608 reclaim_str_hashtbl_size = 0;
2609 nfs4_reclaim_init = 1;
2611 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2612 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
2613 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
2614 INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
2615 INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
2617 for (i = 0; i < FILE_HASH_SIZE; i++) {
2618 INIT_LIST_HEAD(&file_hashtbl[i]);
2620 for (i = 0; i < OWNER_HASH_SIZE; i++) {
2621 INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
2622 INIT_LIST_HEAD(&ownerid_hashtbl[i]);
2624 for (i = 0; i < STATEID_HASH_SIZE; i++) {
2625 INIT_LIST_HEAD(&stateid_hashtbl[i]);
2626 INIT_LIST_HEAD(&lockstateid_hashtbl[i]);
2628 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2629 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
2630 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
2632 memset(&zerostateid, 0, sizeof(stateid_t));
2633 memset(&onestateid, ~0, sizeof(stateid_t));
2635 INIT_LIST_HEAD(&close_lru);
2636 INIT_LIST_HEAD(&client_lru);
2637 boot_time = get_seconds();
2638 grace_time = max(old_lease_time, lease_time);
2639 if (reclaim_str_hashtbl_size == 0)
2640 grace_time = 0;
2641 if (grace_time)
2642 printk("NFSD: starting %ld-second grace period\n", grace_time);
2643 grace_end = boot_time + grace_time;
2644 INIT_WORK(&laundromat_work,laundromat_main, NULL);
2645 schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
2646 nfs4_init = 1;
2650 nfs4_in_grace(void)
2652 return get_seconds() < grace_end;
2655 void
2656 set_no_grace(void)
2658 printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
2659 grace_end = get_seconds();
2662 time_t
2663 nfs4_lease_time(void)
2665 return lease_time;
2668 static void
2669 __nfs4_state_shutdown(void)
2671 int i;
2672 struct nfs4_client *clp = NULL;
2674 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2675 while (!list_empty(&conf_id_hashtbl[i])) {
2676 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
2677 expire_client(clp);
2679 while (!list_empty(&unconf_str_hashtbl[i])) {
2680 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
2681 expire_client(clp);
2684 release_all_files();
2685 cancel_delayed_work(&laundromat_work);
2686 flush_scheduled_work();
2687 nfs4_init = 0;
2688 dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
2689 list_add_perfile, list_del_perfile);
2690 dprintk("NFSD: add_perclient %d del_perclient %d\n",
2691 add_perclient, del_perclient);
2692 dprintk("NFSD: alloc_file %d free_file %d\n",
2693 alloc_file, free_file);
2694 dprintk("NFSD: alloc_sowner %d alloc_lsowner %d free_sowner %d\n",
2695 alloc_sowner, alloc_lsowner, free_sowner);
2696 dprintk("NFSD: vfsopen %d vfsclose %d\n",
2697 vfsopen, vfsclose);
2700 void
2701 nfs4_state_shutdown(void)
2703 nfs4_lock_state();
2704 nfs4_release_reclaim();
2705 __nfs4_state_shutdown();
2706 nfs4_unlock_state();
2710 * Called when leasetime is changed.
2712 * if nfsd is not started, simply set the global lease.
2714 * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
2715 * e.g: boot_time is reset, existing nfs4_client structs are
2716 * used to fill reclaim_str_hashtbl, then all state (except for the
2717 * reclaim_str_hashtbl) is re-initialized.
2719 * if the old lease time is greater than the new lease time, the grace
2720 * period needs to be set to the old lease time to allow clients to reclaim
2721 * their state. XXX - we may want to set the grace period == lease time
2722 * after an initial grace period == old lease time
2724 * if an error occurs in this process, the new lease is set, but the server
2725 * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
2726 * which means OPEN/LOCK/READ/WRITE will fail during grace period.
2728 * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
2729 * OPEN and LOCK reclaims.
2731 void
2732 nfs4_reset_lease(time_t leasetime)
2734 struct nfs4_client *clp;
2735 int i;
2737 printk("NFSD: New leasetime %ld\n",leasetime);
2738 if (!nfs4_init)
2739 return;
2740 nfs4_lock_state();
2741 old_lease_time = lease_time;
2742 lease_time = leasetime;
2744 nfs4_release_reclaim();
2746 /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
2747 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2748 list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
2749 if (!nfs4_client_to_reclaim(clp)) {
2750 nfs4_release_reclaim();
2751 goto init_state;
2753 reclaim_str_hashtbl_size++;
2756 init_state:
2757 __nfs4_state_shutdown();
2758 nfs4_state_init();
2759 nfs4_unlock_state();