]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hfs: disable the updating of file access times (atime)
authorViacheslav Dubeyko <slava@dubeyko.com>
Thu, 14 May 2026 19:56:31 +0000 (12:56 -0700)
committerViacheslav Dubeyko <slava@dubeyko.com>
Tue, 19 May 2026 22:04:27 +0000 (15:04 -0700)
The xfstests' test-case generic/003 fails with errors:

sudo ./check generic/003
FSTYP -- hfs
PLATFORM -- Linux/x86_64 hfsplus-testing-0001 7.0.0-rc1+ #18 SMP PREEMPT_DYNAMIC Fri Mar 13 17:54:19 PDT 2026
MKFS_OPTIONS -- /dev/loop51
MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch

output mismatch
QA output created by 003
ERROR: access time has changed for file1 after remount
ERROR: access time has changed after modifying file1
ERROR: change time has not been updated after changing file1
ERROR: access time has changed for file in read-only filesystem
Silence is golden

This patch fixes the issue with change time by
adding inode_set_ctime_current() and mark_inode_dirty()
in hfs_rename(). Also, it reworks hfs_inode_setattr() by
changing simple_inode_init_ts() on inode_set_mtime_to_ts()
and inode_set_ctime_current() calls.

HFS hasn't any field in on-disk layout that can keep
the file/folder access times (atime). It was added
setting of SB_NOATIME in SB_NOATIME.

Finally, we have only atime related errors in
generic/003 output:

sudo ./check generic/003
FSTYP         -- hfs
PLATFORM      -- Linux/x86_64 hfsplus-testing-0001 7.1.0-rc1+ #52 SMP PREEMPT_DYNAMIC Wed May 13 15:04:37 PDT 2026
MKFS_OPTIONS  -- /dev/loop51
MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch

QA output created by 003
ERROR: access time has not been updated after accessing file1 first time
ERROR: access time has not been updated after accessing file2
ERROR: access time has not been updated after accessing file3 second time
ERROR: access time has not been updated after accessing file3 third time
Silence is golden

The generic/003 test-case needs to be disabled for HFS case
because it cannot support the file/folder access times (atime).

Closes: https://github.com/hfs-linux-kernel/hfs-linux-kernel/issues/3
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/20260514195630.354206-2-slava@dubeyko.com
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
fs/hfs/dir.c
fs/hfs/inode.c
fs/hfs/super.c

index f5e7efe924e7838d3ce3eadcaf275ca2332e90f3..702c16ea954bf76423e1f45645efd3d255aea109 100644 (file)
@@ -306,10 +306,15 @@ static int hfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
        res = hfs_cat_move(d_inode(old_dentry)->i_ino,
                           old_dir, &old_dentry->d_name,
                           new_dir, &new_dentry->d_name);
-       if (!res)
+       if (!res) {
+               struct inode *inode = d_inode(old_dentry);
+
                hfs_cat_build_key(old_dir->i_sb,
-                                 (btree_key *)&HFS_I(d_inode(old_dentry))->cat_key,
+                                 (btree_key *)&HFS_I(inode)->cat_key,
                                  new_dir->i_ino, &new_dentry->d_name);
+               inode_set_ctime_current(inode);
+               mark_inode_dirty(inode);
+       }
        return res;
 }
 
index 1cbba734503896484cdc3eadaede202a4b7e2d23..b2329de151ecaeaa8a1845272cfbe0b717268749 100644 (file)
@@ -348,6 +348,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
        struct hfs_iget_data *idata = data;
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
        hfs_cat_rec *rec;
+       struct timespec64 mtime;
 
        HFS_I(inode)->flags = 0;
        HFS_I(inode)->rsrc_inode = NULL;
@@ -383,8 +384,10 @@ static int hfs_read_inode(struct inode *inode, void *data)
                        inode->i_mode |= S_IWUGO;
                inode->i_mode &= ~hsb->s_file_umask;
                inode->i_mode |= S_IFREG;
-               inode_set_mtime_to_ts(inode,
-                                     inode_set_atime_to_ts(inode, inode_set_ctime_to_ts(inode, hfs_m_to_utime(rec->file.MdDat))));
+               mtime = hfs_m_to_utime(rec->file.MdDat);
+               inode_set_ctime_to_ts(inode, mtime);
+               inode_set_atime_to_ts(inode, mtime);
+               inode_set_mtime_to_ts(inode, mtime);
                inode->i_op = &hfs_file_inode_operations;
                inode->i_fop = &hfs_file_operations;
                inode->i_mapping->a_ops = &hfs_aops;
@@ -394,8 +397,10 @@ static int hfs_read_inode(struct inode *inode, void *data)
                inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
                HFS_I(inode)->fs_blocks = 0;
                inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
-               inode_set_mtime_to_ts(inode,
-                                     inode_set_atime_to_ts(inode, inode_set_ctime_to_ts(inode, hfs_m_to_utime(rec->dir.MdDat))));
+               mtime = hfs_m_to_utime(rec->dir.MdDat);
+               inode_set_ctime_to_ts(inode, mtime);
+               inode_set_atime_to_ts(inode, mtime);
+               inode_set_mtime_to_ts(inode, mtime);
                inode->i_op = &hfs_dir_inode_operations;
                inode->i_fop = &hfs_dir_operations;
                break;
@@ -665,7 +670,7 @@ int hfs_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 
                truncate_setsize(inode, attr->ia_size);
                hfs_file_truncate(inode);
-               simple_inode_init_ts(inode);
+               inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
        }
 
        setattr_copy(&nop_mnt_idmap, inode, attr);
index a4f2a2bfa6d30b897bdfb27c5ffda6339fd814a3..a466c401f6bb260d8f6365fa048c0203a7e11efa 100644 (file)
@@ -338,7 +338,7 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
        sbi->sb = sb;
        sb->s_op = &hfs_super_operations;
        sb->s_xattr = hfs_xattr_handlers;
-       sb->s_flags |= SB_NODIRATIME;
+       sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
        mutex_init(&sbi->bitmap_lock);
 
        res = hfs_mdb_get(sb);