nfsctl.c (4ccdaba5ab560862f89d1d971fbcc2ef424e1867) nfsctl.c (499aa1ca4eb6602df38afaecb88fc14edf50cdbb)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Syscall interface to knfsd.
4 *
5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
6 */
7
8#include <linux/slab.h>

--- 62 unchanged lines hidden (view full) ---

71static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
72static ssize_t write_versions(struct file *file, char *buf, size_t size);
73static ssize_t write_ports(struct file *file, char *buf, size_t size);
74static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
75static ssize_t write_maxconn(struct file *file, char *buf, size_t size);
76#ifdef CONFIG_NFSD_V4
77static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
78static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Syscall interface to knfsd.
4 *
5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
6 */
7
8#include <linux/slab.h>

--- 62 unchanged lines hidden (view full) ---

71static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
72static ssize_t write_versions(struct file *file, char *buf, size_t size);
73static ssize_t write_ports(struct file *file, char *buf, size_t size);
74static ssize_t write_maxblksize(struct file *file, char *buf, size_t size);
75static ssize_t write_maxconn(struct file *file, char *buf, size_t size);
76#ifdef CONFIG_NFSD_V4
77static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
78static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
79#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
79static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
80static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
81#endif
80static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
81#endif
82
83static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
84 [NFSD_Fh] = write_filehandle,
85 [NFSD_FO_UnlockIP] = write_unlock_ip,
86 [NFSD_FO_UnlockFS] = write_unlock_fs,
87 [NFSD_Threads] = write_threads,
88 [NFSD_Pool_Threads] = write_pool_threads,
89 [NFSD_Versions] = write_versions,
90 [NFSD_Ports] = write_ports,
91 [NFSD_MaxBlkSize] = write_maxblksize,
92 [NFSD_MaxConnections] = write_maxconn,
93#ifdef CONFIG_NFSD_V4
94 [NFSD_Leasetime] = write_leasetime,
95 [NFSD_Gracetime] = write_gracetime,
82static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
83#endif
84
85static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
86 [NFSD_Fh] = write_filehandle,
87 [NFSD_FO_UnlockIP] = write_unlock_ip,
88 [NFSD_FO_UnlockFS] = write_unlock_fs,
89 [NFSD_Threads] = write_threads,
90 [NFSD_Pool_Threads] = write_pool_threads,
91 [NFSD_Versions] = write_versions,
92 [NFSD_Ports] = write_ports,
93 [NFSD_MaxBlkSize] = write_maxblksize,
94 [NFSD_MaxConnections] = write_maxconn,
95#ifdef CONFIG_NFSD_V4
96 [NFSD_Leasetime] = write_leasetime,
97 [NFSD_Gracetime] = write_gracetime,
98#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
96 [NFSD_RecoveryDir] = write_recoverydir,
99 [NFSD_RecoveryDir] = write_recoverydir,
100#endif
97 [NFSD_V4EndGrace] = write_v4_end_grace,
98#endif
99};
100
101static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
102{
103 ino_t ino = file_inode(file)->i_ino;
104 char *data;

--- 69 unchanged lines hidden (view full) ---

174}
175
176DEFINE_SHOW_ATTRIBUTE(export_features);
177
178static const struct file_operations pool_stats_operations = {
179 .open = nfsd_pool_stats_open,
180 .read = seq_read,
181 .llseek = seq_lseek,
101 [NFSD_V4EndGrace] = write_v4_end_grace,
102#endif
103};
104
105static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
106{
107 ino_t ino = file_inode(file)->i_ino;
108 char *data;

--- 69 unchanged lines hidden (view full) ---

178}
179
180DEFINE_SHOW_ATTRIBUTE(export_features);
181
182static const struct file_operations pool_stats_operations = {
183 .open = nfsd_pool_stats_open,
184 .read = seq_read,
185 .llseek = seq_lseek,
182 .release = nfsd_pool_stats_release,
186 .release = seq_release,
183};
184
185DEFINE_SHOW_ATTRIBUTE(nfsd_reply_cache_stats);
186
187DEFINE_SHOW_ATTRIBUTE(nfsd_file_cache_stats);
188
189/*----------------------------------------------------------------------------*/
190/*

--- 497 unchanged lines hidden (view full) ---

688 * a socket of a supported family/protocol, and we use it as an
689 * nfsd listener.
690 */
691static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred)
692{
693 char *mesg = buf;
694 int fd, err;
695 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
187};
188
189DEFINE_SHOW_ATTRIBUTE(nfsd_reply_cache_stats);
190
191DEFINE_SHOW_ATTRIBUTE(nfsd_file_cache_stats);
192
193/*----------------------------------------------------------------------------*/
194/*

--- 497 unchanged lines hidden (view full) ---

692 * a socket of a supported family/protocol, and we use it as an
693 * nfsd listener.
694 */
695static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred)
696{
697 char *mesg = buf;
698 int fd, err;
699 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
700 struct svc_serv *serv;
696
697 err = get_int(&mesg, &fd);
698 if (err != 0 || fd < 0)
699 return -EINVAL;
700 trace_nfsd_ctl_ports_addfd(net, fd);
701
702 err = nfsd_create_serv(net);
703 if (err != 0)
704 return err;
705
701
702 err = get_int(&mesg, &fd);
703 if (err != 0 || fd < 0)
704 return -EINVAL;
705 trace_nfsd_ctl_ports_addfd(net, fd);
706
707 err = nfsd_create_serv(net);
708 if (err != 0)
709 return err;
710
706 err = svc_addsock(nn->nfsd_serv, net, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
711 serv = nn->nfsd_serv;
712 err = svc_addsock(serv, net, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred);
707
713
708 if (err < 0 && !nn->nfsd_serv->sv_nrthreads && !nn->keep_active)
709 nfsd_last_thread(net);
710 else if (err >= 0 &&
711 !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
712 svc_get(nn->nfsd_serv);
714 if (!serv->sv_nrthreads && list_empty(&nn->nfsd_serv->sv_permsocks))
715 nfsd_destroy_serv(net);
713
716
714 nfsd_put(net);
715 return err;
716}
717
718/*
719 * A transport listener is added by writing its transport name and
720 * a port number.
721 */
722static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred)
723{
724 char transport[16];
725 struct svc_xprt *xprt;
726 int port, err;
727 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
717 return err;
718}
719
720/*
721 * A transport listener is added by writing its transport name and
722 * a port number.
723 */
724static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct cred *cred)
725{
726 char transport[16];
727 struct svc_xprt *xprt;
728 int port, err;
729 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
730 struct svc_serv *serv;
728
729 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
730 return -EINVAL;
731
732 if (port < 1 || port > USHRT_MAX)
733 return -EINVAL;
734 trace_nfsd_ctl_ports_addxprt(net, transport, port);
735
736 err = nfsd_create_serv(net);
737 if (err != 0)
738 return err;
739
731
732 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
733 return -EINVAL;
734
735 if (port < 1 || port > USHRT_MAX)
736 return -EINVAL;
737 trace_nfsd_ctl_ports_addxprt(net, transport, port);
738
739 err = nfsd_create_serv(net);
740 if (err != 0)
741 return err;
742
740 err = svc_xprt_create(nn->nfsd_serv, transport, net,
743 serv = nn->nfsd_serv;
744 err = svc_xprt_create(serv, transport, net,
741 PF_INET, port, SVC_SOCK_ANONYMOUS, cred);
742 if (err < 0)
743 goto out_err;
744
745 PF_INET, port, SVC_SOCK_ANONYMOUS, cred);
746 if (err < 0)
747 goto out_err;
748
745 err = svc_xprt_create(nn->nfsd_serv, transport, net,
749 err = svc_xprt_create(serv, transport, net,
746 PF_INET6, port, SVC_SOCK_ANONYMOUS, cred);
747 if (err < 0 && err != -EAFNOSUPPORT)
748 goto out_close;
749
750 PF_INET6, port, SVC_SOCK_ANONYMOUS, cred);
751 if (err < 0 && err != -EAFNOSUPPORT)
752 goto out_close;
753
750 if (!nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1))
751 svc_get(nn->nfsd_serv);
752
753 nfsd_put(net);
754 return 0;
755out_close:
754 return 0;
755out_close:
756 xprt = svc_find_xprt(nn->nfsd_serv, transport, net, PF_INET, port);
756 xprt = svc_find_xprt(serv, transport, net, PF_INET, port);
757 if (xprt != NULL) {
758 svc_xprt_close(xprt);
759 svc_xprt_put(xprt);
760 }
761out_err:
757 if (xprt != NULL) {
758 svc_xprt_close(xprt);
759 svc_xprt_put(xprt);
760 }
761out_err:
762 if (!nn->nfsd_serv->sv_nrthreads && !nn->keep_active)
763 nfsd_last_thread(net);
762 if (!serv->sv_nrthreads && list_empty(&nn->nfsd_serv->sv_permsocks))
763 nfsd_destroy_serv(net);
764
764
765 nfsd_put(net);
766 return err;
767}
768
769static ssize_t __write_ports(struct file *file, char *buf, size_t size,
770 struct net *net)
771{
772 if (size == 0)
773 return __write_ports_names(buf, net);

--- 239 unchanged lines hidden (view full) ---

1013 * anyway.)
1014 */
1015static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
1016{
1017 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1018 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
1019}
1020
765 return err;
766}
767
768static ssize_t __write_ports(struct file *file, char *buf, size_t size,
769 struct net *net)
770{
771 if (size == 0)
772 return __write_ports_names(buf, net);

--- 239 unchanged lines hidden (view full) ---

1012 * anyway.)
1013 */
1014static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
1015{
1016 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1017 return nfsd4_write_time(file, buf, size, &nn->nfsd4_grace, nn);
1018}
1019
1020#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
1021static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
1022 struct nfsd_net *nn)
1023{
1024 char *mesg = buf;
1025 char *recdir;
1026 int len, status;
1027
1028 if (size > 0) {

--- 44 unchanged lines hidden (view full) ---

1073 ssize_t rv;
1074 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1075
1076 mutex_lock(&nfsd_mutex);
1077 rv = __write_recoverydir(file, buf, size, nn);
1078 mutex_unlock(&nfsd_mutex);
1079 return rv;
1080}
1021static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size,
1022 struct nfsd_net *nn)
1023{
1024 char *mesg = buf;
1025 char *recdir;
1026 int len, status;
1027
1028 if (size > 0) {

--- 44 unchanged lines hidden (view full) ---

1073 ssize_t rv;
1074 struct nfsd_net *nn = net_generic(netns(file), nfsd_net_id);
1075
1076 mutex_lock(&nfsd_mutex);
1077 rv = __write_recoverydir(file, buf, size, nn);
1078 mutex_unlock(&nfsd_mutex);
1079 return rv;
1080}
1081#endif
1081
1082/*
1083 * write_v4_end_grace - release grace period for nfsd's v4.x lock manager
1084 *
1085 * Input:
1086 * buf: ignored
1087 * size: zero
1088 * OR

--- 147 unchanged lines hidden (view full) ---

1236#else
1237static inline void _nfsd_symlink(struct dentry *parent, const char *name,
1238 const char *content)
1239{
1240}
1241
1242#endif
1243
1082
1083/*
1084 * write_v4_end_grace - release grace period for nfsd's v4.x lock manager
1085 *
1086 * Input:
1087 * buf: ignored
1088 * size: zero
1089 * OR

--- 147 unchanged lines hidden (view full) ---

1237#else
1238static inline void _nfsd_symlink(struct dentry *parent, const char *name,
1239 const char *content)
1240{
1241}
1242
1243#endif
1244
1244static void clear_ncl(struct inode *inode)
1245static void clear_ncl(struct dentry *dentry)
1245{
1246{
1247 struct inode *inode = d_inode(dentry);
1246 struct nfsdfs_client *ncl = inode->i_private;
1247
1248 struct nfsdfs_client *ncl = inode->i_private;
1249
1250 spin_lock(&inode->i_lock);
1248 inode->i_private = NULL;
1251 inode->i_private = NULL;
1252 spin_unlock(&inode->i_lock);
1249 kref_put(&ncl->cl_ref, ncl->cl_release);
1250}
1251
1253 kref_put(&ncl->cl_ref, ncl->cl_release);
1254}
1255
1252static struct nfsdfs_client *__get_nfsdfs_client(struct inode *inode)
1256struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
1253{
1257{
1254 struct nfsdfs_client *nc = inode->i_private;
1258 struct nfsdfs_client *nc;
1255
1259
1260 spin_lock(&inode->i_lock);
1261 nc = inode->i_private;
1256 if (nc)
1257 kref_get(&nc->cl_ref);
1262 if (nc)
1263 kref_get(&nc->cl_ref);
1264 spin_unlock(&inode->i_lock);
1258 return nc;
1259}
1260
1265 return nc;
1266}
1267
1261struct nfsdfs_client *get_nfsdfs_client(struct inode *inode)
1262{
1263 struct nfsdfs_client *nc;
1264
1265 inode_lock_shared(inode);
1266 nc = __get_nfsdfs_client(inode);
1267 inode_unlock_shared(inode);
1268 return nc;
1269}
1270/* from __rpc_unlink */
1271static void nfsdfs_remove_file(struct inode *dir, struct dentry *dentry)
1272{
1273 int ret;
1274
1275 clear_ncl(d_inode(dentry));
1276 dget(dentry);
1277 ret = simple_unlink(dir, dentry);
1278 d_drop(dentry);
1279 fsnotify_unlink(dir, dentry);
1280 dput(dentry);
1281 WARN_ON_ONCE(ret);
1282}
1283
1284static void nfsdfs_remove_files(struct dentry *root)
1285{
1286 struct dentry *dentry, *tmp;
1287
1288 list_for_each_entry_safe(dentry, tmp, &root->d_subdirs, d_child) {
1289 if (!simple_positive(dentry)) {
1290 WARN_ON_ONCE(1); /* I think this can't happen? */
1291 continue;
1292 }
1293 nfsdfs_remove_file(d_inode(root), dentry);
1294 }
1295}
1296
1297/* XXX: cut'n'paste from simple_fill_super; figure out if we could share
1298 * code instead. */
1299static int nfsdfs_create_files(struct dentry *root,
1300 const struct tree_descr *files,
1268/* XXX: cut'n'paste from simple_fill_super; figure out if we could share
1269 * code instead. */
1270static int nfsdfs_create_files(struct dentry *root,
1271 const struct tree_descr *files,
1272 struct nfsdfs_client *ncl,
1301 struct dentry **fdentries)
1302{
1303 struct inode *dir = d_inode(root);
1304 struct inode *inode;
1305 struct dentry *dentry;
1306 int i;
1307
1308 inode_lock(dir);
1309 for (i = 0; files->name && files->name[0]; i++, files++) {
1310 dentry = d_alloc_name(root, files->name);
1311 if (!dentry)
1312 goto out;
1313 inode = nfsd_get_inode(d_inode(root)->i_sb,
1314 S_IFREG | files->mode);
1315 if (!inode) {
1316 dput(dentry);
1317 goto out;
1318 }
1273 struct dentry **fdentries)
1274{
1275 struct inode *dir = d_inode(root);
1276 struct inode *inode;
1277 struct dentry *dentry;
1278 int i;
1279
1280 inode_lock(dir);
1281 for (i = 0; files->name && files->name[0]; i++, files++) {
1282 dentry = d_alloc_name(root, files->name);
1283 if (!dentry)
1284 goto out;
1285 inode = nfsd_get_inode(d_inode(root)->i_sb,
1286 S_IFREG | files->mode);
1287 if (!inode) {
1288 dput(dentry);
1289 goto out;
1290 }
1291 kref_get(&ncl->cl_ref);
1319 inode->i_fop = files->ops;
1292 inode->i_fop = files->ops;
1320 inode->i_private = __get_nfsdfs_client(dir);
1293 inode->i_private = ncl;
1321 d_add(dentry, inode);
1322 fsnotify_create(dir, dentry);
1323 if (fdentries)
1324 fdentries[i] = dentry;
1325 }
1326 inode_unlock(dir);
1327 return 0;
1328out:
1294 d_add(dentry, inode);
1295 fsnotify_create(dir, dentry);
1296 if (fdentries)
1297 fdentries[i] = dentry;
1298 }
1299 inode_unlock(dir);
1300 return 0;
1301out:
1329 nfsdfs_remove_files(root);
1330 inode_unlock(dir);
1331 return -ENOMEM;
1332}
1333
1334/* on success, returns positive number unique to that client. */
1335struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
1336 struct nfsdfs_client *ncl, u32 id,
1337 const struct tree_descr *files,
1338 struct dentry **fdentries)
1339{
1340 struct dentry *dentry;
1341 char name[11];
1342 int ret;
1343
1344 sprintf(name, "%u", id);
1345
1346 dentry = nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
1347 if (IS_ERR(dentry)) /* XXX: tossing errors? */
1348 return NULL;
1302 inode_unlock(dir);
1303 return -ENOMEM;
1304}
1305
1306/* on success, returns positive number unique to that client. */
1307struct dentry *nfsd_client_mkdir(struct nfsd_net *nn,
1308 struct nfsdfs_client *ncl, u32 id,
1309 const struct tree_descr *files,
1310 struct dentry **fdentries)
1311{
1312 struct dentry *dentry;
1313 char name[11];
1314 int ret;
1315
1316 sprintf(name, "%u", id);
1317
1318 dentry = nfsd_mkdir(nn->nfsd_client_dir, ncl, name);
1319 if (IS_ERR(dentry)) /* XXX: tossing errors? */
1320 return NULL;
1349 ret = nfsdfs_create_files(dentry, files, fdentries);
1321 ret = nfsdfs_create_files(dentry, files, ncl, fdentries);
1350 if (ret) {
1351 nfsd_client_rmdir(dentry);
1352 return NULL;
1353 }
1354 return dentry;
1355}
1356
1357/* Taken from __rpc_rmdir: */
1358void nfsd_client_rmdir(struct dentry *dentry)
1359{
1322 if (ret) {
1323 nfsd_client_rmdir(dentry);
1324 return NULL;
1325 }
1326 return dentry;
1327}
1328
1329/* Taken from __rpc_rmdir: */
1330void nfsd_client_rmdir(struct dentry *dentry)
1331{
1360 struct inode *dir = d_inode(dentry->d_parent);
1361 struct inode *inode = d_inode(dentry);
1362 int ret;
1363
1364 inode_lock(dir);
1365 nfsdfs_remove_files(dentry);
1366 clear_ncl(inode);
1367 dget(dentry);
1368 ret = simple_rmdir(dir, dentry);
1369 WARN_ON_ONCE(ret);
1370 d_drop(dentry);
1371 fsnotify_rmdir(dir, dentry);
1372 dput(dentry);
1373 inode_unlock(dir);
1332 simple_recursive_removal(dentry, clear_ncl);
1374}
1375
1376static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)
1377{
1378 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
1379 nfsd_net_id);
1380 struct dentry *dentry;
1381 int ret;

--- 457 unchanged lines hidden ---
1333}
1334
1335static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)
1336{
1337 struct nfsd_net *nn = net_generic(current->nsproxy->net_ns,
1338 nfsd_net_id);
1339 struct dentry *dentry;
1340 int ret;

--- 457 unchanged lines hidden ---