X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fosp%2Fosp_dev.c;h=9a66737bc033d838435b22fa0f9863c16df0b315;hp=c8e490e9266ecb7db0e5fad6c07d39537e01b656;hb=f4547f0569774eb794fb143362e201f658415f4c;hpb=74ec68346e14851ad8a1912185e1dccd3e6d12cd diff --git a/lustre/osp/osp_dev.c b/lustre/osp/osp_dev.c index c8e490e..9a66737 100644 --- a/lustre/osp/osp_dev.c +++ b/lustre/osp/osp_dev.c @@ -39,6 +39,7 @@ * * Author: Alex Zhuravlev * Author: Mikhail Pershin + * Author: Di Wang */ #ifndef EXPORT_SYMTAB @@ -71,20 +72,28 @@ struct lu_object *osp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *d) { - struct lu_object_header *h; + struct lu_object_header *h = NULL; struct osp_object *o; struct lu_object *l; - LASSERT(hdr == NULL); - OBD_SLAB_ALLOC_PTR_GFP(o, osp_object_kmem, CFS_ALLOC_IO); if (o != NULL) { l = &o->opo_obj.do_lu; - h = &o->opo_header; - lu_object_header_init(h); - dt_object_init(&o->opo_obj, h, d); - lu_object_add_top(h, l); + /* For data object, OSP obj would always be the top + * object, i.e. hdr is always NULL, see lu_object_alloc. + * But for metadata object, we always build the object + * stack from MDT. i.e. mdt_object will be the top object + * i.e. hdr != NULL */ + if (hdr == NULL) { + /* object for OST */ + h = &o->opo_header; + lu_object_header_init(h); + dt_object_init(&o->opo_obj, h, d); + lu_object_add_top(h, l); + } else { + dt_object_init(&o->opo_obj, h, d); + } l->lo_ops = &osp_lu_obj_ops; @@ -94,106 +103,215 @@ struct lu_object *osp_object_alloc(const struct lu_env *env, } } -/* 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) +static struct dt_object +*osp_find_or_create(const struct lu_env *env, struct osp_device *osp, + struct lu_attr *attr, __u32 reg_id) { - /* - * 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); + struct osp_thread_info *osi = osp_env_info(env); + struct dt_object_format dof = { 0 }; + struct dt_object *dto; + int rc; + ENTRY; + + lu_local_obj_fid(&osi->osi_fid, reg_id); + attr->la_valid = LA_MODE; + attr->la_mode = S_IFREG | 0644; + dof.dof_type = DFT_REGULAR; + dto = dt_find_or_create(env, osp->opd_storage, &osi->osi_fid, + &dof, attr); + if (IS_ERR(dto)) + RETURN(dto); + + rc = dt_attr_get(env, dto, attr, NULL); + if (rc) { + CERROR("%s: can't be initialized: rc = %d\n", + osp->opd_obd->obd_name, rc); + lu_object_put(env, &dto->do_lu); + RETURN(ERR_PTR(rc)); } + RETURN(dto); } -static int osp_last_used_init(const struct lu_env *env, struct osp_device *m) +static int osp_write_local_file(const struct lu_env *env, + struct osp_device *osp, + struct dt_object *dt_obj, + struct lu_buf *buf, + loff_t offset) { - struct osp_thread_info *osi = osp_env_info(env); - struct dt_object_format dof = { 0 }; - struct dt_object *o; - int rc; - - ENTRY; + struct thandle *th; + int rc; - 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)); + th = dt_trans_create(env, osp->opd_storage); + if (IS_ERR(th)) + RETURN(PTR_ERR(th)); - rc = dt_attr_get(env, o, &osi->osi_attr, NULL); + rc = dt_declare_record_write(env, dt_obj, buf->lb_len, offset, th); + if (rc) + GOTO(out, rc); + rc = dt_trans_start_local(env, osp->opd_storage, th); if (rc) GOTO(out, rc); - /* object will be released in device cleanup path */ - m->opd_last_used_file = o; + rc = dt_record_write(env, dt_obj, buf, &offset, th); +out: + dt_trans_stop(env, osp->opd_storage, th); + RETURN(rc); +} + +static int osp_init_last_objid(const struct lu_env *env, struct osp_device *osp) +{ + struct osp_thread_info *osi = osp_env_info(env); + struct lu_fid *fid = &osp->opd_last_used_fid; + struct dt_object *dto; + int rc; + ENTRY; - 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); + dto = osp_find_or_create(env, osp, &osi->osi_attr, MDD_LOV_OBJ_OID); + if (IS_ERR(dto)) + RETURN(PTR_ERR(dto)); + /* 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->opd_index); + rc = dt_record_read(env, dto, &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; + fid->f_oid = 0; + osp_objid_buf_prep(&osi->osi_lb, &osi->osi_off, &fid->f_oid, + osp->opd_index); + rc = osp_write_local_file(env, osp, dto, &osi->osi_lb, + osi->osi_off); + } + osp->opd_last_used_oid_file = dto; + RETURN(0); +out: + /* object will be released in device cleanup path */ + CERROR("%s: can't initialize lov_objid: rc = %d\n", + osp->opd_obd->obd_name, rc); + lu_object_put(env, &dto->do_lu); + osp->opd_last_used_oid_file = NULL; + RETURN(rc); +} - m->opd_last_used_id = 0; - osp_objid_buf_prep(osi, m, m->opd_index); +static int osp_init_last_seq(const struct lu_env *env, struct osp_device *osp) +{ + struct osp_thread_info *osi = osp_env_info(env); + struct lu_fid *fid = &osp->opd_last_used_fid; + struct dt_object *dto; + int rc; + ENTRY; - th = dt_trans_create(env, m->opd_storage); - if (IS_ERR(th)) - GOTO(out, rc = PTR_ERR(th)); + dto = osp_find_or_create(env, osp, &osi->osi_attr, MDD_LOV_OBJ_OSEQ); + if (IS_ERR(dto)) + RETURN(PTR_ERR(dto)); - 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); + /* object will be released in device cleanup path */ + if (osi->osi_attr.la_size >= + sizeof(osi->osi_id) * (osp->opd_index + 1)) { + osp_objseq_buf_prep(&osi->osi_lb, &osi->osi_off, &fid->f_seq, + osp->opd_index); + rc = dt_record_read(env, dto, &osi->osi_lb, &osi->osi_off); + if (rc != 0) GOTO(out, rc); - } + } else { + fid->f_seq = 0; + osp_objseq_buf_prep(&osi->osi_lb, &osi->osi_off, &fid->f_seq, + osp->opd_index); + rc = osp_write_local_file(env, osp, dto, &osi->osi_lb, + osi->osi_off); + } + osp->opd_last_used_seq_file = dto; + RETURN(0); +out: + /* object will be released in device cleanup path */ + CERROR("%s: can't initialize lov_seq: rc = %d\n", + osp->opd_obd->obd_name, rc); + lu_object_put(env, &dto->do_lu); + osp->opd_last_used_seq_file = NULL; + RETURN(rc); +} + +static int osp_last_used_init(const struct lu_env *env, struct osp_device *osp) +{ + struct osp_thread_info *osi = osp_env_info(env); + int rc; + ENTRY; + + fid_zero(&osp->opd_last_used_fid); + rc = osp_init_last_objid(env, osp); + if (rc < 0) { + CERROR("%s: Can not get ids %d from old objid!\n", + osp->opd_obd->obd_name, rc); + RETURN(rc); + } + + rc = osp_init_last_seq(env, osp); + if (rc < 0) { + CERROR("%s: Can not get ids %d from old objid!\n", + osp->opd_obd->obd_name, rc); + GOTO(out, rc); + } - rc = dt_trans_start_local(env, m->opd_storage, th); + if (fid_oid(&osp->opd_last_used_fid) != 0 && + fid_seq(&osp->opd_last_used_fid) == 0) { + /* Just upgrade from the old version, + * set the seq to be IDIF */ + osp->opd_last_used_fid.f_seq = + fid_idif_seq(fid_oid(&osp->opd_last_used_fid), + osp->opd_index); + osp_objseq_buf_prep(&osi->osi_lb, &osi->osi_off, + &osp->opd_last_used_fid.f_seq, + osp->opd_index); + rc = osp_write_local_file(env, osp, osp->opd_last_used_seq_file, + &osi->osi_lb, osi->osi_off); if (rc) { - dt_trans_stop(env, m->opd_storage, th); + CERROR("%s : Can not write seq file: rc = %d\n", + osp->opd_obd->obd_name, rc); 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); + if (!fid_is_zero(&osp->opd_last_used_fid) && + !fid_is_sane(&osp->opd_last_used_fid)) { + CERROR("%s: Got invalid FID "DFID"\n", osp->opd_obd->obd_name, + PFID(&osp->opd_last_used_fid)); + GOTO(out, rc = -EINVAL); } - CDEBUG(D_HA, "%s: Read last used ID: "LPU64"\n", m->opd_obd->obd_name, - le64_to_cpu(m->opd_last_used_id)); - RETURN(0); + + CDEBUG(D_INFO, "%s: Init last used fid "DFID"\n", + osp->opd_obd->obd_name, PFID(&osp->opd_last_used_fid)); out: - 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; + if (rc != 0) { + if (osp->opd_last_used_oid_file != NULL) { + lu_object_put(env, &osp->opd_last_used_oid_file->do_lu); + osp->opd_last_used_oid_file = NULL; + } + if (osp->opd_last_used_seq_file != NULL) { + lu_object_put(env, &osp->opd_last_used_seq_file->do_lu); + osp->opd_last_used_seq_file = NULL; + } + } + + RETURN(rc); } static void osp_last_used_fini(const struct lu_env *env, struct osp_device *d) { - if (d->opd_last_used_file != NULL) { - lu_object_put(env, &d->opd_last_used_file->do_lu); - d->opd_last_used_file = NULL; + /* release last_used file */ + if (d->opd_last_used_oid_file != NULL) { + lu_object_put(env, &d->opd_last_used_oid_file->do_lu); + d->opd_last_used_oid_file = NULL; + } + + if (d->opd_last_used_seq_file != NULL) { + lu_object_put(env, &d->opd_last_used_seq_file->do_lu); + d->opd_last_used_seq_file = NULL; } } -int osp_disconnect(struct osp_device *d) +static int osp_disconnect(struct osp_device *d) { struct obd_import *imp; int rc = 0; @@ -232,11 +350,6 @@ static int osp_shutdown(const struct lu_env *env, struct osp_device *d) int rc = 0; ENTRY; - if (is_osp_for_connection(d->opd_obd->obd_name)) { - rc = osp_disconnect(d); - RETURN(rc); - } - LASSERT(env); /* release last_used file */ if (!d->opd_connect_mdt) @@ -267,9 +380,11 @@ static int osp_process_config(const struct lu_env *env, ENTRY; switch (lcfg->lcfg_command) { + case LCFG_PRE_CLEANUP: + rc = osp_disconnect(d); + break; case LCFG_CLEANUP: - if (!is_osp_for_connection(d->opd_obd->obd_name)) - lu_dev_del_linkage(dev->ld_site, dev); + lu_dev_del_linkage(dev->ld_site, dev); rc = osp_shutdown(env, d); break; case LCFG_PARAM: @@ -341,8 +456,15 @@ static int osp_statfs(const struct lu_env *env, struct dt_device *dev, * layer above osp (usually lod) can use ffree to estimate * how many objects are available for immediate creation */ + spin_lock(&d->opd_pre_lock); - sfs->os_fprecreated = d->opd_pre_last_created - d->opd_pre_used_id; + LASSERTF(fid_seq(&d->opd_pre_last_created_fid) == + fid_seq(&d->opd_pre_used_fid), + "last_created "DFID", next_fid "DFID"\n", + PFID(&d->opd_pre_last_created_fid), + PFID(&d->opd_pre_used_fid)); + sfs->os_fprecreated = fid_oid(&d->opd_pre_last_created_fid) - + fid_oid(&d->opd_pre_used_fid); sfs->os_fprecreated -= d->opd_pre_reserved; spin_unlock(&d->opd_pre_lock); @@ -369,6 +491,8 @@ static int osp_sync(const struct lu_env *env, struct dt_device *dev) const struct dt_device_operations osp_dt_ops = { .dt_statfs = osp_statfs, .dt_sync = osp_sync, + .dt_trans_start = osp_trans_start, + .dt_trans_stop = osp_trans_stop, }; static int osp_connect_to_osd(const struct lu_env *env, struct osp_device *m, @@ -609,7 +733,7 @@ out_last_used: out_proc: ptlrpc_lprocfs_unregister_obd(obd); lprocfs_obd_cleanup(obd); - class_destroy_import(obd->u.cli.cl_import); + obd_cleanup_client_import(obd); client_obd_cleanup(obd); out_ref: ptlrpcd_decref(); @@ -659,10 +783,7 @@ static struct lu_device *osp_device_alloc(const struct lu_env *env, l = osp2lu_dev(m); dt_device_init(&m->opd_dt_dev, t); - if (is_osp_for_connection(lustre_cfg_string(lcfg, 0))) - rc = osp_init_for_ost(env, m, t, lcfg); - else - rc = osp_init0(env, m, t, lcfg); + rc = osp_init0(env, m, t, lcfg); if (rc != 0) { osp_device_free(env, l); l = ERR_PTR(rc); @@ -683,9 +804,6 @@ static struct lu_device *osp_device_fini(const struct lu_env *env, if (m->opd_storage_exp) obd_disconnect(m->opd_storage_exp); - if (is_osp_for_connection(m->opd_obd->obd_name)) - osp_fini_for_ost(m); - imp = m->opd_obd->u.cli.cl_import; if (imp->imp_rq_pool) { @@ -749,8 +867,6 @@ static int osp_obd_connect(const struct lu_env *env, struct obd_export **exp, RETURN(rc); *exp = class_conn2export(&conn); - osp->opd_exp = *exp; - /* Why should there ever be more than 1 connect? */ osp->opd_connects++; LASSERT(osp->opd_connects == 1); @@ -764,8 +880,6 @@ static int osp_obd_connect(const struct lu_env *env, struct obd_export **exp, LASSERT(data->ocd_connect_flags & OBD_CONNECT_INDEX); ocd = &imp->imp_connect_data; *ocd = *data; - if (is_osp_for_connection(osp->opd_obd->obd_name)) - ocd->ocd_connect_flags |= OBD_CONNECT_LIGHTWEIGHT; imp->imp_connect_flags_orig = ocd->ocd_connect_flags; @@ -781,16 +895,14 @@ static int osp_obd_connect(const struct lu_env *env, struct obd_export **exp, ptlrpc_pinger_add_import(imp); - /* set seq controller export for MDC0 if exists */ - if (osp->opd_connect_mdt && !is_osp_for_connection(obd->obd_name) && - data->ocd_index == 0) { + if (osp->opd_connect_mdt && data->ocd_index == 0) { + /* set seq controller export for MDC0 if exists */ struct seq_server_site *ss; ss = lu_site2seq(osp2lu_dev(osp)->ld_site); ss->ss_control_exp = class_export_get(*exp); ss->ss_server_fld->lsf_control_exp = *exp; } - out: RETURN(rc); } @@ -818,8 +930,7 @@ static int osp_obd_disconnect(struct obd_export *exp) } /* destroy the device */ - if (!is_osp_for_connection(obd->obd_name)) - class_manual_cleanup(obd); + class_manual_cleanup(obd); RETURN(rc); } @@ -921,9 +1032,6 @@ static int osp_import_event(struct obd_device *obd, struct obd_import *imp, d->opd_imp_seen_connected = 1; if (d->opd_connect_mdt) break; - if (d->opd_obd->u.cli.cl_seq->lcs_exp == NULL) - d->opd_obd->u.cli.cl_seq->lcs_exp = - class_export_get(d->opd_exp); cfs_waitq_signal(&d->opd_pre_waitq); __osp_sync_check_for_work(d); CDEBUG(D_HA, "got connected\n"); @@ -1087,6 +1195,16 @@ static int __init osp_mod_init(void) return rc; } + lprocfs_lwp_init_vars(&lvars); + + rc = class_register_type(&lwp_obd_device_ops, NULL, lvars.module_vars, + LUSTRE_LWP_NAME, &lwp_device_type); + if (rc != 0) { + class_unregister_type(LUSTRE_OSP_NAME); + lu_kmem_fini(osp_caches); + return rc; + } + /* Note: add_rec/delcare_add_rec will be only used by catalogs */ osp_mds_ost_orig_logops = llog_osd_ops; osp_mds_ost_orig_logops.lop_add = llog_cat_add_rec; @@ -1107,6 +1225,7 @@ static void __exit osp_mod_exit(void) { lprocfs_try_remove_proc_entry("osc", proc_lustre_root); + class_unregister_type(LUSTRE_LWP_NAME); class_unregister_type(LUSTRE_OSP_NAME); lu_kmem_fini(osp_caches); }