Btrfs: release metadata from global reserve if we have to fallback for unlink
[pandora-kernel.git] / fs / nfsd / nfsctl.c
1 /*
2  * Syscall interface to knfsd.
3  *
4  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
5  */
6
7 #include <linux/slab.h>
8 #include <linux/namei.h>
9 #include <linux/ctype.h>
10
11 #include <linux/sunrpc/svcsock.h>
12 #include <linux/nfsd/syscall.h>
13 #include <linux/lockd/lockd.h>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/sunrpc/gss_api.h>
16 #include <linux/sunrpc/gss_krb5_enctypes.h>
17
18 #include "idmap.h"
19 #include "nfsd.h"
20 #include "cache.h"
21
22 /*
23  *      We have a single directory with several nodes in it.
24  */
25 enum {
26         NFSD_Root = 1,
27         NFSD_List,
28         NFSD_Export_features,
29         NFSD_Fh,
30         NFSD_FO_UnlockIP,
31         NFSD_FO_UnlockFS,
32         NFSD_Threads,
33         NFSD_Pool_Threads,
34         NFSD_Pool_Stats,
35         NFSD_Versions,
36         NFSD_Ports,
37         NFSD_MaxBlkSize,
38         NFSD_SupportedEnctypes,
39         /*
40          * The below MUST come last.  Otherwise we leave a hole in nfsd_files[]
41          * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
42          */
43 #ifdef CONFIG_NFSD_V4
44         NFSD_Leasetime,
45         NFSD_Gracetime,
46         NFSD_RecoveryDir,
47 #endif
48 };
49
50 /*
51  * write() for these nodes.
52  */
53 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
54 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
55 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
56 static ssize_t write_threads(struct file *file, char *buf, size_t size);
57 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
58 static ssize_t write_versions(struct file *file, char *buf, size_t size);
59 static ssize_t write_ports(struct file *file, char *buf, size_t size);
60 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
61 #ifdef CONFIG_NFSD_V4
62 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
63 static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
64 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
65 #endif
66
67 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
68         [NFSD_Fh] = write_filehandle,
69         [NFSD_FO_UnlockIP] = write_unlock_ip,
70         [NFSD_FO_UnlockFS] = write_unlock_fs,
71         [NFSD_Threads] = write_threads,
72         [NFSD_Pool_Threads] = write_pool_threads,
73         [NFSD_Versions] = write_versions,
74         [NFSD_Ports] = write_ports,
75         [NFSD_MaxBlkSize] = write_maxblksize,
76 #ifdef CONFIG_NFSD_V4
77         [NFSD_Leasetime] = write_leasetime,
78         [NFSD_Gracetime] = write_gracetime,
79         [NFSD_RecoveryDir] = write_recoverydir,
80 #endif
81 };
82
83 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
84 {
85         ino_t ino =  file->f_path.dentry->d_inode->i_ino;
86         char *data;
87         ssize_t rv;
88
89         if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
90                 return -EINVAL;
91
92         data = simple_transaction_get(file, buf, size);
93         if (IS_ERR(data))
94                 return PTR_ERR(data);
95
96         rv =  write_op[ino](file, data, size);
97         if (rv >= 0) {
98                 simple_transaction_set(file, rv);
99                 rv = size;
100         }
101         return rv;
102 }
103
104 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
105 {
106         if (! file->private_data) {
107                 /* An attempt to read a transaction file without writing
108                  * causes a 0-byte write so that the file can return
109                  * state information
110                  */
111                 ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
112                 if (rv < 0)
113                         return rv;
114         }
115         return simple_transaction_read(file, buf, size, pos);
116 }
117
118 static const struct file_operations transaction_ops = {
119         .write          = nfsctl_transaction_write,
120         .read           = nfsctl_transaction_read,
121         .release        = simple_transaction_release,
122         .llseek         = default_llseek,
123 };
124
125 static int exports_open(struct inode *inode, struct file *file)
126 {
127         return seq_open(file, &nfs_exports_op);
128 }
129
130 static const struct file_operations exports_operations = {
131         .open           = exports_open,
132         .read           = seq_read,
133         .llseek         = seq_lseek,
134         .release        = seq_release,
135         .owner          = THIS_MODULE,
136 };
137
138 static int export_features_show(struct seq_file *m, void *v)
139 {
140         seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
141         return 0;
142 }
143
144 static int export_features_open(struct inode *inode, struct file *file)
145 {
146         return single_open(file, export_features_show, NULL);
147 }
148
149 static struct file_operations export_features_operations = {
150         .open           = export_features_open,
151         .read           = seq_read,
152         .llseek         = seq_lseek,
153         .release        = single_release,
154 };
155
156 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
157 static int supported_enctypes_show(struct seq_file *m, void *v)
158 {
159         seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
160         return 0;
161 }
162
163 static int supported_enctypes_open(struct inode *inode, struct file *file)
164 {
165         return single_open(file, supported_enctypes_show, NULL);
166 }
167
168 static struct file_operations supported_enctypes_ops = {
169         .open           = supported_enctypes_open,
170         .read           = seq_read,
171         .llseek         = seq_lseek,
172         .release        = single_release,
173 };
174 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
175
176 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
177 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
178
179 static const struct file_operations pool_stats_operations = {
180         .open           = nfsd_pool_stats_open,
181         .read           = seq_read,
182         .llseek         = seq_lseek,
183         .release        = nfsd_pool_stats_release,
184         .owner          = THIS_MODULE,
185 };
186
187 /*----------------------------------------------------------------------------*/
188 /*
189  * payload - write methods
190  */
191
192
193 /**
194  * write_unlock_ip - Release all locks used by a client
195  *
196  * Experimental.
197  *
198  * Input:
199  *                      buf:    '\n'-terminated C string containing a
200  *                              presentation format IP address
201  *                      size:   length of C string in @buf
202  * Output:
203  *      On success:     returns zero if all specified locks were released;
204  *                      returns one if one or more locks were not released
205  *      On error:       return code is negative errno value
206  */
207 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
208 {
209         struct sockaddr_storage address;
210         struct sockaddr *sap = (struct sockaddr *)&address;
211         size_t salen = sizeof(address);
212         char *fo_path;
213
214         /* sanity check */
215         if (size == 0)
216                 return -EINVAL;
217
218         if (buf[size-1] != '\n')
219                 return -EINVAL;
220
221         fo_path = buf;
222         if (qword_get(&buf, fo_path, size) < 0)
223                 return -EINVAL;
224
225         if (rpc_pton(fo_path, size, sap, salen) == 0)
226                 return -EINVAL;
227
228         return nlmsvc_unlock_all_by_ip(sap);
229 }
230
231 /**
232  * write_unlock_fs - Release all locks on a local file system
233  *
234  * Experimental.
235  *
236  * Input:
237  *                      buf:    '\n'-terminated C string containing the
238  *                              absolute pathname of a local file system
239  *                      size:   length of C string in @buf
240  * Output:
241  *      On success:     returns zero if all specified locks were released;
242  *                      returns one if one or more locks were not released
243  *      On error:       return code is negative errno value
244  */
245 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
246 {
247         struct path path;
248         char *fo_path;
249         int error;
250
251         /* sanity check */
252         if (size == 0)
253                 return -EINVAL;
254
255         if (buf[size-1] != '\n')
256                 return -EINVAL;
257
258         fo_path = buf;
259         if (qword_get(&buf, fo_path, size) < 0)
260                 return -EINVAL;
261
262         error = kern_path(fo_path, 0, &path);
263         if (error)
264                 return error;
265
266         /*
267          * XXX: Needs better sanity checking.  Otherwise we could end up
268          * releasing locks on the wrong file system.
269          *
270          * For example:
271          * 1.  Does the path refer to a directory?
272          * 2.  Is that directory a mount point, or
273          * 3.  Is that directory the root of an exported file system?
274          */
275         error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
276
277         path_put(&path);
278         return error;
279 }
280
281 /**
282  * write_filehandle - Get a variable-length NFS file handle by path
283  *
284  * On input, the buffer contains a '\n'-terminated C string comprised of
285  * three alphanumeric words separated by whitespace.  The string may
286  * contain escape sequences.
287  *
288  * Input:
289  *                      buf:
290  *                              domain:         client domain name
291  *                              path:           export pathname
292  *                              maxsize:        numeric maximum size of
293  *                                              @buf
294  *                      size:   length of C string in @buf
295  * Output:
296  *      On success:     passed-in buffer filled with '\n'-terminated C
297  *                      string containing a ASCII hex text version
298  *                      of the NFS file handle;
299  *                      return code is the size in bytes of the string
300  *      On error:       return code is negative errno value
301  */
302 static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
303 {
304         char *dname, *path;
305         int uninitialized_var(maxsize);
306         char *mesg = buf;
307         int len;
308         struct auth_domain *dom;
309         struct knfsd_fh fh;
310
311         if (size == 0)
312                 return -EINVAL;
313
314         if (buf[size-1] != '\n')
315                 return -EINVAL;
316         buf[size-1] = 0;
317
318         dname = mesg;
319         len = qword_get(&mesg, dname, size);
320         if (len <= 0)
321                 return -EINVAL;
322         
323         path = dname+len+1;
324         len = qword_get(&mesg, path, size);
325         if (len <= 0)
326                 return -EINVAL;
327
328         len = get_int(&mesg, &maxsize);
329         if (len)
330                 return len;
331
332         if (maxsize < NFS_FHSIZE)
333                 return -EINVAL;
334         if (maxsize > NFS3_FHSIZE)
335                 maxsize = NFS3_FHSIZE;
336
337         if (qword_get(&mesg, mesg, size)>0)
338                 return -EINVAL;
339
340         /* we have all the words, they are in buf.. */
341         dom = unix_domain_find(dname);
342         if (!dom)
343                 return -ENOMEM;
344
345         len = exp_rootfh(dom, path, &fh,  maxsize);
346         auth_domain_put(dom);
347         if (len)
348                 return len;
349         
350         mesg = buf;
351         len = SIMPLE_TRANSACTION_LIMIT;
352         qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
353         mesg[-1] = '\n';
354         return mesg - buf;      
355 }
356
357 /**
358  * write_threads - Start NFSD, or report the current number of running threads
359  *
360  * Input:
361  *                      buf:            ignored
362  *                      size:           zero
363  * Output:
364  *      On success:     passed-in buffer filled with '\n'-terminated C
365  *                      string numeric value representing the number of
366  *                      running NFSD threads;
367  *                      return code is the size in bytes of the string
368  *      On error:       return code is zero
369  *
370  * OR
371  *
372  * Input:
373  *                      buf:            C string containing an unsigned
374  *                                      integer value representing the
375  *                                      number of NFSD threads to start
376  *                      size:           non-zero length of C string in @buf
377  * Output:
378  *      On success:     NFS service is started;
379  *                      passed-in buffer filled with '\n'-terminated C
380  *                      string numeric value representing the number of
381  *                      running NFSD threads;
382  *                      return code is the size in bytes of the string
383  *      On error:       return code is zero or a negative errno value
384  */
385 static ssize_t write_threads(struct file *file, char *buf, size_t size)
386 {
387         char *mesg = buf;
388         int rv;
389         if (size > 0) {
390                 int newthreads;
391                 rv = get_int(&mesg, &newthreads);
392                 if (rv)
393                         return rv;
394                 if (newthreads < 0)
395                         return -EINVAL;
396                 rv = nfsd_svc(NFS_PORT, newthreads);
397                 if (rv < 0)
398                         return rv;
399         } else
400                 rv = nfsd_nrthreads();
401
402         return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
403 }
404
405 /**
406  * write_pool_threads - Set or report the current number of threads per pool
407  *
408  * Input:
409  *                      buf:            ignored
410  *                      size:           zero
411  *
412  * OR
413  *
414  * Input:
415  *                      buf:            C string containing whitespace-
416  *                                      separated unsigned integer values
417  *                                      representing the number of NFSD
418  *                                      threads to start in each pool
419  *                      size:           non-zero length of C string in @buf
420  * Output:
421  *      On success:     passed-in buffer filled with '\n'-terminated C
422  *                      string containing integer values representing the
423  *                      number of NFSD threads in each pool;
424  *                      return code is the size in bytes of the string
425  *      On error:       return code is zero or a negative errno value
426  */
427 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
428 {
429         /* if size > 0, look for an array of number of threads per node
430          * and apply them  then write out number of threads per node as reply
431          */
432         char *mesg = buf;
433         int i;
434         int rv;
435         int len;
436         int npools;
437         int *nthreads;
438
439         mutex_lock(&nfsd_mutex);
440         npools = nfsd_nrpools();
441         if (npools == 0) {
442                 /*
443                  * NFS is shut down.  The admin can start it by
444                  * writing to the threads file but NOT the pool_threads
445                  * file, sorry.  Report zero threads.
446                  */
447                 mutex_unlock(&nfsd_mutex);
448                 strcpy(buf, "0\n");
449                 return strlen(buf);
450         }
451
452         nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
453         rv = -ENOMEM;
454         if (nthreads == NULL)
455                 goto out_free;
456
457         if (size > 0) {
458                 for (i = 0; i < npools; i++) {
459                         rv = get_int(&mesg, &nthreads[i]);
460                         if (rv == -ENOENT)
461                                 break;          /* fewer numbers than pools */
462                         if (rv)
463                                 goto out_free;  /* syntax error */
464                         rv = -EINVAL;
465                         if (nthreads[i] < 0)
466                                 goto out_free;
467                 }
468                 rv = nfsd_set_nrthreads(i, nthreads);
469                 if (rv)
470                         goto out_free;
471         }
472
473         rv = nfsd_get_nrthreads(npools, nthreads);
474         if (rv)
475                 goto out_free;
476
477         mesg = buf;
478         size = SIMPLE_TRANSACTION_LIMIT;
479         for (i = 0; i < npools && size > 0; i++) {
480                 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
481                 len = strlen(mesg);
482                 size -= len;
483                 mesg += len;
484         }
485         rv = mesg - buf;
486 out_free:
487         kfree(nthreads);
488         mutex_unlock(&nfsd_mutex);
489         return rv;
490 }
491
492 static ssize_t __write_versions(struct file *file, char *buf, size_t size)
493 {
494         char *mesg = buf;
495         char *vers, *minorp, sign;
496         int len, num, remaining;
497         unsigned minor;
498         ssize_t tlen = 0;
499         char *sep;
500
501         if (size>0) {
502                 if (nfsd_serv)
503                         /* Cannot change versions without updating
504                          * nfsd_serv->sv_xdrsize, and reallocing
505                          * rq_argp and rq_resp
506                          */
507                         return -EBUSY;
508                 if (buf[size-1] != '\n')
509                         return -EINVAL;
510                 buf[size-1] = 0;
511
512                 vers = mesg;
513                 len = qword_get(&mesg, vers, size);
514                 if (len <= 0) return -EINVAL;
515                 do {
516                         sign = *vers;
517                         if (sign == '+' || sign == '-')
518                                 num = simple_strtol((vers+1), &minorp, 0);
519                         else
520                                 num = simple_strtol(vers, &minorp, 0);
521                         if (*minorp == '.') {
522                                 if (num < 4)
523                                         return -EINVAL;
524                                 minor = simple_strtoul(minorp+1, NULL, 0);
525                                 if (minor == 0)
526                                         return -EINVAL;
527                                 if (nfsd_minorversion(minor, sign == '-' ?
528                                                      NFSD_CLEAR : NFSD_SET) < 0)
529                                         return -EINVAL;
530                                 goto next;
531                         }
532                         switch(num) {
533                         case 2:
534                         case 3:
535                         case 4:
536                                 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
537                                 break;
538                         default:
539                                 return -EINVAL;
540                         }
541                 next:
542                         vers += len + 1;
543                 } while ((len = qword_get(&mesg, vers, size)) > 0);
544                 /* If all get turned off, turn them back on, as
545                  * having no versions is BAD
546                  */
547                 nfsd_reset_versions();
548         }
549
550         /* Now write current state into reply buffer */
551         len = 0;
552         sep = "";
553         remaining = SIMPLE_TRANSACTION_LIMIT;
554         for (num=2 ; num <= 4 ; num++)
555                 if (nfsd_vers(num, NFSD_AVAIL)) {
556                         len = snprintf(buf, remaining, "%s%c%d", sep,
557                                        nfsd_vers(num, NFSD_TEST)?'+':'-',
558                                        num);
559                         sep = " ";
560
561                         if (len > remaining)
562                                 break;
563                         remaining -= len;
564                         buf += len;
565                         tlen += len;
566                 }
567         if (nfsd_vers(4, NFSD_AVAIL))
568                 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
569                      minor++) {
570                         len = snprintf(buf, remaining, " %c4.%u",
571                                         (nfsd_vers(4, NFSD_TEST) &&
572                                          nfsd_minorversion(minor, NFSD_TEST)) ?
573                                                 '+' : '-',
574                                         minor);
575
576                         if (len > remaining)
577                                 break;
578                         remaining -= len;
579                         buf += len;
580                         tlen += len;
581                 }
582
583         len = snprintf(buf, remaining, "\n");
584         if (len > remaining)
585                 return -EINVAL;
586         return tlen + len;
587 }
588
589 /**
590  * write_versions - Set or report the available NFS protocol versions
591  *
592  * Input:
593  *                      buf:            ignored
594  *                      size:           zero
595  * Output:
596  *      On success:     passed-in buffer filled with '\n'-terminated C
597  *                      string containing positive or negative integer
598  *                      values representing the current status of each
599  *                      protocol version;
600  *                      return code is the size in bytes of the string
601  *      On error:       return code is zero or a negative errno value
602  *
603  * OR
604  *
605  * Input:
606  *                      buf:            C string containing whitespace-
607  *                                      separated positive or negative
608  *                                      integer values representing NFS
609  *                                      protocol versions to enable ("+n")
610  *                                      or disable ("-n")
611  *                      size:           non-zero length of C string in @buf
612  * Output:
613  *      On success:     status of zero or more protocol versions has
614  *                      been updated; passed-in buffer filled with
615  *                      '\n'-terminated C string containing positive
616  *                      or negative integer values representing the
617  *                      current status of each protocol version;
618  *                      return code is the size in bytes of the string
619  *      On error:       return code is zero or a negative errno value
620  */
621 static ssize_t write_versions(struct file *file, char *buf, size_t size)
622 {
623         ssize_t rv;
624
625         mutex_lock(&nfsd_mutex);
626         rv = __write_versions(file, buf, size);
627         mutex_unlock(&nfsd_mutex);
628         return rv;
629 }
630
631 /*
632  * Zero-length write.  Return a list of NFSD's current listener
633  * transports.
634  */
635 static ssize_t __write_ports_names(char *buf)
636 {
637         if (nfsd_serv == NULL)
638                 return 0;
639         return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
640 }
641
642 /*
643  * A single 'fd' number was written, in which case it must be for
644  * a socket of a supported family/protocol, and we use it as an
645  * nfsd listener.
646  */
647 static ssize_t __write_ports_addfd(char *buf)
648 {
649         char *mesg = buf;
650         int fd, err;
651
652         err = get_int(&mesg, &fd);
653         if (err != 0 || fd < 0)
654                 return -EINVAL;
655
656         err = nfsd_create_serv();
657         if (err != 0)
658                 return err;
659
660         err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
661         if (err < 0) {
662                 svc_destroy(nfsd_serv);
663                 return err;
664         }
665
666         /* Decrease the count, but don't shut down the service */
667         nfsd_serv->sv_nrthreads--;
668         return err;
669 }
670
671 /*
672  * A '-' followed by the 'name' of a socket means we close the socket.
673  */
674 static ssize_t __write_ports_delfd(char *buf)
675 {
676         char *toclose;
677         int len = 0;
678
679         toclose = kstrdup(buf + 1, GFP_KERNEL);
680         if (toclose == NULL)
681                 return -ENOMEM;
682
683         if (nfsd_serv != NULL)
684                 len = svc_sock_names(nfsd_serv, buf,
685                                         SIMPLE_TRANSACTION_LIMIT, toclose);
686         kfree(toclose);
687         return len;
688 }
689
690 /*
691  * A transport listener is added by writing it's transport name and
692  * a port number.
693  */
694 static ssize_t __write_ports_addxprt(char *buf)
695 {
696         char transport[16];
697         struct svc_xprt *xprt;
698         int port, err;
699
700         if (sscanf(buf, "%15s %4u", transport, &port) != 2)
701                 return -EINVAL;
702
703         if (port < 1 || port > USHRT_MAX)
704                 return -EINVAL;
705
706         err = nfsd_create_serv();
707         if (err != 0)
708                 return err;
709
710         err = svc_create_xprt(nfsd_serv, transport, &init_net,
711                                 PF_INET, port, SVC_SOCK_ANONYMOUS);
712         if (err < 0)
713                 goto out_err;
714
715         err = svc_create_xprt(nfsd_serv, transport, &init_net,
716                                 PF_INET6, port, SVC_SOCK_ANONYMOUS);
717         if (err < 0 && err != -EAFNOSUPPORT)
718                 goto out_close;
719
720         /* Decrease the count, but don't shut down the service */
721         nfsd_serv->sv_nrthreads--;
722         return 0;
723 out_close:
724         xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
725         if (xprt != NULL) {
726                 svc_close_xprt(xprt);
727                 svc_xprt_put(xprt);
728         }
729 out_err:
730         svc_destroy(nfsd_serv);
731         return err;
732 }
733
734 /*
735  * A transport listener is removed by writing a "-", it's transport
736  * name, and it's port number.
737  */
738 static ssize_t __write_ports_delxprt(char *buf)
739 {
740         struct svc_xprt *xprt;
741         char transport[16];
742         int port;
743
744         if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
745                 return -EINVAL;
746
747         if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
748                 return -EINVAL;
749
750         xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port);
751         if (xprt == NULL)
752                 return -ENOTCONN;
753
754         svc_close_xprt(xprt);
755         svc_xprt_put(xprt);
756         return 0;
757 }
758
759 static ssize_t __write_ports(struct file *file, char *buf, size_t size)
760 {
761         if (size == 0)
762                 return __write_ports_names(buf);
763
764         if (isdigit(buf[0]))
765                 return __write_ports_addfd(buf);
766
767         if (buf[0] == '-' && isdigit(buf[1]))
768                 return __write_ports_delfd(buf);
769
770         if (isalpha(buf[0]))
771                 return __write_ports_addxprt(buf);
772
773         if (buf[0] == '-' && isalpha(buf[1]))
774                 return __write_ports_delxprt(buf);
775
776         return -EINVAL;
777 }
778
779 /**
780  * write_ports - Pass a socket file descriptor or transport name to listen on
781  *
782  * Input:
783  *                      buf:            ignored
784  *                      size:           zero
785  * Output:
786  *      On success:     passed-in buffer filled with a '\n'-terminated C
787  *                      string containing a whitespace-separated list of
788  *                      named NFSD listeners;
789  *                      return code is the size in bytes of the string
790  *      On error:       return code is zero or a negative errno value
791  *
792  * OR
793  *
794  * Input:
795  *                      buf:            C string containing an unsigned
796  *                                      integer value representing a bound
797  *                                      but unconnected socket that is to be
798  *                                      used as an NFSD listener; listen(3)
799  *                                      must be called for a SOCK_STREAM
800  *                                      socket, otherwise it is ignored
801  *                      size:           non-zero length of C string in @buf
802  * Output:
803  *      On success:     NFS service is started;
804  *                      passed-in buffer filled with a '\n'-terminated C
805  *                      string containing a unique alphanumeric name of
806  *                      the listener;
807  *                      return code is the size in bytes of the string
808  *      On error:       return code is a negative errno value
809  *
810  * OR
811  *
812  * Input:
813  *                      buf:            C string containing a "-" followed
814  *                                      by an integer value representing a
815  *                                      previously passed in socket file
816  *                                      descriptor
817  *                      size:           non-zero length of C string in @buf
818  * Output:
819  *      On success:     NFS service no longer listens on that socket;
820  *                      passed-in buffer filled with a '\n'-terminated C
821  *                      string containing a unique name of the listener;
822  *                      return code is the size in bytes of the string
823  *      On error:       return code is a negative errno value
824  *
825  * OR
826  *
827  * Input:
828  *                      buf:            C string containing a transport
829  *                                      name and an unsigned integer value
830  *                                      representing the port to listen on,
831  *                                      separated by whitespace
832  *                      size:           non-zero length of C string in @buf
833  * Output:
834  *      On success:     returns zero; NFS service is started
835  *      On error:       return code is a negative errno value
836  *
837  * OR
838  *
839  * Input:
840  *                      buf:            C string containing a "-" followed
841  *                                      by a transport name and an unsigned
842  *                                      integer value representing the port
843  *                                      to listen on, separated by whitespace
844  *                      size:           non-zero length of C string in @buf
845  * Output:
846  *      On success:     returns zero; NFS service no longer listens
847  *                      on that transport
848  *      On error:       return code is a negative errno value
849  */
850 static ssize_t write_ports(struct file *file, char *buf, size_t size)
851 {
852         ssize_t rv;
853
854         mutex_lock(&nfsd_mutex);
855         rv = __write_ports(file, buf, size);
856         mutex_unlock(&nfsd_mutex);
857         return rv;
858 }
859
860
861 int nfsd_max_blksize;
862
863 /**
864  * write_maxblksize - Set or report the current NFS blksize
865  *
866  * Input:
867  *                      buf:            ignored
868  *                      size:           zero
869  *
870  * OR
871  *
872  * Input:
873  *                      buf:            C string containing an unsigned
874  *                                      integer value representing the new
875  *                                      NFS blksize
876  *                      size:           non-zero length of C string in @buf
877  * Output:
878  *      On success:     passed-in buffer filled with '\n'-terminated C string
879  *                      containing numeric value of the current NFS blksize
880  *                      setting;
881  *                      return code is the size in bytes of the string
882  *      On error:       return code is zero or a negative errno value
883  */
884 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
885 {
886         char *mesg = buf;
887         if (size > 0) {
888                 int bsize;
889                 int rv = get_int(&mesg, &bsize);
890                 if (rv)
891                         return rv;
892                 /* force bsize into allowed range and
893                  * required alignment.
894                  */
895                 if (bsize < 1024)
896                         bsize = 1024;
897                 if (bsize > NFSSVC_MAXBLKSIZE)
898                         bsize = NFSSVC_MAXBLKSIZE;
899                 bsize &= ~(1024-1);
900                 mutex_lock(&nfsd_mutex);
901                 if (nfsd_serv) {
902                         mutex_unlock(&nfsd_mutex);
903                         return -EBUSY;
904                 }
905                 nfsd_max_blksize = bsize;
906                 mutex_unlock(&nfsd_mutex);
907         }
908
909         return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
910                                                         nfsd_max_blksize);
911 }
912
913 #ifdef CONFIG_NFSD_V4
914 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
915 {
916         char *mesg = buf;
917         int rv, i;
918
919         if (size > 0) {
920                 if (nfsd_serv)
921                         return -EBUSY;
922                 rv = get_int(&mesg, &i);
923                 if (rv)
924                         return rv;
925                 /*
926                  * Some sanity checking.  We don't have a reason for
927                  * these particular numbers, but problems with the
928                  * extremes are:
929                  *      - Too short: the briefest network outage may
930                  *        cause clients to lose all their locks.  Also,
931                  *        the frequent polling may be wasteful.
932                  *      - Too long: do you really want reboot recovery
933                  *        to take more than an hour?  Or to make other
934                  *        clients wait an hour before being able to
935                  *        revoke a dead client's locks?
936                  */
937                 if (i < 10 || i > 3600)
938                         return -EINVAL;
939                 *time = i;
940         }
941
942         return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
943 }
944
945 static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time)
946 {
947         ssize_t rv;
948
949         mutex_lock(&nfsd_mutex);
950         rv = __nfsd4_write_time(file, buf, size, time);
951         mutex_unlock(&nfsd_mutex);
952         return rv;
953 }
954
955 /**
956  * write_leasetime - Set or report the current NFSv4 lease time
957  *
958  * Input:
959  *                      buf:            ignored
960  *                      size:           zero
961  *
962  * OR
963  *
964  * Input:
965  *                      buf:            C string containing an unsigned
966  *                                      integer value representing the new
967  *                                      NFSv4 lease expiry time
968  *                      size:           non-zero length of C string in @buf
969  * Output:
970  *      On success:     passed-in buffer filled with '\n'-terminated C
971  *                      string containing unsigned integer value of the
972  *                      current lease expiry time;
973  *                      return code is the size in bytes of the string
974  *      On error:       return code is zero or a negative errno value
975  */
976 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
977 {
978         return nfsd4_write_time(file, buf, size, &nfsd4_lease);
979 }
980
981 /**
982  * write_gracetime - Set or report current NFSv4 grace period time
983  *
984  * As above, but sets the time of the NFSv4 grace period.
985  *
986  * Note this should never be set to less than the *previous*
987  * lease-period time, but we don't try to enforce this.  (In the common
988  * case (a new boot), we don't know what the previous lease time was
989  * anyway.)
990  */
991 static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
992 {
993         return nfsd4_write_time(file, buf, size, &nfsd4_grace);
994 }
995
996 extern char *nfs4_recoverydir(void);
997
998 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
999 {
1000         char *mesg = buf;
1001         char *recdir;
1002         int len, status;
1003
1004         if (size > 0) {
1005                 if (nfsd_serv)
1006                         return -EBUSY;
1007                 if (size > PATH_MAX || buf[size-1] != '\n')
1008                         return -EINVAL;
1009                 buf[size-1] = 0;
1010
1011                 recdir = mesg;
1012                 len = qword_get(&mesg, recdir, size);
1013                 if (len <= 0)
1014                         return -EINVAL;
1015
1016                 status = nfs4_reset_recoverydir(recdir);
1017                 if (status)
1018                         return status;
1019         }
1020
1021         return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
1022                                                         nfs4_recoverydir());
1023 }
1024
1025 /**
1026  * write_recoverydir - Set or report the pathname of the recovery directory
1027  *
1028  * Input:
1029  *                      buf:            ignored
1030  *                      size:           zero
1031  *
1032  * OR
1033  *
1034  * Input:
1035  *                      buf:            C string containing the pathname
1036  *                                      of the directory on a local file
1037  *                                      system containing permanent NFSv4
1038  *                                      recovery data
1039  *                      size:           non-zero length of C string in @buf
1040  * Output:
1041  *      On success:     passed-in buffer filled with '\n'-terminated C string
1042  *                      containing the current recovery pathname setting;
1043  *                      return code is the size in bytes of the string
1044  *      On error:       return code is zero or a negative errno value
1045  */
1046 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1047 {
1048         ssize_t rv;
1049
1050         mutex_lock(&nfsd_mutex);
1051         rv = __write_recoverydir(file, buf, size);
1052         mutex_unlock(&nfsd_mutex);
1053         return rv;
1054 }
1055
1056 #endif
1057
1058 /*----------------------------------------------------------------------------*/
1059 /*
1060  *      populating the filesystem.
1061  */
1062
1063 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1064 {
1065         static struct tree_descr nfsd_files[] = {
1066                 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1067                 [NFSD_Export_features] = {"export_features",
1068                                         &export_features_operations, S_IRUGO},
1069                 [NFSD_FO_UnlockIP] = {"unlock_ip",
1070                                         &transaction_ops, S_IWUSR|S_IRUSR},
1071                 [NFSD_FO_UnlockFS] = {"unlock_filesystem",
1072                                         &transaction_ops, S_IWUSR|S_IRUSR},
1073                 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
1074                 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
1075                 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
1076                 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
1077                 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1078                 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1079                 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1080 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1081                 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1082 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
1083 #ifdef CONFIG_NFSD_V4
1084                 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1085                 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
1086                 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
1087 #endif
1088                 /* last one */ {""}
1089         };
1090         return simple_fill_super(sb, 0x6e667364, nfsd_files);
1091 }
1092
1093 static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1094         int flags, const char *dev_name, void *data)
1095 {
1096         return mount_single(fs_type, flags, data, nfsd_fill_super);
1097 }
1098
1099 static struct file_system_type nfsd_fs_type = {
1100         .owner          = THIS_MODULE,
1101         .name           = "nfsd",
1102         .mount          = nfsd_mount,
1103         .kill_sb        = kill_litter_super,
1104 };
1105
1106 #ifdef CONFIG_PROC_FS
1107 static int create_proc_exports_entry(void)
1108 {
1109         struct proc_dir_entry *entry;
1110
1111         entry = proc_mkdir("fs/nfs", NULL);
1112         if (!entry)
1113                 return -ENOMEM;
1114         entry = proc_create("exports", 0, entry, &exports_operations);
1115         if (!entry)
1116                 return -ENOMEM;
1117         return 0;
1118 }
1119 #else /* CONFIG_PROC_FS */
1120 static int create_proc_exports_entry(void)
1121 {
1122         return 0;
1123 }
1124 #endif
1125
1126 static int __init init_nfsd(void)
1127 {
1128         int retval;
1129         printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
1130
1131         retval = nfs4_state_init(); /* nfs4 locking state */
1132         if (retval)
1133                 return retval;
1134         nfsd_stat_init();       /* Statistics */
1135         retval = nfsd_reply_cache_init();
1136         if (retval)
1137                 goto out_free_stat;
1138         retval = nfsd_export_init();
1139         if (retval)
1140                 goto out_free_cache;
1141         nfsd_lockd_init();      /* lockd->nfsd callbacks */
1142         retval = nfsd_idmap_init();
1143         if (retval)
1144                 goto out_free_lockd;
1145         retval = create_proc_exports_entry();
1146         if (retval)
1147                 goto out_free_idmap;
1148         retval = register_filesystem(&nfsd_fs_type);
1149         if (retval)
1150                 goto out_free_all;
1151         return 0;
1152 out_free_all:
1153         remove_proc_entry("fs/nfs/exports", NULL);
1154         remove_proc_entry("fs/nfs", NULL);
1155 out_free_idmap:
1156         nfsd_idmap_shutdown();
1157 out_free_lockd:
1158         nfsd_lockd_shutdown();
1159         nfsd_export_shutdown();
1160 out_free_cache:
1161         nfsd_reply_cache_shutdown();
1162 out_free_stat:
1163         nfsd_stat_shutdown();
1164         nfsd4_free_slabs();
1165         return retval;
1166 }
1167
1168 static void __exit exit_nfsd(void)
1169 {
1170         nfsd_export_shutdown();
1171         nfsd_reply_cache_shutdown();
1172         remove_proc_entry("fs/nfs/exports", NULL);
1173         remove_proc_entry("fs/nfs", NULL);
1174         nfsd_stat_shutdown();
1175         nfsd_lockd_shutdown();
1176         nfsd_idmap_shutdown();
1177         nfsd4_free_slabs();
1178         unregister_filesystem(&nfsd_fs_type);
1179 }
1180
1181 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
1182 MODULE_LICENSE("GPL");
1183 module_init(init_nfsd)
1184 module_exit(exit_nfsd)