Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / fs / nfs / namespace.c
index 86b3169c8cac0b01eded9d13c59edf01912b6f68..7f86e65182e450b528ab7e0a6811ece68c516b56 100644 (file)
@@ -2,12 +2,11 @@
  * linux/fs/nfs/namespace.c
  *
  * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
+ * - Modified by David Howells <dhowells@redhat.com>
  *
  * NFS namespace
  */
 
-#include <linux/config.h>
-
 #include <linux/dcache.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
-static void nfs_expire_automounts(void *list);
+static void nfs_expire_automounts(struct work_struct *work);
 
 LIST_HEAD(nfs_automount_list);
-static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &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,
+                                       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
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
@@ -38,7 +43,9 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition.
  */
-char *nfs_path(const char *base, const struct dentry *dentry,
+char *nfs_path(const char *base,
+              const struct dentry *droot,
+              const struct dentry *dentry,
               char *buffer, ssize_t buflen)
 {
        char *end = buffer+buflen;
@@ -47,7 +54,7 @@ char *nfs_path(const char *base, const struct dentry *dentry,
        *--end = '\0';
        buflen--;
        spin_lock(&dcache_lock);
-       while (!IS_ROOT(dentry)) {
+       while (!IS_ROOT(dentry) && dentry != droot) {
                namelen = dentry->d_name.len;
                buflen -= namelen + 1;
                if (buflen < 0)
@@ -96,15 +103,18 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
        struct nfs_fattr fattr;
        int err;
 
+       dprintk("--> nfs_follow_mountpoint()\n");
+
        BUG_ON(IS_ROOT(dentry));
        dprintk("%s: enter\n", __FUNCTION__);
        dput(nd->dentry);
        nd->dentry = dget(dentry);
-       if (d_mountpoint(nd->dentry))
-               goto out_follow;
+
        /* Look it up again */
        parent = dget_parent(nd->dentry);
-       err = server->rpc_ops->lookup(parent->d_inode, &nd->dentry->d_name, &fh, &fattr);
+       err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
+                                                 &nd->dentry->d_name,
+                                                 &fh, &fattr);
        dput(parent);
        if (err != 0)
                goto out_err;
@@ -132,6 +142,8 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
        schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
 out:
        dprintk("%s: done, returned %d\n", __FUNCTION__, err);
+
+       dprintk("<-- nfs_follow_mountpoint() = %d\n", err);
        return ERR_PTR(err);
 out_err:
        path_release(nd);
@@ -143,18 +155,18 @@ out_follow:
        goto out;
 }
 
-struct inode_operations nfs_mountpoint_inode_operations = {
+const struct inode_operations nfs_mountpoint_inode_operations = {
        .follow_link    = nfs_follow_mountpoint,
        .getattr        = nfs_getattr,
 };
 
-struct inode_operations nfs_referral_inode_operations = {
+const struct inode_operations nfs_referral_inode_operations = {
        .follow_link    = nfs_follow_mountpoint,
 };
 
-static void nfs_expire_automounts(void *data)
+static void nfs_expire_automounts(struct work_struct *work)
 {
-       struct list_head *list = (struct list_head *)data;
+       struct list_head *list = &nfs_automount_list;
 
        mark_mounts_for_expiry(list);
        if (!list_empty(list))
@@ -172,22 +184,23 @@ void nfs_release_automount_timer(void)
 /*
  * Clone a mountpoint of the appropriate type
  */
-static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname,
+static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
+                                          const char *devname,
                                           struct nfs_clone_mount *mountdata)
 {
 #ifdef CONFIG_NFS_V4
        struct vfsmount *mnt = NULL;
-       switch (server->rpc_ops->version) {
+       switch (server->nfs_client->cl_nfsversion) {
                case 2:
                case 3:
-                       mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
+                       mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
                        break;
                case 4:
-                       mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata);
+                       mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata);
        }
        return mnt;
 #else
-       return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
+       return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata);
 #endif
 }
 
@@ -199,9 +212,10 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devn
  * @fattr - attributes for new root inode
  *
  */
-struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-               const struct dentry *dentry, struct nfs_fh *fh,
-               struct nfs_fattr *fattr)
+static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+                                       const struct dentry *dentry,
+                                       struct nfs_fh *fh,
+                                       struct nfs_fattr *fattr)
 {
        struct nfs_clone_mount mountdata = {
                .sb = mnt_parent->mnt_sb,
@@ -213,6 +227,8 @@ struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
        char *page = (char *) __get_free_page(GFP_USER);
        char *devname;
 
+       dprintk("--> nfs_do_submount()\n");
+
        dprintk("%s: submounting on %s/%s\n", __FUNCTION__,
                        dentry->d_parent->d_name.name,
                        dentry->d_name.name);
@@ -227,5 +243,7 @@ free_page:
        free_page((unsigned long)page);
 out:
        dprintk("%s: done\n", __FUNCTION__);
+
+       dprintk("<-- nfs_do_submount() = %p\n", mnt);
        return mnt;
 }