[XFS] Shutdown the filesystem if all device paths have gone. Made
[safe/jmp/linux-2.6] / fs / namei.c
index 98dc2e1..d6e2ee2 100644 (file)
@@ -546,6 +546,22 @@ struct path {
        struct dentry *dentry;
 };
 
+static inline void dput_path(struct path *path, struct nameidata *nd)
+{
+       dput(path->dentry);
+       if (path->mnt != nd->mnt)
+               mntput(path->mnt);
+}
+
+static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
+{
+       dput(nd->dentry);
+       if (nd->mnt != path->mnt)
+               mntput(nd->mnt);
+       nd->mnt = path->mnt;
+       nd->dentry = path->dentry;
+}
+
 static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
 {
        int error;
@@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
        touch_atime(path->mnt, dentry);
        nd_set_link(nd, NULL);
 
-       if (path->mnt == nd->mnt)
-               mntget(path->mnt);
+       if (path->mnt != nd->mnt) {
+               path_to_nameidata(path, nd);
+               dget(dentry);
+       }
+       mntget(path->mnt);
        cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
        error = PTR_ERR(cookie);
        if (!IS_ERR(cookie)) {
@@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
        return error;
 }
 
-static inline void dput_path(struct path *path, struct nameidata *nd)
-{
-       dput(path->dentry);
-       if (path->mnt != nd->mnt)
-               mntput(path->mnt);
-}
-
-static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
-{
-       dput(nd->dentry);
-       if (nd->mnt != path->mnt)
-               mntput(nd->mnt);
-       nd->mnt = path->mnt;
-       nd->dentry = path->dentry;
-}
-
 /*
  * This limits recursive symlink follows to 8, while
  * limiting consecutive symlinks to 40.
@@ -1077,8 +1080,8 @@ static int fastcall do_path_lookup(int dfd, const char *name,
        nd->flags = flags;
        nd->depth = 0;
 
-       read_lock(&current->fs->lock);
        if (*name=='/') {
+               read_lock(&current->fs->lock);
                if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
                        nd->mnt = mntget(current->fs->altrootmnt);
                        nd->dentry = dget(current->fs->altroot);
@@ -1089,33 +1092,35 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                }
                nd->mnt = mntget(current->fs->rootmnt);
                nd->dentry = dget(current->fs->root);
+               read_unlock(&current->fs->lock);
        } else if (dfd == AT_FDCWD) {
+               read_lock(&current->fs->lock);
                nd->mnt = mntget(current->fs->pwdmnt);
                nd->dentry = dget(current->fs->pwd);
+               read_unlock(&current->fs->lock);
        } else {
                struct dentry *dentry;
 
                file = fget_light(dfd, &fput_needed);
                retval = -EBADF;
                if (!file)
-                       goto unlock_fail;
+                       goto out_fail;
 
                dentry = file->f_dentry;
 
                retval = -ENOTDIR;
                if (!S_ISDIR(dentry->d_inode->i_mode))
-                       goto fput_unlock_fail;
+                       goto fput_fail;
 
                retval = file_permission(file, MAY_EXEC);
                if (retval)
-                       goto fput_unlock_fail;
+                       goto fput_fail;
 
                nd->mnt = mntget(file->f_vfsmnt);
                nd->dentry = dget(dentry);
 
                fput_light(file, fput_needed);
        }
-       read_unlock(&current->fs->lock);
        current->total_link_count = 0;
        retval = link_path_walk(name, nd);
 out:
@@ -1124,13 +1129,12 @@ out:
                                nd->dentry->d_inode))
                audit_inode(name, nd->dentry->d_inode, flags);
        }
+out_fail:
        return retval;
 
-fput_unlock_fail:
+fput_fail:
        fput_light(file, fput_needed);
-unlock_fail:
-       read_unlock(&current->fs->lock);
-       return retval;
+       goto out_fail;
 }
 
 int fastcall path_lookup(const char *name, unsigned int flags,
@@ -1251,7 +1255,7 @@ out:
        return dentry;
 }
 
-struct dentry * lookup_hash(struct nameidata *nd)
+static struct dentry *lookup_hash(struct nameidata *nd)
 {
        return __lookup_hash(&nd->last, nd->dentry, nd);
 }
@@ -2694,7 +2698,6 @@ EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
-EXPORT_SYMBOL(lookup_hash);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);