Skip to content

Commit aef5078

Browse files
committed
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] hfs-linux-kernel#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>
1 parent b18c5b8 commit aef5078

2 files changed

Lines changed: 39 additions & 13 deletions

File tree

fs/hfsplus/inode.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,19 @@ static const struct inode_operations hfsplus_file_inode_operations = {
396396
.fileattr_set = hfsplus_fileattr_set,
397397
};
398398

399+
const struct inode_operations hfsplus_symlink_inode_operations = {
400+
.get_link = page_get_link,
401+
.setattr = hfsplus_setattr,
402+
.getattr = hfsplus_getattr,
403+
.listxattr = hfsplus_listxattr,
404+
};
405+
406+
const struct inode_operations hfsplus_special_inode_operations = {
407+
.setattr = hfsplus_setattr,
408+
.getattr = hfsplus_getattr,
409+
.listxattr = hfsplus_listxattr,
410+
};
411+
399412
static const struct file_operations hfsplus_file_operations = {
400413
.llseek = generic_file_llseek,
401414
.read_iter = generic_file_read_iter,
@@ -455,12 +468,17 @@ struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
455468
hip->clump_blocks = sbi->data_clump_blocks;
456469
} else if (S_ISLNK(inode->i_mode)) {
457470
sbi->file_count++;
458-
inode->i_op = &page_symlink_inode_operations;
471+
inode->i_op = &hfsplus_symlink_inode_operations;
459472
inode_nohighmem(inode);
460473
inode->i_mapping->a_ops = &hfsplus_aops;
461474
hip->clump_blocks = 1;
475+
} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
476+
S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
477+
sbi->file_count++;
478+
inode->i_op = &hfsplus_special_inode_operations;
462479
} else
463480
sbi->file_count++;
481+
464482
insert_inode_hash(inode);
465483
mark_inode_dirty(inode);
466484
hfsplus_mark_mdb_dirty(sb);
@@ -591,10 +609,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
591609
inode->i_fop = &hfsplus_file_operations;
592610
inode->i_mapping->a_ops = &hfsplus_aops;
593611
} else if (S_ISLNK(inode->i_mode)) {
594-
inode->i_op = &page_symlink_inode_operations;
612+
inode->i_op = &hfsplus_symlink_inode_operations;
595613
inode_nohighmem(inode);
596614
inode->i_mapping->a_ops = &hfsplus_aops;
597615
} else {
616+
inode->i_op = &hfsplus_special_inode_operations;
598617
init_special_inode(inode, inode->i_mode,
599618
be32_to_cpu(file->permissions.dev));
600619
}

fs/hfsplus/xattr.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ static int hfsplus_create_attributes_file(struct super_block *sb)
258258
return err;
259259
}
260260

261+
static inline
262+
bool is_xattr_operation_supported(struct inode *inode)
263+
{
264+
if (HFSPLUS_IS_RSRC(inode))
265+
return false;
266+
267+
return true;
268+
}
269+
261270
int __hfsplus_setxattr(struct inode *inode, const char *name,
262271
const void *value, size_t size, int flags)
263272
{
@@ -268,9 +277,11 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
268277
u16 folder_finderinfo_len = sizeof(DInfo) + sizeof(DXInfo);
269278
u16 file_finderinfo_len = sizeof(FInfo) + sizeof(FXInfo);
270279

271-
if ((!S_ISREG(inode->i_mode) &&
272-
!S_ISDIR(inode->i_mode)) ||
273-
HFSPLUS_IS_RSRC(inode))
280+
hfs_dbg("ino %lu, name %s, value %p, size %zu\n",
281+
inode->i_ino, name ? name : NULL,
282+
value, size);
283+
284+
if (!is_xattr_operation_supported(inode))
274285
return -EOPNOTSUPP;
275286

276287
if (value == NULL)
@@ -390,6 +401,7 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
390401

391402
end_setxattr:
392403
hfs_find_exit(&cat_fd);
404+
hfs_dbg("finished: res %d\n", err);
393405
return err;
394406
}
395407

@@ -514,9 +526,7 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
514526
u16 record_length = 0;
515527
ssize_t res;
516528

517-
if ((!S_ISREG(inode->i_mode) &&
518-
!S_ISDIR(inode->i_mode)) ||
519-
HFSPLUS_IS_RSRC(inode))
529+
if (!is_xattr_operation_supported(inode))
520530
return -EOPNOTSUPP;
521531

522532
if (!strcmp_xattr_finder_info(name))
@@ -709,9 +719,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
709719

710720
hfs_dbg("ino %lu\n", inode->i_ino);
711721

712-
if ((!S_ISREG(inode->i_mode) &&
713-
!S_ISDIR(inode->i_mode)) ||
714-
HFSPLUS_IS_RSRC(inode))
722+
if (!is_xattr_operation_supported(inode))
715723
return -EOPNOTSUPP;
716724

717725
res = hfsplus_listxattr_finder_info(dentry, buffer, size);
@@ -737,8 +745,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
737745
err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
738746
if (err) {
739747
if (err == -ENOENT) {
740-
if (res == 0)
741-
res = -ENODATA;
748+
res = 0;
742749
goto end_listxattr;
743750
} else {
744751
res = err;

0 commit comments

Comments
 (0)