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