@@ -2757,13 +2757,62 @@ static int shmem_file_open(struct inode *inode, struct file *file)
2757
2757
#ifdef CONFIG_TMPFS_XATTR
2758
2758
static int shmem_initxattrs (struct inode * , const struct xattr * , void * );
2759
2759
2760
+ #if IS_ENABLED (CONFIG_UNICODE )
2761
+ /*
2762
+ * shmem_inode_casefold_flags - Deal with casefold file attribute flag
2763
+ *
2764
+ * The casefold file attribute needs some special checks. I can just be added to
2765
+ * an empty dir, and can't be removed from a non-empty dir.
2766
+ */
2767
+ static int shmem_inode_casefold_flags (struct inode * inode , unsigned int fsflags ,
2768
+ struct dentry * dentry , unsigned int * i_flags )
2769
+ {
2770
+ unsigned int old = inode -> i_flags ;
2771
+ struct super_block * sb = inode -> i_sb ;
2772
+
2773
+ if (fsflags & FS_CASEFOLD_FL ) {
2774
+ if (!(old & S_CASEFOLD )) {
2775
+ if (!sb -> s_encoding )
2776
+ return - EOPNOTSUPP ;
2777
+
2778
+ if (!S_ISDIR (inode -> i_mode ))
2779
+ return - ENOTDIR ;
2780
+
2781
+ if (dentry && !simple_empty (dentry ))
2782
+ return - ENOTEMPTY ;
2783
+ }
2784
+
2785
+ * i_flags = * i_flags | S_CASEFOLD ;
2786
+ } else if (old & S_CASEFOLD ) {
2787
+ if (dentry && !simple_empty (dentry ))
2788
+ return - ENOTEMPTY ;
2789
+ }
2790
+
2791
+ return 0 ;
2792
+ }
2793
+ #else
2794
+ static int shmem_inode_casefold_flags (struct inode * inode , unsigned int fsflags ,
2795
+ struct dentry * dentry , unsigned int * i_flags )
2796
+ {
2797
+ if (fsflags & FS_CASEFOLD_FL )
2798
+ return - EOPNOTSUPP ;
2799
+
2800
+ return 0 ;
2801
+ }
2802
+ #endif
2803
+
2760
2804
/*
2761
2805
* chattr's fsflags are unrelated to extended attributes,
2762
2806
* but tmpfs has chosen to enable them under the same config option.
2763
2807
*/
2764
- static void shmem_set_inode_flags (struct inode * inode , unsigned int fsflags )
2808
+ static int shmem_set_inode_flags (struct inode * inode , unsigned int fsflags , struct dentry * dentry )
2765
2809
{
2766
2810
unsigned int i_flags = 0 ;
2811
+ int ret ;
2812
+
2813
+ ret = shmem_inode_casefold_flags (inode , fsflags , dentry , & i_flags );
2814
+ if (ret )
2815
+ return ret ;
2767
2816
2768
2817
if (fsflags & FS_NOATIME_FL )
2769
2818
i_flags |= S_NOATIME ;
@@ -2774,10 +2823,12 @@ static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
2774
2823
/*
2775
2824
* But FS_NODUMP_FL does not require any action in i_flags.
2776
2825
*/
2777
- inode_set_flags (inode , i_flags , S_NOATIME | S_APPEND | S_IMMUTABLE );
2826
+ inode_set_flags (inode , i_flags , S_NOATIME | S_APPEND | S_IMMUTABLE | S_CASEFOLD );
2827
+
2828
+ return 0 ;
2778
2829
}
2779
2830
#else
2780
- static void shmem_set_inode_flags (struct inode * inode , unsigned int fsflags )
2831
+ static void shmem_set_inode_flags (struct inode * inode , unsigned int fsflags , struct dentry * dentry )
2781
2832
{
2782
2833
}
2783
2834
#define shmem_initxattrs NULL
@@ -2824,7 +2875,7 @@ static struct inode *__shmem_get_inode(struct mnt_idmap *idmap,
2824
2875
info -> fsflags = (dir == NULL ) ? 0 :
2825
2876
SHMEM_I (dir )-> fsflags & SHMEM_FL_INHERITED ;
2826
2877
if (info -> fsflags )
2827
- shmem_set_inode_flags (inode , info -> fsflags );
2878
+ shmem_set_inode_flags (inode , info -> fsflags , NULL );
2828
2879
INIT_LIST_HEAD (& info -> shrinklist );
2829
2880
INIT_LIST_HEAD (& info -> swaplist );
2830
2881
simple_xattrs_init (& info -> xattrs );
@@ -3931,16 +3982,23 @@ static int shmem_fileattr_set(struct mnt_idmap *idmap,
3931
3982
{
3932
3983
struct inode * inode = d_inode (dentry );
3933
3984
struct shmem_inode_info * info = SHMEM_I (inode );
3985
+ int ret , flags ;
3934
3986
3935
3987
if (fileattr_has_fsx (fa ))
3936
3988
return - EOPNOTSUPP ;
3937
3989
if (fa -> flags & ~SHMEM_FL_USER_MODIFIABLE )
3938
3990
return - EOPNOTSUPP ;
3939
3991
3940
- info -> fsflags = (info -> fsflags & ~SHMEM_FL_USER_MODIFIABLE ) |
3992
+ flags = (info -> fsflags & ~SHMEM_FL_USER_MODIFIABLE ) |
3941
3993
(fa -> flags & SHMEM_FL_USER_MODIFIABLE );
3942
3994
3943
- shmem_set_inode_flags (inode , info -> fsflags );
3995
+ ret = shmem_set_inode_flags (inode , flags , dentry );
3996
+
3997
+ if (ret )
3998
+ return ret ;
3999
+
4000
+ info -> fsflags = flags ;
4001
+
3944
4002
inode_set_ctime_current (inode );
3945
4003
inode_inc_iversion (inode );
3946
4004
return 0 ;
0 commit comments