int orph_declare_index_delete(const struct lu_env *env, struct mdd_object *obj, struct thandle *th) { struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); struct dt_key *key; int rc; key = orph_key_fill(env, mdo2fid(obj), ORPH_OP_UNLINK); rc = dt_declare_delete(env, mdd->mdd_orphans, key, th); if (rc) return rc; rc = mdo_declare_ref_del(env, obj, th); if (rc) return rc; if (S_ISDIR(mdd_object_type(obj))) { rc = mdo_declare_ref_del(env, obj, th); if (rc) return rc; rc = dt_declare_ref_del(env, mdd->mdd_orphans, th); } return rc; }
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; }
/* * Reserve enough credits to 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 where quota settings are stored. * \param id - is the key to be updated * * \retval - 0 on success, appropriate error on failure */ int lquota_disk_declare_write(const struct lu_env *env, struct thandle *th, struct dt_object *obj, union lquota_id *id) { 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); /* speculative delete declaration in case there is already an existing * record in the index */ rc = dt_declare_delete(env, obj, key, th); if (rc) RETURN(rc); /* declare insertion of updated record */ rc = dt_declare_insert(env, obj, (struct dt_rec *)&qti->qti_rec, key, th); if (rc) RETURN(rc); /* we might have to update the version of the global index too */ rc = dt_declare_version_set(env, obj, th); RETURN(rc); }
int mdd_orphan_declare_delete(const struct lu_env *env, struct mdd_object *obj, struct thandle *th) { struct mdd_device *mdd = mdo2mdd(&obj->mod_obj); struct dt_key *key; int rc; key = mdd_orphan_key_fill(env, mdo2fid(obj)); rc = dt_declare_delete(env, mdd->mdd_orphans, key, th); if (rc) return rc; if (!mdd_object_exists(obj)) return -ENOENT; rc = mdo_declare_ref_del(env, obj, th); if (rc) return rc; if (S_ISDIR(mdd_object_type(obj))) { rc = mdo_declare_ref_del(env, obj, th); if (rc) return rc; rc = dt_declare_ref_del(env, mdd->mdd_orphans, th); } return rc; }
static int lfsck_namespace_delete(const struct lu_env *env, struct lfsck_component *com, const struct lu_fid *fid) { 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; ENTRY; 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); rc = dt_trans_start_local(env, lfsck->li_bottom, handle); if (rc != 0) GOTO(out, rc); fid_cpu_to_be(key, fid); rc = dt_delete(env, obj, (const struct dt_key *)key, handle, BYPASS_CAPA); GOTO(out, rc); out: dt_trans_stop(env, lfsck->li_bottom, handle); 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); }
/* * To enable DNE functionality we need FID of /ROOT directory * (which is / as seen by the clients) to belong to MDT0 and * not to FID_SEQ_LOCAL_FILE or some other local sequence, * which can be used by any node, so can't be part of FLDB. * * Pre-production code was using FID_SEQ_LOCAL_FILE for /ROOT * making few existing setups incompatibile with DNE. This * applies to ZFS-based setups only as ldiskfs-based setups * are still using IGIF to identify /ROOT. * * The intention of this code is to fix on-disk state to use * FID_SEQ_ROOT for /ROOT: * - "." and ".." references in /ROOT itself and it`s subdirectories * - LinkEA in all the objects listed in /ROOT * * Given only ZFS is affected where "." and ".." are not stored, we need to: * - delete "." and ".." from /ROOT and its subdirectories * - rename references in LinkEA in all the objects listed in /ROOT * * This code is subject for removal in 2.5 */ static int mdd_convert_remove_dots(const struct lu_env *env, struct mdd_device *mdd, struct mdd_object *o) { struct thandle *th; const struct dt_key *dot = (const struct dt_key *)"."; const struct dt_key *dotdot = (const struct dt_key *)".."; int rc; if (dt_try_as_dir(env, mdd_object_child(o)) == 0) RETURN(-ENOTDIR); /* remove "."/".." and do not insert them back - not stored in ZFS */ th = dt_trans_create(env, mdd->mdd_child); if (IS_ERR(th)) RETURN(PTR_ERR(th)); rc = dt_declare_delete(env, mdd_object_child(o), dot, th); if (rc) GOTO(out, rc); rc = dt_declare_delete(env, mdd_object_child(o), dotdot, th); if (rc) GOTO(out, rc); rc = dt_trans_start_local(env, mdd->mdd_child, th); if (rc) GOTO(out, rc); /* ignore non-existing "."/".." - we stored them on disk for * pre-production systems, but this is not how regular ZFS works */ rc = dt_delete(env, mdd_object_child(o), dot, th, BYPASS_CAPA); if (rc == -ENOENT) rc = 0; if (rc) GOTO(out, rc); rc = dt_delete(env, mdd_object_child(o), dotdot, th, BYPASS_CAPA); if (rc == -ENOENT) rc = 0; if (rc) GOTO(out, rc); out: dt_trans_stop(env, mdd->mdd_child, th); RETURN(rc); }
int fld_declare_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 *tmp; struct lu_seq_range *range; struct fld_thread_info *info; int rc = 0; ENTRY; info = lu_context_key_get(&env->le_ctx, &fld_thread_key); range = &info->fti_lrange; tmp = &info->fti_irange; memset(range, 0, sizeof(*range)); rc = fld_index_lookup(env, fld, new_range->lsr_start, range); if (rc == 0) { /* In case of duplicate entry, the location must be same */ LASSERT((range_compare_loc(new_range, range) == 0)); GOTO(out, rc = -EEXIST); } if (rc != -ENOENT) { CERROR("%s: lookup range "DRANGE" error: rc = %d\n", fld->lsf_name, PRANGE(range), rc); GOTO(out, rc); } /* Check for merge case, since the fld entry can only be increamental, * so we will only check whether it can be merged from the left. */ 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_declare_delete(env, fld->lsf_obj, (struct dt_key *)&tmp->lsr_start, th); if (rc) { CERROR("%s: declare record "DRANGE" failed: rc = %d\n", fld->lsf_name, PRANGE(range), rc); GOTO(out, rc); } memcpy(tmp, new_range, sizeof(*new_range)); tmp->lsr_start = range->lsr_start; } else { memcpy(tmp, new_range, sizeof(*new_range)); } range_cpu_to_be(tmp, tmp); rc = dt_declare_insert(env, fld->lsf_obj, (struct dt_rec *)tmp, (struct dt_key *)&tmp->lsr_start, th); out: RETURN(rc); }
/** * Implementation of the llog_operations::lop_destroy * * This function destroys the llog and deletes also entry in the * llog directory in case of named llog. Llog should be opened prior that. * Destroy method is not part of external transaction and does everything * inside. * * \param[in] env execution environment * \param[in] loghandle llog handle of the current llog * * \retval 0 on successful destroy * \retval negative value on error */ static int llog_osd_destroy(const struct lu_env *env, struct llog_handle *loghandle) { struct llog_ctxt *ctxt; struct dt_object *o, *llog_dir = NULL; struct dt_device *d; struct thandle *th; char *name = NULL; int rc; ENTRY; ctxt = loghandle->lgh_ctxt; LASSERT(ctxt); o = loghandle->lgh_obj; LASSERT(o); d = lu2dt_dev(o->do_lu.lo_dev); LASSERT(d); LASSERT(d == ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt); th = dt_trans_create(env, d); if (IS_ERR(th)) RETURN(PTR_ERR(th)); if (loghandle->lgh_name) { llog_dir = llog_osd_dir_get(env, ctxt); if (IS_ERR(llog_dir)) GOTO(out_trans, rc = PTR_ERR(llog_dir)); name = loghandle->lgh_name; rc = dt_declare_delete(env, llog_dir, (struct dt_key *)name, th); if (rc) GOTO(out_trans, rc); } dt_declare_ref_del(env, o, th); rc = dt_declare_destroy(env, o, th); if (rc) GOTO(out_trans, rc); rc = dt_trans_start_local(env, d, th); if (rc) GOTO(out_trans, rc); dt_write_lock(env, o, 0); if (dt_object_exists(o)) { if (name) { dt_read_lock(env, llog_dir, 0); rc = dt_delete(env, llog_dir, (struct dt_key *) name, th, BYPASS_CAPA); dt_read_unlock(env, llog_dir); if (rc) { CERROR("%s: can't remove llog %s: rc = %d\n", o->do_lu.lo_dev->ld_obd->obd_name, name, rc); GOTO(out_unlock, rc); } } dt_ref_del(env, o, th); rc = dt_destroy(env, o, th); if (rc) GOTO(out_unlock, rc); } out_unlock: dt_write_unlock(env, o); out_trans: dt_trans_stop(env, d, th); if (llog_dir != NULL) lu_object_put(env, &llog_dir->do_lu); RETURN(rc); }
static int llog_osd_destroy(const struct lu_env *env, struct llog_handle *loghandle) { struct llog_thread_info *lgi = llog_info(env); struct llog_ctxt *ctxt; struct dt_object *o, *llog_dir = NULL; struct dt_device *d; struct thandle *th; char *name = NULL; int rc; ENTRY; ctxt = loghandle->lgh_ctxt; LASSERT(ctxt); o = loghandle->lgh_obj; LASSERT(o); d = lu2dt_dev(o->do_lu.lo_dev); LASSERT(d); LASSERT(d == ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt); th = dt_trans_create(env, d); if (IS_ERR(th)) RETURN(PTR_ERR(th)); if (loghandle->lgh_name) { llog_dir = llog_osd_dir_get(env, ctxt); if (IS_ERR(llog_dir)) GOTO(out_trans, rc = PTR_ERR(llog_dir)); dt_declare_ref_del(env, o, th); name = loghandle->lgh_name; rc = dt_declare_delete(env, llog_dir, (struct dt_key *)name, th); if (rc) GOTO(out_trans, rc); } dt_declare_ref_del(env, o, th); rc = dt_declare_destroy(env, o, th); if (rc) GOTO(out_trans, rc); rc = dt_trans_start_local(env, d, th); if (rc) GOTO(out_trans, rc); dt_write_lock(env, o, 0); if (dt_object_exists(o)) { if (name) { dt_ref_del(env, o, th); dt_read_lock(env, llog_dir, 0); rc = dt_delete(env, llog_dir, (struct dt_key *) name, th, BYPASS_CAPA); dt_read_unlock(env, llog_dir); if (rc) { CERROR("%s: can't remove llog %s: rc = %d\n", o->do_lu.lo_dev->ld_obd->obd_name, name, rc); GOTO(out_unlock, rc); } } /* * XXX: compatibility bits * on old filesystems llogs are referenced by the name * on the new ones they are referenced by OI and by * the name */ rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL); if (rc) GOTO(out_unlock, rc); LASSERT(lgi->lgi_attr.la_nlink < 2); if (lgi->lgi_attr.la_nlink == 1) dt_ref_del(env, o, th); rc = dt_destroy(env, o, th); if (rc) GOTO(out_unlock, rc); } out_unlock: dt_write_unlock(env, o); out_trans: dt_trans_stop(env, d, th); if (llog_dir != NULL) lu_object_put(env, &llog_dir->do_lu); 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; }