}
}
+/* Update opd_last_used_id along with checking for gap in objid sequence */
+void osp_update_last_id(struct osp_device *d, obd_id objid)
+{
+ /*
+ * we might have lost precreated objects due to VBR and precreate
+ * orphans, the gap in objid can be calculated properly only here
+ */
+ if (objid > le64_to_cpu(d->opd_last_used_id)) {
+ if (objid - le64_to_cpu(d->opd_last_used_id) > 1) {
+ d->opd_gap_start = le64_to_cpu(d->opd_last_used_id) + 1;
+ d->opd_gap_count = objid - d->opd_gap_start;
+ CDEBUG(D_HA, "Gap in objids: %d, start = %llu\n",
+ d->opd_gap_count, d->opd_gap_start);
+ }
+ d->opd_last_used_id = cpu_to_le64(objid);
+ }
+}
+
+static int osp_last_used_init(const struct lu_env *env, struct osp_device *m)
+{
+ struct osp_thread_info *osi = osp_env_info(env);
+ struct dt_object_format dof = { 0 };
+ struct dt_object *o;
+ int rc;
+
+ ENTRY;
+
+ osi->osi_attr.la_valid = LA_MODE;
+ osi->osi_attr.la_mode = S_IFREG | 0644;
+ lu_local_obj_fid(&osi->osi_fid, MDD_LOV_OBJ_OID);
+ dof.dof_type = DFT_REGULAR;
+ o = dt_find_or_create(env, m->opd_storage, &osi->osi_fid, &dof,
+ &osi->osi_attr);
+ if (IS_ERR(o))
+ RETURN(PTR_ERR(o));
+
+ rc = dt_attr_get(env, o, &osi->osi_attr, NULL);
+ if (rc)
+ GOTO(out, rc);
+
+ m->opd_last_used_file = o;
+
+ if (osi->osi_attr.la_size >= sizeof(osi->osi_id) *
+ (m->opd_index + 1)) {
+ osp_objid_buf_prep(osi, m, m->opd_index);
+ rc = dt_record_read(env, o, &osi->osi_lb, &osi->osi_off);
+ if (rc != 0)
+ GOTO(out, rc);
+ } else {
+ /* reset value to 0, just to make sure and change file's size */
+ struct thandle *th;
+
+ m->opd_last_used_id = 0;
+ osp_objid_buf_prep(osi, m, m->opd_index);
+
+ th = dt_trans_create(env, m->opd_storage);
+ if (IS_ERR(th))
+ GOTO(out, rc = PTR_ERR(th));
+
+ rc = dt_declare_record_write(env, m->opd_last_used_file,
+ osi->osi_lb.lb_len, osi->osi_off,
+ th);
+ if (rc) {
+ dt_trans_stop(env, m->opd_storage, th);
+ GOTO(out, rc);
+ }
+
+ rc = dt_trans_start_local(env, m->opd_storage, th);
+ if (rc) {
+ dt_trans_stop(env, m->opd_storage, th);
+ GOTO(out, rc);
+ }
+
+ rc = dt_record_write(env, m->opd_last_used_file, &osi->osi_lb,
+ &osi->osi_off, th);
+ dt_trans_stop(env, m->opd_storage, th);
+ if (rc)
+ GOTO(out, rc);
+ }
+ RETURN(0);
+out:
+ /* object will be released in device cleanup path */
+ CERROR("%s: can't initialize lov_objid: %d\n",
+ m->opd_obd->obd_name, rc);
+ lu_object_put(env, &o->do_lu);
+ m->opd_last_used_file = NULL;
+ RETURN(rc);
+}
+
+static void osp_last_used_fini(const struct lu_env *env, struct osp_device *d)
+{
+ lu_object_put(env, &d->opd_last_used_file->do_lu);
+ d->opd_last_used_file = NULL;
+}
+
static int osp_shutdown(const struct lu_env *env, struct osp_device *d)
{
struct obd_import *imp;
int rc = 0;
-
ENTRY;
+ /* release last_used file */
+ osp_last_used_fini(env, d);
+
imp = d->opd_obd->u.cli.cl_import;
/* Mark import deactivated now, so we don't try to reconnect if any
}
/*
+ * Initialize last id from the storage - will be used in orphan cleanup
+ */
+ rc = osp_last_used_init(env, m);
+ if (rc)
+ GOTO(out_proc, rc);
+
+ /*
* Initiate connect to OST
*/
ll_generate_random_uuid(uuid);
RETURN(0);
out:
+ osp_last_used_fini(env, m);
+out_proc:
ptlrpc_lprocfs_unregister_obd(m->opd_obd);
lprocfs_obd_cleanup(m->opd_obd);
class_destroy_import(m->opd_obd->u.cli.cl_import);
/* device used to store persistent state (llogs, last ids) */
struct obd_export *opd_storage_exp;
struct dt_device *opd_storage;
+ struct dt_object *opd_last_used_file;
+ /* protected by opd_pre_lock */
+ volatile obd_id opd_last_used_id;
+ obd_id opd_gap_start;
+ int opd_gap_count;
/* connection to OST */
struct obd_device *opd_obd;
struct obd_export *opd_exp;
extern struct lu_object_operations osp_lu_obj_ops;
struct osp_thread_info {
+ struct lu_buf osi_lb;
+ struct lu_fid osi_fid;
struct lu_attr osi_attr;
+ obd_id osi_id;
+ loff_t osi_off;
};
+static inline void osp_objid_buf_prep(struct osp_thread_info *osi,
+ struct osp_device *d, int index)
+{
+ osi->osi_lb.lb_buf = (void *)&d->opd_last_used_id;
+ osi->osi_lb.lb_len = sizeof(d->opd_last_used_id);
+ osi->osi_off = sizeof(d->opd_last_used_id) * index;
+}
+
extern struct lu_context_key osp_thread_key;
static inline struct osp_thread_info *osp_env_info(const struct lu_env *env)
struct dt_object, do_lu);
}
+/* osp_dev.c */
+void osp_update_last_id(struct osp_device *d, obd_id objid);
+
/* lproc_osp.c */
void lprocfs_osp_init_vars(struct lprocfs_static_vars *lvars);