/** * 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; }
/** * 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; }
/** * 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; }