aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
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 */