vfs: open inside ->tmpfile()
authorMiklos Szeredi <mszeredi@redhat.com>
Sat, 24 Sep 2022 05:00:00 +0000 (07:00 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Sat, 24 Sep 2022 05:00:00 +0000 (07:00 +0200)
This is in preparation for adding tmpfile support to fuse, which requires
that the tmpfile creation and opening are done as a single operation.

Replace the 'struct dentry *' argument of i_op->tmpfile with
'struct file *'.

Call finish_open_simple() as the last thing in ->tmpfile() instances (may
be omitted in the error case).

Change d_tmpfile() argument to 'struct file *' as well to make callers more
readable.

Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
19 files changed:
Documentation/filesystems/locking.rst
Documentation/filesystems/porting.rst
Documentation/filesystems/vfs.rst
fs/bad_inode.c
fs/btrfs/inode.c
fs/dcache.c
fs/ext2/namei.c
fs/ext4/namei.c
fs/f2fs/namei.c
fs/hugetlbfs/inode.c
fs/minix/namei.c
fs/namei.c
fs/ramfs/inode.c
fs/ubifs/dir.c
fs/udf/namei.c
fs/xfs/xfs_iops.c
include/linux/dcache.h
include/linux/fs.h
mm/shmem.c

index 4bb2627..8f737e7 100644 (file)
@@ -79,7 +79,8 @@ prototypes::
        int (*atomic_open)(struct inode *, struct dentry *,
                                struct file *, unsigned open_flag,
                                umode_t create_mode);
-       int (*tmpfile) (struct inode *, struct dentry *, umode_t);
+       int (*tmpfile) (struct user_namespace *, struct inode *,
+                       struct file *, umode_t);
        int (*fileattr_set)(struct user_namespace *mnt_userns,
                            struct dentry *dentry, struct fileattr *fa);
        int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
index aee9aaf..af13824 100644 (file)
@@ -922,3 +922,13 @@ is provided - file_open_root_mnt().  In-tree users adjusted.
 no_llseek is gone; don't set .llseek to that - just leave it NULL instead.
 Checks for "does that file have llseek(2), or should it fail with ESPIPE"
 should be done by looking at FMODE_LSEEK in file->f_mode.
+
+---
+
+**mandatory**
+
+Calling conventions for ->tmpfile() have changed.  It now takes a struct
+file pointer instead of struct dentry pointer.  d_tmpfile() is similarly
+changed to simplify callers.  The passed file is in a non-open state and on
+success must be opened before returning (e.g. by calling
+finish_open_simple()).
index 6cd6953..71b0b81 100644 (file)
@@ -439,7 +439,7 @@ As of kernel 2.6.22, the following members are defined:
                void (*update_time)(struct inode *, struct timespec *, int);
                int (*atomic_open)(struct inode *, struct dentry *, struct file *,
                                   unsigned open_flag, umode_t create_mode);
-               int (*tmpfile) (struct user_namespace *, struct inode *, struct dentry *, umode_t);
+               int (*tmpfile) (struct user_namespace *, struct inode *, struct file *, umode_t);
                int (*set_acl)(struct user_namespace *, struct inode *, struct posix_acl *, int);
                int (*fileattr_set)(struct user_namespace *mnt_userns,
                                    struct dentry *dentry, struct fileattr *fa);
@@ -589,7 +589,9 @@ otherwise noted.
 ``tmpfile``
        called in the end of O_TMPFILE open().  Optional, equivalent to
        atomically creating, opening and unlinking a file in given
-       directory.
+       directory.  On success needs to return with the file already
+       open; this can be done by calling finish_open_simple() right at
+       the end.
 
 ``fileattr_get``
        called on ioctl(FS_IOC_GETFLAGS) and ioctl(FS_IOC_FSGETXATTR) to
index 12b8fdc..9d1cde8 100644 (file)
@@ -147,7 +147,7 @@ static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry,
 }
 
 static int bad_inode_tmpfile(struct user_namespace *mnt_userns,
-                            struct inode *inode, struct dentry *dentry,
+                            struct inode *inode, struct file *file,
                             umode_t mode)
 {
        return -EIO;
index 1372210..4163737 100644 (file)
@@ -10168,7 +10168,7 @@ static int btrfs_permission(struct user_namespace *mnt_userns,
 }
 
 static int btrfs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                        struct dentry *dentry, umode_t mode)
+                        struct file *file, umode_t mode)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
        struct btrfs_trans_handle *trans;
@@ -10176,7 +10176,7 @@ static int btrfs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
        struct inode *inode;
        struct btrfs_new_inode_args new_inode_args = {
                .dir = dir,
-               .dentry = dentry,
+               .dentry = file->f_path.dentry,
                .orphan = true,
        };
        unsigned int trans_num_items;
@@ -10213,7 +10213,7 @@ static int btrfs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
        set_nlink(inode, 1);
 
        if (!ret) {
-               d_tmpfile(dentry, inode);
+               d_tmpfile(file, inode);
                unlock_new_inode(inode);
                mark_inode_dirty(inode);
        }
@@ -10225,7 +10225,7 @@ out_new_inode_args:
 out_inode:
        if (ret)
                iput(inode);
-       return ret;
+       return finish_open_simple(file, ret);
 }
 
 void btrfs_set_range_writeback(struct btrfs_inode *inode, u64 start, u64 end)
index bb0c4d0..89dc613 100644 (file)
@@ -3258,8 +3258,10 @@ void d_genocide(struct dentry *parent)
 
 EXPORT_SYMBOL(d_genocide);
 
-void d_tmpfile(struct dentry *dentry, struct inode *inode)
+void d_tmpfile(struct file *file, struct inode *inode)
 {
+       struct dentry *dentry = file->f_path.dentry;
+
        inode_dec_link_count(inode);
        BUG_ON(dentry->d_name.name != dentry->d_iname ||
                !hlist_unhashed(&dentry->d_u.d_alias) ||
index 5fd9a22..9125eab 100644 (file)
@@ -120,7 +120,7 @@ static int ext2_create (struct user_namespace * mnt_userns,
 }
 
 static int ext2_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                       struct dentry *dentry, umode_t mode)
+                       struct file *file, umode_t mode)
 {
        struct inode *inode = ext2_new_inode(dir, mode, NULL);
        if (IS_ERR(inode))
@@ -128,9 +128,9 @@ static int ext2_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 
        ext2_set_file_ops(inode);
        mark_inode_dirty(inode);
-       d_tmpfile(dentry, inode);
+       d_tmpfile(file, inode);
        unlock_new_inode(inode);
-       return 0;
+       return finish_open_simple(file, 0);
 }
 
 static int ext2_mknod (struct user_namespace * mnt_userns, struct inode * dir,
index 3a31b66..9c3fde6 100644 (file)
@@ -2849,7 +2849,7 @@ retry:
 }
 
 static int ext4_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                       struct dentry *dentry, umode_t mode)
+                       struct file *file, umode_t mode)
 {
        handle_t *handle;
        struct inode *inode;
@@ -2871,7 +2871,7 @@ retry:
                inode->i_op = &ext4_file_inode_operations;
                inode->i_fop = &ext4_file_operations;
                ext4_set_aops(inode);
-               d_tmpfile(dentry, inode);
+               d_tmpfile(file, inode);
                err = ext4_orphan_add(handle, inode);
                if (err)
                        goto err_unlock_inode;
@@ -2882,7 +2882,7 @@ retry:
                ext4_journal_stop(handle);
        if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
                goto retry;
-       return err;
+       return finish_open_simple(file, err);
 err_unlock_inode:
        ext4_journal_stop(handle);
        unlock_new_inode(inode);
index bf00d50..d5065a5 100644 (file)
@@ -845,7 +845,7 @@ out:
 }
 
 static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                         struct dentry *dentry, umode_t mode, bool is_whiteout,
+                         struct file *file, umode_t mode, bool is_whiteout,
                          struct inode **new_inode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
@@ -892,8 +892,8 @@ static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
                inode->i_state |= I_LINKABLE;
                spin_unlock(&inode->i_lock);
        } else {
-               if (dentry)
-                       d_tmpfile(dentry, inode);
+               if (file)
+                       d_tmpfile(file, inode);
                else
                        f2fs_i_links_write(inode, false);
        }
@@ -915,16 +915,19 @@ out:
 }
 
 static int f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                       struct dentry *dentry, umode_t mode)
+                       struct file *file, umode_t mode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
+       int err;
 
        if (unlikely(f2fs_cp_error(sbi)))
                return -EIO;
        if (!f2fs_is_checkpoint_ready(sbi))
                return -ENOSPC;
 
-       return __f2fs_tmpfile(mnt_userns, dir, dentry, mode, false, NULL);
+       err = __f2fs_tmpfile(mnt_userns, dir, file, mode, false, NULL);
+
+       return finish_open_simple(file, err);
 }
 
 static int f2fs_create_whiteout(struct user_namespace *mnt_userns,
index 0b458be..026daa8 100644 (file)
@@ -917,7 +917,7 @@ static int hugetlbfs_create(struct user_namespace *mnt_userns,
 }
 
 static int hugetlbfs_tmpfile(struct user_namespace *mnt_userns,
-                            struct inode *dir, struct dentry *dentry,
+                            struct inode *dir, struct file *file,
                             umode_t mode)
 {
        struct inode *inode;
@@ -926,8 +926,8 @@ static int hugetlbfs_tmpfile(struct user_namespace *mnt_userns,
        if (!inode)
                return -ENOSPC;
        dir->i_ctime = dir->i_mtime = current_time(dir);
-       d_tmpfile(dentry, inode);
-       return 0;
+       d_tmpfile(file, inode);
+       return finish_open_simple(file, 0);
 }
 
 static int hugetlbfs_symlink(struct user_namespace *mnt_userns,
index 937fa5f..8afdc40 100644 (file)
@@ -53,16 +53,16 @@ static int minix_mknod(struct user_namespace *mnt_userns, struct inode *dir,
 }
 
 static int minix_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                        struct dentry *dentry, umode_t mode)
+                        struct file *file, umode_t mode)
 {
        int error;
        struct inode *inode = minix_new_inode(dir, mode, &error);
        if (inode) {
                minix_set_inode(inode, 0);
                mark_inode_dirty(inode);
-               d_tmpfile(dentry, inode);
+               d_tmpfile(file, inode);
        }
-       return error;
+       return finish_open_simple(file, error);
 }
 
 static int minix_create(struct user_namespace *mnt_userns, struct inode *dir,
index fea56fe..c4ca2c3 100644 (file)
@@ -3604,8 +3604,7 @@ static int vfs_tmpfile(struct user_namespace *mnt_userns,
        file->f_path.mnt = parentpath->mnt;
        file->f_path.dentry = child;
        mode = vfs_prepare_mode(mnt_userns, dir, mode, mode, mode);
-       error = dir->i_op->tmpfile(mnt_userns, dir, child, mode);
-       error = finish_open_simple(file, error);
+       error = dir->i_op->tmpfile(mnt_userns, dir, file, mode);
        dput(child);
        if (error)
                return error;
index bc66d01..b3257e8 100644 (file)
@@ -146,15 +146,15 @@ static int ramfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
 }
 
 static int ramfs_tmpfile(struct user_namespace *mnt_userns,
-                        struct inode *dir, struct dentry *dentry, umode_t mode)
+                        struct inode *dir, struct file *file, umode_t mode)
 {
        struct inode *inode;
 
        inode = ramfs_get_inode(dir->i_sb, dir, mode, 0);
        if (!inode)
                return -ENOSPC;
-       d_tmpfile(dentry, inode);
-       return 0;
+       d_tmpfile(file, inode);
+       return finish_open_simple(file, 0);
 }
 
 static const struct inode_operations ramfs_dir_inode_operations = {
index 8615188..f59acd6 100644 (file)
@@ -424,8 +424,9 @@ static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
 }
 
 static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                        struct dentry *dentry, umode_t mode)
+                        struct file *file, umode_t mode)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode;
        struct ubifs_info *c = dir->i_sb->s_fs_info;
        struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
@@ -475,7 +476,7 @@ static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 
        mutex_lock(&ui->ui_mutex);
        insert_inode_hash(inode);
-       d_tmpfile(dentry, inode);
+       d_tmpfile(file, inode);
        ubifs_assert(c, ui->dirty);
 
        instantiated = 1;
@@ -489,7 +490,7 @@ static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 
        ubifs_release_budget(c, &req);
 
-       return 0;
+       return finish_open_simple(file, 0);
 
 out_cancel:
        unlock_2_inodes(dir, inode);
index b3d5f97..fb4c30e 100644 (file)
@@ -626,7 +626,7 @@ static int udf_create(struct user_namespace *mnt_userns, struct inode *dir,
 }
 
 static int udf_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-                      struct dentry *dentry, umode_t mode)
+                      struct file *file, umode_t mode)
 {
        struct inode *inode = udf_new_inode(dir, mode);
 
@@ -640,9 +640,9 @@ static int udf_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
        inode->i_op = &udf_file_inode_operations;
        inode->i_fop = &udf_file_operations;
        mark_inode_dirty(inode);
-       d_tmpfile(dentry, inode);
+       d_tmpfile(file, inode);
        unlock_new_inode(inode);
-       return 0;
+       return finish_open_simple(file, 0);
 }
 
 static int udf_mknod(struct user_namespace *mnt_userns, struct inode *dir,
index 45518b8..764409c 100644 (file)
@@ -167,7 +167,7 @@ xfs_generic_create(
        struct dentry   *dentry,
        umode_t         mode,
        dev_t           rdev,
-       bool            tmpfile)        /* unnamed file */
+       struct file     *tmpfile)       /* unnamed file */
 {
        struct inode    *inode;
        struct xfs_inode *ip = NULL;
@@ -234,7 +234,7 @@ xfs_generic_create(
                 * d_tmpfile can immediately set it back to zero.
                 */
                set_nlink(inode, 1);
-               d_tmpfile(dentry, inode);
+               d_tmpfile(tmpfile, inode);
        } else
                d_instantiate(dentry, inode);
 
@@ -261,7 +261,7 @@ xfs_vn_mknod(
        umode_t                 mode,
        dev_t                   rdev)
 {
-       return xfs_generic_create(mnt_userns, dir, dentry, mode, rdev, false);
+       return xfs_generic_create(mnt_userns, dir, dentry, mode, rdev, NULL);
 }
 
 STATIC int
@@ -272,7 +272,7 @@ xfs_vn_create(
        umode_t                 mode,
        bool                    flags)
 {
-       return xfs_generic_create(mnt_userns, dir, dentry, mode, 0, false);
+       return xfs_generic_create(mnt_userns, dir, dentry, mode, 0, NULL);
 }
 
 STATIC int
@@ -283,7 +283,7 @@ xfs_vn_mkdir(
        umode_t                 mode)
 {
        return xfs_generic_create(mnt_userns, dir, dentry, mode | S_IFDIR, 0,
-                                 false);
+                                 NULL);
 }
 
 STATIC struct dentry *
@@ -1080,10 +1080,12 @@ STATIC int
 xfs_vn_tmpfile(
        struct user_namespace   *mnt_userns,
        struct inode            *dir,
-       struct dentry           *dentry,
+       struct file             *file,
        umode_t                 mode)
 {
-       return xfs_generic_create(mnt_userns, dir, dentry, mode, 0, true);
+       int err = xfs_generic_create(mnt_userns, dir, file->f_path.dentry, mode, 0, file);
+
+       return finish_open_simple(file, err);
 }
 
 static const struct inode_operations xfs_inode_operations = {
index 92c78ed..bde9f8f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/wait.h>
 
 struct path;
+struct file;
 struct vfsmount;
 
 /*
@@ -250,7 +251,7 @@ extern struct dentry * d_make_root(struct inode *);
 /* <clickety>-<click> the ramfs-type tree */
 extern void d_genocide(struct dentry *);
 
-extern void d_tmpfile(struct dentry *, struct inode *);
+extern void d_tmpfile(struct file *, struct inode *);
 
 extern struct dentry *d_find_alias(struct inode *);
 extern void d_prune_aliases(struct inode *);
index a3c5086..8218d99 100644 (file)
@@ -2168,7 +2168,7 @@ struct inode_operations {
                           struct file *, unsigned open_flag,
                           umode_t create_mode);
        int (*tmpfile) (struct user_namespace *, struct inode *,
-                       struct dentry *, umode_t);
+                       struct file *, umode_t);
        int (*set_acl)(struct user_namespace *, struct inode *,
                       struct posix_acl *, int);
        int (*fileattr_set)(struct user_namespace *mnt_userns,
index 42e5888..f63c51b 100644 (file)
@@ -2912,7 +2912,7 @@ out_iput:
 
 static int
 shmem_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-             struct dentry *dentry, umode_t mode)
+             struct file *file, umode_t mode)
 {
        struct inode *inode;
        int error = -ENOSPC;
@@ -2927,9 +2927,9 @@ shmem_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
                error = simple_acl_create(dir, inode);
                if (error)
                        goto out_iput;
-               d_tmpfile(dentry, inode);
+               d_tmpfile(file, inode);
        }
-       return error;
+       return finish_open_simple(file, error);
 out_iput:
        iput(inode);
        return error;