static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -2413,12 +2415,17 @@
+@@ -2413,12 +2415,19 @@
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -2425,12 +2425,17 @@
+@@ -2425,12 +2425,19 @@
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -1197,14 +1197,19 @@
+@@ -1197,14 +1197,21 @@
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -2413,13 +2415,18 @@
+@@ -2413,13 +2415,20 @@
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -2413,12 +2413,17 @@ retry_inode:
+@@ -2413,12 +2413,19 @@ retry_inode:
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
static int
ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
-@@ -2413,13 +2415,18 @@
+@@ -2413,13 +2415,20 @@
ext4_handle_sync(handle);
}
+ if (!error && name_index == EXT4_XATTR_INDEX_ENCRYPTION &&
-+ strcmp(name, "c") == 0)
++ strcmp(name, "c") == 0) {
+ EXT4_I(inode)->i_flags |= EXT4_ENCRYPT_FL;
++ mark_inode_dirty(inode);
++ }
+
cleanup:
brelse(is.iloc.bh);
#define OBD_FAIL_LFSCK_BAD_PFL_RANGE 0x162f
#define OBD_FAIL_LFSCK_NO_AGENTOBJ 0x1630
#define OBD_FAIL_LFSCK_NO_AGENTENT 0x1631
+#define OBD_FAIL_LFSCK_NO_ENCFLAG 0x1632
#define OBD_FAIL_LFSCK_NOTIFY_NET 0x16f0
#define OBD_FAIL_LFSCK_QUERY_NET 0x16f1
return rc;
}
+/*
+ * If the MDT-object has the LUSTRE_ENCRYPT_FL flag, it needs to be set
+ * on the OST-object as well.
+ */
+static int lfsck_layout_repair_encflag(const struct lu_env *env,
+ struct lfsck_component *com,
+ struct dt_object *parent,
+ struct lfsck_layout_req *llr)
+{
+ struct lfsck_thread_info *info = lfsck_env_info(env);
+ struct lu_attr *tla = &info->lti_la2;
+ struct dt_object *child = llr->llr_child;
+ struct dt_device *dev = lfsck_obj2dev(child);
+ struct thandle *handle;
+ int rc;
+
+ ENTRY;
+
+ tla->la_valid = LA_FLAGS;
+ tla->la_flags = LUSTRE_ENCRYPT_FL;
+ handle = lfsck_trans_create(env, dev, com->lc_lfsck);
+ if (IS_ERR(handle))
+ GOTO(log, rc = PTR_ERR(handle));
+
+ rc = dt_declare_attr_set(env, child, tla, handle);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ rc = dt_trans_start_local(env, dev, handle);
+ if (rc != 0)
+ GOTO(stop, rc);
+
+ /* Use the dt_object lock to serialize with destroy and attr_set. */
+ dt_read_lock(env, parent, 0);
+ if (unlikely(lfsck_is_dead_obj(parent)))
+ GOTO(unlock, rc = 1);
+
+ rc = dt_attr_set(env, child, tla, handle);
+ GOTO(unlock, rc);
+
+unlock:
+ dt_read_unlock(env, parent);
+
+stop:
+ rc = lfsck_layout_trans_stop(env, dev, handle, rc);
+
+log:
+ if (rc != 0)
+ CDEBUG(D_LFSCK,
+ "%s: layout LFSCK assistant repair of inconsistent file enc flag for: parent "
+ DFID", child "
+ DFID", OST-index %u, stripe-index %u: rc = %d\n",
+ lfsck_lfsck2name(com->lc_lfsck),
+ PFID(lfsck_dto2fid(parent)), PFID(lfsck_dto2fid(child)),
+ llr->llr_ost_idx, llr->llr_lov_idx, rc);
+
+ return rc;
+}
+
static int lfsck_layout_assistant_handler_p1(const struct lu_env *env,
struct lfsck_component *com,
struct lfsck_assistant_req *lar)
if (rc != 0)
GOTO(out, rc);
+ if (!(bk->lb_param & LPF_DRYRUN) &&
+ pla->la_valid & LA_FLAGS && pla->la_flags & LUSTRE_ENCRYPT_FL) {
+ /* MDT-inode is encrypted */
+ struct lu_buf lb = { .lb_buf = NULL, .lb_len = 0 };
+
+ /* if OST-inode is missing encryption.c xattr, fix it */
+ if (dt_xattr_get(env, child, &lb,
+ LL_XATTR_NAME_ENCRYPTION_CONTEXT) >= 0)
+ goto check_fid;
+
+ if (parent == NULL)
+ parent = lfsck_assistant_object_load(env, lfsck, lso);
+ if (!IS_ERR_OR_NULL(parent))
+ rc = lfsck_layout_repair_encflag(env, com, parent, llr);
+ down_write(&com->lc_sem);
+ if (rc < 0)
+ lfsck_layout_record_failure(env, lfsck, lo);
+ else if (rc > 0)
+ lo->ll_objs_repaired[LLIT_OTHERS - 1]++;
+ up_write(&com->lc_sem);
+ }
+
+check_fid:
lfsck_buf_init(&buf, ff, sizeof(*ff));
rc = dt_xattr_get(env, child, &buf, XATTR_NAME_FID);
if (unlikely(rc > 0 && rc < sizeof(struct lu_fid))) {
stat->attributes_mask |= STATX_ATTR_ENCRYPTED;
#endif
stat->attributes |= ll_inode_to_ext_flags(inode->i_flags);
+ /* if Lustre specific LUSTRE_ENCRYPT_FL flag is set, also set
+ * ext4 equivalent to please statx
+ */
+ if (stat->attributes & LUSTRE_ENCRYPT_FL)
+ stat->attributes |= STATX_ATTR_ENCRYPTED;
stat->result_mask &= request_mask;
#endif
body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
flags = body->mbo_flags;
+ /* if Lustre specific LUSTRE_ENCRYPT_FL flag is set, also set
+ * ext4 equivalent to please lsattr and other e2fsprogs tools
+ */
+ if (flags & LUSTRE_ENCRYPT_FL)
+ flags |= STATX_ATTR_ENCRYPTED;
ptlrpc_req_finished(req);
}
/*
+ * Handle multiple attrs at once:
+ *
* Lazy ATIME update to refresh atime every ofd_atime_diff
* seconds so that external scanning tool can see it actual
* within that period and be able to identify accessed files
+ *
+ * Update enc flag on OST object
+ * OSD layer will find out if this is really necessary.
*/
-static void ofd_handle_atime(const struct lu_env *env, struct ofd_device *ofd,
- struct ofd_object *fo, time64_t atime)
+static void ofd_handle_attrs(const struct lu_env *env, struct ofd_device *ofd,
+ struct ofd_object *fo, struct obdo *oa)
{
+ bool need_atime = (oa->o_valid & OBD_MD_FLATIME);
+ bool need_encfl = (oa->o_valid & OBD_MD_FLFLAGS &&
+ oa->o_flags & LUSTRE_ENCRYPT_FL);
struct lu_attr *la;
struct dt_object *o;
struct thandle *th;
int rc;
- if (ofd->ofd_atime_diff == 0)
+ if (need_atime && ofd->ofd_atime_diff == 0)
+ need_atime = false;
+
+ if (need_encfl && OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_ENCFLAG))
+ need_encfl = false;
+
+ if (!need_atime && !need_encfl)
return;
la = &ofd_info(env)->fti_attr2;
o = ofd_object_child(fo);
- if (unlikely(fo->ofo_atime_ondisk == 0)) {
- rc = dt_attr_get(env, o, la);
- if (unlikely(rc))
- return;
- LASSERT(la->la_valid & LA_ATIME);
- if (la->la_atime == 0)
- la->la_atime = la->la_mtime;
- fo->ofo_atime_ondisk = la->la_atime;
+ if (need_atime) {
+ if (unlikely(fo->ofo_atime_ondisk == 0)) {
+ rc = dt_attr_get(env, o, la);
+ if (unlikely(rc)) {
+ need_atime = false;
+ GOTO(trans, rc);
+ }
+ LASSERT(la->la_valid & LA_ATIME);
+ if (la->la_atime == 0)
+ la->la_atime = la->la_mtime;
+ fo->ofo_atime_ondisk = la->la_atime;
+ }
+ if (oa->o_atime - fo->ofo_atime_ondisk < ofd->ofd_atime_diff) {
+ need_atime = false;
+ GOTO(trans, rc = 0);
+ }
+
+ /* atime hasn't been updated too long, update it */
+ fo->ofo_atime_ondisk = oa->o_atime;
}
- if (atime - fo->ofo_atime_ondisk < ofd->ofd_atime_diff)
- return;
- /* atime hasn't been updated too long, update it */
- fo->ofo_atime_ondisk = atime;
+trans:
+ if (!need_atime && !need_encfl)
+ return;
th = ofd_trans_create(env, ofd);
if (IS_ERR(th)) {
return;
}
- la->la_valid = LA_ATIME;
+ la->la_valid = 0;
+ if (need_atime) {
+ la->la_valid |= LA_ATIME;
+ la->la_atime = fo->ofo_atime_ondisk;
+ }
+ if (need_encfl) {
+ la->la_valid |= LA_FLAGS;
+ la->la_flags = LUSTRE_ENCRYPT_FL;
+ }
+
rc = dt_declare_attr_set(env, o, la, th);
if (rc)
GOTO(out_tx, rc);
}
ofd_read_lock(env, fo);
- if (ofd_object_exists(fo)) {
- la->la_atime = fo->ofo_atime_ondisk;
+ if (ofd_object_exists(fo))
rc = dt_attr_set(env, o, la, th);
- }
-
ofd_read_unlock(env, fo);
out_tx:
ofd_info(env)->fti_obj = fo;
- if (oa->o_valid & OBD_MD_FLATIME)
- ofd_handle_atime(env, ofd, fo, oa->o_atime);
+ ofd_handle_attrs(env, ofd, fo, oa);
if (!ofd_object_exists(fo))
GOTO(obj_put, rc = -ENOENT);
struct ofd_object *ofd_obj, struct lu_attr *la,
struct obdo *oa)
{
- struct ofd_thread_info *info = ofd_info(env);
- struct filter_fid *ff = &info->fti_mds_fid;
- __u64 valid = la->la_valid;
- struct thandle *th;
- struct dt_object *dt_obj;
- int fl = 0;
- int rc;
+ struct ofd_thread_info *info = ofd_info(env);
+ struct filter_fid *ff = &info->fti_mds_fid;
+ __u64 valid = la->la_valid;
+ __u32 flags = la->la_flags;
+ struct thandle *th;
+ struct dt_object *dt_obj;
+ int fl = 0;
+ int rc;
ENTRY;
LASSERT(dt_obj != NULL);
la->la_valid &= LA_UID | LA_GID | LA_PROJID;
+ if (oa->o_valid & OBD_MD_FLFLAGS && oa->o_flags & LUSTRE_ENCRYPT_FL &&
+ !OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_ENCFLAG)) {
+ la->la_valid |= LA_FLAGS;
+ la->la_flags = LUSTRE_ENCRYPT_FL;
+ }
rc = ofd_attr_handle_id(env, ofd_obj, la, 0 /* !is_setattr */);
if (rc != 0)
dt_trans_stop(env, ofd->ofd_osd, th);
out:
la->la_valid = valid;
+ la->la_flags = flags;
return rc;
}
else /* short io */
ioobj_max_brw_set(ioobj, 0);
+ if (inode && IS_ENCRYPTED(inode) &&
+ llcrypt_has_encryption_key(inode) &&
+ !OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_ENCFLAG)) {
+ if ((body->oa.o_valid & OBD_MD_FLFLAGS) == 0) {
+ body->oa.o_valid |= OBD_MD_FLFLAGS;
+ body->oa.o_flags = 0;
+ }
+ body->oa.o_flags |= LUSTRE_ENCRYPT_FL;
+ }
+
if (short_io_size != 0) {
if ((body->oa.o_valid & OBD_MD_FLFLAGS) == 0) {
body->oa.o_valid |= OBD_MD_FLFLAGS;
const struct lu_fid *fid);
static int osd_process_scheduled_agent_removals(const struct lu_env *env,
struct osd_device *osd);
+static int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
+ const struct lu_buf *buf, const char *name, int fl,
+ struct thandle *handle);
int osd_trans_declare_op2rb[] = {
[OSD_OT_ATTR_SET] = OSD_OT_ATTR_SET,
const struct lu_attr *attr,
struct thandle *handle)
{
+ struct osd_thread_info *info = osd_oti_get(env);
struct osd_object *obj = osd_dt_obj(dt);
+ struct osd_device *osd = osd_obj2dev(obj);
struct inode *inode;
int rc;
if (!(attr->la_valid & LA_FLAGS))
GOTO(out, rc);
+ /* If setting LUSTRE_ENCRYPT_FL on an OST object, also set a dummy
+ * enc ctx xattr, with 2 benefits:
+ * - setting the LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr internally sets
+ * the LDISKFS_ENCRYPT_FL flag on the on-disk inode;
+ * - it makes e2fsprogs happy to see an enc ctx for an inode that has
+ * the LDISKFS_ENCRYPT_FL flag
+ * We do not need the actual encryption context on OST objects, it is
+ * only stored on MDT inodes, at file creation time.
+ */
+ if (!(LDISKFS_I(obj->oo_inode)->i_flags & LDISKFS_ENCRYPT_FL) &&
+ attr->la_flags & LUSTRE_ENCRYPT_FL && osd->od_is_ost &&
+ !OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_ENCFLAG)) {
+ struct lu_buf buf;
+
+ /* use a dummy enc ctx, fine with e2fsprogs */
+ buf.lb_buf = "\xFF";
+ buf.lb_len = 1;
+ rc = osd_xattr_set(env, dt, &buf,
+ LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ 0, handle);
+ if (rc)
+ CWARN("%s: set "DFID" enc ctx failed: rc = %d\n",
+ osd_name(osd), PFID(lu_object_fid(&dt->do_lu)),
+ rc);
+ }
+
/* Let's check if there are extra flags need to be set into LMA */
if (attr->la_flags & LUSTRE_LMA_FL_MASKS) {
- struct osd_thread_info *info = osd_oti_get(env);
struct lustre_mdt_attrs *lma = &info->oti_ost_attrs.loa_lma;
LASSERT(!obj->oo_pfid_in_lma);
if (rc)
GOTO(out, rc);
+ if ((lma->lma_incompat & lustre_to_lma_flags(attr->la_flags)) ==
+ lustre_to_lma_flags(attr->la_flags))
+ /* if lma incompat already has the flags,
+ * save a useless call to xattr_set
+ */
+ GOTO(out, rc = 0);
+
lma->lma_incompat |=
lustre_to_lma_flags(attr->la_flags);
lustre_lma_swab(lma);
rc = __osd_xattr_set(info, inode, XATTR_NAME_LMA,
lma, sizeof(*lma), XATTR_REPLACE);
- if (rc != 0) {
- struct osd_device *osd = osd_obj2dev(obj);
-
+ if (rc != 0)
CWARN("%s: set "DFID" lma flags %u failed: rc = %d\n",
osd_name(osd), PFID(lu_object_fid(&dt->do_lu)),
lma->lma_incompat, rc);
- } else {
+ else
obj->oo_lma_flags =
attr->la_flags & LUSTRE_LMA_FL_MASKS;
- }
osd_trans_exec_check(env, handle, OSD_OT_XATTR_SET);
}
-out:
+out:
return rc;
}
} else if (!rc) {
lma->lma_incompat =
le32_to_cpu(lma->lma_incompat);
+
+ if ((lma->lma_incompat &
+ lustre_to_lma_flags(la->la_flags)) ==
+ lustre_to_lma_flags(la->la_flags))
+ /* save a useless xattr set if lma
+ * incompat already has the flags
+ */
+ GOTO(lock, rc = 0);
+
lma->lma_incompat |=
lustre_to_lma_flags(la->la_flags);
lma->lma_incompat =
}
}
+lock:
write_lock(&obj->oo_attr_lock);
cnt = 0;
int rc = 0;
ENTRY;
- /* we're interested in uid/gid/projid/layout version changes only */
- if (!(attr->la_valid & LA_REMOTE_ATTR_SET))
+ /* we're interested in uid/gid/projid/layout version changes,
+ * and also specific setting of enc flag
+ */
+ if (!(attr->la_valid & LA_REMOTE_ATTR_SET) &&
+ !(attr->la_valid == LA_FLAGS &&
+ attr->la_flags == LUSTRE_ENCRYPT_FL))
RETURN(0);
if (!is_only_remote_trans(th)) {
}
run_test 41 "SEL support in LFSCK"
+setup_dummy_key() {
+ local mode='\x00\x00\x00\x00'
+ local raw="$(printf ""\\\\x%02x"" {0..63})"
+ local size
+ local key
+
+ [[ $(lscpu) =~ Byte\ Order.*Little ]] && size='\x40\x00\x00\x00' ||
+ size='\x00\x00\x00\x40'
+ key="${mode}${raw}${size}"
+ echo -n -e "${key}" | keyctl padd logon fscrypt:4242424242424242 @s
+}
+
+insert_enc_key() {
+ cancel_lru_locks
+ sync ; echo 3 > /proc/sys/vm/drop_caches
+ setup_dummy_key
+}
+
+remove_enc_key() {
+ local dummy_key
+
+ $LCTL set_param -n ldlm.namespaces.*.lru_size=clear
+ sync ; echo 3 > /proc/sys/vm/drop_caches
+ dummy_key=$(keyctl show | awk '$7 ~ "^fscrypt:" {print $1}')
+ if [ -n "$dummy_key" ]; then
+ keyctl revoke $dummy_key
+ keyctl reap
+ fi
+}
+
+remount_client_normally() {
+ # remount client without dummy encryption key
+ if is_mounted $MOUNT; then
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ fi
+ mount_client $MOUNT ${MOUNT_OPTS} ||
+ error "remount failed"
+
+ if is_mounted $MOUNT2; then
+ umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+ fi
+ if [ "$MOUNT_2" ]; then
+ mount_client $MOUNT2 ${MOUNT_OPTS} ||
+ error "remount failed"
+ fi
+
+ remove_enc_key
+}
+
+remount_client_dummykey() {
+ insert_enc_key
+
+ # remount client with dummy encryption key
+ if is_mounted $MOUNT; then
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ fi
+ mount_client $MOUNT ${MOUNT_OPTS},test_dummy_encryption ||
+ error "remount failed"
+}
+
+setup_for_enc_tests() {
+ rm -rf $DIR/[df][0-9]* || error "Fail to cleanup env"
+
+ # remount client with test_dummy_encryption option
+ if is_mounted $MOUNT; then
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ fi
+ mount_client $MOUNT ${MOUNT_OPTS},test_dummy_encryption ||
+ error "mount with '-o test_dummy_encryption' failed"
+
+ # this directory will be encrypted, because of dummy mode
+ $LFS setdirstripe -c 1 -i 0 $DIR/$tdir
+ $LFS setstripe -c 1 -i 0 $DIR/$tdir
+}
+
+cleanup_for_enc_tests() {
+ rm -rf $DIR/$tdir $*
+
+ remount_client_normally
+}
+
+test_42() {
+ [[ $(facet_fstype ost1) == zfs ]] && skip "skip ZFS backend"
+
+ (( $MDS1_VERSION > $(version_code 2.15.51) )) ||
+ skip "Need MDS version at least 2.15.51"
+
+ echo "#####"
+ echo "If the MDT-object has the encryption flag but the OST-object"
+ echo "does not, add it to the OST-object."
+ echo "#####"
+
+ check_mount_and_prep
+
+ $LCTL get_param mdc.*.import | grep -q client_encryption ||
+ skip "client encryption not supported"
+
+ mount.lustre --help |& grep -q "test_dummy_encryption:" ||
+ skip "need dummy encryption support"
+
+ stack_trap cleanup_for_enc_tests EXIT
+ setup_for_enc_tests
+
+ $LFS setstripe -c 1 -i 0 $DIR/$tdir
+ touch $DIR/$tdir/${tfile}_1 || error "touch ${tfile}_1 failed"
+ dd if=/dev/zero of=$DIR/$tdir/${tfile}_2 bs=1 count=1 conv=fsync ||
+ error "dd ${tfile}_2 failed"
+
+ #define OBD_FAIL_LFSCK_NO_ENCFLAG 0x1632
+ do_nodes $(comma_list $(all_nodes)) "$LCTL set_param fail_loc=0x1632"
+ touch $DIR/$tdir/${tfile}_3 || error "touch ${tfile}_3 failed"
+ dd if=/dev/zero of=$DIR/$tdir/${tfile}_4 bs=1 count=1 conv=fsync ||
+ error "dd ${tfile}_4 failed"
+ do_nodes $(comma_list $(all_nodes)) "$LCTL set_param fail_loc=0x0"
+ cancel_lru_locks osc
+
+ echo "Trigger layout LFSCK to find out inconsistent OST-object enc flag"
+
+ $START_LAYOUT -r || error "Fail to start LFSCK for layout!"
+
+ wait_update_facet $SINGLEMDS "$LCTL get_param -n \
+ mdd.${MDT_DEV}.lfsck_layout |
+ awk '/^status/ { print \\\$2 }'" "completed" 32 || {
+ $SHOW_LAYOUT
+ error "unexpected lfsck status"
+ }
+
+ local repaired=$($SHOW_LAYOUT |
+ awk '/^repaired_others/ { print $2 }')
+ [ $repaired -eq 2 ] ||
+ error "Fail to repair inconsistent enc flag: $repaired"
+}
+run_test 42 "LFSCK can repair inconsistent MDT-object/OST-object encryption flags"
+
# restore MDS/OST size
MDSSIZE=${SAVED_MDSSIZE}
OSTSIZE=${SAVED_OSTSIZE}
}
run_test 61 "Nodemap enforces read-only mount"
+test_62() {
+ local testdir=$DIR/$tdir/mytestdir
+ local testfile=$DIR/$tdir/$tfile
+
+ [[ $(facet_fstype ost1) == zfs ]] && skip "skip ZFS backend"
+
+ (( $MDS1_VERSION > $(version_code 2.15.51) )) ||
+ skip "Need MDS version at least 2.15.51"
+
+ $LCTL get_param mdc.*.import | grep -q client_encryption ||
+ skip "client encryption not supported"
+
+ mount.lustre --help |& grep -q "test_dummy_encryption:" ||
+ skip "need dummy encryption support"
+
+ stack_trap cleanup_for_enc_tests EXIT
+ setup_for_enc_tests
+
+ lfs setstripe -c -1 $DIR/$tdir
+ touch $DIR/$tdir/${tfile}_1 || error "touch ${tfile}_1 failed"
+ dd if=/dev/zero of=$DIR/$tdir/${tfile}_2 bs=1 count=1 conv=fsync ||
+ error "dd ${tfile}_2 failed"
+
+ # unmount the Lustre filesystem
+ stopall || error "stopping for e2fsck run"
+
+ # run e2fsck on the MDT and OST devices
+ local mds_host=$(facet_active_host $SINGLEMDS)
+ local ost_host=$(facet_active_host ost1)
+ local mds_dev=$(mdsdevname ${SINGLEMDS//mds/})
+ local ost_dev=$(ostdevname 1)
+
+ run_e2fsck $mds_host $mds_dev "-n"
+ run_e2fsck $ost_host $ost_dev "-n"
+
+ # mount the Lustre filesystem
+ setupall || error "remounting the filesystem failed"
+}
+run_test 62 "e2fsck with encrypted files"
+
log "cleanup: ======================================================"
sec_unsetup() {