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