[PATCH v2 10/10] ntfs: persist nodump in the $LXFLAGS EA

From: Baolin Liu

Date: Sun Sep 20 2026 - 04:33:12 EST


From: Baolin Liu <liubaolin@xxxxxxxxxx>

Store nodump in bit 2 of LXFLAGS and allow it through fileattr_set.
Report the cached persistent bit through fileattr_get and
STATX_ATTR_NODUMP, including the statx supported-attribute mask. Reuse
the existing EA update and inode-load paths; nodump needs no additional
inode flag enforcement.

Document the complete immutable, append-only and nodump bitmask.

Signed-off-by: Baolin Liu <liubaolin@xxxxxxxxxx>
---
Documentation/filesystems/ntfs.rst | 34 +++++++++++++++++-------------
fs/ntfs/ea.h | 3 ++-
fs/ntfs/file.c | 11 ++++++++--
3 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/Documentation/filesystems/ntfs.rst b/Documentation/filesystems/ntfs.rst
index f00b618a3911..8b71bc6fca81 100644
--- a/Documentation/filesystems/ntfs.rst
+++ b/Documentation/filesystems/ntfs.rst
@@ -38,21 +38,25 @@ The project is available at:
Linux file attributes
=====================

-The driver supports lsattr(1) and setting immutable and append-only with chattr(1).
-Immutable is stored in bit 0 and append-only in bit 1 of a private ``$LXFLAGS`` extended attribute
-within the standard NTFS ``$EA``/``$EA_INFORMATION`` attributes. Its value
-is a 32-bit little-endian bitmask. Unknown bits are preserved; the entry
-is removed when the entire value becomes zero. These settings survive
-inode eviction, unmount and reboot. Direct writes or removal through
-xattr interfaces are rejected; use chattr(1) instead.
-
-System metadata files and files protected by ``sys_immutable`` cannot
-have their immutable protection cleared. Protection derived solely from
-that policy is not stored in the EA. Compression, encryption
-and mount-wide case folding are reported but cannot be changed through
-chattr(1).
-
-Windows does not enforce the Linux immutable and append-only flags stored in this EA.
+The driver supports lsattr(1) and chattr(1). Immutable, append-only and
+nodump are stored in a private ``$LXFLAGS`` 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
+survive inode eviction, unmount and reboot. Direct writes to this EA
+through setxattr(2) or removexattr(2) are rejected; use chattr(1) instead.
+
+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.
+Case folding is reported according to the mount options and cannot be
+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.
+

Supported mount options
=======================
diff --git a/fs/ntfs/ea.h b/fs/ntfs/ea.h
index eac5ab4da44a..d66cdb4e2fe1 100644
--- a/fs/ntfs/ea.h
+++ b/fs/ntfs/ea.h
@@ -10,8 +10,9 @@
/* $LXFLAGS stores these bits in a single little-endian 32-bit value. */
#define NTFS_LXFLAGS_IMMUTABLE BIT(0)
#define NTFS_LXFLAGS_APPEND BIT(1)
+#define NTFS_LXFLAGS_NODUMP BIT(2)
#define NTFS_LXFLAGS_MASK (NTFS_LXFLAGS_IMMUTABLE | \
- NTFS_LXFLAGS_APPEND)
+ NTFS_LXFLAGS_APPEND | NTFS_LXFLAGS_NODUMP)

extern const struct xattr_handler *const ntfs_xattr_handlers[];

diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 5b2a31790275..421dfa34ee7f 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -159,6 +159,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 (ni->lxflags & NTFS_LXFLAGS_NODUMP)
+ flags |= FS_NODUMP_FL;
if (!NVolCaseSensitive(ni->vol))
flags |= FS_CASEFOLD_FL;

@@ -190,7 +192,7 @@ int ntfs_fileattr_set(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;
+ u32 allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL;
u32 readonly = 0;
u32 lxflags = ni->lxflags & ~NTFS_LXFLAGS_MASK;
unsigned int new_fl = 0;
@@ -233,6 +235,8 @@ int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
new_fl |= S_APPEND;
lxflags |= NTFS_LXFLAGS_APPEND;
}
+ if (fa->flags & FS_NODUMP_FL)
+ lxflags |= NTFS_LXFLAGS_NODUMP;

mutex_lock(&ni->mrec_lock);
err = ntfs_ea_set_lxflags(vi, lxflags);
@@ -507,9 +511,12 @@ int ntfs_getattr(struct mnt_idmap *idmap, const struct path *path,

if (inode->i_flags & S_APPEND)
stat->attributes |= STATX_ATTR_APPEND;
+ if (ni->lxflags & NTFS_LXFLAGS_NODUMP)
+ stat->attributes |= STATX_ATTR_NODUMP;

stat->attributes_mask |= STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED |
- STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND;
+ STATX_ATTR_IMMUTABLE | STATX_ATTR_APPEND |
+ STATX_ATTR_NODUMP;

/*
* If it's a compressed or encrypted file, NTFS currently
--
2.51.0