^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Syscall interface to knfsd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/fs_context.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sunrpc/svcsock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/lockd/lockd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/sunrpc/addr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sunrpc/gss_api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sunrpc/gss_krb5_enctypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sunrpc/rpc_pipe_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/fsnotify.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "idmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "nfsd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "cache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "state.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "netns.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "pnfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * We have a single directory with several nodes in it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) NFSD_Root = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) NFSD_List,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) NFSD_Export_features,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) NFSD_Fh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) NFSD_FO_UnlockIP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) NFSD_FO_UnlockFS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) NFSD_Threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) NFSD_Pool_Threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) NFSD_Pool_Stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) NFSD_Reply_Cache_Stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) NFSD_Versions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) NFSD_Ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) NFSD_MaxBlkSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) NFSD_MaxConnections,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) NFSD_SupportedEnctypes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) NFSD_Leasetime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) NFSD_Gracetime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) NFSD_RecoveryDir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) NFSD_V4EndGrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) NFSD_MaxReserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * write() for these nodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static ssize_t write_threads(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static ssize_t write_versions(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static ssize_t write_ports(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static ssize_t write_maxconn(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) [NFSD_Fh] = write_filehandle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) [NFSD_FO_UnlockIP] = write_unlock_ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) [NFSD_FO_UnlockFS] = write_unlock_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) [NFSD_Threads] = write_threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) [NFSD_Pool_Threads] = write_pool_threads,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) [NFSD_Versions] = write_versions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) [NFSD_Ports] = write_ports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) [NFSD_MaxBlkSize] = write_maxblksize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) [NFSD_MaxConnections] = write_maxconn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) [NFSD_Leasetime] = write_leasetime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) [NFSD_Gracetime] = write_gracetime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) [NFSD_RecoveryDir] = write_recoverydir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) [NFSD_V4EndGrace] = write_v4_end_grace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ino_t ino = file_inode(file)->i_ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) data = simple_transaction_get(file, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (IS_ERR(data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return PTR_ERR(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rv = write_op[ino](file, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (rv >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) simple_transaction_set(file, rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) rv = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (! file->private_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* An attempt to read a transaction file without writing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * causes a 0-byte write so that the file can return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * state information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return simple_transaction_read(file, buf, size, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static const struct file_operations transaction_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .write = nfsctl_transaction_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .read = nfsctl_transaction_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .release = simple_transaction_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int exports_net_open(struct net *net, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct seq_file *seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) err = seq_open(file, &nfs_exports_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) seq = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) seq->private = nn->svc_export_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int exports_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return exports_net_open(current->nsproxy->net_ns, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const struct proc_ops exports_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .proc_open = exports_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .proc_read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .proc_release = seq_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int exports_nfsd_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return exports_net_open(inode->i_sb->s_fs_info, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static const struct file_operations exports_nfsd_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .open = exports_nfsd_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .release = seq_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int export_features_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int export_features_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return single_open(file, export_features_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static const struct file_operations export_features_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .open = export_features_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static int supported_enctypes_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int supported_enctypes_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return single_open(file, supported_enctypes_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static const struct file_operations supported_enctypes_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .open = supported_enctypes_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static const struct file_operations pool_stats_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .open = nfsd_pool_stats_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .release = nfsd_pool_stats_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static const struct file_operations reply_cache_stats_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .open = nfsd_reply_cache_stats_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*----------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * payload - write methods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static inline struct net *netns(struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return file_inode(file)->i_sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * write_unlock_ip - Release all locks used by a client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * Experimental.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * buf: '\n'-terminated C string containing a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * presentation format IP address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * size: length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * On success: returns zero if all specified locks were released;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * returns one if one or more locks were not released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * On error: return code is negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct sockaddr_storage address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct sockaddr *sap = (struct sockaddr *)&address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) size_t salen = sizeof(address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) char *fo_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct net *net = netns(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (buf[size-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) fo_path = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (qword_get(&buf, fo_path, size) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (rpc_pton(net, fo_path, size, sap, salen) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return nlmsvc_unlock_all_by_ip(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * write_unlock_fs - Release all locks on a local file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * Experimental.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * buf: '\n'-terminated C string containing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * absolute pathname of a local file system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * size: length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * On success: returns zero if all specified locks were released;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * returns one if one or more locks were not released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * On error: return code is negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) char *fo_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (buf[size-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) fo_path = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (qword_get(&buf, fo_path, size) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) error = kern_path(fo_path, 0, &path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * XXX: Needs better sanity checking. Otherwise we could end up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * releasing locks on the wrong file system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * For example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * 1. Does the path refer to a directory?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * 2. Is that directory a mount point, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * 3. Is that directory the root of an exported file system?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * write_filehandle - Get a variable-length NFS file handle by path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * On input, the buffer contains a '\n'-terminated C string comprised of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * three alphanumeric words separated by whitespace. The string may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * contain escape sequences.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * domain: client domain name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * path: export pathname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * maxsize: numeric maximum size of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * size: length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * On success: passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * string containing a ASCII hex text version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * of the NFS file handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * On error: return code is negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) char *dname, *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int maxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct auth_domain *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct knfsd_fh fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (buf[size-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) buf[size-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dname = mesg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) len = qword_get(&mesg, dname, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) path = dname+len+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) len = qword_get(&mesg, path, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) len = get_int(&mesg, &maxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (maxsize < NFS_FHSIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) maxsize = min(maxsize, NFS3_FHSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (qword_get(&mesg, mesg, size)>0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* we have all the words, they are in buf.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) dom = unix_domain_find(dname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) len = exp_rootfh(netns(file), dom, path, &fh, maxsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) auth_domain_put(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) len = SIMPLE_TRANSACTION_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mesg[-1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return mesg - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * write_threads - Start NFSD, or report the current number of running threads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * On success: passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * string numeric value representing the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * running NFSD threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * On error: return code is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * buf: C string containing an unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * integer value representing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * number of NFSD threads to start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * On success: NFS service is started;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * string numeric value representing the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * running NFSD threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static ssize_t write_threads(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct net *net = netns(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int newthreads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rv = get_int(&mesg, &newthreads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (newthreads < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) rv = nfsd_svc(newthreads, net, file->f_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) rv = nfsd_nrthreads(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * write_pool_threads - Set or report the current number of threads per pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * buf: C string containing whitespace-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * separated unsigned integer values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * representing the number of NFSD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * threads to start in each pool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * On success: passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * string containing integer values representing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * number of NFSD threads in each pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* if size > 0, look for an array of number of threads per node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * and apply them then write out number of threads per node as reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int npools;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int *nthreads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct net *net = netns(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) npools = nfsd_nrpools(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (npools == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * NFS is shut down. The admin can start it by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * writing to the threads file but NOT the pool_threads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * file, sorry. Report zero threads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) strcpy(buf, "0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) rv = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (nthreads == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) for (i = 0; i < npools; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) rv = get_int(&mesg, &nthreads[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (rv == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break; /* fewer numbers than pools */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) goto out_free; /* syntax error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) rv = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (nthreads[i] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) rv = nfsd_set_nrthreads(i, nthreads, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) rv = nfsd_get_nrthreads(npools, nthreads, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) size = SIMPLE_TRANSACTION_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) for (i = 0; i < npools && size > 0; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) snprintf(mesg, size, "%d%c", nthreads[i], (i == npools-1 ? '\n' : ' '));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) len = strlen(mesg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) mesg += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) rv = mesg - buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) kfree(nthreads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) nfsd_print_version_support(struct nfsd_net *nn, char *buf, int remaining,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) const char *sep, unsigned vers, int minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) bool supported = !!nfsd_vers(nn, vers, NFSD_TEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (vers == 4 && minor >= 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) !nfsd_minorversion(nn, minor, NFSD_TEST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) supported = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (minor == 0 && supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * special case for backward compatability.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * +4.0 is never reported, it is implied by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * +4, unless -4.0 is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return snprintf(buf, remaining, format, sep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) supported ? '+' : '-', vers, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static ssize_t __write_versions(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) char *vers, *minorp, sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int len, num, remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ssize_t tlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) char *sep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (size>0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (nn->nfsd_serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* Cannot change versions without updating
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * nn->nfsd_serv->sv_xdrsize, and reallocing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * rq_argp and rq_resp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (buf[size-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) buf[size-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) vers = mesg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) len = qword_get(&mesg, vers, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (len <= 0) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) enum vers_op cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) unsigned minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) sign = *vers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (sign == '+' || sign == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) num = simple_strtol((vers+1), &minorp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) num = simple_strtol(vers, &minorp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (*minorp == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (num != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (kstrtouint(minorp+1, 0, &minor) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) cmd = sign == '-' ? NFSD_CLEAR : NFSD_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) switch(num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) nfsd_vers(nn, num, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (*minorp == '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (nfsd_minorversion(nn, minor, cmd) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) } else if ((cmd == NFSD_SET) != nfsd_vers(nn, num, NFSD_TEST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * Either we have +4 and no minors are enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * or we have -4 and at least one minor is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * In either case, propagate 'cmd' to all minors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) minor = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) while (nfsd_minorversion(nn, minor, cmd) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) minor++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) vers += len + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) } while ((len = qword_get(&mesg, vers, size)) > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* If all get turned off, turn them back on, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * having no versions is BAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) nfsd_reset_versions(nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* Now write current state into reply buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) sep = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) remaining = SIMPLE_TRANSACTION_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) for (num=2 ; num <= 4 ; num++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (!nfsd_vers(nn, num, NFSD_AVAIL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) minor = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) len = nfsd_print_version_support(nn, buf, remaining,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) sep, num, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (len >= remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) remaining -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) buf += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) tlen += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) minor++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) sep = " ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) } while (num == 4 && minor <= NFSD_SUPPORTED_MINOR_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) len = snprintf(buf, remaining, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (len >= remaining)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return tlen + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * write_versions - Set or report the available NFS protocol versions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * On success: passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * string containing positive or negative integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * values representing the current status of each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * protocol version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * buf: C string containing whitespace-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * separated positive or negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * integer values representing NFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * protocol versions to enable ("+n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * or disable ("-n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * On success: status of zero or more protocol versions has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * been updated; passed-in buffer filled with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * '\n'-terminated C string containing positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * or negative integer values representing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * current status of each protocol version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static ssize_t write_versions(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) rv = __write_versions(file, buf, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * Zero-length write. Return a list of NFSD's current listener
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * transports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) static ssize_t __write_ports_names(char *buf, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (nn->nfsd_serv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return svc_xprt_names(nn->nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * A single 'fd' number was written, in which case it must be for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * a socket of a supported family/protocol, and we use it as an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * nfsd listener.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int fd, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) err = get_int(&mesg, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) if (err != 0 || fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (svc_alien_sock(net, fd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) err = nfsd_create_serv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) nfsd_destroy(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* Decrease the count, but don't shut down the service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) nn->nfsd_serv->sv_nrthreads--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * A transport listener is added by writing it's transport name and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * a port number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) char transport[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct svc_xprt *xprt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) int port, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (sscanf(buf, "%15s %5u", transport, &port) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (port < 1 || port > USHRT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) err = nfsd_create_serv(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) err = svc_create_xprt(nn->nfsd_serv, transport, net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) PF_INET, port, SVC_SOCK_ANONYMOUS, cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) err = svc_create_xprt(nn->nfsd_serv, transport, net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) PF_INET6, port, SVC_SOCK_ANONYMOUS, cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (err < 0 && err != -EAFNOSUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) /* Decrease the count, but don't shut down the service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) nn->nfsd_serv->sv_nrthreads--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (xprt != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) svc_close_xprt(xprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) svc_xprt_put(xprt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (!list_empty(&nn->nfsd_serv->sv_permsocks))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) nn->nfsd_serv->sv_nrthreads--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) nfsd_destroy(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static ssize_t __write_ports(struct file *file, char *buf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return __write_ports_names(buf, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (isdigit(buf[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return __write_ports_addfd(buf, net, file->f_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (isalpha(buf[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return __write_ports_addxprt(buf, net, file->f_cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * write_ports - Pass a socket file descriptor or transport name to listen on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * On success: passed-in buffer filled with a '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * string containing a whitespace-separated list of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * named NFSD listeners;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * buf: C string containing an unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * integer value representing a bound
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * but unconnected socket that is to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * used as an NFSD listener; listen(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * must be called for a SOCK_STREAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * socket, otherwise it is ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * On success: NFS service is started;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * passed-in buffer filled with a '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * string containing a unique alphanumeric name of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * the listener;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * On error: return code is a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * buf: C string containing a transport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * name and an unsigned integer value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * representing the port to listen on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * separated by whitespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * On success: returns zero; NFS service is started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * On error: return code is a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) static ssize_t write_ports(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) rv = __write_ports(file, buf, size, netns(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int nfsd_max_blksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * write_maxblksize - Set or report the current NFS blksize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * buf: C string containing an unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * integer value representing the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * NFS blksize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * On success: passed-in buffer filled with '\n'-terminated C string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * containing numeric value of the current NFS blksize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * setting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) int bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) int rv = get_int(&mesg, &bsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* force bsize into allowed range and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * required alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) bsize = max_t(int, bsize, 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) bsize = min_t(int, bsize, NFSSVC_MAXBLKSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) bsize &= ~(1024-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (nn->nfsd_serv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) nfsd_max_blksize = bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) nfsd_max_blksize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * write_maxconn - Set or report the current max number of connections
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * buf: C string containing an unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * integer value representing the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * number of max connections
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * On success: passed-in buffer filled with '\n'-terminated C string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * containing numeric value of max_connections setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * for this net namespace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static ssize_t write_maxconn(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) unsigned int maxconn = nn->max_connections;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int rv = get_uint(&mesg, &maxconn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) nn->max_connections = maxconn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%u\n", maxconn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static ssize_t __nfsd4_write_time(struct file *file, char *buf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) time64_t *time, struct nfsd_net *nn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int rv, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (nn->nfsd_serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) rv = get_int(&mesg, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * Some sanity checking. We don't have a reason for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * these particular numbers, but problems with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * extremes are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) * - Too short: the briefest network outage may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * cause clients to lose all their locks. Also,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * the frequent polling may be wasteful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * - Too long: do you really want reboot recovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * to take more than an hour? Or to make other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * clients wait an hour before being able to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * revoke a dead client's locks?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (i < 10 || i > 3600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) *time = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%lld\n", *time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static ssize_t nfsd4_write_time(struct file *file, char *buf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) time64_t *time, struct nfsd_net *nn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) rv = __nfsd4_write_time(file, buf, size, time, nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * write_leasetime - Set or report the current NFSv4 lease time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * buf: C string containing an unsigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * integer value representing the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * NFSv4 lease expiry time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * On success: passed-in buffer filled with '\n'-terminated C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) * string containing unsigned integer value of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * current lease expiry time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return nfsd4_write_time(file, buf, size, &nn->nfsd4_lease, nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * write_gracetime - Set or report current NFSv4 grace period time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * As above, but sets the time of the NFSv4 grace period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * Note this should never be set to less than the *previous*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * lease-period time, but we don't try to enforce this. (In the common
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) * case (a new boot), we don't know what the previous lease time was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * anyway.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct nfsd_net *nn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) char *mesg = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) char *recdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) int len, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (nn->nfsd_serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (size > PATH_MAX || buf[size-1] != '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) buf[size-1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) recdir = mesg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) len = qword_get(&mesg, recdir, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if (len <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) status = nfs4_reset_recoverydir(recdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) nfs4_recoverydir());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * write_recoverydir - Set or report the pathname of the recovery directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * buf: C string containing the pathname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * of the directory on a local file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) * system containing permanent NFSv4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * recovery data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * On success: passed-in buffer filled with '\n'-terminated C string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * containing the current recovery pathname setting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * return code is the size in bytes of the string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * On error: return code is zero or a negative errno value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ssize_t rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) mutex_lock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) rv = __write_recoverydir(file, buf, size, nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) mutex_unlock(&nfsd_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * write_v4_end_grace - release grace period for nfsd's v4.x lock manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * buf: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) * size: zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * buf: any value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * size: non-zero length of C string in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * passed-in buffer filled with "Y" or "N" with a newline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * and NULL-terminated C string. This indicates whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * the grace period has ended in the current net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * namespace. Return code is the size in bytes of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * string. Writing a string that starts with 'Y', 'y', or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * '1' to the file will end the grace period for nfsd's v4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * lock manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) switch(buf[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) case 'Y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) case 'y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (!nn->nfsd_serv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) nfsd4_end_grace(nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) nn->grace_ended ? 'Y' : 'N');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) /*----------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * populating the filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* Basically copying rpc_get_inode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct inode *inode = new_inode(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /* Following advice from simple_fill_super documentation: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) inode->i_ino = iunique(sb, NFSD_MaxReserved);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) inode->i_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) switch (mode & S_IFMT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) case S_IFDIR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) inode->i_fop = &simple_dir_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) inode->i_op = &simple_dir_inode_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) inc_nlink(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int __nfsd_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, struct nfsdfs_client *ncl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) inode = nfsd_get_inode(dir->i_sb, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (!inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (ncl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) inode->i_private = ncl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) kref_get(&ncl->cl_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) d_add(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) inc_nlink(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) fsnotify_mkdir(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *ncl, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct inode *dir = parent->d_inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) inode_lock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) dentry = d_alloc_name(parent, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (!dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret = __nfsd_mkdir(d_inode(parent), dentry, S_IFDIR | 0600, ncl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) inode_unlock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) dentry = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static void clear_ncl(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct nfsdfs_client *ncl = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) inode->i_private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) kref_put(&ncl->cl_ref, ncl->cl_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) struct nfsdfs_client *nc = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (nc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) kref_get(&nc->cl_ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) struct nfsdfs_client *nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) inode_lock_shared(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) nc = __get_nfsdfs_client(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) inode_unlock_shared(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return nc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* from __rpc_unlink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) clear_ncl(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ret = simple_unlink(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) fsnotify_unlink(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) WARN_ON_ONCE(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) static void nfsdfs_remove_files(struct dentry *root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) struct dentry *dentry, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) list_for_each_entry_safe(dentry, tmp, &root->d_subdirs, d_child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) if (!simple_positive(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) WARN_ON_ONCE(1); /* I think this can't happen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) nfsdfs_remove_file(d_inode(root), dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /* XXX: cut'n'paste from simple_fill_super; figure out if we could share
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * code instead. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) static int nfsdfs_create_files(struct dentry *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) const struct tree_descr *files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct inode *dir = d_inode(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) inode_lock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) for (i = 0; files->name && files->name[0]; i++, files++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (!files->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) dentry = d_alloc_name(root, files->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (!dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) inode = nfsd_get_inode(d_inode(root)->i_sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) S_IFREG | files->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (!inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) inode->i_fop = files->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) inode->i_private = __get_nfsdfs_client(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) d_add(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) fsnotify_create(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) inode_unlock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) nfsdfs_remove_files(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) inode_unlock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) /* on success, returns positive number unique to that client. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) struct nfsdfs_client *ncl, u32 id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) const struct tree_descr *files)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) char name[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) sprintf(name, "%u", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) dentry = nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (IS_ERR(dentry)) /* XXX: tossing errors? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) ret = nfsdfs_create_files(dentry, files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) nfsd_client_rmdir(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* Taken from __rpc_rmdir: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) void nfsd_client_rmdir(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct inode *dir = d_inode(dentry->d_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) inode_lock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) nfsdfs_remove_files(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) clear_ncl(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) dget(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) ret = simple_rmdir(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) WARN_ON_ONCE(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) d_drop(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) fsnotify_rmdir(dir, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) inode_unlock(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) static const struct tree_descr nfsd_files[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) [NFSD_Export_features] = {"export_features",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) &export_features_operations, S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) [NFSD_FO_UnlockIP] = {"unlock_ip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) [NFSD_FO_UnlockFS] = {"unlock_filesystem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) [NFSD_Pool_Stats] = {"pool_stats", &pool_stats_operations, S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) [NFSD_Reply_Cache_Stats] = {"reply_cache_stats", &reply_cache_stats_operations, S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) #ifdef CONFIG_NFSD_V4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /* last one */ {""}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) dentry = nfsd_mkdir(sb->s_root, NULL, "clients");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) nn->nfsd_client_dir = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) static int nfsd_fs_get_tree(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return get_tree_keyed(fc, nfsd_fill_super, get_net(fc->net_ns));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static void nfsd_fs_free_fc(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (fc->s_fs_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) put_net(fc->s_fs_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) static const struct fs_context_operations nfsd_fs_context_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) .free = nfsd_fs_free_fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) .get_tree = nfsd_fs_get_tree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) static int nfsd_init_fs_context(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) put_user_ns(fc->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) fc->user_ns = get_user_ns(fc->net_ns->user_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) fc->ops = &nfsd_fs_context_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static void nfsd_umount(struct super_block *sb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) struct net *net = sb->s_fs_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) kill_litter_super(sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) put_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static struct file_system_type nfsd_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) .name = "nfsd",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) .init_fs_context = nfsd_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) .kill_sb = nfsd_umount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) MODULE_ALIAS_FS("nfsd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) int get_nfsdfs(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) struct vfsmount *mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) mnt = vfs_kern_mount(&nfsd_fs_type, SB_KERNMOUNT, "nfsd", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (IS_ERR(mnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return PTR_ERR(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) nn->nfsd_mnt = mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) static int create_proc_exports_entry(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) struct proc_dir_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) entry = proc_mkdir("fs/nfs", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) entry = proc_create("exports", 0, entry, &exports_proc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) remove_proc_entry("fs/nfs", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) #else /* CONFIG_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) static int create_proc_exports_entry(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) unsigned int nfsd_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) static __net_init int nfsd_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) retval = nfsd_export_init(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) goto out_export_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) retval = nfsd_idmap_init(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) goto out_idmap_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) nn->nfsd_versions = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) nn->nfsd4_minorversions = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) retval = nfsd_reply_cache_init(nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) goto out_drc_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) nn->nfsd4_lease = 90; /* default lease time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) nn->nfsd4_grace = 90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) nn->somebody_reclaimed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) nn->track_reclaim_completes = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) nn->clverifier_counter = prandom_u32();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) nn->clientid_base = prandom_u32();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) nn->clientid_counter = nn->clientid_base + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) nn->s2s_cp_cl_id = nn->clientid_counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) atomic_set(&nn->ntf_refcnt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) init_waitqueue_head(&nn->ntf_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) seqlock_init(&nn->boot_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) out_drc_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) nfsd_idmap_shutdown(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) out_idmap_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) nfsd_export_shutdown(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) out_export_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) static __net_exit void nfsd_exit_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) struct nfsd_net *nn = net_generic(net, nfsd_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) nfsd_reply_cache_shutdown(nn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) nfsd_idmap_shutdown(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) nfsd_export_shutdown(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static struct pernet_operations nfsd_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) .init = nfsd_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) .exit = nfsd_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) .id = &nfsd_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) .size = sizeof(struct nfsd_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) static int __init init_nfsd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) retval = nfsd4_init_slabs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) retval = nfsd4_init_pnfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) goto out_free_slabs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) nfsd_stat_init(); /* Statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) retval = nfsd_drc_slab_create();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) goto out_free_stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) nfsd_lockd_init(); /* lockd->nfsd callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) retval = create_proc_exports_entry();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) goto out_free_lockd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) retval = register_filesystem(&nfsd_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) goto out_free_exports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) retval = register_pernet_subsys(&nfsd_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) goto out_free_filesystem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) retval = register_cld_notifier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) goto out_free_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) out_free_all:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) unregister_pernet_subsys(&nfsd_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) out_free_filesystem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) unregister_filesystem(&nfsd_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) out_free_exports:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) remove_proc_entry("fs/nfs/exports", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) remove_proc_entry("fs/nfs", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) out_free_lockd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) nfsd_lockd_shutdown();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) nfsd_drc_slab_free();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) out_free_stat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) nfsd_stat_shutdown();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) nfsd4_exit_pnfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) out_free_slabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) nfsd4_free_slabs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) static void __exit exit_nfsd(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) unregister_cld_notifier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) unregister_pernet_subsys(&nfsd_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) nfsd_drc_slab_free();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) remove_proc_entry("fs/nfs/exports", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) remove_proc_entry("fs/nfs", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) nfsd_stat_shutdown();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) nfsd_lockd_shutdown();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) nfsd4_free_slabs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) nfsd4_exit_pnfs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) unregister_filesystem(&nfsd_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) module_init(init_nfsd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) module_exit(exit_nfsd)