diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/super.c | 76 |
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); |
208 | static void nfs_kill_super(struct super_block *); | 208 | static void nfs_kill_super(struct super_block *); |
209 | static void nfs_put_super(struct super_block *); | 209 | static void nfs_put_super(struct super_block *); |
210 | static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | ||
210 | 211 | ||
211 | static struct file_system_type nfs_fs_type = { | 212 | static 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 | ||
1402 | static int | ||
1403 | nfs_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 | |||
1424 | static int | ||
1425 | nfs_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); | ||
1470 | out: | ||
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 | */ |