hfsplus: fix generic/062 xfstests failure
The xfstests' test-case generic/062 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/062 - output mismatch (see xfstests-dev/results//generic/062.out.bad) The generic/062 test tries to set and get xattrs for various types of objects (regular file, folder, block device, character device, pipe, etc) with the goal to check that xattr operations works correctly for all possible types of file system objects. But current HFS+ implementation somehow hasn't support of xattr operatioons for the case of block device, character device, and pipe objects. Also, it has not completely correct set of operations for the case symlinks. This patch implements proper declaration of xattrs operations hfsplus_special_inode_operations and hfsplus_symlink_inode_operations. Also, it slightly corrects the logic of hfsplus_listxattr() method. sudo ./check generic/062 FSTYP -- hfsplus PLATFORM -- Linux/x86_64 hfsplus-testing-0001 6.19.0-rc1+ #59 SMP PREEMPT_DYNAMIC Mon Jan 19 16:26:21 PST 2026 MKFS_OPTIONS -- /dev/loop51 MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch generic/062 20s ... 20s Ran: generic/062 Passed all 1 tests [1] https://github.com/hfs-linux-kernel/hfs-linux-kernel/issues/93 Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com> cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> cc: Yangtao Li <frank.li@vivo.com> cc: linux-fsdevel@vger.kernel.org Link: https://lore.kernel.org/r/20260120041937.3450928-1-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
This commit is contained in:
parent
b18c5b84fa
commit
aef5078471
|
|
@ -396,6 +396,19 @@ static const struct inode_operations hfsplus_file_inode_operations = {
|
|||
.fileattr_set = hfsplus_fileattr_set,
|
||||
};
|
||||
|
||||
const struct inode_operations hfsplus_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.setattr = hfsplus_setattr,
|
||||
.getattr = hfsplus_getattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
};
|
||||
|
||||
const struct inode_operations hfsplus_special_inode_operations = {
|
||||
.setattr = hfsplus_setattr,
|
||||
.getattr = hfsplus_getattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
};
|
||||
|
||||
static const struct file_operations hfsplus_file_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read_iter = generic_file_read_iter,
|
||||
|
|
@ -455,12 +468,17 @@ struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
|
|||
hip->clump_blocks = sbi->data_clump_blocks;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
sbi->file_count++;
|
||||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_op = &hfsplus_symlink_inode_operations;
|
||||
inode_nohighmem(inode);
|
||||
inode->i_mapping->a_ops = &hfsplus_aops;
|
||||
hip->clump_blocks = 1;
|
||||
} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
|
||||
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
|
||||
sbi->file_count++;
|
||||
inode->i_op = &hfsplus_special_inode_operations;
|
||||
} else
|
||||
sbi->file_count++;
|
||||
|
||||
insert_inode_hash(inode);
|
||||
mark_inode_dirty(inode);
|
||||
hfsplus_mark_mdb_dirty(sb);
|
||||
|
|
@ -591,10 +609,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
|
|||
inode->i_fop = &hfsplus_file_operations;
|
||||
inode->i_mapping->a_ops = &hfsplus_aops;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_op = &hfsplus_symlink_inode_operations;
|
||||
inode_nohighmem(inode);
|
||||
inode->i_mapping->a_ops = &hfsplus_aops;
|
||||
} else {
|
||||
inode->i_op = &hfsplus_special_inode_operations;
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
be32_to_cpu(file->permissions.dev));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,6 +258,15 @@ end_attr_file_creation:
|
|||
return err;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool is_xattr_operation_supported(struct inode *inode)
|
||||
{
|
||||
if (HFSPLUS_IS_RSRC(inode))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int __hfsplus_setxattr(struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
|
|
@ -268,9 +277,11 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
|
|||
u16 folder_finderinfo_len = sizeof(DInfo) + sizeof(DXInfo);
|
||||
u16 file_finderinfo_len = sizeof(FInfo) + sizeof(FXInfo);
|
||||
|
||||
if ((!S_ISREG(inode->i_mode) &&
|
||||
!S_ISDIR(inode->i_mode)) ||
|
||||
HFSPLUS_IS_RSRC(inode))
|
||||
hfs_dbg("ino %lu, name %s, value %p, size %zu\n",
|
||||
inode->i_ino, name ? name : NULL,
|
||||
value, size);
|
||||
|
||||
if (!is_xattr_operation_supported(inode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (value == NULL)
|
||||
|
|
@ -390,6 +401,7 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
|
|||
|
||||
end_setxattr:
|
||||
hfs_find_exit(&cat_fd);
|
||||
hfs_dbg("finished: res %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -514,9 +526,7 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
|
|||
u16 record_length = 0;
|
||||
ssize_t res;
|
||||
|
||||
if ((!S_ISREG(inode->i_mode) &&
|
||||
!S_ISDIR(inode->i_mode)) ||
|
||||
HFSPLUS_IS_RSRC(inode))
|
||||
if (!is_xattr_operation_supported(inode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!strcmp_xattr_finder_info(name))
|
||||
|
|
@ -709,9 +719,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
|
||||
hfs_dbg("ino %lu\n", inode->i_ino);
|
||||
|
||||
if ((!S_ISREG(inode->i_mode) &&
|
||||
!S_ISDIR(inode->i_mode)) ||
|
||||
HFSPLUS_IS_RSRC(inode))
|
||||
if (!is_xattr_operation_supported(inode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
res = hfsplus_listxattr_finder_info(dentry, buffer, size);
|
||||
|
|
@ -737,8 +745,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 (res == 0)
|
||||
res = -ENODATA;
|
||||
res = 0;
|
||||
goto end_listxattr;
|
||||
} else {
|
||||
res = err;
|
||||
|
|
|
|||
Loading…
Reference in New Issue