Whamcloud - gitweb
LU-11867 osd-ldiskfs: FID in LMA mismatch won't block create 52/34052/5
authorLai Siyao <lai.siyao@whamcloud.com>
Mon, 7 Jan 2019 03:37:48 +0000 (11:37 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 27 Jun 2019 21:34:13 +0000 (21:34 +0000)
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 <lai.siyao@whamcloud.com>
Change-Id: Ic84cdeaca2ea202ab0c01a0075a2f9ee8627f508
Reviewed-on: https://review.whamcloud.com/34052
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/obd_support.h
lustre/osd-ldiskfs/osd_handler.c
lustre/tests/sanity-scrub.sh

index d488249..916eb30 100644 (file)
@@ -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
index 3d6af92..2ede000 100644 (file)
@@ -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)),
index 92c913a..28ddee3 100644 (file)
@@ -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