diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 613 |
1 files changed, 168 insertions, 445 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 8b2a2977b720..d2c7f5db0847 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -64,11 +64,12 @@ | |||
64 | #include "internal.h" | 64 | #include "internal.h" |
65 | #include "fscache.h" | 65 | #include "fscache.h" |
66 | #include "pnfs.h" | 66 | #include "pnfs.h" |
67 | #include "nfs.h" | ||
67 | 68 | ||
68 | #define NFSDBG_FACILITY NFSDBG_VFS | 69 | #define NFSDBG_FACILITY NFSDBG_VFS |
69 | #define NFS_TEXT_DATA 1 | 70 | #define NFS_TEXT_DATA 1 |
70 | 71 | ||
71 | #ifdef CONFIG_NFS_V3 | 72 | #if IS_ENABLED(CONFIG_NFS_V3) |
72 | #define NFS_DEFAULT_VERSION 3 | 73 | #define NFS_DEFAULT_VERSION 3 |
73 | #else | 74 | #else |
74 | #define NFS_DEFAULT_VERSION 2 | 75 | #define NFS_DEFAULT_VERSION 2 |
@@ -278,37 +279,17 @@ static match_table_t nfs_vers_tokens = { | |||
278 | { Opt_vers_err, NULL } | 279 | { Opt_vers_err, NULL } |
279 | }; | 280 | }; |
280 | 281 | ||
281 | struct nfs_mount_info { | ||
282 | void (*fill_super)(struct super_block *, struct nfs_mount_info *); | ||
283 | int (*set_security)(struct super_block *, struct dentry *, struct nfs_mount_info *); | ||
284 | struct nfs_parsed_mount_data *parsed; | ||
285 | struct nfs_clone_mount *cloned; | ||
286 | struct nfs_fh *mntfh; | ||
287 | }; | ||
288 | |||
289 | static void nfs_umount_begin(struct super_block *); | ||
290 | static int nfs_statfs(struct dentry *, struct kstatfs *); | ||
291 | static int nfs_show_options(struct seq_file *, struct dentry *); | ||
292 | static int nfs_show_devname(struct seq_file *, struct dentry *); | ||
293 | static int nfs_show_path(struct seq_file *, struct dentry *); | ||
294 | static int nfs_show_stats(struct seq_file *, struct dentry *); | ||
295 | static struct dentry *nfs_fs_mount_common(struct file_system_type *, | ||
296 | struct nfs_server *, int, const char *, struct nfs_mount_info *); | ||
297 | static struct dentry *nfs_fs_mount(struct file_system_type *, | ||
298 | int, const char *, void *); | ||
299 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, | 282 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, |
300 | int flags, const char *dev_name, void *raw_data); | 283 | int flags, const char *dev_name, void *raw_data); |
301 | static void nfs_put_super(struct super_block *); | ||
302 | static void nfs_kill_super(struct super_block *); | ||
303 | static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | ||
304 | 284 | ||
305 | static struct file_system_type nfs_fs_type = { | 285 | struct file_system_type nfs_fs_type = { |
306 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
307 | .name = "nfs", | 287 | .name = "nfs", |
308 | .mount = nfs_fs_mount, | 288 | .mount = nfs_fs_mount, |
309 | .kill_sb = nfs_kill_super, | 289 | .kill_sb = nfs_kill_super, |
310 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 290 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
311 | }; | 291 | }; |
292 | EXPORT_SYMBOL_GPL(nfs_fs_type); | ||
312 | 293 | ||
313 | struct file_system_type nfs_xdev_fs_type = { | 294 | struct file_system_type nfs_xdev_fs_type = { |
314 | .owner = THIS_MODULE, | 295 | .owner = THIS_MODULE, |
@@ -318,7 +299,7 @@ struct file_system_type nfs_xdev_fs_type = { | |||
318 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 299 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
319 | }; | 300 | }; |
320 | 301 | ||
321 | static const struct super_operations nfs_sops = { | 302 | const struct super_operations nfs_sops = { |
322 | .alloc_inode = nfs_alloc_inode, | 303 | .alloc_inode = nfs_alloc_inode, |
323 | .destroy_inode = nfs_destroy_inode, | 304 | .destroy_inode = nfs_destroy_inode, |
324 | .write_inode = nfs_write_inode, | 305 | .write_inode = nfs_write_inode, |
@@ -332,77 +313,40 @@ static const struct super_operations nfs_sops = { | |||
332 | .show_stats = nfs_show_stats, | 313 | .show_stats = nfs_show_stats, |
333 | .remount_fs = nfs_remount, | 314 | .remount_fs = nfs_remount, |
334 | }; | 315 | }; |
316 | EXPORT_SYMBOL_GPL(nfs_sops); | ||
335 | 317 | ||
336 | #ifdef CONFIG_NFS_V4 | 318 | #if IS_ENABLED(CONFIG_NFS_V4) |
337 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); | 319 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); |
338 | static int nfs4_validate_mount_data(void *options, | 320 | static int nfs4_validate_mount_data(void *options, |
339 | struct nfs_parsed_mount_data *args, const char *dev_name); | 321 | struct nfs_parsed_mount_data *args, const char *dev_name); |
340 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, | ||
341 | struct nfs_mount_info *mount_info); | ||
342 | static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type, | ||
343 | int flags, const char *dev_name, void *raw_data); | ||
344 | static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type, | ||
345 | int flags, const char *dev_name, void *raw_data); | ||
346 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, | ||
347 | int flags, const char *dev_name, void *raw_data); | ||
348 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | ||
349 | int flags, const char *dev_name, void *raw_data); | ||
350 | static void nfs4_kill_super(struct super_block *sb); | ||
351 | |||
352 | static struct file_system_type nfs4_fs_type = { | ||
353 | .owner = THIS_MODULE, | ||
354 | .name = "nfs4", | ||
355 | .mount = nfs_fs_mount, | ||
356 | .kill_sb = nfs4_kill_super, | ||
357 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
358 | }; | ||
359 | 322 | ||
360 | static struct file_system_type nfs4_remote_fs_type = { | 323 | struct file_system_type nfs4_fs_type = { |
361 | .owner = THIS_MODULE, | 324 | .owner = THIS_MODULE, |
362 | .name = "nfs4", | 325 | .name = "nfs4", |
363 | .mount = nfs4_remote_mount, | 326 | .mount = nfs_fs_mount, |
364 | .kill_sb = nfs4_kill_super, | 327 | .kill_sb = nfs_kill_super, |
365 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
366 | }; | ||
367 | |||
368 | struct file_system_type nfs4_xdev_fs_type = { | ||
369 | .owner = THIS_MODULE, | ||
370 | .name = "nfs4", | ||
371 | .mount = nfs4_xdev_mount, | ||
372 | .kill_sb = nfs4_kill_super, | ||
373 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 328 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
374 | }; | 329 | }; |
330 | EXPORT_SYMBOL_GPL(nfs4_fs_type); | ||
375 | 331 | ||
376 | static struct file_system_type nfs4_remote_referral_fs_type = { | 332 | static int __init register_nfs4_fs(void) |
377 | .owner = THIS_MODULE, | 333 | { |
378 | .name = "nfs4", | 334 | return register_filesystem(&nfs4_fs_type); |
379 | .mount = nfs4_remote_referral_mount, | 335 | } |
380 | .kill_sb = nfs4_kill_super, | ||
381 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
382 | }; | ||
383 | 336 | ||
384 | struct file_system_type nfs4_referral_fs_type = { | 337 | static void unregister_nfs4_fs(void) |
385 | .owner = THIS_MODULE, | 338 | { |
386 | .name = "nfs4", | 339 | unregister_filesystem(&nfs4_fs_type); |
387 | .mount = nfs4_referral_mount, | 340 | } |
388 | .kill_sb = nfs4_kill_super, | 341 | #else |
389 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 342 | static int __init register_nfs4_fs(void) |
390 | }; | 343 | { |
344 | return 0; | ||
345 | } | ||
391 | 346 | ||
392 | static const struct super_operations nfs4_sops = { | 347 | static void unregister_nfs4_fs(void) |
393 | .alloc_inode = nfs_alloc_inode, | 348 | { |
394 | .destroy_inode = nfs_destroy_inode, | 349 | } |
395 | .write_inode = nfs_write_inode, | ||
396 | .put_super = nfs_put_super, | ||
397 | .statfs = nfs_statfs, | ||
398 | .evict_inode = nfs4_evict_inode, | ||
399 | .umount_begin = nfs_umount_begin, | ||
400 | .show_options = nfs_show_options, | ||
401 | .show_devname = nfs_show_devname, | ||
402 | .show_path = nfs_show_path, | ||
403 | .show_stats = nfs_show_stats, | ||
404 | .remount_fs = nfs_remount, | ||
405 | }; | ||
406 | #endif | 350 | #endif |
407 | 351 | ||
408 | static struct shrinker acl_shrinker = { | 352 | static struct shrinker acl_shrinker = { |
@@ -421,21 +365,18 @@ int __init register_nfs_fs(void) | |||
421 | if (ret < 0) | 365 | if (ret < 0) |
422 | goto error_0; | 366 | goto error_0; |
423 | 367 | ||
424 | ret = nfs_register_sysctl(); | 368 | ret = register_nfs4_fs(); |
425 | if (ret < 0) | 369 | if (ret < 0) |
426 | goto error_1; | 370 | goto error_1; |
427 | #ifdef CONFIG_NFS_V4 | 371 | |
428 | ret = register_filesystem(&nfs4_fs_type); | 372 | ret = nfs_register_sysctl(); |
429 | if (ret < 0) | 373 | if (ret < 0) |
430 | goto error_2; | 374 | goto error_2; |
431 | #endif | ||
432 | register_shrinker(&acl_shrinker); | 375 | register_shrinker(&acl_shrinker); |
433 | return 0; | 376 | return 0; |
434 | 377 | ||
435 | #ifdef CONFIG_NFS_V4 | ||
436 | error_2: | 378 | error_2: |
437 | nfs_unregister_sysctl(); | 379 | unregister_nfs4_fs(); |
438 | #endif | ||
439 | error_1: | 380 | error_1: |
440 | unregister_filesystem(&nfs_fs_type); | 381 | unregister_filesystem(&nfs_fs_type); |
441 | error_0: | 382 | error_0: |
@@ -448,10 +389,8 @@ error_0: | |||
448 | void __exit unregister_nfs_fs(void) | 389 | void __exit unregister_nfs_fs(void) |
449 | { | 390 | { |
450 | unregister_shrinker(&acl_shrinker); | 391 | unregister_shrinker(&acl_shrinker); |
451 | #ifdef CONFIG_NFS_V4 | ||
452 | unregister_filesystem(&nfs4_fs_type); | ||
453 | #endif | ||
454 | nfs_unregister_sysctl(); | 392 | nfs_unregister_sysctl(); |
393 | unregister_nfs4_fs(); | ||
455 | unregister_filesystem(&nfs_fs_type); | 394 | unregister_filesystem(&nfs_fs_type); |
456 | } | 395 | } |
457 | 396 | ||
@@ -462,6 +401,7 @@ void nfs_sb_active(struct super_block *sb) | |||
462 | if (atomic_inc_return(&server->active) == 1) | 401 | if (atomic_inc_return(&server->active) == 1) |
463 | atomic_inc(&sb->s_active); | 402 | atomic_inc(&sb->s_active); |
464 | } | 403 | } |
404 | EXPORT_SYMBOL_GPL(nfs_sb_active); | ||
465 | 405 | ||
466 | void nfs_sb_deactive(struct super_block *sb) | 406 | void nfs_sb_deactive(struct super_block *sb) |
467 | { | 407 | { |
@@ -470,11 +410,12 @@ void nfs_sb_deactive(struct super_block *sb) | |||
470 | if (atomic_dec_and_test(&server->active)) | 410 | if (atomic_dec_and_test(&server->active)) |
471 | deactivate_super(sb); | 411 | deactivate_super(sb); |
472 | } | 412 | } |
413 | EXPORT_SYMBOL_GPL(nfs_sb_deactive); | ||
473 | 414 | ||
474 | /* | 415 | /* |
475 | * Deliver file system statistics to userspace | 416 | * Deliver file system statistics to userspace |
476 | */ | 417 | */ |
477 | static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 418 | int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
478 | { | 419 | { |
479 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 420 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
480 | unsigned char blockbits; | 421 | unsigned char blockbits; |
@@ -535,6 +476,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
535 | dprintk("%s: statfs error = %d\n", __func__, -error); | 476 | dprintk("%s: statfs error = %d\n", __func__, -error); |
536 | return error; | 477 | return error; |
537 | } | 478 | } |
479 | EXPORT_SYMBOL_GPL(nfs_statfs); | ||
538 | 480 | ||
539 | /* | 481 | /* |
540 | * Map the security flavour number to a name | 482 | * Map the security flavour number to a name |
@@ -640,7 +582,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, | |||
640 | nfs_show_mountd_netid(m, nfss, showdefaults); | 582 | nfs_show_mountd_netid(m, nfss, showdefaults); |
641 | } | 583 | } |
642 | 584 | ||
643 | #ifdef CONFIG_NFS_V4 | 585 | #if IS_ENABLED(CONFIG_NFS_V4) |
644 | static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, | 586 | static void nfs_show_nfsv4_options(struct seq_file *m, struct nfs_server *nfss, |
645 | int showdefaults) | 587 | int showdefaults) |
646 | { | 588 | { |
@@ -757,7 +699,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
757 | /* | 699 | /* |
758 | * Describe the mount options on this VFS mountpoint | 700 | * Describe the mount options on this VFS mountpoint |
759 | */ | 701 | */ |
760 | static int nfs_show_options(struct seq_file *m, struct dentry *root) | 702 | int nfs_show_options(struct seq_file *m, struct dentry *root) |
761 | { | 703 | { |
762 | struct nfs_server *nfss = NFS_SB(root->d_sb); | 704 | struct nfs_server *nfss = NFS_SB(root->d_sb); |
763 | 705 | ||
@@ -771,8 +713,9 @@ static int nfs_show_options(struct seq_file *m, struct dentry *root) | |||
771 | 713 | ||
772 | return 0; | 714 | return 0; |
773 | } | 715 | } |
716 | EXPORT_SYMBOL_GPL(nfs_show_options); | ||
774 | 717 | ||
775 | #ifdef CONFIG_NFS_V4 | 718 | #if IS_ENABLED(CONFIG_NFS_V4) |
776 | #ifdef CONFIG_NFS_V4_1 | 719 | #ifdef CONFIG_NFS_V4_1 |
777 | static void show_sessions(struct seq_file *m, struct nfs_server *server) | 720 | static void show_sessions(struct seq_file *m, struct nfs_server *server) |
778 | { | 721 | { |
@@ -805,7 +748,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss) | |||
805 | } | 748 | } |
806 | } | 749 | } |
807 | #else | 750 | #else |
808 | #ifdef CONFIG_NFS_V4 | 751 | #if IS_ENABLED(CONFIG_NFS_V4) |
809 | static void show_pnfs(struct seq_file *m, struct nfs_server *server) | 752 | static void show_pnfs(struct seq_file *m, struct nfs_server *server) |
810 | { | 753 | { |
811 | } | 754 | } |
@@ -815,7 +758,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss) | |||
815 | } | 758 | } |
816 | #endif | 759 | #endif |
817 | 760 | ||
818 | static int nfs_show_devname(struct seq_file *m, struct dentry *root) | 761 | int nfs_show_devname(struct seq_file *m, struct dentry *root) |
819 | { | 762 | { |
820 | char *page = (char *) __get_free_page(GFP_KERNEL); | 763 | char *page = (char *) __get_free_page(GFP_KERNEL); |
821 | char *devname, *dummy; | 764 | char *devname, *dummy; |
@@ -830,17 +773,19 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root) | |||
830 | free_page((unsigned long)page); | 773 | free_page((unsigned long)page); |
831 | return err; | 774 | return err; |
832 | } | 775 | } |
776 | EXPORT_SYMBOL_GPL(nfs_show_devname); | ||
833 | 777 | ||
834 | static int nfs_show_path(struct seq_file *m, struct dentry *dentry) | 778 | int nfs_show_path(struct seq_file *m, struct dentry *dentry) |
835 | { | 779 | { |
836 | seq_puts(m, "/"); | 780 | seq_puts(m, "/"); |
837 | return 0; | 781 | return 0; |
838 | } | 782 | } |
783 | EXPORT_SYMBOL_GPL(nfs_show_path); | ||
839 | 784 | ||
840 | /* | 785 | /* |
841 | * Present statistical information for this VFS mountpoint | 786 | * Present statistical information for this VFS mountpoint |
842 | */ | 787 | */ |
843 | static int nfs_show_stats(struct seq_file *m, struct dentry *root) | 788 | int nfs_show_stats(struct seq_file *m, struct dentry *root) |
844 | { | 789 | { |
845 | int i, cpu; | 790 | int i, cpu; |
846 | struct nfs_server *nfss = NFS_SB(root->d_sb); | 791 | struct nfs_server *nfss = NFS_SB(root->d_sb); |
@@ -870,7 +815,7 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
870 | seq_printf(m, ",bsize=%u", nfss->bsize); | 815 | seq_printf(m, ",bsize=%u", nfss->bsize); |
871 | seq_printf(m, ",namlen=%u", nfss->namelen); | 816 | seq_printf(m, ",namlen=%u", nfss->namelen); |
872 | 817 | ||
873 | #ifdef CONFIG_NFS_V4 | 818 | #if IS_ENABLED(CONFIG_NFS_V4) |
874 | if (nfss->nfs_client->rpc_ops->version == 4) { | 819 | if (nfss->nfs_client->rpc_ops->version == 4) { |
875 | seq_printf(m, "\n\tnfsv4:\t"); | 820 | seq_printf(m, "\n\tnfsv4:\t"); |
876 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 821 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
@@ -928,12 +873,13 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
928 | 873 | ||
929 | return 0; | 874 | return 0; |
930 | } | 875 | } |
876 | EXPORT_SYMBOL_GPL(nfs_show_stats); | ||
931 | 877 | ||
932 | /* | 878 | /* |
933 | * Begin unmount by attempting to remove all automounted mountpoints we added | 879 | * Begin unmount by attempting to remove all automounted mountpoints we added |
934 | * in response to xdev traversals and referrals | 880 | * in response to xdev traversals and referrals |
935 | */ | 881 | */ |
936 | static void nfs_umount_begin(struct super_block *sb) | 882 | void nfs_umount_begin(struct super_block *sb) |
937 | { | 883 | { |
938 | struct nfs_server *server; | 884 | struct nfs_server *server; |
939 | struct rpc_clnt *rpc; | 885 | struct rpc_clnt *rpc; |
@@ -947,6 +893,7 @@ static void nfs_umount_begin(struct super_block *sb) | |||
947 | if (!IS_ERR(rpc)) | 893 | if (!IS_ERR(rpc)) |
948 | rpc_killall_tasks(rpc); | 894 | rpc_killall_tasks(rpc); |
949 | } | 895 | } |
896 | EXPORT_SYMBOL_GPL(nfs_umount_begin); | ||
950 | 897 | ||
951 | static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) | 898 | static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) |
952 | { | 899 | { |
@@ -1590,7 +1537,7 @@ static int nfs_parse_mount_options(char *raw, | |||
1590 | 1537 | ||
1591 | /* | 1538 | /* |
1592 | * verify that any proto=/mountproto= options match the address | 1539 | * verify that any proto=/mountproto= options match the address |
1593 | * familiies in the addr=/mountaddr= options. | 1540 | * families in the addr=/mountaddr= options. |
1594 | */ | 1541 | */ |
1595 | if (protofamily != AF_UNSPEC && | 1542 | if (protofamily != AF_UNSPEC && |
1596 | protofamily != mnt->nfs_server.address.ss_family) | 1543 | protofamily != mnt->nfs_server.address.ss_family) |
@@ -1748,8 +1695,9 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args, | |||
1748 | return nfs_walk_authlist(args, &request); | 1695 | return nfs_walk_authlist(args, &request); |
1749 | } | 1696 | } |
1750 | 1697 | ||
1751 | static struct dentry *nfs_try_mount(int flags, const char *dev_name, | 1698 | struct dentry *nfs_try_mount(int flags, const char *dev_name, |
1752 | struct nfs_mount_info *mount_info) | 1699 | struct nfs_mount_info *mount_info, |
1700 | struct nfs_subversion *nfs_mod) | ||
1753 | { | 1701 | { |
1754 | int status; | 1702 | int status; |
1755 | struct nfs_server *server; | 1703 | struct nfs_server *server; |
@@ -1761,12 +1709,13 @@ static struct dentry *nfs_try_mount(int flags, const char *dev_name, | |||
1761 | } | 1709 | } |
1762 | 1710 | ||
1763 | /* Get a volume representation */ | 1711 | /* Get a volume representation */ |
1764 | server = nfs_create_server(mount_info->parsed, mount_info->mntfh); | 1712 | server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod); |
1765 | if (IS_ERR(server)) | 1713 | if (IS_ERR(server)) |
1766 | return ERR_CAST(server); | 1714 | return ERR_CAST(server); |
1767 | 1715 | ||
1768 | return nfs_fs_mount_common(&nfs_fs_type, server, flags, dev_name, mount_info); | 1716 | return nfs_fs_mount_common(server, flags, dev_name, mount_info, nfs_mod); |
1769 | } | 1717 | } |
1718 | EXPORT_SYMBOL_GPL(nfs_try_mount); | ||
1770 | 1719 | ||
1771 | /* | 1720 | /* |
1772 | * Split "dev_name" into "hostname:export_path". | 1721 | * Split "dev_name" into "hostname:export_path". |
@@ -1918,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1918 | 1867 | ||
1919 | memcpy(sap, &data->addr, sizeof(data->addr)); | 1868 | memcpy(sap, &data->addr, sizeof(data->addr)); |
1920 | args->nfs_server.addrlen = sizeof(data->addr); | 1869 | args->nfs_server.addrlen = sizeof(data->addr); |
1870 | args->nfs_server.port = ntohs(data->addr.sin_port); | ||
1921 | if (!nfs_verify_server_address(sap)) | 1871 | if (!nfs_verify_server_address(sap)) |
1922 | goto out_no_address; | 1872 | goto out_no_address; |
1923 | 1873 | ||
@@ -1970,7 +1920,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1970 | return NFS_TEXT_DATA; | 1920 | return NFS_TEXT_DATA; |
1971 | } | 1921 | } |
1972 | 1922 | ||
1973 | #ifndef CONFIG_NFS_V3 | 1923 | #if !IS_ENABLED(CONFIG_NFS_V3) |
1974 | if (args->version == 3) | 1924 | if (args->version == 3) |
1975 | goto out_v3_not_compiled; | 1925 | goto out_v3_not_compiled; |
1976 | #endif /* !CONFIG_NFS_V3 */ | 1926 | #endif /* !CONFIG_NFS_V3 */ |
@@ -1990,7 +1940,7 @@ out_no_sec: | |||
1990 | dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n"); | 1940 | dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n"); |
1991 | return -EINVAL; | 1941 | return -EINVAL; |
1992 | 1942 | ||
1993 | #ifndef CONFIG_NFS_V3 | 1943 | #if !IS_ENABLED(CONFIG_NFS_V3) |
1994 | out_v3_not_compiled: | 1944 | out_v3_not_compiled: |
1995 | dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n"); | 1945 | dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n"); |
1996 | return -EPROTONOSUPPORT; | 1946 | return -EPROTONOSUPPORT; |
@@ -2009,7 +1959,7 @@ out_invalid_fh: | |||
2009 | return -EINVAL; | 1959 | return -EINVAL; |
2010 | } | 1960 | } |
2011 | 1961 | ||
2012 | #ifdef CONFIG_NFS_V4 | 1962 | #if IS_ENABLED(CONFIG_NFS_V4) |
2013 | static int nfs_validate_mount_data(struct file_system_type *fs_type, | 1963 | static int nfs_validate_mount_data(struct file_system_type *fs_type, |
2014 | void *options, | 1964 | void *options, |
2015 | struct nfs_parsed_mount_data *args, | 1965 | struct nfs_parsed_mount_data *args, |
@@ -2047,7 +1997,7 @@ static int nfs_validate_text_mount_data(void *options, | |||
2047 | goto out_no_address; | 1997 | goto out_no_address; |
2048 | 1998 | ||
2049 | if (args->version == 4) { | 1999 | if (args->version == 4) { |
2050 | #ifdef CONFIG_NFS_V4 | 2000 | #if IS_ENABLED(CONFIG_NFS_V4) |
2051 | port = NFS_PORT; | 2001 | port = NFS_PORT; |
2052 | max_namelen = NFS4_MAXNAMLEN; | 2002 | max_namelen = NFS4_MAXNAMLEN; |
2053 | max_pathlen = NFS4_MAXPATHLEN; | 2003 | max_pathlen = NFS4_MAXPATHLEN; |
@@ -2070,7 +2020,7 @@ static int nfs_validate_text_mount_data(void *options, | |||
2070 | &args->nfs_server.export_path, | 2020 | &args->nfs_server.export_path, |
2071 | max_pathlen); | 2021 | max_pathlen); |
2072 | 2022 | ||
2073 | #ifndef CONFIG_NFS_V4 | 2023 | #if !IS_ENABLED(CONFIG_NFS_V4) |
2074 | out_v4_not_compiled: | 2024 | out_v4_not_compiled: |
2075 | dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n"); | 2025 | dfprintk(MOUNT, "NFS: NFSv4 is not compiled into kernel\n"); |
2076 | return -EPROTONOSUPPORT; | 2026 | return -EPROTONOSUPPORT; |
@@ -2108,7 +2058,7 @@ nfs_compare_remount_data(struct nfs_server *nfss, | |||
2108 | return 0; | 2058 | return 0; |
2109 | } | 2059 | } |
2110 | 2060 | ||
2111 | static int | 2061 | int |
2112 | nfs_remount(struct super_block *sb, int *flags, char *raw_data) | 2062 | nfs_remount(struct super_block *sb, int *flags, char *raw_data) |
2113 | { | 2063 | { |
2114 | int error; | 2064 | int error; |
@@ -2169,11 +2119,12 @@ out: | |||
2169 | kfree(data); | 2119 | kfree(data); |
2170 | return error; | 2120 | return error; |
2171 | } | 2121 | } |
2122 | EXPORT_SYMBOL_GPL(nfs_remount); | ||
2172 | 2123 | ||
2173 | /* | 2124 | /* |
2174 | * Initialise the common bits of the superblock | 2125 | * Initialise the common bits of the superblock |
2175 | */ | 2126 | */ |
2176 | static inline void nfs_initialise_sb(struct super_block *sb) | 2127 | inline void nfs_initialise_sb(struct super_block *sb) |
2177 | { | 2128 | { |
2178 | struct nfs_server *server = NFS_SB(sb); | 2129 | struct nfs_server *server = NFS_SB(sb); |
2179 | 2130 | ||
@@ -2195,18 +2146,19 @@ static inline void nfs_initialise_sb(struct super_block *sb) | |||
2195 | /* | 2146 | /* |
2196 | * Finish setting up an NFS2/3 superblock | 2147 | * Finish setting up an NFS2/3 superblock |
2197 | */ | 2148 | */ |
2198 | static void nfs_fill_super(struct super_block *sb, | 2149 | void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) |
2199 | struct nfs_mount_info *mount_info) | ||
2200 | { | 2150 | { |
2201 | struct nfs_parsed_mount_data *data = mount_info->parsed; | 2151 | struct nfs_parsed_mount_data *data = mount_info->parsed; |
2202 | struct nfs_server *server = NFS_SB(sb); | 2152 | struct nfs_server *server = NFS_SB(sb); |
2203 | 2153 | ||
2204 | sb->s_blocksize_bits = 0; | 2154 | sb->s_blocksize_bits = 0; |
2205 | sb->s_blocksize = 0; | 2155 | sb->s_blocksize = 0; |
2206 | if (data->bsize) | 2156 | sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr; |
2157 | sb->s_op = server->nfs_client->cl_nfs_mod->sops; | ||
2158 | if (data && data->bsize) | ||
2207 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); | 2159 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); |
2208 | 2160 | ||
2209 | if (server->nfs_client->rpc_ops->version == 3) { | 2161 | if (server->nfs_client->rpc_ops->version != 2) { |
2210 | /* The VFS shouldn't apply the umask to mode bits. We will do | 2162 | /* The VFS shouldn't apply the umask to mode bits. We will do |
2211 | * so ourselves when necessary. | 2163 | * so ourselves when necessary. |
2212 | */ | 2164 | */ |
@@ -2214,15 +2166,14 @@ static void nfs_fill_super(struct super_block *sb, | |||
2214 | sb->s_time_gran = 1; | 2166 | sb->s_time_gran = 1; |
2215 | } | 2167 | } |
2216 | 2168 | ||
2217 | sb->s_op = &nfs_sops; | ||
2218 | nfs_initialise_sb(sb); | 2169 | nfs_initialise_sb(sb); |
2219 | } | 2170 | } |
2171 | EXPORT_SYMBOL_GPL(nfs_fill_super); | ||
2220 | 2172 | ||
2221 | /* | 2173 | /* |
2222 | * Finish setting up a cloned NFS2/3 superblock | 2174 | * Finish setting up a cloned NFS2/3/4 superblock |
2223 | */ | 2175 | */ |
2224 | static void nfs_clone_super(struct super_block *sb, | 2176 | void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) |
2225 | struct nfs_mount_info *mount_info) | ||
2226 | { | 2177 | { |
2227 | const struct super_block *old_sb = mount_info->cloned->sb; | 2178 | const struct super_block *old_sb = mount_info->cloned->sb; |
2228 | struct nfs_server *server = NFS_SB(sb); | 2179 | struct nfs_server *server = NFS_SB(sb); |
@@ -2230,16 +2181,17 @@ static void nfs_clone_super(struct super_block *sb, | |||
2230 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; | 2181 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; |
2231 | sb->s_blocksize = old_sb->s_blocksize; | 2182 | sb->s_blocksize = old_sb->s_blocksize; |
2232 | sb->s_maxbytes = old_sb->s_maxbytes; | 2183 | sb->s_maxbytes = old_sb->s_maxbytes; |
2184 | sb->s_xattr = old_sb->s_xattr; | ||
2185 | sb->s_op = old_sb->s_op; | ||
2186 | sb->s_time_gran = 1; | ||
2233 | 2187 | ||
2234 | if (server->nfs_client->rpc_ops->version == 3) { | 2188 | if (server->nfs_client->rpc_ops->version != 2) { |
2235 | /* The VFS shouldn't apply the umask to mode bits. We will do | 2189 | /* The VFS shouldn't apply the umask to mode bits. We will do |
2236 | * so ourselves when necessary. | 2190 | * so ourselves when necessary. |
2237 | */ | 2191 | */ |
2238 | sb->s_flags |= MS_POSIXACL; | 2192 | sb->s_flags |= MS_POSIXACL; |
2239 | sb->s_time_gran = 1; | ||
2240 | } | 2193 | } |
2241 | 2194 | ||
2242 | sb->s_op = old_sb->s_op; | ||
2243 | nfs_initialise_sb(sb); | 2195 | nfs_initialise_sb(sb); |
2244 | } | 2196 | } |
2245 | 2197 | ||
@@ -2381,14 +2333,15 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2381 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); | 2333 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); |
2382 | } | 2334 | } |
2383 | 2335 | ||
2384 | static int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | 2336 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, |
2385 | struct nfs_mount_info *mount_info) | 2337 | struct nfs_mount_info *mount_info) |
2386 | { | 2338 | { |
2387 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); | 2339 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); |
2388 | } | 2340 | } |
2341 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); | ||
2389 | 2342 | ||
2390 | static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | 2343 | int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, |
2391 | struct nfs_mount_info *mount_info) | 2344 | struct nfs_mount_info *mount_info) |
2392 | { | 2345 | { |
2393 | /* clone any lsm security options from the parent to the new sb */ | 2346 | /* clone any lsm security options from the parent to the new sb */ |
2394 | security_sb_clone_mnt_opts(mount_info->cloned->sb, s); | 2347 | security_sb_clone_mnt_opts(mount_info->cloned->sb, s); |
@@ -2396,11 +2349,12 @@ static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | |||
2396 | return -ESTALE; | 2349 | return -ESTALE; |
2397 | return 0; | 2350 | return 0; |
2398 | } | 2351 | } |
2352 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); | ||
2399 | 2353 | ||
2400 | static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, | 2354 | struct dentry *nfs_fs_mount_common(struct nfs_server *server, |
2401 | struct nfs_server *server, | 2355 | int flags, const char *dev_name, |
2402 | int flags, const char *dev_name, | 2356 | struct nfs_mount_info *mount_info, |
2403 | struct nfs_mount_info *mount_info) | 2357 | struct nfs_subversion *nfs_mod) |
2404 | { | 2358 | { |
2405 | struct super_block *s; | 2359 | struct super_block *s; |
2406 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | 2360 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
@@ -2419,7 +2373,7 @@ static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, | |||
2419 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; | 2373 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; |
2420 | 2374 | ||
2421 | /* Get a superblock - note that we may end up sharing one that already exists */ | 2375 | /* Get a superblock - note that we may end up sharing one that already exists */ |
2422 | s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata); | 2376 | s = sget(nfs_mod->nfs_fs, compare_super, nfs_set_super, flags, &sb_mntdata); |
2423 | if (IS_ERR(s)) { | 2377 | if (IS_ERR(s)) { |
2424 | mntroot = ERR_CAST(s); | 2378 | mntroot = ERR_CAST(s); |
2425 | goto out_err_nosb; | 2379 | goto out_err_nosb; |
@@ -2469,8 +2423,9 @@ error_splat_bdi: | |||
2469 | deactivate_locked_super(s); | 2423 | deactivate_locked_super(s); |
2470 | goto out; | 2424 | goto out; |
2471 | } | 2425 | } |
2426 | EXPORT_SYMBOL_GPL(nfs_fs_mount_common); | ||
2472 | 2427 | ||
2473 | static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | 2428 | struct dentry *nfs_fs_mount(struct file_system_type *fs_type, |
2474 | int flags, const char *dev_name, void *raw_data) | 2429 | int flags, const char *dev_name, void *raw_data) |
2475 | { | 2430 | { |
2476 | struct nfs_mount_info mount_info = { | 2431 | struct nfs_mount_info mount_info = { |
@@ -2478,6 +2433,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2478 | .set_security = nfs_set_sb_security, | 2433 | .set_security = nfs_set_sb_security, |
2479 | }; | 2434 | }; |
2480 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | 2435 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
2436 | struct nfs_subversion *nfs_mod; | ||
2481 | int error; | 2437 | int error; |
2482 | 2438 | ||
2483 | mount_info.parsed = nfs_alloc_parsed_mount_data(); | 2439 | mount_info.parsed = nfs_alloc_parsed_mount_data(); |
@@ -2494,34 +2450,38 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | |||
2494 | goto out; | 2450 | goto out; |
2495 | } | 2451 | } |
2496 | 2452 | ||
2497 | #ifdef CONFIG_NFS_V4 | 2453 | nfs_mod = get_nfs_version(mount_info.parsed->version); |
2498 | if (mount_info.parsed->version == 4) | 2454 | if (IS_ERR(nfs_mod)) { |
2499 | mntroot = nfs4_try_mount(flags, dev_name, &mount_info); | 2455 | mntroot = ERR_CAST(nfs_mod); |
2500 | else | 2456 | goto out; |
2501 | #endif /* CONFIG_NFS_V4 */ | 2457 | } |
2502 | mntroot = nfs_try_mount(flags, dev_name, &mount_info); | 2458 | |
2459 | mntroot = nfs_mod->rpc_ops->try_mount(flags, dev_name, &mount_info, nfs_mod); | ||
2503 | 2460 | ||
2461 | put_nfs_version(nfs_mod); | ||
2504 | out: | 2462 | out: |
2505 | nfs_free_parsed_mount_data(mount_info.parsed); | 2463 | nfs_free_parsed_mount_data(mount_info.parsed); |
2506 | nfs_free_fhandle(mount_info.mntfh); | 2464 | nfs_free_fhandle(mount_info.mntfh); |
2507 | return mntroot; | 2465 | return mntroot; |
2508 | } | 2466 | } |
2467 | EXPORT_SYMBOL_GPL(nfs_fs_mount); | ||
2509 | 2468 | ||
2510 | /* | 2469 | /* |
2511 | * Ensure that we unregister the bdi before kill_anon_super | 2470 | * Ensure that we unregister the bdi before kill_anon_super |
2512 | * releases the device name | 2471 | * releases the device name |
2513 | */ | 2472 | */ |
2514 | static void nfs_put_super(struct super_block *s) | 2473 | void nfs_put_super(struct super_block *s) |
2515 | { | 2474 | { |
2516 | struct nfs_server *server = NFS_SB(s); | 2475 | struct nfs_server *server = NFS_SB(s); |
2517 | 2476 | ||
2518 | bdi_unregister(&server->backing_dev_info); | 2477 | bdi_unregister(&server->backing_dev_info); |
2519 | } | 2478 | } |
2479 | EXPORT_SYMBOL_GPL(nfs_put_super); | ||
2520 | 2480 | ||
2521 | /* | 2481 | /* |
2522 | * Destroy an NFS2/3 superblock | 2482 | * Destroy an NFS2/3 superblock |
2523 | */ | 2483 | */ |
2524 | static void nfs_kill_super(struct super_block *s) | 2484 | void nfs_kill_super(struct super_block *s) |
2525 | { | 2485 | { |
2526 | struct nfs_server *server = NFS_SB(s); | 2486 | struct nfs_server *server = NFS_SB(s); |
2527 | 2487 | ||
@@ -2529,31 +2489,38 @@ static void nfs_kill_super(struct super_block *s) | |||
2529 | nfs_fscache_release_super_cookie(s); | 2489 | nfs_fscache_release_super_cookie(s); |
2530 | nfs_free_server(server); | 2490 | nfs_free_server(server); |
2531 | } | 2491 | } |
2492 | EXPORT_SYMBOL_GPL(nfs_kill_super); | ||
2532 | 2493 | ||
2533 | /* | 2494 | /* |
2534 | * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) | 2495 | * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) |
2535 | */ | 2496 | */ |
2536 | static struct dentry * | 2497 | struct dentry * |
2537 | nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, | 2498 | nfs_xdev_mount(struct file_system_type *fs_type, int flags, |
2538 | const char *dev_name, struct nfs_mount_info *mount_info) | 2499 | const char *dev_name, void *raw_data) |
2539 | { | 2500 | { |
2540 | struct nfs_clone_mount *data = mount_info->cloned; | 2501 | struct nfs_clone_mount *data = raw_data; |
2502 | struct nfs_mount_info mount_info = { | ||
2503 | .fill_super = nfs_clone_super, | ||
2504 | .set_security = nfs_clone_sb_security, | ||
2505 | .cloned = data, | ||
2506 | }; | ||
2541 | struct nfs_server *server; | 2507 | struct nfs_server *server; |
2542 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | 2508 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
2509 | struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod; | ||
2543 | int error; | 2510 | int error; |
2544 | 2511 | ||
2545 | dprintk("--> nfs_xdev_mount_common()\n"); | 2512 | dprintk("--> nfs_xdev_mount_common()\n"); |
2546 | 2513 | ||
2547 | mount_info->mntfh = data->fh; | 2514 | mount_info.mntfh = mount_info.cloned->fh; |
2548 | 2515 | ||
2549 | /* create a new volume representation */ | 2516 | /* create a new volume representation */ |
2550 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); | 2517 | server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor); |
2551 | if (IS_ERR(server)) { | 2518 | if (IS_ERR(server)) { |
2552 | error = PTR_ERR(server); | 2519 | error = PTR_ERR(server); |
2553 | goto out_err; | 2520 | goto out_err; |
2554 | } | 2521 | } |
2555 | 2522 | ||
2556 | mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); | 2523 | mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod); |
2557 | dprintk("<-- nfs_xdev_mount_common() = 0\n"); | 2524 | dprintk("<-- nfs_xdev_mount_common() = 0\n"); |
2558 | out: | 2525 | out: |
2559 | return mntroot; | 2526 | return mntroot; |
@@ -2563,60 +2530,7 @@ out_err: | |||
2563 | goto out; | 2530 | goto out; |
2564 | } | 2531 | } |
2565 | 2532 | ||
2566 | /* | 2533 | #if IS_ENABLED(CONFIG_NFS_V4) |
2567 | * Clone an NFS2/3 server record on xdev traversal (FSID-change) | ||
2568 | */ | ||
2569 | static struct dentry * | ||
2570 | nfs_xdev_mount(struct file_system_type *fs_type, int flags, | ||
2571 | const char *dev_name, void *raw_data) | ||
2572 | { | ||
2573 | struct nfs_mount_info mount_info = { | ||
2574 | .fill_super = nfs_clone_super, | ||
2575 | .set_security = nfs_clone_sb_security, | ||
2576 | .cloned = raw_data, | ||
2577 | }; | ||
2578 | return nfs_xdev_mount_common(&nfs_fs_type, flags, dev_name, &mount_info); | ||
2579 | } | ||
2580 | |||
2581 | #ifdef CONFIG_NFS_V4 | ||
2582 | |||
2583 | /* | ||
2584 | * Finish setting up a cloned NFS4 superblock | ||
2585 | */ | ||
2586 | static void nfs4_clone_super(struct super_block *sb, | ||
2587 | struct nfs_mount_info *mount_info) | ||
2588 | { | ||
2589 | const struct super_block *old_sb = mount_info->cloned->sb; | ||
2590 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; | ||
2591 | sb->s_blocksize = old_sb->s_blocksize; | ||
2592 | sb->s_maxbytes = old_sb->s_maxbytes; | ||
2593 | sb->s_time_gran = 1; | ||
2594 | sb->s_op = old_sb->s_op; | ||
2595 | /* | ||
2596 | * The VFS shouldn't apply the umask to mode bits. We will do | ||
2597 | * so ourselves when necessary. | ||
2598 | */ | ||
2599 | sb->s_flags |= MS_POSIXACL; | ||
2600 | sb->s_xattr = old_sb->s_xattr; | ||
2601 | nfs_initialise_sb(sb); | ||
2602 | } | ||
2603 | |||
2604 | /* | ||
2605 | * Set up an NFS4 superblock | ||
2606 | */ | ||
2607 | static void nfs4_fill_super(struct super_block *sb, | ||
2608 | struct nfs_mount_info *mount_info) | ||
2609 | { | ||
2610 | sb->s_time_gran = 1; | ||
2611 | sb->s_op = &nfs4_sops; | ||
2612 | /* | ||
2613 | * The VFS shouldn't apply the umask to mode bits. We will do | ||
2614 | * so ourselves when necessary. | ||
2615 | */ | ||
2616 | sb->s_flags |= MS_POSIXACL; | ||
2617 | sb->s_xattr = nfs4_xattr_handlers; | ||
2618 | nfs_initialise_sb(sb); | ||
2619 | } | ||
2620 | 2534 | ||
2621 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) | 2535 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) |
2622 | { | 2536 | { |
@@ -2651,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options, | |||
2651 | return -EFAULT; | 2565 | return -EFAULT; |
2652 | if (!nfs_verify_server_address(sap)) | 2566 | if (!nfs_verify_server_address(sap)) |
2653 | goto out_no_address; | 2567 | goto out_no_address; |
2568 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); | ||
2654 | 2569 | ||
2655 | if (data->auth_flavourlen) { | 2570 | if (data->auth_flavourlen) { |
2656 | if (data->auth_flavourlen > 1) | 2571 | if (data->auth_flavourlen > 1) |
@@ -2716,249 +2631,57 @@ out_no_address: | |||
2716 | } | 2631 | } |
2717 | 2632 | ||
2718 | /* | 2633 | /* |
2719 | * Get the superblock for the NFS4 root partition | 2634 | * NFS v4 module parameters need to stay in the |
2635 | * NFS client for backwards compatibility | ||
2720 | */ | 2636 | */ |
2721 | static struct dentry * | 2637 | unsigned int nfs_callback_set_tcpport; |
2722 | nfs4_remote_mount(struct file_system_type *fs_type, int flags, | 2638 | unsigned short nfs_callback_tcpport; |
2723 | const char *dev_name, void *info) | 2639 | /* Default cache timeout is 10 minutes */ |
2724 | { | 2640 | unsigned int nfs_idmap_cache_timeout = 600; |
2725 | struct nfs_mount_info *mount_info = info; | 2641 | /* Turn off NFSv4 uid/gid mapping when using AUTH_SYS */ |
2726 | struct nfs_server *server; | 2642 | bool nfs4_disable_idmapping = true; |
2727 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | 2643 | unsigned short max_session_slots = NFS4_DEF_SLOT_TABLE_SIZE; |
2728 | 2644 | unsigned short send_implementation_id = 1; | |
2729 | mount_info->fill_super = nfs4_fill_super; | 2645 | |
2730 | mount_info->set_security = nfs_set_sb_security; | 2646 | EXPORT_SYMBOL_GPL(nfs_callback_set_tcpport); |
2731 | 2647 | EXPORT_SYMBOL_GPL(nfs_callback_tcpport); | |
2732 | /* Get a volume representation */ | 2648 | EXPORT_SYMBOL_GPL(nfs_idmap_cache_timeout); |
2733 | server = nfs4_create_server(mount_info->parsed, mount_info->mntfh); | 2649 | EXPORT_SYMBOL_GPL(nfs4_disable_idmapping); |
2734 | if (IS_ERR(server)) { | 2650 | EXPORT_SYMBOL_GPL(max_session_slots); |
2735 | mntroot = ERR_CAST(server); | 2651 | EXPORT_SYMBOL_GPL(send_implementation_id); |
2736 | goto out; | 2652 | |
2737 | } | 2653 | #define NFS_CALLBACK_MAXPORTNR (65535U) |
2738 | 2654 | ||
2739 | mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); | 2655 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
2740 | 2656 | { | |
2741 | out: | 2657 | unsigned long num; |
2742 | return mntroot; | 2658 | int ret; |
2743 | } | ||
2744 | |||
2745 | static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, | ||
2746 | int flags, void *data, const char *hostname) | ||
2747 | { | ||
2748 | struct vfsmount *root_mnt; | ||
2749 | char *root_devname; | ||
2750 | size_t len; | ||
2751 | 2659 | ||
2752 | len = strlen(hostname) + 5; | 2660 | if (!val) |
2753 | root_devname = kmalloc(len, GFP_KERNEL); | 2661 | return -EINVAL; |
2754 | if (root_devname == NULL) | 2662 | ret = strict_strtoul(val, 0, &num); |
2755 | return ERR_PTR(-ENOMEM); | 2663 | if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR) |
2756 | /* Does hostname needs to be enclosed in brackets? */ | 2664 | return -EINVAL; |
2757 | if (strchr(hostname, ':')) | 2665 | *((unsigned int *)kp->arg) = num; |
2758 | snprintf(root_devname, len, "[%s]:/", hostname); | 2666 | return 0; |
2759 | else | ||
2760 | snprintf(root_devname, len, "%s:/", hostname); | ||
2761 | root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); | ||
2762 | kfree(root_devname); | ||
2763 | return root_mnt; | ||
2764 | } | 2667 | } |
2765 | 2668 | static struct kernel_param_ops param_ops_portnr = { | |
2766 | struct nfs_referral_count { | 2669 | .set = param_set_portnr, |
2767 | struct list_head list; | 2670 | .get = param_get_uint, |
2768 | const struct task_struct *task; | ||
2769 | unsigned int referral_count; | ||
2770 | }; | 2671 | }; |
2771 | 2672 | #define param_check_portnr(name, p) __param_check(name, p, unsigned int); | |
2772 | static LIST_HEAD(nfs_referral_count_list); | 2673 | |
2773 | static DEFINE_SPINLOCK(nfs_referral_count_list_lock); | 2674 | module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); |
2774 | 2675 | module_param(nfs_idmap_cache_timeout, int, 0644); | |
2775 | static struct nfs_referral_count *nfs_find_referral_count(void) | 2676 | module_param(nfs4_disable_idmapping, bool, 0644); |
2776 | { | 2677 | MODULE_PARM_DESC(nfs4_disable_idmapping, |
2777 | struct nfs_referral_count *p; | 2678 | "Turn off NFSv4 idmapping when using 'sec=sys'"); |
2778 | 2679 | module_param(max_session_slots, ushort, 0644); | |
2779 | list_for_each_entry(p, &nfs_referral_count_list, list) { | 2680 | MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " |
2780 | if (p->task == current) | 2681 | "requests the client will negotiate"); |
2781 | return p; | 2682 | module_param(send_implementation_id, ushort, 0644); |
2782 | } | 2683 | MODULE_PARM_DESC(send_implementation_id, |
2783 | return NULL; | 2684 | "Send implementation ID with NFSv4.1 exchange_id"); |
2784 | } | 2685 | MODULE_ALIAS("nfs4"); |
2785 | |||
2786 | #define NFS_MAX_NESTED_REFERRALS 2 | ||
2787 | |||
2788 | static int nfs_referral_loop_protect(void) | ||
2789 | { | ||
2790 | struct nfs_referral_count *p, *new; | ||
2791 | int ret = -ENOMEM; | ||
2792 | |||
2793 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
2794 | if (!new) | ||
2795 | goto out; | ||
2796 | new->task = current; | ||
2797 | new->referral_count = 1; | ||
2798 | |||
2799 | ret = 0; | ||
2800 | spin_lock(&nfs_referral_count_list_lock); | ||
2801 | p = nfs_find_referral_count(); | ||
2802 | if (p != NULL) { | ||
2803 | if (p->referral_count >= NFS_MAX_NESTED_REFERRALS) | ||
2804 | ret = -ELOOP; | ||
2805 | else | ||
2806 | p->referral_count++; | ||
2807 | } else { | ||
2808 | list_add(&new->list, &nfs_referral_count_list); | ||
2809 | new = NULL; | ||
2810 | } | ||
2811 | spin_unlock(&nfs_referral_count_list_lock); | ||
2812 | kfree(new); | ||
2813 | out: | ||
2814 | return ret; | ||
2815 | } | ||
2816 | |||
2817 | static void nfs_referral_loop_unprotect(void) | ||
2818 | { | ||
2819 | struct nfs_referral_count *p; | ||
2820 | |||
2821 | spin_lock(&nfs_referral_count_list_lock); | ||
2822 | p = nfs_find_referral_count(); | ||
2823 | p->referral_count--; | ||
2824 | if (p->referral_count == 0) | ||
2825 | list_del(&p->list); | ||
2826 | else | ||
2827 | p = NULL; | ||
2828 | spin_unlock(&nfs_referral_count_list_lock); | ||
2829 | kfree(p); | ||
2830 | } | ||
2831 | |||
2832 | static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt, | ||
2833 | const char *export_path) | ||
2834 | { | ||
2835 | struct dentry *dentry; | ||
2836 | int err; | ||
2837 | |||
2838 | if (IS_ERR(root_mnt)) | ||
2839 | return ERR_CAST(root_mnt); | ||
2840 | |||
2841 | err = nfs_referral_loop_protect(); | ||
2842 | if (err) { | ||
2843 | mntput(root_mnt); | ||
2844 | return ERR_PTR(err); | ||
2845 | } | ||
2846 | |||
2847 | dentry = mount_subtree(root_mnt, export_path); | ||
2848 | nfs_referral_loop_unprotect(); | ||
2849 | |||
2850 | return dentry; | ||
2851 | } | ||
2852 | |||
2853 | static struct dentry *nfs4_try_mount(int flags, const char *dev_name, | ||
2854 | struct nfs_mount_info *mount_info) | ||
2855 | { | ||
2856 | char *export_path; | ||
2857 | struct vfsmount *root_mnt; | ||
2858 | struct dentry *res; | ||
2859 | struct nfs_parsed_mount_data *data = mount_info->parsed; | ||
2860 | |||
2861 | dfprintk(MOUNT, "--> nfs4_try_mount()\n"); | ||
2862 | |||
2863 | mount_info->fill_super = nfs4_fill_super; | ||
2864 | |||
2865 | export_path = data->nfs_server.export_path; | ||
2866 | data->nfs_server.export_path = "/"; | ||
2867 | root_mnt = nfs_do_root_mount(&nfs4_remote_fs_type, flags, mount_info, | ||
2868 | data->nfs_server.hostname); | ||
2869 | data->nfs_server.export_path = export_path; | ||
2870 | |||
2871 | res = nfs_follow_remote_path(root_mnt, export_path); | ||
2872 | |||
2873 | dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n", | ||
2874 | IS_ERR(res) ? PTR_ERR(res) : 0, | ||
2875 | IS_ERR(res) ? " [error]" : ""); | ||
2876 | return res; | ||
2877 | } | ||
2878 | |||
2879 | static void nfs4_kill_super(struct super_block *sb) | ||
2880 | { | ||
2881 | struct nfs_server *server = NFS_SB(sb); | ||
2882 | |||
2883 | dprintk("--> %s\n", __func__); | ||
2884 | nfs_super_return_all_delegations(sb); | ||
2885 | kill_anon_super(sb); | ||
2886 | nfs_fscache_release_super_cookie(sb); | ||
2887 | nfs_free_server(server); | ||
2888 | dprintk("<-- %s\n", __func__); | ||
2889 | } | ||
2890 | |||
2891 | /* | ||
2892 | * Clone an NFS4 server record on xdev traversal (FSID-change) | ||
2893 | */ | ||
2894 | static struct dentry * | ||
2895 | nfs4_xdev_mount(struct file_system_type *fs_type, int flags, | ||
2896 | const char *dev_name, void *raw_data) | ||
2897 | { | ||
2898 | struct nfs_mount_info mount_info = { | ||
2899 | .fill_super = nfs4_clone_super, | ||
2900 | .set_security = nfs_clone_sb_security, | ||
2901 | .cloned = raw_data, | ||
2902 | }; | ||
2903 | return nfs_xdev_mount_common(&nfs4_fs_type, flags, dev_name, &mount_info); | ||
2904 | } | ||
2905 | |||
2906 | static struct dentry * | ||
2907 | nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags, | ||
2908 | const char *dev_name, void *raw_data) | ||
2909 | { | ||
2910 | struct nfs_mount_info mount_info = { | ||
2911 | .fill_super = nfs4_fill_super, | ||
2912 | .set_security = nfs_clone_sb_security, | ||
2913 | .cloned = raw_data, | ||
2914 | }; | ||
2915 | struct nfs_server *server; | ||
2916 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | ||
2917 | |||
2918 | dprintk("--> nfs4_referral_get_sb()\n"); | ||
2919 | |||
2920 | mount_info.mntfh = nfs_alloc_fhandle(); | ||
2921 | if (mount_info.cloned == NULL || mount_info.mntfh == NULL) | ||
2922 | goto out; | ||
2923 | |||
2924 | /* create a new volume representation */ | ||
2925 | server = nfs4_create_referral_server(mount_info.cloned, mount_info.mntfh); | ||
2926 | if (IS_ERR(server)) { | ||
2927 | mntroot = ERR_CAST(server); | ||
2928 | goto out; | ||
2929 | } | ||
2930 | |||
2931 | mntroot = nfs_fs_mount_common(&nfs4_fs_type, server, flags, dev_name, &mount_info); | ||
2932 | out: | ||
2933 | nfs_free_fhandle(mount_info.mntfh); | ||
2934 | return mntroot; | ||
2935 | } | ||
2936 | |||
2937 | /* | ||
2938 | * Create an NFS4 server record on referral traversal | ||
2939 | */ | ||
2940 | static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, | ||
2941 | int flags, const char *dev_name, void *raw_data) | ||
2942 | { | ||
2943 | struct nfs_clone_mount *data = raw_data; | ||
2944 | char *export_path; | ||
2945 | struct vfsmount *root_mnt; | ||
2946 | struct dentry *res; | ||
2947 | |||
2948 | dprintk("--> nfs4_referral_mount()\n"); | ||
2949 | |||
2950 | export_path = data->mnt_path; | ||
2951 | data->mnt_path = "/"; | ||
2952 | |||
2953 | root_mnt = nfs_do_root_mount(&nfs4_remote_referral_fs_type, | ||
2954 | flags, data, data->hostname); | ||
2955 | data->mnt_path = export_path; | ||
2956 | |||
2957 | res = nfs_follow_remote_path(root_mnt, export_path); | ||
2958 | dprintk("<-- nfs4_referral_mount() = %ld%s\n", | ||
2959 | IS_ERR(res) ? PTR_ERR(res) : 0, | ||
2960 | IS_ERR(res) ? " [error]" : ""); | ||
2961 | return res; | ||
2962 | } | ||
2963 | 2686 | ||
2964 | #endif /* CONFIG_NFS_V4 */ | 2687 | #endif /* CONFIG_NFS_V4 */ |