From: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
As Jan suggested in links below, refactor udf_current_aext() to
differentiate between error and "hit EOF", it now takes pointer to etype
to store the extent type, return 0 when get etype success; return -ENODATA
when hit EOF; return -EINVAL when i_alloc_type invalid. Add two macroes to
test return value.
Link: https://lore.kernel.org/all/20240912111235.6nr3wuqvktecy3vh@quack3/
Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn>
Suggested-by: Jan Kara <jack@suse.cz>
---
fs/udf/inode.c | 37 +++++++++++++++++++++++--------------
fs/udf/truncate.c | 10 ++++++++--
fs/udf/udfdecl.h | 8 ++++++--
3 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 4726a4d014b6..3be59aa8d4fd 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1955,6 +1955,7 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
struct extent_position nepos;
struct kernel_lb_addr neloc;
int ver, adsize;
+ int err = 0;
if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(struct short_ad);
@@ -1999,10 +2000,12 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
if (epos->offset + adsize > sb->s_blocksize) {
struct kernel_lb_addr cp_loc;
uint32_t cp_len;
- int cp_type;
+ int8_t cp_type;
epos->offset -= adsize;
- cp_type = udf_current_aext(inode, epos, &cp_loc, &cp_len, 0);
+ err = udf_current_aext(inode, epos, &cp_loc, &cp_len, &cp_type, 0);
+ if (err < 0)
+ goto err_out;
cp_len |= ((uint32_t)cp_type) << 30;
__udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1);
@@ -2017,6 +2020,9 @@ int udf_setup_indirect_aext(struct inode *inode, udf_pblk_t block,
*epos = nepos;
return 0;
+err_out:
+ brelse(bh);
+ return err;
}
/*
@@ -2167,9 +2173,12 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
{
int8_t etype;
unsigned int indirections = 0;
+ int err = 0;
+
+ while ((err = udf_current_aext(inode, epos, eloc, elen, &etype, inc))) {
+ if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30))
+ break;
- while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
- (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
udf_pblk_t block;
if (++indirections > UDF_MAX_INDIR_EXTS) {
@@ -2190,14 +2199,14 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
}
}
- return etype;
+ return !err ? etype : -1;
}
-int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
- struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
+int udf_current_aext(struct inode *inode, struct extent_position *epos,
+ struct kernel_lb_addr *eloc, uint32_t *elen, int8_t *etype,
+ int inc)
{
int alen;
- int8_t etype;
uint8_t *ptr;
struct short_ad *sad;
struct long_ad *lad;
@@ -2224,8 +2233,8 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
case ICBTAG_FLAG_AD_SHORT:
sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc);
if (!sad)
- return -1;
- etype = le32_to_cpu(sad->extLength) >> 30;
+ return -ENODATA;
+ *etype = le32_to_cpu(sad->extLength) >> 30;
eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
eloc->partitionReferenceNum =
iinfo->i_location.partitionReferenceNum;
@@ -2234,17 +2243,17 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
case ICBTAG_FLAG_AD_LONG:
lad = udf_get_filelongad(ptr, alen, &epos->offset, inc);
if (!lad)
- return -1;
- etype = le32_to_cpu(lad->extLength) >> 30;
+ return -ENODATA;
+ *etype = le32_to_cpu(lad->extLength) >> 30;
*eloc = lelb_to_cpu(lad->extLocation);
*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
break;
default:
udf_debug("alloc_type = %u unsupported\n", iinfo->i_alloc_type);
- return -1;
+ return -EINVAL;
}
- return etype;
+ return 0;
}
static int udf_insert_aext(struct inode *inode, struct extent_position epos,
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index a686c10fd709..16db2613401d 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -188,6 +188,7 @@ int udf_truncate_extents(struct inode *inode)
loff_t byte_offset;
int adsize;
struct udf_inode_info *iinfo = UDF_I(inode);
+ int err = 0;
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(struct short_ad);
@@ -217,8 +218,8 @@ int udf_truncate_extents(struct inode *inode)
else
lenalloc -= sizeof(struct allocExtDesc);
- while ((etype = udf_current_aext(inode, &epos, &eloc,
- &elen, 0)) != -1) {
+ while (!(err = udf_current_aext(inode, &epos, &eloc, &elen, &etype,
+ 0))) {
if (etype == (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) {
udf_write_aext(inode, &epos, &neloc, nelen, 0);
if (indirect_ext_len) {
@@ -253,6 +254,11 @@ int udf_truncate_extents(struct inode *inode)
}
}
+ if (UDF_EXT_ERR(err)) {
+ brelse(epos.bh);
+ return err;
+ }
+
if (indirect_ext_len) {
BUG_ON(!epos.bh);
udf_free_blocks(sb, NULL, &epos.block, 0, indirect_ext_len);
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 88692512a466..a902652450dd 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -43,6 +43,9 @@ extern __printf(3, 4) void _udf_warn(struct super_block *sb,
#define UDF_NAME_LEN 254
#define UDF_NAME_LEN_CS0 255
+#define UDF_EXT_EOF(err) ((err) == -ENODATA)
+#define UDF_EXT_ERR(err) (((err) < 0) && (!UDF_EXT_EOF(err)))
+
static inline size_t udf_file_entry_alloc_offset(struct inode *inode)
{
struct udf_inode_info *iinfo = UDF_I(inode);
@@ -171,8 +174,9 @@ extern void udf_write_aext(struct inode *, struct extent_position *,
extern int8_t udf_delete_aext(struct inode *, struct extent_position);
extern int8_t udf_next_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t *, int);
-extern int8_t udf_current_aext(struct inode *, struct extent_position *,
- struct kernel_lb_addr *, uint32_t *, int);
+extern int udf_current_aext(struct inode *inode, struct extent_position *epos,
+ struct kernel_lb_addr *eloc, uint32_t *elen,
+ int8_t *etype, int inc);
extern void udf_update_extra_perms(struct inode *inode, umode_t mode);
/* misc.c */
--
2.43.0
On Thu 26-09-24 20:07:51, Zhao Mengmeng wrote: > From: Zhao Mengmeng <zhaomengmeng@kylinos.cn> > > As Jan suggested in links below, refactor udf_current_aext() to > differentiate between error and "hit EOF", it now takes pointer to etype > to store the extent type, return 0 when get etype success; return -ENODATA > when hit EOF; return -EINVAL when i_alloc_type invalid. Add two macroes to > test return value. > > Link: https://lore.kernel.org/all/20240912111235.6nr3wuqvktecy3vh@quack3/ > Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn> > Suggested-by: Jan Kara <jack@suse.cz> ... > @@ -2167,9 +2173,12 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, > { > int8_t etype; > unsigned int indirections = 0; > + int err = 0; > + > + while ((err = udf_current_aext(inode, epos, eloc, elen, &etype, inc))) { > + if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) > + break; > > - while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == > - (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) { This looks wrong. If udf_current_aext() succeeds, you'll immediately abort the loop now. I'd rather code this as: while (1) { err = udf_current_aext(inode, epos, eloc, elen, &etype, inc); if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) break; ... } > diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h > index 88692512a466..a902652450dd 100644 > --- a/fs/udf/udfdecl.h > +++ b/fs/udf/udfdecl.h > @@ -43,6 +43,9 @@ extern __printf(3, 4) void _udf_warn(struct super_block *sb, > #define UDF_NAME_LEN 254 > #define UDF_NAME_LEN_CS0 255 > > +#define UDF_EXT_EOF(err) ((err) == -ENODATA) > +#define UDF_EXT_ERR(err) (((err) < 0) && (!UDF_EXT_EOF(err))) > + So I agree the explicit ENODATA checks are a bit ugly but these macros aren't really much better. How about the following calling convention: On error, ret < 0, on EOF ret == 0, on success ret == 1. This is a similar convention as e.g. for read(2) so it is well understood and easy test for various combinations. Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR
On 2024/9/27 19:55, Jan Kara wrote: > On Thu 26-09-24 20:07:51, Zhao Mengmeng wrote: >> From: Zhao Mengmeng <zhaomengmeng@kylinos.cn> >> >> As Jan suggested in links below, refactor udf_current_aext() to >> differentiate between error and "hit EOF", it now takes pointer to etype >> to store the extent type, return 0 when get etype success; return -ENODATA >> when hit EOF; return -EINVAL when i_alloc_type invalid. Add two macroes to >> test return value. >> >> Link: https://lore.kernel.org/all/20240912111235.6nr3wuqvktecy3vh@quack3/ >> Signed-off-by: Zhao Mengmeng <zhaomengmeng@kylinos.cn> >> Suggested-by: Jan Kara <jack@suse.cz> > ... >> @@ -2167,9 +2173,12 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, >> { >> int8_t etype; >> unsigned int indirections = 0; >> + int err = 0; >> + >> + while ((err = udf_current_aext(inode, epos, eloc, elen, &etype, inc))) { >> + if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) >> + break; >> >> - while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == >> - (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) { > > This looks wrong. If udf_current_aext() succeeds, you'll immediately abort > the loop now. I'd rather code this as: > > while (1) { > err = udf_current_aext(inode, epos, eloc, elen, &etype, inc); > if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) > break; > ... > } Yes, you are right. I forget the return check, should be: while (!(err = udf_current_aext(inode, epos, eloc, elen, &etype, inc))) { if (err || etype != (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) break; >> diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h >> index 88692512a466..a902652450dd 100644 >> --- a/fs/udf/udfdecl.h >> +++ b/fs/udf/udfdecl.h >> @@ -43,6 +43,9 @@ extern __printf(3, 4) void _udf_warn(struct super_block *sb, >> #define UDF_NAME_LEN 254 >> #define UDF_NAME_LEN_CS0 255 >> >> +#define UDF_EXT_EOF(err) ((err) == -ENODATA) >> +#define UDF_EXT_ERR(err) (((err) < 0) && (!UDF_EXT_EOF(err))) >> + > > So I agree the explicit ENODATA checks are a bit ugly but these macros > aren't really much better. How about the following calling convention: > > On error, ret < 0, on EOF ret == 0, on success ret == 1. This is a similar > convention as e.g. for read(2) so it is well understood and easy test for > various combinations. No problem, I will add some comments on these three functions do it in V3.
© 2016 - 2024 Red Hat, Inc.