]> Pileus Git - ~andy/linux/blobdiff - fs/namei.c
GFS2: Read in rindex if necessary during unlink
[~andy/linux] / fs / namei.c
index 5008f01787f5681730a9273693a1a863e7e6cc7e..a780ea515c47988623fc4954b734562182ed24c5 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/uaccess.h>
 
 #include "internal.h"
+#include "mount.h"
 
 /* [Feb-1997 T. Schoebel-Theuer]
  * Fundamental changes in the pathname lookup mechanisms (namei)
@@ -139,21 +140,19 @@ static int do_getname(const char __user *filename, char *page)
 
 static char *getname_flags(const char __user *filename, int flags, int *empty)
 {
-       char *tmp, *result;
+       char *result = __getname();
+       int retval;
 
-       result = ERR_PTR(-ENOMEM);
-       tmp = __getname();
-       if (tmp)  {
-               int retval = do_getname(filename, tmp);
+       if (!result)
+               return ERR_PTR(-ENOMEM);
 
-               result = tmp;
-               if (retval < 0) {
-                       if (retval == -ENOENT && empty)
-                               *empty = 1;
-                       if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
-                               __putname(tmp);
-                               result = ERR_PTR(retval);
-                       }
+       retval = do_getname(filename, result);
+       if (retval < 0) {
+               if (retval == -ENOENT && empty)
+                       *empty = 1;
+               if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
+                       __putname(result);
+                       return ERR_PTR(retval);
                }
        }
        audit_getname(result);
@@ -676,36 +675,38 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 
 static int follow_up_rcu(struct path *path)
 {
-       struct vfsmount *parent;
+       struct mount *mnt = real_mount(path->mnt);
+       struct mount *parent;
        struct dentry *mountpoint;
 
-       parent = path->mnt->mnt_parent;
-       if (parent == path->mnt)
+       parent = mnt->mnt_parent;
+       if (&parent->mnt == path->mnt)
                return 0;
-       mountpoint = path->mnt->mnt_mountpoint;
+       mountpoint = mnt->mnt_mountpoint;
        path->dentry = mountpoint;
-       path->mnt = parent;
+       path->mnt = &parent->mnt;
        return 1;
 }
 
 int follow_up(struct path *path)
 {
-       struct vfsmount *parent;
+       struct mount *mnt = real_mount(path->mnt);
+       struct mount *parent;
        struct dentry *mountpoint;
 
        br_read_lock(vfsmount_lock);
-       parent = path->mnt->mnt_parent;
-       if (parent == path->mnt) {
+       parent = mnt->mnt_parent;
+       if (&parent->mnt == path->mnt) {
                br_read_unlock(vfsmount_lock);
                return 0;
        }
-       mntget(parent);
-       mountpoint = dget(path->mnt->mnt_mountpoint);
+       mntget(&parent->mnt);
+       mountpoint = dget(mnt->mnt_mountpoint);
        br_read_unlock(vfsmount_lock);
        dput(path->dentry);
        path->dentry = mountpoint;
        mntput(path->mnt);
-       path->mnt = parent;
+       path->mnt = &parent->mnt;
        return 1;
 }
 
@@ -884,7 +885,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                               struct inode **inode)
 {
        for (;;) {
-               struct vfsmount *mounted;
+               struct mount *mounted;
                /*
                 * Don't forget we might have a non-mountpoint managed dentry
                 * that wants to block transit.
@@ -898,8 +899,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                mounted = __lookup_mnt(path->mnt, path->dentry, 1);
                if (!mounted)
                        break;
-               path->mnt = mounted;
-               path->dentry = mounted->mnt_root;
+               path->mnt = &mounted->mnt;
+               path->dentry = mounted->mnt.mnt_root;
                nd->flags |= LOOKUP_JUMPED;
                nd->seq = read_seqcount_begin(&path->dentry->d_seq);
                /*
@@ -915,12 +916,12 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
 static void follow_mount_rcu(struct nameidata *nd)
 {
        while (d_mountpoint(nd->path.dentry)) {
-               struct vfsmount *mounted;
+               struct mount *mounted;
                mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
                if (!mounted)
                        break;
-               nd->path.mnt = mounted;
-               nd->path.dentry = mounted->mnt_root;
+               nd->path.mnt = &mounted->mnt;
+               nd->path.dentry = mounted->mnt.mnt_root;
                nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
        }
 }
@@ -1094,8 +1095,10 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr
        struct dentry *old;
 
        /* Don't create child dentry for a dead directory. */
-       if (unlikely(IS_DEADDIR(inode)))
+       if (unlikely(IS_DEADDIR(inode))) {
+               dput(dentry);
                return ERR_PTR(-ENOENT);
+       }
 
        old = inode->i_op->lookup(inode, dentry, nd);
        if (unlikely(old)) {
@@ -1976,7 +1979,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
        }
 }
 
-int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                struct nameidata *nd)
 {
        int error = may_create(dir, dentry);
@@ -2177,7 +2180,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 
        /* Negative dentry, just create the file */
        if (!dentry->d_inode) {
-               int mode = op->mode;
+               umode_t mode = op->mode;
                if (!IS_POSIXACL(dir->d_inode))
                        mode &= ~current_umask();
                /*
@@ -2444,7 +2447,7 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, struct pat
 }
 EXPORT_SYMBOL(user_path_create);
 
-int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
        int error = may_create(dir, dentry);
 
@@ -2472,7 +2475,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        return error;
 }
 
-static int may_mknod(mode_t mode)
+static int may_mknod(umode_t mode)
 {
        switch (mode & S_IFMT) {
        case S_IFREG:
@@ -2489,7 +2492,7 @@ static int may_mknod(mode_t mode)
        }
 }
 
-SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode,
+SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
                unsigned, dev)
 {
        struct dentry *dentry;
@@ -2536,12 +2539,12 @@ out_dput:
        return error;
 }
 
-SYSCALL_DEFINE3(mknod, const char __user *, filename, int, mode, unsigned, dev)
+SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev)
 {
        return sys_mknodat(AT_FDCWD, filename, mode, dev);
 }
 
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int error = may_create(dir, dentry);
 
@@ -2562,7 +2565,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        return error;
 }
 
-SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
+SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
 {
        struct dentry *dentry;
        struct path path;
@@ -2590,7 +2593,7 @@ out_dput:
        return error;
 }
 
-SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
+SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
 {
        return sys_mkdirat(AT_FDCWD, pathname, mode);
 }