static int out_tx_index_insert_exec(struct mdt_thread_info *info, struct thandle *th, struct tx_arg *arg) { struct dt_object *dt_obj = arg->object; int rc; LASSERT(dt_obj != NULL && !IS_ERR(dt_obj)); CDEBUG(D_OTHER, "index insert "DFID" name: %s fid "DFID"\n", PFID(lu_object_fid(&arg->object->do_lu)), (char *)arg->u.insert.key, PFID((struct lu_fid *)arg->u.insert.rec)); if (dt_try_as_dir(info->mti_env, dt_obj) == 0) return -ENOTDIR; dt_write_lock(info->mti_env, dt_obj, MOR_TGT_CHILD); rc = dt_insert(info->mti_env, dt_obj, arg->u.insert.rec, arg->u.insert.key, th, NULL, 0); dt_write_unlock(info->mti_env, dt_obj); update_insert_reply(arg->reply, NULL, 0, arg->index, rc); return rc; }
/* * Write a global record * * \param env - is the environment passed by the caller * \param obj - is the on-disk global index to be updated * \param id - index to be updated * \param rec - record to be written */ int lquota_disk_write_glb(const struct lu_env *env, struct dt_object *obj, __u64 id, struct lquota_glb_rec *rec) { struct dt_device *dev = lu2dt_dev(obj->do_lu.lo_dev); struct thandle *th; struct dt_key *key = (struct dt_key *)&id; int rc; ENTRY; th = dt_trans_create(env, dev); if (IS_ERR(th)) RETURN(PTR_ERR(th)); /* the entry with 0 key can always be found in IAM file. */ if (id == 0) { rc = dt_declare_delete(env, obj, key, th); if (rc) GOTO(out, rc); } rc = dt_declare_insert(env, obj, (struct dt_rec *)rec, key, th); if (rc) GOTO(out, rc); rc = dt_trans_start_local(env, dev, th); if (rc) GOTO(out, rc); dt_write_lock(env, obj, 0); if (id == 0) { struct lquota_glb_rec *tmp; OBD_ALLOC_PTR(tmp); if (tmp == NULL) GOTO(out_lock, rc = -ENOMEM); rc = dt_lookup(env, obj, (struct dt_rec *)tmp, key, BYPASS_CAPA); OBD_FREE_PTR(tmp); if (rc == 0) { rc = dt_delete(env, obj, key, th, BYPASS_CAPA); if (rc) GOTO(out_lock, rc); } rc = 0; } rc = dt_insert(env, obj, (struct dt_rec *)rec, key, th, BYPASS_CAPA, 1); out_lock: dt_write_unlock(env, obj); out: dt_trans_stop(env, dev, th); RETURN(rc); }
/** * Implementation of the llog_operations::lop_create * * This function creates the llog according with llog_handle::lgh_obj * and llog_handle::lgh_name. * * \param[in] env execution environment * \param[in] res llog handle of the current llog * \param[in] th current transaction handle * * \retval 0 on successful create * \retval negative value on error */ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res, struct thandle *th) { struct llog_thread_info *lgi = llog_info(env); struct dt_insert_rec *rec = &lgi->lgi_dt_rec; struct local_oid_storage *los; struct dt_object *o; int rc = 0; ENTRY; LASSERT(env); o = res->lgh_obj; LASSERT(o); /* llog can be already created */ if (dt_object_exists(o)) RETURN(-EEXIST); los = res->private_data; LASSERT(los); dt_write_lock(env, o, 0); if (!dt_object_exists(o)) rc = llog_osd_create_new_object(env, los, o, th); else rc = -EEXIST; dt_write_unlock(env, o); if (rc) RETURN(rc); if (res->lgh_name) { struct dt_object *llog_dir; llog_dir = llog_osd_dir_get(env, res->lgh_ctxt); if (IS_ERR(llog_dir)) RETURN(PTR_ERR(llog_dir)); logid_to_fid(&res->lgh_id, &lgi->lgi_fid); rec->rec_fid = &lgi->lgi_fid; rec->rec_type = S_IFREG; dt_read_lock(env, llog_dir, 0); rc = dt_insert(env, llog_dir, (struct dt_rec *)rec, (struct dt_key *)res->lgh_name, th, BYPASS_CAPA, 1); dt_read_unlock(env, llog_dir); lu_object_put(env, &llog_dir->do_lu); if (rc) CERROR("%s: can't create named llog %s: rc = %d\n", o->do_lu.lo_dev->ld_obd->obd_name, res->lgh_name, rc); } RETURN(rc); }
/** * Builds a d-tree using database entries. * \return negative on failure, postive on success, indicating the number of d-tree entries */ int db_build_userbl_tree(const str *username, const str *domain, const str *table, struct dt_node_t *root, int use_domain) { db_key_t columns[2] = { &prefix_col, &whitelist_col }; db_key_t key[2] = { &username_key, &domain_key }; db_val_t val[2]; VAL_TYPE(val) = VAL_TYPE(val + 1) = DB_STR; VAL_NULL(val) = VAL_NULL(val + 1) = 0; VAL_STR(val).s = username->s; VAL_STR(val).len = username->len; VAL_STR(val + 1).s = domain->s; VAL_STR(val + 1).len = domain->len; db_res_t *res; int i; int n = 0; if (dbf.use_table(dbc, table) < 0) { LM_ERR("cannot use table '%.*s'.\n", table->len, table->s); return -1; } if (dbf.query(dbc, key, 0, val, columns, (!use_domain) ? (1) : (2), 2, 0, &res) < 0) { LM_ERR("error while executing query.\n"); return -1; } dt_clear(root); if (RES_COL_N(res) > 1) { for(i = 0; i < RES_ROW_N(res); i++) { if ((!RES_ROWS(res)[i].values[0].nul) && (!RES_ROWS(res)[i].values[1].nul)) { if ((RES_ROWS(res)[i].values[0].type == DB_STRING) && (RES_ROWS(res)[i].values[1].type == DB_INT)) { /* LM_DBG("insert into tree prefix %s, whitelist %d", RES_ROWS(res)[i].values[0].val.string_val, RES_ROWS(res)[i].values[1].val.int_val); */ dt_insert(root, RES_ROWS(res)[i].values[0].val.string_val, RES_ROWS(res)[i].values[1].val.int_val); n++; } else { LM_ERR("got invalid result type from query.\n"); } } } } dbf.free_result(dbc, res); return n; }
static inline int mdd_orphan_insert_obj(const struct lu_env *env, struct mdd_device *mdd, struct mdd_object *obj, __u32 op, struct thandle *th) { struct dt_insert_rec *rec = &mdd_env_info(env)->mti_dt_rec; struct dt_object *dor = mdd->mdd_orphans; const struct lu_fid *lf = mdo2fid(obj); struct dt_key *key = orph_key_fill(env, lf, op); rec->rec_fid = lf; rec->rec_type = mdd_object_type(obj); return dt_insert(env, dor, (const struct dt_rec *)rec, key, th, 1); }
static int orph_index_insert(const struct lu_env *env, struct mdd_object *obj, __u32 op, struct thandle *th) { struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); struct dt_object *dor = mdd->mdd_orphans; const struct lu_fid *lf_dor = lu_object_fid(&dor->do_lu); struct dt_object *next = mdd_object_child(obj); struct dt_insert_rec *rec = &mdd_env_info(env)->mti_dt_rec; int rc; ENTRY; LASSERT(mdd_write_locked(env, obj) != 0); LASSERT(!(obj->mod_flags & ORPHAN_OBJ)); mdd_orphan_write_lock(env, mdd); rc = mdd_orphan_insert_obj(env, mdd, obj, op, th); if (rc) GOTO(out, rc); mdo_ref_add(env, obj, th); if (!S_ISDIR(mdd_object_type(obj))) GOTO(out, rc = 0); mdo_ref_add(env, obj, th); mdd_orphan_ref_add(env, mdd, th); /* try best to fixup directory, dont return errors * from here */ if (!dt_try_as_dir(env, next)) GOTO(out, rc = 0); dt_delete(env, next, (const struct dt_key *)dotdot, th); rec->rec_fid = lf_dor; rec->rec_type = S_IFDIR; dt_insert(env, next, (const struct dt_rec *)rec, (const struct dt_key *)dotdot, th, 1); out: if (rc == 0) obj->mod_flags |= ORPHAN_OBJ; mdd_orphan_write_unlock(env, mdd); RETURN(rc); }
/** * Rebuild d-tree using database entries * \return negative on failure, positive on success, indicating the number of d-tree entries */ int db_reload_source(const str *table, struct dt_node_t *root) { db_key_t columns[2] = { &prefix_col, &whitelist_col }; db_res_t *res; int i; int n = 0; if (dbf.use_table(dbc, table) < 0) { LM_ERR("cannot use table '%.*s'.\n", table->len, table->s); return -1; } if (dbf.query(dbc, NULL, NULL, NULL, columns, 0, 2, NULL, &res) < 0) { LM_ERR("error while executing query.\n"); return -1; } dt_clear(root); if (RES_COL_N(res) > 1) { for(i = 0; i < RES_ROW_N(res); i++) { if ((!RES_ROWS(res)[i].values[0].nul) && (!RES_ROWS(res)[i].values[1].nul)) { if ((RES_ROWS(res)[i].values[0].type == DB_STRING) && (RES_ROWS(res)[i].values[1].type == DB_INT)) { /* LM_DBG("insert into tree prefix %s, whitelist %d", RES_ROWS(res)[i].values[0].val.string_val, RES_ROWS(res)[i].values[1].val.int_val); */ dt_insert(root, RES_ROWS(res)[i].values[0].val.string_val, RES_ROWS(res)[i].values[1].val.int_val); n++; } else { LM_ERR("got invalid result type from query.\n"); } } } } dbf.free_result(dbc, res); return n; }
static int out_obj_index_insert(const struct lu_env *env, struct dt_object *dt_obj, const struct dt_rec *rec, const struct dt_key *key, struct thandle *th) { int rc; CDEBUG(D_INFO, "%s: index insert "DFID" name: %s fid "DFID"\n", dt_obd_name(th->th_dev), PFID(lu_object_fid(&dt_obj->do_lu)), (char *)key, PFID((struct lu_fid *)rec)); if (dt_try_as_dir(env, dt_obj) == 0) return -ENOTDIR; dt_write_lock(env, dt_obj, MOR_TGT_CHILD); rc = dt_insert(env, dt_obj, rec, key, th, NULL, 0); dt_write_unlock(env, dt_obj); return rc; }
/* * Update a record in a quota index file. * * \param env - is the environment passed by the caller * \param th - is the transaction to use for disk writes * \param obj - is the on-disk index to be updated. * \param id - is the key to be updated * \param rec - is the input record containing the new quota settings. * \param flags - can be LQUOTA_BUMP_VER or LQUOTA_SET_VER. * \param ver - is the new version of the index if LQUOTA_SET_VER is set or is * used to return the new version of the index when * LQUOTA_BUMP_VER is set. * * \retval - 0 on success, appropriate error on failure */ int lquota_disk_write(const struct lu_env *env, struct thandle *th, struct dt_object *obj, union lquota_id *id, struct dt_rec *rec, __u32 flags, __u64 *ver) { struct lquota_thread_info *qti = lquota_info(env); struct dt_key *key = (struct dt_key *)&id->qid_uid; int rc; ENTRY; LASSERT(dt_object_exists(obj)); LASSERT(obj->do_index_ops != NULL); /* lock index */ dt_write_lock(env, obj, 0); /* check whether there is already an existing record for this ID */ rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_rec, key, BYPASS_CAPA); if (rc == 0) { /* delete existing record in order to replace it */ rc = dt_delete(env, obj, key, th, BYPASS_CAPA); if (rc) GOTO(out, rc); } else if (rc == -ENOENT) { /* probably first insert */ rc = 0; } else { GOTO(out, rc); } if (rec != NULL) { /* insert record with updated quota settings */ rc = dt_insert(env, obj, rec, key, th, BYPASS_CAPA, 1); if (rc) { /* try to insert the old one */ rc = dt_insert(env, obj, (struct dt_rec *)&qti->qti_rec, key, th, BYPASS_CAPA, 1); LASSERTF(rc == 0, "failed to insert record in quota " "index "DFID, PFID(lu_object_fid(&obj->do_lu))); GOTO(out, rc); } } if (flags != 0) { LASSERT(ver); if (flags & LQUOTA_BUMP_VER) { /* caller wants to bump the version, let's first read * it */ *ver = dt_version_get(env, obj); (*ver)++; } else { LASSERT(flags & LQUOTA_SET_VER); } dt_version_set(env, obj, *ver, th); } EXIT; out: dt_write_unlock(env, obj); return rc; }
/** * insert range in fld store. * * \param range range to be inserted * \param th transaction for this operation as it could compound * transaction. * * \retval 0 success * \retval -ve error * * The whole fld index insertion is protected by seq->lss_mutex (see * seq_server_alloc_super), i.e. only one thread will access fldb each * time, so we do not need worry the fld file and cache will being * changed between declare and create. * Because the fld entry can only be increamental, so we will only check * whether it can be merged from the left. **/ int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld, const struct lu_seq_range *new_range, struct thandle *th) { struct lu_seq_range *range; struct lu_seq_range *tmp; struct fld_thread_info *info; int rc = 0; int deleted = 0; struct fld_cache_entry *flde; ENTRY; info = lu_context_key_get(&env->le_ctx, &fld_thread_key); LASSERT_MUTEX_LOCKED(&fld->lsf_lock); range = &info->fti_lrange; memset(range, 0, sizeof(*range)); tmp = &info->fti_irange; rc = fld_index_lookup(env, fld, new_range->lsr_start, range); if (rc != -ENOENT) { rc = rc == 0 ? -EEXIST : rc; GOTO(out, rc); } if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 && range_compare_loc(new_range, range) == 0) { range_cpu_to_be(tmp, range); rc = dt_delete(env, fld->lsf_obj, (struct dt_key *)&tmp->lsr_start, th, BYPASS_CAPA); if (rc != 0) GOTO(out, rc); memcpy(tmp, new_range, sizeof(*new_range)); tmp->lsr_start = range->lsr_start; deleted = 1; } else { memcpy(tmp, new_range, sizeof(*new_range)); } range_cpu_to_be(tmp, tmp); rc = dt_insert(env, fld->lsf_obj, (struct dt_rec *)tmp, (struct dt_key *)&tmp->lsr_start, th, BYPASS_CAPA, 1); if (rc != 0) { CERROR("%s: insert range "DRANGE" failed: rc = %d\n", fld->lsf_name, PRANGE(new_range), rc); GOTO(out, rc); } flde = fld_cache_entry_create(new_range); if (IS_ERR(flde)) GOTO(out, rc = PTR_ERR(flde)); write_lock(&fld->lsf_cache->fci_lock); if (deleted) fld_cache_delete_nolock(fld->lsf_cache, new_range); rc = fld_cache_insert_nolock(fld->lsf_cache, flde); write_unlock(&fld->lsf_cache->fci_lock); if (rc) OBD_FREE_PTR(flde); out: RETURN(rc); }
static int lfsck_namespace_update(const struct lu_env *env, struct lfsck_component *com, const struct lu_fid *fid, __u8 flags, bool force) { struct lfsck_instance *lfsck = com->lc_lfsck; struct lu_fid *key = &lfsck_env_info(env)->lti_fid; struct thandle *handle; struct dt_object *obj = com->lc_obj; int rc; bool exist = false; __u8 tf; ENTRY; rc = lfsck_namespace_lookup(env, com, fid, &tf); if (rc != 0 && rc != -ENOENT) RETURN(rc); if (rc == 0) { if (!force || flags == tf) RETURN(0); exist = true; handle = dt_trans_create(env, lfsck->li_bottom); if (IS_ERR(handle)) RETURN(PTR_ERR(handle)); rc = dt_declare_delete(env, obj, (const struct dt_key *)fid, handle); if (rc != 0) GOTO(out, rc); } else { handle = dt_trans_create(env, lfsck->li_bottom); if (IS_ERR(handle)) RETURN(PTR_ERR(handle)); } rc = dt_declare_insert(env, obj, (const struct dt_rec *)&flags, (const struct dt_key *)fid, handle); if (rc != 0) GOTO(out, rc); rc = dt_trans_start_local(env, lfsck->li_bottom, handle); if (rc != 0) GOTO(out, rc); fid_cpu_to_be(key, fid); if (exist) { rc = dt_delete(env, obj, (const struct dt_key *)key, handle, BYPASS_CAPA); if (rc != 0) { CERROR("%s: fail to insert "DFID": rc = %d\n", lfsck_lfsck2name(com->lc_lfsck), PFID(fid), rc); GOTO(out, rc); } } rc = dt_insert(env, obj, (const struct dt_rec *)&flags, (const struct dt_key *)key, handle, BYPASS_CAPA, 1); GOTO(out, rc); out: dt_trans_stop(env, lfsck->li_bottom, handle); return rc; }