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