ENTRY;
LASSERT(lock != NULL);
- if (rc != 0) {
- rc = ldlm_handle_ast_error(lock, req, rc,
- arg->type == LDLM_BL_CALLBACK
- ? "blocking" : "completion");
- if (rc == -ERESTART)
- cfs_atomic_inc(&arg->restart);
- }
+
+ switch (arg->type) {
+ case LDLM_GL_CALLBACK:
+ /* Update the LVB from disk if the AST failed
+ * (this is a legal race)
+ *
+ * - Glimpse callback of local lock just returns
+ * -ELDLM_NO_LOCK_DATA.
+ * - Glimpse callback of remote lock might return
+ * -ELDLM_NO_LOCK_DATA when inode is cleared. LU-274
+ */
+ if (rc == -ELDLM_NO_LOCK_DATA) {
+ LDLM_DEBUG(lock, "lost race - client has a lock but no "
+ "inode");
+ ldlm_res_lvbo_update(lock->l_resource, NULL, 1);
+ } else if (rc != 0) {
+ rc = ldlm_handle_ast_error(lock, req, rc, "glimpse");
+ } else {
+ rc = ldlm_res_lvbo_update(lock->l_resource, req, 1);
+ }
+ break;
+ case LDLM_BL_CALLBACK:
+ if (rc != 0)
+ rc = ldlm_handle_ast_error(lock, req, rc, "blocking");
+ break;
+ case LDLM_CP_CALLBACK:
+ if (rc != 0)
+ rc = ldlm_handle_ast_error(lock, req, rc, "completion");
+ break;
+ default:
+ LDLM_ERROR(lock, "invalid opcode for lock callback %d",
+ arg->type);
+ LBUG();
+ }
+
+ /* release extra reference taken in ldlm_ast_fini() */
LDLM_LOCK_RELEASE(lock);
+ if (rc == -ERESTART)
+ cfs_atomic_inc(&arg->restart);
+
RETURN(0);
}
-static inline int ldlm_bl_and_cp_ast_tail(struct ptlrpc_request *req,
- struct ldlm_cb_set_arg *arg,
- struct ldlm_lock *lock,
- int instant_cancel)
+static inline int ldlm_ast_fini(struct ptlrpc_request *req,
+ struct ldlm_cb_set_arg *arg,
+ struct ldlm_lock *lock,
+ int instant_cancel)
{
int rc = 0;
ENTRY;
lprocfs_counter_incr(lock->l_export->exp_nid_stats->nid_ldlm_stats,
LDLM_BL_CALLBACK - LDLM_FIRST_OPC);
- rc = ldlm_bl_and_cp_ast_tail(req, arg, lock, instant_cancel);
+ rc = ldlm_ast_fini(req, arg, lock, instant_cancel);
RETURN(rc);
}
long total_enqueue_wait;
int instant_cancel = 0;
int rc = 0;
+ int lvb_len;
ENTRY;
LASSERT(lock != NULL);
if (req == NULL)
RETURN(-ENOMEM);
- /* server namespace, doesn't need lock */
- if (lock->l_resource->lr_lvb_len) {
+ /* server namespace, doesn't need lock */
+ lvb_len = ldlm_lvbo_size(lock);
+ if (lvb_len > 0)
req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_CLIENT,
- lock->l_resource->lr_lvb_len);
- }
+ lvb_len);
rc = ptlrpc_request_pack(req, LUSTRE_DLM_VERSION, LDLM_CP_CALLBACK);
if (rc) {
body->lock_handle[0] = lock->l_remote_handle;
body->lock_flags = flags;
ldlm_lock2desc(lock, &body->lock_desc);
- if (lock->l_resource->lr_lvb_len) {
- void *lvb = req_capsule_client_get(&req->rq_pill, &RMF_DLM_LVB);
+ if (lvb_len > 0) {
+ void *lvb = req_capsule_client_get(&req->rq_pill, &RMF_DLM_LVB);
- lock_res(lock->l_resource);
- memcpy(lvb, lock->l_resource->lr_lvb_data,
- lock->l_resource->lr_lvb_len);
- unlock_res(lock->l_resource);
+ lvb_len = ldlm_lvbo_fill(lock, lvb, lvb_len);
+ req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB,
+ lvb_len, RCL_CLIENT);
}
LDLM_DEBUG(lock, "server preparing completion AST (after %lds wait)",
lprocfs_counter_incr(lock->l_export->exp_nid_stats->nid_ldlm_stats,
LDLM_CP_CALLBACK - LDLM_FIRST_OPC);
- rc = ldlm_bl_and_cp_ast_tail(req, arg, lock, instant_cancel);
+ rc = ldlm_ast_fini(req, arg, lock, instant_cancel);
RETURN(rc);
}
int ldlm_server_glimpse_ast(struct ldlm_lock *lock, void *data)
{
- struct ldlm_resource *res = lock->l_resource;
- struct ldlm_request *body;
- struct ptlrpc_request *req;
- int rc;
+ struct ldlm_cb_set_arg *arg = data;
+ struct ldlm_request *body;
+ struct ptlrpc_request *req;
+ struct ldlm_cb_async_args *ca;
+ int rc;
+ struct req_format *req_fmt;
ENTRY;
LASSERT(lock != NULL);
+ if (arg->gl_desc != NULL)
+ /* There is a glimpse descriptor to pack */
+ req_fmt = &RQF_LDLM_GL_DESC_CALLBACK;
+ else
+ req_fmt = &RQF_LDLM_GL_CALLBACK;
+
req = ptlrpc_request_alloc_pack(lock->l_export->exp_imp_reverse,
- &RQF_LDLM_GL_CALLBACK,
- LUSTRE_DLM_VERSION, LDLM_GL_CALLBACK);
+ req_fmt, LUSTRE_DLM_VERSION,
+ LDLM_GL_CALLBACK);
if (req == NULL)
RETURN(-ENOMEM);
+ if (arg->gl_desc != NULL) {
+ /* copy the GL descriptor */
+ union ldlm_gl_desc *desc;
+ desc = req_capsule_client_get(&req->rq_pill, &RMF_DLM_GL_DESC);
+ *desc = *arg->gl_desc;
+ }
+
body = req_capsule_client_get(&req->rq_pill, &RMF_DLM_REQ);
body->lock_handle[0] = lock->l_remote_handle;
ldlm_lock2desc(lock, &body->lock_desc);
+ CLASSERT(sizeof(*ca) <= sizeof(req->rq_async_args));
+ ca = ptlrpc_req_async_args(req);
+ ca->ca_set_arg = arg;
+ ca->ca_lock = lock;
+
/* server namespace, doesn't need lock */
req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
- lock->l_resource->lr_lvb_len);
- res = lock->l_resource;
+ ldlm_lvbo_size(lock));
ptlrpc_request_set_replen(req);
-
req->rq_send_state = LUSTRE_IMP_FULL;
/* ptlrpc_request_alloc_pack already set timeout */
if (AT_OFF)
req->rq_timeout = ldlm_get_rq_timeout();
+ req->rq_interpret_reply = ldlm_cb_interpret;
+
if (lock->l_export && lock->l_export->exp_nid_stats &&
lock->l_export->exp_nid_stats->nid_ldlm_stats)
lprocfs_counter_incr(lock->l_export->exp_nid_stats->nid_ldlm_stats,
LDLM_GL_CALLBACK - LDLM_FIRST_OPC);
- rc = ptlrpc_queue_wait(req);
- /* Update the LVB from disk if the AST failed (this is a legal race)
- *
- * - Glimpse callback of local lock just return -ELDLM_NO_LOCK_DATA.
- * - Glimpse callback of remote lock might return -ELDLM_NO_LOCK_DATA
- * when inode is cleared. LU-274
- */
- if (rc == -ELDLM_NO_LOCK_DATA) {
- LDLM_DEBUG(lock, "lost race - client has a lock but no inode");
- ldlm_res_lvbo_update(res, NULL, 1);
- } else if (rc != 0) {
- rc = ldlm_handle_ast_error(lock, req, rc, "glimpse");
- } else {
- rc = ldlm_res_lvbo_update(res, req, 1);
- }
+ rc = ldlm_ast_fini(req, arg, lock, 0);
+
+ RETURN(rc);
+}
- ptlrpc_req_finished(req);
- if (rc == -ERESTART)
- ldlm_reprocess_all(res);
+int ldlm_glimpse_locks(struct ldlm_resource *res, cfs_list_t *gl_work_list)
+{
+ int rc;
+ ENTRY;
- RETURN(rc);
+ rc = ldlm_run_ast_work(ldlm_res_to_ns(res), gl_work_list,
+ LDLM_WORK_GL_AST);
+ if (rc == -ERESTART)
+ ldlm_reprocess_all(res);
+
+ RETURN(rc);
+}
+
+/* return ldlm lock associated with a lock callback request */
+struct ldlm_lock *ldlm_request_lock(struct ptlrpc_request *req)
+{
+ struct ldlm_cb_async_args *ca;
+ struct ldlm_lock *lock;
+ ENTRY;
+
+ ca = ptlrpc_req_async_args(req);
+ lock = ca->ca_lock;
+ if (lock == NULL)
+ RETURN(ERR_PTR(-EFAULT));
+
+ RETURN(lock);
}
+EXPORT_SYMBOL(ldlm_request_lock);
static void ldlm_svc_get_eopc(const struct ldlm_request *dlm_req,
struct lprocfs_stats *srv_stats)
if (unlikely(flags & LDLM_FL_REPLAY)) {
/* Find an existing lock in the per-export lock hash */
+ /* In the function below, .hs_keycmp resolves to
+ * ldlm_export_lock_keycmp() */
+ /* coverity[overrun-buffer-val] */
lock = cfs_hash_lookup(req->rq_export->exp_lock_hash,
(void *)&dlm_req->lock_handle[0]);
if (lock != NULL) {
/* based on the assumption that lvb size never changes during
* resource life time otherwise it need resource->lr_lock's
* protection */
- if (lock->l_resource->lr_lvb_len) {
- req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB,
- RCL_SERVER,
- lock->l_resource->lr_lvb_len);
- }
+ req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB,
+ RCL_SERVER, ldlm_lvbo_size(lock));
if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_ENQUEUE_EXTENT_ERR))
GOTO(out, rc = -ENOMEM);
"(err=%d, rc=%d)", err, rc);
if (rc == 0) {
- if (lock->l_resource->lr_lvb_len > 0) {
- /* MDT path won't handle lr_lvb_data, so
- * lock/unlock better be contained in the
- * if block */
- void *lvb;
-
- lvb = req_capsule_server_get(&req->rq_pill,
- &RMF_DLM_LVB);
- LASSERTF(lvb != NULL, "req %p, lock %p\n",
- req, lock);
- lock_res(lock->l_resource);
- memcpy(lvb, lock->l_resource->lr_lvb_data,
- lock->l_resource->lr_lvb_len);
- unlock_res(lock->l_resource);
- }
+ int lvb_len = ldlm_lvbo_size(lock);
+
+ if (lvb_len > 0) {
+ void *buf;
+ int buflen;
+
+ buf = req_capsule_server_get(&req->rq_pill,
+ &RMF_DLM_LVB);
+ LASSERTF(buf != NULL, "req %p, lock %p\n",
+ req, lock);
+ buflen = req_capsule_get_size(&req->rq_pill,
+ &RMF_DLM_LVB, RCL_SERVER);
+ buflen = ldlm_lvbo_fill(lock, buf, buflen);
+ req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB,
+ buflen, RCL_SERVER);
+ }
} else {
lock_res_and_lock(lock);
ldlm_resource_unlink_lock(lock);
if (first >= count)
RETURN(0);
+ if (count == 1 && dlm_req->lock_handle[0].cookie == 0)
+ RETURN(0);
+
/* There is no lock on the server at the replay time,
* skip lock cancelling to make replay tests to pass. */
if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)
LASSERT(req->rq_export != NULL);
LASSERT(req->rq_export->exp_obd != NULL);
- switch (lustre_msg_get_opc(req->rq_reqmsg)) {
- case LDLM_BL_CALLBACK:
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK))
- RETURN(0);
- break;
- case LDLM_CP_CALLBACK:
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CP_CALLBACK))
- RETURN(0);
- break;
- case LDLM_GL_CALLBACK:
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_GL_CALLBACK))
- RETURN(0);
- break;
+ switch (lustre_msg_get_opc(req->rq_reqmsg)) {
+ case LDLM_BL_CALLBACK:
+ if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_BL_CALLBACK_NET))
+ RETURN(0);
+ break;
+ case LDLM_CP_CALLBACK:
+ if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CP_CALLBACK_NET))
+ RETURN(0);
+ break;
+ case LDLM_GL_CALLBACK:
+ if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_GL_CALLBACK_NET))
+ RETURN(0);
+ break;
case LDLM_SET_INFO:
rc = ldlm_handle_setinfo(req);
ldlm_callback_reply(req, rc);
RETURN(0);
ldlm_callback_reply(req, rc);
RETURN(0);
- case OBD_QC_CALLBACK:
- req_capsule_set(&req->rq_pill, &RQF_QC_CALLBACK);
- if (OBD_FAIL_CHECK(OBD_FAIL_OBD_QC_CALLBACK_NET))
- RETURN(0);
- rc = target_handle_qc_callback(req);
- ldlm_callback_reply(req, rc);
- RETURN(0);
- case QUOTA_DQACQ:
- case QUOTA_DQREL:
- /* reply in handler */
- req_capsule_set(&req->rq_pill, &RQF_MDS_QUOTA_DQACQ);
- rc = target_handle_dqacq_callback(req);
- RETURN(0);
case LLOG_ORIGIN_HANDLE_CREATE:
req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
if (OBD_FAIL_CHECK(OBD_FAIL_OBD_LOGD_NET))
RETURN(0);
- rc = llog_origin_handle_create(req);
+ rc = llog_origin_handle_open(req);
ldlm_callback_reply(req, rc);
RETURN(0);
case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
case LDLM_CANCEL:
req_capsule_set(&req->rq_pill, &RQF_LDLM_CANCEL);
CDEBUG(D_INODE, "cancel\n");
- if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CANCEL))
- RETURN(0);
+ if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_CANCEL_NET))
+ RETURN(0);
rc = ldlm_handle_cancel(req);
if (rc)
break;
if (lock->l_export && lock->l_export->exp_lock_hash) {
/* NB: it's safe to call cfs_hash_del() even lock isn't
* in exp_lock_hash. */
+ /* In the function below, .hs_keycmp resolves to
+ * ldlm_export_lock_keycmp() */
+ /* coverity[overrun-buffer-val] */
cfs_hash_del(lock->l_export->exp_lock_hash,
&lock->l_remote_handle, &lock->l_exp_hash);
}
if (ldlm_resource_slab == NULL)
return -ENOMEM;
- ldlm_lock_slab = cfs_mem_cache_create("ldlm_locks",
- sizeof(struct ldlm_lock), 0,
- CFS_SLAB_HWCACHE_ALIGN | CFS_SLAB_DESTROY_BY_RCU);
- if (ldlm_lock_slab == NULL) {
- cfs_mem_cache_destroy(ldlm_resource_slab);
- return -ENOMEM;
- }
+ ldlm_lock_slab = cfs_mem_cache_create("ldlm_locks",
+ sizeof(struct ldlm_lock), 0,
+ CFS_SLAB_HWCACHE_ALIGN | SLAB_DESTROY_BY_RCU);
+ if (ldlm_lock_slab == NULL) {
+ cfs_mem_cache_destroy(ldlm_resource_slab);
+ return -ENOMEM;
+ }
ldlm_interval_slab = cfs_mem_cache_create("interval_node",
sizeof(struct ldlm_interval),
EXPORT_SYMBOL(ldlm_server_blocking_ast);
EXPORT_SYMBOL(ldlm_server_completion_ast);
EXPORT_SYMBOL(ldlm_server_glimpse_ast);
+EXPORT_SYMBOL(ldlm_glimpse_locks);
EXPORT_SYMBOL(ldlm_handle_enqueue);
EXPORT_SYMBOL(ldlm_handle_enqueue0);
EXPORT_SYMBOL(ldlm_handle_cancel);