From cbf59ba6a56086c53a15622db7fa9f95d9798b7f Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Mon, 7 Jan 2019 11:37:48 +0800 Subject: [PATCH] LU-11867 osd-ldiskfs: FID in LMA mismatch won't block create Sometimes two OST objects may be mapped to the same inode, so the second object FID mismatch with FID in inode LMA, in this case, if this inode was not written yet, it's safe to set object inode to NULL to let it create a new inode. Another case is if the mapped inode doesn't exist, it's also safe to not initialize inode and return 0, so that create can succeed. Add sanity-scrub.sh 4d for this. Signed-off-by: Lai Siyao Change-Id: Ic84cdeaca2ea202ab0c01a0075a2f9ee8627f508 Reviewed-on: https://review.whamcloud.com/34052 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- lustre/include/obd_support.h | 2 ++ lustre/osd-ldiskfs/osd_handler.c | 35 +++++++++++++++++++++++++++++++++++ lustre/tests/sanity-scrub.sh | 25 +++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index d488249..916eb30 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -283,6 +283,8 @@ extern char obd_jobid_var[]; #define OBD_FAIL_OSD_TXN_START 0x19a +#define OBD_FAIL_OSD_DUPLICATE_MAP 0x19b + #define OBD_FAIL_OFD_SET_OID 0x1e0 #define OBD_FAIL_OST 0x200 diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index 3d6af92..2ede000 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -1128,6 +1128,12 @@ static int osd_fid_lookup(const struct lu_env *env, struct osd_object *obj, goto trigger; } + /* -ESTALE is returned if inode of OST object doesn't exist */ + if (result == -ESTALE && + fid_is_on_ost(info, dev, fid, OI_CHECK_FLD)) { + GOTO(out, result = 0); + } + if (result) GOTO(out, result); @@ -1290,6 +1296,19 @@ check_lma: LASSERT(!updated); + /* + * if two OST objects map to the same inode, and inode mode is + * (S_IFREG | S_ISUID | S_ISGID | S_ISVTX | 0666), which means it's + * reserved by precreate, and not written yet, in this case, don't + * set inode for the object whose FID mismatch, so that it can create + * inode and not block precreate. + */ + if (fid_is_on_ost(info, dev, fid, OI_CHECK_FLD) && + inode->i_mode == (S_IFREG | S_ISUID | S_ISGID | S_ISVTX | 0666)) { + obj->oo_inode = NULL; + GOTO(out, result = 0); + } + result = osd_oi_lookup(info, dev, fid, id, OI_CHECK_FLD); /* * "result == -ENOENT" means the cached OI mapping has been removed @@ -3392,6 +3411,19 @@ static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj, osd_id_gen(id, obj->oo_inode->i_ino, obj->oo_inode->i_generation); rc = osd_oi_insert(info, osd, fid, id, oh->ot_handle, OI_CHECK_FLD, NULL); + if (CFS_FAIL_CHECK(OBD_FAIL_OSD_DUPLICATE_MAP) && osd->od_is_ost) { + struct lu_fid next_fid = *fid; + + /* insert next object in advance, and map to the same inode */ + next_fid.f_oid++; + if (next_fid.f_oid != 0) { + osd_trans_exec_op(env, th, OSD_OT_INSERT); + osd_oi_insert(info, osd, &next_fid, id, oh->ot_handle, + OI_CHECK_FLD, NULL); + osd_trans_exec_check(env, th, OSD_OT_INSERT); + } + } + osd_trans_exec_check(env, th, OSD_OT_INSERT); return rc; @@ -3456,6 +3488,9 @@ static int osd_declare_create(const struct lu_env *env, struct dt_object *dt, */ osd_trans_declare_op(env, oh, OSD_OT_INSERT, osd_dto_credits_noquota[DTO_INDEX_INSERT] + 1); + if (CFS_FAIL_CHECK(OBD_FAIL_OSD_DUPLICATE_MAP)) + osd_trans_declare_op(env, oh, OSD_OT_INSERT, + osd_dto_credits_noquota[DTO_INDEX_INSERT] + 1); /* will help to find FID->ino mapping at dt_insert() */ rc = osd_idc_find_and_init(env, osd_obj2dev(osd_dt_obj(dt)), diff --git a/lustre/tests/sanity-scrub.sh b/lustre/tests/sanity-scrub.sh index 92c913a..28ddee3 100644 --- a/lustre/tests/sanity-scrub.sh +++ b/lustre/tests/sanity-scrub.sh @@ -49,7 +49,6 @@ build_test_filter MDT_DEV="${FSNAME}-MDT0000" OST_DEV="${FSNAME}-OST0000" -MDT_DEVNAME=$(mdsdevname ${SINGLEMDS//mds/}) scrub_start() { local error_id=$1 @@ -375,7 +374,7 @@ test_1a() { stop $SINGLEMDS > /dev/null || error "(6) Fail to stop MDS!" echo "start $SINGLEMDS with disabling OI scrub" - start $SINGLEMDS $MDT_DEVNAME $MOUNT_OPTS_NOSCRUB > /dev/null || + start $SINGLEMDS $(mdsdevname 1) $MOUNT_OPTS_NOSCRUB > /dev/null || error "(7) Fail to start MDS!" local FLAGS=$($SHOW_SCRUB | awk '/^flags/ { print $2 }') @@ -654,6 +653,28 @@ test_4c() { } run_test 4c "Auto trigger OI scrub if bad OI mapping was found (3)" +test_4d() { + [ $(facet_fstype $SINGLEMDS) != "ldiskfs" ] && skip "ldiskfs only test" + + check_mount_and_prep + + #define OBD_FAIL_OSD_DUPLICATE_MAP 0x19b + do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0x19b + for i in {1..100}; do + echo $i > $DIR/$tdir/f_$i || error "write f_$i failed" + done + do_nodes $(comma_list $(osts_nodes)) $LCTL set_param fail_loc=0 + + for i in {101..200}; do + echo $i > $DIR/$tdir/f_$i || error "write f_$i failed" + done + + for i in {1..200}; do + echo $i | cmp $DIR/$tdir/f_$i - || error "f_$i data corrupt" + done +} +run_test 4d "FID in LMA mismatch with object FID won't block create" + test_5() { formatall > /dev/null setupall > /dev/null -- 1.8.3.1