Revert "input: touch: raydium: V61.7 code drop"
[linux-3.10.git] / fs / namei.c
index 6868699..cccaf77 100644 (file)
@@ -451,7 +451,7 @@ int inode_permission(struct inode *inode, int mask)
  *
  * Given a path increment the reference count to the dentry and the vfsmount.
  */
-void path_get(struct path *path)
+void path_get(const struct path *path)
 {
        mntget(path->mnt);
        dget(path->dentry);
@@ -464,7 +464,7 @@ EXPORT_SYMBOL(path_get);
  *
  * Given a path decrement the reference count to the dentry and the vfsmount.
  */
-void path_put(struct path *path)
+void path_put(const struct path *path)
 {
        dput(path->dentry);
        mntput(path->mnt);
@@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd)
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
                return 0;
 
-       if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
+       if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
                return 0;
 
-       if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
-               return 0;
-
-       /* Note: we do not d_invalidate() */
-       status = d_revalidate(dentry, nd->flags);
+       status = dentry->d_op->d_weak_revalidate(dentry, nd->flags);
        if (status > 0)
                return 0;
 
@@ -693,8 +689,6 @@ void nd_jump_link(struct nameidata *nd, struct path *path)
        nd->path = *path;
        nd->inode = nd->path.dentry->d_inode;
        nd->flags |= LOOKUP_JUMPED;
-
-       BUG_ON(nd->inode->i_op->follow_link);
 }
 
 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
@@ -1342,7 +1336,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
  *  small and for now I'd prefer to have fast path as straight as possible.
  *  It _is_ time-critical.
  */
-static int lookup_fast(struct nameidata *nd, struct qstr *name,
+static int lookup_fast(struct nameidata *nd,
                       struct path *path, struct inode **inode)
 {
        struct vfsmount *mnt = nd->path.mnt;
@@ -1358,7 +1352,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name,
         */
        if (nd->flags & LOOKUP_RCU) {
                unsigned seq;
-               dentry = __d_lookup_rcu(parent, name, &seq, nd->inode);
+               dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode);
                if (!dentry)
                        goto unlazy;
 
@@ -1400,7 +1394,7 @@ unlazy:
                if (unlazy_walk(nd, dentry))
                        return -ECHILD;
        } else {
-               dentry = __d_lookup(parent, name);
+               dentry = __d_lookup(parent, &nd->last);
        }
 
        if (unlikely(!dentry))
@@ -1436,8 +1430,7 @@ need_lookup:
 }
 
 /* Fast lookup failed, do it the slow way */
-static int lookup_slow(struct nameidata *nd, struct qstr *name,
-                      struct path *path)
+static int lookup_slow(struct nameidata *nd, struct path *path)
 {
        struct dentry *dentry, *parent;
        int err;
@@ -1446,7 +1439,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name,
        BUG_ON(nd->inode != parent->d_inode);
 
        mutex_lock(&parent->d_inode->i_mutex);
-       dentry = __lookup_hash(name, parent, nd->flags);
+       dentry = __lookup_hash(&nd->last, parent, nd->flags);
        mutex_unlock(&parent->d_inode->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
@@ -1519,7 +1512,7 @@ static inline int should_follow_link(struct inode *inode, int follow)
 }
 
 static inline int walk_component(struct nameidata *nd, struct path *path,
-               struct qstr *name, int type, int follow)
+               int follow)
 {
        struct inode *inode;
        int err;
@@ -1528,14 +1521,14 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
         * to be able to know about the current root directory and
         * parent relationships.
         */
-       if (unlikely(type != LAST_NORM))
-               return handle_dots(nd, type);
-       err = lookup_fast(nd, name, path, &inode);
+       if (unlikely(nd->last_type != LAST_NORM))
+               return handle_dots(nd, nd->last_type);
+       err = lookup_fast(nd, path, &inode);
        if (unlikely(err)) {
                if (err < 0)
                        goto out_err;
 
-               err = lookup_slow(nd, name, path);
+               err = lookup_slow(nd, path);
                if (err < 0)
                        goto out_err;
 
@@ -1594,8 +1587,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
                res = follow_link(&link, nd, &cookie);
                if (res)
                        break;
-               res = walk_component(nd, path, &nd->last,
-                                    nd->last_type, LOOKUP_FOLLOW);
+               res = walk_component(nd, path, LOOKUP_FOLLOW);
                put_link(nd, &link, cookie);
        } while (res > 0);
 
@@ -1802,8 +1794,11 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        }
                }
 
+               nd->last = this;
+               nd->last_type = type;
+
                if (!name[len])
-                       goto last_component;
+                       return 0;
                /*
                 * If it wasn't NUL, we know it was '/'. Skip that
                 * slash, and continue until no more slashes.
@@ -1812,10 +1807,11 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        len++;
                } while (unlikely(name[len] == '/'));
                if (!name[len])
-                       goto last_component;
+                       return 0;
+
                name += len;
 
-               err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
+               err = walk_component(nd, &next, LOOKUP_FOLLOW);
                if (err < 0)
                        return err;
 
@@ -1824,16 +1820,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        if (err)
                                return err;
                }
-               if (can_lookup(nd->inode))
-                       continue;
-               err = -ENOTDIR; 
-               break;
-               /* here ends the main loop */
-
-last_component:
-               nd->last = this;
-               nd->last_type = type;
-               return 0;
+               if (!can_lookup(nd->inode)) {
+                       err = -ENOTDIR; 
+                       break;
+               }
        }
        terminate_walk(nd);
        return err;
@@ -1932,8 +1922,7 @@ static inline int lookup_last(struct nameidata *nd, struct path *path)
                nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 
        nd->flags &= ~LOOKUP_PARENT;
-       return walk_component(nd, path, &nd->last, nd->last_type,
-                                       nd->flags & LOOKUP_FOLLOW);
+       return walk_component(nd, path, nd->flags & LOOKUP_FOLLOW);
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
@@ -1987,7 +1976,7 @@ static int path_lookupat(int dfd, const char *name,
                err = complete_walk(nd);
 
        if (!err && nd->flags & LOOKUP_DIRECTORY) {
-               if (!nd->inode->i_op->lookup) {
+               if (!can_lookup(nd->inode)) {
                        path_put(&nd->path);
                        err = -ENOTDIR;
                }
@@ -2175,15 +2164,19 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
  *     path-walking is complete.
  */
 static struct filename *
-user_path_parent(int dfd, const char __user *path, struct nameidata *nd)
+user_path_parent(int dfd, const char __user *path, struct nameidata *nd,
+                unsigned int flags)
 {
        struct filename *s = getname(path);
        int error;
 
+       /* only LOOKUP_REVAL is allowed in extra flags */
+       flags &= LOOKUP_REVAL;
+
        if (IS_ERR(s))
                return s;
 
-       error = filename_lookup(dfd, s, LOOKUP_PARENT, nd);
+       error = filename_lookup(dfd, s, flags | LOOKUP_PARENT, nd);
        if (error) {
                putname(s);
                return ERR_PTR(error);
@@ -2270,6 +2263,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
  */
 static inline int may_create(struct inode *dir, struct dentry *child)
 {
+       audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
        if (child->d_inode)
                return -EEXIST;
        if (IS_DEADDIR(dir))
@@ -2728,7 +2722,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
                        symlink_ok = true;
                /* we _can_ be in RCU mode here */
-               error = lookup_fast(nd, &nd->last, path, &inode);
+               error = lookup_fast(nd, path, &inode);
                if (likely(!error))
                        goto finish_lookup;
 
@@ -2747,7 +2741,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                if (error)
                        return error;
 
-               audit_inode(name, dir, 0);
+               audit_inode(name, dir, LOOKUP_PARENT);
                error = -EISDIR;
                /* trailing slashes? */
                if (nd->last.name[nd->last.len])
@@ -2774,7 +2768,7 @@ retry_lookup:
                        goto out;
 
                if ((*opened & FILE_CREATED) ||
-                   !S_ISREG(file->f_path.dentry->d_inode->i_mode))
+                   !S_ISREG(file_inode(file)->i_mode))
                        will_truncate = false;
 
                audit_inode(name, file->f_path.dentry, 0);
@@ -2857,7 +2851,7 @@ finish_lookup:
        if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
                goto out;
        error = -ENOTDIR;
-       if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
+       if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode))
                goto out;
        audit_inode(name, nd->path.dentry, 0);
 finish_open:
@@ -2937,8 +2931,8 @@ static struct file *path_openat(int dfd, struct filename *pathname,
        int error;
 
        file = get_empty_filp();
-       if (!file)
-               return ERR_PTR(-ENFILE);
+       if (IS_ERR(file))
+               return file;
 
        file->f_flags = op->open_flag;
 
@@ -3335,8 +3329,9 @@ static long do_rmdir(int dfd, const char __user *pathname)
        struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
-
-       name = user_path_parent(dfd, pathname, &nd);
+       unsigned int lookup_flags = 0;
+retry:
+       name = user_path_parent(dfd, pathname, &nd, lookup_flags);
        if (IS_ERR(name))
                return PTR_ERR(name);
 
@@ -3378,6 +3373,10 @@ exit2:
 exit1:
        path_put(&nd.path);
        putname(name);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
        return error;
 }
 
@@ -3431,8 +3430,9 @@ static long do_unlinkat(int dfd, const char __user *pathname)
        struct dentry *dentry;
        struct nameidata nd;
        struct inode *inode = NULL;
-
-       name = user_path_parent(dfd, pathname, &nd);
+       unsigned int lookup_flags = 0;
+retry:
+       name = user_path_parent(dfd, pathname, &nd, lookup_flags);
        if (IS_ERR(name))
                return PTR_ERR(name);
 
@@ -3470,6 +3470,11 @@ exit2:
 exit1:
        path_put(&nd.path);
        putname(name);
+       if (retry_estale(error, lookup_flags)) {
+               lookup_flags |= LOOKUP_REVAL;
+               inode = NULL;
+               goto retry;
+       }
        return error;
 
 slashes:
@@ -3825,15 +3830,17 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
        struct nameidata oldnd, newnd;
        struct filename *from;
        struct filename *to;
+       unsigned int lookup_flags = 0;
+       bool should_retry = false;
        int error;
-
-       from = user_path_parent(olddfd, oldname, &oldnd);
+retry:
+       from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
        if (IS_ERR(from)) {
                error = PTR_ERR(from);
                goto exit;
        }
 
-       to = user_path_parent(newdfd, newname, &newnd);
+       to = user_path_parent(newdfd, newname, &newnd, lookup_flags);
        if (IS_ERR(to)) {
                error = PTR_ERR(to);
                goto exit1;
@@ -3905,11 +3912,18 @@ exit3:
        unlock_rename(new_dir, old_dir);
        mnt_drop_write(oldnd.path.mnt);
 exit2:
+       if (retry_estale(error, lookup_flags))
+               should_retry = true;
        path_put(&newnd.path);
        putname(to);
 exit1:
        path_put(&oldnd.path);
        putname(from);
+       if (should_retry) {
+               should_retry = false;
+               lookup_flags |= LOOKUP_REVAL;
+               goto retry;
+       }
 exit:
        return error;
 }