diff mbox series

[RFC,2/4] fs: Extend FS_IOC_FS[GS]ETXATTR API for Windows attributes

Message ID 20250216164029.20673-3-pali@kernel.org (mailing list archive)
State New
Headers show
Series fs: Add support for Windows file attributes | expand

Commit Message

Pali Rohár Feb. 16, 2025, 4:40 p.m. UTC
struct fsxattr has 8 reserved padding bytes. Use these bytes for defining
new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward
compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is
not set then these new fields are treated as not present, like before this
change.

New field fsx_xflags_mask for SET operation specifies which flags in
fsx_xflags are going to be changed. This would allow userspace application
to change just subset of all flags. For GET operation this field specifies
which FS_XFLAG_* flags are supported by the file.

New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of
Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be
interpreted or used by the kernel, and are mostly going to be used by
userspace. Field fsx_xflags2_mask then specify mask for them.

This change defines just API without filesystem support for them. These
attributes can be implemented later for Windows filesystems like FAT, NTFS,
exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at
least some subset of them).

Signed-off-by: Pali Rohár <pali@kernel.org>
---
 include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++-----
 1 file changed, 31 insertions(+), 5 deletions(-)

Comments

Amir Goldstein Feb. 16, 2025, 7:55 p.m. UTC | #1
On Sun, Feb 16, 2025 at 5:42 PM Pali Rohár <pali@kernel.org> wrote:
>
> struct fsxattr has 8 reserved padding bytes. Use these bytes for defining
> new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward
> compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is
> not set then these new fields are treated as not present, like before this
> change.
>
> New field fsx_xflags_mask for SET operation specifies which flags in
> fsx_xflags are going to be changed. This would allow userspace application
> to change just subset of all flags. For GET operation this field specifies
> which FS_XFLAG_* flags are supported by the file.
>
> New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of
> Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be
> interpreted or used by the kernel, and are mostly going to be used by
> userspace. Field fsx_xflags2_mask then specify mask for them.
>
> This change defines just API without filesystem support for them. These
> attributes can be implemented later for Windows filesystems like FAT, NTFS,
> exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at
> least some subset of them).
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
>  include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++-----
>  1 file changed, 31 insertions(+), 5 deletions(-)
>
> diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
> index 367bc5289c47..93e947d6e604 100644
> --- a/include/uapi/linux/fs.h
> +++ b/include/uapi/linux/fs.h
> @@ -145,15 +145,26 @@ struct fsxattr {
>         __u32           fsx_nextents;   /* nextents field value (get)   */
>         __u32           fsx_projid;     /* project identifier (get/set) */
>         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> -       unsigned char   fsx_pad[8];
> +       __u16           fsx_xflags2;    /* xflags2 field value (get/set)*/
> +       __u16           fsx_xflags2_mask;/*mask for xflags2 (get/set)*/
> +       __u32           fsx_xflags_mask;/* mask for xflags (get/set)*/
> +       /*
> +        * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags
> +        * and fsx_xflags2 fields are going to be changed.
> +        *
> +        * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported.
> +        */
>  };
>
>  /*
> - * Flags for the fsx_xflags field
> + * Flags for the fsx_xflags and fsx_xflags_mask fields
>   */
>  #define FS_XFLAG_REALTIME      0x00000001      /* data in realtime volume */
>  #define FS_XFLAG_PREALLOC      0x00000002      /* preallocated file extents */
> -#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified */
> +#define FS_XFLAG_IMMUTABLEUSER 0x00000004      /* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */

So why not call it FS_XFLAG2_READONLY? IDGI

Does anyone think that FS_XFLAG_IMMUTABLEUSER is more clear or something?

Thanks,
Amir.

> +#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified, changing this bit requires CAP_LINUX_IMMUTABLE */
>  #define FS_XFLAG_APPEND                0x00000010      /* all writes append */
>  #define FS_XFLAG_SYNC          0x00000020      /* all writes synchronous */
>  #define FS_XFLAG_NOATIME       0x00000040      /* do not update access time */
> @@ -167,10 +178,25 @@ struct fsxattr {
>  #define FS_XFLAG_FILESTREAM    0x00004000      /* use filestream allocator */
>  #define FS_XFLAG_DAX           0x00008000      /* use DAX for IO */
>  #define FS_XFLAG_COWEXTSIZE    0x00010000      /* CoW extent size allocator hint */
> -#define FS_XFLAG_COMPRESSED    0x00020000      /* compressed file */
> -#define FS_XFLAG_ENCRYPTED     0x00040000      /* encrypted file */
> +#define FS_XFLAG_COMPRESSED    0x00020000      /* compressed file, equivalent of Windows FILE_ATTRIBUTE_COMPRESSED */
> +#define FS_XFLAG_ENCRYPTED     0x00040000      /* encrypted file, equivalent of Windows FILE_ATTRIBUTE_ENCRYPTED */
> +#define FS_XFLAG_CHECKSUMS     0x00080000      /* checksum for data and metadata, equivalent of Windows FILE_ATTRIBUTE_INTEGRITY_STREAM */
> +#define FS_XFLAG_HASEXTFIELDS  0x40000000      /* fields fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask are present */
>  #define FS_XFLAG_HASATTR       0x80000000      /* no DIFLAG for this   */
>
> +/*
> + * Flags for the fsx_xflags2 and fsx_xflags2_mask fields
> + */
> +#define FS_XFLAG2_HIDDEN       0x0001  /* inode is hidden, equivalent of Widows FILE_ATTRIBUTE_HIDDEN */
> +#define FS_XFLAG2_SYSTEM       0x0002  /* inode is part of operating system, equivalent of Windows FILE_ATTRIBUTE_SYSTEM */
> +#define FS_XFLAG2_ARCHIVE      0x0004  /* inode was not archived yet, equivalent of Windows FILE_ATTRIBUTE_ARCHIVE */
> +#define FS_XFLAG2_TEMPORARY    0x0008  /* inode content does not have to preserved across reboots, equivalent of Windows FILE_ATTRIBUTE_TEMPORARY */
> +#define FS_XFLAG2_NOTINDEXED   0x0010  /* inode will not be indexed by content indexing service, equivalent of Windows FILE_ATTRIBUTE_NOT_CONTENT_INDEXED */
> +#define FS_XFLAG2_NOSCRUBDATA  0x0020  /* file inode will not be checked by scrubber (proactive background data integrity scanner), for directory inode it means that newly created child would have this flag set, equivalent of Windows FILE_ATTRIBUTE_NO_SCRUB_DATA */
> +#define FS_XFLAG2_OFFLINE      0x0040  /* inode is marked as HSM offline, equivalent of Windows FILE_ATTRIBUTE_OFFLINE */
> +#define FS_XFLAG2_PINNED       0x0080  /* inode data content must be always stored in local HSM storage, equivalent of Windows FILE_ATTRIBUTE_PINNED */
> +#define FS_XFLAG2_UNPINNED     0x0100  /* inode data content can be removed from local HSM storage, equivalent of Windows FILE_ATTRIBUTE_UNPINNED */
> +
>  /* the read-only stuff doesn't really belong here, but any other place is
>     probably as bad and I don't want to create yet another include file. */
>
> --
> 2.20.1
>
Pali Rohár Feb. 16, 2025, 8:01 p.m. UTC | #2
On Sunday 16 February 2025 20:55:09 Amir Goldstein wrote:
> On Sun, Feb 16, 2025 at 5:42 PM Pali Rohár <pali@kernel.org> wrote:
> >
> > struct fsxattr has 8 reserved padding bytes. Use these bytes for defining
> > new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward
> > compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is
> > not set then these new fields are treated as not present, like before this
> > change.
> >
> > New field fsx_xflags_mask for SET operation specifies which flags in
> > fsx_xflags are going to be changed. This would allow userspace application
> > to change just subset of all flags. For GET operation this field specifies
> > which FS_XFLAG_* flags are supported by the file.
> >
> > New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of
> > Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be
> > interpreted or used by the kernel, and are mostly going to be used by
> > userspace. Field fsx_xflags2_mask then specify mask for them.
> >
> > This change defines just API without filesystem support for them. These
> > attributes can be implemented later for Windows filesystems like FAT, NTFS,
> > exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at
> > least some subset of them).
> >
> > Signed-off-by: Pali Rohár <pali@kernel.org>
> > ---
> >  include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++-----
> >  1 file changed, 31 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
> > index 367bc5289c47..93e947d6e604 100644
> > --- a/include/uapi/linux/fs.h
> > +++ b/include/uapi/linux/fs.h
> > @@ -145,15 +145,26 @@ struct fsxattr {
> >         __u32           fsx_nextents;   /* nextents field value (get)   */
> >         __u32           fsx_projid;     /* project identifier (get/set) */
> >         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > -       unsigned char   fsx_pad[8];
> > +       __u16           fsx_xflags2;    /* xflags2 field value (get/set)*/
> > +       __u16           fsx_xflags2_mask;/*mask for xflags2 (get/set)*/
> > +       __u32           fsx_xflags_mask;/* mask for xflags (get/set)*/
> > +       /*
> > +        * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags
> > +        * and fsx_xflags2 fields are going to be changed.
> > +        *
> > +        * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported.
> > +        */
> >  };
> >
> >  /*
> > - * Flags for the fsx_xflags field
> > + * Flags for the fsx_xflags and fsx_xflags_mask fields
> >   */
> >  #define FS_XFLAG_REALTIME      0x00000001      /* data in realtime volume */
> >  #define FS_XFLAG_PREALLOC      0x00000002      /* preallocated file extents */
> > -#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified */
> > +#define FS_XFLAG_IMMUTABLEUSER 0x00000004      /* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */
> 
> So why not call it FS_XFLAG2_READONLY? IDGI

Just because to show that these two flags are similar, just one is for
root (or CAP_LINUX_IMMUTABLE) and another is for normal user.

For example FreeBSD has also both flags (one for root and one for user)
and uses names SF_IMMUTABLE and UF_IMMUTABLE.

For me having FS_XFLAG_IMMUTABLE and FS_XFLAG2_READONLY sounds less
clear, and does not explain how these two flags differs.

> Does anyone think that FS_XFLAG_IMMUTABLEUSER is more clear or something?
> 
> Thanks,
> Amir.
> 
> > +#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified, changing this bit requires CAP_LINUX_IMMUTABLE */
> >  #define FS_XFLAG_APPEND                0x00000010      /* all writes append */
> >  #define FS_XFLAG_SYNC          0x00000020      /* all writes synchronous */
> >  #define FS_XFLAG_NOATIME       0x00000040      /* do not update access time */
> > @@ -167,10 +178,25 @@ struct fsxattr {
> >  #define FS_XFLAG_FILESTREAM    0x00004000      /* use filestream allocator */
> >  #define FS_XFLAG_DAX           0x00008000      /* use DAX for IO */
> >  #define FS_XFLAG_COWEXTSIZE    0x00010000      /* CoW extent size allocator hint */
> > -#define FS_XFLAG_COMPRESSED    0x00020000      /* compressed file */
> > -#define FS_XFLAG_ENCRYPTED     0x00040000      /* encrypted file */
> > +#define FS_XFLAG_COMPRESSED    0x00020000      /* compressed file, equivalent of Windows FILE_ATTRIBUTE_COMPRESSED */
> > +#define FS_XFLAG_ENCRYPTED     0x00040000      /* encrypted file, equivalent of Windows FILE_ATTRIBUTE_ENCRYPTED */
> > +#define FS_XFLAG_CHECKSUMS     0x00080000      /* checksum for data and metadata, equivalent of Windows FILE_ATTRIBUTE_INTEGRITY_STREAM */
> > +#define FS_XFLAG_HASEXTFIELDS  0x40000000      /* fields fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask are present */
> >  #define FS_XFLAG_HASATTR       0x80000000      /* no DIFLAG for this   */
> >
> > +/*
> > + * Flags for the fsx_xflags2 and fsx_xflags2_mask fields
> > + */
> > +#define FS_XFLAG2_HIDDEN       0x0001  /* inode is hidden, equivalent of Widows FILE_ATTRIBUTE_HIDDEN */
> > +#define FS_XFLAG2_SYSTEM       0x0002  /* inode is part of operating system, equivalent of Windows FILE_ATTRIBUTE_SYSTEM */
> > +#define FS_XFLAG2_ARCHIVE      0x0004  /* inode was not archived yet, equivalent of Windows FILE_ATTRIBUTE_ARCHIVE */
> > +#define FS_XFLAG2_TEMPORARY    0x0008  /* inode content does not have to preserved across reboots, equivalent of Windows FILE_ATTRIBUTE_TEMPORARY */
> > +#define FS_XFLAG2_NOTINDEXED   0x0010  /* inode will not be indexed by content indexing service, equivalent of Windows FILE_ATTRIBUTE_NOT_CONTENT_INDEXED */
> > +#define FS_XFLAG2_NOSCRUBDATA  0x0020  /* file inode will not be checked by scrubber (proactive background data integrity scanner), for directory inode it means that newly created child would have this flag set, equivalent of Windows FILE_ATTRIBUTE_NO_SCRUB_DATA */
> > +#define FS_XFLAG2_OFFLINE      0x0040  /* inode is marked as HSM offline, equivalent of Windows FILE_ATTRIBUTE_OFFLINE */
> > +#define FS_XFLAG2_PINNED       0x0080  /* inode data content must be always stored in local HSM storage, equivalent of Windows FILE_ATTRIBUTE_PINNED */
> > +#define FS_XFLAG2_UNPINNED     0x0100  /* inode data content can be removed from local HSM storage, equivalent of Windows FILE_ATTRIBUTE_UNPINNED */
> > +
> >  /* the read-only stuff doesn't really belong here, but any other place is
> >     probably as bad and I don't want to create yet another include file. */
> >
> > --
> > 2.20.1
> >
Amir Goldstein Feb. 16, 2025, 8:34 p.m. UTC | #3
On Sun, Feb 16, 2025 at 9:01 PM Pali Rohár <pali@kernel.org> wrote:
>
> On Sunday 16 February 2025 20:55:09 Amir Goldstein wrote:
> > On Sun, Feb 16, 2025 at 5:42 PM Pali Rohár <pali@kernel.org> wrote:
> > >
> > > struct fsxattr has 8 reserved padding bytes. Use these bytes for defining
> > > new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward
> > > compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is
> > > not set then these new fields are treated as not present, like before this
> > > change.
> > >
> > > New field fsx_xflags_mask for SET operation specifies which flags in
> > > fsx_xflags are going to be changed. This would allow userspace application
> > > to change just subset of all flags. For GET operation this field specifies
> > > which FS_XFLAG_* flags are supported by the file.
> > >
> > > New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of
> > > Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be
> > > interpreted or used by the kernel, and are mostly going to be used by
> > > userspace. Field fsx_xflags2_mask then specify mask for them.
> > >
> > > This change defines just API without filesystem support for them. These
> > > attributes can be implemented later for Windows filesystems like FAT, NTFS,
> > > exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at
> > > least some subset of them).
> > >
> > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > ---
> > >  include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++-----
> > >  1 file changed, 31 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
> > > index 367bc5289c47..93e947d6e604 100644
> > > --- a/include/uapi/linux/fs.h
> > > +++ b/include/uapi/linux/fs.h
> > > @@ -145,15 +145,26 @@ struct fsxattr {
> > >         __u32           fsx_nextents;   /* nextents field value (get)   */
> > >         __u32           fsx_projid;     /* project identifier (get/set) */
> > >         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > > -       unsigned char   fsx_pad[8];
> > > +       __u16           fsx_xflags2;    /* xflags2 field value (get/set)*/
> > > +       __u16           fsx_xflags2_mask;/*mask for xflags2 (get/set)*/
> > > +       __u32           fsx_xflags_mask;/* mask for xflags (get/set)*/
> > > +       /*
> > > +        * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags
> > > +        * and fsx_xflags2 fields are going to be changed.
> > > +        *
> > > +        * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported.
> > > +        */
> > >  };
> > >
> > >  /*
> > > - * Flags for the fsx_xflags field
> > > + * Flags for the fsx_xflags and fsx_xflags_mask fields
> > >   */
> > >  #define FS_XFLAG_REALTIME      0x00000001      /* data in realtime volume */
> > >  #define FS_XFLAG_PREALLOC      0x00000002      /* preallocated file extents */
> > > -#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified */
> > > +#define FS_XFLAG_IMMUTABLEUSER 0x00000004      /* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */
> >
> > So why not call it FS_XFLAG2_READONLY? IDGI
>
> Just because to show that these two flags are similar, just one is for
> root (or CAP_LINUX_IMMUTABLE) and another is for normal user.
>
> For example FreeBSD has also both flags (one for root and one for user)
> and uses names SF_IMMUTABLE and UF_IMMUTABLE.
>
> For me having FS_XFLAG_IMMUTABLE and FS_XFLAG2_READONLY sounds less
> clear, and does not explain how these two flags differs.
>

Yes, I understand, but I do not agree.

What is your goal here?

Do you want to implement FreeBSD UF_IMMUTABLE?
maybe UF_APPEND as well?
Did anyone ask for this functionality?
Not that I know of.
The requirement is to implement an API to the functionality known
as READONLY in SMB and NTFS. Right?

TBH, I did not study the semantics of READONLY, but I had a
strong feeling that if we looked closely, we will find that other things are
possible to do with READONLY files that are not possible with IMMUTABLE
files. So I asked ChatGPT and it told me that all these can be changed:
1. File Attributes (Hidden, System, Archive, or Indexed).
2. Permissions (ACL - Access Control List)
3. Timestamps
4. Alternate Data Streams (ADS)

I do not know if ChatGPT is correct, but it also told me that a READONLY
file can be deleted (without removing the flag first).

This is very very far from what IS_IMMUTABLE is.
IS_IMMUTABLE is immutable to any metadata change.

Thanks,
Amir.
Pali Rohár Feb. 16, 2025, 9:01 p.m. UTC | #4
On Sunday 16 February 2025 21:34:42 Amir Goldstein wrote:
> On Sun, Feb 16, 2025 at 9:01 PM Pali Rohár <pali@kernel.org> wrote:
> >
> > On Sunday 16 February 2025 20:55:09 Amir Goldstein wrote:
> > > On Sun, Feb 16, 2025 at 5:42 PM Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > struct fsxattr has 8 reserved padding bytes. Use these bytes for defining
> > > > new fields fsx_xflags2, fsx_xflags2_mask and fsx_xflags_mask in backward
> > > > compatible manner. If the new FS_XFLAG_HASEXTFIELDS flag in fsx_xflags is
> > > > not set then these new fields are treated as not present, like before this
> > > > change.
> > > >
> > > > New field fsx_xflags_mask for SET operation specifies which flags in
> > > > fsx_xflags are going to be changed. This would allow userspace application
> > > > to change just subset of all flags. For GET operation this field specifies
> > > > which FS_XFLAG_* flags are supported by the file.
> > > >
> > > > New field fsx_xflags2 specify new flags FS_XFLAG2_* which defines some of
> > > > Windows FILE_ATTRIBUTE_* attributes, which are mostly not going to be
> > > > interpreted or used by the kernel, and are mostly going to be used by
> > > > userspace. Field fsx_xflags2_mask then specify mask for them.
> > > >
> > > > This change defines just API without filesystem support for them. These
> > > > attributes can be implemented later for Windows filesystems like FAT, NTFS,
> > > > exFAT, UDF, SMB, NFS4 which all native storage for those attributes (or at
> > > > least some subset of them).
> > > >
> > > > Signed-off-by: Pali Rohár <pali@kernel.org>
> > > > ---
> > > >  include/uapi/linux/fs.h | 36 +++++++++++++++++++++++++++++++-----
> > > >  1 file changed, 31 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
> > > > index 367bc5289c47..93e947d6e604 100644
> > > > --- a/include/uapi/linux/fs.h
> > > > +++ b/include/uapi/linux/fs.h
> > > > @@ -145,15 +145,26 @@ struct fsxattr {
> > > >         __u32           fsx_nextents;   /* nextents field value (get)   */
> > > >         __u32           fsx_projid;     /* project identifier (get/set) */
> > > >         __u32           fsx_cowextsize; /* CoW extsize field value (get/set)*/
> > > > -       unsigned char   fsx_pad[8];
> > > > +       __u16           fsx_xflags2;    /* xflags2 field value (get/set)*/
> > > > +       __u16           fsx_xflags2_mask;/*mask for xflags2 (get/set)*/
> > > > +       __u32           fsx_xflags_mask;/* mask for xflags (get/set)*/
> > > > +       /*
> > > > +        * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > > > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags
> > > > +        * and fsx_xflags2 fields are going to be changed.
> > > > +        *
> > > > +        * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
> > > > +        * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported.
> > > > +        */
> > > >  };
> > > >
> > > >  /*
> > > > - * Flags for the fsx_xflags field
> > > > + * Flags for the fsx_xflags and fsx_xflags_mask fields
> > > >   */
> > > >  #define FS_XFLAG_REALTIME      0x00000001      /* data in realtime volume */
> > > >  #define FS_XFLAG_PREALLOC      0x00000002      /* preallocated file extents */
> > > > -#define FS_XFLAG_IMMUTABLE     0x00000008      /* file cannot be modified */
> > > > +#define FS_XFLAG_IMMUTABLEUSER 0x00000004      /* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */
> > >
> > > So why not call it FS_XFLAG2_READONLY? IDGI
> >
> > Just because to show that these two flags are similar, just one is for
> > root (or CAP_LINUX_IMMUTABLE) and another is for normal user.
> >
> > For example FreeBSD has also both flags (one for root and one for user)
> > and uses names SF_IMMUTABLE and UF_IMMUTABLE.
> >
> > For me having FS_XFLAG_IMMUTABLE and FS_XFLAG2_READONLY sounds less
> > clear, and does not explain how these two flags differs.
> >
> 
> Yes, I understand, but I do not agree.
> 
> What is your goal here?
> 
> Do you want to implement FreeBSD UF_IMMUTABLE?
> maybe UF_APPEND as well?
> Did anyone ask for this functionality?
> Not that I know of.

None of those.

> The requirement is to implement an API to the functionality known
> as READONLY in SMB and NTFS. Right?

Yes. But Linux is already calling this functionality as "immutable", not
as "readonly". That is why I thought that using existing name is better
than inventing a new name for some existing functionality.

> TBH, I did not study the semantics of READONLY, but I had a
> strong feeling that if we looked closely, we will find that other things are
> possible to do with READONLY files that are not possible with IMMUTABLE
> files. So I asked ChatGPT and it told me that all these can be changed:
> 1. File Attributes (Hidden, System, Archive, or Indexed).
> 2. Permissions (ACL - Access Control List)
> 3. Timestamps
> 4. Alternate Data Streams (ADS)
> 
> I do not know if ChatGPT is correct

Do not trust ChatGPT.

Modification of main data stream (= file content) or alternate data
streams is not possible.

Changing of file or extended attributes is possible.
Timestamp is a file attribute. xattrs are extended attributes.

About ACL I was not sure. But now I tried it and changing ACL is
possible even with readonly attribute set.

So 1. 2. and 3. is possible to change. 4. not.

> but it also told me that a READONLY
> file can be deleted (without removing the flag first).

That is wrong. File cannot be deleted if the READONLY attribute is set.
You first need to clear the READONLY flag. This is one of the main point
of READONLY attribute.

For example cifs.ko for unlink syscall issue SMB removal and if it is
failing due to readonly attribute, it clears it and try removal again.

> This is very very far from what IS_IMMUTABLE is.
> IS_IMMUTABLE is immutable to any metadata change.

I was always looking at this readonly attribute as IMMUTABLE as it
prevents modification of file content and prevents unlinking the file.

For me it was always very similar to immutable. But if you think that
changing ACL and file/extended attributes is the reason why it should
not be called immutable, then I'm fine. Maybe it needs better
documentation and explanation what each of those two flags can and
cannot do.

> Thanks,
> Amir.
diff mbox series

Patch

diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 367bc5289c47..93e947d6e604 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -145,15 +145,26 @@  struct fsxattr {
 	__u32		fsx_nextents;	/* nextents field value (get)	*/
 	__u32		fsx_projid;	/* project identifier (get/set) */
 	__u32		fsx_cowextsize;	/* CoW extsize field value (get/set)*/
-	unsigned char	fsx_pad[8];
+	__u16		fsx_xflags2;	/* xflags2 field value (get/set)*/
+	__u16		fsx_xflags2_mask;/*mask for xflags2 (get/set)*/
+	__u32		fsx_xflags_mask;/* mask for xflags (get/set)*/
+	/*
+	 * For FS_IOC_FSSETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
+	 * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags from fsx_xflags
+	 * and fsx_xflags2 fields are going to be changed.
+	 *
+	 * For FS_IOC_FSGETXATTR ioctl, fsx_xflags_mask and fsx_xflags2_mask
+	 * fields specify which FS_XFLAG_* and FS_XFLAG2_* flags are supported.
+	 */
 };
 
 /*
- * Flags for the fsx_xflags field
+ * Flags for the fsx_xflags and fsx_xflags_mask fields
  */
 #define FS_XFLAG_REALTIME	0x00000001	/* data in realtime volume */
 #define FS_XFLAG_PREALLOC	0x00000002	/* preallocated file extents */
-#define FS_XFLAG_IMMUTABLE	0x00000008	/* file cannot be modified */
+#define FS_XFLAG_IMMUTABLEUSER	0x00000004	/* file cannot be modified, changing this bit does not require CAP_LINUX_IMMUTABLE, equivalent of Windows FILE_ATTRIBUTE_READONLY */
+#define FS_XFLAG_IMMUTABLE	0x00000008	/* file cannot be modified, changing this bit requires CAP_LINUX_IMMUTABLE */
 #define FS_XFLAG_APPEND		0x00000010	/* all writes append */
 #define FS_XFLAG_SYNC		0x00000020	/* all writes synchronous */
 #define FS_XFLAG_NOATIME	0x00000040	/* do not update access time */
@@ -167,10 +178,25 @@  struct fsxattr {
 #define FS_XFLAG_FILESTREAM	0x00004000	/* use filestream allocator */
 #define FS_XFLAG_DAX		0x00008000	/* use DAX for IO */
 #define FS_XFLAG_COWEXTSIZE	0x00010000	/* CoW extent size allocator hint */
-#define FS_XFLAG_COMPRESSED	0x00020000	/* compressed file */
-#define FS_XFLAG_ENCRYPTED	0x00040000	/* encrypted file */
+#define FS_XFLAG_COMPRESSED	0x00020000	/* compressed file, equivalent of Windows FILE_ATTRIBUTE_COMPRESSED */
+#define FS_XFLAG_ENCRYPTED	0x00040000	/* encrypted file, equivalent of Windows FILE_ATTRIBUTE_ENCRYPTED */
+#define FS_XFLAG_CHECKSUMS	0x00080000	/* checksum for data and metadata, equivalent of Windows FILE_ATTRIBUTE_INTEGRITY_STREAM */
+#define FS_XFLAG_HASEXTFIELDS	0x40000000	/* fields fsx_xflags_mask, fsx_xflags2 and fsx_xflags2_mask are present */
 #define FS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
 
+/*
+ * Flags for the fsx_xflags2 and fsx_xflags2_mask fields
+ */
+#define FS_XFLAG2_HIDDEN	0x0001	/* inode is hidden, equivalent of Widows FILE_ATTRIBUTE_HIDDEN */
+#define FS_XFLAG2_SYSTEM	0x0002	/* inode is part of operating system, equivalent of Windows FILE_ATTRIBUTE_SYSTEM */
+#define FS_XFLAG2_ARCHIVE	0x0004	/* inode was not archived yet, equivalent of Windows FILE_ATTRIBUTE_ARCHIVE */
+#define FS_XFLAG2_TEMPORARY	0x0008	/* inode content does not have to preserved across reboots, equivalent of Windows FILE_ATTRIBUTE_TEMPORARY */
+#define FS_XFLAG2_NOTINDEXED	0x0010	/* inode will not be indexed by content indexing service, equivalent of Windows FILE_ATTRIBUTE_NOT_CONTENT_INDEXED */
+#define FS_XFLAG2_NOSCRUBDATA	0x0020	/* file inode will not be checked by scrubber (proactive background data integrity scanner), for directory inode it means that newly created child would have this flag set, equivalent of Windows FILE_ATTRIBUTE_NO_SCRUB_DATA */
+#define FS_XFLAG2_OFFLINE	0x0040	/* inode is marked as HSM offline, equivalent of Windows FILE_ATTRIBUTE_OFFLINE */
+#define FS_XFLAG2_PINNED	0x0080	/* inode data content must be always stored in local HSM storage, equivalent of Windows FILE_ATTRIBUTE_PINNED */
+#define FS_XFLAG2_UNPINNED	0x0100	/* inode data content can be removed from local HSM storage, equivalent of Windows FILE_ATTRIBUTE_UNPINNED */
+
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */