0d485189c92d79eaf686ce10e2dd1066833aa228
[linux-flexiantxendom0-3.2.10.git] / fs / nfsd / nfs4state.c
1 /*
2 *  linux/fs/nfsd/nfs4state.c
3 *
4 *  Copyright (c) 2001 The Regents of the University of Michigan.
5 *  All rights reserved.
6 *
7 *  Kendrick Smith <kmsmith@umich.edu>
8 *  Andy Adamson <kandros@umich.edu>
9 *
10 *  Redistribution and use in source and binary forms, with or without
11 *  modification, are permitted provided that the following conditions
12 *  are met:
13 *
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.
22 *
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.
34 *
35 */
36
37 #include <linux/param.h>
38 #include <linux/major.h>
39 #include <linux/slab.h>
40
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/nfs4.h>
47 #include <linux/nfsd/state.h>
48 #include <linux/nfsd/xdr4.h>
49
50 #define NFSDDBG_FACILITY                NFSDDBG_PROC
51
52 /* Globals */
53 time_t boot_time;
54 static u32 current_clientid = 1;
55 static u32 current_ownerid;
56 static u32 current_fileid;
57 static u32 nfs4_init;
58 stateid_t zerostateid;             /* bits all 0 */
59 stateid_t onestateid;              /* bits all 1 */
60
61 /* debug counters */
62 u32 list_add_perfile = 0; 
63 u32 list_del_perfile = 0;
64 u32 add_perclient = 0;
65 u32 del_perclient = 0;
66 u32 alloc_file = 0;
67 u32 free_file = 0;
68 u32 alloc_sowner = 0;
69 u32 free_sowner = 0;
70 u32 vfsopen = 0;
71 u32 vfsclose = 0;
72 u32 alloc_lsowner= 0;
73
74 /* forward declarations */
75 struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
76
77 /* Locking:
78  *
79  * client_sema: 
80  *      protects clientid_hashtbl[], clientstr_hashtbl[],
81  *      unconfstr_hashtbl[], uncofid_hashtbl[].
82  */
83 static struct semaphore client_sema;
84
85 void
86 nfs4_lock_state(void)
87 {
88         down(&client_sema);
89 }
90
91 void
92 nfs4_unlock_state(void)
93 {
94         up(&client_sema);
95 }
96
97 static inline u32
98 opaque_hashval(const void *ptr, int nbytes)
99 {
100         unsigned char *cptr = (unsigned char *) ptr;
101
102         u32 x = 0;
103         while (nbytes--) {
104                 x *= 37;
105                 x += *cptr++;
106         }
107         return x;
108 }
109
110 /* forward declarations */
111 static void release_stateowner(struct nfs4_stateowner *sop);
112 static void release_stateid(struct nfs4_stateid *stp, int flags);
113 static void release_file(struct nfs4_file *fp);
114
115
116 /* 
117  * SETCLIENTID state 
118  */
119
120 /* Hash tables for nfs4_clientid state */
121 #define CLIENT_HASH_BITS                 4
122 #define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
123 #define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
124
125 #define clientid_hashval(id) \
126         ((id) & CLIENT_HASH_MASK)
127 #define clientstr_hashval(name, namelen) \
128         (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
129
130 /* conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
131  * setclientid_confirmed info. 
132  *
133  * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed 
134  * setclientid info.
135  *
136  * client_lru holds client queue ordered by nfs4_client.cl_time
137  * for lease renewal.
138  */
139 static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE];
140 static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE];
141 static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE];
142 static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
143 static struct list_head client_lru;
144
145 static inline void
146 renew_client(struct nfs4_client *clp)
147 {
148         /*
149         * Move client to the end to the LRU list.
150         */
151         dprintk("renewing client (clientid %08x/%08x)\n", 
152                         clp->cl_clientid.cl_boot, 
153                         clp->cl_clientid.cl_id);
154         list_move_tail(&clp->cl_lru, &client_lru);
155         clp->cl_time = get_seconds();
156 }
157
158 /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
159 static int
160 STALE_CLIENTID(clientid_t *clid)
161 {
162         if (clid->cl_boot == boot_time)
163                 return 0;
164         dprintk("NFSD stale clientid (%08x/%08x)\n", 
165                         clid->cl_boot, clid->cl_id);
166         return 1;
167 }
168
169 /* 
170  * XXX Should we use a slab cache ?
171  * This type of memory management is somewhat inefficient, but we use it
172  * anyway since SETCLIENTID is not a common operation.
173  */
174 static inline struct nfs4_client *
175 alloc_client(struct xdr_netobj name)
176 {
177         struct nfs4_client *clp;
178
179         if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
180                 memset(clp, 0, sizeof(*clp));
181                 if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
182                         memcpy(clp->cl_name.data, name.data, name.len);
183                         clp->cl_name.len = name.len;
184                 }
185                 else {
186                         kfree(clp);
187                         clp = NULL;
188                 }
189         }
190         return clp;
191 }
192
193 static inline void
194 free_client(struct nfs4_client *clp)
195 {
196         kfree(clp->cl_name.data);
197         kfree(clp);
198 }
199
200 static void
201 expire_client(struct nfs4_client *clp)
202 {
203         struct nfs4_stateowner *sop;
204
205         dprintk("NFSD: expire_client\n");
206         list_del(&clp->cl_idhash);
207         list_del(&clp->cl_strhash);
208         list_del(&clp->cl_lru);
209         while (!list_empty(&clp->cl_perclient)) {
210                 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
211                 release_stateowner(sop);
212         }
213         free_client(clp);
214 }
215
216 static struct nfs4_client *
217 create_client(struct xdr_netobj name) {
218         struct nfs4_client *clp;
219
220         if(!(clp = alloc_client(name)))
221                 goto out;
222         INIT_LIST_HEAD(&clp->cl_idhash);
223         INIT_LIST_HEAD(&clp->cl_strhash);
224         INIT_LIST_HEAD(&clp->cl_perclient);
225         INIT_LIST_HEAD(&clp->cl_lru);
226 out:
227         return clp;
228 }
229
230 static void
231 copy_verf(struct nfs4_client *target, nfs4_verifier *source) {
232         memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data));
233 }
234
235 static void
236 copy_clid(struct nfs4_client *target, struct nfs4_client *source) {
237         target->cl_clientid.cl_boot = source->cl_clientid.cl_boot; 
238         target->cl_clientid.cl_id = source->cl_clientid.cl_id; 
239 }
240
241 static void
242 copy_cred(struct svc_cred *target, struct svc_cred *source) {
243         int i;
244
245         target->cr_uid = source->cr_uid;
246         target->cr_gid = source->cr_gid;
247         for(i = 0; i < NGROUPS; i++)
248                 target->cr_groups[i] = source->cr_groups[i];
249 }
250
251 static int
252 cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
253         if(!n1 || !n2)
254                 return 0;
255         return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
256 }
257
258 static int
259 cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) {
260         return(!memcmp(v1->data,v2->data,sizeof(v1->data)));
261 }
262
263 static int
264 cmp_clid(clientid_t * cl1, clientid_t * cl2) {
265         return((cl1->cl_boot == cl2->cl_boot) &&
266                 (cl1->cl_id == cl2->cl_id));
267 }
268
269 /* XXX what about NGROUP */
270 static int
271 cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){
272         return((cr1->cr_uid == cr2->cr_uid) &&
273                 (cr1->cr_gid == cr2->cr_gid));
274
275 }
276
277 static void
278 gen_clid(struct nfs4_client *clp) {
279         clp->cl_clientid.cl_boot = boot_time;
280         clp->cl_clientid.cl_id = current_clientid++; 
281 }
282
283 static void
284 gen_confirm(struct nfs4_client *clp) {
285         struct timespec         tv;
286         u32 *                   p;
287
288         tv = CURRENT_TIME;
289         p = (u32 *)clp->cl_confirm.data;
290         *p++ = tv.tv_sec;
291         *p++ = tv.tv_nsec;
292 }
293
294 static int
295 check_name(struct xdr_netobj name) {
296
297         if (name.len == 0) 
298                 return 0;
299         if (name.len > NFS4_OPAQUE_LIMIT) {
300                 printk("NFSD: check_name: name too long(%d)!\n", name.len);
301                 return 0;
302         }
303         return 1;
304 }
305
306 void
307 add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
308 {
309         unsigned int idhashval;
310
311         list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
312         idhashval = clientid_hashval(clp->cl_clientid.cl_id);
313         list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
314         list_add_tail(&clp->cl_lru, &client_lru);
315         clp->cl_time = get_seconds();
316 }
317
318 void
319 move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
320 {
321         unsigned int strhashval;
322
323         dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
324         list_del_init(&clp->cl_strhash);
325         list_del_init(&clp->cl_idhash);
326         list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
327         strhashval = clientstr_hashval(clp->cl_name.data, 
328                         clp->cl_name.len);
329         list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
330         renew_client(clp);
331 }
332
333 /*
334  * RFC 3010 has a complex implmentation description of processing a 
335  * SETCLIENTID request consisting of 5 bullets, labeled as 
336  * CASE0 - CASE4 below.
337  *
338  * NOTES:
339  *      callback information will be processed in a future patch
340  *
341  *      an unconfirmed record is added when:
342  *      NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record.
343  *      CASE 1: confirmed record found with matching name, principal,
344  *              verifier, and clientid.
345  *      CASE 2: confirmed record found with matching name, principal,
346  *              and there is no unconfirmed record with matching
347  *              name and principal
348  *
349  *      an unconfirmed record is replaced when:
350  *      CASE 3: confirmed record found with matching name, principal,
351  *              and an unconfirmed record is found with matching 
352  *              name, principal, and with clientid and
353  *              confirm that does not match the confirmed record.
354  *      CASE 4: there is no confirmed record with matching name and 
355  *              principal. there is an unconfirmed record with 
356  *              matching name, principal.
357  *
358  *      an unconfirmed record is deleted when:
359  *      CASE 1: an unconfirmed record that matches input name, verifier,
360  *              and confirmed clientid.
361  *      CASE 4: any unconfirmed records with matching name and principal
362  *              that exist after an unconfirmed record has been replaced
363  *              as described above.
364  *
365  */
366 int
367 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
368 {
369         u32                     ip_addr = rqstp->rq_addr.sin_addr.s_addr;
370         struct xdr_netobj       clname = { 
371                 .len = setclid->se_namelen,
372                 .data = setclid->se_name,
373         };
374         nfs4_verifier           clverifier = setclid->se_verf;
375         unsigned int            strhashval;
376         struct nfs4_client *    conf, * unconf, * new, * clp;
377         int                     status;
378         struct list_head *pos, *next;
379         
380         status = nfserr_inval;
381         if (!check_name(clname))
382                 goto out;
383
384         /* 
385          * XXX The Duplicate Request Cache (DRC) has been checked (??)
386          * We get here on a DRC miss.
387          */
388
389         strhashval = clientstr_hashval(clname.data, clname.len);
390
391         conf = NULL;
392         nfs4_lock_state();
393         list_for_each_safe(pos, next, &conf_str_hashtbl[strhashval]) {
394                 clp = list_entry(pos, struct nfs4_client, cl_strhash);
395                 if (!cmp_name(&clp->cl_name, &clname))
396                         continue;
397                 /* 
398                  * CASE 0:
399                  * clname match, confirmed, different principal
400                  * or different ip_address
401                  */
402                 status = nfserr_clid_inuse;
403                 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
404                         printk("NFSD: setclientid: string in use by client"
405                         "(clientid %08x/%08x)\n",
406                         clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
407                         goto out;
408                 }
409                 if (clp->cl_addr != ip_addr) { 
410                         printk("NFSD: setclientid: string in use by client"
411                         "(clientid %08x/%08x)\n",
412                         clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
413                         goto out;
414                 }
415
416                 /* 
417                  * cl_name match from a previous SETCLIENTID operation
418                  * XXX check for additional matches?
419                  */
420                 conf = clp;
421                 break;
422         }
423         unconf = NULL;
424         list_for_each_safe(pos, next, &unconf_str_hashtbl[strhashval]) {
425                 clp = list_entry(pos, struct nfs4_client, cl_strhash);
426                 if (!cmp_name(&clp->cl_name, &clname))
427                         continue;
428                 /* cl_name match from a previous SETCLIENTID operation */
429                 unconf = clp;
430                 break;
431         }
432         status = nfserr_resource;
433         if (!conf) {
434                 /* 
435                  * CASE 4:
436                  * placed first, because it is the normal case.
437                  */
438                 if (unconf)
439                         expire_client(unconf);
440                 if (!(new = create_client(clname)))
441                         goto out;
442                 copy_verf(new, &clverifier);
443                 new->cl_addr = ip_addr;
444                 copy_cred(&new->cl_cred,&rqstp->rq_cred);
445                 gen_clid(new);
446                 gen_confirm(new);
447                 add_to_unconfirmed(new, strhashval);
448         } else if (cmp_verf(&conf->cl_verifier, &clverifier)) {
449                 /*
450                  * CASE 1:
451                  * cl_name match, confirmed, principal match
452                  * verifier match: probable callback update
453                  *
454                  * remove any unconfirmed nfs4_client with 
455                  * matching cl_name, cl_verifier, and cl_clientid
456                  *
457                  * create and insert an unconfirmed nfs4_client with same 
458                  * cl_name, cl_verifier, and cl_clientid as existing 
459                  * nfs4_client,  but with the new callback info and a 
460                  * new cl_confirm
461                  */
462                 if ((unconf) && 
463                     cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
464                      cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
465                                 expire_client(unconf);
466                 }
467                 if (!(new = create_client(clname)))
468                         goto out;
469                 copy_verf(new,&conf->cl_verifier);
470                 new->cl_addr = ip_addr;
471                 copy_cred(&new->cl_cred,&rqstp->rq_cred);
472                 copy_clid(new, conf);
473                 gen_confirm(new);
474                 add_to_unconfirmed(new,strhashval);
475         } else if (!unconf) {
476                 /*
477                  * CASE 2:
478                  * clname match, confirmed, principal match
479                  * verfier does not match
480                  * no unconfirmed. create a new unconfirmed nfs4_client
481                  * using input clverifier, clname, and callback info
482                  * and generate a new cl_clientid and cl_confirm.
483                  */
484                 if (!(new = create_client(clname)))
485                         goto out;
486                 copy_verf(new,&clverifier);
487                 new->cl_addr = ip_addr;
488                 copy_cred(&new->cl_cred,&rqstp->rq_cred);
489                 gen_clid(new);
490                 gen_confirm(new);
491                 add_to_unconfirmed(new, strhashval);
492         } else if (!cmp_clid(&conf->cl_clientid, &unconf->cl_clientid) &&
493               !cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
494                 /*      
495                  * CASE3:
496                  * confirmed found (name, principal match)
497                  * confirmed verifier does not match input clverifier
498                  *
499                  * unconfirmed found (name match)
500                  * confirmed->cl_clientid != unconfirmed->cl_clientid and
501                  * confirmed->cl_confirm != unconfirmed->cl_confirm
502                  *
503                  * remove unconfirmed.
504                  *
505                  * create an unconfirmed nfs4_client 
506                  * with same cl_name as existing confirmed nfs4_client, 
507                  * but with new callback info, new cl_clientid,
508                  * new cl_verifier and a new cl_confirm
509                  */
510                 expire_client(unconf);
511                 if (!(new = create_client(clname)))
512                         goto out;
513                 copy_verf(new,&clverifier);
514                 new->cl_addr = ip_addr;
515                 copy_cred(&new->cl_cred,&rqstp->rq_cred);
516                 gen_clid(new);
517                 gen_confirm(new);
518                 add_to_unconfirmed(new, strhashval);
519         } else {
520                 /* No cases hit !!! */
521                 status = nfserr_inval;
522                 goto out;
523
524         }
525         setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
526         setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
527         memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
528         printk(KERN_INFO "NFSD: this client will not receive delegations\n");
529         status = nfs_ok;
530 out:
531         nfs4_unlock_state();
532         return status;
533 }
534
535
536 /*
537  * RFC 3010 has a complex implmentation description of processing a 
538  * SETCLIENTID_CONFIRM request consisting of 4 bullets describing
539  * processing on a DRC miss, labeled as CASE1 - CASE4 below.
540  *
541  * NOTE: callback information will be processed here in a future patch
542  */
543 int
544 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
545 {
546         u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
547         unsigned int idhashval;
548         struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
549         nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
550         clientid_t * clid = &setclientid_confirm->sc_clientid;
551         struct list_head *pos, *next;
552         int status;
553
554         status = nfserr_stale_clientid;
555         if (STALE_CLIENTID(clid))
556                 goto out;
557         /* 
558          * XXX The Duplicate Request Cache (DRC) has been checked (??)
559          * We get here on a DRC miss.
560          */
561
562         idhashval = clientid_hashval(clid->cl_id);
563         nfs4_lock_state();
564         list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
565                 clp = list_entry(pos, struct nfs4_client, cl_idhash);
566                 if (!cmp_clid(&clp->cl_clientid, clid))
567                         continue;
568
569                 status = nfserr_inval;
570                 /* 
571                  * Found a record for this clientid. If the IP addresses
572                  * don't match, return ERR_INVAL just as if the record had
573                  * not been found.
574                  */
575                 if (clp->cl_addr != ip_addr) { 
576                         printk("NFSD: setclientid: string in use by client"
577                         "(clientid %08x/%08x)\n",
578                         clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
579                         goto out;
580                 }
581                 conf = clp;
582                 break;
583         }
584         list_for_each_safe(pos, next, &unconf_id_hashtbl[idhashval]) {
585                 clp = list_entry(pos, struct nfs4_client, cl_idhash);
586                 if (!cmp_clid(&clp->cl_clientid, clid))
587                         continue;
588                 status = nfserr_inval;
589                 if (clp->cl_addr != ip_addr) { 
590                         printk("NFSD: setclientid: string in use by client"
591                         "(clientid %08x/%08x)\n",
592                         clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
593                         goto out;
594                 }
595                 unconf = clp;
596                 break;
597         }
598         /* CASE 1: 
599         * unconf record that matches input clientid and input confirm.
600         * conf record that matches input clientid.
601         * conf  and unconf records match names, verifiers 
602         */
603         if ((conf && unconf) && 
604             (cmp_verf(&unconf->cl_confirm, &confirm)) &&
605             (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
606             (cmp_name(&conf->cl_name,&unconf->cl_name))  &&
607             (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
608                 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
609                         status = nfserr_clid_inuse;
610                 else {
611                         expire_client(conf);
612                         move_to_confirmed(unconf, idhashval);
613                         status = nfs_ok;
614                 }
615                 goto out;
616         } 
617         /* CASE 2:
618          * conf record that matches input clientid.
619          * if unconf record that matches input clientid, then unconf->cl_name
620          * or unconf->cl_verifier don't match the conf record.
621          */
622         if ((conf && !unconf) || 
623             ((conf && unconf) && 
624              (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
625               !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
626                 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
627                         status = nfserr_clid_inuse;
628                 } else {
629                         status = nfs_ok;
630                 }
631                 goto out;
632         }
633         /* CASE 3:
634          * conf record not found.
635          * unconf record found. 
636          * unconf->cl_confirm matches input confirm
637          */ 
638         if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
639                 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
640                         status = nfserr_clid_inuse;
641                 } else {
642                         status = nfs_ok;
643                         move_to_confirmed(unconf, idhashval);
644                 }
645                 goto out;
646         }
647         /* CASE 4:
648          * conf record not found, or if conf, then conf->cl_confirm does not
649          * match input confirm.
650          * unconf record not found, or if unconf, then unconf->cl_confirm 
651          * does not match input confirm.
652          */
653         if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
654             (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
655                 status = nfserr_stale_clientid;
656                 goto out;
657         }
658         /* check that we have hit one of the cases...*/
659         status = nfserr_inval;
660         goto out;
661 out:
662         /* XXX if status == nfs_ok, probe callback path */
663         nfs4_unlock_state();
664         return status;
665 }
666
667 /* 
668  * Open owner state (share locks)
669  */
670
671 /* hash tables for nfs4_stateowner */
672 #define OWNER_HASH_BITS              8
673 #define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
674 #define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
675
676 #define ownerid_hashval(id) \
677         ((id) & OWNER_HASH_MASK)
678 #define ownerstr_hashval(clientid, ownername) \
679         (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
680
681 static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
682 static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
683
684 /* hash table for nfs4_file */
685 #define FILE_HASH_BITS                   8
686 #define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
687 #define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
688 /* hash table for (open)nfs4_stateid */
689 #define STATEID_HASH_BITS              10
690 #define STATEID_HASH_SIZE              (1 << STATEID_HASH_BITS)
691 #define STATEID_HASH_MASK              (STATEID_HASH_SIZE - 1)
692
693 #define file_hashval(x) \
694         hash_ptr(x, FILE_HASH_BITS)
695 #define stateid_hashval(owner_id, file_id)  \
696         (((owner_id) + (file_id)) & STATEID_HASH_MASK)
697
698 static struct list_head file_hashtbl[FILE_HASH_SIZE];
699 static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
700
701 /* OPEN Share state helper functions */
702 static inline struct nfs4_file *
703 alloc_init_file(unsigned int hashval, struct inode *ino) {
704         struct nfs4_file *fp;
705         if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
706                 INIT_LIST_HEAD(&fp->fi_hash);
707                 INIT_LIST_HEAD(&fp->fi_perfile);
708                 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
709                 fp->fi_inode = igrab(ino);
710                 fp->fi_id = current_fileid++;
711                 alloc_file++;
712                 return fp;
713         }
714         return (struct nfs4_file *)NULL;
715 }
716
717 static void
718 release_all_files(void)
719 {
720         int i;
721         struct nfs4_file *fp;
722
723         for (i=0;i<FILE_HASH_SIZE;i++) {
724                 while (!list_empty(&file_hashtbl[i])) {
725                         fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
726                         /* this should never be more than once... */
727                         if(!list_empty(&fp->fi_perfile)) {
728                                 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
729                         }
730                         release_file(fp);
731                 }
732         }
733 }
734
735 static inline struct nfs4_stateowner *
736 alloc_stateowner(struct xdr_netobj *owner)
737 {
738         struct nfs4_stateowner *sop;
739
740         if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
741                 if((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
742                         memcpy(sop->so_owner.data, owner->data, owner->len);
743                         sop->so_owner.len = owner->len;
744                         return sop;
745                 } 
746                 kfree(sop);
747         }
748         return (struct nfs4_stateowner *)NULL;
749 }
750
751 /* should use a slab cache */
752 static void
753 free_stateowner(struct nfs4_stateowner *sop) {
754         if(sop) {
755                 kfree(sop->so_owner.data);
756                 kfree(sop);
757                 sop = NULL;
758                 free_sowner++;
759         }
760 }
761
762 static struct nfs4_stateowner *
763 alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
764         struct nfs4_stateowner *sop;
765         struct nfs4_replay *rp;
766         unsigned int idhashval;
767
768         if (!(sop = alloc_stateowner(&open->op_owner)))
769                 return (struct nfs4_stateowner *)NULL;
770         idhashval = ownerid_hashval(current_ownerid);
771         INIT_LIST_HEAD(&sop->so_idhash);
772         INIT_LIST_HEAD(&sop->so_strhash);
773         INIT_LIST_HEAD(&sop->so_perclient);
774         INIT_LIST_HEAD(&sop->so_perfilestate);
775         list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
776         list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
777         list_add(&sop->so_perclient, &clp->cl_perclient);
778         add_perclient++;
779         sop->so_is_open_owner = 1;
780         sop->so_id = current_ownerid++;
781         sop->so_client = clp;
782         sop->so_seqid = open->op_seqid;
783         sop->so_confirmed = 0;
784         rp = &sop->so_replay;
785         rp->rp_status = NFSERR_SERVERFAULT;
786         rp->rp_buflen = 0;
787         rp->rp_buf = rp->rp_ibuf;
788         alloc_sowner++;
789         return sop;
790 }
791
792 static void
793 release_stateowner(struct nfs4_stateowner *sop)
794 {
795         struct nfs4_stateid *stp;
796
797         list_del_init(&sop->so_idhash);
798         list_del_init(&sop->so_strhash);
799         list_del_init(&sop->so_perclient);
800         del_perclient++;
801         while (!list_empty(&sop->so_perfilestate)) {
802                 stp = list_entry(sop->so_perfilestate.next, 
803                         struct nfs4_stateid, st_perfilestate);
804                 if(sop->so_is_open_owner)
805                         release_stateid(stp, OPEN_STATE);
806                 else
807                         release_stateid(stp, LOCK_STATE);
808         }
809         free_stateowner(sop);
810 }
811
812 static inline void
813 init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
814         unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
815
816         INIT_LIST_HEAD(&stp->st_hash);
817         INIT_LIST_HEAD(&stp->st_perfilestate);
818         INIT_LIST_HEAD(&stp->st_perfile);
819         list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
820         list_add(&stp->st_perfilestate, &sop->so_perfilestate);
821         list_add_perfile++;
822         list_add(&stp->st_perfile, &fp->fi_perfile);
823         stp->st_stateowner = sop;
824         stp->st_file = fp;
825         stp->st_stateid.si_boot = boot_time;
826         stp->st_stateid.si_stateownerid = sop->so_id;
827         stp->st_stateid.si_fileid = fp->fi_id;
828         stp->st_stateid.si_generation = 0;
829         stp->st_share_access = open->op_share_access;
830         stp->st_share_deny = open->op_share_deny;
831 }
832
833 static void
834 release_stateid(struct nfs4_stateid *stp, int flags) {
835
836         list_del_init(&stp->st_hash);
837         list_del_perfile++;
838         list_del_init(&stp->st_perfile);
839         list_del_init(&stp->st_perfilestate);
840         if((stp->st_vfs_set) && (flags & OPEN_STATE)) {
841                 nfsd_close(&stp->st_vfs_file);
842                 vfsclose++;
843                 dput(stp->st_vfs_file.f_dentry);
844                 mntput(stp->st_vfs_file.f_vfsmnt);
845         }
846         /* should use a slab cache */
847         kfree(stp);
848         stp = NULL;
849 }
850
851 static void
852 release_file(struct nfs4_file *fp)
853 {
854         free_file++;
855         list_del_init(&fp->fi_hash);
856         iput(fp->fi_inode);
857         kfree(fp);
858 }       
859
860 void
861 release_state_owner(struct nfs4_stateid *stp, struct nfs4_stateowner **sopp,
862                 int flag)
863 {
864         struct nfs4_stateowner *sop = stp->st_stateowner;
865         struct nfs4_file *fp = stp->st_file;
866
867         dprintk("NFSD: release_state_owner\n");
868         release_stateid(stp, flag);
869         /*
870          * release unused nfs4_stateowners.
871          * XXX will need to be placed  on an  open_stateid_lru list to be
872          * released by the laundromat service after the lease period
873          * to enable us to handle CLOSE replay
874          */
875         if (sop->so_confirmed && list_empty(&sop->so_perfilestate)) {
876                 release_stateowner(sop);
877                 *sopp = NULL;
878         }
879         /* unused nfs4_file's are releseed. XXX slab cache? */
880         if (list_empty(&fp->fi_perfile)) {
881                 release_file(fp);
882         }
883 }
884
885 static int
886 cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
887         return ((sop->so_owner.len == owner->len) && 
888          !memcmp(sop->so_owner.data, owner->data, owner->len) && 
889           (sop->so_client->cl_clientid.cl_id == clid->cl_id));
890 }
891
892 /* search ownerstr_hashtbl[] for owner */
893 static int
894 find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
895         struct list_head *pos, *next;
896         struct nfs4_stateowner *local = NULL;
897
898         list_for_each_safe(pos, next, &ownerstr_hashtbl[hashval]) {
899                 local = list_entry(pos, struct nfs4_stateowner, so_strhash);
900                 if(!cmp_owner_str(local, &open->op_owner, &open->op_clientid)) 
901                         continue;
902                 *op = local;
903                 return(1);
904         }
905         return 0;
906 }
907
908 /* see if clientid is in confirmed hash table */
909 static int
910 verify_clientid(struct nfs4_client **client, clientid_t *clid) {
911
912         struct list_head *pos, *next;
913         struct nfs4_client *clp;
914         unsigned int idhashval = clientid_hashval(clid->cl_id);
915
916         list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
917                 clp = list_entry(pos, struct nfs4_client, cl_idhash);
918                 if (!cmp_clid(&clp->cl_clientid, clid))
919                         continue;
920                 *client = clp;
921                 return 1;
922         }
923         *client = NULL;
924         return 0;
925 }
926
927 /* search file_hashtbl[] for file */
928 static int
929 find_file(unsigned int hashval, struct inode *ino, struct nfs4_file **fp) {
930         struct list_head *pos, *next;
931         struct nfs4_file *local = NULL;
932
933         list_for_each_safe(pos, next, &file_hashtbl[hashval]) {
934                 local = list_entry(pos, struct nfs4_file, fi_hash);
935                 if (local->fi_inode == ino) {
936                         *fp = local;
937                         return(1);
938                 }
939         }
940         return 0;
941 }
942
943 static int
944 test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
945         if ((stp->st_share_access & open->op_share_deny) ||
946             (stp->st_share_deny & open->op_share_access)) {
947                 return 0;
948         }
949         return 1;
950 }
951
952 int
953 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
954 {
955         struct inode *ino = current_fh->fh_dentry->d_inode;
956         unsigned int fi_hashval;
957         struct nfs4_file *fp;
958         struct nfs4_stateid *stp;
959         struct list_head *pos, *next;
960
961         dprintk("NFSD: nfs4_share_conflict\n");
962
963         fi_hashval = file_hashval(ino);
964         if (find_file(fi_hashval, ino, &fp)) {
965         /* Search for conflicting share reservations */
966                 list_for_each_safe(pos, next, &fp->fi_perfile) {
967                         stp = list_entry(pos, struct nfs4_stateid, st_perfile);
968                         if (stp->st_share_deny & deny_type)
969                                 return nfserr_share_denied;
970                 }
971         }
972         return nfs_ok;
973 }
974
975 static inline int
976 nfs4_file_upgrade(struct file *filp, unsigned int share_access)
977 {
978 int status;
979
980         if (share_access & NFS4_SHARE_ACCESS_WRITE) {
981                 status = get_write_access(filp->f_dentry->d_inode);
982                 if (!status)
983                         filp->f_mode = FMODE_WRITE;
984                 else
985                         return nfserrno(status);
986         }
987         return nfs_ok;
988 }
989
990 static inline void
991 nfs4_file_downgrade(struct file *filp, unsigned int share_access)
992 {
993         if (share_access & NFS4_SHARE_ACCESS_WRITE) {
994                 put_write_access(filp->f_dentry->d_inode);
995                 filp->f_mode = FMODE_READ;
996         }
997 }
998
999
1000 /*
1001  * nfsd4_process_open1()
1002  *      lookup stateowner.
1003  *              found:
1004  *                      check confirmed 
1005  *                              confirmed:
1006  *                                      check seqid
1007  *                              not confirmed:
1008  *                                      delete owner
1009  *                                      create new owner
1010  *              notfound:
1011  *                      verify clientid
1012  *                      create new owner
1013  */
1014 int
1015 nfsd4_process_open1(struct nfsd4_open *open)
1016 {
1017         int status;
1018         clientid_t *clientid = &open->op_clientid;
1019         struct nfs4_client *clp = NULL;
1020         unsigned int strhashval;
1021         struct nfs4_stateowner *sop = NULL;
1022
1023         status = nfserr_inval;
1024         if (!check_name(open->op_owner))
1025                 goto out;
1026
1027         status = nfserr_stale_clientid;
1028         if (STALE_CLIENTID(&open->op_clientid))
1029                 goto out;
1030
1031         nfs4_lock_state();
1032         strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1033         if (find_openstateowner_str(strhashval, open, &sop)) {
1034                 open->op_stateowner = sop;
1035                 /* check for replay */
1036                 if (open->op_seqid == sop->so_seqid){
1037                         if (!sop->so_replay.rp_buflen) {
1038                         /*
1039                         * The original OPEN failed in so spectacularly that we
1040                         * don't even have replay data saved!  Therefore, we
1041                         * have no choice but to continue processing
1042                         * this OPEN; presumably, we'll fail again for the same
1043                         * reason.
1044                         */
1045                                 dprintk("nfsd4_process_open1: replay with no replay cache\n");
1046                                 status = NFS_OK;
1047                                 goto renew;
1048                         }
1049                         /* replay: indicate to calling function */
1050                         status = NFSERR_REPLAY_ME;
1051                         goto out;
1052                 }
1053                 if (sop->so_confirmed) {
1054                         if (open->op_seqid == sop->so_seqid + 1) { 
1055                                 status = nfs_ok;
1056                                 goto renew;
1057                         } 
1058                         status = nfserr_bad_seqid;
1059                         goto out;
1060                 }
1061                 /* If we get here, we received and OPEN for an unconfirmed
1062                  * nfs4_stateowner. 
1063                  * Since the sequid's are different, purge the 
1064                  * existing nfs4_stateowner, and instantiate a new one.
1065                  */
1066                 clp = sop->so_client;
1067                 release_stateowner(sop);
1068                 goto instantiate_new_owner;
1069         } 
1070         /* nfs4_stateowner not found. 
1071         * verify clientid and instantiate new nfs4_stateowner
1072         * if verify fails this is presumably the result of the 
1073         * client's lease expiring.
1074         *
1075         * XXX compare clp->cl_addr with rqstp addr? 
1076         */
1077         status = nfserr_expired;
1078         if (!verify_clientid(&clp, clientid))
1079                 goto out;
1080 instantiate_new_owner:
1081         status = nfserr_resource;
1082         if (!(sop = alloc_init_open_stateowner(strhashval, clp, open))) 
1083                 goto out;
1084         open->op_stateowner = sop;
1085         status = nfs_ok;
1086 renew:
1087         renew_client(sop->so_client);
1088 out:
1089         nfs4_unlock_state();
1090         return status;
1091 }
1092
1093 int
1094 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
1095 {
1096         struct iattr iattr;
1097         struct nfs4_stateowner *sop = open->op_stateowner;
1098         struct nfs4_file *fp;
1099         struct inode *ino;
1100         unsigned int fi_hashval;
1101         struct list_head *pos, *next;
1102         struct nfs4_stateid *stq, *stp = NULL;
1103         int status;
1104
1105         status = nfserr_resource;
1106         if (!sop)
1107                 goto out;
1108
1109         ino = current_fh->fh_dentry->d_inode;
1110
1111         nfs4_lock_state();
1112         fi_hashval = file_hashval(ino);
1113         if (find_file(fi_hashval, ino, &fp)) {
1114                 /* Search for conflicting share reservations */
1115                 status = nfserr_share_denied;
1116                 list_for_each_safe(pos, next, &fp->fi_perfile) {
1117                 stq = list_entry(pos, struct nfs4_stateid, st_perfile);
1118                         if(stq->st_stateowner == sop) {
1119                                 stp = stq;
1120                                 continue;
1121                         }
1122                         if (!test_share(stq,open))      
1123                                 goto out;
1124                 }
1125         } else {
1126         /* No nfs4_file found; allocate and init a new one */
1127                 status = nfserr_resource;
1128                 if ((fp = alloc_init_file(fi_hashval, ino)) == NULL)
1129                         goto out;
1130         }
1131
1132         if (!stp) {
1133                 int flags = 0;
1134
1135                 status = nfserr_resource;
1136                 if ((stp = kmalloc(sizeof(struct nfs4_stateid),
1137                                                 GFP_KERNEL)) == NULL)
1138                         goto out;
1139
1140                 if (open->op_share_access && NFS4_SHARE_ACCESS_WRITE)
1141                         flags = MAY_WRITE;
1142                 else
1143                         flags = MAY_READ;
1144                 if ((status = nfsd_open(rqstp, current_fh,  S_IFREG,
1145                                               flags,
1146                                               &stp->st_vfs_file)) != 0)
1147                         goto out_free;
1148
1149                 vfsopen++;
1150                 dget(stp->st_vfs_file.f_dentry);
1151                 mntget(stp->st_vfs_file.f_vfsmnt);
1152
1153                 init_stateid(stp, fp, sop, open);
1154                 stp->st_vfs_set = 1;
1155         } else {
1156                 /* This is an upgrade of an existing OPEN. 
1157                  * OR the incoming share with the existing 
1158                  * nfs4_stateid share */
1159                 int share_access = open->op_share_access;
1160
1161                 share_access &= ~(stp->st_share_access);
1162
1163                 /* update the struct file */
1164                 if ((status = nfs4_file_upgrade(&stp->st_vfs_file, share_access)))
1165                         goto out;
1166                 stp->st_share_access |= share_access;
1167                 stp->st_share_deny |= open->op_share_deny;
1168                 /* bump the stateid */
1169                 update_stateid(&stp->st_stateid);
1170         }
1171         dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n\n",
1172                     stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1173                     stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1174
1175         if (open->op_truncate) {
1176                 iattr.ia_valid = ATTR_SIZE;
1177                 iattr.ia_size = 0;
1178                 status = nfsd_setattr(rqstp, current_fh, &iattr, 0, (time_t)0);
1179                 if (status)
1180                         goto out;
1181         }
1182         memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
1183
1184         open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
1185         status = nfs_ok;
1186 out:
1187         if (fp && list_empty(&fp->fi_perfile))
1188                 release_file(fp);
1189
1190         /*
1191         * To finish the open response, we just need to set the rflags.
1192         */
1193         open->op_rflags = 0;
1194         if (!open->op_stateowner->so_confirmed)
1195                 open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
1196
1197         nfs4_unlock_state();
1198         return status;
1199 out_free:
1200         kfree(stp);
1201         goto out;
1202 }
1203 static struct work_struct laundromat_work;
1204 static void laundromat_main(void *);
1205 static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
1206
1207 int 
1208 nfsd4_renew(clientid_t *clid)
1209 {
1210         struct nfs4_client *clp;
1211         struct list_head *pos, *next;
1212         unsigned int idhashval;
1213         int status;
1214
1215         nfs4_lock_state();
1216         dprintk("process_renew(%08x/%08x): starting\n", 
1217                         clid->cl_boot, clid->cl_id);
1218         status = nfserr_stale_clientid;
1219         if (STALE_CLIENTID(clid))
1220                 goto out;
1221         status = nfs_ok;
1222         idhashval = clientid_hashval(clid->cl_id);
1223         list_for_each_safe(pos, next, &conf_id_hashtbl[idhashval]) {
1224                 clp = list_entry(pos, struct nfs4_client, cl_idhash);
1225                 if (!cmp_clid(&clp->cl_clientid, clid))
1226                         continue;
1227                 renew_client(clp);
1228                 goto out;
1229         }
1230         list_for_each_safe(pos, next, &unconf_id_hashtbl[idhashval]) {
1231                 clp = list_entry(pos, struct nfs4_client, cl_idhash);
1232                 if (!cmp_clid(&clp->cl_clientid, clid))
1233                         continue;
1234                 renew_client(clp);
1235         goto out;
1236         }
1237         /*
1238         * Couldn't find an nfs4_client for this clientid.  
1239         * Presumably this is because the client took too long to 
1240         * RENEW, so return NFS4ERR_EXPIRED.
1241         */
1242         dprintk("nfsd4_renew: clientid not found!\n");
1243         status = nfserr_expired;
1244 out:
1245         nfs4_unlock_state();
1246         return status;
1247 }
1248
1249 time_t
1250 nfs4_laundromat(void)
1251 {
1252         struct nfs4_client *clp;
1253         struct list_head *pos, *next;
1254         time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
1255         time_t t, return_val = NFSD_LEASE_TIME;
1256
1257         nfs4_lock_state();
1258
1259         dprintk("NFSD: laundromat service - starting, examining clients\n");
1260         list_for_each_safe(pos, next, &client_lru) {
1261                 clp = list_entry(pos, struct nfs4_client, cl_lru);
1262                 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
1263                         t = clp->cl_time - cutoff;
1264                         if (return_val > t)
1265                                 return_val = t;
1266                         break;
1267                 }
1268                 dprintk("NFSD: purging unused client (clientid %08x)\n",
1269                         clp->cl_clientid.cl_id);
1270                 expire_client(clp);
1271         }
1272         if (return_val < NFSD_LAUNDROMAT_MINTIMEOUT)
1273                 return_val = NFSD_LAUNDROMAT_MINTIMEOUT;
1274         nfs4_unlock_state();
1275         return return_val;
1276 }
1277
1278 void
1279 laundromat_main(void *not_used)
1280 {
1281         time_t t;
1282
1283         t = nfs4_laundromat();
1284         dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1285         schedule_delayed_work(&laundromat_work, t*HZ);
1286 }
1287
1288 /* search ownerid_hashtbl[] for stateid owner (stateid->si_stateownerid) */
1289 struct nfs4_stateowner *
1290 find_openstateowner_id(u32 st_id) {
1291         struct list_head *pos, *next;
1292         struct nfs4_stateowner *local = NULL;
1293         unsigned int hashval = ownerid_hashval(st_id);
1294
1295         list_for_each_safe(pos, next, &ownerid_hashtbl[hashval]) {
1296                 local = list_entry(pos, struct nfs4_stateowner, so_idhash);
1297                 if(local->so_id == st_id)
1298                         return local;
1299         }
1300         return NULL;
1301 }
1302
1303 static inline int
1304 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
1305 {
1306         return (fhp->fh_dentry != stp->st_vfs_file.f_dentry);
1307 }
1308
1309 static int
1310 STALE_STATEID(stateid_t *stateid)
1311 {
1312         if (stateid->si_boot == boot_time)
1313                 return 0;
1314         printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
1315                 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
1316                 stateid->si_generation);
1317         return 1;
1318 }
1319
1320
1321 /*
1322 * Checks for stateid operations
1323 */
1324 int
1325 nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct nfs4_stateid **stpp)
1326 {
1327         struct nfs4_stateid *stp;
1328         int status;
1329
1330         dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
1331                 stateid->si_boot, stateid->si_stateownerid, 
1332                 stateid->si_fileid, stateid->si_generation); 
1333
1334         *stpp = NULL;
1335
1336         /* STALE STATEID */
1337         status = nfserr_stale_stateid;
1338         if (STALE_STATEID(stateid)) 
1339                 goto out;
1340
1341         /* BAD STATEID */
1342         status = nfserr_bad_stateid;
1343         if (!(stp = find_stateid(stateid, flags))) {
1344                 dprintk("NFSD: preprocess_stateid_op: no open stateid!\n");
1345                 goto out;
1346         }
1347         if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
1348                 dprintk("NFSD: preprocess_stateid_op: fh-stateid mismatch!\n");
1349                 goto out;
1350         }
1351         if (!stp->st_stateowner->so_confirmed) {
1352                 dprintk("preprocess_stateid_op: lockowner not confirmed yet!\n");
1353                 goto out;
1354         }
1355         if (stateid->si_generation > stp->st_stateid.si_generation) {
1356                 dprintk("preprocess_stateid_op: future stateid?!\n");
1357                 goto out;
1358         }
1359
1360         /* OLD STATEID */
1361         status = nfserr_old_stateid;
1362         if (stateid->si_generation < stp->st_stateid.si_generation) {
1363                 dprintk("preprocess_stateid_op: old stateid!\n");
1364                 goto out;
1365         }
1366         *stpp = stp;
1367         status = nfs_ok;
1368         renew_client(stp->st_stateowner->so_client);
1369 out:
1370         return status;
1371 }
1372
1373
1374 /* 
1375  * Checks for sequence id mutating operations. 
1376  */
1377 int
1378 nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp)
1379 {
1380         int status;
1381         struct nfs4_stateid *stp;
1382         struct nfs4_stateowner *sop;
1383
1384         dprintk("NFSD: preprocess_seqid_op: seqid=%d " 
1385                         "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
1386                 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
1387                 stateid->si_generation);
1388                                 
1389         *stpp = NULL;
1390         *sopp = NULL;
1391
1392         status = nfserr_bad_stateid;
1393         if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
1394                 printk("NFSD: preprocess_seqid_op: magic stateid!\n");
1395                 goto out;
1396         }
1397
1398         status = nfserr_stale_stateid;
1399         if (STALE_STATEID(stateid))
1400                 goto out;
1401         /*
1402         * We return BAD_STATEID if filehandle doesn't match stateid, 
1403         * the confirmed flag is incorrecly set, or the generation 
1404         * number is incorrect.  
1405         * If there is no entry in the openfile table for this id, 
1406         * we can't always return BAD_STATEID;
1407         * this might be a retransmitted CLOSE which has arrived after 
1408         * the openfile has been released.
1409         */
1410         if (!(stp = find_stateid(stateid, flags)))
1411                 goto no_nfs4_stateid;
1412
1413         status = nfserr_bad_stateid;
1414
1415         if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
1416                 printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
1417                 goto out;
1418         }
1419
1420         *stpp = stp;
1421         *sopp = sop = stp->st_stateowner;
1422
1423         /*
1424         *  We now validate the seqid and stateid generation numbers.
1425         *  For the moment, we ignore the possibility of 
1426         *  generation number wraparound.
1427         */
1428         if (seqid != sop->so_seqid + 1)
1429                 goto check_replay;
1430
1431         if (sop->so_confirmed) {
1432                 if (flags & CONFIRM) {
1433                         printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
1434                         goto out;
1435                 }
1436         }
1437         else {
1438                 if (!(flags & CONFIRM)) {
1439                         printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
1440                         goto out;
1441                 }
1442         }
1443         if (stateid->si_generation > stp->st_stateid.si_generation) {
1444                 printk("NFSD: preprocess_seqid_op: future stateid?!\n");
1445                 goto out;
1446         }
1447
1448         status = nfserr_old_stateid;
1449         if (stateid->si_generation < stp->st_stateid.si_generation) {
1450                 printk("NFSD: preprocess_seqid_op: old stateid!\n");
1451                 goto out;
1452         }
1453         /* XXX renew the client lease here */
1454         status = nfs_ok;
1455
1456 out:
1457         return status;
1458
1459 no_nfs4_stateid:
1460
1461         /*
1462         * We determine whether this is a bad stateid or a replay, 
1463         * starting by trying to look up the stateowner.
1464         * If stateowner is not found - stateid is bad.
1465         */
1466         if (!(sop = find_openstateowner_id(stateid->si_stateownerid))) {
1467                 printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
1468                 status = nfserr_bad_stateid;
1469                 goto out;
1470         }
1471
1472 check_replay:
1473         if (seqid == sop->so_seqid) {
1474                 printk("NFSD: preprocess_seqid_op: retransmission?\n");
1475                 /* indicate replay to calling function */
1476                 status = NFSERR_REPLAY_ME;
1477         } else 
1478                 printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
1479
1480                 status = nfserr_bad_seqid;
1481         goto out;
1482 }
1483
1484 int
1485 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
1486 {
1487         int status;
1488         struct nfs4_stateowner *sop;
1489         struct nfs4_stateid *stp;
1490
1491         dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
1492                         (int)current_fh->fh_dentry->d_name.len,
1493                         current_fh->fh_dentry->d_name.name);
1494         oc->oc_stateowner = NULL;
1495         nfs4_lock_state();
1496
1497         if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
1498                                         &oc->oc_req_stateid,
1499                                         CHECK_FH | CONFIRM | OPEN_STATE,
1500                                         &oc->oc_stateowner, &stp)))
1501                 goto out; 
1502
1503         sop = oc->oc_stateowner;
1504         sop->so_confirmed = 1;
1505         update_stateid(&stp->st_stateid);
1506         memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
1507         dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d " 
1508                 "stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
1509                          stp->st_stateid.si_boot,
1510                          stp->st_stateid.si_stateownerid,
1511                          stp->st_stateid.si_fileid,
1512                          stp->st_stateid.si_generation);
1513         status = nfs_ok;
1514 out:
1515         nfs4_unlock_state();
1516         return status;
1517 }
1518 int
1519 nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
1520 {
1521         int status;
1522         struct nfs4_stateid *stp;
1523
1524         dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
1525                         (int)current_fh->fh_dentry->d_name.len,
1526                         current_fh->fh_dentry->d_name.name);
1527
1528         nfs4_lock_state();
1529         if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 
1530                                         &od->od_stateid, 
1531                                         CHECK_FH | OPEN_STATE, 
1532                                         &od->od_stateowner, &stp)))
1533                 goto out; 
1534
1535         status = nfserr_inval;
1536         if (od->od_share_access & ~stp->st_share_access) {
1537                 dprintk("NFSD:access not a subset current=%08x, desired=%08x\n", 
1538                         stp->st_share_access, od->od_share_access); 
1539                 goto out;
1540         }
1541         if (od->od_share_deny & ~stp->st_share_deny) {
1542                 dprintk("NFSD:deny not a subset current=%08x, desired=%08x\n", 
1543                         stp->st_share_deny, od->od_share_deny);
1544                 goto out;
1545         }
1546         nfs4_file_downgrade(&stp->st_vfs_file, 
1547         stp->st_share_access & ~od->od_share_access);
1548         stp->st_share_access = od->od_share_access;
1549         stp->st_share_deny = od->od_share_deny;
1550         update_stateid(&stp->st_stateid);
1551         memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
1552         status = nfs_ok;
1553 out:
1554         nfs4_unlock_state();
1555         return status;
1556 }
1557
1558 int
1559 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
1560 {
1561         int status;
1562         struct nfs4_stateid *stp;
1563
1564         dprintk("NFSD: nfsd4_close on file %.*s\n", 
1565                         (int)current_fh->fh_dentry->d_name.len,
1566                         current_fh->fh_dentry->d_name.name);
1567
1568         nfs4_lock_state();
1569         if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 
1570                                         &close->cl_stateid, 
1571                                         CHECK_FH | OPEN_STATE, 
1572                                         &close->cl_stateowner, &stp)))
1573                 goto out; 
1574         /*
1575         *  Return success, but first update the stateid.
1576         */
1577         status = nfs_ok;
1578         update_stateid(&stp->st_stateid);
1579         memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
1580
1581         /* release_state_owner() calls nfsd_close() if needed */
1582         release_state_owner(stp, &close->cl_stateowner, OPEN_STATE);
1583 out:
1584         nfs4_unlock_state();
1585         return status;
1586 }
1587
1588 /* 
1589  * Lock owner state (byte-range locks)
1590  */
1591 #define LOFF_OVERFLOW(start, len)      ((u64)(len) > ~(u64)(start))
1592 #define LOCK_HASH_BITS              8
1593 #define LOCK_HASH_SIZE             (1 << LOCK_HASH_BITS)
1594 #define LOCK_HASH_MASK             (LOCK_HASH_SIZE - 1)
1595
1596 #define lockownerid_hashval(id) \
1597         ((id) & LOCK_HASH_MASK)
1598 #define lock_ownerstr_hashval(x, clientid, ownername) \
1599         ((file_hashval(x) + (clientid) + opaque_hashval((ownername.data), (ownername.len))) & LOCK_HASH_MASK)
1600
1601 static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
1602 static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
1603 static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
1604
1605 struct nfs4_stateid *
1606 find_stateid(stateid_t *stid, int flags)
1607 {
1608         struct list_head *pos, *next;
1609         struct nfs4_stateid *local = NULL;
1610         u32 st_id = stid->si_stateownerid;
1611         u32 f_id = stid->si_fileid;
1612         unsigned int hashval;
1613
1614         dprintk("NFSD: find_stateid flags 0x%x\n",flags);
1615         if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
1616                 hashval = stateid_hashval(st_id, f_id);
1617                 list_for_each_safe(pos, next, &lockstateid_hashtbl[hashval]) {
1618                         local = list_entry(pos, struct nfs4_stateid, st_hash);
1619                         if((local->st_stateid.si_stateownerid == st_id) &&
1620                            (local->st_stateid.si_fileid == f_id))
1621                                 return local;
1622                 }
1623         } 
1624         if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
1625                 hashval = stateid_hashval(st_id, f_id);
1626                 list_for_each_safe(pos, next, &stateid_hashtbl[hashval]) {
1627                         local = list_entry(pos, struct nfs4_stateid, st_hash);
1628                         if((local->st_stateid.si_stateownerid == st_id) &&
1629                            (local->st_stateid.si_fileid == f_id))
1630                                 return local;
1631                 }
1632         } else
1633                 printk("NFSD: find_stateid: ERROR: no state flag\n");
1634         return NULL;
1635 }
1636
1637
1638 /*
1639  * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
1640  * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
1641  * byte, because of sign extension problems.  Since NFSv4 calls for 64-bit
1642  * locking, this prevents us from being completely protocol-compliant.  The
1643  * real solution to this problem is to start using unsigned file offsets in
1644  * the VFS, but this is a very deep change!
1645  */
1646 static inline void
1647 nfs4_transform_lock_offset(struct file_lock *lock)
1648 {
1649         if (lock->fl_start < 0)
1650                 lock->fl_start = OFFSET_MAX;
1651         if (lock->fl_end < 0)
1652                 lock->fl_end = OFFSET_MAX;
1653 }
1654
1655 int
1656 nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
1657 {
1658         struct list_head *pos, *next;
1659         struct nfs4_stateowner *local = NULL;
1660         int status = 0;
1661                                 
1662         if (hashval >= LOCK_HASH_SIZE)
1663                 goto out;
1664         list_for_each_safe(pos, next, &lock_ownerid_hashtbl[hashval]) {
1665                 local = list_entry(pos, struct nfs4_stateowner, so_idhash);
1666                 if (local == sop) {
1667                         status = 1;
1668                         goto out;
1669                 }
1670         }
1671 out:
1672         return status;
1673 }
1674
1675
1676 static inline void
1677 nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
1678 {
1679         struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
1680
1681         deny->ld_sop = NULL;
1682         if (nfs4_verify_lock_stateowner(sop, fl->fl_pid))
1683                 deny->ld_sop = sop;
1684         deny->ld_start = fl->fl_start;
1685         deny->ld_length = ~(u64)0;
1686         if (fl->fl_end != ~(u64)0)
1687                 deny->ld_length = fl->fl_end - fl->fl_start + 1;        
1688         deny->ld_type = NFS4_READ_LT;
1689         if (fl->fl_type != F_RDLCK)
1690                 deny->ld_type = NFS4_WRITE_LT;
1691 }
1692
1693
1694 static int
1695 find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid_t *clid, struct nfs4_stateowner **op) {
1696         struct list_head *pos, *next;
1697         struct nfs4_stateowner *local = NULL;
1698
1699         list_for_each_safe(pos, next, &lock_ownerstr_hashtbl[hashval]) {
1700                 local = list_entry(pos, struct nfs4_stateowner, so_strhash);
1701                 if(!cmp_owner_str(local, owner, clid)) 
1702                         continue;
1703                 *op = local;
1704                 return(1);
1705         }
1706         *op = NULL;
1707         return 0;
1708 }
1709
1710 /*
1711  * Alloc a lock owner structure.
1712  * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 
1713  * occured. 
1714  *
1715  * strhashval = lock_ownerstr_hashval 
1716  * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode 
1717  */
1718
1719 static struct nfs4_stateowner *
1720 alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_lock *lock) {
1721         struct nfs4_stateowner *sop;
1722         struct nfs4_replay *rp;
1723         unsigned int idhashval;
1724
1725         if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
1726                 return (struct nfs4_stateowner *)NULL;
1727         idhashval = lockownerid_hashval(current_ownerid);
1728         INIT_LIST_HEAD(&sop->so_idhash);
1729         INIT_LIST_HEAD(&sop->so_strhash);
1730         INIT_LIST_HEAD(&sop->so_perclient);
1731         INIT_LIST_HEAD(&sop->so_perfilestate);
1732         list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
1733         list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
1734         list_add(&sop->so_perclient, &clp->cl_perclient);
1735         add_perclient++;
1736         sop->so_is_open_owner = 0;
1737         sop->so_id = current_ownerid++;
1738         sop->so_client = clp;
1739         sop->so_seqid = lock->lk_new_lock_seqid - 1;
1740         sop->so_confirmed = 1;
1741         rp = &sop->so_replay;
1742         rp->rp_status = NFSERR_SERVERFAULT;
1743         rp->rp_buflen = 0;
1744         rp->rp_buf = rp->rp_ibuf;
1745         alloc_lsowner++;
1746         return sop;
1747 }
1748
1749 struct nfs4_stateid *
1750 alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
1751 {
1752         struct nfs4_stateid *stp;
1753         unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
1754
1755         if ((stp = kmalloc(sizeof(struct nfs4_stateid), 
1756                                         GFP_KERNEL)) == NULL)
1757                 goto out;
1758
1759         INIT_LIST_HEAD(&stp->st_hash);
1760         INIT_LIST_HEAD(&stp->st_perfile);
1761         INIT_LIST_HEAD(&stp->st_perfilestate);
1762         list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
1763         list_add(&stp->st_perfile, &fp->fi_perfile);
1764         list_add_perfile++;
1765         list_add(&stp->st_perfilestate, &sop->so_perfilestate);
1766         stp->st_stateowner = sop;
1767         stp->st_file = fp;
1768         stp->st_stateid.si_boot = boot_time;
1769         stp->st_stateid.si_stateownerid = sop->so_id;
1770         stp->st_stateid.si_fileid = fp->fi_id;
1771         stp->st_stateid.si_generation = 0;
1772         stp->st_vfs_file = open_stp->st_vfs_file;
1773         stp->st_vfs_set = open_stp->st_vfs_set;
1774         stp->st_share_access = -1; 
1775         stp->st_share_deny = -1;
1776
1777 out:
1778         return stp;
1779 }
1780
1781 /*
1782  *  LOCK operation 
1783  */
1784 int
1785 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
1786 {
1787         struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
1788         struct nfs4_stateid *lock_stp;
1789         struct file *filp;
1790         struct file_lock file_lock;
1791         struct file_lock *conflock;
1792         int status = 0;
1793         unsigned int strhashval;
1794
1795         dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
1796                 lock->lk_offset, lock->lk_length);
1797
1798         lock->lk_stateowner = NULL;
1799         nfs4_lock_state();
1800
1801         if (lock->lk_is_new) {
1802         /*
1803          * Client indicates that this is a new lockowner.
1804          * Use open owner and open stateid to create lock owner and lock 
1805          * stateid.
1806          */
1807                 struct nfs4_stateid *open_stp = NULL;
1808                 struct nfs4_file *fp;
1809                 
1810                 status = nfserr_stale_clientid;
1811                 if (STALE_CLIENTID(&lock->lk_new_clientid)) {
1812                         printk("NFSD: nfsd4_lock: clientid is stale!\n");
1813                         goto out;
1814                 }
1815                 /* validate and update open stateid and open seqid */
1816                 status = nfs4_preprocess_seqid_op(current_fh, 
1817                                         lock->lk_new_open_seqid,
1818                                         &lock->lk_new_open_stateid,
1819                                         CHECK_FH | OPEN_STATE,
1820                                         &open_sop, &open_stp);
1821                 if (status)
1822                         goto out;
1823                 /* create lockowner and lock stateid */
1824                 fp = open_stp->st_file;
1825                 strhashval = lock_ownerstr_hashval(fp->fi_inode, 
1826                                 open_sop->so_client->cl_clientid.cl_id, 
1827                                 lock->v.new.owner);
1828
1829                 /* 
1830                  * If we already have this lock owner, the client is in 
1831                  * error (or our bookeeping is wrong!) 
1832                  * for asking for a 'new lock'.
1833                  */
1834                 status = nfserr_bad_stateid;
1835                 if (find_lockstateowner_str(strhashval, &lock->v.new.owner,
1836                                         &lock->v.new.clientid, &lock_sop))
1837                         goto out;
1838                 status = nfserr_resource;
1839                 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, 
1840                                                 open_sop->so_client, lock)))
1841                         goto out;
1842                 if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, 
1843                                                 fp, open_stp)) == NULL)
1844                         goto out;
1845                 /* bump the open seqid used to create the lock */
1846                 open_sop->so_seqid++;
1847         } else {
1848                 /* lock (lock owner + lock stateid) already exists */
1849                 status = nfs4_preprocess_seqid_op(current_fh,
1850                                        lock->lk_old_lock_seqid, 
1851                                        &lock->lk_old_lock_stateid, 
1852                                        CHECK_FH | LOCK_STATE, 
1853                                        &lock->lk_stateowner, &lock_stp);
1854                 if (status)
1855                         goto out;
1856         }
1857         /* lock->lk_stateowner and lock_stp have been created or found */
1858         filp = &lock_stp->st_vfs_file;
1859
1860         if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
1861                 printk("NFSD: nfsd4_lock: permission denied!\n");
1862                 goto out;
1863         }
1864
1865         switch (lock->lk_type) {
1866                 case NFS4_READ_LT:
1867                 case NFS4_READW_LT:
1868                         file_lock.fl_type = F_RDLCK;
1869                 break;
1870                 case NFS4_WRITE_LT:
1871                 case NFS4_WRITEW_LT:
1872                         file_lock.fl_type = F_WRLCK;
1873                 break;
1874                 default:
1875                         status = nfserr_inval;
1876                 goto out;
1877         }
1878         file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
1879         file_lock.fl_pid = lockownerid_hashval(lock->lk_stateowner->so_id);
1880         file_lock.fl_file = filp;
1881         file_lock.fl_flags = FL_POSIX;
1882         file_lock.fl_notify = NULL;
1883         file_lock.fl_insert = NULL;
1884         file_lock.fl_remove = NULL;
1885
1886         file_lock.fl_start = lock->lk_offset;
1887         if ((lock->lk_length == ~(u64)0) || 
1888                         LOFF_OVERFLOW(lock->lk_offset, lock->lk_length))
1889                 file_lock.fl_end = ~(u64)0;
1890         else
1891                 file_lock.fl_end = lock->lk_offset + lock->lk_length - 1;
1892         nfs4_transform_lock_offset(&file_lock);
1893
1894         /*
1895         * Try to lock the file in the VFS.
1896         * Note: locks.c uses the BKL to protect the inode's lock list.
1897         */
1898
1899         status = posix_lock_file(filp, &file_lock);
1900         dprintk("NFSD: nfsd4_lock: posix_test_lock passed. posix_lock_file status %d\n",status);
1901         switch (-status) {
1902         case 0: /* success! */
1903                 update_stateid(&lock_stp->st_stateid);
1904                 memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, 
1905                                 sizeof(stateid_t));
1906                 goto out;
1907         case (EAGAIN):
1908                 goto conflicting_lock;
1909         case (EDEADLK):
1910                 status = nfserr_deadlock;
1911         default:        
1912                 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
1913                 goto out_destroy_new_stateid;
1914         }
1915
1916 conflicting_lock:
1917         dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
1918         status = nfserr_denied;
1919         /* XXX There is a race here. Future patch needed to provide 
1920          * an atomic posix_lock_and_test_file
1921          */
1922         if (!(conflock = posix_test_lock(filp, &file_lock))) {
1923                 status = nfserr_serverfault;
1924                 goto out;
1925         }
1926         nfs4_set_lock_denied(conflock, &lock->lk_denied);
1927
1928 out_destroy_new_stateid:
1929         if (lock->lk_is_new) {
1930                 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
1931         /*
1932         * An error encountered after instantiation of the new
1933         * stateid has forced us to destroy it.
1934         */
1935                 if (!seqid_mutating_err(status))
1936                         open_sop->so_seqid--;
1937
1938                 release_state_owner(lock_stp, &lock->lk_stateowner, LOCK_STATE);
1939         }
1940 out:
1941         nfs4_unlock_state();
1942         return status;
1943 }
1944
1945 /*
1946  * LOCKT operation
1947  */
1948 int
1949 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
1950 {
1951         struct inode *inode;
1952         struct nfs4_stateowner *sop;
1953         struct file file;
1954         struct file_lock file_lock;
1955         struct file_lock *conflicting_lock;
1956         unsigned int strhashval;
1957         int status;
1958
1959         lockt->lt_stateowner = NULL;
1960         nfs4_lock_state();
1961
1962         status = nfserr_stale_clientid;
1963         if (STALE_CLIENTID(&lockt->lt_clientid)) {
1964                 printk("NFSD: nfsd4_lockt: clientid is stale!\n");
1965                 goto out;
1966         }
1967
1968         if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
1969                 printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
1970                 goto out;
1971         }
1972
1973         inode = current_fh->fh_dentry->d_inode;
1974         switch (lockt->lt_type) {
1975                 case NFS4_READ_LT:
1976                 case NFS4_READW_LT:
1977                         file_lock.fl_type = F_RDLCK;
1978                 break;
1979                 case NFS4_WRITE_LT:
1980                 case NFS4_WRITEW_LT:
1981                         file_lock.fl_type = F_WRLCK;
1982                 break;
1983                 default:
1984                         printk("NFSD: nfs4_lockt: bad lock type!\n");
1985                         status = nfserr_inval;
1986                 goto out;
1987         }
1988
1989         strhashval = lock_ownerstr_hashval(inode, 
1990                         lockt->lt_clientid.cl_id, lockt->lt_owner);
1991
1992         if (find_lockstateowner_str(strhashval, &lockt->lt_owner, 
1993                                         &lockt->lt_clientid, 
1994                                         &lockt->lt_stateowner)) {
1995                 printk("NFSD: nsfd4_lockt: lookup_lockowner() failed!\n");
1996                 goto out;
1997         }
1998
1999         sop = lockt->lt_stateowner;
2000         if (sop) {
2001                 file_lock.fl_owner = (fl_owner_t) sop;
2002                 file_lock.fl_pid = lockownerid_hashval(sop->so_id);
2003         } else {
2004                 file_lock.fl_owner = NULL;
2005                 file_lock.fl_pid = 0;
2006         }
2007         file_lock.fl_flags = FL_POSIX;
2008
2009         file_lock.fl_start = lockt->lt_offset;
2010         if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
2011                 file_lock.fl_end = ~(u64)0;
2012         else
2013                 file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1;
2014
2015         nfs4_transform_lock_offset(&file_lock);
2016
2017         /* posix_test_lock uses the struct file _only_ to resolve the inode.
2018          * since LOCKT doesn't require an OPEN, and therefore a struct
2019          * file may not exist, pass posix_test_lock a struct file with
2020          * only the dentry:inode set.
2021          */
2022         memset(&file, 0, sizeof (struct file));
2023         file.f_dentry = current_fh->fh_dentry;
2024
2025         status = nfs_ok;
2026         conflicting_lock = posix_test_lock(&file, &file_lock);
2027         if (conflicting_lock) {
2028                 status = nfserr_denied;
2029                 nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied);
2030         }
2031 out:
2032         nfs4_unlock_state();
2033         return status;
2034 }
2035
2036 int
2037 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
2038 {
2039         struct nfs4_stateid *stp;
2040         struct file *filp = NULL;
2041         struct file_lock file_lock;
2042         int status;
2043                                                         
2044         dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
2045                 locku->lu_offset, locku->lu_length);
2046         nfs4_lock_state();
2047                                                                                 
2048         if ((status = nfs4_preprocess_seqid_op(current_fh, 
2049                                         locku->lu_seqid, 
2050                                         &locku->lu_stateid, 
2051                                         CHECK_FH | LOCK_STATE, 
2052                                         &locku->lu_stateowner, &stp)))
2053                 goto out;
2054
2055         filp = &stp->st_vfs_file;
2056         BUG_ON(!filp);
2057         file_lock.fl_type = F_UNLCK;
2058         file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
2059         file_lock.fl_pid = lockownerid_hashval(locku->lu_stateowner->so_id);
2060         file_lock.fl_file = filp;
2061         file_lock.fl_flags = FL_POSIX; 
2062         file_lock.fl_notify = NULL;
2063         file_lock.fl_insert = NULL;
2064         file_lock.fl_remove = NULL;
2065         file_lock.fl_start = locku->lu_offset;
2066
2067         if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
2068                 file_lock.fl_end = ~(u64)0;
2069         else
2070                 file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
2071         nfs4_transform_lock_offset(&file_lock);
2072
2073         /*
2074         *  Try to unlock the file in the VFS.
2075         */
2076         status = posix_lock_file(filp, &file_lock); 
2077         if (status) {
2078                 printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2079                 goto out_nfserr;
2080         }
2081         /*
2082         * OK, unlock succeeded; the only thing left to do is update the stateid.
2083         */
2084         update_stateid(&stp->st_stateid);
2085         memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
2086
2087 out:
2088         nfs4_unlock_state();
2089         return status;
2090
2091 out_nfserr:
2092         status = nfserrno(status);
2093         goto out;
2094 }
2095
2096 /* 
2097  * Start and stop routines
2098  */
2099
2100 void 
2101 nfs4_state_init(void)
2102 {
2103         int i;
2104
2105         if (nfs4_init)
2106                 return;
2107         for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2108                 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
2109                 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
2110                 INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
2111                 INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
2112         }
2113         for (i = 0; i < FILE_HASH_SIZE; i++) {
2114                 INIT_LIST_HEAD(&file_hashtbl[i]);
2115         }
2116         for (i = 0; i < OWNER_HASH_SIZE; i++) {
2117                 INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
2118                 INIT_LIST_HEAD(&ownerid_hashtbl[i]);
2119         }
2120         for (i = 0; i < STATEID_HASH_SIZE; i++) {
2121                 INIT_LIST_HEAD(&stateid_hashtbl[i]);
2122                 INIT_LIST_HEAD(&lockstateid_hashtbl[i]);
2123         }
2124         for (i = 0; i < LOCK_HASH_SIZE; i++) {
2125                 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
2126                 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
2127         }
2128         memset(&zerostateid, 0, sizeof(stateid_t));
2129         memset(&onestateid, ~0, sizeof(stateid_t));
2130
2131         INIT_LIST_HEAD(&client_lru);
2132         init_MUTEX(&client_sema);
2133         boot_time = get_seconds();
2134         INIT_WORK(&laundromat_work,laundromat_main, NULL);
2135         schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
2136         nfs4_init = 1;
2137
2138 }
2139
2140 static void
2141 __nfs4_state_shutdown(void)
2142 {
2143         int i;
2144         struct nfs4_client *clp = NULL;
2145
2146         for (i = 0; i < CLIENT_HASH_SIZE; i++) {
2147                 while (!list_empty(&conf_id_hashtbl[i])) {
2148                         clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
2149                         expire_client(clp);
2150                 }
2151                 while (!list_empty(&unconf_str_hashtbl[i])) {
2152                         clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
2153                         expire_client(clp);
2154                 }
2155         }
2156         release_all_files();
2157         cancel_delayed_work(&laundromat_work);
2158         flush_scheduled_work();
2159         nfs4_init = 0;
2160         dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
2161                         list_add_perfile, list_del_perfile);
2162         dprintk("NFSD: add_perclient %d del_perclient %d\n",
2163                         add_perclient, del_perclient);
2164         dprintk("NFSD: alloc_file %d free_file %d\n",
2165                         alloc_file, free_file);
2166         dprintk("NFSD: alloc_sowner %d alloc_lsowner %d free_sowner %d\n",
2167                         alloc_sowner, alloc_lsowner, free_sowner);
2168         dprintk("NFSD: vfsopen %d vfsclose %d\n",
2169                         vfsopen, vfsclose);
2170 }
2171
2172 void
2173 nfs4_state_shutdown(void)
2174 {
2175         nfs4_lock_state();
2176         __nfs4_state_shutdown();
2177         nfs4_unlock_state();
2178 }