From e4c78a98b9abb8c09cef2863822021fe28869bcf Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Thu, 25 Nov 2021 18:39:22 +0800 Subject: [PATCH] LU-15278 mdt: protect layout xattr During layout change, the layout xattr could be simultaneously used by others. This patch put the server LOVEA access in the protection of mdt_object::mot_lov_mutex. Lustre-change: https://review.whamcloud.com/45663 Lustre-commit: TBD (from 48bb7206fb656a35283ea7eefdec208dd6c42078) Signed-off-by: Bobi Jam Signed-off-by: John L. Hammond Change-Id: Iabad4a3211b7ef74592d92b86082201687964ab2 Reviewed-on: https://review.whamcloud.com/46262 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Bobi Jam Reviewed-by: Alex Zhuravlev Reviewed-on: https://review.whamcloud.com/46327 --- lustre/mdt/mdt_handler.c | 4 ++-- lustre/mdt/mdt_open.c | 10 ++++++++++ lustre/mdt/mdt_reint.c | 3 +++ lustre/mdt/mdt_xattr.c | 8 ++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 954bac57..26610dc 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -1710,9 +1710,9 @@ int mdt_layout_change(struct mdt_thread_info *info, struct mdt_object *obj, OBD_FAIL_TIMEOUT(OBD_FAIL_MDS_LL_PCCRO, cfs_fail_val); } - mutex_lock(&obj->mot_som_mutex); + mutex_lock(&obj->mot_lov_mutex); rc = mo_layout_change(info->mti_env, mdt_object_child(obj), layout); - mutex_unlock(&obj->mot_som_mutex); + mutex_unlock(&obj->mot_lov_mutex); if (rc) mdt_object_unlock(info, obj, lhc, 1); diff --git a/lustre/mdt/mdt_open.c b/lustre/mdt/mdt_open.c index d7d47fd..ce3bd66 100644 --- a/lustre/mdt/mdt_open.c +++ b/lustre/mdt/mdt_open.c @@ -2164,10 +2164,20 @@ int mdt_close_handle_layouts(struct mdt_thread_info *info, buf->lb_len = sizeof(mrd); buf->lb_buf = &mrd; + /* In the LOD layer, we cache and modify layouts + * during the declare phase and depend on these being + * unchanged during the operation. But LOD (through + * the dt_device API) does not give us an easy way to + * lock and unlock what we need. The MDD layer uses + * dt_{read,write}_lock() extensively but these must + * be acquired after transaction start. So we + * repurpose mot_lov_mutex here. See LU-15278. */ + mutex_lock(&o->mot_lov_mutex); rc = mo_xattr_set(info->mti_env, mdt_object_child(o), buf, XATTR_LUSTRE_LOV, ma->ma_attr_flags & MDS_CLOSE_LAYOUT_SPLIT ? LU_XATTR_SPLIT : LU_XATTR_MERGE); + mutex_unlock(&o->mot_lov_mutex); if (rc == 0 && ma->ma_attr.la_valid & (LA_SIZE | LA_BLOCKS | LA_LSIZE | LA_LBLOCKS)) { int rc2; diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index d3a37a2..f7d7770 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -935,6 +935,9 @@ static int mdt_reint_setattr(struct mdt_thread_info *info, GOTO(out_put, rc = -EPERM); } + /* settattr with striping is only for directories and + * may not be combined with other attributes. See + * ll_dir_setstripe(). */ if (!S_ISDIR(lu_object_attr(&mo->mot_obj))) GOTO(out_put, rc = -ENOTDIR); diff --git a/lustre/mdt/mdt_xattr.c b/lustre/mdt/mdt_xattr.c index 1a6eb9e..d1ace5b 100644 --- a/lustre/mdt/mdt_xattr.c +++ b/lustre/mdt/mdt_xattr.c @@ -287,6 +287,7 @@ int mdt_getxattr(struct mdt_thread_info *info) if (valid == OBD_MD_FLXATTR) { const char *xattr_name = req_capsule_client_get(info->mti_pill, &RMF_NAME); + rc = mo_xattr_get(info->mti_env, next, buf, xattr_name); if (rc < 0) GOTO(out, rc); @@ -667,7 +668,14 @@ int mdt_reint_setxattr(struct mdt_thread_info *info, buf->lb_buf = rr->rr_eadata; buf->lb_len = xattr_len; + /* Need an upper level lock around the magical + * "lustre.lov.{add,del,set}" operations. See LU-15278 + * and the comment in mdt_close_handle_layouts(). */ + if (lockpart & MDS_INODELOCK_LAYOUT) + mutex_lock(&obj->mot_lov_mutex); rc = mo_xattr_set(env, child, buf, xattr_name, flags); + if (lockpart & MDS_INODELOCK_LAYOUT) + mutex_unlock(&obj->mot_lov_mutex); /* update ctime after xattr changed */ if (rc == 0) { ma->ma_attr_flags |= MDS_PERM_BYPASS; -- 1.8.3.1