aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c438
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
281struct 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
289static void nfs_umount_begin(struct super_block *);
290static int nfs_statfs(struct dentry *, struct kstatfs *);
291static int nfs_show_options(struct seq_file *, struct dentry *);
292static int nfs_show_devname(struct seq_file *, struct dentry *);
293static int nfs_show_path(struct seq_file *, struct dentry *);
294static int nfs_show_stats(struct seq_file *, struct dentry *);
295static struct dentry *nfs_fs_mount_common(struct file_system_type *,
296 struct nfs_server *, int, const char *, struct nfs_mount_info *);
297static struct dentry *nfs_fs_mount(struct file_system_type *,
298 int, const char *, void *);
299static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type, 281static 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);
301static void nfs_put_super(struct super_block *);
302static void nfs_kill_super(struct super_block *);
303static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
304 283
305static struct file_system_type nfs_fs_type = { 284static 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 = {
337static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); 316static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *);
338static int nfs4_validate_mount_data(void *options, 317static 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);
340static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
341 struct nfs_mount_info *mount_info);
342static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
343 int flags, const char *dev_name, void *raw_data);
344static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
345 int flags, const char *dev_name, void *raw_data);
346static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
347 int flags, const char *dev_name, void *raw_data);
348static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
349 int flags, const char *dev_name, void *raw_data);
350static void nfs4_kill_super(struct super_block *sb);
351
352static 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
360static 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
368struct 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
376static 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
384struct 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
392static 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
408static struct shrinker acl_shrinker = { 321static 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
436error_2:
437 nfs_unregister_sysctl();
438#endif
439error_1: 343error_1:
440 unregister_filesystem(&nfs_fs_type); 344 unregister_filesystem(&nfs_fs_type);
441error_0: 345error_0:
@@ -448,9 +352,6 @@ error_0:
448void __exit unregister_nfs_fs(void) 352void __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 */
477static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) 378int 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 */
760static int nfs_show_options(struct seq_file *m, struct dentry *root) 661int 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
818static int nfs_show_devname(struct seq_file *m, struct dentry *root) 719int 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
834static int nfs_show_path(struct seq_file *m, struct dentry *dentry) 735int 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 */
843static int nfs_show_stats(struct seq_file *m, struct dentry *root) 744int 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 */
936static void nfs_umount_begin(struct super_block *sb) 837void 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
2111static int 2012int
2112nfs_remount(struct super_block *sb, int *flags, char *raw_data) 2013nfs_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 */
2176static inline void nfs_initialise_sb(struct super_block *sb) 2077inline 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 */
2198static void nfs_fill_super(struct super_block *sb, 2099void 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 */
2224static void nfs_clone_super(struct super_block *sb, 2124void 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
2384static int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, 2284int 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
2390static int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, 2290int 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
2400static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, 2300struct 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
2473static struct dentry *nfs_fs_mount(struct file_system_type *fs_type, 2373struct 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 */
2514static void nfs_put_super(struct super_block *s) 2414void 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 */
2524static void nfs_kill_super(struct super_block *s) 2424void 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 */
2536static struct dentry * 2436struct dentry *
2537nfs_xdev_mount_common(struct file_system_type *fs_type, int flags, 2437nfs_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 */
2586static 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 */
2607static 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
2621static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args) 2483static 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 */
2721static struct dentry *
2722nfs4_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
2741out:
2742 return mntroot;
2743}
2744
2745static 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
2766struct nfs_referral_count {
2767 struct list_head list;
2768 const struct task_struct *task;
2769 unsigned int referral_count;
2770};
2771
2772static LIST_HEAD(nfs_referral_count_list);
2773static DEFINE_SPINLOCK(nfs_referral_count_list_lock);
2774
2775static 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
2788static 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);
2813out:
2814 return ret;
2815}
2816
2817static 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
2832static 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
2853static 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
2879static 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 */
2894static struct dentry *
2895nfs4_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
2906static struct dentry *
2907nfs4_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);
2932out:
2933 nfs_free_fhandle(mount_info.mntfh);
2934 return mntroot;
2935}
2936
2937/*
2938 * Create an NFS4 server record on referral traversal
2939 */
2940static 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 */