#define OBD_FAIL_LDLM_NEW_LOCK 0x319
#define OBD_FAIL_LDLM_AGL_DELAY 0x31a
#define OBD_FAIL_LDLM_AGL_NOLOCK 0x31b
+#define OBD_FAIL_LDLM_OST_LVB 0x31c
/* LOCKLESS IO */
#define OBD_FAIL_LDLM_SET_CONTENTION 0x385
void *lvb = req_capsule_client_get(&req->rq_pill, &RMF_DLM_LVB);
lvb_len = ldlm_lvbo_fill(lock, lvb, lvb_len);
- req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB,
- lvb_len, RCL_CLIENT);
+ if (lvb_len < 0) {
+ /* We still need to send the RPC to wake up the blocked
+ * enqueue thread on the client.
+ *
+ * Consider old client, there is no better way to notify
+ * the failure, just zero-sized the LVB, then the client
+ * will fail out as "-EPROTO". */
+ req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB, 0,
+ RCL_CLIENT);
+ instant_cancel = 1;
+ } else {
+ req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB, lvb_len,
+ RCL_CLIENT);
+ }
}
LDLM_DEBUG(lock, "server preparing completion AST (after %lds wait)",
rc = ldlm_ast_fini(req, arg, lock, instant_cancel);
- RETURN(rc);
+ RETURN(lvb_len < 0 ? lvb_len : rc);
}
EXPORT_SYMBOL(ldlm_server_completion_ast);
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);
+ if (buflen >= 0)
+ req_capsule_shrink(&req->rq_pill,
+ &RMF_DLM_LVB,
+ buflen, RCL_SERVER);
+ else
+ rc = buflen;
}
} else {
lock_res_and_lock(lock);
rc = ldlm_fill_lvb(lock, &req->rq_pill, RCL_SERVER,
lock->l_lvb_data, size);
unlock_res_and_lock(lock);
- if (rc < 0)
+ if (rc < 0) {
+ cleanup_phase = 1;
GOTO(cleanup, rc);
+ }
}
if (!is_replay) {
ofd = ldlm_res_to_ns(res)->ns_lvbp;
LASSERT(ofd != NULL);
+ if (OBD_FAIL_CHECK(OBD_FAIL_LDLM_OST_LVB))
+ RETURN(-ENOMEM);
+
rc = lu_env_init(&env, LCT_DT_THREAD);
if (rc)
RETURN(rc);
OBD_ALLOC_PTR(lvb);
if (lvb == NULL)
- RETURN(-ENOMEM);
+ GOTO(out, rc = -ENOMEM);
res->lr_lvb_data = lvb;
res->lr_lvb_len = sizeof(*lvb);
ofd_object_put(&env, fo);
out:
lu_env_fini(&env);
- if (rc)
+ if (rc && lvb != NULL)
OST_LVB_SET_ERR(lvb->lvb_blocks, rc);
/* Don't free lvb data on lookup error */
return rc;
struct ldlm_resource *res = lock->l_resource;
int lvb_len;
+ /* Former lvbo_init not allocate the "LVB". */
+ if (unlikely(res->lr_lvb_len == 0))
+ return 0;
+
lvb_len = ofd_lvbo_size(lock);
LASSERT(lvb_len <= res->lr_lvb_len);
lvb = req_capsule_server_get(&req->rq_pill, &RMF_DLM_LVB);
lvb_len = ldlm_lvbo_size(*lockp);
lvb_len = ldlm_lvbo_fill(*lockp, lvb, lvb_len);
+ if (lvb_len < 0)
+ GOTO(out, rc = lvb_len);
+
req_capsule_shrink(&req->rq_pill, &RMF_DLM_LVB, lvb_len, RCL_SERVER);
EXIT;
out:
}
run_test 231b "must not assert on fully utilized OST request buffer"
+test_232() {
+ mkdir -p $DIR/$tdir
+ #define OBD_FAIL_LDLM_OST_LVB 0x31c
+ $LCTL set_param fail_loc=0x31c
+
+ # ignore dd failure
+ dd if=/dev/zero of=$DIR/$tdir/$tfile bs=1M count=1 || true
+
+ $LCTL set_param fail_loc=0
+ umount_client $MOUNT || error "umount failed"
+ mount_client $MOUNT || error "mount failed"
+}
+run_test 232 "failed lock should not block umount"
+
#
# tests that do cleanup/setup should be run at the end
#