original development tree for Linux kernel GTP module; now long in mainline.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1217 lines
30 KiB

include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo <tj@kernel.org> Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
12 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
llseek: automatically add .llseek fop All file_operations should get a .llseek operation so we can make nonseekable_open the default for future file operations without a .llseek pointer. The three cases that we can automatically detect are no_llseek, seq_lseek and default_llseek. For cases where we can we can automatically prove that the file offset is always ignored, we use noop_llseek, which maintains the current behavior of not returning an error from a seek. New drivers should normally not use noop_llseek but instead use no_llseek and call nonseekable_open at open time. Existing drivers can be converted to do the same when the maintainer knows for certain that no user code relies on calling seek on the device file. The generated code is often incorrectly indented and right now contains comments that clarify for each added line why a specific variant was chosen. In the version that gets submitted upstream, the comments will be gone and I will manually fix the indentation, because there does not seem to be a way to do that using coccinelle. Some amount of new code is currently sitting in linux-next that should get the same modifications, which I will do at the end of the merge window. Many thanks to Julia Lawall for helping me learn to write a semantic patch that does all this. ===== begin semantic patch ===== // This adds an llseek= method to all file operations, // as a preparation for making no_llseek the default. // // The rules are // - use no_llseek explicitly if we do nonseekable_open // - use seq_lseek for sequential files // - use default_llseek if we know we access f_pos // - use noop_llseek if we know we don't access f_pos, // but we still want to allow users to call lseek // @ open1 exists @ identifier nested_open; @@ nested_open(...) { <+... nonseekable_open(...) ...+> } @ open exists@ identifier open_f; identifier i, f; identifier open1.nested_open; @@ int open_f(struct inode *i, struct file *f) { <+... ( nonseekable_open(...) | nested_open(...) ) ...+> } @ read disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ read_no_fpos disable optional_qualifier exists @ identifier read_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off) { ... when != off } @ write @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; expression E; identifier func; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { <+... ( *off = E | *off += E | func(..., off, ...) | E = *off ) ...+> } @ write_no_fpos @ identifier write_f; identifier f, p, s, off; type ssize_t, size_t, loff_t; @@ ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off) { ... when != off } @ fops0 @ identifier fops; @@ struct file_operations fops = { ... }; @ has_llseek depends on fops0 @ identifier fops0.fops; identifier llseek_f; @@ struct file_operations fops = { ... .llseek = llseek_f, ... }; @ has_read depends on fops0 @ identifier fops0.fops; identifier read_f; @@ struct file_operations fops = { ... .read = read_f, ... }; @ has_write depends on fops0 @ identifier fops0.fops; identifier write_f; @@ struct file_operations fops = { ... .write = write_f, ... }; @ has_open depends on fops0 @ identifier fops0.fops; identifier open_f; @@ struct file_operations fops = { ... .open = open_f, ... }; // use no_llseek if we call nonseekable_open //////////////////////////////////////////// @ nonseekable1 depends on !has_llseek && has_open @ identifier fops0.fops; identifier nso ~= "nonseekable_open"; @@ struct file_operations fops = { ... .open = nso, ... +.llseek = no_llseek, /* nonseekable */ }; @ nonseekable2 depends on !has_llseek @ identifier fops0.fops; identifier open.open_f; @@ struct file_operations fops = { ... .open = open_f, ... +.llseek = no_llseek, /* open uses nonseekable */ }; // use seq_lseek for sequential files ///////////////////////////////////// @ seq depends on !has_llseek @ identifier fops0.fops; identifier sr ~= "seq_read"; @@ struct file_operations fops = { ... .read = sr, ... +.llseek = seq_lseek, /* we have seq_read */ }; // use default_llseek if there is a readdir /////////////////////////////////////////// @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier readdir_e; @@ // any other fop is used that changes pos struct file_operations fops = { ... .readdir = readdir_e, ... +.llseek = default_llseek, /* readdir is present */ }; // use default_llseek if at least one of read/write touches f_pos ///////////////////////////////////////////////////////////////// @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read.read_f; @@ // read fops use offset struct file_operations fops = { ... .read = read_f, ... +.llseek = default_llseek, /* read accesses f_pos */ }; @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, ... + .llseek = default_llseek, /* write accesses f_pos */ }; // Use noop_llseek if neither read nor write accesses f_pos /////////////////////////////////////////////////////////// @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; identifier write_no_fpos.write_f; @@ // write fops use offset struct file_operations fops = { ... .write = write_f, .read = read_f, ... +.llseek = noop_llseek, /* read and write both use no f_pos */ }; @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier write_no_fpos.write_f; @@ struct file_operations fops = { ... .write = write_f, ... +.llseek = noop_llseek, /* write uses no f_pos */ }; @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; identifier read_no_fpos.read_f; @@ struct file_operations fops = { ... .read = read_f, ... +.llseek = noop_llseek, /* read uses no f_pos */ }; @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @ identifier fops0.fops; @@ struct file_operations fops = { ... +.llseek = noop_llseek, /* no read or write fn */ }; ===== End semantic patch ===== Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: Julia Lawall <julia@diku.dk> Cc: Christoph Hellwig <hch@infradead.org>
11 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
lockd: unlock lockd locks associated with a given server ip For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
14 years ago
fs: Limit sys_mount to only request filesystem modules. Modify the request_module to prefix the file system type with "fs-" and add aliases to all of the filesystems that can be built as modules to match. A common practice is to build all of the kernel code and leave code that is not commonly needed as modules, with the result that many users are exposed to any bug anywhere in the kernel. Looking for filesystems with a fs- prefix limits the pool of possible modules that can be loaded by mount to just filesystems trivially making things safer with no real cost. Using aliases means user space can control the policy of which filesystem modules are auto-loaded by editing /etc/modprobe.d/*.conf with blacklist and alias directives. Allowing simple, safe, well understood work-arounds to known problematic software. This also addresses a rare but unfortunate problem where the filesystem name is not the same as it's module name and module auto-loading would not work. While writing this patch I saw a handful of such cases. The most significant being autofs that lives in the module autofs4. This is relevant to user namespaces because we can reach the request module in get_fs_type() without having any special permissions, and people get uncomfortable when a user specified string (in this case the filesystem type) goes all of the way to request_module. After having looked at this issue I don't think there is any particular reason to perform any filtering or permission checks beyond making it clear in the module request that we want a filesystem module. The common pattern in the kernel is to call request_module() without regards to the users permissions. In general all a filesystem module does once loaded is call register_filesystem() and go to sleep. Which means there is not much attack surface exposed by loading a filesytem module unless the filesystem is mounted. In a user namespace filesystems are not mounted unless .fs_flags = FS_USERNS_MOUNT, which most filesystems do not set today. Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Acked-by: Kees Cook <keescook@chromium.org> Reported-by: Kees Cook <keescook@google.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
9 years ago
  1. /*
  2. * Syscall interface to knfsd.
  3. *
  4. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  5. */
  6. #include <linux/slab.h>
  7. #include <linux/namei.h>
  8. #include <linux/ctype.h>
  9. #include <linux/sunrpc/svcsock.h>
  10. #include <linux/lockd/lockd.h>
  11. #include <linux/sunrpc/addr.h>
  12. #include <linux/sunrpc/gss_api.h>
  13. #include <linux/sunrpc/gss_krb5_enctypes.h>
  14. #include <linux/sunrpc/rpc_pipe_fs.h>
  15. #include <linux/module.h>
  16. #include "idmap.h"
  17. #include "nfsd.h"
  18. #include "cache.h"
  19. #include "state.h"
  20. #include "netns.h"
  21. /*
  22. * We have a single directory with several nodes in it.
  23. */
  24. enum {
  25. NFSD_Root = 1,
  26. NFSD_List,
  27. NFSD_Export_features,
  28. NFSD_Fh,
  29. NFSD_FO_UnlockIP,
  30. NFSD_FO_UnlockFS,
  31. NFSD_Threads,
  32. NFSD_Pool_Threads,
  33. NFSD_Pool_Stats,
  34. NFSD_Versions,
  35. NFSD_Ports,
  36. NFSD_MaxBlkSize,
  37. NFSD_SupportedEnctypes,
  38. /*
  39. * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
  40. * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
  41. */
  42. #ifdef CONFIG_NFSD_V4
  43. NFSD_Leasetime,
  44. NFSD_Gracetime,
  45. NFSD_RecoveryDir,
  46. #endif
  47. };
  48. /*
  49. * write() for these nodes.
  50. */
  51. static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
  52. static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
  53. static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
  54. static ssize_t write_threads(struct file *file, char *buf, size_t size);
  55. static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
  56. static ssize_t write_versions(struct file *file, char *buf, size_t size);
  57. static ssize_t write_ports(struct file *file, char *buf, size_t size);
  58. static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
  59. #ifdef CONFIG_NFSD_V4
  60. static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
  61. static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
  62. static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
  63. #endif
  64. static ssize_t (*write_op[])(struct file *, char *, size_t) = {
  65. [NFSD_Fh] = write_filehandle,
  66. [NFSD_FO_UnlockIP] = write_unlock_ip,
  67. [NFSD_FO_UnlockFS] = write_unlock_fs,
  68. [NFSD_Threads] = write_threads,
  69. [NFSD_Pool_Threads] = write_pool_threads,
  70. [NFSD_Versions] = write_versions,
  71. [NFSD_Ports] = write_ports,
  72. [NFSD_MaxBlkSize] = write_maxblksize,
  73. #ifdef CONFIG_NFSD_V4
  74. [NFSD_Leasetime] = write_leasetime,
  75. [NFSD_Gracetime] = write_gracetime,
  76. [NFSD_RecoveryDir] = write_recoverydir,
  77. #endif
  78. };
  79. static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
  80. {
  81. ino_t ino = file_inode(file)->i_ino;
  82. char *data;
  83. ssize_t rv;
  84. if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
  85. return -EINVAL;
  86. data = simple_transaction_get(file, buf, size);
  87. if (IS_ERR(data))
  88. return PTR_ERR(data);
  89. rv = write_op[ino](file, data, size);
  90. if (rv >= 0) {
  91. simple_transaction_set(file, rv);
  92. rv = size;
  93. }
  94. return rv;
  95. }
  96. static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
  97. {
  98. if (! file->private_data) {
  99. /* An attempt to read a transaction file without writing
  100. * causes a 0-byte write so that the file can return
  101. * state information
  102. */
  103. ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
  104. if (rv < 0)
  105. return rv;
  106. }
  107. return simple_transaction_read(file, buf, size, pos);
  108. }
  109. static const struct file_operations transaction_ops = {
  110. .write = nfsctl_transaction_write,
  111. .read = nfsctl_transaction_read,
  112. .release = simple_transaction_release,
  113. .llseek = default_llseek,
  114. };
  115. static int exports_net_open(struct net *net, struct file *file)
  116. {
  117. int err;
  118. struct seq_file *seq;
  119. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  120. err = seq_open(file, &nfs_exports_op);
  121. if (err)
  122. return err;
  123. seq = file->private_data;
  124. seq->private = nn->svc_export_cache;
  125. return 0;
  126. }
  127. static int exports_proc_open(struct inode *inode, struct file *file)
  128. {
  129. return exports_net_open(current->nsproxy->net_ns, file);
  130. }
  131. static const struct file_operations exports_proc_operations = {
  132. .open = exports_proc_open,
  133. .read = seq_read,
  134. .llseek = seq_lseek,
  135. .release = seq_release,
  136. .owner = THIS_MODULE,
  137. };
  138. static int exports_nfsd_open(struct inode *inode, struct file *file)
  139. {
  140. return exports_net_open(inode->i_sb->s_fs_info, file);
  141. }
  142. static const struct file_operations exports_nfsd_operations = {
  143. .open = exports_nfsd_open,
  144. .read = seq_read,
  145. .llseek = seq_lseek,
  146. .release = seq_release,
  147. .owner = THIS_MODULE,
  148. };
  149. static int export_features_show(struct seq_file *m, void *v)
  150. {
  151. seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
  152. return 0;
  153. }
  154. static int export_features_open(struct inode *inode, struct file *file)
  155. {
  156. return single_open(file, export_features_show, NULL);
  157. }
  158. static struct file_operations export_features_operations = {
  159. .open = export_features_open,
  160. .read = seq_read,
  161. .llseek = seq_lseek,
  162. .release = single_release,
  163. };
  164. #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
  165. static int supported_enctypes_show(struct seq_file *m, void *v)
  166. {
  167. seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
  168. return 0;
  169. }
  170. static int supported_enctypes_open(struct inode *inode, struct file *file)
  171. {
  172. return single_open(file, supported_enctypes_show, NULL);
  173. }
  174. static struct file_operations supported_enctypes_ops = {
  175. .open = supported_enctypes_open,
  176. .read = seq_read,
  177. .llseek = seq_lseek,
  178. .release = single_release,
  179. };
  180. #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
  181. static const struct file_operations pool_stats_operations = {
  182. .open = nfsd_pool_stats_open,
  183. .read = seq_read,
  184. .llseek = seq_lseek,
  185. .release = nfsd_pool_stats_release,
  186. .owner = THIS_MODULE,
  187. };
  188. /*----------------------------------------------------------------------------*/
  189. /*
  190. * payload - write methods
  191. */
  192. /**
  193. * write_unlock_ip - Release all locks used by a client
  194. *
  195. * Experimental.
  196. *
  197. * Input:
  198. * buf: '\n'-terminated C string containing a
  199. * presentation format IP address
  200. * size: length of C string in @buf
  201. * Output:
  202. * On success: returns zero if all specified locks were released;
  203. * returns one if one or more locks were not released
  204. * On error: return code is negative errno value
  205. */
  206. static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
  207. {
  208. struct sockaddr_storage address;
  209. struct sockaddr *sap = (struct sockaddr *)&address;
  210. size_t salen = sizeof(address);
  211. char *fo_path;
  212. struct net *net = file->f_dentry->d_sb->s_fs_info;
  213. /* sanity check */
  214. if (size == 0)
  215. return -EINVAL;
  216. if (buf[size-1] != '\n')
  217. return -EINVAL;
  218. fo_path = buf;
  219. if (qword_get(&buf, fo_path, size) < 0)
  220. return -EINVAL;
  221. if (rpc_pton(net, fo_path, size, sap, salen) == 0)
  222. return -EINVAL;
  223. return nlmsvc_unlock_all_by_ip(sap);
  224. }
  225. /**
  226. * write_unlock_fs - Release all locks on a local file system
  227. *
  228. * Experimental.
  229. *
  230. * Input:
  231. * buf: '\n'-terminated C string containing the
  232. * absolute pathname of a local file system
  233. * size: length of C string in @buf
  234. * Output:
  235. * On success: returns zero if all specified locks were released;
  236. * returns one if one or more locks were not released
  237. * On error: return code is negative errno value
  238. */
  239. static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
  240. {
  241. struct path path;
  242. char *fo_path;
  243. int error;
  244. /* sanity check */
  245. if (size == 0)
  246. return -EINVAL;
  247. if (buf[size-1] != '\n')
  248. return -EINVAL;
  249. fo_path = buf;
  250. if (qword_get(&buf, fo_path, size) < 0)
  251. return -EINVAL;
  252. error = kern_path(fo_path, 0, &path);
  253. if (error)
  254. return error;
  255. /*
  256. * XXX: Needs better sanity checking. Otherwise we could end up
  257. * releasing locks on the wrong file system.
  258. *
  259. * For example:
  260. * 1. Does the path refer to a directory?
  261. * 2. Is that directory a mount point, or
  262. * 3. Is that directory the root of an exported file system?
  263. */
  264. error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
  265. path_put(&path);
  266. return error;
  267. }
  268. /**
  269. * write_filehandle - Get a variable-length NFS file handle by path
  270. *
  271. * On input, the buffer contains a '\n'-terminated C string comprised of
  272. * three alphanumeric words separated by whitespace. The string may
  273. * contain escape sequences.
  274. *
  275. * Input:
  276. * buf:
  277. * domain: client domain name
  278. * path: export pathname
  279. * maxsize: numeric maximum size of
  280. * @buf
  281. * size: length of C string in @buf
  282. * Output:
  283. * On success: passed-in buffer filled with '\n'-terminated C
  284. * string containing a ASCII hex text version
  285. * of the NFS file handle;
  286. * return code is the size in bytes of the string
  287. * On error: return code is negative errno value
  288. */
  289. static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
  290. {
  291. char *dname, *path;
  292. int uninitialized_var(maxsize);
  293. char *mesg = buf;
  294. int len;
  295. struct auth_domain *dom;
  296. struct knfsd_fh fh;
  297. struct net *net = file->f_dentry->d_sb->s_fs_info;
  298. if (size == 0)
  299. return -EINVAL;
  300. if (buf[size-1] != '\n')
  301. return -EINVAL;
  302. buf[size-1] = 0;
  303. dname = mesg;
  304. len = qword_get(&mesg, dname, size);
  305. if (len <= 0)
  306. return -EINVAL;
  307. path = dname+len+1;
  308. len = qword_get(&mesg, path, size);
  309. if (len <= 0)
  310. return -EINVAL;
  311. len = get_int(&mesg, &maxsize);
  312. if (len)
  313. return len;
  314. if (maxsize < NFS_FHSIZE)
  315. return -EINVAL;
  316. if (maxsize > NFS3_FHSIZE)
  317. maxsize = NFS3_FHSIZE;
  318. if (qword_get(&mesg, mesg, size)>0)
  319. return -EINVAL;
  320. /* we have all the words, they are in buf.. */
  321. dom = unix_domain_find(dname);
  322. if (!dom)
  323. return -ENOMEM;
  324. len = exp_rootfh(net, dom, path, &fh, maxsize);
  325. auth_domain_put(dom);
  326. if (len)
  327. return len;
  328. mesg = buf;
  329. len = SIMPLE_TRANSACTION_LIMIT;
  330. qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
  331. mesg[-1] = '\n';
  332. return mesg - buf;
  333. }
  334. /**
  335. * write_threads - Start NFSD, or report the current number of running threads
  336. *
  337. * Input:
  338. * buf: ignored
  339. * size: zero
  340. * Output:
  341. * On success: passed-in buffer filled with '\n'-terminated C
  342. * string numeric value representing the number of
  343. * running NFSD threads;
  344. * return code is the size in bytes of the string
  345. * On error: return code is zero
  346. *
  347. * OR
  348. *
  349. * Input:
  350. * buf: C string containing an unsigned
  351. * integer value representing the
  352. * number of NFSD threads to start
  353. * size: non-zero length of C string in @buf
  354. * Output:
  355. * On success: NFS service is started;
  356. * passed-in buffer filled with '\n'-terminated C
  357. * string numeric value representing the number of
  358. * running NFSD threads;
  359. * return code is the size in bytes of the string
  360. * On error: return code is zero or a negative errno value
  361. */
  362. static ssize_t write_threads(struct file *file, char *buf, size_t size)
  363. {
  364. char *mesg = buf;
  365. int rv;
  366. struct net *net = file->f_dentry->d_sb->s_fs_info;
  367. if (size > 0) {
  368. int newthreads;
  369. rv = get_int(&mesg, &newthreads);
  370. if (rv)
  371. return rv;
  372. if (newthreads < 0)
  373. return -EINVAL;
  374. rv = nfsd_svc(newthreads, net);
  375. if (rv < 0)
  376. return rv;
  377. } else
  378. rv = nfsd_nrthreads(net);
  379. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
  380. }
  381. /**
  382. * write_pool_threads - Set or report the current number of threads per pool
  383. *
  384. * Input:
  385. * buf: ignored
  386. * size: zero
  387. *
  388. * OR
  389. *
  390. * Input:
  391. * buf: C string containing whitespace-
  392. * separated unsigned integer values
  393. * representing the number of NFSD
  394. * threads to start in each pool
  395. * size: non-zero length of C string in @buf
  396. * Output:
  397. * On success: passed-in buffer filled with '\n'-terminated C
  398. * string containing integer values representing the
  399. * number of NFSD threads in each pool;
  400. * return code is the size in bytes of the string
  401. * On error: return code is zero or a negative errno value
  402. */
  403. static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
  404. {
  405. /* if size > 0, look for an array of number of threads per node
  406. * and apply them then write out number of threads per node as reply
  407. */
  408. char *mesg = buf;
  409. int i;
  410. int rv;
  411. int len;
  412. int npools;
  413. int *nthreads;
  414. struct net *net = file->f_dentry->d_sb->s_fs_info;
  415. mutex_lock(&nfsd_mutex);
  416. npools = nfsd_nrpools(net);
  417. if (npools == 0) {
  418. /*
  419. * NFS is shut down. The admin can start it by
  420. * writing to the threads file but NOT the pool_threads
  421. * file, sorry. Report zero threads.
  422. */
  423. mutex_unlock(&nfsd_mutex);
  424. strcpy(buf, "0\n");
  425. return strlen(buf);
  426. }
  427. nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
  428. rv = -ENOMEM;
  429. if (nthreads == NULL)
  430. goto out_free;
  431. if (size > 0) {
  432. for (i = 0; i < npools; i++) {
  433. rv = get_int(&mesg, &nthreads[i]);
  434. if (rv == -ENOENT)
  435. break; /* fewer numbers than pools */
  436. if (rv)
  437. goto out_free; /* syntax error */
  438. rv = -EINVAL;
  439. if (nthreads[i] < 0)
  440. goto out_free;
  441. }
  442. rv = nfsd_set_nrthreads(i, nthreads, net);
  443. if (rv)
  444. goto out_free;
  445. }
  446. rv = nfsd_get_nrthreads(npools, nthreads, net);
  447. if (rv)
  448. goto out_free;
  449. mesg = buf;
  450. size = SIMPLE_TRANSACTION_LIMIT;
  451. for (i = 0; i < npools && size > 0; i++) {
  452. snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
  453. len = strlen(mesg);
  454. size -= len;
  455. mesg += len;
  456. }
  457. rv = mesg - buf;
  458. out_free:
  459. kfree(nthreads);
  460. mutex_unlock(&nfsd_mutex);
  461. return rv;
  462. }
  463. static ssize_t __write_versions(struct file *file, char *buf, size_t size)
  464. {
  465. char *mesg = buf;
  466. char *vers, *minorp, sign;
  467. int len, num, remaining;
  468. unsigned minor;
  469. ssize_t tlen = 0;
  470. char *sep;
  471. struct net *net = file->f_dentry->d_sb->s_fs_info;
  472. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  473. if (size>0) {
  474. if (nn->nfsd_serv)
  475. /* Cannot change versions without updating
  476. * nn->nfsd_serv->sv_xdrsize, and reallocing
  477. * rq_argp and rq_resp
  478. */
  479. return -EBUSY;
  480. if (buf[size-1] != '\n')
  481. return -EINVAL;
  482. buf[size-1] = 0;
  483. vers = mesg;
  484. len = qword_get(&mesg, vers, size);
  485. if (len <= 0) return -EINVAL;
  486. do {
  487. sign = *vers;
  488. if (sign == '+' || sign == '-')
  489. num = simple_strtol((vers+1), &minorp, 0);
  490. else
  491. num = simple_strtol(vers, &minorp, 0);
  492. if (*minorp == '.') {
  493. if (num != 4)
  494. return -EINVAL;
  495. minor = simple_strtoul(minorp+1, NULL, 0);
  496. if (minor == 0)
  497. return -EINVAL;
  498. if (nfsd_minorversion(minor, sign == '-' ?
  499. NFSD_CLEAR : NFSD_SET) < 0)
  500. return -EINVAL;
  501. goto next;
  502. }
  503. switch(num) {
  504. case 2:
  505. case 3:
  506. case 4:
  507. nfsd_vers(num, sign == '-' ? NFSD_CLEAR : NFSD_SET);
  508. break;
  509. default:
  510. return -EINVAL;
  511. }
  512. next:
  513. vers += len + 1;
  514. } while ((len = qword_get(&mesg, vers, size)) > 0);
  515. /* If all get turned off, turn them back on, as
  516. * having no versions is BAD
  517. */
  518. nfsd_reset_versions();
  519. }
  520. /* Now write current state into reply buffer */
  521. len = 0;
  522. sep = "";
  523. remaining = SIMPLE_TRANSACTION_LIMIT;
  524. for (num=2 ; num <= 4 ; num++)
  525. if (nfsd_vers(num, NFSD_AVAIL)) {
  526. len = snprintf(buf, remaining, "%s%c%d", sep,
  527. nfsd_vers(num, NFSD_TEST)?'+':'-',
  528. num);
  529. sep = " ";
  530. if (len > remaining)
  531. break;
  532. remaining -= len;
  533. buf += len;
  534. tlen += len;
  535. }
  536. if (nfsd_vers(4, NFSD_AVAIL))
  537. for (minor = 1; minor <= NFSD_SUPPORTED_MINOR_VERSION;
  538. minor++) {
  539. len = snprintf(buf, remaining, " %c4.%u",
  540. (nfsd_vers(4, NFSD_TEST) &&
  541. nfsd_minorversion(minor, NFSD_TEST)) ?
  542. '+' : '-',
  543. minor);
  544. if (len > remaining)
  545. break;
  546. remaining -= len;
  547. buf += len;
  548. tlen += len;
  549. }
  550. len = snprintf(buf, remaining, "\n");
  551. if (len > remaining)
  552. return -EINVAL;
  553. return tlen + len;
  554. }
  555. /**
  556. * write_versions - Set or report the available NFS protocol versions
  557. *
  558. * Input:
  559. * buf: ignored
  560. * size: zero
  561. * Output:
  562. * On success: passed-in buffer filled with '\n'-terminated C
  563. * string containing positive or negative integer
  564. * values representing the current status of each
  565. * protocol version;
  566. * return code is the size in bytes of the string
  567. * On error: return code is zero or a negative errno value
  568. *
  569. * OR
  570. *
  571. * Input:
  572. * buf: C string containing whitespace-
  573. * separated positive or negative
  574. * integer values representing NFS
  575. * protocol versions to enable ("+n")
  576. * or disable ("-n")
  577. * size: non-zero length of C string in @buf
  578. * Output:
  579. * On success: status of zero or more protocol versions has
  580. * been updated; passed-in buffer filled with
  581. * '\n'-terminated C string containing positive
  582. * or negative integer values representing the
  583. * current status of each protocol version;
  584. * return code is the size in bytes of the string
  585. * On error: return code is zero or a negative errno value
  586. */
  587. static ssize_t write_versions(struct file *file, char *buf, size_t size)
  588. {
  589. ssize_t rv;
  590. mutex_lock(&nfsd_mutex);
  591. rv = __write_versions(file, buf, size);
  592. mutex_unlock(&nfsd_mutex);
  593. return rv;
  594. }
  595. /*
  596. * Zero-length write. Return a list of NFSD's current listener
  597. * transports.
  598. */
  599. static ssize_t __write_ports_names(char *buf, struct net *net)
  600. {
  601. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  602. if (nn->nfsd_serv == NULL)
  603. return 0;
  604. return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
  605. }
  606. /*
  607. * A single 'fd' number was written, in which case it must be for
  608. * a socket of a supported family/protocol, and we use it as an
  609. * nfsd listener.
  610. */
  611. static ssize_t __write_ports_addfd(char *buf, struct net *net)
  612. {
  613. char *mesg = buf;
  614. int fd, err;
  615. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  616. err = get_int(&mesg, &fd);
  617. if (err != 0 || fd < 0)
  618. return -EINVAL;
  619. err = nfsd_create_serv(net);
  620. if (err != 0)
  621. return err;
  622. err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
  623. if (err < 0) {
  624. nfsd_destroy(net);
  625. return err;
  626. }
  627. /* Decrease the count, but don't shut down the service */
  628. nn->nfsd_serv->sv_nrthreads--;
  629. return err;
  630. }
  631. /*
  632. * A transport listener is added by writing it's transport name and
  633. * a port number.
  634. */
  635. static ssize_t __write_ports_addxprt(char *buf, struct net *net)
  636. {
  637. char transport[16];
  638. struct svc_xprt *xprt;
  639. int port, err;
  640. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  641. if (sscanf(buf, "%15s %5u", transport, &port) != 2)
  642. return -EINVAL;
  643. if (port < 1 || port > USHRT_MAX)
  644. return -EINVAL;
  645. err = nfsd_create_serv(net);
  646. if (err != 0)
  647. return err;
  648. err = svc_create_xprt(nn->nfsd_serv, transport, net,
  649. PF_INET, port, SVC_SOCK_ANONYMOUS);
  650. if (err < 0)
  651. goto out_err;
  652. err = svc_create_xprt(nn->nfsd_serv, transport, net,
  653. PF_INET6, port, SVC_SOCK_ANONYMOUS);
  654. if (err < 0 && err != -EAFNOSUPPORT)
  655. goto out_close;
  656. /* Decrease the count, but don't shut down the service */
  657. nn->nfsd_serv->sv_nrthreads--;
  658. return 0;
  659. out_close:
  660. xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
  661. if (xprt != NULL) {
  662. svc_close_xprt(xprt);
  663. svc_xprt_put(xprt);
  664. }
  665. out_err:
  666. nfsd_destroy(net);
  667. return err;
  668. }
  669. static ssize_t __write_ports(struct file *file, char *buf, size_t size,
  670. struct net *net)
  671. {
  672. if (size == 0)
  673. return __write_ports_names(buf, net);
  674. if (isdigit(buf[0]))
  675. return __write_ports_addfd(buf, net);
  676. if (isalpha(buf[0]))
  677. return __write_ports_addxprt(buf, net);
  678. return -EINVAL;
  679. }
  680. /**
  681. * write_ports - Pass a socket file descriptor or transport name to listen on
  682. *
  683. * Input:
  684. * buf: ignored
  685. * size: zero
  686. * Output:
  687. * On success: passed-in buffer filled with a '\n'-terminated C
  688. * string containing a whitespace-separated list of
  689. * named NFSD listeners;
  690. * return code is the size in bytes of the string
  691. * On error: return code is zero or a negative errno value
  692. *
  693. * OR
  694. *
  695. * Input:
  696. * buf: C string containing an unsigned
  697. * integer value representing a bound
  698. * but unconnected socket that is to be
  699. * used as an NFSD listener; listen(3)
  700. * must be called for a SOCK_STREAM
  701. * socket, otherwise it is ignored
  702. * size: non-zero length of C string in @buf
  703. * Output:
  704. * On success: NFS service is started;
  705. * passed-in buffer filled with a '\n'-terminated C
  706. * string containing a unique alphanumeric name of
  707. * the listener;
  708. * return code is the size in bytes of the string
  709. * On error: return code is a negative errno value
  710. *
  711. * OR
  712. *
  713. * Input:
  714. * buf: C string containing a transport
  715. * name and an unsigned integer value
  716. * representing the port to listen on,
  717. * separated by whitespace
  718. * size: non-zero length of C string in @buf
  719. * Output:
  720. * On success: returns zero; NFS service is started
  721. * On error: return code is a negative errno value
  722. */
  723. static ssize_t write_ports(struct file *file, char *buf, size_t size)
  724. {
  725. ssize_t rv;
  726. struct net *net = file->f_dentry->d_sb->s_fs_info;
  727. mutex_lock(&nfsd_mutex);
  728. rv = __write_ports(file, buf, size, net);
  729. mutex_unlock(&nfsd_mutex);
  730. return rv;
  731. }
  732. int nfsd_max_blksize;
  733. /**
  734. * write_maxblksize - Set or report the current NFS blksize
  735. *
  736. * Input:
  737. * buf: ignored
  738. * size: zero
  739. *
  740. * OR
  741. *
  742. * Input:
  743. * buf: C string containing an unsigned
  744. * integer value representing the new
  745. * NFS blksize
  746. * size: non-zero length of C string in @buf
  747. * Output:
  748. * On success: passed-in buffer filled with '\n'-terminated C string
  749. * containing numeric value of the current NFS blksize
  750. * setting;
  751. * return code is the size in bytes of the string
  752. * On error: return code is zero or a negative errno value
  753. */
  754. static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
  755. {
  756. char *mesg = buf;
  757. struct net *net = file->f_dentry->d_sb->s_fs_info;
  758. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  759. if (size > 0) {
  760. int bsize;
  761. int rv = get_int(&mesg, &bsize);
  762. if (rv)
  763. return rv;
  764. /* force bsize into allowed range and
  765. * required alignment.
  766. */
  767. if (bsize < 1024)
  768. bsize = 1024;
  769. if (bsize > NFSSVC_MAXBLKSIZE)
  770. bsize = NFSSVC_MAXBLKSIZE;
  771. bsize &= ~(1024-1);
  772. mutex_lock(&nfsd_mutex);
  773. if (nn->nfsd_serv) {
  774. mutex_unlock(&nfsd_mutex);
  775. return -EBUSY;
  776. }
  777. nfsd_max_blksize = bsize;
  778. mutex_unlock(&nfsd_mutex);
  779. }
  780. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
  781. nfsd_max_blksize);
  782. }
  783. #ifdef CONFIG_NFSD_V4
  784. static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
  785. time_t *time, struct nfsd_net *nn)
  786. {
  787. char *mesg = buf;
  788. int rv, i;
  789. if (size > 0) {
  790. if (nn->nfsd_serv)
  791. return -EBUSY;
  792. rv = get_int(&mesg, &i);
  793. if (rv)
  794. return rv;
  795. /*
  796. * Some sanity checking. We don't have a reason for
  797. * these particular numbers, but problems with the
  798. * extremes are:
  799. * - Too short: the briefest network outage may
  800. * cause clients to lose all their locks. Also,
  801. * the frequent polling may be wasteful.
  802. * - Too long: do you really want reboot recovery
  803. * to take more than an hour? Or to make other
  804. * clients wait an hour before being able to
  805. * revoke a dead client's locks?
  806. */
  807. if (i < 10 || i > 3600)
  808. return -EINVAL;
  809. *time = i;
  810. }
  811. return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%ld\n", *time);
  812. }
  813. static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
  814. time_t *time, struct nfsd_net *nn)
  815. {
  816. ssize_t rv;
  817. mutex_lock(&nfsd_mutex);
  818. rv = __nfsd4_write_time(file, buf, size, time, nn);
  819. mutex_unlock(&nfsd_mutex);
  820. return rv;
  821. }
  822. /**
  823. * write_leasetime - Set or report the current NFSv4 lease time
  824. *
  825. * Input:
  826. * buf: ignored
  827. * size: zero
  828. *
  829. * OR
  830. *
  831. * Input:
  832. * buf: C string containing an unsigned
  833. * integer value representing the new
  834. * NFSv4 lease expiry time
  835. * size: non-zero length of C string in @buf
  836. * Output:
  837. * On success: passed-in buffer filled with '\n'-terminated C
  838. * string containing unsigned integer value of the
  839. * current lease expiry time;
  840. * return code is the size in bytes of the string
  841. * On error: return code is zero or a negative errno value
  842. */
  843. static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
  844. {
  845. struct net *net = file->f_dentry->d_sb->s_fs_info;
  846. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  847. return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
  848. }
  849. /**
  850. * write_gracetime - Set or report current NFSv4 grace period time
  851. *
  852. * As above, but sets the time of the NFSv4 grace period.
  853. *
  854. * Note this should never be set to less than the *previous*
  855. * lease-period time, but we don't try to enforce this. (In the common
  856. * case (a new boot), we don't know what the previous lease time was
  857. * anyway.)
  858. */
  859. static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
  860. {
  861. struct net *net = file->f_dentry->d_sb->s_fs_info;
  862. struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  863. return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
  864. }
  865. static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
  866. struct nfsd_net *nn)
  867. {