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))) {
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));
*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
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) &&
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));
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);
}
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) {
* 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);
/*
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"
assert_DIR
rm -rf $DIR/[Rdfs][0-9]*
-force_new_seq mds1
-
test_0a() {
[ $OSTCOUNT -lt 2 ] && skip "needs >= 2 OSTs"