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 #ifdef CONFIG_NFSD_DEPRECATED 28 NFSD_Svc, 29 NFSD_Add, 30 NFSD_Del, 31 NFSD_Export, 32 NFSD_Unexport, 33 NFSD_Getfd, 34 NFSD_Getfs, 35 #endif 36 NFSD_List, 37 NFSD_Export_features, 38 NFSD_Fh, 39 NFSD_FO_UnlockIP, 40 NFSD_FO_UnlockFS, 41 NFSD_Threads, 42 NFSD_Pool_Threads, 43 NFSD_Pool_Stats, 44 NFSD_Versions, 45 NFSD_Ports, 46 NFSD_MaxBlkSize, 47 NFSD_SupportedEnctypes, 48 /* 49 * The below MUST come last. Otherwise we leave a hole in nfsd_files[] 50 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops 51 */ 52 #ifdef CONFIG_NFSD_V4 53 NFSD_Leasetime, 54 NFSD_Gracetime, 55 NFSD_RecoveryDir, 56 #endif 57 }; 58 59 /* 60 * write() for these nodes. 61 */ 62 #ifdef CONFIG_NFSD_DEPRECATED 63 static ssize_t write_svc(struct file *file, char *buf, size_t size); 64 static ssize_t write_add(struct file *file, char *buf, size_t size); 65 static ssize_t write_del(struct file *file, char *buf, size_t size); 66 static ssize_t write_export(struct file *file, char *buf, size_t size); 67 static ssize_t write_unexport(struct file *file, char *buf, size_t size); 68 static ssize_t write_getfd(struct file *file, char *buf, size_t size); 69 static ssize_t write_getfs(struct file *file, char *buf, size_t size); 70 #endif 71 static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 72 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size); 73 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size); 74 static ssize_t write_threads(struct file *file, char *buf, size_t size); 75 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); 76 static ssize_t write_versions(struct file *file, char *buf, size_t size); 77 static ssize_t write_ports(struct file *file, char *buf, size_t size); 78 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size); 79 #ifdef CONFIG_NFSD_V4 80 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); 81 static ssize_t write_gracetime(struct file *file, char *buf, size_t size); 82 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 83 #endif 84 85 static ssize_t (*write_op[])(struct file *, char *, size_t) = { 86 #ifdef CONFIG_NFSD_DEPRECATED 87 [NFSD_Svc] = write_svc, 88 [NFSD_Add] = write_add, 89 [NFSD_Del] = write_del, 90 [NFSD_Export] = write_export, 91 [NFSD_Unexport] = write_unexport, 92 [NFSD_Getfd] = write_getfd, 93 [NFSD_Getfs] = write_getfs, 94 #endif 95 [NFSD_Fh] = write_filehandle, 96 [NFSD_FO_UnlockIP] = write_unlock_ip, 97 [NFSD_FO_UnlockFS] = write_unlock_fs, 98 [NFSD_Threads] = write_threads, 99 [NFSD_Pool_Threads] = write_pool_threads, 100 [NFSD_Versions] = write_versions, 101 [NFSD_Ports] = write_ports, 102 [NFSD_MaxBlkSize] = write_maxblksize, 103 #ifdef CONFIG_NFSD_V4 104 [NFSD_Leasetime] = write_leasetime, 105 [NFSD_Gracetime] = write_gracetime, 106 [NFSD_RecoveryDir] = write_recoverydir, 107 #endif 108 }; 109 110 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 111 { 112 ino_t ino = file->f_path.dentry->d_inode->i_ino; 113 char *data; 114 ssize_t rv; 115 116 if (ino >= ARRAY_SIZE(write_op) || !write_op[ino]) 117 return -EINVAL; 118 119 data = simple_transaction_get(file, buf, size); 120 if (IS_ERR(data)) 121 return PTR_ERR(data); 122 123 rv = write_op[ino](file, data, size); 124 if (rv >= 0) { 125 simple_transaction_set(file, rv); 126 rv = size; 127 } 128 return rv; 129 } 130 131 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) 132 { 133 #ifdef CONFIG_NFSD_DEPRECATED 134 static int warned; 135 if (file->f_dentry->d_name.name[0] == '.' && !warned) { 136 printk(KERN_INFO 137 "Warning: \"%s\" uses deprecated NFSD interface: %s." 138 " This will be removed in 2.6.40\n", 139 current->comm, file->f_dentry->d_name.name); 140 warned = 1; 141 } 142 #endif 143 if (! file->private_data) { 144 /* An attempt to read a transaction file without writing 145 * causes a 0-byte write so that the file can return 146 * state information 147 */ 148 ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos); 149 if (rv < 0) 150 return rv; 151 } 152 return simple_transaction_read(file, buf, size, pos); 153 } 154 155 static const struct file_operations transaction_ops = { 156 .write = nfsctl_transaction_write, 157 .read = nfsctl_transaction_read, 158 .release = simple_transaction_release, 159 .llseek = default_llseek, 160 }; 161 162 static int exports_open(struct inode *inode, struct file *file) 163 { 164 return seq_open(file, &nfs_exports_op); 165 } 166 167 static const struct file_operations exports_operations = { 168 .open = exports_open, 169 .read = seq_read, 170 .llseek = seq_lseek, 171 .release = seq_release, 172 .owner = THIS_MODULE, 173 }; 174 175 static int export_features_show(struct seq_file *m, void *v) 176 { 177 seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS); 178 return 0; 179 } 180 181 static int export_features_open(struct inode *inode, struct file *file) 182 { 183 return single_open(file, export_features_show, NULL); 184 } 185 186 static struct file_operations export_features_operations = { 187 .open = export_features_open, 188 .read = seq_read, 189 .llseek = seq_lseek, 190 .release = single_release, 191 }; 192 193 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) 194 static int supported_enctypes_show(struct seq_file *m, void *v) 195 { 196 seq_printf(m, KRB5_SUPPORTED_ENCTYPES); 197 return 0; 198 } 199 200 static int supported_enctypes_open(struct inode *inode, struct file *file) 201 { 202 return single_open(file, supported_enctypes_show, NULL); 203 } 204 205 static struct file_operations supported_enctypes_ops = { 206 .open = supported_enctypes_open, 207 .read = seq_read, 208 .llseek = seq_lseek, 209 .release = single_release, 210 }; 211 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ 212 213 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); 214 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); 215 216 static const struct file_operations pool_stats_operations = { 217 .open = nfsd_pool_stats_open, 218 .read = seq_read, 219 .llseek = seq_lseek, 220 .release = nfsd_pool_stats_release, 221 .owner = THIS_MODULE, 222 }; 223 224 /*----------------------------------------------------------------------------*/ 225 /* 226 * payload - write methods 227 */ 228 229 #ifdef CONFIG_NFSD_DEPRECATED 230 /** 231 * write_svc - Start kernel's NFSD server 232 * 233 * Deprecated. /proc/fs/nfsd/threads is preferred. 234 * Function remains to support old versions of nfs-utils. 235 * 236 * Input: 237 * buf: struct nfsctl_svc 238 * svc_port: port number of this 239 * server's listener 240 * svc_nthreads: number of threads to start 241 * size: size in bytes of passed in nfsctl_svc 242 * Output: 243 * On success: returns zero 244 * On error: return code is negative errno value 245 */ 246 static ssize_t write_svc(struct file *file, char *buf, size_t size) 247 { 248 struct nfsctl_svc *data; 249 int err; 250 if (size < sizeof(*data)) 251 return -EINVAL; 252 data = (struct nfsctl_svc*) buf; 253 err = nfsd_svc(data->svc_port, data->svc_nthreads); 254 if (err < 0) 255 return err; 256 return 0; 257 } 258 259 /** 260 * write_add - Add or modify client entry in auth unix cache 261 * 262 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred. 263 * Function remains to support old versions of nfs-utils. 264 * 265 * Input: 266 * buf: struct nfsctl_client 267 * cl_ident: '\0'-terminated C string 268 * containing domain name 269 * of client 270 * cl_naddr: no. of items in cl_addrlist 271 * cl_addrlist: array of client addresses 272 * cl_fhkeytype: ignored 273 * cl_fhkeylen: ignored 274 * cl_fhkey: ignored 275 * size: size in bytes of passed in nfsctl_client 276 * Output: 277 * On success: returns zero 278 * On error: return code is negative errno value 279 * 280 * Note: Only AF_INET client addresses are passed in, since 281 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses. 282 */ 283 static ssize_t write_add(struct file *file, char *buf, size_t size) 284 { 285 struct nfsctl_client *data; 286 if (size < sizeof(*data)) 287 return -EINVAL; 288 data = (struct nfsctl_client *)buf; 289 return exp_addclient(data); 290 } 291 292 /** 293 * write_del - Remove client from auth unix cache 294 * 295 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred. 296 * Function remains to support old versions of nfs-utils. 297 * 298 * Input: 299 * buf: struct nfsctl_client 300 * cl_ident: '\0'-terminated C string 301 * containing domain name 302 * of client 303 * cl_naddr: ignored 304 * cl_addrlist: ignored 305 * cl_fhkeytype: ignored 306 * cl_fhkeylen: ignored 307 * cl_fhkey: ignored 308 * size: size in bytes of passed in nfsctl_client 309 * Output: 310 * On success: returns zero 311 * On error: return code is negative errno value 312 * 313 * Note: Only AF_INET client addresses are passed in, since 314 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses. 315 */ 316 static ssize_t write_del(struct file *file, char *buf, size_t size) 317 { 318 struct nfsctl_client *data; 319 if (size < sizeof(*data)) 320 return -EINVAL; 321 data = (struct nfsctl_client *)buf; 322 return exp_delclient(data); 323 } 324 325 /** 326 * write_export - Export part or all of a local file system 327 * 328 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred. 329 * Function remains to support old versions of nfs-utils. 330 * 331 * Input: 332 * buf: struct nfsctl_export 333 * ex_client: '\0'-terminated C string 334 * containing domain name 335 * of client allowed to access 336 * this export 337 * ex_path: '\0'-terminated C string 338 * containing pathname of 339 * directory in local file system 340 * ex_dev: fsid to use for this export 341 * ex_ino: ignored 342 * ex_flags: export flags for this export 343 * ex_anon_uid: UID to use for anonymous 344 * requests 345 * ex_anon_gid: GID to use for anonymous 346 * requests 347 * size: size in bytes of passed in nfsctl_export 348 * Output: 349 * On success: returns zero 350 * On error: return code is negative errno value 351 */ 352 static ssize_t write_export(struct file *file, char *buf, size_t size) 353 { 354 struct nfsctl_export *data; 355 if (size < sizeof(*data)) 356 return -EINVAL; 357 data = (struct nfsctl_export*)buf; 358 return exp_export(data); 359 } 360 361 /** 362 * write_unexport - Unexport a previously exported file system 363 * 364 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred. 365 * Function remains to support old versions of nfs-utils. 366 * 367 * Input: 368 * buf: struct nfsctl_export 369 * ex_client: '\0'-terminated C string 370 * containing domain name 371 * of client no longer allowed 372 * to access this export 373 * ex_path: '\0'-terminated C string 374 * containing pathname of 375 * directory in local file system 376 * ex_dev: ignored 377 * ex_ino: ignored 378 * ex_flags: ignored 379 * ex_anon_uid: ignored 380 * ex_anon_gid: ignored 381 * size: size in bytes of passed in nfsctl_export 382 * Output: 383 * On success: returns zero 384 * On error: return code is negative errno value 385 */ 386 static ssize_t write_unexport(struct file *file, char *buf, size_t size) 387 { 388 struct nfsctl_export *data; 389 390 if (size < sizeof(*data)) 391 return -EINVAL; 392 data = (struct nfsctl_export*)buf; 393 return exp_unexport(data); 394 } 395 396 /** 397 * write_getfs - Get a variable-length NFS file handle by path 398 * 399 * Deprecated. /proc/fs/nfsd/filehandle is preferred. 400 * Function remains to support old versions of nfs-utils. 401 * 402 * Input: 403 * buf: struct nfsctl_fsparm 404 * gd_addr: socket address of client 405 * gd_path: '\0'-terminated C string 406 * containing pathname of 407 * directory in local file system 408 * gd_maxlen: maximum size of returned file 409 * handle 410 * size: size in bytes of passed in nfsctl_fsparm 411 * Output: 412 * On success: passed-in buffer filled with a knfsd_fh structure 413 * (a variable-length raw NFS file handle); 414 * return code is the size in bytes of the file handle 415 * On error: return code is negative errno value 416 * 417 * Note: Only AF_INET client addresses are passed in, since gd_addr 418 * is the same size as a struct sockaddr_in. 419 */ 420 static ssize_t write_getfs(struct file *file, char *buf, size_t size) 421 { 422 struct nfsctl_fsparm *data; 423 struct sockaddr_in *sin; 424 struct auth_domain *clp; 425 int err = 0; 426 struct knfsd_fh *res; 427 struct in6_addr in6; 428 429 if (size < sizeof(*data)) 430 return -EINVAL; 431 data = (struct nfsctl_fsparm*)buf; 432 err = -EPROTONOSUPPORT; 433 if (data->gd_addr.sa_family != AF_INET) 434 goto out; 435 sin = (struct sockaddr_in *)&data->gd_addr; 436 if (data->gd_maxlen > NFS3_FHSIZE) 437 data->gd_maxlen = NFS3_FHSIZE; 438 439 res = (struct knfsd_fh*)buf; 440 441 exp_readlock(); 442 443 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6); 444 445 clp = auth_unix_lookup(&init_net, &in6); 446 if (!clp) 447 err = -EPERM; 448 else { 449 err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen); 450 auth_domain_put(clp); 451 } 452 exp_readunlock(); 453 if (err == 0) 454 err = res->fh_size + offsetof(struct knfsd_fh, fh_base); 455 out: 456 return err; 457 } 458 459 /** 460 * write_getfd - Get a fixed-length NFS file handle by path (used by mountd) 461 * 462 * Deprecated. /proc/fs/nfsd/filehandle is preferred. 463 * Function remains to support old versions of nfs-utils. 464 * 465 * Input: 466 * buf: struct nfsctl_fdparm 467 * gd_addr: socket address of client 468 * gd_path: '\0'-terminated C string 469 * containing pathname of 470 * directory in local file system 471 * gd_version: fdparm structure version 472 * size: size in bytes of passed in nfsctl_fdparm 473 * Output: 474 * On success: passed-in buffer filled with nfsctl_res 475 * (a fixed-length raw NFS file handle); 476 * return code is the size in bytes of the file handle 477 * On error: return code is negative errno value 478 * 479 * Note: Only AF_INET client addresses are passed in, since gd_addr 480 * is the same size as a struct sockaddr_in. 481 */ 482 static ssize_t write_getfd(struct file *file, char *buf, size_t size) 483 { 484 struct nfsctl_fdparm *data; 485 struct sockaddr_in *sin; 486 struct auth_domain *clp; 487 int err = 0; 488 struct knfsd_fh fh; 489 char *res; 490 struct in6_addr in6; 491 492 if (size < sizeof(*data)) 493 return -EINVAL; 494 data = (struct nfsctl_fdparm*)buf; 495 err = -EPROTONOSUPPORT; 496 if (data->gd_addr.sa_family != AF_INET) 497 goto out; 498 err = -EINVAL; 499 if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS) 500 goto out; 501 502 res = buf; 503 sin = (struct sockaddr_in *)&data->gd_addr; 504 exp_readlock(); 505 506 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6); 507 508 clp = auth_unix_lookup(&init_net, &in6); 509 if (!clp) 510 err = -EPERM; 511 else { 512 err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE); 513 auth_domain_put(clp); 514 } 515 exp_readunlock(); 516 517 if (err == 0) { 518 memset(res,0, NFS_FHSIZE); 519 memcpy(res, &fh.fh_base, fh.fh_size); 520 err = NFS_FHSIZE; 521 } 522 out: 523 return err; 524 } 525 #endif /* CONFIG_NFSD_DEPRECATED */ 526 527 /** 528 * write_unlock_ip - Release all locks used by a client 529 * 530 * Experimental. 531 * 532 * Input: 533 * buf: '\n'-terminated C string containing a 534 * presentation format IP address 535 * size: length of C string in @buf 536 * Output: 537 * On success: returns zero if all specified locks were released; 538 * returns one if one or more locks were not released 539 * On error: return code is negative errno value 540 */ 541 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) 542 { 543 struct sockaddr_storage address; 544 struct sockaddr *sap = (struct sockaddr *)&address; 545 size_t salen = sizeof(address); 546 char *fo_path; 547 548 /* sanity check */ 549 if (size == 0) 550 return -EINVAL; 551 552 if (buf[size-1] != '\n') 553 return -EINVAL; 554 555 fo_path = buf; 556 if (qword_get(&buf, fo_path, size) < 0) 557 return -EINVAL; 558 559 if (rpc_pton(fo_path, size, sap, salen) == 0) 560 return -EINVAL; 561 562 return nlmsvc_unlock_all_by_ip(sap); 563 } 564 565 /** 566 * write_unlock_fs - Release all locks on a local file system 567 * 568 * Experimental. 569 * 570 * Input: 571 * buf: '\n'-terminated C string containing the 572 * absolute pathname of a local file system 573 * size: length of C string in @buf 574 * Output: 575 * On success: returns zero if all specified locks were released; 576 * returns one if one or more locks were not released 577 * On error: return code is negative errno value 578 */ 579 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) 580 { 581 struct path path; 582 char *fo_path; 583 int error; 584 585 /* sanity check */ 586 if (size == 0) 587 return -EINVAL; 588 589 if (buf[size-1] != '\n') 590 return -EINVAL; 591 592 fo_path = buf; 593 if (qword_get(&buf, fo_path, size) < 0) 594 return -EINVAL; 595 596 error = kern_path(fo_path, 0, &path); 597 if (error) 598 return error; 599 600 /* 601 * XXX: Needs better sanity checking. Otherwise we could end up 602 * releasing locks on the wrong file system. 603 * 604 * For example: 605 * 1. Does the path refer to a directory? 606 * 2. Is that directory a mount point, or 607 * 3. Is that directory the root of an exported file system? 608 */ 609 error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb); 610 611 path_put(&path); 612 return error; 613 } 614 615 /** 616 * write_filehandle - Get a variable-length NFS file handle by path 617 * 618 * On input, the buffer contains a '\n'-terminated C string comprised of 619 * three alphanumeric words separated by whitespace. The string may 620 * contain escape sequences. 621 * 622 * Input: 623 * buf: 624 * domain: client domain name 625 * path: export pathname 626 * maxsize: numeric maximum size of 627 * @buf 628 * size: length of C string in @buf 629 * Output: 630 * On success: passed-in buffer filled with '\n'-terminated C 631 * string containing a ASCII hex text version 632 * of the NFS file handle; 633 * return code is the size in bytes of the string 634 * On error: return code is negative errno value 635 */ 636 static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 637 { 638 char *dname, *path; 639 int uninitialized_var(maxsize); 640 char *mesg = buf; 641 int len; 642 struct auth_domain *dom; 643 struct knfsd_fh fh; 644 645 if (size == 0) 646 return -EINVAL; 647 648 if (buf[size-1] != '\n') 649 return -EINVAL; 650 buf[size-1] = 0; 651 652 dname = mesg; 653 len = qword_get(&mesg, dname, size); 654 if (len <= 0) 655 return -EINVAL; 656 657 path = dname+len+1; 658 len = qword_get(&mesg, path, size); 659 if (len <= 0) 660 return -EINVAL; 661 662 len = get_int(&mesg, &maxsize); 663 if (len) 664 return len; 665 666 if (maxsize < NFS_FHSIZE) 667 return -EINVAL; 668 if (maxsize > NFS3_FHSIZE) 669 maxsize = NFS3_FHSIZE; 670 671 if (qword_get(&mesg, mesg, size)>0) 672 return -EINVAL; 673 674 /* we have all the words, they are in buf.. */ 675 dom = unix_domain_find(dname); 676 if (!dom) 677 return -ENOMEM; 678 679 len = exp_rootfh(dom, path, &fh, maxsize); 680 auth_domain_put(dom); 681 if (len) 682 return len; 683 684 mesg = buf; 685 len = SIMPLE_TRANSACTION_LIMIT; 686 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); 687 mesg[-1] = '\n'; 688 return mesg - buf; 689 } 690 691 /** 692 * write_threads - Start NFSD, or report the current number of running threads 693 * 694 * Input: 695 * buf: ignored 696 * size: zero 697 * Output: 698 * On success: passed-in buffer filled with '\n'-terminated C 699 * string numeric value representing the number of 700 * running NFSD threads; 701 * return code is the size in bytes of the string 702 * On error: return code is zero 703 * 704 * OR 705 * 706 * Input: 707 * buf: C string containing an unsigned 708 * integer value representing the 709 * number of NFSD threads to start 710 * size: non-zero length of C string in @buf 711 * Output: 712 * On success: NFS service is started; 713 * passed-in buffer filled with '\n'-terminated C 714 * string numeric value representing the number of 715 * running NFSD threads; 716 * return code is the size in bytes of the string 717 * On error: return code is zero or a negative errno value 718 */ 719 static ssize_t write_threads(struct file *file, char *buf, size_t size) 720 { 721 char *mesg = buf; 722 int rv; 723 if (size > 0) { 724 int newthreads; 725 rv = get_int(&mesg, &newthreads); 726 if (rv) 727 return rv; 728 if (newthreads < 0) 729 return -EINVAL; 730 rv = nfsd_svc(NFS_PORT, newthreads); 731 if (rv < 0) 732 return rv; 733 } else 734 rv = nfsd_nrthreads(); 735 736 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv); 737 } 738 739 /** 740 * write_pool_threads - Set or report the current number of threads per pool 741 * 742 * Input: 743 * buf: ignored 744 * size: zero 745 * 746 * OR 747 * 748 * Input: 749 * buf: C string containing whitespace- 750 * separated unsigned integer values 751 * representing the number of NFSD 752 * threads to start in each pool 753 * size: non-zero length of C string in @buf 754 * Output: 755 * On success: passed-in buffer filled with '\n'-terminated C 756 * string containing integer values representing the 757 * number of NFSD threads in each pool; 758 * return code is the size in bytes of the string 759 * On error: return code is zero or a negative errno value 760 */ 761 static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) 762 { 763 /* if size > 0, look for an array of number of threads per node 764 * and apply them then write out number of threads per node as reply 765 */ 766 char *mesg = buf; 767 int i; 768 int rv; 769 int len; 770 int npools; 771 int *nthreads; 772 773 mutex_lock(&nfsd_mutex); 774 npools = nfsd_nrpools(); 775 if (npools == 0) { 776 /* 777 * NFS is shut down. The admin can start it by 778 * writing to the threads file but NOT the pool_threads 779 * file, sorry. Report zero threads. 780 */ 781 mutex_unlock(&nfsd_mutex); 782 strcpy(buf, "0\n"); 783 return strlen(buf); 784 } 785 786 nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); 787 rv = -ENOMEM; 788 if (nthreads == NULL) 789 goto out_free; 790 791 if (size > 0) { 792 for (i = 0; i < npools; i++) { 793 rv = get_int(&mesg, &nthreads[i]); 794 if (rv == -ENOENT) 795 break; /* fewer numbers than pools */ 796 if (rv) 797 goto out_free; /* syntax error */ 798 rv = -EINVAL; 799 if (nthreads[i] < 0) 800 goto out_free; 801 } 802 rv = nfsd_set_nrthreads(i, nthreads); 803 if (rv) 804 goto out_free; 805 } 806 807 rv = nfsd_get_nrthreads(npools, nthreads); 808 if (rv) 809 goto out_free; 810 811 mesg = buf; 812 size = SIMPLE_TRANSACTION_LIMIT; 813 for (i = 0; i < npools && size > 0; i++) { 814 snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' ')); 815 len = strlen(mesg); 816 size -= len; 817 mesg += len; 818 } 819 rv = mesg - buf; 820 out_free: 821 kfree(nthreads); 822 mutex_unlock(&nfsd_mutex); 823 return rv; 824 } 825 826 static ssize_t __write_versions(struct file *file, char *buf, size_t size) 827 { 828 char *mesg = buf; 829 char *vers, *minorp, sign; 830 int len, num, remaining; 831 unsigned minor; 832 ssize_t tlen = 0; 833 char *sep; 834 835 if (size>0) { 836 if (nfsd_serv) 837 /* Cannot change versions without updating 838 * nfsd_serv->sv_xdrsize, and reallocing 839 * rq_argp and rq_resp 840 */ 841 return -EBUSY; 842 if (buf[size-1] != '\n') 843 return -EINVAL; 844 buf[size-1] = 0; 845 846 vers = mesg; 847 len = qword_get(&mesg, vers, size); 848 if (len <= 0) return -EINVAL; 849 do { 850 sign = *vers; 851 if (sign == '+' || sign == '-') 852 num = simple_strtol((vers+1), &minorp, 0); 853 else 854 num = simple_strtol(vers, &minorp, 0); 855 if (*minorp == '.') { 856 if (num < 4) 857 return -EINVAL; 858 minor = simple_strtoul(minorp+1, NULL, 0); 859 if (minor == 0) 860 return -EINVAL; 861 if (nfsd_minorversion(minor, sign == '-' ? 862 NFSD_CLEAR : NFSD_SET) < 0) 863 return -EINVAL; 864 goto next; 865 } 866 switch(num) { 867 case 2: 868 case 3: 869 case 4: 870 nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET); 871 break; 872 default: 873 return -EINVAL; 874 } 875 next: 876 vers += len + 1; 877 } while ((len = qword_get(&mesg, vers, size)) > 0); 878 /* If all get turned off, turn them back on, as 879 * having no versions is BAD 880 */ 881 nfsd_reset_versions(); 882 } 883 884 /* Now write current state into reply buffer */ 885 len = 0; 886 sep = ""; 887 remaining = SIMPLE_TRANSACTION_LIMIT; 888 for (num=2 ; num <= 4 ; num++) 889 if (nfsd_vers(num, NFSD_AVAIL)) { 890 len = snprintf(buf, remaining, "%s%c%d", sep, 891 nfsd_vers(num, NFSD_TEST)?'+':'-', 892 num); 893 sep = " "; 894 895 if (len > remaining) 896 break; 897 remaining -= len; 898 buf += len; 899 tlen += len; 900 } 901 if (nfsd_vers(4, NFSD_AVAIL)) 902 for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION; 903 minor++) { 904 len = snprintf(buf, remaining, " %c4.%u", 905 (nfsd_vers(4, NFSD_TEST) && 906 nfsd_minorversion(minor, NFSD_TEST)) ? 907 '+' : '-', 908 minor); 909 910 if (len > remaining) 911 break; 912 remaining -= len; 913 buf += len; 914 tlen += len; 915 } 916 917 len = snprintf(buf, remaining, "\n"); 918 if (len > remaining) 919 return -EINVAL; 920 return tlen + len; 921 } 922 923 /** 924 * write_versions - Set or report the available NFS protocol versions 925 * 926 * Input: 927 * buf: ignored 928 * size: zero 929 * Output: 930 * On success: passed-in buffer filled with '\n'-terminated C 931 * string containing positive or negative integer 932 * values representing the current status of each 933 * protocol version; 934 * return code is the size in bytes of the string 935 * On error: return code is zero or a negative errno value 936 * 937 * OR 938 * 939 * Input: 940 * buf: C string containing whitespace- 941 * separated positive or negative 942 * integer values representing NFS 943 * protocol versions to enable ("+n") 944 * or disable ("-n") 945 * size: non-zero length of C string in @buf 946 * Output: 947 * On success: status of zero or more protocol versions has 948 * been updated; passed-in buffer filled with 949 * '\n'-terminated C string containing positive 950 * or negative integer values representing the 951 * current status of each protocol version; 952 * return code is the size in bytes of the string 953 * On error: return code is zero or a negative errno value 954 */ 955 static ssize_t write_versions(struct file *file, char *buf, size_t size) 956 { 957 ssize_t rv; 958 959 mutex_lock(&nfsd_mutex); 960 rv = __write_versions(file, buf, size); 961 mutex_unlock(&nfsd_mutex); 962 return rv; 963 } 964 965 /* 966 * Zero-length write. Return a list of NFSD's current listener 967 * transports. 968 */ 969 static ssize_t __write_ports_names(char *buf) 970 { 971 if (nfsd_serv == NULL) 972 return 0; 973 return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT); 974 } 975 976 /* 977 * A single 'fd' number was written, in which case it must be for 978 * a socket of a supported family/protocol, and we use it as an 979 * nfsd listener. 980 */ 981 static ssize_t __write_ports_addfd(char *buf) 982 { 983 char *mesg = buf; 984 int fd, err; 985 986 err = get_int(&mesg, &fd); 987 if (err != 0 || fd < 0) 988 return -EINVAL; 989 990 err = nfsd_create_serv(); 991 if (err != 0) 992 return err; 993 994 err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); 995 if (err < 0) { 996 svc_destroy(nfsd_serv); 997 return err; 998 } 999 1000 /* Decrease the count, but don't shut down the service */ 1001 nfsd_serv->sv_nrthreads--; 1002 return err; 1003 } 1004 1005 /* 1006 * A '-' followed by the 'name' of a socket means we close the socket. 1007 */ 1008 static ssize_t __write_ports_delfd(char *buf) 1009 { 1010 char *toclose; 1011 int len = 0; 1012 1013 toclose = kstrdup(buf + 1, GFP_KERNEL); 1014 if (toclose == NULL) 1015 return -ENOMEM; 1016 1017 if (nfsd_serv != NULL) 1018 len = svc_sock_names(nfsd_serv, buf, 1019 SIMPLE_TRANSACTION_LIMIT, toclose); 1020 kfree(toclose); 1021 return len; 1022 } 1023 1024 /* 1025 * A transport listener is added by writing it's transport name and 1026 * a port number. 1027 */ 1028 static ssize_t __write_ports_addxprt(char *buf) 1029 { 1030 char transport[16]; 1031 struct svc_xprt *xprt; 1032 int port, err; 1033 1034 if (sscanf(buf, "%15s %4u", transport, &port) != 2) 1035 return -EINVAL; 1036 1037 if (port < 1 || port > USHRT_MAX) 1038 return -EINVAL; 1039 1040 err = nfsd_create_serv(); 1041 if (err != 0) 1042 return err; 1043 1044 err = svc_create_xprt(nfsd_serv, transport, &init_net, 1045 PF_INET, port, SVC_SOCK_ANONYMOUS); 1046 if (err < 0) 1047 goto out_err; 1048 1049 err = svc_create_xprt(nfsd_serv, transport, &init_net, 1050 PF_INET6, port, SVC_SOCK_ANONYMOUS); 1051 if (err < 0 && err != -EAFNOSUPPORT) 1052 goto out_close; 1053 1054 /* Decrease the count, but don't shut down the service */ 1055 nfsd_serv->sv_nrthreads--; 1056 return 0; 1057 out_close: 1058 xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); 1059 if (xprt != NULL) { 1060 svc_close_xprt(xprt); 1061 svc_xprt_put(xprt); 1062 } 1063 out_err: 1064 svc_destroy(nfsd_serv); 1065 return err; 1066 } 1067 1068 /* 1069 * A transport listener is removed by writing a "-", it's transport 1070 * name, and it's port number. 1071 */ 1072 static ssize_t __write_ports_delxprt(char *buf) 1073 { 1074 struct svc_xprt *xprt; 1075 char transport[16]; 1076 int port; 1077 1078 if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2) 1079 return -EINVAL; 1080 1081 if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) 1082 return -EINVAL; 1083 1084 xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port); 1085 if (xprt == NULL) 1086 return -ENOTCONN; 1087 1088 svc_close_xprt(xprt); 1089 svc_xprt_put(xprt); 1090 return 0; 1091 } 1092 1093 static ssize_t __write_ports(struct file *file, char *buf, size_t size) 1094 { 1095 if (size == 0) 1096 return __write_ports_names(buf); 1097 1098 if (isdigit(buf[0])) 1099 return __write_ports_addfd(buf); 1100 1101 if (buf[0] == '-' && isdigit(buf[1])) 1102 return __write_ports_delfd(buf); 1103 1104 if (isalpha(buf[0])) 1105 return __write_ports_addxprt(buf); 1106 1107 if (buf[0] == '-' && isalpha(buf[1])) 1108 return __write_ports_delxprt(buf); 1109 1110 return -EINVAL; 1111 } 1112 1113 /** 1114 * write_ports - Pass a socket file descriptor or transport name to listen on 1115 * 1116 * Input: 1117 * buf: ignored 1118 * size: zero 1119 * Output: 1120 * On success: passed-in buffer filled with a '\n'-terminated C 1121 * string containing a whitespace-separated list of 1122 * named NFSD listeners; 1123 * return code is the size in bytes of the string 1124 * On error: return code is zero or a negative errno value 1125 * 1126 * OR 1127 * 1128 * Input: 1129 * buf: C string containing an unsigned 1130 * integer value representing a bound 1131 * but unconnected socket that is to be 1132 * used as an NFSD listener; listen(3) 1133 * must be called for a SOCK_STREAM 1134 * socket, otherwise it is ignored 1135 * size: non-zero length of C string in @buf 1136 * Output: 1137 * On success: NFS service is started; 1138 * passed-in buffer filled with a '\n'-terminated C 1139 * string containing a unique alphanumeric name of 1140 * the listener; 1141 * return code is the size in bytes of the string 1142 * On error: return code is a negative errno value 1143 * 1144 * OR 1145 * 1146 * Input: 1147 * buf: C string containing a "-" followed 1148 * by an integer value representing a 1149 * previously passed in socket file 1150 * descriptor 1151 * size: non-zero length of C string in @buf 1152 * Output: 1153 * On success: NFS service no longer listens on that socket; 1154 * passed-in buffer filled with a '\n'-terminated C 1155 * string containing a unique name of the listener; 1156 * return code is the size in bytes of the string 1157 * On error: return code is a negative errno value 1158 * 1159 * OR 1160 * 1161 * Input: 1162 * buf: C string containing a transport 1163 * name and an unsigned integer value 1164 * representing the port to listen on, 1165 * separated by whitespace 1166 * size: non-zero length of C string in @buf 1167 * Output: 1168 * On success: returns zero; NFS service is started 1169 * On error: return code is a negative errno value 1170 * 1171 * OR 1172 * 1173 * Input: 1174 * buf: C string containing a "-" followed 1175 * by a transport name and an unsigned 1176 * integer value representing the port 1177 * to listen on, separated by whitespace 1178 * size: non-zero length of C string in @buf 1179 * Output: 1180 * On success: returns zero; NFS service no longer listens 1181 * on that transport 1182 * On error: return code is a negative errno value 1183 */ 1184 static ssize_t write_ports(struct file *file, char *buf, size_t size) 1185 { 1186 ssize_t rv; 1187 1188 mutex_lock(&nfsd_mutex); 1189 rv = __write_ports(file, buf, size); 1190 mutex_unlock(&nfsd_mutex); 1191 return rv; 1192 } 1193 1194 1195 int nfsd_max_blksize; 1196 1197 /** 1198 * write_maxblksize - Set or report the current NFS blksize 1199 * 1200 * Input: 1201 * buf: ignored 1202 * size: zero 1203 * 1204 * OR 1205 * 1206 * Input: 1207 * buf: C string containing an unsigned 1208 * integer value representing the new 1209 * NFS blksize 1210 * size: non-zero length of C string in @buf 1211 * Output: 1212 * On success: passed-in buffer filled with '\n'-terminated C string 1213 * containing numeric value of the current NFS blksize 1214 * setting; 1215 * return code is the size in bytes of the string 1216 * On error: return code is zero or a negative errno value 1217 */ 1218 static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 1219 { 1220 char *mesg = buf; 1221 if (size > 0) { 1222 int bsize; 1223 int rv = get_int(&mesg, &bsize); 1224 if (rv) 1225 return rv; 1226 /* force bsize into allowed range and 1227 * required alignment. 1228 */ 1229 if (bsize < 1024) 1230 bsize = 1024; 1231 if (bsize > NFSSVC_MAXBLKSIZE) 1232 bsize = NFSSVC_MAXBLKSIZE; 1233 bsize &= ~(1024-1); 1234 mutex_lock(&nfsd_mutex); 1235 if (nfsd_serv) { 1236 mutex_unlock(&nfsd_mutex); 1237 return -EBUSY; 1238 } 1239 nfsd_max_blksize = bsize; 1240 mutex_unlock(&nfsd_mutex); 1241 } 1242 1243 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", 1244 nfsd_max_blksize); 1245 } 1246 1247 #ifdef CONFIG_NFSD_V4 1248 static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 1249 { 1250 char *mesg = buf; 1251 int rv, i; 1252 1253 if (size > 0) { 1254 if (nfsd_serv) 1255 return -EBUSY; 1256 rv = get_int(&mesg, &i); 1257 if (rv) 1258 return rv; 1259 /* 1260 * Some sanity checking. We don't have a reason for 1261 * these particular numbers, but problems with the 1262 * extremes are: 1263 * - Too short: the briefest network outage may 1264 * cause clients to lose all their locks. Also, 1265 * the frequent polling may be wasteful. 1266 * - Too long: do you really want reboot recovery 1267 * to take more than an hour? Or to make other 1268 * clients wait an hour before being able to 1269 * revoke a dead client's locks? 1270 */ 1271 if (i < 10 || i > 3600) 1272 return -EINVAL; 1273 *time = i; 1274 } 1275 1276 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time); 1277 } 1278 1279 static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size, time_t *time) 1280 { 1281 ssize_t rv; 1282 1283 mutex_lock(&nfsd_mutex); 1284 rv = __nfsd4_write_time(file, buf, size, time); 1285 mutex_unlock(&nfsd_mutex); 1286 return rv; 1287 } 1288 1289 /** 1290 * write_leasetime - Set or report the current NFSv4 lease time 1291 * 1292 * Input: 1293 * buf: ignored 1294 * size: zero 1295 * 1296 * OR 1297 * 1298 * Input: 1299 * buf: C string containing an unsigned 1300 * integer value representing the new 1301 * NFSv4 lease expiry time 1302 * size: non-zero length of C string in @buf 1303 * Output: 1304 * On success: passed-in buffer filled with '\n'-terminated C 1305 * string containing unsigned integer value of the 1306 * current lease expiry time; 1307 * return code is the size in bytes of the string 1308 * On error: return code is zero or a negative errno value 1309 */ 1310 static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 1311 { 1312 return nfsd4_write_time(file, buf, size, &nfsd4_lease); 1313 } 1314 1315 /** 1316 * write_gracetime - Set or report current NFSv4 grace period time 1317 * 1318 * As above, but sets the time of the NFSv4 grace period. 1319 * 1320 * Note this should never be set to less than the *previous* 1321 * lease-period time, but we don't try to enforce this. (In the common 1322 * case (a new boot), we don't know what the previous lease time was 1323 * anyway.) 1324 */ 1325 static ssize_t write_gracetime(struct file *file, char *buf, size_t size) 1326 { 1327 return nfsd4_write_time(file, buf, size, &nfsd4_grace); 1328 } 1329 1330 extern char *nfs4_recoverydir(void); 1331 1332 static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 1333 { 1334 char *mesg = buf; 1335 char *recdir; 1336 int len, status; 1337 1338 if (size > 0) { 1339 if (nfsd_serv) 1340 return -EBUSY; 1341 if (size > PATH_MAX || buf[size-1] != '\n') 1342 return -EINVAL; 1343 buf[size-1] = 0; 1344 1345 recdir = mesg; 1346 len = qword_get(&mesg, recdir, size); 1347 if (len <= 0) 1348 return -EINVAL; 1349 1350 status = nfs4_reset_recoverydir(recdir); 1351 if (status) 1352 return status; 1353 } 1354 1355 return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n", 1356 nfs4_recoverydir()); 1357 } 1358 1359 /** 1360 * write_recoverydir - Set or report the pathname of the recovery directory 1361 * 1362 * Input: 1363 * buf: ignored 1364 * size: zero 1365 * 1366 * OR 1367 * 1368 * Input: 1369 * buf: C string containing the pathname 1370 * of the directory on a local file 1371 * system containing permanent NFSv4 1372 * recovery data 1373 * size: non-zero length of C string in @buf 1374 * Output: 1375 * On success: passed-in buffer filled with '\n'-terminated C string 1376 * containing the current recovery pathname setting; 1377 * return code is the size in bytes of the string 1378 * On error: return code is zero or a negative errno value 1379 */ 1380 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 1381 { 1382 ssize_t rv; 1383 1384 mutex_lock(&nfsd_mutex); 1385 rv = __write_recoverydir(file, buf, size); 1386 mutex_unlock(&nfsd_mutex); 1387 return rv; 1388 } 1389 1390 #endif 1391 1392 /*----------------------------------------------------------------------------*/ 1393 /* 1394 * populating the filesystem. 1395 */ 1396 1397 static int nfsd_fill_super(struct super_block * sb, void * data, int silent) 1398 { 1399 static struct tree_descr nfsd_files[] = { 1400 #ifdef CONFIG_NFSD_DEPRECATED 1401 [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR}, 1402 [NFSD_Add] = {".add", &transaction_ops, S_IWUSR}, 1403 [NFSD_Del] = {".del", &transaction_ops, S_IWUSR}, 1404 [NFSD_Export] = {".export", &transaction_ops, S_IWUSR}, 1405 [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR}, 1406 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, 1407 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, 1408 #endif 1409 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 1410 [NFSD_Export_features] = {"export_features", 1411 &export_features_operations, S_IRUGO}, 1412 [NFSD_FO_UnlockIP] = {"unlock_ip", 1413 &transaction_ops, S_IWUSR|S_IRUSR}, 1414 [NFSD_FO_UnlockFS] = {"unlock_filesystem", 1415 &transaction_ops, S_IWUSR|S_IRUSR}, 1416 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 1417 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 1418 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, 1419 [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO}, 1420 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1421 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1422 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1423 #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) 1424 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, 1425 #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ 1426 #ifdef CONFIG_NFSD_V4 1427 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1428 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1429 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, 1430 #endif 1431 /* last one */ {""} 1432 }; 1433 return simple_fill_super(sb, 0x6e667364, nfsd_files); 1434 } 1435 1436 static struct dentry *nfsd_mount(struct file_system_type *fs_type, 1437 int flags, const char *dev_name, void *data) 1438 { 1439 return mount_single(fs_type, flags, data, nfsd_fill_super); 1440 } 1441 1442 static struct file_system_type nfsd_fs_type = { 1443 .owner = THIS_MODULE, 1444 .name = "nfsd", 1445 .mount = nfsd_mount, 1446 .kill_sb = kill_litter_super, 1447 }; 1448 1449 #ifdef CONFIG_PROC_FS 1450 static int create_proc_exports_entry(void) 1451 { 1452 struct proc_dir_entry *entry; 1453 1454 entry = proc_mkdir("fs/nfs", NULL); 1455 if (!entry) 1456 return -ENOMEM; 1457 entry = proc_create("exports", 0, entry, &exports_operations); 1458 if (!entry) 1459 return -ENOMEM; 1460 return 0; 1461 } 1462 #else /* CONFIG_PROC_FS */ 1463 static int create_proc_exports_entry(void) 1464 { 1465 return 0; 1466 } 1467 #endif 1468 1469 static int __init init_nfsd(void) 1470 { 1471 int retval; 1472 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); 1473 1474 retval = nfs4_state_init(); /* nfs4 locking state */ 1475 if (retval) 1476 return retval; 1477 nfsd_stat_init(); /* Statistics */ 1478 retval = nfsd_reply_cache_init(); 1479 if (retval) 1480 goto out_free_stat; 1481 retval = nfsd_export_init(); 1482 if (retval) 1483 goto out_free_cache; 1484 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 1485 retval = nfsd_idmap_init(); 1486 if (retval) 1487 goto out_free_lockd; 1488 retval = create_proc_exports_entry(); 1489 if (retval) 1490 goto out_free_idmap; 1491 retval = register_filesystem(&nfsd_fs_type); 1492 if (retval) 1493 goto out_free_all; 1494 return 0; 1495 out_free_all: 1496 remove_proc_entry("fs/nfs/exports", NULL); 1497 remove_proc_entry("fs/nfs", NULL); 1498 out_free_idmap: 1499 nfsd_idmap_shutdown(); 1500 out_free_lockd: 1501 nfsd_lockd_shutdown(); 1502 nfsd_export_shutdown(); 1503 out_free_cache: 1504 nfsd_reply_cache_shutdown(); 1505 out_free_stat: 1506 nfsd_stat_shutdown(); 1507 nfsd4_free_slabs(); 1508 return retval; 1509 } 1510 1511 static void __exit exit_nfsd(void) 1512 { 1513 nfsd_export_shutdown(); 1514 nfsd_reply_cache_shutdown(); 1515 remove_proc_entry("fs/nfs/exports", NULL); 1516 remove_proc_entry("fs/nfs", NULL); 1517 nfsd_stat_shutdown(); 1518 nfsd_lockd_shutdown(); 1519 nfsd_idmap_shutdown(); 1520 nfsd4_free_slabs(); 1521 unregister_filesystem(&nfsd_fs_type); 1522 } 1523 1524 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); 1525 MODULE_LICENSE("GPL"); 1526 module_init(init_nfsd) 1527 module_exit(exit_nfsd) 1528