udf: Factor out block mapping into udf_map_block()
authorJan Kara <jack@suse.cz>
Wed, 18 Jan 2023 11:29:22 +0000 (12:29 +0100)
committerJan Kara <jack@suse.cz>
Thu, 26 Jan 2023 15:46:33 +0000 (16:46 +0100)
Create new block mapping function udf_map_block() that takes new
udf_map_rq structure describing mapping request. We will convert other
places to use this function for block mapping.

Signed-off-by: Jan Kara <jack@suse.cz>
fs/udf/inode.c
fs/udf/udfdecl.h

index 6f190d0..3e0adfe 100644 (file)
@@ -52,6 +52,8 @@
 #define FE_DELETE_PERMS        (FE_PERM_U_DELETE | FE_PERM_G_DELETE | \
                         FE_PERM_O_DELETE)
 
+struct udf_map_rq;
+
 static umode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static int udf_sync_inode(struct inode *inode);
@@ -320,43 +322,67 @@ int udf_expand_file_adinicb(struct inode *inode)
        return err;
 }
 
-static int udf_get_block(struct inode *inode, sector_t block,
-                        struct buffer_head *bh_result, int create)
+#define UDF_MAP_CREATE 0x01    /* Mapping can allocate new blocks */
+
+#define UDF_BLK_MAPPED 0x01    /* Block was successfully mapped */
+#define UDF_BLK_NEW    0x02    /* Block was freshly allocated */
+
+struct udf_map_rq {
+       sector_t lblk;
+       udf_pblk_t pblk;
+       int iflags;             /* UDF_MAP_ flags determining behavior */
+       int oflags;             /* UDF_BLK_ flags reporting results */
+};
+
+static int udf_map_block(struct inode *inode, struct udf_map_rq *map)
 {
        int err, new;
-       sector_t phys = 0;
-       struct udf_inode_info *iinfo;
+       struct udf_inode_info *iinfo = UDF_I(inode);
 
-       if (!create) {
-               phys = udf_block_map(inode, block);
-               if (phys)
-                       map_bh(bh_result, inode->i_sb, phys);
+       map->oflags = 0;
+       if (!(map->iflags & UDF_MAP_CREATE)) {
+               map->pblk = udf_block_map(inode, map->lblk);
+               if (map->pblk != 0)
+                       map->oflags |= UDF_BLK_MAPPED;
                return 0;
        }
 
-       err = -EIO;
-       new = 0;
-       iinfo = UDF_I(inode);
-
        down_write(&iinfo->i_data_sem);
        /*
         * Block beyond EOF and prealloc extents? Just discard preallocation
         * as it is not useful and complicates things.
         */
-       if (((loff_t)block) << inode->i_blkbits > iinfo->i_lenExtents)
+       if (((loff_t)map->lblk) << inode->i_blkbits > iinfo->i_lenExtents)
                udf_discard_prealloc(inode);
        udf_clear_extent_cache(inode);
-       phys = inode_getblk(inode, block, &err, &new);
-       if (!phys)
-               goto abort;
-
+       map->pblk = inode_getblk(inode, map->lblk, &err, &new);
+       up_write(&iinfo->i_data_sem);
+       if (err)
+               return err;
+       map->oflags |= UDF_BLK_MAPPED;
        if (new)
-               set_buffer_new(bh_result);
-       map_bh(bh_result, inode->i_sb, phys);
+               map->oflags |= UDF_BLK_NEW;
+       return 0;
+}
 
-abort:
-       up_write(&iinfo->i_data_sem);
-       return err;
+static int udf_get_block(struct inode *inode, sector_t block,
+                        struct buffer_head *bh_result, int create)
+{
+       int err;
+       struct udf_map_rq map = {
+               .lblk = block,
+               .iflags = create ? UDF_MAP_CREATE : 0,
+       };
+
+       err = udf_map_block(inode, &map);
+       if (err < 0)
+               return err;
+       if (map.oflags & UDF_BLK_MAPPED) {
+               map_bh(bh_result, inode->i_sb, map.pblk);
+               if (map.oflags & UDF_BLK_NEW)
+                       set_buffer_new(bh_result);
+       }
+       return 0;
 }
 
 static struct buffer_head *udf_getblk(struct inode *inode, udf_pblk_t block,
index 88667a8..d791458 100644 (file)
@@ -138,6 +138,7 @@ static inline unsigned int udf_dir_entry_len(struct fileIdentDesc *cfi)
 
 /* file.c */
 extern long udf_ioctl(struct file *, unsigned int, unsigned long);
+
 /* inode.c */
 extern struct inode *__udf_iget(struct super_block *, struct kernel_lb_addr *,
                                bool hidden_inode);