Merge branch 'mnt_devname' of git://git.kernel.org/pub/scm/linux/kernel/git/viro...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2011 02:09:57 +0000 (19:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2011 02:09:57 +0000 (19:09 -0700)
* 'mnt_devname' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  vfs: bury ->get_sb()
  nfs: switch NFS from ->get_sb() to ->mount()
  nfs: stop mangling ->mnt_devname on NFS
  vfs: new superblock methods to override /proc/*/mount{s,info}
  nfs: nfs_do_{ref,sub}mount() superblock argument is redundant
  nfs: make nfs_path() work without vfsmount
  nfs: store devname at disconnected NFS roots
  nfs: propagate devname to nfs{,4}_get_root()

13 files changed:
Documentation/filesystems/Locking
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
fs/namespace.c
fs/nfs/dir.c
fs/nfs/getroot.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs4namespace.c
fs/nfs/super.c
fs/nfs/unlink.c
fs/super.c
include/linux/fs.h

index 4471a41..2e994ef 100644 (file)
@@ -166,13 +166,11 @@ prototypes:
        void (*kill_sb) (struct super_block *);
 locking rules:
                may block
-get_sb         yes
 mount          yes
 kill_sb                yes
 
-->get_sb() returns error or 0 with locked superblock attached to the vfsmount
-(exclusive on ->s_umount).
-->mount() returns ERR_PTR or the root dentry.
+->mount() returns ERR_PTR or the root dentry; its superblock should be locked
+on return.
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
index dfbcd1b..0c986c9 100644 (file)
@@ -394,3 +394,10 @@ file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode.
 Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
 so the i_size should not change when hole punching, even when puching the end of
 a file off.
+
+--
+[mandatory]
+       ->get_sb() is gone.  Switch to use of ->mount().  Typically it's just
+a matter of switching from calling get_sb_... to mount_... and changing the
+function type.  If you were doing it manually, just switch from setting ->mnt_root
+to some pointer to returning that pointer.  On errors return ERR_PTR(...).
index 94cf97b..ef0714a 100644 (file)
@@ -95,10 +95,11 @@ functions:
    extern int unregister_filesystem(struct file_system_type *);
 
 The passed struct file_system_type describes your filesystem. When a
-request is made to mount a device onto a directory in your filespace,
-the VFS will call the appropriate get_sb() method for the specific
-filesystem. The dentry for the mount point will then be updated to
-point to the root inode for the new filesystem.
+request is made to mount a filesystem onto a directory in your namespace,
+the VFS will call the appropriate mount() method for the specific
+filesystem.  New vfsmount refering to the tree returned by ->mount()
+will be attached to the mountpoint, so that when pathname resolution
+reaches the mountpoint it will jump into the root of that vfsmount.
 
 You can see all filesystems that are registered to the kernel in the
 file /proc/filesystems.
@@ -107,14 +108,14 @@ file /proc/filesystems.
 struct file_system_type
 -----------------------
 
-This describes the filesystem. As of kernel 2.6.22, the following
+This describes the filesystem. As of kernel 2.6.39, the following
 members are defined:
 
 struct file_system_type {
        const char *name;
        int fs_flags;
-        int (*get_sb) (struct file_system_type *, int,
-                       const char *, void *, struct vfsmount *);
+        struct dentry (*mount) (struct file_system_type *, int,
+                       const char *, void *);
         void (*kill_sb) (struct super_block *);
         struct module *owner;
         struct file_system_type * next;
@@ -128,11 +129,11 @@ struct file_system_type {
 
   fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
 
-  get_sb: the method to call when a new instance of this
+  mount: the method to call when a new instance of this
        filesystem should be mounted
 
   kill_sb: the method to call when an instance of this filesystem
-       should be unmounted
+       should be shut down
 
   owner: for internal VFS use: you should initialize this to THIS_MODULE in
        most cases.
@@ -141,7 +142,7 @@ struct file_system_type {
 
   s_lock_key, s_umount_key: lockdep-specific
 
-The get_sb() method has the following arguments:
+The mount() method has the following arguments:
 
   struct file_system_type *fs_type: describes the filesystem, partly initialized
        by the specific filesystem code
@@ -153,32 +154,39 @@ The get_sb() method has the following arguments:
   void *data: arbitrary mount options, usually comes as an ASCII
        string (see "Mount Options" section)
 
-  struct vfsmount *mnt: a vfs-internal representation of a mount point
+The mount() method must return the root dentry of the tree requested by
+caller.  An active reference to its superblock must be grabbed and the
+superblock must be locked.  On failure it should return ERR_PTR(error).
 
-The get_sb() method must determine if the block device specified
-in the dev_name and fs_type contains a filesystem of the type the method
-supports. If it succeeds in opening the named block device, it initializes a
-struct super_block descriptor for the filesystem contained by the block device.
-On failure it returns an error.
+The arguments match those of mount(2) and their interpretation
+depends on filesystem type.  E.g. for block filesystems, dev_name is
+interpreted as block device name, that device is opened and if it
+contains a suitable filesystem image the method creates and initializes
+struct super_block accordingly, returning its root dentry to caller.
+
+->mount() may choose to return a subtree of existing filesystem - it
+doesn't have to create a new one.  The main result from the caller's
+point of view is a reference to dentry at the root of (sub)tree to
+be attached; creation of new superblock is a common side effect.
 
 The most interesting member of the superblock structure that the
-get_sb() method fills in is the "s_op" field. This is a pointer to
+mount() method fills in is the "s_op" field. This is a pointer to
 a "struct super_operations" which describes the next level of the
 filesystem implementation.
 
-Usually, a filesystem uses one of the generic get_sb() implementations
-and provides a fill_super() method instead. The generic methods are:
+Usually, a filesystem uses one of the generic mount() implementations
+and provides a fill_super() callback instead. The generic variants are:
 
-  get_sb_bdev: mount a filesystem residing on a block device
+  mount_bdev: mount a filesystem residing on a block device
 
-  get_sb_nodev: mount a filesystem that is not backed by a device
+  mount_nodev: mount a filesystem that is not backed by a device
 
-  get_sb_single: mount a filesystem which shares the instance between
+  mount_single: mount a filesystem which shares the instance between
        all mounts
 
-A fill_super() method implementation has the following arguments:
+A fill_super() callback implementation has the following arguments:
 
-  struct super_block *sb: the superblock structure. The method fill_super()
+  struct super_block *sb: the superblock structure. The callback
        must initialize this properly.
 
   void *data: arbitrary mount options, usually comes as an ASCII
index e96e037..d751348 100644 (file)
@@ -978,7 +978,13 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        int err = 0;
        struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
 
-       mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+       if (mnt->mnt_sb->s_op->show_devname) {
+               err = mnt->mnt_sb->s_op->show_devname(m, mnt);
+               if (err)
+                       goto out;
+       } else {
+               mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+       }
        seq_putc(m, ' ');
        seq_path(m, &mnt_path, " \t\n\\");
        seq_putc(m, ' ');
@@ -1025,7 +1031,12 @@ static int show_mountinfo(struct seq_file *m, void *v)
 
        seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id,
                   MAJOR(sb->s_dev), MINOR(sb->s_dev));
-       seq_dentry(m, mnt->mnt_root, " \t\n\\");
+       if (sb->s_op->show_path)
+               err = sb->s_op->show_path(m, mnt);
+       else
+               seq_dentry(m, mnt->mnt_root, " \t\n\\");
+       if (err)
+               goto out;
        seq_putc(m, ' ');
        seq_path_root(m, &mnt_path, &root, " \t\n\\");
        if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) {
@@ -1060,7 +1071,12 @@ static int show_mountinfo(struct seq_file *m, void *v)
        seq_puts(m, " - ");
        show_type(m, sb);
        seq_putc(m, ' ');
-       mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+       if (sb->s_op->show_devname)
+               err = sb->s_op->show_devname(m, mnt);
+       else
+               mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+       if (err)
+               goto out;
        seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
        err = show_sb_opts(m, sb);
        if (err)
@@ -1086,11 +1102,15 @@ static int show_vfsstat(struct seq_file *m, void *v)
        int err = 0;
 
        /* device */
-       if (mnt->mnt_devname) {
-               seq_puts(m, "device ");
-               mangle(m, mnt->mnt_devname);
-       } else
-               seq_puts(m, "no device");
+       if (mnt->mnt_sb->s_op->show_devname) {
+               err = mnt->mnt_sb->s_op->show_devname(m, mnt);
+       } else {
+               if (mnt->mnt_devname) {
+                       seq_puts(m, "device ");
+                       mangle(m, mnt->mnt_devname);
+               } else
+                       seq_puts(m, "no device");
+       }
 
        /* mount point */
        seq_puts(m, " mounted on ");
@@ -1104,7 +1124,8 @@ static int show_vfsstat(struct seq_file *m, void *v)
        /* optional statistics */
        if (mnt->mnt_sb->s_op->show_stats) {
                seq_putc(m, ' ');
-               err = mnt->mnt_sb->s_op->show_stats(m, mnt);
+               if (!err)
+                       err = mnt->mnt_sb->s_op->show_stats(m, mnt);
        }
 
        seq_putc(m, '\n');
index 2c3eb33..abdf38d 100644 (file)
@@ -1169,11 +1169,23 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
        iput(inode);
 }
 
+static void nfs_d_release(struct dentry *dentry)
+{
+       /* free cached devname value, if it survived that far */
+       if (unlikely(dentry->d_fsdata)) {
+               if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
+                       WARN_ON(1);
+               else
+                       kfree(dentry->d_fsdata);
+       }
+}
+
 const struct dentry_operations nfs_dentry_operations = {
        .d_revalidate   = nfs_lookup_revalidate,
        .d_delete       = nfs_dentry_delete,
        .d_iput         = nfs_dentry_iput,
        .d_automount    = nfs_d_automount,
+       .d_release      = nfs_d_release,
 };
 
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
@@ -1248,6 +1260,7 @@ const struct dentry_operations nfs4_dentry_operations = {
        .d_delete       = nfs_dentry_delete,
        .d_iput         = nfs_dentry_iput,
        .d_automount    = nfs_d_automount,
+       .d_release      = nfs_d_release,
 };
 
 /*
index b5ffe8f..1084792 100644 (file)
@@ -75,18 +75,25 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
 /*
  * get an NFS2/NFS3 root dentry from the root filehandle
  */
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+                           const char *devname)
 {
        struct nfs_server *server = NFS_SB(sb);
        struct nfs_fsinfo fsinfo;
        struct dentry *ret;
        struct inode *inode;
+       void *name = kstrdup(devname, GFP_KERNEL);
        int error;
 
+       if (!name)
+               return ERR_PTR(-ENOMEM);
+
        /* get the actual root for this mount */
        fsinfo.fattr = nfs_alloc_fattr();
-       if (fsinfo.fattr == NULL)
+       if (fsinfo.fattr == NULL) {
+               kfree(name);
                return ERR_PTR(-ENOMEM);
+       }
 
        error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
        if (error < 0) {
@@ -119,7 +126,15 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
        }
 
        security_d_instantiate(ret, inode);
+       spin_lock(&ret->d_lock);
+       if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+               ret->d_fsdata = name;
+               name = NULL;
+       }
+       spin_unlock(&ret->d_lock);
 out:
+       if (name)
+               kfree(name);
        nfs_free_fattr(fsinfo.fattr);
        return ret;
 }
@@ -169,27 +184,35 @@ out:
 /*
  * get an NFS4 root dentry from the root filehandle
  */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+                            const char *devname)
 {
        struct nfs_server *server = NFS_SB(sb);
        struct nfs_fattr *fattr = NULL;
        struct dentry *ret;
        struct inode *inode;
+       void *name = kstrdup(devname, GFP_KERNEL);
        int error;
 
        dprintk("--> nfs4_get_root()\n");
 
+       if (!name)
+               return ERR_PTR(-ENOMEM);
+
        /* get the info about the server and filesystem */
        error = nfs4_server_capabilities(server, mntfh);
        if (error < 0) {
                dprintk("nfs_get_root: getcaps error = %d\n",
                        -error);
+               kfree(name);
                return ERR_PTR(error);
        }
 
        fattr = nfs_alloc_fattr();
-       if (fattr == NULL)
-               return ERR_PTR(-ENOMEM);;
+       if (fattr == NULL) {
+               kfree(name);
+               return ERR_PTR(-ENOMEM);
+       }
 
        /* get the actual root for this mount */
        error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
@@ -223,8 +246,15 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
        }
 
        security_d_instantiate(ret, inode);
-
+       spin_lock(&ret->d_lock);
+       if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+               ret->d_fsdata = name;
+               name = NULL;
+       }
+       spin_unlock(&ret->d_lock);
 out:
+       if (name)
+               kfree(name);
        nfs_free_fattr(fattr);
        dprintk("<-- nfs4_get_root()\n");
        return ret;
index cf9fdbd..e94ad22 100644 (file)
@@ -163,10 +163,10 @@ static inline void nfs_fs_proc_exit(void)
 
 /* nfs4namespace.c */
 #ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
+extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
 #else
 static inline
-struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct dentry *dentry)
 {
        return ERR_PTR(-ENOENT);
 }
@@ -247,16 +247,16 @@ extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
 
 /* namespace.c */
-extern char *nfs_path(const char *base,
-                     const struct dentry *droot,
-                     const struct dentry *dentry,
+extern char *nfs_path(char **p, struct dentry *dentry,
                      char *buffer, ssize_t buflen);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 
 /* getroot.c */
-extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
+                                  const char *);
 #ifdef CONFIG_NFS_V4
-extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
+                                   const char *);
 
 extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh);
 #endif
@@ -288,12 +288,11 @@ extern int _nfs4_call_sync_session(struct nfs_server *server,
 /*
  * Determine the device name as a string
  */
-static inline char *nfs_devname(const struct vfsmount *mnt_parent,
-                               const struct dentry *dentry,
+static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
-       return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root,
-                       dentry, buffer, buflen);
+       char *dummy;
+       return nfs_path(&dummy, dentry, buffer, buflen);
 }
 
 /*
index f32b860..c0b8344 100644 (file)
@@ -25,33 +25,30 @@ static LIST_HEAD(nfs_automount_list);
 static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
-static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-                                       const struct dentry *dentry,
+static struct vfsmount *nfs_do_submount(struct dentry *dentry,
                                        struct nfs_fh *fh,
                                        struct nfs_fattr *fattr);
 
 /*
  * nfs_path - reconstruct the path given an arbitrary dentry
- * @base - arbitrary string to prepend to the path
- * @droot - pointer to root dentry for mountpoint
+ * @base - used to return pointer to the end of devname part of path
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
  *
- * Helper function for constructing the path from the
- * root dentry to an arbitrary hashed dentry.
+ * Helper function for constructing the server pathname
+ * by arbitrary hashed dentry.
  *
  * This is mainly for use in figuring out the path on the
- * server side when automounting on top of an existing partition.
+ * server side when automounting on top of an existing partition
+ * and in generating /proc/mounts and friends.
  */
-char *nfs_path(const char *base,
-              const struct dentry *droot,
-              const struct dentry *dentry,
-              char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *end;
        int namelen;
        unsigned seq;
+       const char *base;
 
 rename_retry:
        end = buffer+buflen;
@@ -60,7 +57,10 @@ rename_retry:
 
        seq = read_seqbegin(&rename_lock);
        rcu_read_lock();
-       while (!IS_ROOT(dentry) && dentry != droot) {
+       while (1) {
+               spin_lock(&dentry->d_lock);
+               if (IS_ROOT(dentry))
+                       break;
                namelen = dentry->d_name.len;
                buflen -= namelen + 1;
                if (buflen < 0)
@@ -68,27 +68,47 @@ rename_retry:
                end -= namelen;
                memcpy(end, dentry->d_name.name, namelen);
                *--end = '/';
+               spin_unlock(&dentry->d_lock);
                dentry = dentry->d_parent;
        }
-       rcu_read_unlock();
-       if (read_seqretry(&rename_lock, seq))
+       if (read_seqretry(&rename_lock, seq)) {
+               spin_unlock(&dentry->d_lock);
+               rcu_read_unlock();
                goto rename_retry;
+       }
        if (*end != '/') {
-               if (--buflen < 0)
+               if (--buflen < 0) {
+                       spin_unlock(&dentry->d_lock);
+                       rcu_read_unlock();
                        goto Elong;
+               }
                *--end = '/';
        }
+       *p = end;
+       base = dentry->d_fsdata;
+       if (!base) {
+               spin_unlock(&dentry->d_lock);
+               rcu_read_unlock();
+               WARN_ON(1);
+               return end;
+       }
        namelen = strlen(base);
        /* Strip off excess slashes in base string */
        while (namelen > 0 && base[namelen - 1] == '/')
                namelen--;
        buflen -= namelen;
-       if (buflen < 0)
+       if (buflen < 0) {
+               spin_lock(&dentry->d_lock);
+               rcu_read_unlock();
                goto Elong;
+       }
        end -= namelen;
        memcpy(end, base, namelen);
+       spin_unlock(&dentry->d_lock);
+       rcu_read_unlock();
        return end;
 Elong_unlock:
+       spin_lock(&dentry->d_lock);
        rcu_read_unlock();
        if (read_seqretry(&rename_lock, seq))
                goto rename_retry;
@@ -143,9 +163,9 @@ struct vfsmount *nfs_d_automount(struct path *path)
        }
 
        if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
-               mnt = nfs_do_refmount(path->mnt, path->dentry);
+               mnt = nfs_do_refmount(path->dentry);
        else
-               mnt = nfs_do_submount(path->mnt, path->dentry, fh, fattr);
+               mnt = nfs_do_submount(path->dentry, fh, fattr);
        if (IS_ERR(mnt))
                goto out;
 
@@ -209,19 +229,17 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
 
 /**
  * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
- * @mnt_parent - mountpoint of parent directory
  * @dentry - parent directory
  * @fh - filehandle for new root dentry
  * @fattr - attributes for new root inode
  *
  */
-static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-                                       const struct dentry *dentry,
+static struct vfsmount *nfs_do_submount(struct dentry *dentry,
                                        struct nfs_fh *fh,
                                        struct nfs_fattr *fattr)
 {
        struct nfs_clone_mount mountdata = {
-               .sb = mnt_parent->mnt_sb,
+               .sb = dentry->d_sb,
                .dentry = dentry,
                .fh = fh,
                .fattr = fattr,
@@ -237,11 +255,11 @@ static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
                        dentry->d_name.name);
        if (page == NULL)
                goto out;
-       devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+       devname = nfs_devname(dentry, page, PAGE_SIZE);
        mnt = (struct vfsmount *)devname;
        if (IS_ERR(devname))
                goto free_page;
-       mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
+       mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
 free_page:
        free_page((unsigned long)page);
 out:
index 3c2a172..bb80c49 100644 (file)
@@ -54,33 +54,29 @@ Elong:
 /*
  * Determine the mount path as a string
  */
-static char *nfs4_path(const struct vfsmount *mnt_parent,
-                      const struct dentry *dentry,
-                      char *buffer, ssize_t buflen)
+static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
-       const char *srvpath;
-
-       srvpath = strchr(mnt_parent->mnt_devname, ':');
-       if (srvpath)
-               srvpath++;
-       else
-               srvpath = mnt_parent->mnt_devname;
-
-       return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen);
+       char *limit;
+       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       if (!IS_ERR(path)) {
+               char *colon = strchr(path, ':');
+               if (colon && colon < limit)
+                       path = colon + 1;
+       }
+       return path;
 }
 
 /*
  * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
  * believe to be the server path to this dentry
  */
-static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
-                               const struct dentry *dentry,
+static int nfs4_validate_fspath(struct dentry *dentry,
                                const struct nfs4_fs_locations *locations,
                                char *page, char *page2)
 {
        const char *path, *fs_path;
 
-       path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE);
+       path = nfs4_path(dentry, page, PAGE_SIZE);
        if (IS_ERR(path))
                return PTR_ERR(path);
 
@@ -165,20 +161,18 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
 
 /**
  * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
- * @mnt_parent - mountpoint of parent directory
  * @dentry - parent directory
  * @locations - array of NFSv4 server location information
  *
  */
-static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
-                                           const struct dentry *dentry,
+static struct vfsmount *nfs_follow_referral(struct dentry *dentry,
                                            const struct nfs4_fs_locations *locations)
 {
        struct vfsmount *mnt = ERR_PTR(-ENOENT);
        struct nfs_clone_mount mountdata = {
-               .sb = mnt_parent->mnt_sb,
+               .sb = dentry->d_sb,
                .dentry = dentry,
-               .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
+               .authflavor = NFS_SB(dentry->d_sb)->client->cl_auth->au_flavor,
        };
        char *page = NULL, *page2 = NULL;
        int loc, error;
@@ -198,7 +192,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
                goto out;
 
        /* Ensure fs path is a prefix of current dentry path */
-       error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2);
+       error = nfs4_validate_fspath(dentry, locations, page, page2);
        if (error < 0) {
                mnt = ERR_PTR(error);
                goto out;
@@ -225,11 +219,10 @@ out:
 
 /*
  * nfs_do_refmount - handle crossing a referral on server
- * @mnt_parent - mountpoint of referral
  * @dentry - dentry of referral
  *
  */
-struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct dentry *dentry)
 {
        struct vfsmount *mnt = ERR_PTR(-ENOMEM);
        struct dentry *parent;
@@ -262,7 +255,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
            fs_locations->fs_path.ncomponents <= 0)
                goto out_free;
 
-       mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations);
+       mnt = nfs_follow_referral(dentry, fs_locations);
 out_free:
        __free_page(page);
        kfree(fs_locations);
index b68c860..d328658 100644 (file)
@@ -263,8 +263,11 @@ static match_table_t nfs_local_lock_tokens = {
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static int  nfs_show_devname(struct seq_file *, struct vfsmount *);
+static int  nfs_show_path(struct seq_file *, struct vfsmount *);
 static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
-static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
+static struct dentry *nfs_fs_mount(struct file_system_type *,
+               int, const char *, void *);
 static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *raw_data);
 static void nfs_put_super(struct super_block *);
@@ -274,7 +277,7 @@ static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 static struct file_system_type nfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "nfs",
-       .get_sb         = nfs_get_sb,
+       .mount          = nfs_fs_mount,
        .kill_sb        = nfs_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -296,6 +299,8 @@ static const struct super_operations nfs_sops = {
        .evict_inode    = nfs_evict_inode,
        .umount_begin   = nfs_umount_begin,
        .show_options   = nfs_show_options,
+       .show_devname   = nfs_show_devname,
+       .show_path      = nfs_show_path,
        .show_stats     = nfs_show_stats,
        .remount_fs     = nfs_remount,
 };
@@ -303,16 +308,16 @@ static const struct super_operations nfs_sops = {
 #ifdef CONFIG_NFS_V4
 static int nfs4_validate_text_mount_data(void *options,
        struct nfs_parsed_mount_data *args, const char *dev_name);
-static int nfs4_try_mount(int flags, const char *dev_name,
-       struct nfs_parsed_mount_data *data, struct vfsmount *mnt);
-static int nfs4_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+       struct nfs_parsed_mount_data *data);
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data);
-static int nfs4_referral_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data);
 static void nfs4_kill_super(struct super_block *sb);
@@ -320,7 +325,7 @@ static void nfs4_kill_super(struct super_block *sb);
 static struct file_system_type nfs4_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "nfs4",
-       .get_sb         = nfs4_get_sb,
+       .mount          = nfs4_mount,
        .kill_sb        = nfs4_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -352,7 +357,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = {
 struct file_system_type nfs4_referral_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "nfs4",
-       .get_sb         = nfs4_referral_get_sb,
+       .mount          = nfs4_referral_mount,
        .kill_sb        = nfs4_kill_super,
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -366,6 +371,8 @@ static const struct super_operations nfs4_sops = {
        .evict_inode    = nfs4_evict_inode,
        .umount_begin   = nfs_umount_begin,
        .show_options   = nfs_show_options,
+       .show_devname   = nfs_show_devname,
+       .show_path      = nfs_show_path,
        .show_stats     = nfs_show_stats,
        .remount_fs     = nfs_remount,
 };
@@ -726,6 +733,28 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
        return 0;
 }
 
+static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
+{
+       char *page = (char *) __get_free_page(GFP_KERNEL);
+       char *devname, *dummy;
+       int err = 0;
+       if (!page)
+               return -ENOMEM;
+       devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE);
+       if (IS_ERR(devname))
+               err = PTR_ERR(devname);
+       else
+               seq_escape(m, devname, " \t\n\\");
+       free_page((unsigned long)page);
+       return err;
+}
+
+static int nfs_show_path(struct seq_file *m, struct vfsmount *mnt)
+{
+       seq_puts(m, "/");
+       return 0;
+}
+
 /*
  * Present statistical information for this VFS mountpoint
  */
@@ -2267,19 +2296,19 @@ static int nfs_bdi_register(struct nfs_server *server)
        return bdi_register_dev(&server->backing_dev_info, server->s_dev);
 }
 
-static int nfs_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data)
 {
        struct nfs_server *server = NULL;
        struct super_block *s;
        struct nfs_parsed_mount_data *data;
        struct nfs_fh *mntfh;
-       struct dentry *mntroot;
+       struct dentry *mntroot = ERR_PTR(-ENOMEM);
        int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
        struct nfs_sb_mountdata sb_mntdata = {
                .mntflags = flags,
        };
-       int error = -ENOMEM;
+       int error;
 
        data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
        mntfh = nfs_alloc_fhandle();
@@ -2290,12 +2319,14 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 
        /* Validate the mount data */
        error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
-       if (error < 0)
+       if (error < 0) {
+               mntroot = ERR_PTR(error);
                goto out;
+       }
 
 #ifdef CONFIG_NFS_V4
        if (data->version == 4) {
-               error = nfs4_try_mount(flags, dev_name, data, mnt);
+               mntroot = nfs4_try_mount(flags, dev_name, data);
                kfree(data->client_address);
                kfree(data->nfs_server.export_path);
                goto out;
@@ -2305,7 +2336,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        /* Get a volume representation */
        server = nfs_create_server(data, mntfh);
        if (IS_ERR(server)) {
-               error = PTR_ERR(server);
+               mntroot = ERR_CAST(server);
                goto out;
        }
        sb_mntdata.server = server;
@@ -2316,7 +2347,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        /* Get a superblock - note that we may end up sharing one that already exists */
        s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
        if (IS_ERR(s)) {
-               error = PTR_ERR(s);
+               mntroot = ERR_CAST(s);
                goto out_err_nosb;
        }
 
@@ -2325,8 +2356,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                server = NULL;
        } else {
                error = nfs_bdi_register(server);
-               if (error)
+               if (error) {
+                       mntroot = ERR_PTR(error);
                        goto error_splat_bdi;
+               }
        }
 
        if (!s->s_root) {
@@ -2336,20 +2369,15 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                        s, data ? data->fscache_uniq : NULL, NULL);
        }
 
-       mntroot = nfs_get_root(s, mntfh);
-       if (IS_ERR(mntroot)) {
-               error = PTR_ERR(mntroot);
+       mntroot = nfs_get_root(s, mntfh, dev_name);
+       if (IS_ERR(mntroot))
                goto error_splat_super;
-       }
 
        error = security_sb_set_mnt_opts(s, &data->lsm_opts);
        if (error)
                goto error_splat_root;
 
        s->s_flags |= MS_ACTIVE;
-       mnt->mnt_sb = s;
-       mnt->mnt_root = mntroot;
-       error = 0;
 
 out:
        kfree(data->nfs_server.hostname);
@@ -2359,7 +2387,7 @@ out:
 out_free_fh:
        nfs_free_fhandle(mntfh);
        kfree(data);
-       return error;
+       return mntroot;
 
 out_err_nosb:
        nfs_free_server(server);
@@ -2367,6 +2395,7 @@ out_err_nosb:
 
 error_splat_root:
        dput(mntroot);
+       mntroot = ERR_PTR(error);
 error_splat_super:
        if (server && !s->s_root)
                bdi_unregister(&server->backing_dev_info);
@@ -2450,7 +2479,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
                nfs_fscache_get_super_cookie(s, NULL, data);
        }
 
-       mntroot = nfs_get_root(s, data->fh);
+       mntroot = nfs_get_root(s, data->fh, dev_name);
        if (IS_ERR(mntroot)) {
                error = PTR_ERR(mntroot);
                goto error_splat_super;
@@ -2718,7 +2747,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
                        s, data ? data->fscache_uniq : NULL, NULL);
        }
 
-       mntroot = nfs4_get_root(s, mntfh);
+       mntroot = nfs4_get_root(s, mntfh, dev_name);
        if (IS_ERR(mntroot)) {
                error = PTR_ERR(mntroot);
                goto error_splat_super;
@@ -2771,27 +2800,6 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
        return root_mnt;
 }
 
-static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt)
-{
-       char *page = (char *) __get_free_page(GFP_KERNEL);
-       char *devname, *tmp;
-
-       if (page == NULL)
-               return;
-       devname = nfs_path(path->mnt->mnt_devname,
-                       path->mnt->mnt_root, path->dentry,
-                       page, PAGE_SIZE);
-       if (IS_ERR(devname))
-               goto out_freepage;
-       tmp = kstrdup(devname, GFP_KERNEL);
-       if (tmp == NULL)
-               goto out_freepage;
-       kfree(mnt->mnt_devname);
-       mnt->mnt_devname = tmp;
-out_freepage:
-       free_page((unsigned long)page);
-}
-
 struct nfs_referral_count {
        struct list_head list;
        const struct task_struct *task;
@@ -2858,17 +2866,18 @@ static void nfs_referral_loop_unprotect(void)
        kfree(p);
 }
 
-static int nfs_follow_remote_path(struct vfsmount *root_mnt,
-               const char *export_path, struct vfsmount *mnt_target)
+static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
+               const char *export_path)
 {
        struct nameidata *nd = NULL;
        struct mnt_namespace *ns_private;
        struct super_block *s;
+       struct dentry *dentry;
        int ret;
 
        nd = kmalloc(sizeof(*nd), GFP_KERNEL);
        if (nd == NULL)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        ns_private = create_mnt_ns(root_mnt);
        ret = PTR_ERR(ns_private);
@@ -2890,32 +2899,27 @@ static int nfs_follow_remote_path(struct vfsmount *root_mnt,
 
        s = nd->path.mnt->mnt_sb;
        atomic_inc(&s->s_active);
-       mnt_target->mnt_sb = s;
-       mnt_target->mnt_root = dget(nd->path.dentry);
-
-       /* Correct the device pathname */
-       nfs_fix_devname(&nd->path, mnt_target);
+       dentry = dget(nd->path.dentry);
 
        path_put(&nd->path);
        kfree(nd);
        down_write(&s->s_umount);
-       return 0;
+       return dentry;
 out_put_mnt_ns:
        put_mnt_ns(ns_private);
 out_mntput:
        mntput(root_mnt);
 out_err:
        kfree(nd);
-       return ret;
+       return ERR_PTR(ret);
 }
 
-static int nfs4_try_mount(int flags, const char *dev_name,
-                        struct nfs_parsed_mount_data *data,
-                        struct vfsmount *mnt)
+static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+                        struct nfs_parsed_mount_data *data)
 {
        char *export_path;
        struct vfsmount *root_mnt;
-       int error;
+       struct dentry *res;
 
        dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
@@ -2925,26 +2929,25 @@ static int nfs4_try_mount(int flags, const char *dev_name,
                        data->nfs_server.hostname);
        data->nfs_server.export_path = export_path;
 
-       error = PTR_ERR(root_mnt);
-       if (IS_ERR(root_mnt))
-               goto out;
+       res = ERR_CAST(root_mnt);
+       if (!IS_ERR(root_mnt))
+               res = nfs_follow_remote_path(root_mnt, export_path);
 
-       error = nfs_follow_remote_path(root_mnt, export_path, mnt);
-
-out:
-       dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", error,
-                       error != 0 ? " [error]" : "");
-       return error;
+       dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
+                       IS_ERR(res) ? PTR_ERR(res) : 0,
+                       IS_ERR(res) ? " [error]" : "");
+       return res;
 }
 
 /*
  * Get the superblock for an NFS4 mountpoint
  */
-static int nfs4_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *raw_data)
 {
        struct nfs_parsed_mount_data *data;
        int error = -ENOMEM;
+       struct dentry *res = ERR_PTR(-ENOMEM);
 
        data = nfs_alloc_parsed_mount_data(4);
        if (data == NULL)
@@ -2952,10 +2955,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
 
        /* Validate the mount data */
        error = nfs4_validate_mount_data(raw_data, data, dev_name);
-       if (error < 0)
+       if (error < 0) {
+               res = ERR_PTR(error);
                goto out;
+       }
 
-       error = nfs4_try_mount(flags, dev_name, data, mnt);
+       res = nfs4_try_mount(flags, dev_name, data);
+       if (IS_ERR(res))
+               error = PTR_ERR(res);
 
 out:
        kfree(data->client_address);
@@ -2964,9 +2971,9 @@ out:
        kfree(data->fscache_uniq);
 out_free_data:
        kfree(data);
-       dprintk("<-- nfs4_get_sb() = %d%s\n", error,
+       dprintk("<-- nfs4_mount() = %d%s\n", error,
                        error != 0 ? " [error]" : "");
-       return error;
+       return res;
 }
 
 static void nfs4_kill_super(struct super_block *sb)
@@ -3033,7 +3040,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
                nfs_fscache_get_super_cookie(s, NULL, data);
        }
 
-       mntroot = nfs4_get_root(s, data->fh);
+       mntroot = nfs4_get_root(s, data->fh, dev_name);
        if (IS_ERR(mntroot)) {
                error = PTR_ERR(mntroot);
                goto error_splat_super;
@@ -3120,7 +3127,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
                nfs_fscache_get_super_cookie(s, NULL, data);
        }
 
-       mntroot = nfs4_get_root(s, mntfh);
+       mntroot = nfs4_get_root(s, mntfh, dev_name);
        if (IS_ERR(mntroot)) {
                error = PTR_ERR(mntroot);
                goto error_splat_super;
@@ -3160,16 +3167,15 @@ error_splat_bdi:
 /*
  * Create an NFS4 server record on referral traversal
  */
-static int nfs4_referral_get_sb(struct file_system_type *fs_type,
-               int flags, const char *dev_name, void *raw_data,
-               struct vfsmount *mnt)
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+               int flags, const char *dev_name, void *raw_data)
 {
        struct nfs_clone_mount *data = raw_data;
        char *export_path;
        struct vfsmount *root_mnt;
-       int error;
+       struct dentry *res;
 
-       dprintk("--> nfs4_referral_get_sb()\n");
+       dprintk("--> nfs4_referral_mount()\n");
 
        export_path = data->mnt_path;
        data->mnt_path = "/";
@@ -3178,15 +3184,13 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type,
                        flags, data, data->hostname);
        data->mnt_path = export_path;
 
-       error = PTR_ERR(root_mnt);
-       if (IS_ERR(root_mnt))
-               goto out;
-
-       error = nfs_follow_remote_path(root_mnt, export_path, mnt);
-out:
-       dprintk("<-- nfs4_referral_get_sb() = %d%s\n", error,
-                       error != 0 ? " [error]" : "");
-       return error;
+       res = ERR_CAST(root_mnt);
+       if (!IS_ERR(root_mnt))
+               res = nfs_follow_remote_path(root_mnt, export_path);
+       dprintk("<-- nfs4_referral_mount() = %ld%s\n",
+                       IS_ERR(res) ? PTR_ERR(res) : 0,
+                       IS_ERR(res) ? " [error]" : "");
+       return res;
 }
 
 #endif /* CONFIG_NFS_V4 */
index 6481d53..8d6864c 100644 (file)
@@ -148,6 +148,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
        alias = d_lookup(parent, &data->args.name);
        if (alias != NULL) {
                int ret = 0;
+               void *devname_garbage = NULL;
 
                /*
                 * Hey, we raced with lookup... See if we need to transfer
@@ -157,6 +158,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
                spin_lock(&alias->d_lock);
                if (alias->d_inode != NULL &&
                    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
+                       devname_garbage = alias->d_fsdata;
                        alias->d_fsdata = data;
                        alias->d_flags |= DCACHE_NFSFS_RENAMED;
                        ret = 1;
@@ -164,6 +166,13 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
                spin_unlock(&alias->d_lock);
                nfs_dec_sillycount(dir);
                dput(alias);
+               /*
+                * If we'd displaced old cached devname, free it.  At that
+                * point dentry is definitely not a root, so we won't need
+                * that anymore.
+                */
+               if (devname_garbage)
+                       kfree(devname_garbage);
                return ret;
        }
        data->dir = igrab(dir);
@@ -252,6 +261,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct nfs_unlinkdata *data;
        int status = -ENOMEM;
+       void *devname_garbage = NULL;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (data == NULL)
@@ -269,8 +279,16 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
                goto out_unlock;
        dentry->d_flags |= DCACHE_NFSFS_RENAMED;
+       devname_garbage = dentry->d_fsdata;
        dentry->d_fsdata = data;
        spin_unlock(&dentry->d_lock);
+       /*
+        * If we'd displaced old cached devname, free it.  At that
+        * point dentry is definitely not a root, so we won't need
+        * that anymore.
+        */
+       if (devname_garbage)
+               kfree(devname_garbage);
        return 0;
 out_unlock:
        spin_unlock(&dentry->d_lock);
@@ -299,6 +317,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
                dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
                data = dentry->d_fsdata;
+               dentry->d_fsdata = NULL;
        }
        spin_unlock(&dentry->d_lock);
 
@@ -315,6 +334,7 @@ nfs_cancel_async_unlink(struct dentry *dentry)
                struct nfs_unlinkdata *data = dentry->d_fsdata;
 
                dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
+               dentry->d_fsdata = NULL;
                spin_unlock(&dentry->d_lock);
                nfs_free_unlinkdata(data);
                return;
index 7e9dd4c..4bae0ef 100644 (file)
@@ -843,23 +843,6 @@ error:
 }
 EXPORT_SYMBOL(mount_bdev);
 
-int get_sb_bdev(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt)
-{
-       struct dentry *root;
-
-       root = mount_bdev(fs_type, flags, dev_name, data, fill_super);
-       if (IS_ERR(root))
-               return PTR_ERR(root);
-       mnt->mnt_root = root;
-       mnt->mnt_sb = root->d_sb;
-       return 0;
-}
-
-EXPORT_SYMBOL(get_sb_bdev);
-
 void kill_block_super(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
@@ -897,22 +880,6 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
 }
 EXPORT_SYMBOL(mount_nodev);
 
-int get_sb_nodev(struct file_system_type *fs_type,
-       int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt)
-{
-       struct dentry *root;
-
-       root = mount_nodev(fs_type, flags, data, fill_super);
-       if (IS_ERR(root))
-               return PTR_ERR(root);
-       mnt->mnt_root = root;
-       mnt->mnt_sb = root->d_sb;
-       return 0;
-}
-EXPORT_SYMBOL(get_sb_nodev);
-
 static int compare_single(struct super_block *s, void *p)
 {
        return 1;
@@ -943,22 +910,6 @@ struct dentry *mount_single(struct file_system_type *fs_type,
 }
 EXPORT_SYMBOL(mount_single);
 
-int get_sb_single(struct file_system_type *fs_type,
-       int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt)
-{
-       struct dentry *root;
-       root = mount_single(fs_type, flags, data, fill_super);
-       if (IS_ERR(root))
-               return PTR_ERR(root);
-       mnt->mnt_root = root;
-       mnt->mnt_sb = root->d_sb;
-       return 0;
-}
-
-EXPORT_SYMBOL(get_sb_single);
-
 struct vfsmount *
 vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
 {
@@ -988,19 +939,13 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
                        goto out_free_secdata;
        }
 
-       if (type->mount) {
-               root = type->mount(type, flags, name, data);
-               if (IS_ERR(root)) {
-                       error = PTR_ERR(root);
-                       goto out_free_secdata;
-               }
-               mnt->mnt_root = root;
-               mnt->mnt_sb = root->d_sb;
-       } else {
-               error = type->get_sb(type, flags, name, data, mnt);
-               if (error < 0)
-                       goto out_free_secdata;
+       root = type->mount(type, flags, name, data);
+       if (IS_ERR(root)) {
+               error = PTR_ERR(root);
+               goto out_free_secdata;
        }
+       mnt->mnt_root = root;
+       mnt->mnt_sb = root->d_sb;
        BUG_ON(!mnt->mnt_sb);
        WARN_ON(!mnt->mnt_sb->s_bdi);
        mnt->mnt_sb->s_flags |= MS_BORN;
index 2f5a71d..92f7e04 100644 (file)
@@ -1631,6 +1631,8 @@ struct super_operations {
        void (*umount_begin) (struct super_block *);
 
        int (*show_options)(struct seq_file *, struct vfsmount *);
+       int (*show_devname)(struct seq_file *, struct vfsmount *);
+       int (*show_path)(struct seq_file *, struct vfsmount *);
        int (*show_stats)(struct seq_file *, struct vfsmount *);
 #ifdef CONFIG_QUOTA
        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -1794,8 +1796,6 @@ int sync_inode_metadata(struct inode *inode, int wait);
 struct file_system_type {
        const char *name;
        int fs_flags;
-       int (*get_sb) (struct file_system_type *, int,
-                      const char *, void *, struct vfsmount *);
        struct dentry *(*mount) (struct file_system_type *, int,
                       const char *, void *);
        void (*kill_sb) (struct super_block *);
@@ -1818,24 +1818,12 @@ extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
 extern struct dentry *mount_bdev(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data,
        int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_bdev(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt);
 extern struct dentry *mount_single(struct file_system_type *fs_type,
        int flags, void *data,
        int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_single(struct file_system_type *fs_type,
-       int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt);
 extern struct dentry *mount_nodev(struct file_system_type *fs_type,
        int flags, void *data,
        int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_nodev(struct file_system_type *fs_type,
-       int flags, void *data,
-       int (*fill_super)(struct super_block *, void *, int),
-       struct vfsmount *mnt);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);