/* * Look-up a slave index file. * * \param env - is the environment passed by the caller * \param dev - is the backend dt_device where to look-up/create the slave index * \param parent - is the parent directory where to lookup the slave index * \param glb_fid - is the fid of the global index file associated with this * slave index. * \param uuid - is the uuid of slave which is (re)connecting to the master * target * * \retval - pointer to the dt_object of the slave index on success, * appropriate error on failure */ struct dt_object *lquota_disk_slv_find(const struct lu_env *env, struct dt_device *dev, struct dt_object *parent, const struct lu_fid *glb_fid, struct obd_uuid *uuid) { struct lquota_thread_info *qti = lquota_info(env); struct dt_object *slv_idx; int rc; ENTRY; LASSERT(uuid != NULL); CDEBUG(D_QUOTA, "lookup slave index file for %s\n", obd_uuid2str(uuid)); /* generate filename associated with the slave */ rc = lquota_disk_slv_filename(glb_fid, uuid, qti->qti_buf); if (rc) RETURN(ERR_PTR(rc)); /* lookup slave index file */ rc = dt_lookup_dir(env, parent, qti->qti_buf, &qti->qti_fid); if (rc) RETURN(ERR_PTR(rc)); /* name is found, get the object */ slv_idx = dt_locate(env, dev, &qti->qti_fid); if (IS_ERR(slv_idx)) RETURN(slv_idx); if (slv_idx->do_index_ops == NULL) { rc = slv_idx->do_ops->do_index_try(env, slv_idx, &dt_quota_slv_features); if (rc) { CERROR("%s: failed to setup slave index operations for " "%s, rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name, obd_uuid2str(uuid), rc); lu_object_put(env, &slv_idx->do_lu); slv_idx = ERR_PTR(rc); } } RETURN(slv_idx); }
/** * Implementation of the llog_operations::lop_open * * This function opens the llog by its logid or by name, it may open also * non existent llog and assing then new id to it. * The llog_open/llog_close pair works similar to lu_object_find/put, * the object may not exist prior open. The result of open is just dt_object * in the llog header. * * \param[in] env execution environment * \param[in] handle llog handle of the current llog * \param[in] logid logid of llog to open (nameless llog) * \param[in] name name of llog to open (named llog) * \param[in] open_param * LLOG_OPEN_NEW - new llog, may not exist * LLOG_OPEN_EXIST - old llog, must exist * * \retval 0 on successful open, llog_handle::lgh_obj * contains the dt_object of the llog. * \retval negative value on error */ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle, struct llog_logid *logid, char *name, enum llog_open_param open_param) { struct llog_thread_info *lgi = llog_info(env); struct llog_ctxt *ctxt = handle->lgh_ctxt; struct dt_object *o; struct dt_device *dt; struct ls_device *ls; struct local_oid_storage *los; int rc = 0; ENTRY; LASSERT(env); LASSERT(ctxt); LASSERT(ctxt->loc_exp); LASSERT(ctxt->loc_exp->exp_obd); dt = ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt; LASSERT(dt); ls = ls_device_get(dt); if (IS_ERR(ls)) RETURN(PTR_ERR(ls)); mutex_lock(&ls->ls_los_mutex); los = dt_los_find(ls, name != NULL ? FID_SEQ_LLOG_NAME : FID_SEQ_LLOG); mutex_unlock(&ls->ls_los_mutex); LASSERT(los); ls_device_put(env, ls); LASSERT(handle); if (logid != NULL) { logid_to_fid(logid, &lgi->lgi_fid); } else if (name) { struct dt_object *llog_dir; llog_dir = llog_osd_dir_get(env, ctxt); if (IS_ERR(llog_dir)) GOTO(out, rc = PTR_ERR(llog_dir)); dt_read_lock(env, llog_dir, 0); rc = dt_lookup_dir(env, llog_dir, name, &lgi->lgi_fid); dt_read_unlock(env, llog_dir); lu_object_put(env, &llog_dir->do_lu); if (rc == -ENOENT && open_param == LLOG_OPEN_NEW) { /* generate fid for new llog */ rc = local_object_fid_generate(env, los, &lgi->lgi_fid); } if (rc < 0) GOTO(out, rc); OBD_ALLOC(handle->lgh_name, strlen(name) + 1); if (handle->lgh_name) strcpy(handle->lgh_name, name); else GOTO(out, rc = -ENOMEM); } else { LASSERTF(open_param & LLOG_OPEN_NEW, "%#x\n", open_param); /* generate fid for new llog */ rc = local_object_fid_generate(env, los, &lgi->lgi_fid); if (rc < 0) GOTO(out, rc); } o = ls_locate(env, ls, &lgi->lgi_fid, NULL); if (IS_ERR(o)) GOTO(out_name, rc = PTR_ERR(o)); /* No new llog is expected but doesn't exist */ if (open_param != LLOG_OPEN_NEW && !dt_object_exists(o)) GOTO(out_put, rc = -ENOENT); fid_to_logid(&lgi->lgi_fid, &handle->lgh_id); handle->lgh_obj = o; handle->private_data = los; LASSERT(handle->lgh_ctxt); RETURN(rc); out_put: lu_object_put(env, &o->do_lu); out_name: if (handle->lgh_name != NULL) OBD_FREE(handle->lgh_name, strlen(name) + 1); out: dt_los_put(los); RETURN(rc); }
/* * Iterate over all slave index files associated with global index \glb_fid and * invoke a callback function for each slave index file. * * \param env - is the environment passed by the caller * \param parent - is the parent directory where the slave index files are * stored * \param glb_fid - is the fid of the global index file associated with the * slave indexes to scan * \param func - is the callback function to call each time a slave index * file is found * \param arg - is an opaq argument passed to the callback function \func */ int lquota_disk_for_each_slv(const struct lu_env *env, struct dt_object *parent, struct lu_fid *glb_fid, lquota_disk_slv_cb_t func, void *arg) { struct lquota_thread_info *qti = lquota_info(env); struct dt_it *it; const struct dt_it_ops *iops; char *name; int rc; ENTRY; OBD_ALLOC(name, LQUOTA_NAME_MAX); if (name == NULL) RETURN(-ENOMEM); /* filename associated with slave index files are prefixed with the most * signicant bits of the global FID */ sprintf(name, "0x%x-", glb_fid->f_oid); iops = &parent->do_index_ops->dio_it; it = iops->init(env, parent, 0, BYPASS_CAPA); if (IS_ERR(it)) { OBD_FREE(name, LQUOTA_NAME_MAX); RETURN(PTR_ERR(it)); } rc = iops->load(env, it, 0); if (rc == 0) { /* * Iterator didn't find record with exactly the key requested. * * It is currently either * * - positioned above record with key less than * requested---skip it. * * - or not positioned at all (is in IAM_IT_SKEWED * state)---position it on the next item. */ rc = iops->next(env, it); } else if (rc > 0) rc = 0; while (rc == 0) { struct dt_key *key; int len; len = iops->key_size(env, it); /* IAM iterator can return record with zero len. */ if (len == 0 || len <= strlen(name) || len >= LQUOTA_NAME_MAX) goto next; key = iops->key(env, it); if (IS_ERR(key)) { rc = PTR_ERR(key); break; } if (strncmp((char *)key, name, strlen(name)) != 0) goto next; /* ldiskfs OSD returns filename as stored in directory entry * which does not end up with '\0' */ memcpy(&qti->qti_buf, key, len); qti->qti_buf[len] = '\0'; /* lookup fid associated with this slave index file */ rc = dt_lookup_dir(env, parent, qti->qti_buf, &qti->qti_fid); if (rc) break; if (qti->qti_fid.f_seq != FID_SEQ_QUOTA) goto next; rc = func(env, glb_fid, (char *)key, &qti->qti_fid, arg); if (rc) break; next: do { rc = iops->next(env, it); } while (rc == -ESTALE); } iops->put(env, it); iops->fini(env, it); OBD_FREE(name, LQUOTA_NAME_MAX); if (rc > 0) rc = 0; RETURN(rc); }