]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/namei.c
iw_cxgb4: do not send RX_DATA_ACK CPLs after close/abort
[mirror_ubuntu-artful-kernel.git] / fs / namei.c
index 5d31f0b2006d40772f482f2b493ccb966ef52e05..ad74877e1442c0c9ea5fca87b065e59090088b10 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/hash.h>
 #include <linux/bitops.h>
 #include <linux/init_task.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "internal.h"
 #include "mount.h"
@@ -1200,7 +1200,7 @@ static int follow_managed(struct path *path, struct nameidata *nd)
                if (managed & DCACHE_MANAGE_TRANSIT) {
                        BUG_ON(!path->dentry->d_op);
                        BUG_ON(!path->dentry->d_op->d_manage);
-                       ret = path->dentry->d_op->d_manage(path->dentry, false);
+                       ret = path->dentry->d_op->d_manage(path, false);
                        if (ret < 0)
                                break;
                }
@@ -1263,10 +1263,10 @@ int follow_down_one(struct path *path)
 }
 EXPORT_SYMBOL(follow_down_one);
 
-static inline int managed_dentry_rcu(struct dentry *dentry)
+static inline int managed_dentry_rcu(const struct path *path)
 {
-       return (dentry->d_flags & DCACHE_MANAGE_TRANSIT) ?
-               dentry->d_op->d_manage(dentry, true) : 0;
+       return (path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) ?
+               path->dentry->d_op->d_manage(path, true) : 0;
 }
 
 /*
@@ -1282,7 +1282,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                 * Don't forget we might have a non-mountpoint managed dentry
                 * that wants to block transit.
                 */
-               switch (managed_dentry_rcu(path->dentry)) {
+               switch (managed_dentry_rcu(path)) {
                case -ECHILD:
                default:
                        return false;
@@ -1392,8 +1392,7 @@ int follow_down(struct path *path)
                if (managed & DCACHE_MANAGE_TRANSIT) {
                        BUG_ON(!path->dentry->d_op);
                        BUG_ON(!path->dentry->d_op->d_manage);
-                       ret = path->dentry->d_op->d_manage(
-                               path->dentry, false);
+                       ret = path->dentry->d_op->d_manage(path, false);
                        if (ret < 0)
                                return ret == -EISDIR ? 0 : ret;
                }
@@ -1725,7 +1724,7 @@ static int pick_link(struct nameidata *nd, struct path *link,
        return 1;
 }
 
-enum {WALK_GET = 1, WALK_MORE = 2};
+enum {WALK_FOLLOW = 1, WALK_MORE = 2};
 
 /*
  * Do we need to follow links? We _really_ want to be able
@@ -1733,22 +1732,25 @@ enum {WALK_GET = 1, WALK_MORE = 2};
  * so we keep a cache of "no, this doesn't need follow_link"
  * for the common case.
  */
-static inline int should_follow_link(struct nameidata *nd, struct path *link,
-                                    int flags,
-                                    struct inode *inode, unsigned seq)
+static inline int step_into(struct nameidata *nd, struct path *path,
+                           int flags, struct inode *inode, unsigned seq)
 {
        if (!(flags & WALK_MORE) && nd->depth)
                put_link(nd);
-       if (likely(!d_is_symlink(link->dentry)))
-               return 0;
-       if (!(flags & WALK_GET) && !(nd->flags & LOOKUP_FOLLOW))
+       if (likely(!d_is_symlink(path->dentry)) ||
+          !(flags & WALK_FOLLOW || nd->flags & LOOKUP_FOLLOW)) {
+               /* not a symlink or should not follow */
+               path_to_nameidata(path, nd);
+               nd->inode = inode;
+               nd->seq = seq;
                return 0;
+       }
        /* make sure that d_is_symlink above matches inode */
        if (nd->flags & LOOKUP_RCU) {
-               if (read_seqcount_retry(&link->dentry->d_seq, seq))
+               if (read_seqcount_retry(&path->dentry->d_seq, seq))
                        return -ECHILD;
        }
-       return pick_link(nd, link, inode, seq);
+       return pick_link(nd, path, inode, seq);
 }
 
 static int walk_component(struct nameidata *nd, int flags)
@@ -1791,13 +1793,7 @@ static int walk_component(struct nameidata *nd, int flags)
                inode = d_backing_inode(path.dentry);
        }
 
-       err = should_follow_link(nd, &path, flags, inode, seq);
-       if (unlikely(err))
-               return err;
-       path_to_nameidata(&path, nd);
-       nd->inode = inode;
-       nd->seq = seq;
-       return 0;
+       return step_into(nd, &path, flags, inode, seq);
 }
 
 /*
@@ -2104,10 +2100,10 @@ OK:
                        if (!name)
                                return 0;
                        /* last component of nested symlink */
-                       err = walk_component(nd, WALK_GET);
+                       err = walk_component(nd, WALK_FOLLOW);
                } else {
                        /* not the last component */
-                       err = walk_component(nd, WALK_GET | WALK_MORE);
+                       err = walk_component(nd, WALK_FOLLOW | WALK_MORE);
                }
                if (err < 0)
                        return err;
@@ -2617,12 +2613,7 @@ mountpoint_last(struct nameidata *nd)
                return -ENOENT;
        }
        path.mnt = nd->path.mnt;
-       error = should_follow_link(nd, &path, 0,
-                                  d_backing_inode(path.dentry), 0);
-       if (unlikely(error))
-               return error;
-       path_to_nameidata(&path, nd);
-       return 0;
+       return step_into(nd, &path, 0, d_backing_inode(path.dentry), 0);
 }
 
 /**
@@ -2871,7 +2862,7 @@ bool may_open_dev(const struct path *path)
                !(path->mnt->mnt_sb->s_iflags & SB_I_NODEV);
 }
 
-static int may_open(struct path *path, int acc_mode, int flag)
+static int may_open(const struct path *path, int acc_mode, int flag)
 {
        struct dentry *dentry = path->dentry;
        struct inode *inode = dentry->d_inode;
@@ -2921,7 +2912,7 @@ static int may_open(struct path *path, int acc_mode, int flag)
 
 static int handle_truncate(struct file *filp)
 {
-       struct path *path = &filp->f_path;
+       const struct path *path = &filp->f_path;
        struct inode *inode = path->dentry->d_inode;
        int error = get_write_access(inode);
        if (error)
@@ -3311,15 +3302,11 @@ static int do_last(struct nameidata *nd,
        seq = 0;        /* out of RCU mode, so the value doesn't matter */
        inode = d_backing_inode(path.dentry);
 finish_lookup:
-       error = should_follow_link(nd, &path, 0, inode, seq);
+       error = step_into(nd, &path, 0, inode, seq);
        if (unlikely(error))
                return error;
-
-       path_to_nameidata(&path, nd);
-       nd->inode = inode;
-       nd->seq = seq;
-       /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
 finish_open:
+       /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
        error = complete_walk(nd);
        if (error)
                return error;
@@ -4318,11 +4305,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        bool new_is_dir = false;
        unsigned max_links = new_dir->i_sb->s_max_links;
 
-       /*
-        * Check source == target.
-        * On overlayfs need to look at underlying inodes.
-        */
-       if (d_real_inode(old_dentry) == d_real_inode(new_dentry))
+       if (source == target)
                return 0;
 
        error = may_delete(old_dir, old_dentry, is_dir);
@@ -4623,7 +4606,8 @@ out:
  * have ->get_link() not calling nd_jump_link().  Using (or not using) it
  * for any given inode is up to filesystem.
  */
-int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+static int generic_readlink(struct dentry *dentry, char __user *buffer,
+                           int buflen)
 {
        DEFINE_DELAYED_CALL(done);
        struct inode *inode = d_inode(dentry);
@@ -4639,7 +4623,36 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
        do_delayed_call(&done);
        return res;
 }
-EXPORT_SYMBOL(generic_readlink);
+
+/**
+ * vfs_readlink - copy symlink body into userspace buffer
+ * @dentry: dentry on which to get symbolic link
+ * @buffer: user memory pointer
+ * @buflen: size of buffer
+ *
+ * Does not touch atime.  That's up to the caller if necessary
+ *
+ * Does not call security hook.
+ */
+int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+{
+       struct inode *inode = d_inode(dentry);
+
+       if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) {
+               if (unlikely(inode->i_op->readlink))
+                       return inode->i_op->readlink(dentry, buffer, buflen);
+
+               if (!d_is_symlink(dentry))
+                       return -EINVAL;
+
+               spin_lock(&inode->i_lock);
+               inode->i_opflags |= IOP_DEFAULT_READLINK;
+               spin_unlock(&inode->i_lock);
+       }
+
+       return generic_readlink(dentry, buffer, buflen);
+}
+EXPORT_SYMBOL(vfs_readlink);
 
 /**
  * vfs_get_link - get symlink body
@@ -4756,7 +4769,6 @@ int page_symlink(struct inode *inode, const char *symname, int len)
 EXPORT_SYMBOL(page_symlink);
 
 const struct inode_operations page_symlink_inode_operations = {
-       .readlink       = generic_readlink,
        .get_link       = page_get_link,
 };
 EXPORT_SYMBOL(page_symlink_inode_operations);