diff mbox series

mm/shmem: add support for FS_IOC_[SG]ETFLAGS for tmpfs

Message ID 20220713145234.2356641-1-tytso@mit.edu (mailing list archive)
State New
Headers show
Series mm/shmem: add support for FS_IOC_[SG]ETFLAGS for tmpfs | expand

Commit Message

Theodore Ts'o July 13, 2022, 2:52 p.m. UTC
This allows userspace to set flags like FS_APPEND_FL, FS_IMMUTABLE_FL,
FS_NODUMP_FL, etc., like all other standard Linux file systems.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
 include/linux/shmem_fs.h | 11 +++++++
 mm/shmem.c               | 65 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 1 deletion(-)

Comments

Andrew Morton July 13, 2022, 7:11 p.m. UTC | #1
On Wed, 13 Jul 2022 10:52:34 -0400 "Theodore Ts'o" <tytso@mit.edu> wrote:

> This allows userspace to set flags like FS_APPEND_FL, FS_IMMUTABLE_FL,
> FS_NODUMP_FL, etc., like all other standard Linux file systems.
> 
> ...
>
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -28,6 +28,7 @@
>  #include <linux/ramfs.h>
>  #include <linux/pagemap.h>
>  #include <linux/file.h>
> +#include <linux/fileattr.h>
>  #include <linux/mm.h>
>  #include <linux/random.h>
>  #include <linux/sched/signal.h>
> @@ -1058,6 +1059,15 @@ static int shmem_getattr(struct user_namespace *mnt_userns,
>  		shmem_recalc_inode(inode);
>  		spin_unlock_irq(&info->lock);
>  	}
> +	if (info->fsflags & EXT2_APPEND_FL)
> +		stat->attributes |= STATX_ATTR_APPEND;
> +	if (info->fsflags & EXT2_IMMUTABLE_FL)
> +		stat->attributes |= STATX_ATTR_IMMUTABLE;
> +	if (info->fsflags & EXT2_NODUMP_FL)
> +		stat->attributes |= STATX_ATTR_NODUMP;
> +	stat->attributes_mask |= (STATX_ATTR_APPEND |
> +			STATX_ATTR_IMMUTABLE |
> +			STATX_ATTR_NODUMP);
>  	generic_fillattr(&init_user_ns, inode, stat);
>  
>  	if (shmem_is_huge(NULL, inode, 0))

hm, how did you even test this?

mm/shmem.c: In function 'shmem_getattr':
mm/shmem.c:1062:29: error: 'EXT2_APPEND_FL' undeclared (first use in this function); did you mean 'FS_APPEND_FL'?
 1062 |         if (info->fsflags & EXT2_APPEND_FL)
      |                             ^~~~~~~~~~~~~~
      |                             FS_APPEND_FL


this

--- a/mm/shmem.c~mm-shmem-add-support-for-fs_ioc_etflags-for-tmpfs-fix-2
+++ a/mm/shmem.c
@@ -40,6 +40,8 @@
 #include <linux/swapfile.h>
 #include "swap.h"
 
+#include <../fs/ext2/ext2.h>
+
 static struct vfsmount *shm_mnt;
 
 #ifdef CONFIG_SHMEM

seems quite wrong.
Theodore Ts'o July 14, 2022, 1:40 a.m. UTC | #2
On Wed, Jul 13, 2022 at 12:11:22PM -0700, Andrew Morton wrote:
> 
> hm, how did you even test this?

Sorry, I dropped the -a from "git commit --amend -a".

A corrected version is coming up...

				- Ted
kernel test robot July 14, 2022, 11:01 p.m. UTC | #3
Hi Theodore,

I love your patch! Yet something to improve:

[auto build test ERROR on akpm-mm/mm-everything]

url:    https://github.com/intel-lab-lkp/linux/commits/Theodore-Ts-o/mm-shmem-add-support-for-FS_IOC_-SG-ETFLAGS-for-tmpfs/20220713-225257
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
config: hexagon-randconfig-r024-20220714 (https://download.01.org/0day-ci/archive/20220715/202207150617.dHbSxB55-lkp@intel.com/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 5e61b9c556267086ef9b743a0b57df302eef831b)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/2a3164ac6dafb6c7a3cd8a1002e89370eec359c1
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Theodore-Ts-o/mm-shmem-add-support-for-FS_IOC_-SG-ETFLAGS-for-tmpfs/20220713-225257
        git checkout 2a3164ac6dafb6c7a3cd8a1002e89370eec359c1
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> mm/shmem.c:1062:22: error: use of undeclared identifier 'EXT2_APPEND_FL'
           if (info->fsflags & EXT2_APPEND_FL)
                               ^
>> mm/shmem.c:1064:22: error: use of undeclared identifier 'EXT2_IMMUTABLE_FL'
           if (info->fsflags & EXT2_IMMUTABLE_FL)
                               ^
>> mm/shmem.c:1066:22: error: use of undeclared identifier 'EXT2_NODUMP_FL'
           if (info->fsflags & EXT2_NODUMP_FL)
                               ^
>> mm/shmem.c:2840:5: warning: no previous prototype for function 'shmem_fileattr_get' [-Wmissing-prototypes]
   int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
       ^
   mm/shmem.c:2840:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
   ^
   static 
>> mm/shmem.c:2851:5: warning: no previous prototype for function 'shmem_fileattr_set' [-Wmissing-prototypes]
   int shmem_fileattr_set(struct user_namespace *mnt_userns,
       ^
   mm/shmem.c:2851:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int shmem_fileattr_set(struct user_namespace *mnt_userns,
   ^
   static 
   2 warnings and 3 errors generated.


vim +/EXT2_APPEND_FL +1062 mm/shmem.c

  1049	
  1050	static int shmem_getattr(struct user_namespace *mnt_userns,
  1051				 const struct path *path, struct kstat *stat,
  1052				 u32 request_mask, unsigned int query_flags)
  1053	{
  1054		struct inode *inode = path->dentry->d_inode;
  1055		struct shmem_inode_info *info = SHMEM_I(inode);
  1056	
  1057		if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
  1058			spin_lock_irq(&info->lock);
  1059			shmem_recalc_inode(inode);
  1060			spin_unlock_irq(&info->lock);
  1061		}
> 1062		if (info->fsflags & EXT2_APPEND_FL)
  1063			stat->attributes |= STATX_ATTR_APPEND;
> 1064		if (info->fsflags & EXT2_IMMUTABLE_FL)
  1065			stat->attributes |= STATX_ATTR_IMMUTABLE;
> 1066		if (info->fsflags & EXT2_NODUMP_FL)
  1067			stat->attributes |= STATX_ATTR_NODUMP;
  1068		stat->attributes_mask |= (STATX_ATTR_APPEND |
  1069				STATX_ATTR_IMMUTABLE |
  1070				STATX_ATTR_NODUMP);
  1071		generic_fillattr(&init_user_ns, inode, stat);
  1072	
  1073		if (shmem_is_huge(NULL, inode, 0))
  1074			stat->blksize = HPAGE_PMD_SIZE;
  1075	
  1076		if (request_mask & STATX_BTIME) {
  1077			stat->result_mask |= STATX_BTIME;
  1078			stat->btime.tv_sec = info->i_crtime.tv_sec;
  1079			stat->btime.tv_nsec = info->i_crtime.tv_nsec;
  1080		}
  1081	
  1082		return 0;
  1083	}
  1084
kernel test robot July 14, 2022, 11:11 p.m. UTC | #4
Hi Theodore,

I love your patch! Yet something to improve:

[auto build test ERROR on akpm-mm/mm-everything]

url:    https://github.com/intel-lab-lkp/linux/commits/Theodore-Ts-o/mm-shmem-add-support-for-FS_IOC_-SG-ETFLAGS-for-tmpfs/20220713-225257
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
config: um-i386_defconfig (https://download.01.org/0day-ci/archive/20220715/202207150754.j4ldkYik-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/2a3164ac6dafb6c7a3cd8a1002e89370eec359c1
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Theodore-Ts-o/mm-shmem-add-support-for-FS_IOC_-SG-ETFLAGS-for-tmpfs/20220713-225257
        git checkout 2a3164ac6dafb6c7a3cd8a1002e89370eec359c1
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=um SUBARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   mm/shmem.c: In function 'shmem_getattr':
>> mm/shmem.c:1062:29: error: 'EXT2_APPEND_FL' undeclared (first use in this function); did you mean 'FS_APPEND_FL'?
    1062 |         if (info->fsflags & EXT2_APPEND_FL)
         |                             ^~~~~~~~~~~~~~
         |                             FS_APPEND_FL
   mm/shmem.c:1062:29: note: each undeclared identifier is reported only once for each function it appears in
>> mm/shmem.c:1064:29: error: 'EXT2_IMMUTABLE_FL' undeclared (first use in this function); did you mean 'FS_IMMUTABLE_FL'?
    1064 |         if (info->fsflags & EXT2_IMMUTABLE_FL)
         |                             ^~~~~~~~~~~~~~~~~
         |                             FS_IMMUTABLE_FL
>> mm/shmem.c:1066:29: error: 'EXT2_NODUMP_FL' undeclared (first use in this function); did you mean 'FS_NODUMP_FL'?
    1066 |         if (info->fsflags & EXT2_NODUMP_FL)
         |                             ^~~~~~~~~~~~~~
         |                             FS_NODUMP_FL
   mm/shmem.c: At top level:
>> mm/shmem.c:2840:5: warning: no previous prototype for 'shmem_fileattr_get' [-Wmissing-prototypes]
    2840 | int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
         |     ^~~~~~~~~~~~~~~~~~
>> mm/shmem.c:2851:5: warning: no previous prototype for 'shmem_fileattr_set' [-Wmissing-prototypes]
    2851 | int shmem_fileattr_set(struct user_namespace *mnt_userns,
         |     ^~~~~~~~~~~~~~~~~~


vim +1062 mm/shmem.c

  1049	
  1050	static int shmem_getattr(struct user_namespace *mnt_userns,
  1051				 const struct path *path, struct kstat *stat,
  1052				 u32 request_mask, unsigned int query_flags)
  1053	{
  1054		struct inode *inode = path->dentry->d_inode;
  1055		struct shmem_inode_info *info = SHMEM_I(inode);
  1056	
  1057		if (info->alloced - info->swapped != inode->i_mapping->nrpages) {
  1058			spin_lock_irq(&info->lock);
  1059			shmem_recalc_inode(inode);
  1060			spin_unlock_irq(&info->lock);
  1061		}
> 1062		if (info->fsflags & EXT2_APPEND_FL)
  1063			stat->attributes |= STATX_ATTR_APPEND;
> 1064		if (info->fsflags & EXT2_IMMUTABLE_FL)
  1065			stat->attributes |= STATX_ATTR_IMMUTABLE;
> 1066		if (info->fsflags & EXT2_NODUMP_FL)
  1067			stat->attributes |= STATX_ATTR_NODUMP;
  1068		stat->attributes_mask |= (STATX_ATTR_APPEND |
  1069				STATX_ATTR_IMMUTABLE |
  1070				STATX_ATTR_NODUMP);
  1071		generic_fillattr(&init_user_ns, inode, stat);
  1072	
  1073		if (shmem_is_huge(NULL, inode, 0))
  1074			stat->blksize = HPAGE_PMD_SIZE;
  1075	
  1076		if (request_mask & STATX_BTIME) {
  1077			stat->result_mask |= STATX_BTIME;
  1078			stat->btime.tv_sec = info->i_crtime.tv_sec;
  1079			stat->btime.tv_nsec = info->i_crtime.tv_nsec;
  1080		}
  1081	
  1082		return 0;
  1083	}
  1084
Arnd Bergmann July 15, 2022, 11:09 a.m. UTC | #5
On Fri, Jul 15, 2022 at 1:01 AM kernel test robot <lkp@intel.com> wrote:
>
> >> mm/shmem.c:1062:22: error: use of undeclared identifier 'EXT2_APPEND_FL'
>            if (info->fsflags & EXT2_APPEND_FL)
>                                ^
> >> mm/shmem.c:1064:22: error: use of undeclared identifier 'EXT2_IMMUTABLE_FL'
>            if (info->fsflags & EXT2_IMMUTABLE_FL)
>                                ^
> >> mm/shmem.c:1066:22: error: use of undeclared identifier 'EXT2_NODUMP_FL'
>            if (info->fsflags & EXT2_NODUMP_FL)
>                                ^


I suppose this just needs to use FS_APPEND_FL/FS_IMMUTABLE_FL/FS_NODUMP_FL
instead of the ext2 alias names?

      Arnd
Theodore Ts'o July 15, 2022, 11:36 a.m. UTC | #6
On Fri, Jul 15, 2022 at 01:09:04PM +0200, Arnd Bergmann wrote:
> On Fri, Jul 15, 2022 at 1:01 AM kernel test robot <lkp@intel.com> wrote:
> >
> > >> mm/shmem.c:1062:22: error: use of undeclared identifier 'EXT2_APPEND_FL'
> >            if (info->fsflags & EXT2_APPEND_FL)
> >                                ^
> > >> mm/shmem.c:1064:22: error: use of undeclared identifier 'EXT2_IMMUTABLE_FL'
> >            if (info->fsflags & EXT2_IMMUTABLE_FL)
> >                                ^
> > >> mm/shmem.c:1066:22: error: use of undeclared identifier 'EXT2_NODUMP_FL'
> >            if (info->fsflags & EXT2_NODUMP_FL)
> >                                ^
> 
> I suppose this just needs to use FS_APPEND_FL/FS_IMMUTABLE_FL/FS_NODUMP_FL
> instead of the ext2 alias names?

The zero day bot was testing the v1 version of the patch.  This was
fixed in the -v2 and -v3 versions.

     	      	     	    	    - Ted
diff mbox series

Patch

diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index a68f982f22d1..1b6c4013f691 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -25,9 +25,20 @@  struct shmem_inode_info {
 	struct simple_xattrs	xattrs;		/* list of xattrs */
 	atomic_t		stop_eviction;	/* hold when working on inode */
 	struct timespec64	i_crtime;	/* file creation time */
+	unsigned int		fsflags;	/* flags for FS_IOC_[SG]ETFLAGS */
 	struct inode		vfs_inode;
 };
 
+#define SHMEM_FL_USER_VISIBLE FS_FL_USER_VISIBLE
+#define SHMEM_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE
+#define SHMEM_FL_INHERITED FS_FL_USER_MODIFIABLE
+
+/* Flags that are appropriate for regular files (all but dir-specific ones). */
+#define SHMEM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
+
+/* Flags that are appropriate for non-directories/regular files. */
+#define SHMEM_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
+
 struct shmem_sb_info {
 	unsigned long max_blocks;   /* How many blocks are allowed */
 	struct percpu_counter used_blocks;  /* How many are allocated */
diff --git a/mm/shmem.c b/mm/shmem.c
index a6f565308133..515a2708d658 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -28,6 +28,7 @@ 
 #include <linux/ramfs.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
+#include <linux/fileattr.h>
 #include <linux/mm.h>
 #include <linux/random.h>
 #include <linux/sched/signal.h>
@@ -1058,6 +1059,15 @@  static int shmem_getattr(struct user_namespace *mnt_userns,
 		shmem_recalc_inode(inode);
 		spin_unlock_irq(&info->lock);
 	}
+	if (info->fsflags & EXT2_APPEND_FL)
+		stat->attributes |= STATX_ATTR_APPEND;
+	if (info->fsflags & EXT2_IMMUTABLE_FL)
+		stat->attributes |= STATX_ATTR_IMMUTABLE;
+	if (info->fsflags & EXT2_NODUMP_FL)
+		stat->attributes |= STATX_ATTR_NODUMP;
+	stat->attributes_mask |= (STATX_ATTR_APPEND |
+			STATX_ATTR_IMMUTABLE |
+			STATX_ATTR_NODUMP);
 	generic_fillattr(&init_user_ns, inode, stat);
 
 	if (shmem_is_huge(NULL, inode, 0))
@@ -2272,7 +2282,18 @@  static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
 	return 0;
 }
 
-static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
+/* Mask out flags that are inappropriate for the given type of inode. */
+static unsigned shmem_mask_flags(umode_t mode, __u32 flags)
+{
+	if (S_ISDIR(mode))
+		return flags;
+	else if (S_ISREG(mode))
+		return flags & SHMEM_REG_FLMASK;
+	else
+		return flags & SHMEM_OTHER_FLMASK;
+}
+
+static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
 				     umode_t mode, dev_t dev, unsigned long flags)
 {
 	struct inode *inode;
@@ -2297,6 +2318,9 @@  static struct inode *shmem_get_inode(struct super_block *sb, const struct inode
 		info->seals = F_SEAL_SEAL;
 		info->flags = flags & VM_NORESERVE;
 		info->i_crtime = inode->i_mtime;
+		info->fsflags = (dir == NULL) ? 0 :
+			SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
+		info->fsflags = shmem_mask_flags(mode, info->fsflags);
 		INIT_LIST_HEAD(&info->shrinklist);
 		INIT_LIST_HEAD(&info->swaplist);
 		simple_xattrs_init(&info->xattrs);
@@ -2813,6 +2837,41 @@  static long shmem_fallocate(struct file *file, int mode, loff_t offset,
 	return error;
 }
 
+int shmem_fileattr_get(struct dentry *dentry, struct fileattr *fa)
+{
+	struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
+
+	fileattr_fill_flags(fa, info->fsflags & SHMEM_FL_USER_VISIBLE);
+
+	return 0;
+}
+
+
+
+int shmem_fileattr_set(struct user_namespace *mnt_userns,
+		       struct dentry *dentry, struct fileattr *fa)
+{
+	struct inode *inode = d_inode(dentry);
+	struct shmem_inode_info *info = SHMEM_I(inode);
+
+	if (fileattr_has_fsx(fa))
+		return -EOPNOTSUPP;
+
+	info->fsflags = (fa->flags & ~SHMEM_FL_USER_MODIFIABLE) |
+		(fa->flags & SHMEM_FL_USER_MODIFIABLE);
+
+	inode->i_flags &= ~(S_APPEND | S_IMMUTABLE | S_NOATIME);
+	if (info->fsflags & FS_APPEND_FL)
+		inode->i_flags |= S_APPEND;
+	if (info->fsflags & FS_IMMUTABLE_FL)
+		inode->i_flags |= S_IMMUTABLE;
+	if (info->fsflags & FS_NOATIME_FL)
+		inode->i_flags |= S_NOATIME;
+
+	inode->i_ctime = current_time(inode);
+	return 0;
+}
+
 static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -3828,6 +3887,8 @@  static const struct inode_operations shmem_inode_operations = {
 #ifdef CONFIG_TMPFS_XATTR
 	.listxattr	= shmem_listxattr,
 	.set_acl	= simple_set_acl,
+	.fileattr_get	= shmem_fileattr_get,
+	.fileattr_set	= shmem_fileattr_set,
 #endif
 };
 
@@ -3847,6 +3908,8 @@  static const struct inode_operations shmem_dir_inode_operations = {
 #endif
 #ifdef CONFIG_TMPFS_XATTR
 	.listxattr	= shmem_listxattr,
+	.fileattr_get	= shmem_fileattr_get,
+	.fileattr_set	= shmem_fileattr_set,
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	.setattr	= shmem_setattr,