Whamcloud - gitweb
LU-16692 osp: do not assert on seq got over network 20/54020/15
authorLi Dongyang <dongyangli@ddn.com>
Tue, 13 Feb 2024 04:10:53 +0000 (15:10 +1100)
committerOleg Drokin <green@whamcloud.com>
Mon, 8 Apr 2024 15:34:58 +0000 (15:34 +0000)
Replay requests have FIDs already assigned and the
sequence could be different to the osp:
seq rollover happened after the original request,
then something triggers replay, or osp lost the
seq rollover record on storage.

Detect this and avoid the assert in osp_fid_diff(),
we don't update the last id on osp in this case,
otherwise orhpan cleanup could cleanup the objects
in the current osp's sequence.

Also when rollover seq happens in osp, do not
LASSERT() if we didn't get a new seq, most likely
on ofd/ost the previous seq update was lost on storage.
We could return the error code and let precreate
thread try again.

Cleanup lu_fid_diff() which is not used.
In osp_create(), do not call osp_update_last_fid()
again for the regular non-replay case, it's already
done via osp_object_assign_fid()->osp_precreate_get_fid().

Change-Id: I509c00b998933d45865c9540e12a2db7d1b2b8ed
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/54020
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_fid.h
lustre/osp/osp_internal.h
lustre/osp/osp_object.c
lustre/osp/osp_precreate.c
lustre/tests/recovery-small.sh
lustre/tests/sanity-pfl.sh

index c2bea87..c454a37 100644 (file)
@@ -766,19 +766,6 @@ static inline __u32 fid_hash(const struct lu_fid *f, int bits)
 
 u32 lu_fid_hash(const void *data, u32 len, u32 seed);
 
-static inline int
-lu_fid_diff(const struct lu_fid *fid1, const struct lu_fid *fid2)
-{
-       LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:"DFID", fid2:"DFID"\n",
-                PFID(fid1), PFID(fid2));
-
-       if (fid_is_idif(fid1) && fid_is_idif(fid2))
-               return fid_idif_id(fid1->f_seq, fid1->f_oid, fid1->f_ver) -
-                      fid_idif_id(fid2->f_seq, fid2->f_oid, fid2->f_ver);
-
-       return fid_oid(fid1) - fid_oid(fid2);
-}
-
 static inline int fid_set_id(struct lu_fid *fid, u64 oid)
 {
        if (unlikely(fid_seq_is_igif(fid->f_seq))) {
index 1ba8c54..f0eb673 100644 (file)
@@ -531,12 +531,6 @@ static inline int osp_fid_diff(const struct lu_fid *fid1,
                       fid_idif_id(fid2->f_seq, fid2->f_oid, 0);
        }
 
-       /* Changed to new seq before replay, we always start with oid 2 in
-        * a new seq. In this case just return 1.
-        */
-       if (fid_seq(fid1) != fid_seq(fid2) && fid_oid(fid1) == 2)
-               return 1;
-
        LASSERTF(fid_seq(fid1) == fid_seq(fid2), "fid1:"DFID", fid2:"DFID"\n",
                 PFID(fid1), PFID(fid2));
 
@@ -552,10 +546,20 @@ static inline void osp_fid_to_obdid(struct lu_fid *last_fid, u64 *osi_id)
                *osi_id = fid_oid(last_fid);
 }
 
-static inline void osp_update_last_fid(struct osp_device *d, struct lu_fid *fid)
+static inline void osp_update_last_fid(struct osp_device *d, struct lu_fid *fid,
+                                      bool replay)
 {
-       int diff = osp_fid_diff(fid, &d->opd_last_used_fid);
        struct lu_fid *gap_start = &d->opd_gap_start_fid;
+       int diff;
+
+       /*
+        * replay could cross seq rollover, in this case we don't update
+        * the last used fid
+        */
+       if (replay && fid_seq(fid) != fid_seq(&d->opd_last_used_fid))
+               diff = 0;
+       else
+               diff = osp_fid_diff(fid, &d->opd_last_used_fid);
 
        /*
         * we might have lost precreated objects due to VBR and precreate
index ef21c44..38910f1 100644 (file)
@@ -1558,12 +1558,14 @@ static int osp_create(const struct lu_env *env, struct dt_object *dt,
                      struct lu_attr *attr, struct dt_allocation_hint *hint,
                      struct dt_object_format *dof, struct thandle *th)
 {
-       struct osp_thread_info  *osi = osp_env_info(env);
-       struct osp_device       *d = lu2osp_dev(dt->do_lu.lo_dev);
-       struct osp_object       *o = dt2osp_obj(dt);
-       int                     rc = 0;
-       struct lu_fid           *fid = &osi->osi_fid;
-       struct thandle          *local_th;
+       struct osp_thread_info *osi = osp_env_info(env);
+       struct osp_device *d = lu2osp_dev(dt->do_lu.lo_dev);
+       struct osp_object *o = dt2osp_obj(dt);
+       struct lu_fid *fid = &osi->osi_fid;
+       struct thandle *local_th;
+       bool replay = false;
+       int rc = 0;
+
        ENTRY;
 
        if (is_only_remote_trans(th) &&
@@ -1581,6 +1583,8 @@ static int osp_create(const struct lu_env *env, struct dt_object *dt,
        if (o->opo_reserved) {
                /* regular case, fid is assigned holding transaction open */
                 osp_object_assign_fid(env, d, o);
+       } else {
+               replay = true;
        }
 
        memcpy(fid, lu_object_fid(&dt->do_lu), sizeof(*fid));
@@ -1588,12 +1592,12 @@ static int osp_create(const struct lu_env *env, struct dt_object *dt,
        LASSERTF(fid_is_sane(fid), "fid for osp_object %px is insane"DFID"!\n",
                 o, PFID(fid));
 
-       if (!o->opo_reserved) {
+       if (replay) {
                /* special case, id was assigned outside of transaction
                 * see comments in osp_declare_attr_set */
                LASSERT(d->opd_pre != NULL);
                spin_lock(&d->opd_pre_lock);
-               osp_update_last_fid(d, fid);
+               osp_update_last_fid(d, fid, true);
                spin_unlock(&d->opd_pre_lock);
        }
 
index 64d5a80..9ddef83 100644 (file)
@@ -482,11 +482,15 @@ static int osp_precreate_rollover_new_seq(struct lu_env *env,
                RETURN(rc);
        }
 
+       if (fid_seq(fid) <= fid_seq(last_fid)) {
+               rc = -ESTALE;
+               CERROR("%s: not a new sequence: fid "DFID", last_used_fid "DFID": rc = %d\n",
+                      osp->opd_obd->obd_name, PFID(fid), PFID(last_fid), rc);
+               RETURN(rc);
+       }
+
        fid->f_oid = 1;
        fid->f_ver = 0;
-       LASSERTF(fid_seq(fid) != fid_seq(last_fid),
-                "fid "DFID", last_fid "DFID"\n", PFID(fid),
-                PFID(last_fid));
 
        rc = osp_write_last_oid_seq_files(env, osp, fid, 1);
        if (rc != 0) {
@@ -1640,7 +1644,7 @@ int osp_precreate_get_fid(const struct lu_env *env, struct osp_device *d,
         * last_used_id must be changed along with getting new id otherwise
         * we might miscalculate gap causing object loss or leak
         */
-       osp_update_last_fid(d, fid);
+       osp_update_last_fid(d, fid, false);
        spin_unlock(&d->opd_pre_lock);
 
        /*
index 72ebcc1..24be100 100755 (executable)
@@ -28,8 +28,6 @@ check_and_setup_lustre
 assert_DIR
 rm -rf $DIR/d[0-9]* $DIR/f.${TESTSUITE}*
 
-force_new_seq mds1
-
 test_1() {
        local f1="$DIR/$tfile"
        local f2="$DIR/$tfile.2"
index 0dc8571..cc78292 100755 (executable)
@@ -40,8 +40,6 @@ check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
 assert_DIR
 rm -rf $DIR/[Rdfs][0-9]*
 
-force_new_seq mds1
-
 test_0a() {
        [ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"