LASSERT(lu_seq_range_is_sane(space));
+restart:
rc = seq_server_check_and_alloc_super(env, seq);
if (rc < 0) {
if (rc == -EINPROGRESS) {
if (seq->lss_set_width) {
rc = range_alloc_set(env, out, seq);
} else {
+ __u64 last_seq;
+
+ rc = dt_last_seq_get(env, seq->lss_dev, &last_seq);
+ if (!rc) {
+ if (last_seq + 1 >= space->lsr_end) {
+ LCONSOLE_INFO("%s: On disk last known sequence %#llx beyond super-sequence "
+ DRANGE", getting new super-sequence\n",
+ seq->lss_name, last_seq,
+ PRANGE(space));
+ space->lsr_start = space->lsr_end;
+ GOTO(restart, rc);
+ }
+ if (last_seq >= space->lsr_start) {
+ LCONSOLE_INFO("%s: On disk last known sequence %#llx within super-sequence "
+ DRANGE", updating super-sequence\n",
+ seq->lss_name, last_seq,
+ PRANGE(space));
+ space->lsr_start = last_seq + 1;
+ }
+ }
range_alloc(out, space, seq->lss_width);
rc = seq_store_update(env, seq, NULL, 1);
}
dt_obj = dt_find_or_create(env, dt, &fid, &dof, &attr);
if (!IS_ERR(dt_obj)) {
seq->lss_obj = dt_obj;
+ seq->lss_dev = dt;
rc = 0;
} else {
CERROR("%s: Can't find \"%s\" obj %d\n",
int (*dt_reserve_or_free_quota)(const struct lu_env *env,
struct dt_device *dev,
struct lquota_id_info *qi);
+
+ /**
+ * Return last known sequence number from disk.
+ *
+ * \param[in] env execution environment for this thread
+ * \param[in] dev dt device
+ * \param[out] seq last known sequence on disk
+ *
+ * \retval 0 on success
+ * \retval negative negated errno on error
+ */
+ int (*dt_last_seq_get)(const struct lu_env *env,
+ struct dt_device *dev,
+ __u64 *seq);
};
struct dt_index_features {
return dev->dd_ops->dt_reserve_or_free_quota(env, dev, qi);
}
+static inline int dt_last_seq_get(const struct lu_env *env,
+ struct dt_device *dev,
+ __u64 *seq)
+{
+ LASSERT(dev);
+ LASSERT(dev->dd_ops);
+ LASSERT(dev->dd_ops->dt_last_seq_get);
+ return dev->dd_ops->dt_last_seq_get(env, dev, seq);
+}
+
static inline int dt_lookup(const struct lu_env *env,
struct dt_object *dt,
struct dt_rec *rec,
.dt_ro = osd_ro,
.dt_commit_async = osd_commit_async,
.dt_reserve_or_free_quota = osd_reserve_or_free_quota,
+ .dt_last_seq_get = osd_last_seq_get,
};
static void osd_inode_getattr(const struct lu_env *env,
return osd_scan_dir(env, dev, dev->od_ost_map->om_root->d_inode,
osd_scan_O_seq);
}
+
+static int osd_seq_dir_helper(const struct lu_env *env,
+ struct osd_device *osd, struct inode *dir,
+ struct osd_it_ea *oie)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct lu_fid *fid = &info->oti_fid;
+ struct inode *inode;
+ struct osd_inode_id id;
+ char *name = NULL;
+ __u64 seq;
+ int rc = 0;
+
+ ENTRY;
+
+ osd_id_gen(&id, oie->oie_dirent->oied_ino, OSD_OII_NOGEN);
+ inode = osd_iget(info, osd, &id, 0);
+ if (IS_ERR(inode))
+ RETURN(PTR_ERR(inode));
+
+ if (!S_ISDIR(inode->i_mode))
+ GOTO(out, rc);
+
+ OBD_ALLOC(name, oie->oie_dirent->oied_namelen + 1);
+ if (name == NULL)
+ GOTO(out, rc = -ENOMEM);
+ memcpy(name, oie->oie_dirent->oied_name,
+ oie->oie_dirent->oied_namelen);
+ name[oie->oie_dirent->oied_namelen] = '\0';
+
+ rc = kstrtoull(name, 16, &seq);
+ if (!rc && seq >= FID_SEQ_NORMAL && seq > fid_seq(fid))
+ fid->f_seq = seq;
+
+ OBD_FREE(name, oie->oie_dirent->oied_namelen + 1);
+out:
+ iput(inode);
+ RETURN(rc);
+}
+
+int osd_last_seq_get(const struct lu_env *env, struct dt_device *dt,
+ __u64 *seq)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct osd_device *osd = osd_dt_dev(dt);
+ struct lu_fid *fid = &info->oti_fid;
+ int rc;
+
+ ENTRY;
+
+ if (!osd->od_is_ost)
+ RETURN(-EINVAL);
+
+ fid_zero(fid);
+ rc = osd_scan_dir(env, osd, osd->od_ost_map->om_root->d_inode,
+ osd_seq_dir_helper);
+ if (!rc)
+ *seq = fid_seq(fid);
+
+ RETURN(rc);
+}
time64_t os_bad_oimap_time;
};
+int osd_last_seq_get(const struct lu_env *env, struct dt_device *dt,
+ __u64 *seq);
#endif /* _OSD_SCRUB_H */
.dt_commit_async = osd_commit_async,
.dt_ro = osd_ro,
.dt_reserve_or_free_quota = osd_reserve_or_free_quota,
+ .dt_last_seq_get = osd_last_seq_get,
};
static void *osd_key_init(const struct lu_context *ctx,
const struct lu_fid *fid, uint64_t oid, bool insert);
int osd_oii_lookup(struct osd_device *dev, const struct lu_fid *fid,
uint64_t *oid);
+int osd_last_seq_get(const struct lu_env *env, struct dt_device *dt,
+ __u64 *seq);
/**
* Basic transaction credit op
{
return osd_scan_dir(env, dev, dev->od_O_id, osd_scan_O_seq);
}
+
+static int osd_seq_dir_helper(const struct lu_env *env,
+ struct osd_device *osd, uint64_t dir_oid,
+ struct osd_zap_it *ozi)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct lu_fid *fid = &info->oti_fid;
+ __u64 seq;
+ int rc;
+
+ if (!S_ISDIR(cpu_to_le16(DTTOIF(ozi->ozi_zde.lzd_reg.zde_type))))
+ return 0;
+
+ rc = kstrtoull(ozi->ozi_name, 16, &seq);
+ if (!rc && seq >= FID_SEQ_NORMAL && seq > fid_seq(fid))
+ fid->f_seq = seq;
+
+ return 0;
+}
+
+int osd_last_seq_get(const struct lu_env *env, struct dt_device *dt,
+ __u64 *seq)
+{
+ struct osd_thread_info *info = osd_oti_get(env);
+ struct osd_device *osd = osd_dt_dev(dt);
+ struct lu_fid *fid = &info->oti_fid;
+ int rc;
+
+ ENTRY;
+
+ if (!osd->od_is_ost)
+ RETURN(-EINVAL);
+
+ fid_zero(fid);
+ rc = osd_scan_dir(env, osd, osd->od_O_id, osd_seq_dir_helper);
+ if (!rc)
+ *seq = fid_seq(fid);
+
+ RETURN(rc);
+}