Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/vos/vos_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,8 @@ struct vos_obj_iter {
daos_recx_t it_recx;
/** For fake akey, save the dkey krec as well */
struct vos_krec_df *it_dkey_krec;
/** Pin held for shared and dkey buckets during nested iteration */
struct umem_pin_handle *it_dkey_pin_hdl;
/** Store the fake akey */
char it_fake_akey;
};
Expand Down
67 changes: 62 additions & 5 deletions src/vos/vos_obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,21 +1010,59 @@ key_ilog_prepare(struct vos_obj_iter *oiter, daos_handle_t toh,
return rc;
}

/* Pin single dkey bucket while holding the object shared buckets, deadlock free. */
static inline int
dkey_bkt_iter_pin(struct vos_object *obj, struct vos_krec_df *krec,
struct umem_pin_handle **pin_hdl)
{
struct vos_pool *pool = vos_obj2pool(obj);
struct umem_store *store = vos_pool2store(pool);
struct umem_cache_range rg;
uint32_t bkt_id;
int rc;

D_ASSERT(*pin_hdl == NULL);
if (!vos_pool_is_evictable(pool) || !(krec->kr_bmap & KREC_BF_BKT_ID))
return 0;

bkt_id = *vos_krec2bkt_id(krec);
if (bkt_id == UMEM_DEFAULT_MBKT_ID)
return 0;

rg.cr_off = umem_get_mb_base_offset(vos_pool2umm(pool), vos_bkt_id_raw(bkt_id));
rg.cr_size = store->cache->ca_page_sz;
rc = vos_cache_pin(pool, &rg, 1, false, pin_hdl);
if (rc)
DL_ERROR(rc, "Failed to pin dkey bucket:%u for object:" DF_UOID ".", bkt_id,
DP_UOID(obj->obj_id));
return rc;
}

static inline int
key_ilog_prepare_dkey(struct vos_obj_iter *oiter, daos_key_t *key, daos_handle_t *sub_toh,
struct vos_krec_df **krecp, struct vos_ts_set *ts_set)
{
struct vos_object *obj = oiter->it_obj;
int flags = 0;
struct vos_object *obj = oiter->it_obj;
struct vos_krec_df *krec;
int rc, flags = 0;

if (vos_obj_skip_akey_supported(obj->obj_cont, obj->obj_id)) {
flags |= SUBTR_FLAT;
if (daos_is_array(obj->obj_id.id_pub))
flags |= SUBTR_EVT;
}

return key_ilog_prepare(oiter, obj->obj_toh, VOS_BTR_DKEY, key, flags, sub_toh, krecp,
&oiter->it_epr, &oiter->it_punched, &oiter->it_ilog_info, ts_set);
rc = key_ilog_prepare(oiter, obj->obj_toh, VOS_BTR_DKEY, key, flags, sub_toh, krecp,
&oiter->it_epr, &oiter->it_punched, &oiter->it_ilog_info, ts_set);
if (rc)
return rc;

krec = *krecp;
rc = dkey_bkt_iter_pin(obj, krec, &oiter->it_dkey_pin_hdl);
if (rc != 0)
key_tree_release(*sub_toh, key_tree_is_evt(flags, VOS_BTR_DKEY, krec));

return rc;
}

/**
Expand Down Expand Up @@ -1168,6 +1206,7 @@ key_iter_fetch_root(struct vos_obj_iter *oiter, vos_iter_type_t type,
}

krec = rbund.rb_krec;
info->ii_dkey_krec = krec;
info->ii_vea_info = obj->obj_cont->vc_pool->vp_vea_info;
info->ii_uma = vos_obj2uma(obj);

Expand Down Expand Up @@ -1226,7 +1265,6 @@ key_iter_fetch_root(struct vos_obj_iter *oiter, vos_iter_type_t type,
info->ii_fake_akey_flag = VOS_IT_DKEY_SV;
}
info->ii_ilog_info = &oiter->it_ilog_info;
info->ii_dkey_krec = krec;
}

return 0;
Expand Down Expand Up @@ -2174,8 +2212,21 @@ vos_obj_akey_iter_nested_prep(vos_iter_type_t type, struct vos_iter_info *info,
}

rc = nested_prep_common_init(obj->obj_cont, &oiter, info);
if (rc != 0) {
if (info->ii_fake_akey_flag)
key_tree_release(info->ii_tree_hdl,
info->ii_fake_akey_flag == VOS_IT_DKEY_EV);
return rc;
}

oiter->it_obj = obj;
rc = dkey_bkt_iter_pin(obj, info->ii_dkey_krec, &oiter->it_dkey_pin_hdl);
if (rc != 0) {
if (info->ii_fake_akey_flag)
key_tree_release(info->ii_tree_hdl,
info->ii_fake_akey_flag == VOS_IT_DKEY_EV);
goto failed;
}

if (info->ii_fake_akey_flag) {
/** In this case, we already opened the subtree so just store it
Expand Down Expand Up @@ -2213,6 +2264,8 @@ vos_obj_akey_iter_nested_prep(vos_iter_type_t type, struct vos_iter_info *info,
return 0;

failed:
if (oiter->it_dkey_pin_hdl != NULL)
umem_cache_unpin(vos_pool2store(vos_obj2pool(obj)), oiter->it_dkey_pin_hdl);
nested_prep_common_abort(oiter);
return rc;
}
Expand Down Expand Up @@ -2374,6 +2427,10 @@ vos_obj_iter_fini(struct vos_iterator *iter)
break;
}
out:
if (oiter->it_dkey_pin_hdl != NULL)
umem_cache_unpin(vos_pool2store(vos_obj2pool(oiter->it_obj)),
oiter->it_dkey_pin_hdl);

/* Release the object only if we didn't borrow it from the parent
* iterator. The generic code reference counts the iterators
* to ensure that a parent never gets removed before all nested
Expand Down
1 change: 1 addition & 0 deletions src/vos/vos_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct vos_obj_bkt_node {
uint8_t bn_bkt_cnt; /* valid entries in bn_bkt_ids[] */
uint8_t bn_flags;
uint16_t bn_pad;
void *bn_next;
};

/**
Expand Down
56 changes: 44 additions & 12 deletions src/vos/vos_obj_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -324,18 +324,53 @@ obj_allot_bkt(struct vos_pool *pool, struct vos_object *obj)
ABT_mutex_unlock(obj->obj_mutex);
}

/* Get all object shared buckets from in-memory vos_object */
static int
obj_shared_bkts(struct vos_pool *pool, struct vos_object *obj, struct vos_bkt_array *bkts)
{
struct vos_obj_bkt_node *node, *next = NULL;
int i, rc;

if (obj->obj_bkt_id0 != UMEM_DEFAULT_MBKT_ID) {
D_ASSERT(vos_bkt_id_is_shared(obj->obj_bkt_id0));
rc = vos_bkt_array_add(bkts, vos_bkt_id_raw(obj->obj_bkt_id0));
if (rc != 0)
return rc;
}

next = obj->obj_bkt_nodes;
while (next != NULL) {
node = next;
for (i = 0; i < node->bn_bkt_cnt; i++) {
D_ASSERT(node->bn_bkt_ids[i] != UMEM_DEFAULT_MBKT_ID);
if (!vos_bkt_id_is_shared(node->bn_bkt_ids[i]))
continue;
rc = vos_bkt_array_add(bkts, vos_bkt_id_raw(node->bn_bkt_ids[i]));
if (rc != 0)
return rc;
}
next = node->bn_next;
}
return 0;
}

static int
obj_pin_bkt(struct vos_pool *pool, struct vos_object *obj)
{
struct umem_store *store = vos_pool2store(pool);
struct dtx_handle *cur_dth;
struct umem_cache_range rg;
struct vos_bkt_array bkts;
int rc;

if (obj->obj_bkt_id0 == UMEM_DEFAULT_MBKT_ID) {
vos_bkt_array_init(&bkts);
rc = obj_shared_bkts(pool, obj, &bkts);
if (rc)
goto out;

if (bkts.vba_cnt == 0) {
D_ASSERT(obj->obj_pin_hdl == NULL);
D_ASSERT(!obj->obj_bkt_loading);
return 0;
goto out;
}

if (obj->obj_bkt_loading) {
Expand All @@ -349,7 +384,8 @@ obj_pin_bkt(struct vos_pool *pool, struct vos_object *obj)
/* The loader failed on vos_cache_pin() */
if (obj->obj_pin_hdl == NULL) {
D_ERROR("Object:"DF_UOID" isn't pinned.\n", DP_UOID(obj->obj_id));
return -DER_BUSY;
rc = -DER_BUSY;
goto out;
}
}

Expand All @@ -358,15 +394,11 @@ obj_pin_bkt(struct vos_pool *pool, struct vos_object *obj)

if (vcm)
d_tm_inc_counter(vcm->vcm_obj_hit, 1);
return 0;
goto out;
}

obj->obj_bkt_loading = 1;

rg.cr_off = umem_get_mb_base_offset(vos_pool2umm(pool), obj->obj_bkt_id0);
rg.cr_size = store->cache->ca_page_sz;

rc = vos_cache_pin(pool, &rg, 1, false, &obj->obj_pin_hdl);
rc = vos_bkt_array_pin(pool, &bkts, &obj->obj_pin_hdl);
if (rc)
DL_ERROR(rc, "Failed to pin object:"DF_UOID".", DP_UOID(obj->obj_id));

Expand All @@ -375,11 +407,11 @@ obj_pin_bkt(struct vos_pool *pool, struct vos_object *obj)
ABT_mutex_lock(obj->obj_mutex);
ABT_cond_broadcast(obj->obj_wait_loading);
ABT_mutex_unlock(obj->obj_mutex);

out:
vos_bkt_array_fini(&bkts);
return rc;
}

/* Support single evict-able bucket for this moment */
static inline int
vos_obj_pin(struct vos_object *obj)
{
Expand Down
Loading