aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-06-10 15:38:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:09 -0400
commit48b605f83c920d8daa50e43fc2c7f718e04c7bfa (patch)
tree745de009daf7e4efe7105d2501276c83de31466d /fs/nfs
parentc2d946e55e1be20a7443918e3b7497b905e6b3f7 (diff)
NFS: implement option checking when remounting NFS filesystems (resend)
When remounting an NFS or NFS4 filesystem, the new NFS options are not respected, yet the remount will still return success. This patch adds a remount_fs sb op for NFS that checks any new nfs mount options against the existing ones and fails the mount if any have changed. This is only implemented for string-based mount options since doing this with binary options isn't really feasible. This is essentially the same as the original patch I sent out, but adds a check to see if the addr= option has changed. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/super.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 614efeed5437..b550e921f661 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -207,6 +207,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type,
207 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); 207 int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
208static void nfs_kill_super(struct super_block *); 208static void nfs_kill_super(struct super_block *);
209static void nfs_put_super(struct super_block *); 209static void nfs_put_super(struct super_block *);
210static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
210 211
211static struct file_system_type nfs_fs_type = { 212static struct file_system_type nfs_fs_type = {
212 .owner = THIS_MODULE, 213 .owner = THIS_MODULE,
@@ -234,6 +235,7 @@ static const struct super_operations nfs_sops = {
234 .umount_begin = nfs_umount_begin, 235 .umount_begin = nfs_umount_begin,
235 .show_options = nfs_show_options, 236 .show_options = nfs_show_options,
236 .show_stats = nfs_show_stats, 237 .show_stats = nfs_show_stats,
238 .remount_fs = nfs_remount,
237}; 239};
238 240
239#ifdef CONFIG_NFS_V4 241#ifdef CONFIG_NFS_V4
@@ -278,6 +280,7 @@ static const struct super_operations nfs4_sops = {
278 .umount_begin = nfs_umount_begin, 280 .umount_begin = nfs_umount_begin,
279 .show_options = nfs_show_options, 281 .show_options = nfs_show_options,
280 .show_stats = nfs_show_stats, 282 .show_stats = nfs_show_stats,
283 .remount_fs = nfs_remount,
281}; 284};
282#endif 285#endif
283 286
@@ -1396,6 +1399,79 @@ out_invalid_fh:
1396 return -EINVAL; 1399 return -EINVAL;
1397} 1400}
1398 1401
1402static int
1403nfs_compare_remount_data(struct nfs_server *nfss,
1404 struct nfs_parsed_mount_data *data)
1405{
1406 if (data->flags != nfss->flags ||
1407 data->rsize != nfss->rsize ||
1408 data->wsize != nfss->wsize ||
1409 data->retrans != nfss->client->cl_timeout->to_retries ||
1410 data->auth_flavors[0] != nfss->client->cl_auth->au_flavor ||
1411 data->acregmin != nfss->acregmin / HZ ||
1412 data->acregmax != nfss->acregmax / HZ ||
1413 data->acdirmin != nfss->acdirmin / HZ ||
1414 data->acdirmax != nfss->acdirmax / HZ ||
1415 data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
1416 data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
1417 memcmp(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
1418 data->nfs_server.addrlen) != 0)
1419 return -EINVAL;
1420
1421 return 0;
1422}
1423
1424static int
1425nfs_remount(struct super_block *sb, int *flags, char *raw_data)
1426{
1427 int error;
1428 struct nfs_server *nfss = sb->s_fs_info;
1429 struct nfs_parsed_mount_data *data;
1430 struct nfs_mount_data *options = (struct nfs_mount_data *)raw_data;
1431 struct nfs4_mount_data *options4 = (struct nfs4_mount_data *)raw_data;
1432
1433 /*
1434 * Userspace mount programs that send binary options generally send
1435 * them populated with default values. We have no way to know which
1436 * ones were explicitly specified. Fall back to legacy behavior and
1437 * just return success.
1438 */
1439 if ((sb->s_type == &nfs4_fs_type && options4->version == 1) ||
1440 (sb->s_type == &nfs_fs_type && options->version >= 1 &&
1441 options->version <= 6))
1442 return 0;
1443
1444 data = kzalloc(sizeof(*data), GFP_KERNEL);
1445 if (data == NULL)
1446 return -ENOMEM;
1447
1448 /* fill out struct with values from existing mount */
1449 data->flags = nfss->flags;
1450 data->rsize = nfss->rsize;
1451 data->wsize = nfss->wsize;
1452 data->retrans = nfss->client->cl_timeout->to_retries;
1453 data->auth_flavors[0] = nfss->client->cl_auth->au_flavor;
1454 data->acregmin = nfss->acregmin / HZ;
1455 data->acregmax = nfss->acregmax / HZ;
1456 data->acdirmin = nfss->acdirmin / HZ;
1457 data->acdirmax = nfss->acdirmax / HZ;
1458 data->timeo = 10U * nfss->client->cl_timeout->to_initval / HZ;
1459 data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen;
1460 memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
1461 data->nfs_server.addrlen);
1462
1463 /* overwrite those values with any that were specified */
1464 error = nfs_parse_mount_options((char *)options, data);
1465 if (error < 0)
1466 goto out;
1467
1468 /* compare new mount options with old ones */
1469 error = nfs_compare_remount_data(nfss, data);
1470out:
1471 kfree(data);
1472 return error;
1473}
1474
1399/* 1475/*
1400 * Initialise the common bits of the superblock 1476 * Initialise the common bits of the superblock
1401 */ 1477 */