From: Yang Sheng Date: Sat, 5 Apr 2025 06:58:40 +0000 (+0800) Subject: LU-16569 llite: fix file attribute operation X-Git-Tag: 2.16.55~41 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=101b67fcd91617590006c8d16d74401f6489cf8d;p=fs%2Flustre-release.git LU-16569 llite: fix file attribute operation 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 Change-Id: I12dc70daec5297f54b83e6e71474547b014f9f49 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/58693 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Li Dongyang Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index 1636271..a686c44 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -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 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 91df3cf..3ef6650 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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); diff --git a/lustre/mdt/mdt_lib.c b/lustre/mdt/mdt_lib.c index 495b04b..18ef1c0 100644 --- a/lustre/mdt/mdt_lib.c +++ b/lustre/mdt/mdt_lib.c @@ -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)) diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 2e2e4b9..f1dc4d3 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -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; } diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index c0b2797..999fd07 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -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 */ diff --git a/lustre/osd-zfs/osd_internal.h b/lustre/osd-zfs/osd_internal.h index d90d9e7..a98bd7c 100644 --- a/lustre/osd-zfs/osd_internal.h +++ b/lustre/osd-zfs/osd_internal.h @@ -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) diff --git a/lustre/tests/recovery-small.sh b/lustre/tests/recovery-small.sh index e580307..e222513 100755 --- a/lustre/tests/recovery-small.sh +++ b/lustre/tests/recovery-small.sh @@ -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