u64 valid;
int size, err, checksum;
bool api32;
+ void *encctx;
+ int encctxlen;
ENTRY;
sbi->ll_md_obd = class_name2obd(md);
/* make root inode
* XXX: move this to after cbd setup? */
- valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMODEASIZE;
+ valid = OBD_MD_FLGETATTR | OBD_MD_FLBLOCKS | OBD_MD_FLMODEASIZE |
+ OBD_MD_ENCCTX;
if (test_bit(LL_SBI_ACL, sbi->ll_flags))
valid |= OBD_MD_FLACL;
err = md_getattr(sbi->ll_md_exp, op_data, &request);
+ /* We need enc ctx info, so reset it in op_data to
+ * prevent it from being freed.
+ */
+ encctx = op_data->op_file_encctx;
+ encctxlen = op_data->op_file_encctx_size;
+ op_data->op_file_encctx = NULL;
+ op_data->op_file_encctx_size = 0;
OBD_FREE_PTR(op_data);
if (err) {
CERROR("%s: md_getattr failed for root: rc = %d\n",
api32 = test_bit(LL_SBI_32BIT_API, sbi->ll_flags);
root = ll_iget(sb, cl_fid_build_ino(&sbi->ll_root_fid, api32), &lmd);
md_free_lustre_md(sbi->ll_md_exp, &lmd);
- ptlrpc_req_finished(request);
if (IS_ERR(root)) {
lmd_clear_acl(&lmd);
root = NULL;
CERROR("%s: bad ll_iget() for root: rc = %d\n",
sbi->ll_fsname, err);
+ ptlrpc_req_finished(request);
GOTO(out_root, err);
}
+ if (encctxlen) {
+ CDEBUG(D_SEC,
+ "server returned encryption ctx for root inode "DFID"\n",
+ PFID(&sbi->ll_root_fid));
+ err = ll_set_encflags(root, encctx, encctxlen, true);
+ if (err)
+ CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n",
+ sbi->ll_fsname,
+ PFID(&sbi->ll_root_fid), err);
+ }
+ ptlrpc_req_finished(request);
+
checksum = test_bit(LL_SBI_CHECKSUM, sbi->ll_flags);
if (sbi->ll_checksum_set) {
err = obd_set_info_async(NULL, sbi->ll_dt_exp,
if (ll_need_32bit_api(ll_i2sbi(i1)))
op_data->op_cli_flags |= CLI_API32;
- if (opc == LUSTRE_OPC_LOOKUP || opc == LUSTRE_OPC_CREATE) {
+ if ((i2 && is_root_inode(i2)) ||
+ opc == LUSTRE_OPC_LOOKUP || opc == LUSTRE_OPC_CREATE) {
/* In case of lookup, ll_setup_filename() has already been
* called in ll_lookup_it(), so just take provided name.
+ * Also take provided name if we are dealing with root inode.
*/
fname.disk_name.name = (unsigned char *)name;
fname.disk_name.len = namelen;
req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, 0);
req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER, 0);
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX, RCL_SERVER, 0);
ptlrpc_request_set_replen(req);
req->rq_interpret_reply = mdc_data_version_interpret;
* layouts. --umka
*/
static int mdc_getattr_common(struct obd_export *exp,
- struct ptlrpc_request *req)
+ struct ptlrpc_request *req,
+ struct md_op_data *op_data)
{
struct req_capsule *pill = &req->rq_pill;
struct mdt_body *body;
RETURN(-EPROTO);
}
+ /* If encryption context was returned by MDT, put it in op_data
+ * so that caller can set it on inode and save an extra getxattr.
+ */
+ if (op_data && op_data->op_valid & OBD_MD_ENCCTX &&
+ body->mbo_valid & OBD_MD_ENCCTX) {
+ op_data->op_file_encctx =
+ req_capsule_server_get(pill, &RMF_FILE_ENCCTX);
+ op_data->op_file_encctx_size =
+ req_capsule_get_size(pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER);
+ }
+
RETURN(0);
}
struct ptlrpc_request **request)
{
struct ptlrpc_request *req;
+ struct obd_device *obd = class_exp2obd(exp);
struct obd_import *imp = class_exp2cliimp(exp);
__u32 acl_bufsize = LUSTRE_POSIX_ACL_MAX_SIZE_OLD;
int rc;
req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, acl_bufsize);
req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
op_data->op_mode);
+ if (exp_connect_encrypt(exp) && op_data->op_valid & OBD_MD_ENCCTX)
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER,
+ obd->u.cli.cl_max_mds_easize);
+ else
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER, 0);
ptlrpc_request_set_replen(req);
- rc = mdc_getattr_common(exp, req);
+ rc = mdc_getattr_common(exp, req, op_data);
if (rc) {
if (rc == -ERANGE) {
acl_bufsize = min_t(__u32,
req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
op_data->op_mode);
req_capsule_set_size(&req->rq_pill, &RMF_ACL, RCL_SERVER, acl_bufsize);
+ req_capsule_set_size(&req->rq_pill, &RMF_FILE_ENCCTX, RCL_SERVER, 0);
ptlrpc_request_set_replen(req);
if (op_data->op_bias & MDS_FID_OP) {
struct mdt_body *b = req_capsule_client_get(&req->rq_pill,
}
}
- rc = mdc_getattr_common(exp, req);
+ rc = mdc_getattr_common(exp, req, NULL);
if (rc) {
if (rc == -ERANGE) {
acl_bufsize = min_t(__u32,
RETURN(rc);
}
+static void mdt_preset_encctx_size(struct mdt_thread_info *info)
+{
+ struct req_capsule *pill = info->mti_pill;
+
+ ENTRY;
+ if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER))
+ /* pre-set size in server part with max size */
+ req_capsule_set_size(pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER,
+ info->mti_mdt->mdt_max_mdsize);
+ EXIT;
+}
+
static int mdt_getattr_internal(struct mdt_thread_info *info,
struct mdt_object *o, int ma_need)
{
* enlarge the buffer when necessary. */
req_capsule_set_size(pill, &RMF_ACL, RCL_SERVER,
LUSTRE_POSIX_ACL_MAX_SIZE_OLD);
+ mdt_preset_encctx_size(info);
rc = req_capsule_server_pack(pill);
if (unlikely(rc != 0))
info->mti_cross_ref = !!(reqbody->mbo_valid & OBD_MD_FLCROSSREF);
rc = mdt_getattr_internal(info, obj, 0);
+ if (unlikely(rc))
+ GOTO(out_shrink, rc);
+
+ rc = mdt_pack_encctx_in_reply(info, obj);
EXIT;
out_shrink:
mdt_client_compatibility(info);
}
}
-static void mdt_preset_encctx_size(struct mdt_thread_info *info)
-{
- struct req_capsule *pill = info->mti_pill;
-
- if (req_capsule_has_field(pill, &RMF_FILE_ENCCTX,
- RCL_SERVER))
- /* pre-set size in server part with max size */
- req_capsule_set_size(pill, &RMF_FILE_ENCCTX,
- RCL_SERVER,
- info->mti_mdt->mdt_max_mdsize);
-}
-
static int mdt_reint_internal(struct mdt_thread_info *info,
struct mdt_lock_handle *lhc,
__u32 op)
req_capsule_set_size(tsi->tsi_pill, &RMF_MDT_MD, RCL_SERVER, 0);
req_capsule_set_size(tsi->tsi_pill, &RMF_ACL, RCL_SERVER, 0);
+ req_capsule_set_size(tsi->tsi_pill, &RMF_FILE_ENCCTX, RCL_SERVER, 0);
rc = req_capsule_server_pack(tsi->tsi_pill);
if (unlikely(rc != 0))
RETURN(err_serious(rc));
};
static const struct req_msg_field *mds_getattr_server[] = {
- &RMF_PTLRPC_BODY,
- &RMF_MDT_BODY,
- &RMF_MDT_MD,
- &RMF_ACL,
- &RMF_CAPA1,
- &RMF_CAPA2
+ &RMF_PTLRPC_BODY,
+ &RMF_MDT_BODY,
+ &RMF_MDT_MD,
+ &RMF_ACL,
+ &RMF_CAPA1,
+ &RMF_CAPA2,
+ &RMF_FILE_ENCCTX,
};
static const struct req_msg_field *mds_setattr_server[] = {
body->oa.o_flags & OBD_FL_SHORT_IO) ?
remote_nb[0].rnb_len : 0);
}
+ if (req_capsule_has_field(tsi->tsi_pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER))
+ req_capsule_set_size(tsi->tsi_pill, &RMF_FILE_ENCCTX,
+ RCL_SERVER, 0);
rc = req_capsule_server_pack(tsi->tsi_pill);
}
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() {
+ cancel_lru_locks
+ sync ; echo 3 > /proc/sys/vm/drop_caches
+ keyctl revoke $(keyctl show | awk '$7 ~ "^fscrypt:" {print $1}')
+ keyctl reap
+}
+
setup_for_enc_tests() {
# remount client with test_dummy_encryption option
if is_mounted $MOUNT; then
}
run_test 58 "access to enc file's xattrs"
-insert_enc_key() {
- sync ; echo 3 > /proc/sys/vm/drop_caches
- setup_dummy_key
-}
-
-remove_env_key() {
- cancel_lru_locks
- sync ; echo 3 > /proc/sys/vm/drop_caches
- keyctl revoke $(keyctl show | awk '$7 ~ "^fscrypt:" {print $1}')
- keyctl reap
-}
-
verify_mirror() {
local mirror1=$TMP/$tfile.mirror1
local mirror2=$TMP/$tfile.mirror2
$LFS getstripe $testfile
# now, without the key
- remove_env_key
+ remove_enc_key
scrambledfile=$(find $DIR/$tdir/ -maxdepth 1 -mindepth 1 -type f)
$LFS mirror resync $scrambledfile ||
error "could not resync mirror"
$LFS getstripe $testfile
# now, without the key
- remove_env_key
+ remove_enc_key
scrambledfile=$(find $DIR/$tdir/ -maxdepth 1 -mindepth 1 -type f)
$LFS migrate -i1 $scrambledfile ||
error "migrate $scrambledfile failed"
error "migrated file is corrupted"
# now, without the key
- remove_env_key
+ remove_enc_key
$LFS mirror extend -N -i0 $scrambledfile ||
error "mirror extend $scrambledfile failed (1)"
$LFS getstripe $scrambledfile
verify_mirror $testfile $tmpfile
# now, without the key
- remove_env_key
+ remove_enc_key
$LFS mirror split --mirror-id 1 -d $scrambledfile ||
error "mirror split file $scrambledfile failed (1)"
$LFS getstripe $scrambledfile
echo b > $dirname/subf
# now, without the key
- remove_env_key
+ remove_enc_key
scrambleddir=$(find $DIR/$tdir/ -maxdepth 1 -mindepth 1 -type d)
# migrate a non-empty encrypted dir
}
run_test 59c "MDT migrate of encrypted files without key"
+test_60() {
+ local testdir=$DIR/$tdir/mytestdir
+ local testfile=$DIR/$tdir/$tfile
+
+ (( $MDS1_VERSION > $(version_code 2.14.53) )) ||
+ skip "Need MDS version at least 2.14.53"
+
+ $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
+
+ echo a > $DIR/$tdir/file1
+ mkdir $DIR/$tdir/subdir
+ echo b > $DIR/$tdir/subdir/subfile1
+
+ remove_enc_key
+ # unmount client completely
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ if is_mounted $MOUNT2; then
+ umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+ fi
+
+ # remount client with subdirectory mount
+ export FILESET=/$tdir
+ mount_client $MOUNT ${MOUNT_OPTS} || error "remount failed"
+ if [ "$MOUNT_2" ]; then
+ mount_client $MOUNT2 ${MOUNT_OPTS} || error "remount failed"
+ fi
+ export FILESET=""
+
+ ls -Rl $DIR || error "ls -Rl $DIR failed (1)"
+
+ # now, with the key
+ insert_enc_key
+
+ ls -Rl $DIR || error "ls -Rl $DIR failed (2)"
+ cat $DIR/file1 || error "cat $DIR/$tdir/file1 failed"
+ cat $DIR/subdir/subfile1 ||
+ error "cat $DIR/$tdir/subdir/subfile1 failed"
+}
+run_test 60 "Subdirmount of encrypted dir"
+
log "cleanup: ======================================================"
sec_unsetup() {