Whamcloud - gitweb
LU-16569 llite: fix file attribute operation 93/58693/9
authorYang Sheng <ys@whamcloud.com>
Sat, 5 Apr 2025 06:58:40 +0000 (14:58 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 7 May 2025 21:11:07 +0000 (21:11 +0000)
The file attribute should be filtered. Also the
kernel removed the option to propagate i_flags
from vfs_inode to ext4_inode_info since commit:
v4.11-rc3-45-g38eae95ddc ("ext4: Remove ext4_get_inode_flags()")
This makes file attribute flags cannot be persisted
after MDS failover.

Signed-off-by: Yang Sheng <ys@whamcloud.com>
Change-Id: I12dc70daec5297f54b83e6e71474547b014f9f49
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58693
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/llite/llite_lib.c
lustre/mdt/mdt_lib.c
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-zfs/osd_internal.h
lustre/tests/recovery-small.sh

index 1636271..a686c44 100644 (file)
@@ -1859,16 +1859,24 @@ enum {
        /* these should be identical to their EXT4_*_FL counterparts, they are
         * redefined here only to avoid dragging in fs/ext4/ext4.h
         */
+       LUSTRE_UNRM_FL          = 0x00000002, /* Undelete */
+       LUSTRE_COMPR_FL         = 0x00000004, /* Compress file */
        LUSTRE_SYNC_FL          = 0x00000008, /* Synchronous updates */
        LUSTRE_IMMUTABLE_FL     = 0x00000010, /* Immutable file */
        LUSTRE_APPEND_FL        = 0x00000020, /* file writes may only append */
        LUSTRE_NODUMP_FL        = 0x00000040, /* do not dump file */
        LUSTRE_NOATIME_FL       = 0x00000080, /* do not update atime */
+       LUSTRE_NOCOMPR_FL       = 0x00000400, /* Don't compress */
+       COMPAT_ENCRYPT_FL       = 0x00000800, /* filter out FS_ENCRYPT_FL */
        LUSTRE_INDEX_FL         = 0x00001000, /* hash-indexed directory */
+       LUSTRE_EXTENTS_FL       = 0x00080000, /* Inode uses extents */
+       LUSTRE_JOURNAL_DATA_FL  = 0x00004000, /* file should be journaled */
        LUSTRE_DIRSYNC_FL       = 0x00010000, /* dirsync behaviour (dir only) */
        LUSTRE_TOPDIR_FL        = 0x00020000, /* Top of directory hierarchies*/
+       LUSTRE_VERITY_FL        = 0x00100000, /* Verity protected inode */
        LUSTRE_INLINE_DATA_FL   = 0x10000000, /* Inode has inline data. */
        LUSTRE_PROJINHERIT_FL   = 0x20000000, /* Create with parents projid */
+       LUSTRE_CASEFOLD_FL      = 0x40000000, /* Casefolded directory */
 
        /* These flags will not be identical to any EXT4_*_FL counterparts,
         * and only reserved for lustre purpose. Note: these flags might
@@ -1885,6 +1893,30 @@ enum {
        LUSTRE_LMA_FL_MASKS     = LUSTRE_ENCRYPT_FL | LUSTRE_ORPHAN_FL,
 };
 
+#define LUSTRE_FL_USER_MODIFIABLE (LUSTRE_SYNC_FL      | \
+                                  LUSTRE_IMMUTABLE_FL  | \
+                                  LUSTRE_APPEND_FL     | \
+                                  LUSTRE_NODUMP_FL     | \
+                                  LUSTRE_NOATIME_FL    | \
+                                  LUSTRE_NOCOMPR_FL    | \
+                                  LUSTRE_NOATIME_FL    | \
+                                  LUSTRE_DIRSYNC_FL    | \
+                                  LUSTRE_TOPDIR_FL     | \
+                                  LUSTRE_PROJINHERIT_FL)
+
+#define LUSTRE_FL_USER_VISIBLE (LUSTRE_FL_USER_MODIFIABLE | \
+                               LUSTRE_UNRM_FL            | \
+                               COMPAT_ENCRYPT_FL         | \
+                               LUSTRE_COMPR_FL           | \
+                               LUSTRE_NOCOMPR_FL         | \
+                               LUSTRE_ENCRYPT_FL         | \
+                               LUSTRE_INDEX_FL           | \
+                               LUSTRE_JOURNAL_DATA_FL    | \
+                               LUSTRE_EXTENTS_FL         | \
+                               LUSTRE_VERITY_FL          | \
+                               LUSTRE_INLINE_DATA_FL     | \
+                               LUSTRE_CASEFOLD_FL)
+
 #ifndef FS_XFLAG_SYNC
 #define FS_XFLAG_SYNC          0x00000020      /* all writes synchronous */
 #endif
index 91df3cf..3ef6650 100644 (file)
@@ -3276,7 +3276,10 @@ static int fileattr_set(struct inode *inode, int flags)
        if (IS_ERR(op_data))
                RETURN(PTR_ERR(op_data));
 
-       op_data->op_attr_flags = flags;
+       /* Since chattr will get attr first, so we have to filter
+        * out encrypt flag added in the fileattr_get.
+        */
+       op_data->op_attr_flags = flags & ~LUSTRE_ENCRYPT_FL;
        op_data->op_xvalid |= OP_XVALID_FLAGS;
        rc = md_setattr(sbi->ll_md_exp, op_data, NULL, 0, &req);
        ll_finish_md_op_data(op_data);
index 495b04b..18ef1c0 100644 (file)
@@ -1253,7 +1253,12 @@ static int mdt_setattr_unpack_rec(struct mdt_thread_info *info)
        rr->rr_fid1 = &rec->sa_fid;
        la->la_valid = mdt_attr_valid_xlate(rec->sa_valid, rr, ma);
        la->la_mode  = rec->sa_mode;
-       la->la_flags = rec->sa_attr_flags;
+
+       if (rec->sa_attr_flags & ~LUSTRE_FL_USER_VISIBLE) {
+               CDEBUG(D_INODE, "Unsupported flags: %x\n", rec->sa_attr_flags);
+               RETURN(-EOPNOTSUPP);
+       }
+       la->la_flags = rec->sa_attr_flags & LUSTRE_FL_USER_MODIFIABLE;
 
        nodemap = nodemap_get_from_exp(info->mti_exp);
        if (IS_ERR(nodemap))
index 2e2e4b9..f1dc4d3 100644 (file)
@@ -2827,8 +2827,7 @@ static void osd_inode_getattr(const struct lu_env *env,
         * to inode flags, and ext4 internally test raw inode
         * @i_flags directly. Instead of patching ext4, we do it here.
         */
-       if (LDISKFS_I(inode)->i_flags & LUSTRE_PROJINHERIT_FL)
-               attr->la_flags |= LUSTRE_PROJINHERIT_FL;
+       attr->la_flags |= LDISKFS_I(inode)->i_flags & LUSTRE_FL_USER_VISIBLE;
 }
 
 static int osd_dirent_count(const struct lu_env *env, struct dt_object *dt,
@@ -3128,6 +3127,8 @@ static int osd_inode_setattr(const struct lu_env *env,
                inode->i_rdev = attr->la_rdev;
 
        if (bits & LA_FLAGS) {
+               struct ldiskfs_inode_info *ei = LDISKFS_I(inode);
+
                /* always keep S_NOCMTIME */
                inode->i_flags = ll_ext_to_inode_flags(attr->la_flags) |
                                 S_NOCMTIME;
@@ -3143,10 +3144,8 @@ static int osd_inode_setattr(const struct lu_env *env,
                 * @inode->i_flags to raw inode i_flags when writing
                 * flags, we do it explictly here.
                 */
-               if (attr->la_flags & LUSTRE_PROJINHERIT_FL)
-                       LDISKFS_I(inode)->i_flags |= LUSTRE_PROJINHERIT_FL;
-               else
-                       LDISKFS_I(inode)->i_flags &= ~LUSTRE_PROJINHERIT_FL;
+               ei->i_flags = (ei->i_flags & ~LDISKFS_OSD_USER_MODIFIABLE) |
+                             (attr->la_flags & LDISKFS_OSD_USER_MODIFIABLE);
        }
        return 0;
 }
index c0b2797..999fd07 100644 (file)
@@ -1763,4 +1763,6 @@ static int fill_fn(struct dir_context *buf, const char *name, int namelen,  \
 #define WRAP_FILLDIR_FN(prefix, fill_fn)
 #endif
 
+#define LDISKFS_OSD_USER_MODIFIABLE    LUSTRE_FL_USER_MODIFIABLE
+
 #endif /* _OSD_INTERNAL_H */
index d90d9e7..a98bd7c 100644 (file)
@@ -829,6 +829,11 @@ static inline uint32_t attrs_zfs2fs(const uint64_t flags)
 
 #endif
 
+#define ZFS_OSD_USER_USER_MODIFIABLE   (LUSTRE_APPEND_FL | \
+                                        LUSTRE_NODUMP_FL | \
+                                        LUSTRE_PROJINHERIT_FL | \
+                                        LUSTRE_IMMUTABLE_FL)
+
 static inline uint64_t
 osd_dmu_object_alloc(objset_t *os, dmu_object_type_t objtype, int blocksize,
                     int dnodesize, dmu_tx_t *tx)
index e580307..e222513 100755 (executable)
@@ -3795,6 +3795,42 @@ test_161() {
 }
 run_test 161 "evict osp by ping evictor"
 
+test_162() {
+       local mntpt=$(facet_mntpt $SINGLEMDS)
+
+       test_mkdir -i 0 -c 1 $DIR/$tdir
+       $LFS setstripe -c 1 -i 0 $DIR/$tdir
+
+       local wfile=$DIR/$tdir/$tfile
+       local rstr="aAdDiPST"
+
+       stack_trap "chattr -$rstr $wfile; rm -rf $DIR/$tdir" EXIT
+
+       touch $wfile
+       for ((i = 0; i < ${#rstr[0]}; i++)); do
+               local c=${rstr:i:1}
+
+               chattr +$c $wfile || error "Flag [$c] should succeed"
+       done
+
+       local attr1=($(lsattr $wfile))
+       echo $attr1
+
+       [[ -n ${attr1//-/} ]] || error "lsattr failed: $(lsattr $wfile)"
+
+       stop mds1
+       start mds1 $(mdsdevname 1) $MDS_MOUNT_OPTS || error "mds1 start fail"
+
+       wait_recovery_complete $SINGLEMDS || error "MDS recovery not done"
+
+       local attr2=($(lsattr $wfile))
+       echo $attr2
+       [[ "$attr1" == "$attr2" ]] ||
+               error "'$attr1' different with '$attr2'"
+
+}
+run_test 162 "File attributes should be persisted after MDS failover"
+
 complete_test $SECONDS
 check_and_cleanup_lustre
 exit_status