aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2023-01-18 12:29:22 +0100
committerJan Kara <jack@suse.cz>2023-01-26 16:46:33 +0100
commitf3a30be777508c371067ca2b47a55c4cb142d5f5 (patch)
treef6b28bdfb53deb3dbce224497424a3f2d354c447 /fs/udf
parentde80dae03c436b43017dd5e479486f1f73fa6769 (diff)
downloadlinux-f3a30be777508c371067ca2b47a55c4cb142d5f5.tar.gz
udf: Factor out block mapping into udf_map_block()
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>
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/inode.c70
-rw-r--r--fs/udf/udfdecl.h1
2 files changed, 49 insertions, 22 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 6f190d0d590c3..3e0adfee29c43 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -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,
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 88667a80795dc..d791458fe52af 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -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);