From 2dde01f1edac9e330f853c3ffee64eb43d82b7c1 Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Thu, 15 Jun 2017 08:14:07 +0300 Subject: [PATCH] LU-9442 osp: can't create IDIF fid number > 0xFFFFFFFF fid_is_last_id didn't recognize IDIFes. This caused OST to allocate new sequence despite of MDT still used initial FID_SEQ_IDIF. Finally allocation failed with -115 returned from osd_check_lma: osd_check_lma()) lustre-OST0000-osd: FID [0x100000001:0x0:0x0] != self_fid [0x100000000:0x0:0x0] Patch has several typical "IDIF" fixes. Also it has lov_objid fix to store all 48 IDIF bits instead of 32. Finally it changes union fields order in ost_id. Before the fix oi_fid.f_seq addressed oi_id instead of oi_seq. Change-Id: Ifbda97a5b228254aedcb050c3d94d2ecb3a9590c Seagate-bug-id: MRP-4392 Signed-off-by: Sergey Cheremencev Reviewed-on: https://review.whamcloud.com/27225 Tested-by: Jenkins Reviewed-by: Fan Yong Tested-by: Maloo Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin --- lustre/include/uapi/linux/lustre_fid.h | 13 +++++++++++-- lustre/lfsck/lfsck_layout.c | 11 ++--------- lustre/osp/lproc_osp.c | 34 +++++++++++++++++++++++++++++----- lustre/osp/osp_dev.c | 13 ++++++++++--- lustre/osp/osp_internal.h | 11 +++++++++-- lustre/osp/osp_object.c | 8 +++++++- lustre/osp/osp_precreate.c | 15 +++++++++++++++ 7 files changed, 83 insertions(+), 22 deletions(-) diff --git a/lustre/include/uapi/linux/lustre_fid.h b/lustre/include/uapi/linux/lustre_fid.h index 608f733..a43507e 100644 --- a/lustre/include/uapi/linux/lustre_fid.h +++ b/lustre/include/uapi/linux/lustre_fid.h @@ -258,8 +258,17 @@ static inline __u32 fid_idif_ost_idx(const struct lu_fid *fid) /* Check whether the fid is for LAST_ID */ static inline bool fid_is_last_id(const struct lu_fid *fid) { - return !fid_oid(fid) && fid_seq(fid) != FID_SEQ_UPDATE_LOG && - fid_seq(fid) != FID_SEQ_UPDATE_LOG_DIR; + if (fid_oid(fid) != 0) + return false; + + if (fid_is_idif(fid) && ((fid_seq(fid) & 0xFFFF) != 0)) + return false; + + if (fid_seq(fid) == FID_SEQ_UPDATE_LOG || + fid_seq(fid) == FID_SEQ_UPDATE_LOG_DIR) + return false; + + return true; } /** diff --git a/lustre/lfsck/lfsck_layout.c b/lustre/lfsck/lfsck_layout.c index 5a00031..b0179a7 100644 --- a/lustre/lfsck/lfsck_layout.c +++ b/lustre/lfsck/lfsck_layout.c @@ -3096,7 +3096,6 @@ static int lfsck_layout_scan_orphan(const struct lu_env *env, struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct lfsck_thread_info *info = lfsck_env_info(env); - struct ost_id *oi = &info->lti_oi; struct lu_fid *fid = &info->lti_fid; struct dt_object *obj; const struct dt_it_ops *iops; @@ -3116,14 +3115,8 @@ static int lfsck_layout_scan_orphan(const struct lu_env *env, RETURN(0); } - ostid_set_seq(oi, FID_SEQ_IDIF); - rc = ostid_set_id(oi, 0); - if (rc) - GOTO(log, rc); - - rc = ostid_to_fid(fid, oi, ltd->ltd_index); - if (rc != 0) - GOTO(log, rc); + fid->f_seq = fid_idif_seq(0, ltd->ltd_index); + fid->f_oid = fid->f_ver = 0; obj = lfsck_object_find_by_dev(env, ltd->ltd_tgt, fid); if (unlikely(IS_ERR(obj))) diff --git a/lustre/osp/lproc_osp.c b/lustre/osp/lproc_osp.c index 4bd59f6..5fc7a02 100644 --- a/lustre/osp/lproc_osp.c +++ b/lustre/osp/lproc_osp.c @@ -444,11 +444,22 @@ static int osp_prealloc_next_id_seq_show(struct seq_file *m, void *data) { struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + struct lu_fid *fid; + __u64 id; if (osp == NULL || osp->opd_pre == NULL) return 0; - seq_printf(m, "%u\n", fid_oid(&osp->opd_pre_used_fid) + 1); + fid = &osp->opd_pre_used_fid; + if (fid_is_idif(fid)) { + id = fid_idif_id(fid_seq(fid), fid_oid(fid), fid_ver(fid)); + id++; + } else { + id = unlikely(fid_oid(fid) == LUSTRE_DATA_SEQ_MAX_WIDTH) ? + 1 : fid_oid(fid) + 1; + } + + seq_printf(m, "%llu\n", id); return 0; } LPROC_SEQ_FOPS_RO(osp_prealloc_next_id); @@ -465,11 +476,17 @@ static int osp_prealloc_last_id_seq_show(struct seq_file *m, void *data) { struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + struct lu_fid *fid; + __u64 id; if (osp == NULL || osp->opd_pre == NULL) return 0; + fid = &osp->opd_pre_last_created_fid; + id = fid_is_idif(fid) ? + fid_idif_id(fid_seq(fid), fid_oid(fid), fid_ver(fid)) : + fid_oid(fid); - seq_printf(m, "%u\n", fid_oid(&osp->opd_pre_last_created_fid)); + seq_printf(m, "%llu\n", id); return 0; } LPROC_SEQ_FOPS_RO(osp_prealloc_last_id); @@ -486,11 +503,15 @@ static int osp_prealloc_next_seq_seq_show(struct seq_file *m, void *data) { struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + struct lu_fid *fid; if (osp == NULL || osp->opd_pre == NULL) return 0; - seq_printf(m, "%#llx\n", fid_seq(&osp->opd_pre_used_fid)); + fid = &osp->opd_pre_used_fid; + seq_printf(m, "%#llx\n", fid_is_idif(fid) ? + fid_seq(fid) & (~0xffff) : fid_seq(fid)); + return 0; } LPROC_SEQ_FOPS_RO(osp_prealloc_next_seq); @@ -507,12 +528,15 @@ static int osp_prealloc_last_seq_seq_show(struct seq_file *m, void *data) { struct obd_device *obd = m->private; struct osp_device *osp = lu2osp_dev(obd->obd_lu_dev); + struct lu_fid *fid; if (osp == NULL || osp->opd_pre == NULL) return 0; - seq_printf(m, "%#llx\n", - fid_seq(&osp->opd_pre_last_created_fid)); + fid = &osp->opd_pre_last_created_fid; + seq_printf(m, "%#llx\n", fid_is_idif(fid) ? + fid_seq(fid) & (~0xffff) : fid_seq(fid)); + return 0; } LPROC_SEQ_FOPS_RO(osp_prealloc_last_seq); diff --git a/lustre/osp/osp_dev.c b/lustre/osp/osp_dev.c index 7e3819f..982a46f 100644 --- a/lustre/osp/osp_dev.c +++ b/lustre/osp/osp_dev.c @@ -261,16 +261,21 @@ static int osp_init_last_objid(const struct lu_env *env, struct osp_device *osp) /* object will be released in device cleanup path */ if (osi->osi_attr.la_size >= sizeof(osi->osi_id) * (osp->opd_index + 1)) { - osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, &fid->f_oid, + osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, &osi->osi_id, osp->opd_index); rc = dt_record_read(env, dto, &osi->osi_lb, &osi->osi_off); if (rc != 0 && rc != -EFAULT) GOTO(out, rc); + /* In case of idif bits 32-48 go to f_seq + * (see osp_init_last_seq). So don't care + * about u64->u32 convertion. */ + fid->f_oid = osi->osi_id; } if (rc == -EFAULT) { /* fresh LAST_ID */ + osi->osi_id = 0; fid->f_oid = 0; - osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, &fid->f_oid, + osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, &osi->osi_id, osp->opd_index); rc = osp_write_local_file(env, osp, dto, &osi->osi_lb, osi->osi_off); @@ -323,6 +328,8 @@ static int osp_init_last_seq(const struct lu_env *env, struct osp_device *osp) rc = dt_record_read(env, dto, &osi->osi_lb, &osi->osi_off); if (rc != 0 && rc != -EFAULT) GOTO(out, rc); + if (fid_is_idif(fid)) + fid->f_seq = fid_idif_seq(osi->osi_id, osp->opd_index); } if (rc == -EFAULT) { /* fresh OSP */ @@ -374,7 +381,7 @@ static int osp_last_used_init(const struct lu_env *env, struct osp_device *osp) rc = osp_init_last_seq(env, osp); if (rc < 0) { - CERROR("%s: Can not get ids %d from old objid!\n", + CERROR("%s: Can not get sequence %d from old objseq!\n", osp->opd_obd->obd_name, rc); GOTO(out, rc); } diff --git a/lustre/osp/osp_internal.h b/lustre/osp/osp_internal.h index 49ea455..6a95d9a 100644 --- a/lustre/osp/osp_internal.h +++ b/lustre/osp/osp_internal.h @@ -394,7 +394,7 @@ static inline bool is_only_remote_trans(struct thandle *th) } static inline void osp_objid_buf_prep(struct lu_buf *buf, loff_t *off, - __u32 *id, int index) + __u64 *id, int index) { /* Note: through id is only 32 bits, it will also write 64 bits * for oid to keep compatibility with the previous version. */ @@ -547,6 +547,7 @@ static inline int osp_fid_diff(const struct lu_fid *fid1, static inline void osp_update_last_fid(struct osp_device *d, struct lu_fid *fid) { int diff = osp_fid_diff(fid, &d->opd_last_used_fid); + struct lu_fid *gap_start = &d->opd_gap_start_fid; /* * we might have lost precreated objects due to VBR and precreate * orphans, the gap in objid can be calculated properly only here @@ -554,7 +555,13 @@ static inline void osp_update_last_fid(struct osp_device *d, struct lu_fid *fid) if (diff > 0) { if (diff > 1) { d->opd_gap_start_fid = d->opd_last_used_fid; - d->opd_gap_start_fid.f_oid++; + if (fid_oid(gap_start) == LUSTRE_DATA_SEQ_MAX_WIDTH) { + gap_start->f_seq++; + gap_start->f_oid = fid_is_idif(gap_start) ? + 0 : 1; + } else { + gap_start->f_oid++; + } d->opd_gap_count = diff - 1; CDEBUG(D_HA, "Gap in objids: start="DFID", count =%d\n", PFID(&d->opd_gap_start_fid), d->opd_gap_count); diff --git a/lustre/osp/osp_object.c b/lustre/osp/osp_object.c index 9ba9051..446f55a 100644 --- a/lustre/osp/osp_object.c +++ b/lustre/osp/osp_object.c @@ -1417,6 +1417,7 @@ static int osp_create(const struct lu_env *env, struct dt_object *dt, int rc = 0; struct lu_fid *fid = &osi->osi_fid; struct thandle *local_th; + struct lu_fid *last_fid = &d->opd_last_used_fid; ENTRY; if (is_only_remote_trans(th) && @@ -1496,8 +1497,13 @@ static int osp_create(const struct lu_env *env, struct dt_object *dt, /* Only need update last_used oid file, seq file will only be update * during seq rollover */ + if (fid_is_idif((last_fid))) + osi->osi_id = fid_idif_id(fid_seq(last_fid), + fid_oid(last_fid), fid_ver(last_fid)); + else + osi->osi_id = fid_oid(last_fid); osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, - &d->opd_last_used_fid.f_oid, d->opd_index); + &osi->osi_id, d->opd_index); rc = dt_record_write(env, d->opd_last_used_oid_file, &osi->osi_lb, &osi->osi_off, local_th); diff --git a/lustre/osp/osp_precreate.c b/lustre/osp/osp_precreate.c index 5e0c8c7..e3d2ee1 100644 --- a/lustre/osp/osp_precreate.c +++ b/lustre/osp/osp_precreate.c @@ -1475,6 +1475,7 @@ int osp_precreate_reserve(const struct lu_env *env, struct osp_device *d) int osp_precreate_get_fid(const struct lu_env *env, struct osp_device *d, struct lu_fid *fid) { + struct lu_fid *pre_used_fid = &d->opd_pre_used_fid; /* grab next id from the pool */ spin_lock(&d->opd_pre_lock); @@ -1484,6 +1485,20 @@ int osp_precreate_get_fid(const struct lu_env *env, struct osp_device *d, PFID(&d->opd_pre_used_fid), PFID(&d->opd_pre_last_created_fid)); + /* + * When sequence is used up, new one should be allocated in + * osp_precreate_rollover_new_seq. So ASSERT here to avoid + * objid overflow. + */ + LASSERTF(osp_fid_end_seq(env, pre_used_fid) == 0, + "next fid "DFID" last created fid "DFID"\n", + PFID(&d->opd_pre_used_fid), + PFID(&d->opd_pre_last_created_fid)); + /* Non IDIF fids shoulnd't get here with oid == 0xFFFFFFFF. */ + if (fid_is_idif(pre_used_fid) && + unlikely(fid_oid(pre_used_fid) == LUSTRE_DATA_SEQ_MAX_WIDTH)) + pre_used_fid->f_seq++; + d->opd_pre_used_fid.f_oid++; memcpy(fid, &d->opd_pre_used_fid, sizeof(*fid)); d->opd_pre_reserved--; -- 1.8.3.1