static int __out_tx_xattr_set(const struct lu_env *env, struct dt_object *dt_obj, const struct lu_buf *buf, const char *name, int flags, struct thandle_exec_args *ta, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(ta->ta_handle != NULL); ta->ta_err = dt_declare_xattr_set(env, dt_obj, buf, name, flags, ta->ta_handle); if (ta->ta_err != 0) return ta->ta_err; arg = tx_add_exec(ta, out_tx_xattr_set_exec, NULL, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->u.xattr_set.name = name; arg->u.xattr_set.flags = flags; arg->u.xattr_set.buf = *buf; arg->reply = reply; arg->index = index; arg->u.xattr_set.csum = 0; return 0; }
/** * This is helper function to get llog directory object. It is used by named * llog operations to find/insert/delete llog entry from llog directory. * * \param[in] env execution environment * \param[in] ctxt llog context * * \retval dt_object of llog directory * \retval ERR_PTR of negative value on error */ struct dt_object *llog_osd_dir_get(const struct lu_env *env, struct llog_ctxt *ctxt) { struct dt_device *dt; struct dt_thread_info *dti = dt_info(env); struct dt_object *dir; int rc; dt = ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt; if (ctxt->loc_dir == NULL) { rc = dt_root_get(env, dt, &dti->dti_fid); if (rc) return ERR_PTR(rc); dir = dt_locate(env, dt, &dti->dti_fid); if (!IS_ERR(dir) && !dt_try_as_dir(env, dir)) { lu_object_put(env, &dir->do_lu); return ERR_PTR(-ENOTDIR); } } else { lu_object_get(&ctxt->loc_dir->do_lu); dir = ctxt->loc_dir; } return dir; }
static int __out_tx_write(const struct lu_env *env, struct dt_object *dt_obj, const struct lu_buf *buf, loff_t pos, struct thandle_exec_args *ta, struct object_update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(ta->ta_handle != NULL); ta->ta_err = dt_declare_record_write(env, dt_obj, buf, pos, ta->ta_handle); if (ta->ta_err != 0) return ta->ta_err; arg = tx_add_exec(ta, out_tx_write_exec, NULL, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->u.write.buf = *buf; arg->u.write.pos = pos; arg->reply = reply; arg->index = index; return 0; }
static int __out_tx_create(const struct lu_env *env, struct dt_object *obj, struct lu_attr *attr, struct lu_fid *parent_fid, struct dt_object_format *dof, struct thandle_exec_args *ta, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(ta->ta_handle != NULL); ta->ta_err = dt_declare_create(env, obj, attr, NULL, dof, ta->ta_handle); if (ta->ta_err != 0) return ta->ta_err; arg = tx_add_exec(ta, out_tx_create_exec, out_tx_create_undo, file, line); LASSERT(arg); /* release the object in out_trans_stop */ lu_object_get(&obj->do_lu); arg->object = obj; arg->u.create.attr = *attr; if (parent_fid) arg->u.create.fid = *parent_fid; memset(&arg->u.create.hint, 0, sizeof(arg->u.create.hint)); arg->u.create.dof = *dof; arg->reply = reply; arg->index = index; return 0; }
static int __out_tx_index_delete(const struct lu_env *env, struct dt_object *dt_obj, char *name, struct thandle_exec_args *ta, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; if (dt_try_as_dir(env, dt_obj) == 0) { ta->ta_err = -ENOTDIR; return ta->ta_err; } LASSERT(ta->ta_handle != NULL); ta->ta_err = dt_declare_delete(env, dt_obj, (struct dt_key *)name, ta->ta_handle); if (ta->ta_err != 0) return ta->ta_err; arg = tx_add_exec(ta, out_tx_index_delete_exec, out_tx_index_delete_undo, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->reply = reply; arg->index = index; arg->u.insert.key = (struct dt_key *)name; return 0; }
/** * Initialize osd Iterator for given osd index object. * * \param dt - osd index object * \param attr - not used * \param capa - BYPASS_CAPA */ static struct dt_it *osd_it_acct_init(const struct lu_env *env, struct dt_object *dt, __u32 attr, struct lustre_capa *capa) { struct osd_thread_info *info = osd_oti_get(env); struct osd_it_quota *it; struct lu_object *lo = &dt->do_lu; struct osd_device *osd = osd_dev(lo->lo_dev); int rc; ENTRY; LASSERT(lu_object_exists(lo)); if (info == NULL) RETURN(ERR_PTR(-ENOMEM)); it = &info->oti_it_quota; memset(it, 0, sizeof(*it)); it->oiq_oid = osd_quota_fid2dmu(lu_object_fid(lo)); /* initialize zap cursor */ rc = -udmu_zap_cursor_init(&it->oiq_zc, &osd->od_objset, it->oiq_oid,0); if (rc) RETURN(ERR_PTR(rc)); /* take object reference */ lu_object_get(lo); it->oiq_obj = osd_dt_obj(dt); it->oiq_reset = 1; RETURN((struct dt_it *)it); }
static int __out_tx_attr_set(struct mdt_thread_info *info, struct dt_object *dt_obj, const struct lu_attr *attr, struct thandle_exec_args *th, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(th->ta_handle != NULL); th->ta_err = dt_declare_attr_set(info->mti_env, dt_obj, attr, th->ta_handle); if (th->ta_err != 0) return th->ta_err; arg = tx_add_exec(th, out_tx_attr_set_exec, out_tx_attr_set_undo, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->u.attr_set.attr = *attr; arg->reply = reply; arg->index = index; return 0; }
static struct dt_it *osd_index_it_init(const struct lu_env *env, struct dt_object *dt, __u32 unused, struct lustre_capa *capa) { struct osd_thread_info *info = osd_oti_get(env); struct osd_zap_it *it; struct osd_object *obj = osd_dt_obj(dt); struct osd_device *osd = osd_obj2dev(obj); struct lu_object *lo = &dt->do_lu; ENTRY; /* XXX: check capa ? */ LASSERT(lu_object_exists(lo)); LASSERT(obj->oo_db); LASSERT(udmu_object_is_zap(obj->oo_db)); LASSERT(info); it = &info->oti_it_zap; if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset, obj->oo_db->db_object, 0)) RETURN(ERR_PTR(-ENOMEM)); it->ozi_obj = obj; it->ozi_capa = capa; it->ozi_reset = 1; lu_object_get(lo); RETURN((struct dt_it *)it); }
/** * Add new item for parent FID verification. * * Prepare new verification item and pass it to the dedicated * verification thread for further processing. * * \param[in] env execution environment * \param[in] fo OFD object * \param[in] oa OBDO structure with PFID */ static void ofd_add_inconsistency_item(const struct lu_env *env, struct ofd_object *fo, struct obdo *oa) { struct ofd_device *ofd = ofd_obj2dev(fo); struct ofd_inconsistency_item *oii; struct filter_fid *ff; bool wakeup = false; OBD_ALLOC_PTR(oii); if (oii == NULL) return; INIT_LIST_HEAD(&oii->oii_list); lu_object_get(&fo->ofo_obj.do_lu); oii->oii_obj = fo; ff = &oii->oii_ff; ff->ff_parent.f_seq = oa->o_parent_seq; ff->ff_parent.f_oid = oa->o_parent_oid; ff->ff_parent.f_stripe_idx = oa->o_stripe_idx; ff->ff_layout = oa->o_layout; spin_lock(&ofd->ofd_inconsistency_lock); if (fo->ofo_pfid_checking || fo->ofo_pfid_verified) { spin_unlock(&ofd->ofd_inconsistency_lock); OBD_FREE_PTR(oii); return; } fo->ofo_pfid_checking = 1; if (list_empty(&ofd->ofd_inconsistency_list)) wakeup = true; list_add_tail(&oii->oii_list, &ofd->ofd_inconsistency_list); spin_unlock(&ofd->ofd_inconsistency_lock); if (wakeup) wake_up_all(&ofd->ofd_inconsistency_thread.t_ctl_waitq); /* XXX: When the found inconsistency exceeds some threshold, * we can trigger the LFSCK to scan part of the system * or the whole system, which depends on how to define * the threshold, a simple way maybe like that: define * the absolute value of how many inconsisteny allowed * to be repaired via self detect/repair mechanism, if * exceeded, then trigger the LFSCK to scan the layout * inconsistency within the whole system. */ }
static int __out_tx_destroy(const struct lu_env *env, struct dt_object *dt_obj, struct thandle_exec_args *ta, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(ta->ta_handle != NULL); ta->ta_err = dt_declare_destroy(env, dt_obj, ta->ta_handle); if (ta->ta_err) return ta->ta_err; arg = tx_add_exec(ta, out_tx_destroy_exec, out_tx_destroy_undo, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->reply = reply; arg->index = index; return 0; }
static int __out_tx_index_insert(struct mdt_thread_info *info, struct dt_object *dt_obj, char *name, struct lu_fid *fid, struct thandle_exec_args *th, struct update_reply *reply, int index, char *file, int line) { struct tx_arg *arg; LASSERT(th->ta_handle != NULL); if (lu_object_exists(&dt_obj->do_lu)) { if (dt_try_as_dir(info->mti_env, dt_obj) == 0) { th->ta_err = -ENOTDIR; return th->ta_err; } th->ta_err = dt_declare_insert(info->mti_env, dt_obj, (struct dt_rec *)fid, (struct dt_key *)name, th->ta_handle); } if (th->ta_err != 0) return th->ta_err; arg = tx_add_exec(th, out_tx_index_insert_exec, out_tx_index_insert_undo, file, line); LASSERT(arg); lu_object_get(&dt_obj->do_lu); arg->object = dt_obj; arg->reply = reply; arg->index = index; arg->u.insert.rec = (struct dt_rec *)fid; arg->u.insert.key = (struct dt_key *)name; return 0; }
/* * Set up quota directory (either "quota_master" or "quota_slave") for a QMT or * QSD instance. This function is also used to create per-pool directory on * the quota master. * The directory is created with a local sequence if it does not exist already. * This function is called at ->ldo_prepare time when the full device stack is * configured. * * \param env - is the environment passed by the caller * \param dev - is the dt_device where to create the quota directory * \param parent - is the parent directory. If not specified, the directory * will be created under the root directory * \param name - is the name of quota directory to be created * * \retval - pointer to quota root dt_object on success, appropriate error * on failure */ struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env, struct dt_device *dev, struct dt_object *parent, const char *name) { struct lquota_thread_info *qti = lquota_info(env); struct dt_object *qt_dir = NULL; struct local_oid_storage *los = NULL; int rc; ENTRY; /* Set up local storage to create the quota directory. * We use the sequence reserved for local named objects */ lu_local_name_obj_fid(&qti->qti_fid, 1); rc = local_oid_storage_init(env, dev, &qti->qti_fid, &los); if (rc) RETURN(ERR_PTR(rc)); if (parent == NULL) { /* Fetch dt object associated with root directory */ rc = dt_root_get(env, dev, &qti->qti_fid); if (rc) GOTO(out, rc); parent = dt_locate_at(env, dev, &qti->qti_fid, dev->dd_lu_dev.ld_site->ls_top_dev, NULL); if (IS_ERR(parent)) GOTO(out, rc = PTR_ERR(parent)); } else { lu_object_get(&parent->do_lu); } /* create quota directory to be used for all quota index files */ qt_dir = local_file_find_or_create(env, los, parent, name, S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO); if (IS_ERR(qt_dir)) GOTO(out, rc = PTR_ERR(qt_dir)); /* local_oid_storage_fini() will finalize the local storage device, * we have to open the object in another device stack */ qti->qti_fid = qt_dir->do_lu.lo_header->loh_fid; lu_object_put_nocache(env, &qt_dir->do_lu); qt_dir = dt_locate(env, dev, &qti->qti_fid); if (IS_ERR(qt_dir)) GOTO(out, rc = PTR_ERR(qt_dir)); if (!dt_try_as_dir(env, qt_dir)) GOTO(out, rc = -ENOTDIR); EXIT; out: if (parent != NULL && !IS_ERR(parent)) lu_object_put(env, &parent->do_lu); if (los != NULL) local_oid_storage_fini(env, los); if (rc) { if (qt_dir != NULL && !IS_ERR(qt_dir)) lu_object_put(env, &qt_dir->do_lu); qt_dir = ERR_PTR(rc); } return qt_dir; }
static int llog_test_8(const struct lu_env *env, struct obd_device *obd) { struct llog_handle *llh = NULL; char name[10]; int rc, rc2, i; int orig_counter; struct llog_mini_rec lmr; struct llog_ctxt *ctxt; struct dt_object *obj = NULL; ENTRY; ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE; lmr.lmr_hdr.lrh_type = 0xf00f00; CWARN("8a: fill the first plain llog\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8a: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8a: can't init llog handle: %d\n", rc); GOTO(out, rc); } plain_counter = 0; rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0); if (rc != 0) { CERROR("5a: process with test_8_cb failed: %d\n", rc); GOTO(out, rc); } orig_counter = plain_counter; for (i = 0; i < 100; i++) { rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL); if (rc) { CERROR("5a: add record failed\n"); GOTO(out, rc); } } /* grab the current plain llog, we'll corrupt it later */ obj = llh->u.chd.chd_current_log->lgh_obj; LASSERT(obj); lu_object_get(&obj->do_lu); CWARN("8a: pin llog "DFID"\n", PFID(lu_object_fid(&obj->do_lu))); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8a: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; GOTO(out_put, rc); } CWARN("8b: fill the second plain llog\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8b: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8b: can't init llog handle: %d\n", rc); GOTO(out, rc); } for (i = 0; i < 100; i++) { rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL); if (rc) { CERROR("8b: add record failed\n"); GOTO(out, rc); } } CWARN("8b: second llog "DFID"\n", PFID(lu_object_fid(&llh->u.chd.chd_current_log->lgh_obj->do_lu))); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8b: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; GOTO(out_put, rc); } CWARN("8c: drop two records from the first plain llog\n"); llog_truncate(env, obj); CWARN("8d: count survived records\n"); rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS); if (rc) { CERROR("8d: llog_create with logid failed: %d\n", rc); GOTO(out_put, rc); } rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid); if (rc) { CERROR("8d: can't init llog handle: %d\n", rc); GOTO(out, rc); } plain_counter = 0; rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0); if (rc != 0) { CERROR("8d: process with test_8_cb failed: %d\n", rc); GOTO(out, rc); } if (orig_counter + 200 - 2 != plain_counter) { CERROR("found %d records (expected %d)\n", plain_counter, orig_counter + 200 - 2); rc = -EIO; } out: CWARN("8d: close re-opened catalog\n"); rc2 = llog_cat_close(env, llh); if (rc2) { CERROR("8d: close log %s failed: %d\n", name, rc2); if (rc == 0) rc = rc2; } out_put: llog_ctxt_put(ctxt); if (obj != NULL) lu_object_put(env, &obj->do_lu); RETURN(rc); }