Пример #1
0
static int osc_io_ladvise_start(const struct lu_env *env,
				const struct cl_io_slice *slice)
{
	int			 result = 0;
	struct cl_io		*io = slice->cis_io;
	struct osc_io		*oio = cl2osc_io(env, slice);
	struct cl_object	*obj = slice->cis_obj;
	struct lov_oinfo	*loi = cl2osc(obj)->oo_oinfo;
	struct cl_ladvise_io	*lio = &io->u.ci_ladvise;
	struct obdo		*oa = &oio->oi_oa;
	struct osc_async_cbargs	*cbargs = &oio->oi_cbarg;
	struct lu_ladvise	*ladvise;
	struct ladvise_hdr	*ladvise_hdr;
	int			 buf_size;
	int			 num_advise = 1;
	ENTRY;

	/* TODO: add multiple ladvise support in CLIO */
	buf_size = offsetof(typeof(*ladvise_hdr), lah_advise[num_advise]);
	if (osc_env_info(env)->oti_ladvise_buf.lb_len < buf_size)
		lu_buf_realloc(&osc_env_info(env)->oti_ladvise_buf, buf_size);

	ladvise_hdr = osc_env_info(env)->oti_ladvise_buf.lb_buf;
	if (ladvise_hdr == NULL)
		RETURN(-ENOMEM);

	memset(ladvise_hdr, 0, buf_size);
	ladvise_hdr->lah_magic = LADVISE_MAGIC;
	ladvise_hdr->lah_count = num_advise;
	ladvise_hdr->lah_flags = lio->li_flags;

	memset(oa, 0, sizeof(*oa));
	oa->o_oi = loi->loi_oi;
	oa->o_valid = OBD_MD_FLID;
	obdo_set_parent_fid(oa, lio->li_fid);

	ladvise = ladvise_hdr->lah_advise;
	ladvise->lla_start = lio->li_start;
	ladvise->lla_end = lio->li_end;
	ladvise->lla_advice = lio->li_advice;

	if (lio->li_flags & LF_ASYNC) {
		result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
					  ladvise_hdr, NULL, NULL, NULL);
	} else {
		init_completion(&cbargs->opc_sync);
		result = osc_ladvise_base(osc_export(cl2osc(obj)), oa,
					  ladvise_hdr, osc_async_upcall,
					  cbargs, PTLRPCD_SET);
		cbargs->opc_rpc_sent = result == 0;
	}
	RETURN(result);
}
Пример #2
0
static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj,
			 struct cl_fsync_io *fio)
{
	struct osc_io    *oio   = osc_env_io(env);
	struct obdo      *oa    = &oio->oi_oa;
	struct obd_info  *oinfo = &oio->oi_info;
	struct lov_oinfo *loi   = obj->oo_oinfo;
	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
	int rc = 0;

	memset(oa, 0, sizeof(*oa));
	oa->o_oi = loi->loi_oi;
	oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;

	/* reload size abd blocks for start and end of sync range */
	oa->o_size = fio->fi_start;
	oa->o_blocks = fio->fi_end;
	oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;

	obdo_set_parent_fid(oa, fio->fi_fid);

	memset(oinfo, 0, sizeof(*oinfo));
	oinfo->oi_oa = oa;
	oinfo->oi_capa = fio->fi_capa;
	init_completion(&cbargs->opc_sync);

	rc = osc_sync_base(osc_export(obj), oinfo, osc_async_upcall, cbargs,
			   PTLRPCD_SET);
	return rc;
}
Пример #3
0
static int osc_io_commit_write(const struct lu_env *env,
			       const struct cl_io_slice *ios,
			       const struct cl_page_slice *slice,
			       unsigned from, unsigned to)
{
	struct osc_io	 *oio = cl2osc_io(env, ios);
	struct osc_page       *opg = cl2osc_page(slice);
	struct osc_object     *obj = cl2osc(opg->ops_cl.cpl_obj);
	struct osc_async_page *oap = &opg->ops_oap;

	LASSERT(to > 0);
	/*
	 * XXX instead of calling osc_page_touch() here and in
	 * osc_io_fault_start() it might be more logical to introduce
	 * cl_page_touch() method, that generic cl_io_commit_write() and page
	 * fault code calls.
	 */
	osc_page_touch(env, cl2osc_page(slice), to);
	if (!client_is_remote(osc_export(obj)) &&
	    capable(CFS_CAP_SYS_RESOURCE))
		oap->oap_brw_flags |= OBD_BRW_NOQUOTA;

	if (oio->oi_lockless)
		/* see osc_io_prepare_write() for lockless io handling. */
		cl_page_clip(env, slice->cpl_page, from, to);

	return 0;
}
Пример #4
0
static int osc_object_prune(const struct lu_env *env, struct cl_object *obj)
{
    struct osc_object       *osc = cl2osc(obj);
    struct ldlm_res_id      *resname = &osc_env_info(env)->oti_resname;

    /* DLM locks don't hold a reference of osc_object so we have to
     * clear it before the object is being destroyed. */
    ostid_build_res_name(&osc->oo_oinfo->loi_oi, resname);
    ldlm_resource_iterate(osc_export(osc)->exp_obd->obd_namespace, resname,
                          osc_object_ast_clear, osc);
    return 0;
}
Пример #5
0
static int osc_io_data_version_start(const struct lu_env *env,
				     const struct cl_io_slice *slice)
{
	struct cl_data_version_io *dv	= &slice->cis_io->u.ci_data_version;
	struct osc_io		*oio	= cl2osc_io(env, slice);
	struct obdo		*oa	= &oio->oi_oa;
	struct osc_async_cbargs	*cbargs	= &oio->oi_cbarg;
	struct osc_object	*obj	= cl2osc(slice->cis_obj);
	struct lov_oinfo	*loi	= obj->oo_oinfo;
	struct obd_export	*exp	= osc_export(obj);
	struct ptlrpc_request	*req;
	struct ost_body		*body;
	struct osc_data_version_args *dva;
	int rc;

	ENTRY;
	memset(oa, 0, sizeof(*oa));
	oa->o_oi = loi->loi_oi;
	oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP;

	if (dv->dv_flags & (LL_DV_RD_FLUSH | LL_DV_WR_FLUSH)) {
		oa->o_valid |= OBD_MD_FLFLAGS;
		oa->o_flags |= OBD_FL_SRVLOCK;
		if (dv->dv_flags & LL_DV_WR_FLUSH)
			oa->o_flags |= OBD_FL_FLUSH;
	}

	init_completion(&cbargs->opc_sync);

	req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR);
	if (req == NULL)
		RETURN(-ENOMEM);

	rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GETATTR);
	if (rc < 0) {
		ptlrpc_request_free(req);
		RETURN(rc);
	}

	body = req_capsule_client_get(&req->rq_pill, &RMF_OST_BODY);
	lustre_set_wire_obdo(&req->rq_import->imp_connect_data, &body->oa, oa);

	ptlrpc_request_set_replen(req);
	req->rq_interpret_reply = osc_data_version_interpret;
	CLASSERT(sizeof(*dva) <= sizeof(req->rq_async_args));
	dva = ptlrpc_req_async_args(req);
	dva->dva_oio = oio;

	ptlrpcd_add_req(req);

	RETURN(0);
}
Пример #6
0
static int osc_object_prune(const struct lu_env *env, struct cl_object *obj)
{
	struct osc_object       *osc = cl2osc(obj);
	struct ldlm_res_id      *resname = &osc_env_info(env)->oti_resname;

	LASSERTF(osc->oo_npages == 0,
		 DFID "still have %lu pages, obj: %p, osc: %p\n",
		 PFID(lu_object_fid(&obj->co_lu)), osc->oo_npages, obj, osc);

	/* DLM locks don't hold a reference of osc_object so we have to
	 * clear it before the object is being destroyed. */
	ostid_build_res_name(&osc->oo_oinfo->loi_oi, resname);
	ldlm_resource_iterate(osc_export(osc)->exp_obd->obd_namespace, resname,
			      osc_object_ast_clear, osc);
	return 0;
}
Пример #7
0
/**
 * Finds an existing lock covering a page with given index.
 * Copy of osc_obj_dlmlock_at_pgoff() but for DoM IBITS lock.
 */
struct ldlm_lock *mdc_dlmlock_at_pgoff(const struct lu_env *env,
				       struct osc_object *obj, pgoff_t index,
				       enum osc_dap_flags dap_flags)
{
	struct osc_thread_info *info = osc_env_info(env);
	struct ldlm_res_id *resname = &info->oti_resname;
	union ldlm_policy_data *policy = &info->oti_policy;
	struct lustre_handle lockh;
	struct ldlm_lock *lock = NULL;
	enum ldlm_mode mode;
	__u64 flags;

	ENTRY;

	fid_build_reg_res_name(lu_object_fid(osc2lu(obj)), resname);
	mdc_lock_build_policy(env, policy);

	flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING;
	if (dap_flags & OSC_DAP_FL_TEST_LOCK)
		flags |= LDLM_FL_TEST_LOCK;

again:
	/* Next, search for already existing extent locks that will cover us */
	/* If we're trying to read, we also search for an existing PW lock.  The
	 * VFS and page cache already protect us locally, so lots of readers/
	 * writers can share a single PW lock. */
	mode = mdc_dom_lock_match(env, osc_export(obj), resname, LDLM_IBITS,
				  policy, LCK_PR | LCK_PW, &flags, obj, &lockh,
				  dap_flags & OSC_DAP_FL_CANCELING);
	if (mode != 0) {
		lock = ldlm_handle2lock(&lockh);
		/* RACE: the lock is cancelled so let's try again */
		if (unlikely(lock == NULL))
			goto again;
	}

	RETURN(lock);
}
Пример #8
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);
        }
    }
}
Пример #9
0
static int osc_object_fiemap(const struct lu_env *env, struct cl_object *obj,
                             struct ll_fiemap_info_key *fmkey,
                             struct fiemap *fiemap, size_t *buflen)
{
    struct obd_export *exp = osc_export(cl2osc(obj));
    struct ldlm_res_id resid;
    union ldlm_policy_data policy;
    struct lustre_handle lockh;
    enum ldlm_mode mode = LCK_MINMODE;
    struct ptlrpc_request *req;
    struct fiemap *reply;
    char *tmp;
    int rc;
    ENTRY;

    fmkey->lfik_oa.o_oi = cl2osc(obj)->oo_oinfo->loi_oi;
    if (!(fmkey->lfik_fiemap.fm_flags & FIEMAP_FLAG_SYNC))
        goto skip_locking;

    policy.l_extent.start = fmkey->lfik_fiemap.fm_start & PAGE_MASK;

    if (OBD_OBJECT_EOF - fmkey->lfik_fiemap.fm_length <=
            fmkey->lfik_fiemap.fm_start + PAGE_SIZE - 1)
        policy.l_extent.end = OBD_OBJECT_EOF;
    else
        policy.l_extent.end = (fmkey->lfik_fiemap.fm_start +
                               fmkey->lfik_fiemap.fm_length +
                               PAGE_SIZE - 1) & PAGE_MASK;

    ostid_build_res_name(&fmkey->lfik_oa.o_oi, &resid);
    mode = ldlm_lock_match(exp->exp_obd->obd_namespace,
                           LDLM_FL_BLOCK_GRANTED | LDLM_FL_LVB_READY,
                           &resid, LDLM_EXTENT, &policy,
                           LCK_PR | LCK_PW, &lockh, 0);
    if (mode) { /* lock is cached on client */
        if (mode != LCK_PR) {
            ldlm_lock_addref(&lockh, LCK_PR);
            ldlm_lock_decref(&lockh, LCK_PW);
        }
    } else { /* no cached lock, needs acquire lock on server side */
        fmkey->lfik_oa.o_valid |= OBD_MD_FLFLAGS;
        fmkey->lfik_oa.o_flags |= OBD_FL_SRVLOCK;
    }

skip_locking:
    req = ptlrpc_request_alloc(class_exp2cliimp(exp),
                               &RQF_OST_GET_INFO_FIEMAP);
    if (req == NULL)
        GOTO(drop_lock, rc = -ENOMEM);

    req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_KEY, RCL_CLIENT,
                         sizeof(*fmkey));
    req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_CLIENT,
                         *buflen);
    req_capsule_set_size(&req->rq_pill, &RMF_FIEMAP_VAL, RCL_SERVER,
                         *buflen);

    rc = ptlrpc_request_pack(req, LUSTRE_OST_VERSION, OST_GET_INFO);
    if (rc != 0) {
        ptlrpc_request_free(req);
        GOTO(drop_lock, rc);
    }
    tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_KEY);
    memcpy(tmp, fmkey, sizeof(*fmkey));
    tmp = req_capsule_client_get(&req->rq_pill, &RMF_FIEMAP_VAL);
    memcpy(tmp, fiemap, *buflen);
    ptlrpc_request_set_replen(req);

    rc = ptlrpc_queue_wait(req);
    if (rc != 0)
        GOTO(fini_req, rc);

    reply = req_capsule_server_get(&req->rq_pill, &RMF_FIEMAP_VAL);
    if (reply == NULL)
        GOTO(fini_req, rc = -EPROTO);

    memcpy(fiemap, reply, *buflen);
fini_req:
    ptlrpc_req_finished(req);
drop_lock:
    if (mode)
        ldlm_lock_decref(&lockh, LCK_PR);
    RETURN(rc);
}
Пример #10
0
static int osc_io_setattr_start(const struct lu_env *env,
				const struct cl_io_slice *slice)
{
	struct cl_io	    *io     = slice->cis_io;
	struct osc_io	   *oio    = cl2osc_io(env, slice);
	struct cl_object	*obj    = slice->cis_obj;
	struct lov_oinfo	*loi    = cl2osc(obj)->oo_oinfo;
	struct cl_attr	  *attr   = &osc_env_info(env)->oti_attr;
	struct obdo	     *oa     = &oio->oi_oa;
	struct osc_async_cbargs *cbargs = &oio->oi_cbarg;
	__u64		    size   = io->u.ci_setattr.sa_attr.lvb_size;
	unsigned int	     ia_valid = io->u.ci_setattr.sa_valid;
	int		      result = 0;
	struct obd_info	  oinfo = { { { 0 } } };

	/* truncate cache dirty pages first */
	if (cl_io_is_trunc(io))
		result = osc_cache_truncate_start(env, oio, cl2osc(obj), size);

	if (result == 0 && oio->oi_lockless == 0) {
		cl_object_attr_lock(obj);
		result = cl_object_attr_get(env, obj, attr);
		if (result == 0) {
			struct ost_lvb *lvb = &io->u.ci_setattr.sa_attr;
			unsigned int cl_valid = 0;

			if (ia_valid & ATTR_SIZE) {
				attr->cat_size = attr->cat_kms = size;
				cl_valid = (CAT_SIZE | CAT_KMS);
			}
			if (ia_valid & ATTR_MTIME_SET) {
				attr->cat_mtime = lvb->lvb_mtime;
				cl_valid |= CAT_MTIME;
			}
			if (ia_valid & ATTR_ATIME_SET) {
				attr->cat_atime = lvb->lvb_atime;
				cl_valid |= CAT_ATIME;
			}
			if (ia_valid & ATTR_CTIME_SET) {
				attr->cat_ctime = lvb->lvb_ctime;
				cl_valid |= CAT_CTIME;
			}
			result = cl_object_attr_set(env, obj, attr, cl_valid);
		}
		cl_object_attr_unlock(obj);
	}
	memset(oa, 0, sizeof(*oa));
	if (result == 0) {
		oa->o_oi = loi->loi_oi;
		oa->o_mtime = attr->cat_mtime;
		oa->o_atime = attr->cat_atime;
		oa->o_ctime = attr->cat_ctime;
		oa->o_valid = OBD_MD_FLID | OBD_MD_FLGROUP | OBD_MD_FLATIME |
			OBD_MD_FLCTIME | OBD_MD_FLMTIME;
		if (ia_valid & ATTR_SIZE) {
			oa->o_size = size;
			oa->o_blocks = OBD_OBJECT_EOF;
			oa->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;

			if (oio->oi_lockless) {
				oa->o_flags = OBD_FL_SRVLOCK;
				oa->o_valid |= OBD_MD_FLFLAGS;
			}
		} else {
			LASSERT(oio->oi_lockless == 0);
		}

		oinfo.oi_oa = oa;
		oinfo.oi_capa = io->u.ci_setattr.sa_capa;
		init_completion(&cbargs->opc_sync);

		if (ia_valid & ATTR_SIZE)
			result = osc_punch_base(osc_export(cl2osc(obj)),
						&oinfo, osc_async_upcall,
						cbargs, PTLRPCD_SET);
		else
			result = osc_setattr_async_base(osc_export(cl2osc(obj)),
							&oinfo, NULL,
							osc_async_upcall,
							cbargs, PTLRPCD_SET);
		cbargs->opc_rpc_sent = result == 0;
	}
	return result;
}