vboxsf: Add vboxsf_[create|release]_sf_handle() helpers
authorHans de Goede <hdegoede@redhat.com>
Thu, 21 Jan 2021 09:55:03 +0000 (10:55 +0100)
committerHans de Goede <hdegoede@redhat.com>
Wed, 23 Jun 2021 12:36:46 +0000 (14:36 +0200)
Factor out the code to create / release a struct vboxsf_handle into
2 new helper functions.

This is a preparation patch for adding atomic_open support.

Fixes: 0fd169576648 ("fs: Add VirtualBox guest shared folder (vboxsf) support")
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
fs/vboxsf/file.c
fs/vboxsf/vfsmod.h

index c4ab5996d97a83c02567024fa94829a083a55afc..864c2fad23beb34bdeed5d2c981ace8019eed687 100644 (file)
@@ -20,17 +20,39 @@ struct vboxsf_handle {
        struct list_head head;
 };
 
-static int vboxsf_file_open(struct inode *inode, struct file *file)
+struct vboxsf_handle *vboxsf_create_sf_handle(struct inode *inode,
+                                             u64 handle, u32 access_flags)
 {
        struct vboxsf_inode *sf_i = VBOXSF_I(inode);
-       struct shfl_createparms params = {};
        struct vboxsf_handle *sf_handle;
-       u32 access_flags = 0;
-       int err;
 
        sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL);
        if (!sf_handle)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
+
+       /* the host may have given us different attr then requested */
+       sf_i->force_restat = 1;
+
+       /* init our handle struct and add it to the inode's handles list */
+       sf_handle->handle = handle;
+       sf_handle->root = VBOXSF_SBI(inode->i_sb)->root;
+       sf_handle->access_flags = access_flags;
+       kref_init(&sf_handle->refcount);
+
+       mutex_lock(&sf_i->handle_list_mutex);
+       list_add(&sf_handle->head, &sf_i->handle_list);
+       mutex_unlock(&sf_i->handle_list_mutex);
+
+       return sf_handle;
+}
+
+static int vboxsf_file_open(struct inode *inode, struct file *file)
+{
+       struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
+       struct shfl_createparms params = {};
+       struct vboxsf_handle *sf_handle;
+       u32 access_flags = 0;
+       int err;
 
        /*
         * We check the value of params.handle afterwards to find out if
@@ -83,23 +105,14 @@ static int vboxsf_file_open(struct inode *inode, struct file *file)
        err = vboxsf_create_at_dentry(file_dentry(file), &params);
        if (err == 0 && params.handle == SHFL_HANDLE_NIL)
                err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT;
-       if (err) {
-               kfree(sf_handle);
+       if (err)
                return err;
-       }
-
-       /* the host may have given us different attr then requested */
-       sf_i->force_restat = 1;
 
-       /* init our handle struct and add it to the inode's handles list */
-       sf_handle->handle = params.handle;
-       sf_handle->root = VBOXSF_SBI(inode->i_sb)->root;
-       sf_handle->access_flags = access_flags;
-       kref_init(&sf_handle->refcount);
-
-       mutex_lock(&sf_i->handle_list_mutex);
-       list_add(&sf_handle->head, &sf_i->handle_list);
-       mutex_unlock(&sf_i->handle_list_mutex);
+       sf_handle = vboxsf_create_sf_handle(inode, params.handle, access_flags);
+       if (IS_ERR(sf_handle)) {
+               vboxsf_close(sbi->root, params.handle);
+               return PTR_ERR(sf_handle);
+       }
 
        file->private_data = sf_handle;
        return 0;
@@ -114,22 +127,26 @@ static void vboxsf_handle_release(struct kref *refcount)
        kfree(sf_handle);
 }
 
-static int vboxsf_file_release(struct inode *inode, struct file *file)
+void vboxsf_release_sf_handle(struct inode *inode, struct vboxsf_handle *sf_handle)
 {
        struct vboxsf_inode *sf_i = VBOXSF_I(inode);
-       struct vboxsf_handle *sf_handle = file->private_data;
 
+       mutex_lock(&sf_i->handle_list_mutex);
+       list_del(&sf_handle->head);
+       mutex_unlock(&sf_i->handle_list_mutex);
+
+       kref_put(&sf_handle->refcount, vboxsf_handle_release);
+}
+
+static int vboxsf_file_release(struct inode *inode, struct file *file)
+{
        /*
         * When a file is closed on our (the guest) side, we want any subsequent
         * accesses done on the host side to see all changes done from our side.
         */
        filemap_write_and_wait(inode->i_mapping);
 
-       mutex_lock(&sf_i->handle_list_mutex);
-       list_del(&sf_handle->head);
-       mutex_unlock(&sf_i->handle_list_mutex);
-
-       kref_put(&sf_handle->refcount, vboxsf_handle_release);
+       vboxsf_release_sf_handle(inode, file->private_data);
        return 0;
 }
 
index 6a7a9cedebc6e1708f6e593b3110a66e37c05740..9047befa66c5a8d3c8c125d5f5f66ed957c3122e 100644 (file)
@@ -18,6 +18,8 @@
 #define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info)
 #define VBOXSF_I(i)    container_of(i, struct vboxsf_inode, vfs_inode)
 
+struct vboxsf_handle;
+
 struct vboxsf_options {
        unsigned long ttl;
        kuid_t uid;
@@ -80,6 +82,11 @@ extern const struct file_operations vboxsf_reg_fops;
 extern const struct address_space_operations vboxsf_reg_aops;
 extern const struct dentry_operations vboxsf_dentry_ops;
 
+/* from file.c */
+struct vboxsf_handle *vboxsf_create_sf_handle(struct inode *inode,
+                                             u64 handle, u32 access_flags);
+void vboxsf_release_sf_handle(struct inode *inode, struct vboxsf_handle *sf_handle);
+
 /* from utils.c */
 struct inode *vboxsf_new_inode(struct super_block *sb);
 int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,