ath10k: Remove qca98xx hw1.0 support
[cascardo/linux.git] / fs / namei.c
index 9ed9361..8b61d10 100644 (file)
@@ -1352,7 +1352,7 @@ static int lookup_fast(struct nameidata *nd,
         */
        if (nd->flags & LOOKUP_RCU) {
                unsigned seq;
-               dentry = __d_lookup_rcu(parent, &nd->last, &seq, nd->inode);
+               dentry = __d_lookup_rcu(parent, &nd->last, &seq);
                if (!dentry)
                        goto unlazy;
 
@@ -1787,8 +1787,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        struct dentry *parent = nd->path.dentry;
                        nd->flags &= ~LOOKUP_JUMPED;
                        if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
-                               err = parent->d_op->d_hash(parent, nd->inode,
-                                                          &this);
+                               err = parent->d_op->d_hash(parent, &this);
                                if (err < 0)
                                        break;
                        }
@@ -2121,7 +2120,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
         * to use its own hash..
         */
        if (base->d_flags & DCACHE_OP_HASH) {
-               int err = base->d_op->d_hash(base, base->d_inode, &this);
+               int err = base->d_op->d_hash(base, &this);
                if (err < 0)
                        return ERR_PTR(err);
        }
@@ -2690,28 +2689,10 @@ static int do_last(struct nameidata *nd, struct path *path,
        nd->flags &= ~LOOKUP_PARENT;
        nd->flags |= op->intent;
 
-       switch (nd->last_type) {
-       case LAST_DOTDOT:
-       case LAST_DOT:
+       if (nd->last_type != LAST_NORM) {
                error = handle_dots(nd, nd->last_type);
                if (error)
                        return error;
-               /* fallthrough */
-       case LAST_ROOT:
-               error = complete_walk(nd);
-               if (error)
-                       return error;
-               audit_inode(name, nd->path.dentry, 0);
-               if (open_flag & O_CREAT) {
-                       error = -EISDIR;
-                       goto out;
-               }
-               goto finish_open;
-       case LAST_BIND:
-               error = complete_walk(nd);
-               if (error)
-                       return error;
-               audit_inode(name, dir, 0);
                goto finish_open;
        }
 
@@ -2841,19 +2822,19 @@ finish_lookup:
        }
        nd->inode = inode;
        /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
+finish_open:
        error = complete_walk(nd);
        if (error) {
                path_put(&save_parent);
                return error;
        }
+       audit_inode(name, nd->path.dentry, 0);
        error = -EISDIR;
        if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
                goto out;
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode))
                goto out;
-       audit_inode(name, nd->path.dentry, 0);
-finish_open:
        if (!S_ISREG(nd->inode->i_mode))
                will_truncate = false;
 
@@ -2920,6 +2901,67 @@ stale_open:
        goto retry_lookup;
 }
 
+static int do_tmpfile(int dfd, struct filename *pathname,
+               struct nameidata *nd, int flags,
+               const struct open_flags *op,
+               struct file *file, int *opened)
+{
+       static const struct qstr name = QSTR_INIT("/", 1);
+       struct dentry *dentry, *child;
+       struct inode *dir;
+       int error = path_lookupat(dfd, pathname->name,
+                                 flags | LOOKUP_DIRECTORY, nd);
+       if (unlikely(error))
+               return error;
+       error = mnt_want_write(nd->path.mnt);
+       if (unlikely(error))
+               goto out;
+       /* we want directory to be writable */
+       error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC);
+       if (error)
+               goto out2;
+       dentry = nd->path.dentry;
+       dir = dentry->d_inode;
+       if (!dir->i_op->tmpfile) {
+               error = -EOPNOTSUPP;
+               goto out2;
+       }
+       child = d_alloc(dentry, &name);
+       if (unlikely(!child)) {
+               error = -ENOMEM;
+               goto out2;
+       }
+       nd->flags &= ~LOOKUP_DIRECTORY;
+       nd->flags |= op->intent;
+       dput(nd->path.dentry);
+       nd->path.dentry = child;
+       error = dir->i_op->tmpfile(dir, nd->path.dentry, op->mode);
+       if (error)
+               goto out2;
+       audit_inode(pathname, nd->path.dentry, 0);
+       error = may_open(&nd->path, op->acc_mode, op->open_flag);
+       if (error)
+               goto out2;
+       file->f_path.mnt = nd->path.mnt;
+       error = finish_open(file, nd->path.dentry, NULL, opened);
+       if (error)
+               goto out2;
+       error = open_check_o_direct(file);
+       if (error) {
+               fput(file);
+       } else if (!(op->open_flag & O_EXCL)) {
+               struct inode *inode = file_inode(file);
+               spin_lock(&inode->i_lock);
+               inode->i_state |= I_LINKABLE;
+               spin_unlock(&inode->i_lock);
+       }
+out2:
+       mnt_drop_write(nd->path.mnt);
+out:
+       path_put(&nd->path);
+       return error;
+}
+
 static struct file *path_openat(int dfd, struct filename *pathname,
                struct nameidata *nd, const struct open_flags *op, int flags)
 {
@@ -2935,6 +2977,11 @@ static struct file *path_openat(int dfd, struct filename *pathname,
 
        file->f_flags = op->open_flag;
 
+       if (unlikely(file->f_flags & __O_TMPFILE)) {
+               error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
+               goto out;
+       }
+
        error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);
        if (unlikely(error))
                goto out;
@@ -2987,9 +3034,10 @@ out:
 }
 
 struct file *do_filp_open(int dfd, struct filename *pathname,
-               const struct open_flags *op, int flags)
+               const struct open_flags *op)
 {
        struct nameidata nd;
+       int flags = op->lookup_flags;
        struct file *filp;
 
        filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
@@ -3001,17 +3049,16 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
 }
 
 struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
-               const char *name, const struct open_flags *op, int flags)
+               const char *name, const struct open_flags *op)
 {
        struct nameidata nd;
        struct file *file;
        struct filename filename = { .name = name };
+       int flags = op->lookup_flags | LOOKUP_ROOT;
 
        nd.root.mnt = mnt;
        nd.root.dentry = dentry;
 
-       flags |= LOOKUP_ROOT;
-
        if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
                return ERR_PTR(-ELOOP);
 
@@ -3586,12 +3633,18 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 
        mutex_lock(&inode->i_mutex);
        /* Make sure we don't allow creating hardlink to an unlinked file */
-       if (inode->i_nlink == 0)
+       if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
                error =  -ENOENT;
        else if (max_links && inode->i_nlink >= max_links)
                error = -EMLINK;
        else
                error = dir->i_op->link(old_dentry, dir, new_dentry);
+
+       if (!error && (inode->i_state & I_LINKABLE)) {
+               spin_lock(&inode->i_lock);
+               inode->i_state &= ~I_LINKABLE;
+               spin_unlock(&inode->i_lock);
+       }
        mutex_unlock(&inode->i_mutex);
        if (!error)
                fsnotify_link(dir, inode, new_dentry);