Esempio n. 1
0
/**
 * Implementation of dt_object_operations::do_object_lock
 *
 * Enqueue a lock (by ldlm_cli_enqueue()) of remote object on the remote MDT,
 * which will lock the object in the global namespace. And because the
 * cross-MDT locks are relatively rare compared with normal local MDT operation,
 * let's release it right away, instead of putting it into the LRU list.
 *
 * \param[in] env	execution environment
 * \param[in] dt	object to be locked
 * \param[out] lh	lock handle
 * \param[in] einfo	enqueue information
 * \param[in] policy	lock policy
 *
 * \retval		ELDLM_OK if locking the object succeeds.
 * \retval		negative errno if locking fails.
 */
static int osp_md_object_lock(const struct lu_env *env,
			      struct dt_object *dt,
			      struct lustre_handle *lh,
			      struct ldlm_enqueue_info *einfo,
			      union ldlm_policy_data *policy)
{
	struct ldlm_res_id	*res_id;
	struct dt_device	*dt_dev = lu2dt_dev(dt->do_lu.lo_dev);
	struct osp_device	*osp = dt2osp_dev(dt_dev);
	struct ptlrpc_request	*req;
	int			rc = 0;
	__u64			flags = 0;
	enum ldlm_mode		mode;

	res_id = einfo->ei_res_id;
	LASSERT(res_id != NULL);

	mode = ldlm_lock_match(osp->opd_obd->obd_namespace,
			       LDLM_FL_BLOCK_GRANTED, res_id,
			       einfo->ei_type, policy,
			       einfo->ei_mode, lh, 0);
	if (mode > 0)
		return ELDLM_OK;

	if (einfo->ei_nonblock)
		flags |= LDLM_FL_BLOCK_NOWAIT;

	req = ldlm_enqueue_pack(osp->opd_exp, 0);
	if (IS_ERR(req))
		RETURN(PTR_ERR(req));

	rc = ldlm_cli_enqueue(osp->opd_exp, &req, einfo, res_id,
			      (const union ldlm_policy_data *)policy,
			      &flags, NULL, 0, LVB_T_NONE, lh, 0);

	ptlrpc_req_finished(req);
	if (rc == ELDLM_OK) {
		struct ldlm_lock *lock;

		lock = __ldlm_handle2lock(lh, 0);
		ldlm_set_cbpending(lock);
		LDLM_LOCK_PUT(lock);
	}

	return rc == ELDLM_OK ? 0 : -EIO;
}
Esempio n. 2
0
/**
 * Implementation of dt_object_operations::do_object_lock
 *
 * Enqueue a lock (by ldlm_cli_enqueue()) of remote object on the remote MDT,
 * which will lock the object in the global namespace. And because the
 * cross-MDT locks are relatively rare compared with normal local MDT operation,
 * let's release it right away, instead of putting it into the LRU list.
 *
 * \param[in] env	execution environment
 * \param[in] dt	object to be locked
 * \param[out] lh	lock handle
 * \param[in] einfo	enqueue information
 * \param[in] policy	lock policy
 *
 * \retval		ELDLM_OK if locking the object succeeds.
 * \retval		negative errno if locking fails.
 */
static int osp_md_object_lock(const struct lu_env *env,
			      struct dt_object *dt,
			      struct lustre_handle *lh,
			      struct ldlm_enqueue_info *einfo,
			      union ldlm_policy_data *policy)
{
	struct ldlm_res_id	*res_id;
	struct dt_device	*dt_dev = lu2dt_dev(dt->do_lu.lo_dev);
	struct osp_device	*osp = dt2osp_dev(dt_dev);
	struct lu_device	*top_device;
	struct ptlrpc_request	*req;
	int			rc = 0;
	__u64			flags = LDLM_FL_NO_LRU;

	res_id = einfo->ei_res_id;
	LASSERT(res_id != NULL);

	if (einfo->ei_nonblock)
		flags |= LDLM_FL_BLOCK_NOWAIT;
	if (einfo->ei_mode & (LCK_EX | LCK_PW))
		flags |= LDLM_FL_COS_INCOMPAT;

	req = ldlm_enqueue_pack(osp->opd_exp, 0);
	if (IS_ERR(req))
		RETURN(PTR_ERR(req));

	/* During recovery, it needs to let OSP send enqueue
	 * without checking recoverying status, in case the
	 * other target is being recovered at the same time,
	 * and if we wait here for the import to be recovered,
	 * it might cause deadlock */
	top_device = dt_dev->dd_lu_dev.ld_site->ls_top_dev;
	if (top_device->ld_obd->obd_recovering)
		req->rq_allow_replay = 1;

	rc = ldlm_cli_enqueue(osp->opd_exp, &req, einfo, res_id,
			      (const union ldlm_policy_data *)policy,
			      &flags, NULL, 0, LVB_T_NONE, lh, 0);

	ptlrpc_req_finished(req);

	return rc == ELDLM_OK ? 0 : -EIO;
}
Esempio n. 3
0
/**
 * Implementation of dt_body_operations::dbo_declare_write
 *
 * Create the osp_update_request to track the update for this OSP
 * in the transaction.
  *
 * \param[in] env	execution environment
 * \param[in] dt	object to be written
 * \param[in] buf	buffer to write which includes an embedded size field
 * \param[in] pos	offet in the object to start writing at
 * \param[in] th	transaction handle
 *
 * \retval		0 if preparation succeeds.
 * \retval		negative errno if preparation fails.
 */
static ssize_t osp_md_declare_write(const struct lu_env *env,
				    struct dt_object *dt,
				    const struct lu_buf *buf,
				    loff_t pos, struct thandle *th)
{
	struct osp_device *osp = dt2osp_dev(th->th_dev);
	int rc;

	rc = osp_trans_update_request_create(th);
	if (rc != 0)
		return rc;

	if (osp->opd_update == NULL)
		return 0;

	if (dt2osp_obj(dt)->opo_stale)
		return -ESTALE;

	return 0;
}