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