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