Example #1
0
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;
}
Example #2
0
/**
 * Checks that there are no pages being written in the extent being truncated.
 */
static int trunc_check_cb(const struct lu_env *env, struct cl_io *io,
			  struct cl_page *page, void *cbdata)
{
	const struct cl_page_slice *slice;
	struct osc_page *ops;
	struct osc_async_page *oap;
	__u64 start = *(__u64 *)cbdata;

	slice = cl_page_at(page, &osc_device_type);
	LASSERT(slice != NULL);
	ops = cl2osc_page(slice);
	oap = &ops->ops_oap;

	if (oap->oap_cmd & OBD_BRW_WRITE &&
	    !list_empty(&oap->oap_pending_item))
		CL_PAGE_DEBUG(D_ERROR, env, page, "exists %llu/%s.\n",
				start, current->comm);

	{
		struct page *vmpage = cl_page_vmpage(env, page);

		if (PageLocked(vmpage))
			CDEBUG(D_CACHE, "page %p index %lu locked for %d.\n",
			       ops, page->cp_index,
			       (oap->oap_cmd & OBD_BRW_RWMASK));
	}

	return CLP_GANG_OKAY;
}
Example #3
0
/**
 * Checks that there are no pages being written in the extent being truncated.
 */
static int trunc_check_cb(const struct lu_env *env, struct cl_io *io,
			  struct osc_page *ops , void *cbdata)
{
	struct cl_page *page = ops->ops_cl.cpl_page;
	struct osc_async_page *oap;
	__u64 start = *(__u64 *)cbdata;

	oap = &ops->ops_oap;
	if (oap->oap_cmd & OBD_BRW_WRITE &&
	    !list_empty(&oap->oap_pending_item))
		CL_PAGE_DEBUG(D_ERROR, env, page, "exists " LPU64 "/%s.\n",
				start, current->comm);

	if (PageLocked(page->cp_vmpage))
		CDEBUG(D_CACHE, "page %p index %lu locked for %d.\n",
		       ops, osc_index(ops), oap->oap_cmd & OBD_BRW_RWMASK);

	return CLP_GANG_OKAY;
}
Example #4
0
static int lov_page_cache_add(const struct lu_env *env,
			      const struct cl_page_slice *slice,
			      struct cl_io *io)
{
	struct lov_io     *lio = lov_env_io(env);
	struct lov_io_sub *sub;
	int rc = 0;

	LINVRNT(lov_page_invariant(slice));
	LINVRNT(!cl2lov_page(slice)->lps_invalid);

	sub = lov_page_subio(env, lio, slice);
	if (!IS_ERR(sub)) {
		rc = cl_page_cache_add(sub->sub_env, sub->sub_io,
				       slice->cpl_page->cp_child, CRT_WRITE);
		lov_sub_put(sub);
	} else {
		rc = PTR_ERR(sub);
		CL_PAGE_DEBUG(D_ERROR, env, slice->cpl_page, "rc = %d\n", rc);
	}
	return rc;
}
Example #5
0
File: rw26.c Project: rread/lustre
static int ll_write_end(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *vmpage, void *fsdata)
{
    struct ll_cl_context *lcc = fsdata;
    const struct lu_env *env;
    struct cl_io *io;
    struct vvp_io *vio;
    struct cl_page *page;
    unsigned from = pos & (PAGE_SIZE - 1);
    bool unplug = false;
    int result = 0;
    ENTRY;

    put_page(vmpage);

    LASSERT(lcc != NULL);
    env  = lcc->lcc_env;
    page = lcc->lcc_page;
    io   = lcc->lcc_io;
    vio  = vvp_env_io(env);

    LASSERT(cl_page_is_owned(page, io));
    if (copied > 0) {
        struct cl_page_list *plist = &vio->u.write.vui_queue;

        lcc->lcc_page = NULL; /* page will be queued */

        /* Add it into write queue */
        cl_page_list_add(plist, page);
        if (plist->pl_nr == 1) /* first page */
            vio->u.write.vui_from = from;
        else
            LASSERT(from == 0);
        vio->u.write.vui_to = from + copied;

        /* To address the deadlock in balance_dirty_pages() where
         * this dirty page may be written back in the same thread. */
        if (PageDirty(vmpage))
            unplug = true;

        /* We may have one full RPC, commit it soon */
        if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES)
            unplug = true;

        CL_PAGE_DEBUG(D_VFSTRACE, env, page,
                      "queued page: %d.\n", plist->pl_nr);
    } else {
        cl_page_disown(env, io, page);

        lcc->lcc_page = NULL;
        lu_ref_del(&page->cp_reference, "cl_io", io);
        cl_page_put(env, page);

        /* page list is not contiguous now, commit it now */
        unplug = true;
    }
    if (unplug ||
            file->f_flags & O_SYNC || IS_SYNC(file_inode(file)))
        result = vvp_io_write_commit(env, io);

    if (result < 0)
        io->ci_result = result;
    RETURN(result >= 0 ? copied : result);
}
Example #6
0
/**
 * Implementation of struct cl_object_operations::coo_req_attr_set() for osc
 * layer. osc is responsible for struct obdo::o_id and struct obdo::o_seq
 * fields.
 */
static void osc_req_attr_set(const struct lu_env *env, struct cl_object *obj,
                             struct cl_req_attr *attr)
{
    struct lov_oinfo *oinfo;
    struct obdo      *oa;
    struct ost_lvb   *lvb;
    u64		  flags = attr->cra_flags;

    oinfo   = cl2osc(obj)->oo_oinfo;
    lvb     = &oinfo->loi_lvb;
    oa      = attr->cra_oa;

    if ((flags & OBD_MD_FLMTIME) != 0) {
        oa->o_mtime = lvb->lvb_mtime;
        oa->o_valid |= OBD_MD_FLMTIME;
    }
    if ((flags & OBD_MD_FLATIME) != 0) {
        oa->o_atime = lvb->lvb_atime;
        oa->o_valid |= OBD_MD_FLATIME;
    }
    if ((flags & OBD_MD_FLCTIME) != 0) {
        oa->o_ctime = lvb->lvb_ctime;
        oa->o_valid |= OBD_MD_FLCTIME;
    }
    if (flags & OBD_MD_FLGROUP) {
        ostid_set_seq(&oa->o_oi, ostid_seq(&oinfo->loi_oi));
        oa->o_valid |= OBD_MD_FLGROUP;
    }
    if (flags & OBD_MD_FLID) {
        ostid_set_id(&oa->o_oi, ostid_id(&oinfo->loi_oi));
        oa->o_valid |= OBD_MD_FLID;
    }
    if (flags & OBD_MD_FLHANDLE) {
        struct ldlm_lock *lock;
        struct osc_page *opg;

        opg = osc_cl_page_osc(attr->cra_page, cl2osc(obj));
        lock = osc_dlmlock_at_pgoff(env, cl2osc(obj), osc_index(opg),
                                    OSC_DAP_FL_TEST_LOCK | OSC_DAP_FL_CANCELING);
        if (lock == NULL && !opg->ops_srvlock) {
            struct ldlm_resource *res;
            struct ldlm_res_id *resname;

            CL_PAGE_DEBUG(D_ERROR, env, attr->cra_page,
                          "uncovered page!\n");

            resname = &osc_env_info(env)->oti_resname;
            ostid_build_res_name(&oinfo->loi_oi, resname);
            res = ldlm_resource_get(
                      osc_export(cl2osc(obj))->exp_obd->obd_namespace,
                      NULL, resname, LDLM_EXTENT, 0);
            ldlm_resource_dump(D_ERROR, res);

            libcfs_debug_dumpstack(NULL);
            LBUG();
        }

        /* check for lockless io. */
        if (lock != NULL) {
            oa->o_handle = lock->l_remote_handle;
            oa->o_valid |= OBD_MD_FLHANDLE;
            LDLM_LOCK_PUT(lock);
        }
    }
}
Example #7
0
/**
 * Implementation of struct cl_req_operations::cro_attr_set() for osc
 * layer. osc is responsible for struct obdo::o_id and struct obdo::o_seq
 * fields.
 */
static void osc_req_attr_set(const struct lu_env *env,
			     const struct cl_req_slice *slice,
			     const struct cl_object *obj,
			     struct cl_req_attr *attr, u64 flags)
{
	struct lov_oinfo *oinfo;
	struct cl_req    *clerq;
	struct cl_page   *apage; /* _some_ page in @clerq */
	struct cl_lock   *lock;  /* _some_ lock protecting @apage */
	struct osc_lock  *olck;
	struct osc_page  *opg;
	struct obdo      *oa;
	struct ost_lvb   *lvb;

	oinfo	= cl2osc(obj)->oo_oinfo;
	lvb	= &oinfo->loi_lvb;
	oa	= attr->cra_oa;

	if ((flags & OBD_MD_FLMTIME) != 0) {
		oa->o_mtime = lvb->lvb_mtime;
		oa->o_valid |= OBD_MD_FLMTIME;
	}
	if ((flags & OBD_MD_FLATIME) != 0) {
		oa->o_atime = lvb->lvb_atime;
		oa->o_valid |= OBD_MD_FLATIME;
	}
	if ((flags & OBD_MD_FLCTIME) != 0) {
		oa->o_ctime = lvb->lvb_ctime;
		oa->o_valid |= OBD_MD_FLCTIME;
	}
	if (flags & OBD_MD_FLGROUP) {
		ostid_set_seq(&oa->o_oi, ostid_seq(&oinfo->loi_oi));
		oa->o_valid |= OBD_MD_FLGROUP;
	}
	if (flags & OBD_MD_FLID) {
		ostid_set_id(&oa->o_oi, ostid_id(&oinfo->loi_oi));
		oa->o_valid |= OBD_MD_FLID;
	}
	if (flags & OBD_MD_FLHANDLE) {
		clerq = slice->crs_req;
		LASSERT(!list_empty(&clerq->crq_pages));
		apage = container_of(clerq->crq_pages.next,
				     struct cl_page, cp_flight);
		opg = osc_cl_page_osc(apage);
		apage = opg->ops_cl.cpl_page; /* now apage is a sub-page */
		lock = cl_lock_at_page(env, apage->cp_obj, apage, NULL, 1, 1);
		if (lock == NULL) {
			struct cl_object_header *head;
			struct cl_lock	  *scan;

			head = cl_object_header(apage->cp_obj);
			list_for_each_entry(scan, &head->coh_locks,
						cll_linkage)
				CL_LOCK_DEBUG(D_ERROR, env, scan,
					      "no cover page!\n");
			CL_PAGE_DEBUG(D_ERROR, env, apage,
				      "dump uncover page!\n");
			dump_stack();
			LBUG();
		}

		olck = osc_lock_at(lock);
		LASSERT(olck != NULL);
		LASSERT(ergo(opg->ops_srvlock, olck->ols_lock == NULL));
		/* check for lockless io. */
		if (olck->ols_lock != NULL) {
			oa->o_handle = olck->ols_lock->l_remote_handle;
			oa->o_valid |= OBD_MD_FLHANDLE;
		}
		cl_lock_put(env, lock);
	}