int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, struct page *vmpage) { struct lov_object *loo = cl2lov(obj); struct lov_layout_raid0 *r0 = lov_r0(loo); struct lov_io *lio = lov_env_io(env); struct cl_page *subpage; struct cl_object *subobj; struct lov_io_sub *sub; struct lov_page *lpg = cl_object_page_slice(obj, page); loff_t offset; u64 suboff; int stripe; int rc; offset = cl_offset(obj, page->cp_index); stripe = lov_stripe_number(loo->lo_lsm, offset); LASSERT(stripe < r0->lo_nr); rc = lov_stripe_offset(loo->lo_lsm, offset, stripe, &suboff); LASSERT(rc == 0); lpg->lps_invalid = 1; cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_page_ops); sub = lov_sub_get(env, lio, stripe); if (IS_ERR(sub)) { rc = PTR_ERR(sub); goto out; } subobj = lovsub2cl(r0->lo_sub[stripe]); subpage = cl_page_find_sub(sub->sub_env, subobj, cl_index(subobj, suboff), vmpage, page); lov_sub_put(sub); if (IS_ERR(subpage)) { rc = PTR_ERR(subpage); goto out; } if (likely(subpage->cp_parent == page)) { lu_ref_add(&subpage->cp_reference, "lov", page); lpg->lps_invalid = 0; rc = 0; } else { CL_PAGE_DEBUG(D_ERROR, env, page, "parent page\n"); CL_PAGE_DEBUG(D_ERROR, env, subpage, "child page\n"); LASSERT(0); } out: return rc; }
static void lov_subobject_kill(const struct lu_env *env, struct lov_object *lov, struct lovsub_object *los, int idx) { struct cl_object *sub; struct lov_layout_raid0 *r0; struct lu_site *site; struct lu_site_bkt_data *bkt; wait_queue_t *waiter; r0 = &lov->u.raid0; LASSERT(r0->lo_sub[idx] == los); sub = lovsub2cl(los); site = sub->co_lu.lo_dev->ld_site; bkt = lu_site_bkt_from_fid(site, &sub->co_lu.lo_header->loh_fid); cl_object_kill(env, sub); /* release a reference to the sub-object and ... */ lu_object_ref_del(&sub->co_lu, "lov-parent", lov); cl_object_put(env, sub); /* ... wait until it is actually destroyed---sub-object clears its * ->lo_sub[] slot in lovsub_object_fini() */ if (r0->lo_sub[idx] == los) { waiter = &lov_env_info(env)->lti_waiter; init_waitqueue_entry(waiter, current); add_wait_queue(&bkt->lsb_marche_funebre, waiter); set_current_state(TASK_UNINTERRUPTIBLE); while (1) { /* this wait-queue is signaled at the end of * lu_object_free(). */ set_current_state(TASK_UNINTERRUPTIBLE); spin_lock(&r0->lo_sub_lock); if (r0->lo_sub[idx] == los) { spin_unlock(&r0->lo_sub_lock); schedule(); } else { spin_unlock(&r0->lo_sub_lock); set_current_state(TASK_RUNNING); break; } } remove_wait_queue(&bkt->lsb_marche_funebre, waiter); } LASSERT(!r0->lo_sub[idx]); }
static int lov_find_cbdata_raid0(const struct lu_env *env, struct cl_object *obj, ldlm_iterator_t iter, void *data) { struct lov_object *lov = cl2lov(obj); struct lov_layout_raid0 *r0 = lov_r0(lov); struct cl_object *subobj; int i; int rc = 0; for (i = 0; i < r0->lo_nr; ++i) { if (r0->lo_sub[i] == NULL) continue; subobj = lovsub2cl(r0->lo_sub[i]); rc = cl_object_find_cbdata(env, subobj, iter, data); if (rc != 0) break; } return rc; }
/** * Creates sub-locks for a given lov_lock for the first time. * * Goes through all sub-objects of top-object, and creates sub-locks on every * sub-object intersecting with top-lock extent. This is complicated by the * fact that top-lock (that is being created) can be accessed concurrently * through already created sub-locks (possibly shared with other top-locks). */ static struct lov_lock *lov_lock_sub_init(const struct lu_env *env, const struct cl_object *obj, struct cl_lock *lock) { int result = 0; int i; int nr; u64 start; u64 end; u64 file_start; u64 file_end; struct lov_object *loo = cl2lov(obj); struct lov_layout_raid0 *r0 = lov_r0(loo); struct lov_lock *lovlck; file_start = cl_offset(lov2cl(loo), lock->cll_descr.cld_start); file_end = cl_offset(lov2cl(loo), lock->cll_descr.cld_end + 1) - 1; for (i = 0, nr = 0; i < r0->lo_nr; i++) { /* * XXX for wide striping smarter algorithm is desirable, * breaking out of the loop, early. */ if (likely(r0->lo_sub[i]) && /* spare layout */ lov_stripe_intersects(loo->lo_lsm, i, file_start, file_end, &start, &end)) nr++; } LASSERT(nr > 0); lovlck = libcfs_kvzalloc(offsetof(struct lov_lock, lls_sub[nr]), GFP_NOFS); if (!lovlck) return ERR_PTR(-ENOMEM); lovlck->lls_nr = nr; for (i = 0, nr = 0; i < r0->lo_nr; ++i) { if (likely(r0->lo_sub[i]) && lov_stripe_intersects(loo->lo_lsm, i, file_start, file_end, &start, &end)) { struct lov_lock_sub *lls = &lovlck->lls_sub[nr]; struct cl_lock_descr *descr; descr = &lls->sub_lock.cll_descr; LASSERT(!descr->cld_obj); descr->cld_obj = lovsub2cl(r0->lo_sub[i]); descr->cld_start = cl_index(descr->cld_obj, start); descr->cld_end = cl_index(descr->cld_obj, end); descr->cld_mode = lock->cll_descr.cld_mode; descr->cld_gid = lock->cll_descr.cld_gid; descr->cld_enq_flags = lock->cll_descr.cld_enq_flags; lls->sub_stripe = i; /* initialize sub lock */ result = lov_sublock_init(env, lock, lls); if (result < 0) break; lls->sub_initialized = 1; nr++; } } LASSERT(ergo(result == 0, nr == lovlck->lls_nr)); if (result != 0) { for (i = 0; i < nr; ++i) { if (!lovlck->lls_sub[i].sub_initialized) break; cl_lock_fini(env, &lovlck->lls_sub[i].sub_lock); } kvfree(lovlck); lovlck = ERR_PTR(result); } return lovlck; }