Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / fs / namei.c
index e615ff3..d1ebe96 100644 (file)
@@ -1054,53 +1054,65 @@ static void follow_dotdot(struct nameidata *nd)
 }
 
 /*
- * Allocate a dentry with name and parent, and perform a parent
- * directory ->lookup on it. Returns the new dentry, or ERR_PTR
- * on error. parent->d_inode->i_mutex must be held. d_lookup must
- * have verified that no child exists while under i_mutex.
+ * This looks up the name in dcache, possibly revalidates the old dentry and
+ * allocates a new one if not found or not valid.  In the need_lookup argument
+ * returns whether i_op->lookup is necessary.
+ *
+ * dir->d_inode->i_mutex must be held
  */
-static struct dentry *d_alloc_and_lookup(struct dentry *parent,
-                               struct qstr *name, struct nameidata *nd)
+static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
+                                   struct nameidata *nd, bool *need_lookup)
 {
-       struct inode *inode = parent->d_inode;
        struct dentry *dentry;
-       struct dentry *old;
+       int error;
 
-       /* Don't create child dentry for a dead directory. */
-       if (unlikely(IS_DEADDIR(inode)))
-               return ERR_PTR(-ENOENT);
+       *need_lookup = false;
+       dentry = d_lookup(dir, name);
+       if (dentry) {
+               if (d_need_lookup(dentry)) {
+                       *need_lookup = true;
+               } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
+                       error = d_revalidate(dentry, nd);
+                       if (unlikely(error <= 0)) {
+                               if (error < 0) {
+                                       dput(dentry);
+                                       return ERR_PTR(error);
+                               } else if (!d_invalidate(dentry)) {
+                                       dput(dentry);
+                                       dentry = NULL;
+                               }
+                       }
+               }
+       }
 
-       dentry = d_alloc(parent, name);
-       if (unlikely(!dentry))
-               return ERR_PTR(-ENOMEM);
+       if (!dentry) {
+               dentry = d_alloc(dir, name);
+               if (unlikely(!dentry))
+                       return ERR_PTR(-ENOMEM);
 
-       old = inode->i_op->lookup(inode, dentry, nd);
-       if (unlikely(old)) {
-               dput(dentry);
-               dentry = old;
+               *need_lookup = true;
        }
        return dentry;
 }
 
 /*
- * We already have a dentry, but require a lookup to be performed on the parent
- * directory to fill in d_inode. Returns the new dentry, or ERR_PTR on error.
- * parent->d_inode->i_mutex must be held. d_lookup must have verified that no
- * child exists while under i_mutex.
+ * Call i_op->lookup on the dentry.  The dentry must be negative but may be
+ * hashed if it was pouplated with DCACHE_NEED_LOOKUP.
+ *
+ * dir->d_inode->i_mutex must be held
  */
-static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry,
-                                    struct nameidata *nd)
+static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
+                                 struct nameidata *nd)
 {
-       struct inode *inode = parent->d_inode;
        struct dentry *old;
 
        /* Don't create child dentry for a dead directory. */
-       if (unlikely(IS_DEADDIR(inode))) {
+       if (unlikely(IS_DEADDIR(dir))) {
                dput(dentry);
                return ERR_PTR(-ENOENT);
        }
 
-       old = inode->i_op->lookup(inode, dentry, nd);
+       old = dir->i_op->lookup(dir, dentry, nd);
        if (unlikely(old)) {
                dput(dentry);
                dentry = old;
@@ -1108,6 +1120,19 @@ static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentr
        return dentry;
 }
 
+static struct dentry *__lookup_hash(struct qstr *name,
+               struct dentry *base, struct nameidata *nd)
+{
+       bool need_lookup;
+       struct dentry *dentry;
+
+       dentry = lookup_dcache(name, base, nd, &need_lookup);
+       if (!need_lookup)
+               return dentry;
+
+       return lookup_real(base->d_inode, dentry, nd);
+}
+
 /*
  *  It's more convoluted than I'd like it to be, but... it's still fairly
  *  small and for now I'd prefer to have fast path as straight as possible.
@@ -1139,6 +1164,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
                        return -ECHILD;
                nd->seq = seq;
 
+               if (unlikely(d_need_lookup(dentry)))
+                       goto unlazy;
                if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
                        status = d_revalidate(dentry, nd);
                        if (unlikely(status <= 0)) {
@@ -1147,8 +1174,6 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
                                goto unlazy;
                        }
                }
-               if (unlikely(d_need_lookup(dentry)))
-                       goto unlazy;
                path->mnt = mnt;
                path->dentry = dentry;
                if (unlikely(!__follow_mount_rcu(nd, path, inode)))
@@ -1163,38 +1188,14 @@ unlazy:
                dentry = __d_lookup(parent, name);
        }
 
-       if (dentry && unlikely(d_need_lookup(dentry))) {
+       if (unlikely(!dentry))
+               goto need_lookup;
+
+       if (unlikely(d_need_lookup(dentry))) {
                dput(dentry);
-               dentry = NULL;
-       }
-retry:
-       if (unlikely(!dentry)) {
-               struct inode *dir = parent->d_inode;
-               BUG_ON(nd->inode != dir);
-
-               mutex_lock(&dir->i_mutex);
-               dentry = d_lookup(parent, name);
-               if (likely(!dentry)) {
-                       dentry = d_alloc_and_lookup(parent, name, nd);
-                       if (IS_ERR(dentry)) {
-                               mutex_unlock(&dir->i_mutex);
-                               return PTR_ERR(dentry);
-                       }
-                       /* known good */
-                       need_reval = 0;
-                       status = 1;
-               } else if (unlikely(d_need_lookup(dentry))) {
-                       dentry = d_inode_lookup(parent, dentry, nd);
-                       if (IS_ERR(dentry)) {
-                               mutex_unlock(&dir->i_mutex);
-                               return PTR_ERR(dentry);
-                       }
-                       /* known good */
-                       need_reval = 0;
-                       status = 1;
-               }
-               mutex_unlock(&dir->i_mutex);
+               goto need_lookup;
        }
+
        if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
                status = d_revalidate(dentry, nd);
        if (unlikely(status <= 0)) {
@@ -1204,12 +1205,10 @@ retry:
                }
                if (!d_invalidate(dentry)) {
                        dput(dentry);
-                       dentry = NULL;
-                       need_reval = 1;
-                       goto retry;
+                       goto need_lookup;
                }
        }
-
+done:
        path->mnt = mnt;
        path->dentry = dentry;
        err = follow_managed(path, nd->flags);
@@ -1221,6 +1220,16 @@ retry:
                nd->flags |= LOOKUP_JUMPED;
        *inode = path->dentry->d_inode;
        return 0;
+
+need_lookup:
+       BUG_ON(nd->inode != parent->d_inode);
+
+       mutex_lock(&parent->d_inode->i_mutex);
+       dentry = __lookup_hash(name, parent, nd);
+       mutex_unlock(&parent->d_inode->i_mutex);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+       goto done;
 }
 
 static inline int may_lookup(struct nameidata *nd)
@@ -1398,18 +1407,9 @@ static inline int can_lookup(struct inode *inode)
  */
 #ifdef CONFIG_DCACHE_WORD_ACCESS
 
-#ifdef CONFIG_64BIT
+#include <asm/word-at-a-time.h>
 
-/*
- * Jan Achrenius on G+: microoptimized version of
- * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
- * that works for the bytemasks without having to
- * mask them first.
- */
-static inline long count_masked_bytes(unsigned long mask)
-{
-       return mask*0x0001020304050608ul >> 56;
-}
+#ifdef CONFIG_64BIT
 
 static inline unsigned int fold_hash(unsigned long hash)
 {
@@ -1419,15 +1419,6 @@ static inline unsigned int fold_hash(unsigned long hash)
 
 #else  /* 32-bit case */
 
-/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
-static inline long count_masked_bytes(long mask)
-{
-       /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
-       long a = (0x0ff0001+mask) >> 23;
-       /* Fix the 1 for 00 case */
-       return a & mask;
-}
-
 #define fold_hash(x) (x)
 
 #endif
@@ -1438,7 +1429,7 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
        unsigned long hash = 0;
 
        for (;;) {
-               a = *(unsigned long *)name;
+               a = load_unaligned_zeropad(name);
                if (len < sizeof(unsigned long))
                        break;
                hash += a;
@@ -1455,17 +1446,6 @@ done:
 }
 EXPORT_SYMBOL(full_name_hash);
 
-#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
-#define ONEBYTES       REPEAT_BYTE(0x01)
-#define SLASHBYTES     REPEAT_BYTE('/')
-#define HIGHBITS       REPEAT_BYTE(0x80)
-
-/* Return the high bit set in the first byte that is a zero */
-static inline unsigned long has_zero(unsigned long a)
-{
-       return ((a - ONEBYTES) & ~a) & HIGHBITS;
-}
-
 /*
  * Calculate the length and hash of the path component, and
  * return the length of the component;
@@ -1479,9 +1459,9 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp)
        do {
                hash = (hash + a) * 9;
                len += sizeof(unsigned long);
-               a = *(unsigned long *)(name+len);
+               a = load_unaligned_zeropad(name+len);
                /* Do we have any NUL or '/' bytes in this word? */
-               mask = has_zero(a) | has_zero(a ^ SLASHBYTES);
+               mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/'));
        } while (!mask);
 
        /* The mask *below* the first high bit set */
@@ -1846,59 +1826,6 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
        return err;
 }
 
-static struct dentry *__lookup_hash(struct qstr *name,
-               struct dentry *base, struct nameidata *nd)
-{
-       struct inode *inode = base->d_inode;
-       struct dentry *dentry;
-       int err;
-
-       err = inode_permission(inode, MAY_EXEC);
-       if (err)
-               return ERR_PTR(err);
-
-       /*
-        * Don't bother with __d_lookup: callers are for creat as
-        * well as unlink, so a lot of the time it would cost
-        * a double lookup.
-        */
-       dentry = d_lookup(base, name);
-
-       if (dentry && d_need_lookup(dentry)) {
-               /*
-                * __lookup_hash is called with the parent dir's i_mutex already
-                * held, so we are good to go here.
-                */
-               dentry = d_inode_lookup(base, dentry, nd);
-               if (IS_ERR(dentry))
-                       return dentry;
-       }
-
-       if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) {
-               int status = d_revalidate(dentry, nd);
-               if (unlikely(status <= 0)) {
-                       /*
-                        * The dentry failed validation.
-                        * If d_revalidate returned 0 attempt to invalidate
-                        * the dentry otherwise d_revalidate is asking us
-                        * to return a fail status.
-                        */
-                       if (status < 0) {
-                               dput(dentry);
-                               return ERR_PTR(status);
-                       } else if (!d_invalidate(dentry)) {
-                               dput(dentry);
-                               dentry = NULL;
-                       }
-               }
-       }
-
-       if (!dentry)
-               dentry = d_alloc_and_lookup(base, name, nd);
-
-       return dentry;
-}
-
 /*
  * Restricted form of lookup. Doesn't follow links, single-component only,
  * needs parent already locked. Doesn't follow mounts.
@@ -1924,6 +1851,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
 {
        struct qstr this;
        unsigned int c;
+       int err;
 
        WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
 
@@ -1948,6 +1876,10 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
                        return ERR_PTR(err);
        }
 
+       err = inode_permission(base->d_inode, MAY_EXEC);
+       if (err)
+               return ERR_PTR(err);
+
        return __lookup_hash(&this, base, NULL);
 }
 
@@ -2015,6 +1947,26 @@ other_userns:
 }
 
 /*
+ * Do the directory specific tests of inode_permission() and call the
+ * may_delete inode operation.  The may_delete inode operation must do the
+ * sticky check when needed.
+ */
+static int may_delete_iop(struct inode *dir, struct inode *inode, int replace)
+{
+       int error;
+
+       if (IS_RDONLY(dir))
+               return -EROFS;
+       if (IS_IMMUTABLE(dir))
+               return -EACCES;
+       error = dir->i_op->may_delete(dir, inode, replace);
+       if (!error)
+               error = security_inode_permission(dir, MAY_WRITE | MAY_EXEC);
+
+       return error;
+}
+
+/*
  *     Check whether we can remove a link victim from directory dir, check
  *  whether the type of victim is right.
  *  1. We can't do it if dir is read-only (done in permission())
@@ -2033,7 +1985,8 @@ other_userns:
  * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
  *     nfs_async_unlink().
  */
-static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct inode *dir, struct dentry *victim,
+                     int isdir, int replace)
 {
        int error;
 
@@ -2042,14 +1995,19 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
 
        BUG_ON(victim->d_parent->d_inode != dir);
        audit_inode_child(victim, dir);
-
-       error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+       if (dir->i_op->may_delete)
+               error = may_delete_iop(dir, victim->d_inode, replace);
+       else {
+               error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+               if (!error && check_sticky(dir, victim->d_inode))
+                       error = -EPERM;
+       }
        if (error)
                return error;
        if (IS_APPEND(dir))
                return -EPERM;
-       if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
-           IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
+       if (IS_APPEND(victim->d_inode) || IS_IMMUTABLE(victim->d_inode) ||
+               IS_SWAPFILE(victim->d_inode))
                return -EPERM;
        if (isdir) {
                if (!S_ISDIR(victim->d_inode->i_mode))
@@ -2065,6 +2023,25 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
        return 0;
 }
 
+/*
+ * Do the directory specific tests of inode_permission() and call the
+ * may_create inode operation.
+ */
+static int may_create_iop(struct inode *dir, int isdir)
+{
+       int error;
+
+       if (IS_RDONLY(dir))
+               return -EROFS;
+       if (IS_IMMUTABLE(dir))
+               return -EACCES;
+       error = dir->i_op->may_create(dir, isdir);
+       if (!error)
+               error = security_inode_permission(dir, MAY_WRITE | MAY_EXEC);
+
+       return error;
+}
+
 /*     Check whether we can create an object with dentry child in directory
  *  dir.
  *  1. We can't do it if child already exists (open has special treatment for
@@ -2073,13 +2050,16 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
  *  3. We should have write and exec permissions on dir
  *  4. We can't do it if dir is immutable (done in permission())
  */
-static inline int may_create(struct inode *dir, struct dentry *child)
+static inline int may_create(struct inode *dir, struct dentry *child, int isdir)
 {
        if (child->d_inode)
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
-       return inode_permission(dir, MAY_WRITE | MAY_EXEC);
+       if (dir->i_op->may_create)
+               return may_create_iop(dir, isdir);
+       else
+               return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 }
 
 /*
@@ -2127,7 +2107,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
 int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
                struct nameidata *nd)
 {
-       int error = may_create(dir, dentry);
+       int error = may_create(dir, dentry, 0);
 
        if (error)
                return error;
@@ -2326,7 +2306,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        /* Negative dentry, just create the file */
        if (!dentry->d_inode) {
                umode_t mode = op->mode;
-               if (!IS_POSIXACL(dir->d_inode))
+               if (!IS_ACL(dir->d_inode))
                        mode &= ~current_umask();
                /*
                 * This write is needed to ensure that a
@@ -2594,7 +2574,7 @@ EXPORT_SYMBOL(user_path_create);
 
 int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
-       int error = may_create(dir, dentry);
+       int error = may_create(dir, dentry, 0);
 
        if (error)
                return error;
@@ -2651,7 +2631,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       if (!IS_POSIXACL(path.dentry->d_inode))
+       if (!IS_ACL(path.dentry->d_inode))
                mode &= ~current_umask();
        error = may_mknod(mode);
        if (error)
@@ -2691,7 +2671,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
 
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
-       int error = may_create(dir, dentry);
+       int error = may_create(dir, dentry, 1);
        unsigned max_links = dir->i_sb->s_max_links;
 
        if (error)
@@ -2724,7 +2704,7 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode)
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       if (!IS_POSIXACL(path.dentry->d_inode))
+       if (!IS_ACL(path.dentry->d_inode))
                mode &= ~current_umask();
        error = mnt_want_write(path.mnt);
        if (error)
@@ -2749,7 +2729,7 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
 
 /*
  * The dentry_unhash() helper will try to drop the dentry early: we
- * should have a usage count of 2 if we're the only user of this
+ * should have a usage count of 1 if we're the only user of this
  * dentry, and if that is true (possibly after pruning the dcache),
  * then we drop the dentry now.
  *
@@ -2773,7 +2753,7 @@ void dentry_unhash(struct dentry *dentry)
 
 int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       int error = may_delete(dir, dentry, 1);
+       int error = may_delete(dir, dentry, 1, 0);
 
        if (error)
                return error;
@@ -2868,7 +2848,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
 
 int vfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       int error = may_delete(dir, dentry, 0);
+       int error = may_delete(dir, dentry, 0, 0);
 
        if (error)
                return error;
@@ -2977,7 +2957,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname)
 
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 {
-       int error = may_create(dir, dentry);
+       int error = may_create(dir, dentry, 0);
 
        if (error)
                return error;
@@ -3044,7 +3024,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
        if (!inode)
                return -ENOENT;
 
-       error = may_create(dir, new_dentry);
+       error = may_create(dir, new_dentry, S_ISDIR(inode->i_mode));
        if (error)
                return error;
 
@@ -3272,14 +3252,14 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (old_dentry->d_inode == new_dentry->d_inode)
                return 0;
  
-       error = may_delete(old_dir, old_dentry, is_dir);
+       error = may_delete(old_dir, old_dentry, is_dir, 0);
        if (error)
                return error;
 
        if (!new_dentry->d_inode)
-               error = may_create(new_dir, new_dentry);
+               error = may_create(new_dir, new_dentry, is_dir);
        else
-               error = may_delete(new_dir, new_dentry, is_dir);
+               error = may_delete(new_dir, new_dentry, is_dir, 1);
        if (error)
                return error;