diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 438 |
1 files changed, 27 insertions, 411 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 8b2a2977b720..95866a8c21bb 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -278,29 +278,8 @@ static match_table_t nfs_vers_tokens = { | |||
278 | { Opt_vers_err, NULL } | 278 | { Opt_vers_err, NULL } |
279 | }; | 279 | }; |
280 | 280 | ||
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, | 281 | static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, |
300 | int flags, const char *dev_name, void *raw_data); | 282 | 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 | 283 | ||
305 | static struct file_system_type nfs_fs_type = { | 284 | static struct file_system_type nfs_fs_type = { |
306 | .owner = THIS_MODULE, | 285 | .owner = THIS_MODULE, |
@@ -337,72 +316,6 @@ static const struct super_operations nfs_sops = { | |||
337 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); | 316 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); |
338 | static int nfs4_validate_mount_data(void *options, | 317 | static int nfs4_validate_mount_data(void *options, |
339 | struct nfs_parsed_mount_data *args, const char *dev_name); | 318 | 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 | |||
360 | static struct file_system_type nfs4_remote_fs_type = { | ||
361 | .owner = THIS_MODULE, | ||
362 | .name = "nfs4", | ||
363 | .mount = nfs4_remote_mount, | ||
364 | .kill_sb = nfs4_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, | ||
374 | }; | ||
375 | |||
376 | static struct file_system_type nfs4_remote_referral_fs_type = { | ||
377 | .owner = THIS_MODULE, | ||
378 | .name = "nfs4", | ||
379 | .mount = nfs4_remote_referral_mount, | ||
380 | .kill_sb = nfs4_kill_super, | ||
381 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
382 | }; | ||
383 | |||
384 | struct file_system_type nfs4_referral_fs_type = { | ||
385 | .owner = THIS_MODULE, | ||
386 | .name = "nfs4", | ||
387 | .mount = nfs4_referral_mount, | ||
388 | .kill_sb = nfs4_kill_super, | ||
389 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
390 | }; | ||
391 | |||
392 | static const struct super_operations nfs4_sops = { | ||
393 | .alloc_inode = nfs_alloc_inode, | ||
394 | .destroy_inode = nfs_destroy_inode, | ||
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 | 319 | #endif |
407 | 320 | ||
408 | static struct shrinker acl_shrinker = { | 321 | static struct shrinker acl_shrinker = { |
@@ -424,18 +337,9 @@ int __init register_nfs_fs(void) | |||
424 | ret = nfs_register_sysctl(); | 337 | ret = nfs_register_sysctl(); |
425 | if (ret < 0) | 338 | if (ret < 0) |
426 | goto error_1; | 339 | goto error_1; |
427 | #ifdef CONFIG_NFS_V4 | ||
428 | ret = register_filesystem(&nfs4_fs_type); | ||
429 | if (ret < 0) | ||
430 | goto error_2; | ||
431 | #endif | ||
432 | register_shrinker(&acl_shrinker); | 340 | register_shrinker(&acl_shrinker); |
433 | return 0; | 341 | return 0; |
434 | 342 | ||
435 | #ifdef CONFIG_NFS_V4 | ||
436 | error_2: | ||
437 | nfs_unregister_sysctl(); | ||
438 | #endif | ||
439 | error_1: | 343 | error_1: |
440 | unregister_filesystem(&nfs_fs_type); | 344 | unregister_filesystem(&nfs_fs_type); |
441 | error_0: | 345 | error_0: |
@@ -448,9 +352,6 @@ error_0: | |||
448 | void __exit unregister_nfs_fs(void) | 352 | void __exit unregister_nfs_fs(void) |
449 | { | 353 | { |
450 | unregister_shrinker(&acl_shrinker); | 354 | unregister_shrinker(&acl_shrinker); |
451 | #ifdef CONFIG_NFS_V4 | ||
452 | unregister_filesystem(&nfs4_fs_type); | ||
453 | #endif | ||
454 | nfs_unregister_sysctl(); | 355 | nfs_unregister_sysctl(); |
455 | unregister_filesystem(&nfs_fs_type); | 356 | unregister_filesystem(&nfs_fs_type); |
456 | } | 357 | } |
@@ -474,7 +375,7 @@ void nfs_sb_deactive(struct super_block *sb) | |||
474 | /* | 375 | /* |
475 | * Deliver file system statistics to userspace | 376 | * Deliver file system statistics to userspace |
476 | */ | 377 | */ |
477 | static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 378 | int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
478 | { | 379 | { |
479 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 380 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
480 | unsigned char blockbits; | 381 | unsigned char blockbits; |
@@ -757,7 +658,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
757 | /* | 658 | /* |
758 | * Describe the mount options on this VFS mountpoint | 659 | * Describe the mount options on this VFS mountpoint |
759 | */ | 660 | */ |
760 | static int nfs_show_options(struct seq_file *m, struct dentry *root) | 661 | int nfs_show_options(struct seq_file *m, struct dentry *root) |
761 | { | 662 | { |
762 | struct nfs_server *nfss = NFS_SB(root->d_sb); | 663 | struct nfs_server *nfss = NFS_SB(root->d_sb); |
763 | 664 | ||
@@ -815,7 +716,7 @@ static void show_implementation_id(struct seq_file *m, struct nfs_server *nfss) | |||
815 | } | 716 | } |
816 | #endif | 717 | #endif |
817 | 718 | ||
818 | static int nfs_show_devname(struct seq_file *m, struct dentry *root) | 719 | int nfs_show_devname(struct seq_file *m, struct dentry *root) |
819 | { | 720 | { |
820 | char *page = (char *) __get_free_page(GFP_KERNEL); | 721 | char *page = (char *) __get_free_page(GFP_KERNEL); |
821 | char *devname, *dummy; | 722 | char *devname, *dummy; |
@@ -831,7 +732,7 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root) | |||
831 | return err; | 732 | return err; |
832 | } | 733 | } |
833 | 734 | ||
834 | static int nfs_show_path(struct seq_file *m, struct dentry *dentry) | 735 | int nfs_show_path(struct seq_file *m, struct dentry *dentry) |
835 | { | 736 | { |
836 | seq_puts(m, "/"); | 737 | seq_puts(m, "/"); |
837 | return 0; | 738 | return 0; |
@@ -840,7 +741,7 @@ static int nfs_show_path(struct seq_file *m, struct dentry *dentry) | |||
840 | /* | 741 | /* |
841 | * Present statistical information for this VFS mountpoint | 742 | * Present statistical information for this VFS mountpoint |
842 | */ | 743 | */ |
843 | static int nfs_show_stats(struct seq_file *m, struct dentry *root) | 744 | int nfs_show_stats(struct seq_file *m, struct dentry *root) |
844 | { | 745 | { |
845 | int i, cpu; | 746 | int i, cpu; |
846 | struct nfs_server *nfss = NFS_SB(root->d_sb); | 747 | struct nfs_server *nfss = NFS_SB(root->d_sb); |
@@ -933,7 +834,7 @@ static int nfs_show_stats(struct seq_file *m, struct dentry *root) | |||
933 | * Begin unmount by attempting to remove all automounted mountpoints we added | 834 | * Begin unmount by attempting to remove all automounted mountpoints we added |
934 | * in response to xdev traversals and referrals | 835 | * in response to xdev traversals and referrals |
935 | */ | 836 | */ |
936 | static void nfs_umount_begin(struct super_block *sb) | 837 | void nfs_umount_begin(struct super_block *sb) |
937 | { | 838 | { |
938 | struct nfs_server *server; | 839 | struct nfs_server *server; |
939 | struct rpc_clnt *rpc; | 840 | struct rpc_clnt *rpc; |
@@ -2108,7 +2009,7 @@ nfs_compare_remount_data(struct nfs_server *nfss, | |||
2108 | return 0; | 2009 | return 0; |
2109 | } | 2010 | } |
2110 | 2011 | ||
2111 | static int | 2012 | int |
2112 | nfs_remount(struct super_block *sb, int *flags, char *raw_data) | 2013 | nfs_remount(struct super_block *sb, int *flags, char *raw_data) |
2113 | { | 2014 | { |
2114 | int error; | 2015 | int error; |
@@ -2173,7 +2074,7 @@ out: | |||
2173 | /* | 2074 | /* |
2174 | * Initialise the common bits of the superblock | 2075 | * Initialise the common bits of the superblock |
2175 | */ | 2076 | */ |
2176 | static inline void nfs_initialise_sb(struct super_block *sb) | 2077 | inline void nfs_initialise_sb(struct super_block *sb) |
2177 | { | 2078 | { |
2178 | struct nfs_server *server = NFS_SB(sb); | 2079 | struct nfs_server *server = NFS_SB(sb); |
2179 | 2080 | ||
@@ -2195,8 +2096,7 @@ static inline void nfs_initialise_sb(struct super_block *sb) | |||
2195 | /* | 2096 | /* |
2196 | * Finish setting up an NFS2/3 superblock | 2097 | * Finish setting up an NFS2/3 superblock |
2197 | */ | 2098 | */ |
2198 | static void nfs_fill_super(struct super_block *sb, | 2099 | void nfs_fill_super(struct super_block *sb, struct nfs_mount_info *mount_info) |
2199 | struct nfs_mount_info *mount_info) | ||
2200 | { | 2100 | { |
2201 | struct nfs_parsed_mount_data *data = mount_info->parsed; | 2101 | struct nfs_parsed_mount_data *data = mount_info->parsed; |
2202 | struct nfs_server *server = NFS_SB(sb); | 2102 | struct nfs_server *server = NFS_SB(sb); |
@@ -2219,10 +2119,9 @@ static void nfs_fill_super(struct super_block *sb, | |||
2219 | } | 2119 | } |
2220 | 2120 | ||
2221 | /* | 2121 | /* |
2222 | * Finish setting up a cloned NFS2/3 superblock | 2122 | * Finish setting up a cloned NFS2/3/4 superblock |
2223 | */ | 2123 | */ |
2224 | static void nfs_clone_super(struct super_block *sb, | 2124 | void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info) |
2225 | struct nfs_mount_info *mount_info) | ||
2226 | { | 2125 | { |
2227 | const struct super_block *old_sb = mount_info->cloned->sb; | 2126 | const struct super_block *old_sb = mount_info->cloned->sb; |
2228 | struct nfs_server *server = NFS_SB(sb); | 2127 | struct nfs_server *server = NFS_SB(sb); |
@@ -2230,16 +2129,17 @@ static void nfs_clone_super(struct super_block *sb, | |||
2230 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; | 2129 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; |
2231 | sb->s_blocksize = old_sb->s_blocksize; | 2130 | sb->s_blocksize = old_sb->s_blocksize; |
2232 | sb->s_maxbytes = old_sb->s_maxbytes; | 2131 | sb->s_maxbytes = old_sb->s_maxbytes; |
2132 | sb->s_xattr = old_sb->s_xattr; | ||
2133 | sb->s_op = old_sb->s_op; | ||
2134 | sb->s_time_gran = 1; | ||
2233 | 2135 | ||
2234 | if (server->nfs_client->rpc_ops->version == 3) { | 2136 | if (server->nfs_client->rpc_ops->version != 2) { |
2235 | /* The VFS shouldn't apply the umask to mode bits. We will do | 2137 | /* The VFS shouldn't apply the umask to mode bits. We will do |
2236 | * so ourselves when necessary. | 2138 | * so ourselves when necessary. |
2237 | */ | 2139 | */ |
2238 | sb->s_flags |= MS_POSIXACL; | 2140 | sb->s_flags |= MS_POSIXACL; |
2239 | sb->s_time_gran = 1; | ||
2240 | } | 2141 | } |
2241 | 2142 | ||
2242 | sb->s_op = old_sb->s_op; | ||
2243 | nfs_initialise_sb(sb); | 2143 | nfs_initialise_sb(sb); |
2244 | } | 2144 | } |
2245 | 2145 | ||
@@ -2381,14 +2281,14 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2381 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); | 2281 | return bdi_register_dev(&server->backing_dev_info, server->s_dev); |
2382 | } | 2282 | } |
2383 | 2283 | ||
2384 | static int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | 2284 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, |
2385 | struct nfs_mount_info *mount_info) | 2285 | struct nfs_mount_info *mount_info) |
2386 | { | 2286 | { |
2387 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); | 2287 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts); |
2388 | } | 2288 | } |
2389 | 2289 | ||
2390 | static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | 2290 | int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, |
2391 | struct nfs_mount_info *mount_info) | 2291 | struct nfs_mount_info *mount_info) |
2392 | { | 2292 | { |
2393 | /* clone any lsm security options from the parent to the new sb */ | 2293 | /* clone any lsm security options from the parent to the new sb */ |
2394 | security_sb_clone_mnt_opts(mount_info->cloned->sb, s); | 2294 | security_sb_clone_mnt_opts(mount_info->cloned->sb, s); |
@@ -2397,10 +2297,10 @@ static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | |||
2397 | return 0; | 2297 | return 0; |
2398 | } | 2298 | } |
2399 | 2299 | ||
2400 | static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, | 2300 | struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, |
2401 | struct nfs_server *server, | 2301 | struct nfs_server *server, |
2402 | int flags, const char *dev_name, | 2302 | int flags, const char *dev_name, |
2403 | struct nfs_mount_info *mount_info) | 2303 | struct nfs_mount_info *mount_info) |
2404 | { | 2304 | { |
2405 | struct super_block *s; | 2305 | struct super_block *s; |
2406 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | 2306 | struct dentry *mntroot = ERR_PTR(-ENOMEM); |
@@ -2470,7 +2370,7 @@ error_splat_bdi: | |||
2470 | goto out; | 2370 | goto out; |
2471 | } | 2371 | } |
2472 | 2372 | ||
2473 | static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, | 2373 | struct dentry *nfs_fs_mount(struct file_system_type *fs_type, |
2474 | int flags, const char *dev_name, void *raw_data) | 2374 | int flags, const char *dev_name, void *raw_data) |
2475 | { | 2375 | { |
2476 | struct nfs_mount_info mount_info = { | 2376 | struct nfs_mount_info mount_info = { |
@@ -2511,7 +2411,7 @@ out: | |||
2511 | * Ensure that we unregister the bdi before kill_anon_super | 2411 | * Ensure that we unregister the bdi before kill_anon_super |
2512 | * releases the device name | 2412 | * releases the device name |
2513 | */ | 2413 | */ |
2514 | static void nfs_put_super(struct super_block *s) | 2414 | void nfs_put_super(struct super_block *s) |
2515 | { | 2415 | { |
2516 | struct nfs_server *server = NFS_SB(s); | 2416 | struct nfs_server *server = NFS_SB(s); |
2517 | 2417 | ||
@@ -2521,7 +2421,7 @@ static void nfs_put_super(struct super_block *s) | |||
2521 | /* | 2421 | /* |
2522 | * Destroy an NFS2/3 superblock | 2422 | * Destroy an NFS2/3 superblock |
2523 | */ | 2423 | */ |
2524 | static void nfs_kill_super(struct super_block *s) | 2424 | void nfs_kill_super(struct super_block *s) |
2525 | { | 2425 | { |
2526 | struct nfs_server *server = NFS_SB(s); | 2426 | struct nfs_server *server = NFS_SB(s); |
2527 | 2427 | ||
@@ -2533,7 +2433,7 @@ static void nfs_kill_super(struct super_block *s) | |||
2533 | /* | 2433 | /* |
2534 | * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) | 2434 | * Clone an NFS2/3/4 server record on xdev traversal (FSID-change) |
2535 | */ | 2435 | */ |
2536 | static struct dentry * | 2436 | struct dentry * |
2537 | nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, | 2437 | nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, |
2538 | const char *dev_name, struct nfs_mount_info *mount_info) | 2438 | const char *dev_name, struct nfs_mount_info *mount_info) |
2539 | { | 2439 | { |
@@ -2580,44 +2480,6 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags, | |||
2580 | 2480 | ||
2581 | #ifdef CONFIG_NFS_V4 | 2481 | #ifdef CONFIG_NFS_V4 |
2582 | 2482 | ||
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 | |||
2621 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) | 2483 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) |
2622 | { | 2484 | { |
2623 | args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3| | 2485 | args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3| |
@@ -2715,250 +2577,4 @@ out_no_address: | |||
2715 | return -EINVAL; | 2577 | return -EINVAL; |
2716 | } | 2578 | } |
2717 | 2579 | ||
2718 | /* | ||
2719 | * Get the superblock for the NFS4 root partition | ||
2720 | */ | ||
2721 | static struct dentry * | ||
2722 | nfs4_remote_mount(struct file_system_type *fs_type, int flags, | ||
2723 | const char *dev_name, void *info) | ||
2724 | { | ||
2725 | struct nfs_mount_info *mount_info = info; | ||
2726 | struct nfs_server *server; | ||
2727 | struct dentry *mntroot = ERR_PTR(-ENOMEM); | ||
2728 | |||
2729 | mount_info->fill_super = nfs4_fill_super; | ||
2730 | mount_info->set_security = nfs_set_sb_security; | ||
2731 | |||
2732 | /* Get a volume representation */ | ||
2733 | server = nfs4_create_server(mount_info->parsed, mount_info->mntfh); | ||
2734 | if (IS_ERR(server)) { | ||
2735 | mntroot = ERR_CAST(server); | ||
2736 | goto out; | ||
2737 | } | ||
2738 | |||
2739 | mntroot = nfs_fs_mount_common(fs_type, server, flags, dev_name, mount_info); | ||
2740 | |||
2741 | out: | ||
2742 | return mntroot; | ||
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 | |||
2752 | len = strlen(hostname) + 5; | ||
2753 | root_devname = kmalloc(len, GFP_KERNEL); | ||
2754 | if (root_devname == NULL) | ||
2755 | return ERR_PTR(-ENOMEM); | ||
2756 | /* Does hostname needs to be enclosed in brackets? */ | ||
2757 | if (strchr(hostname, ':')) | ||
2758 | snprintf(root_devname, len, "[%s]:/", hostname); | ||
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 | } | ||
2765 | |||
2766 | struct nfs_referral_count { | ||
2767 | struct list_head list; | ||
2768 | const struct task_struct *task; | ||
2769 | unsigned int referral_count; | ||
2770 | }; | ||
2771 | |||
2772 | static LIST_HEAD(nfs_referral_count_list); | ||
2773 | static DEFINE_SPINLOCK(nfs_referral_count_list_lock); | ||
2774 | |||
2775 | static struct nfs_referral_count *nfs_find_referral_count(void) | ||
2776 | { | ||
2777 | struct nfs_referral_count *p; | ||
2778 | |||
2779 | list_for_each_entry(p, &nfs_referral_count_list, list) { | ||
2780 | if (p->task == current) | ||
2781 | return p; | ||
2782 | } | ||
2783 | return NULL; | ||
2784 | } | ||
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 | |||
2964 | #endif /* CONFIG_NFS_V4 */ | 2580 | #endif /* CONFIG_NFS_V4 */ |