mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
hfsplus: fix generic/533 test-case failure
The xfstests' test-case generic/533 fails to execute correctly: FSTYP -- hfsplus PLATFORM -- Linux/x86_64 hfsplus-testing-0001 6.15.0-rc4+ #8 SMP PREEMPT_DYNAMIC Thu May 1 16:43:22 PDT 2025 MKFS_OPTIONS -- /dev/loop51 MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch generic/533 _check_generic_filesystem: filesystem on /dev/loop50 is inconsistent (see xfstests-dev/results//generic/533.full for details) The key reason of the issue is returning -ENOENT error code from hfsplus_find_attr(), __hfsplus_delete_attr(), hfsplus_delete_attr_nolock(), hfsplus_delete_all_attrs(). The file exists but we don't have any xattr for this file. Finally, -ENODATA error code is expected by application logic. This patch reworks xattr logic of HFS+ by means exchanging the -ENOENT error code on -ENODATA error code if xattr has not been found for existing file or folder. sudo ./check generic/533 FSTYP -- hfsplus PLATFORM -- Linux/x86_64 hfsplus-testing-0001 7.0.0-rc1+ #16 SMP PREEMPT_DYNAMIC Wed Mar 11 15:04:58 PDT 2026 MKFS_OPTIONS -- /dev/loop51 MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch generic/533 33s ... 32s Ran: generic/533 Passed all 1 tests Closes: https://github.com/hfs-linux-kernel/hfs-linux-kernel/issues/184 cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> cc: Yangtao Li <frank.li@vivo.com> cc: linux-fsdevel@vger.kernel.org Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com> Link: https://lore.kernel.org/r/20260312221920.1422683-2-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
This commit is contained in:
parent
e89b5724aa
commit
a46aaa76ad
|
|
@ -153,14 +153,22 @@ int hfsplus_find_attr(struct super_block *sb, u32 cnid,
|
|||
if (err)
|
||||
goto failed_find_attr;
|
||||
err = hfs_brec_find(fd, hfs_find_rec_by_key);
|
||||
if (err)
|
||||
if (err == -ENOENT) {
|
||||
/* file exists but xattr is absent */
|
||||
err = -ENODATA;
|
||||
goto failed_find_attr;
|
||||
} else if (err)
|
||||
goto failed_find_attr;
|
||||
} else {
|
||||
err = hfsplus_attr_build_key(sb, fd->search_key, cnid, NULL);
|
||||
if (err)
|
||||
goto failed_find_attr;
|
||||
err = hfs_brec_find(fd, hfs_find_1st_rec_by_cnid);
|
||||
if (err)
|
||||
if (err == -ENOENT) {
|
||||
/* file exists but xattr is absent */
|
||||
err = -ENODATA;
|
||||
goto failed_find_attr;
|
||||
} else if (err)
|
||||
goto failed_find_attr;
|
||||
}
|
||||
|
||||
|
|
@ -174,6 +182,9 @@ int hfsplus_attr_exists(struct inode *inode, const char *name)
|
|||
struct super_block *sb = inode->i_sb;
|
||||
struct hfs_find_data fd;
|
||||
|
||||
hfs_dbg("name %s, ino %ld\n",
|
||||
name ? name : NULL, inode->i_ino);
|
||||
|
||||
if (!HFSPLUS_SB(sb)->attr_tree)
|
||||
return 0;
|
||||
|
||||
|
|
@ -293,15 +304,16 @@ int hfsplus_create_attr(struct inode *inode,
|
|||
static int __hfsplus_delete_attr(struct inode *inode, u32 cnid,
|
||||
struct hfs_find_data *fd)
|
||||
{
|
||||
int err = 0;
|
||||
int err;
|
||||
__be32 found_cnid, record_type;
|
||||
|
||||
found_cnid = U32_MAX;
|
||||
hfs_bnode_read(fd->bnode, &found_cnid,
|
||||
fd->keyoffset +
|
||||
offsetof(struct hfsplus_attr_key, cnid),
|
||||
sizeof(__be32));
|
||||
if (cnid != be32_to_cpu(found_cnid))
|
||||
return -ENOENT;
|
||||
return -ENODATA;
|
||||
|
||||
hfs_bnode_read(fd->bnode, &record_type,
|
||||
fd->entryoffset, sizeof(record_type));
|
||||
|
|
@ -330,7 +342,7 @@ static int __hfsplus_delete_attr(struct inode *inode, u32 cnid,
|
|||
hfsplus_mark_inode_dirty(HFSPLUS_ATTR_TREE_I(inode->i_sb),
|
||||
HFSPLUS_I_ATTR_DIRTY);
|
||||
hfsplus_mark_inode_dirty(inode, HFSPLUS_I_ATTR_DIRTY);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -354,7 +366,10 @@ int hfsplus_delete_attr_nolock(struct inode *inode, const char *name,
|
|||
}
|
||||
|
||||
err = hfs_brec_find(fd, hfs_find_rec_by_key);
|
||||
if (err)
|
||||
if (err == -ENOENT) {
|
||||
/* file exists but xattr is absent */
|
||||
return -ENODATA;
|
||||
} else if (err)
|
||||
return err;
|
||||
|
||||
err = __hfsplus_delete_attr(inode, inode->i_ino, fd);
|
||||
|
|
@ -414,9 +429,14 @@ int hfsplus_delete_all_attrs(struct inode *dir, u32 cnid)
|
|||
|
||||
for (;;) {
|
||||
err = hfsplus_find_attr(dir->i_sb, cnid, NULL, &fd);
|
||||
if (err) {
|
||||
if (err != -ENOENT)
|
||||
pr_err("xattr search failed\n");
|
||||
if (err == -ENOENT || err == -ENODATA) {
|
||||
/*
|
||||
* xattr has not been found
|
||||
*/
|
||||
err = -ENODATA;
|
||||
goto end_delete_all;
|
||||
} else if (err) {
|
||||
pr_err("xattr search failed\n");
|
||||
goto end_delete_all;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -571,7 +571,12 @@ hfsplus_btree_lock_class(struct hfs_btree *tree)
|
|||
static inline
|
||||
bool is_bnode_offset_valid(struct hfs_bnode *node, u32 off)
|
||||
{
|
||||
bool is_valid = off < node->tree->node_size;
|
||||
bool is_valid;
|
||||
|
||||
if (!node || !node->tree)
|
||||
return false;
|
||||
|
||||
is_valid = off < node->tree->node_size;
|
||||
|
||||
if (!is_valid) {
|
||||
pr_err("requested invalid offset: "
|
||||
|
|
|
|||
|
|
@ -562,10 +562,10 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
|
|||
|
||||
res = hfsplus_find_attr(inode->i_sb, inode->i_ino, name, &fd);
|
||||
if (res) {
|
||||
if (res == -ENOENT)
|
||||
if (res == -ENOENT || res == -ENODATA)
|
||||
res = -ENODATA;
|
||||
else
|
||||
pr_err("xattr searching failed\n");
|
||||
pr_err("xattr search failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -757,7 +757,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
|
||||
err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
|
||||
if (err) {
|
||||
if (err == -ENOENT) {
|
||||
if (err == -ENOENT || err == -ENODATA) {
|
||||
res = 0;
|
||||
goto end_listxattr;
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user