md/raid5: Replace deprecated CPU-hotplug functions.
[linux-2.6-microblaze.git] / fs / namei.c
index 48a2f28..bf6d8a7 100644 (file)
@@ -554,7 +554,7 @@ struct nameidata {
        struct qstr     last;
        struct path     root;
        struct inode    *inode; /* path.dentry.d_inode */
-       unsigned int    flags;
+       unsigned int    flags, state;
        unsigned        seq, m_seq, r_seq;
        int             last_type;
        unsigned        depth;
@@ -573,10 +573,15 @@ struct nameidata {
        umode_t         dir_mode;
 } __randomize_layout;
 
-static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
+#define ND_ROOT_PRESET 1
+#define ND_ROOT_GRABBED 2
+#define ND_JUMPED 4
+
+static void __set_nameidata(struct nameidata *p, int dfd, struct filename *name)
 {
        struct nameidata *old = current->nameidata;
        p->stack = p->internal;
+       p->depth = 0;
        p->dfd = dfd;
        p->name = name;
        p->path.mnt = NULL;
@@ -586,6 +591,17 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
        current->nameidata = p;
 }
 
+static inline void set_nameidata(struct nameidata *p, int dfd, struct filename *name,
+                         const struct path *root)
+{
+       __set_nameidata(p, dfd, name);
+       p->state = 0;
+       if (unlikely(root)) {
+               p->state = ND_ROOT_PRESET;
+               p->root = *root;
+       }
+}
+
 static void restore_nameidata(void)
 {
        struct nameidata *now = current->nameidata, *old = now->saved;
@@ -645,9 +661,9 @@ static void terminate_walk(struct nameidata *nd)
                path_put(&nd->path);
                for (i = 0; i < nd->depth; i++)
                        path_put(&nd->stack[i].link);
-               if (nd->flags & LOOKUP_ROOT_GRABBED) {
+               if (nd->state & ND_ROOT_GRABBED) {
                        path_put(&nd->root);
-                       nd->flags &= ~LOOKUP_ROOT_GRABBED;
+                       nd->state &= ~ND_ROOT_GRABBED;
                }
        } else {
                nd->flags &= ~LOOKUP_RCU;
@@ -710,9 +726,9 @@ static bool legitimize_root(struct nameidata *nd)
        if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED))
                return false;
        /* Nothing to do if nd->root is zero or is managed by the VFS user. */
-       if (!nd->root.mnt || (nd->flags & LOOKUP_ROOT))
+       if (!nd->root.mnt || (nd->state & ND_ROOT_PRESET))
                return true;
-       nd->flags |= LOOKUP_ROOT_GRABBED;
+       nd->state |= ND_ROOT_GRABBED;
        return legitimize_path(nd, &nd->root, nd->root_seq);
 }
 
@@ -849,8 +865,9 @@ static int complete_walk(struct nameidata *nd)
                 * We don't want to zero nd->root for scoped-lookups or
                 * externally-managed nd->root.
                 */
-               if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
-                       nd->root.mnt = NULL;
+               if (!(nd->state & ND_ROOT_PRESET))
+                       if (!(nd->flags & LOOKUP_IS_SCOPED))
+                               nd->root.mnt = NULL;
                nd->flags &= ~LOOKUP_CACHED;
                if (!try_to_unlazy(nd))
                        return -ECHILD;
@@ -877,7 +894,7 @@ static int complete_walk(struct nameidata *nd)
                        return -EXDEV;
        }
 
-       if (likely(!(nd->flags & LOOKUP_JUMPED)))
+       if (likely(!(nd->state & ND_JUMPED)))
                return 0;
 
        if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
@@ -915,7 +932,7 @@ static int set_root(struct nameidata *nd)
                } while (read_seqcount_retry(&fs->seq, seq));
        } else {
                get_fs_root(fs, &nd->root);
-               nd->flags |= LOOKUP_ROOT_GRABBED;
+               nd->state |= ND_ROOT_GRABBED;
        }
        return 0;
 }
@@ -948,7 +965,7 @@ static int nd_jump_root(struct nameidata *nd)
                path_get(&nd->path);
                nd->inode = nd->path.dentry->d_inode;
        }
-       nd->flags |= LOOKUP_JUMPED;
+       nd->state |= ND_JUMPED;
        return 0;
 }
 
@@ -976,7 +993,7 @@ int nd_jump_link(struct path *path)
        path_put(&nd->path);
        nd->path = *path;
        nd->inode = nd->path.dentry->d_inode;
-       nd->flags |= LOOKUP_JUMPED;
+       nd->state |= ND_JUMPED;
        return 0;
 
 err:
@@ -1126,8 +1143,7 @@ int may_linkat(struct user_namespace *mnt_userns, struct path *link)
  *                       should be allowed, or not, on files that already
  *                       exist.
  * @mnt_userns:        user namespace of the mount the inode was found from
- * @dir_mode: mode bits of directory
- * @dir_uid: owner of directory
+ * @nd: nameidata pathwalk data
  * @inode: the inode of the file to open
  *
  * Block an O_CREAT open of a FIFO (or a regular file) when:
@@ -1424,7 +1440,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                        if (mounted) {
                                path->mnt = &mounted->mnt;
                                dentry = path->dentry = mounted->mnt.mnt_root;
-                               nd->flags |= LOOKUP_JUMPED;
+                               nd->state |= ND_JUMPED;
                                *seqp = read_seqcount_begin(&dentry->d_seq);
                                *inode = dentry->d_inode;
                                /*
@@ -1469,7 +1485,7 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
                if (unlikely(nd->flags & LOOKUP_NO_XDEV))
                        ret = -EXDEV;
                else
-                       nd->flags |= LOOKUP_JUMPED;
+                       nd->state |= ND_JUMPED;
        }
        if (unlikely(ret)) {
                dput(path->dentry);
@@ -2220,7 +2236,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        case 2:
                                if (name[1] == '.') {
                                        type = LAST_DOTDOT;
-                                       nd->flags |= LOOKUP_JUMPED;
+                                       nd->state |= ND_JUMPED;
                                }
                                break;
                        case 1:
@@ -2228,7 +2244,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                }
                if (likely(type == LAST_NORM)) {
                        struct dentry *parent = nd->path.dentry;
-                       nd->flags &= ~LOOKUP_JUMPED;
+                       nd->state &= ~ND_JUMPED;
                        if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
                                struct qstr this = { { .hash_len = hash_len }, .name = name };
                                err = parent->d_op->d_hash(parent, &this);
@@ -2302,14 +2318,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
        if (flags & LOOKUP_RCU)
                rcu_read_lock();
 
-       nd->flags = flags | LOOKUP_JUMPED;
-       nd->depth = 0;
+       nd->flags = flags;
+       nd->state |= ND_JUMPED;
 
        nd->m_seq = __read_seqcount_begin(&mount_lock.seqcount);
        nd->r_seq = __read_seqcount_begin(&rename_lock.seqcount);
        smp_rmb();
 
-       if (flags & LOOKUP_ROOT) {
+       if (nd->state & ND_ROOT_PRESET) {
                struct dentry *root = nd->root.dentry;
                struct inode *inode = root->d_inode;
                if (*s && unlikely(!d_can_lookup(root)))
@@ -2384,7 +2400,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
                        nd->root_seq = nd->seq;
                } else {
                        path_get(&nd->root);
-                       nd->flags |= LOOKUP_ROOT_GRABBED;
+                       nd->state |= ND_ROOT_GRABBED;
                }
        }
        return s;
@@ -2423,7 +2439,7 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
                ;
        if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) {
                err = handle_lookup_down(nd);
-               nd->flags &= ~LOOKUP_JUMPED; // no d_weak_revalidate(), please...
+               nd->state &= ~ND_JUMPED; // no d_weak_revalidate(), please...
        }
        if (!err)
                err = complete_walk(nd);
@@ -2447,11 +2463,7 @@ int filename_lookup(int dfd, struct filename *name, unsigned flags,
        struct nameidata nd;
        if (IS_ERR(name))
                return PTR_ERR(name);
-       if (unlikely(root)) {
-               nd.root = *root;
-               flags |= LOOKUP_ROOT;
-       }
-       set_nameidata(&nd, dfd, name);
+       set_nameidata(&nd, dfd, name, root);
        retval = path_lookupat(&nd, flags | LOOKUP_RCU, path);
        if (unlikely(retval == -ECHILD))
                retval = path_lookupat(&nd, flags, path);
@@ -2492,7 +2504,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
 
        if (IS_ERR(name))
                return name;
-       set_nameidata(&nd, dfd, name);
+       set_nameidata(&nd, dfd, name, NULL);
        retval = path_parentat(&nd, flags | LOOKUP_RCU, parent);
        if (unlikely(retval == -ECHILD))
                retval = path_parentat(&nd, flags, parent);
@@ -2825,16 +2837,14 @@ static int may_delete(struct user_namespace *mnt_userns, struct inode *dir,
 static inline int may_create(struct user_namespace *mnt_userns,
                             struct inode *dir, struct dentry *child)
 {
-       struct user_namespace *s_user_ns;
        audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
        if (child->d_inode)
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
-       s_user_ns = dir->i_sb->s_user_ns;
-       if (!kuid_has_mapping(s_user_ns, fsuid_into_mnt(mnt_userns)) ||
-           !kgid_has_mapping(s_user_ns, fsgid_into_mnt(mnt_userns)))
+       if (!fsuidgid_has_mapping(dir->i_sb, mnt_userns))
                return -EOVERFLOW;
+
        return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC);
 }
 
@@ -3036,14 +3046,11 @@ static int may_o_create(struct user_namespace *mnt_userns,
                        const struct path *dir, struct dentry *dentry,
                        umode_t mode)
 {
-       struct user_namespace *s_user_ns;
        int error = security_path_mknod(dir, dentry, mode, 0);
        if (error)
                return error;
 
-       s_user_ns = dir->dentry->d_sb->s_user_ns;
-       if (!kuid_has_mapping(s_user_ns, fsuid_into_mnt(mnt_userns)) ||
-           !kgid_has_mapping(s_user_ns, fsgid_into_mnt(mnt_userns)))
+       if (!fsuidgid_has_mapping(dir->dentry->d_sb, mnt_userns))
                return -EOVERFLOW;
 
        error = inode_permission(mnt_userns, dir->dentry->d_inode,
@@ -3383,7 +3390,7 @@ static int do_open(struct nameidata *nd,
  * @mnt_userns:        user namespace of the mount the inode was found from
  * @dentry:    pointer to dentry of the base directory
  * @mode:      mode of the new tmpfile
- * @open_flags:        flags
+ * @open_flag: flags
  *
  * Create a temporary file.
  *
@@ -3523,7 +3530,7 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
        int flags = op->lookup_flags;
        struct file *filp;
 
-       set_nameidata(&nd, dfd, pathname);
+       set_nameidata(&nd, dfd, pathname, NULL);
        filp = path_openat(&nd, op, flags | LOOKUP_RCU);
        if (unlikely(filp == ERR_PTR(-ECHILD)))
                filp = path_openat(&nd, op, flags);
@@ -3533,25 +3540,22 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
        return filp;
 }
 
-struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
+struct file *do_file_open_root(const struct path *root,
                const char *name, const struct open_flags *op)
 {
        struct nameidata nd;
        struct file *file;
        struct filename *filename;
-       int flags = op->lookup_flags | LOOKUP_ROOT;
-
-       nd.root.mnt = mnt;
-       nd.root.dentry = dentry;
+       int flags = op->lookup_flags;
 
-       if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN)
+       if (d_is_symlink(root->dentry) && op->intent & LOOKUP_OPEN)
                return ERR_PTR(-ELOOP);
 
        filename = getname_kernel(name);
        if (IS_ERR(filename))
                return ERR_CAST(filename);
 
-       set_nameidata(&nd, -1, filename);
+       set_nameidata(&nd, -1, filename, root);
        file = path_openat(&nd, op, flags | LOOKUP_RCU);
        if (unlikely(file == ERR_PTR(-ECHILD)))
                file = path_openat(&nd, op, flags);
@@ -4408,14 +4412,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname
 
 /**
  * vfs_rename - rename a filesystem object
- * @old_mnt_userns:    old user namespace of the mount the inode was found from
- * @old_dir:           parent of source
- * @old_dentry:                source
- * @new_mnt_userns:    new user namespace of the mount the inode was found from
- * @new_dir:           parent of destination
- * @new_dentry:                destination
- * @delegated_inode:   returns an inode needing a delegation break
- * @flags:             rename flags
+ * @rd:                pointer to &struct renamedata info
  *
  * The caller must hold multiple mutexes--see lock_rename()).
  *