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