diff --git a/Documentation/filesystems/ntfs.rst b/Documentation/filesystems/ntfs.rst index 699e91f884d4..d5819da6ab53 100644 --- a/Documentation/filesystems/ntfs.rst +++ b/Documentation/filesystems/ntfs.rst @@ -38,15 +38,20 @@ The project is available at: Linux file attributes ===================== -The driver supports lsattr(1) and chattr(1). Immutable, append-only and -nodump are stored in a private ``$LINUXFLAGS`` extended attribute within the +The driver supports lsattr(1) and chattr(1). Immutable, append-only, nodump +and noatime are stored in a private ``$LINUXFLAGS`` extended attribute within the standard NTFS ``$EA``/``$EA_INFORMATION`` attributes. Its value is a 32-bit little-endian bitmask: bit 0 is immutable, bit 1 is append-only, -and bit 2 is nodump. Unknown bits are preserved when updating the flags; -the entry is removed when the entire value becomes zero. These settings +bit 2 is nodump, and bit 3 is noatime. Unknown bits are preserved when updating +the flags; the entry is removed when the entire value becomes zero. These settings survive inode eviction, unmount and reboot. Direct writes to this EA through setxattr(2) or removexattr(2) are rejected; use chattr(1) instead. +The noatime attribute (``chattr +A``) suppresses automatic access-time +updates for the inode, including when mounted with ``strictatime``. It +applies to directories as well as files, but is not inherited by newly +created children. Use ``chattr -A`` to restore the mount's access-time policy. + System metadata files and files protected by the ``sys_immutable`` mount option cannot have their immutable protection cleared with chattr(1). Protection derived solely from the mount option is not stored in the EA. @@ -55,7 +60,7 @@ configured per file. Compression and encryption are reported but cannot be changed through chattr(1). These Linux flags are enforced by Linux. Storing them in an NTFS EA does -not make Windows enforce immutable, append-only or nodump semantics. +not make Windows enforce immutable, append-only, nodump or noatime semantics. Supported mount options diff --git a/fs/ntfs/ea.c b/fs/ntfs/ea.c index 7a8094c543b9..fa5c5c625751 100644 --- a/fs/ntfs/ea.c +++ b/fs/ntfs/ea.c @@ -501,6 +501,8 @@ int ntfs_ea_get_linuxflags(struct inode *inode) inode->i_flags |= S_IMMUTABLE; if (ni->linuxflags & NTFS_LINUXFLAGS_APPEND) inode->i_flags |= S_APPEND; + if (ni->linuxflags & NTFS_LINUXFLAGS_NOATIME) + inode->i_flags |= S_NOATIME; return 0; } diff --git a/fs/ntfs/ea.h b/fs/ntfs/ea.h index 3d29fb35e076..f200d49063e0 100644 --- a/fs/ntfs/ea.h +++ b/fs/ntfs/ea.h @@ -11,8 +11,10 @@ #define NTFS_LINUXFLAGS_IMMUTABLE BIT(0) #define NTFS_LINUXFLAGS_APPEND BIT(1) #define NTFS_LINUXFLAGS_NODUMP BIT(2) +#define NTFS_LINUXFLAGS_NOATIME BIT(3) #define NTFS_LINUXFLAGS_MASK (NTFS_LINUXFLAGS_IMMUTABLE | \ - NTFS_LINUXFLAGS_APPEND | NTFS_LINUXFLAGS_NODUMP) + NTFS_LINUXFLAGS_APPEND | NTFS_LINUXFLAGS_NODUMP | \ + NTFS_LINUXFLAGS_NOATIME) extern const struct xattr_handler *const ntfs_xattr_handlers[]; diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index abec36f4e4bb..3334b56c7eaa 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -167,6 +167,8 @@ int ntfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) flags |= FS_IMMUTABLE_FL; if (vi->i_flags & S_APPEND) flags |= FS_APPEND_FL; + if (vi->i_flags & S_NOATIME) + flags |= FS_NOATIME_FL; if (ni->linuxflags & NTFS_LINUXFLAGS_NODUMP) flags |= FS_NODUMP_FL; if (!NVolCaseSensitive(ni->vol)) @@ -200,7 +202,8 @@ int ntfs_fileattr_set(const struct mnt_idmap *idmap, struct dentry *dentry, { struct inode *vi = d_inode(dentry); struct ntfs_inode *ni = NTFS_I(vi); - u32 allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL; + u32 allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | + FS_NOATIME_FL; u32 readonly = 0; u32 linuxflags = ni->linuxflags & ~NTFS_LINUXFLAGS_MASK; unsigned int new_fl = 0; @@ -245,6 +248,10 @@ int ntfs_fileattr_set(const struct mnt_idmap *idmap, struct dentry *dentry, } if (fa->flags & FS_NODUMP_FL) linuxflags |= NTFS_LINUXFLAGS_NODUMP; + if (fa->flags & FS_NOATIME_FL) { + new_fl |= S_NOATIME; + linuxflags |= NTFS_LINUXFLAGS_NOATIME; + } mutex_lock(&ni->mrec_lock); err = ntfs_ea_set_linuxflags(vi, linuxflags); @@ -252,7 +259,7 @@ int ntfs_fileattr_set(const struct mnt_idmap *idmap, struct dentry *dentry, if (err) return err; - inode_set_flags(vi, new_fl, S_IMMUTABLE | S_APPEND); + inode_set_flags(vi, new_fl, S_IMMUTABLE | S_APPEND | S_NOATIME); inode_set_ctime_current(vi); mark_inode_dirty(vi); return 0;