Details
-
Improvement
-
Resolution: Fixed
-
Minor
-
None
-
2
-
4595
Description
It is desirable to allow disabling the client mdc_
{get,put}_rpc_lock() in order to allow clients to send multiple filesystem-modifying RPCs at the same time. While this would break MDS recovery (due to insufficient transaction slots in the MDS last_rcvd file) it would allow a smaller number of clients to generate a much higher RPC load on the MDS. This is ideal for MDS/RPC load testing purposes, and can also be used to help evaluate the potential benefits of implementing the multi-slot last_rcvd feature.
A simple mechanism to do this would be to set the client fail_loc to a specific value, which allows the client to multiple metadata-modifying requests at one time. Some care must be taken when setting and clearing this fail_loc, since it could lead to inconsistencies where mdc_get_rpc_lock() is skipped when the fail_loc is set, but mdc_put_rpc_lock() for that same RPC is run when fail_loc is cleared.
One possibility is something like the following, though there are may others. This implementation:
- ensures that requests sent when OBD_FAIL_MDC_SEM is turned off do not happen concurrent with other requests
- is race free even in the transition period when OBD_FAIL_MDC_SEM is turned on or ff
struct mdc_rpc_lock {
cfs_semaphore_t rpcl_sem;
struct lookup_intent *rpcl_it;
int rpcl_fakes;
};
#define MDC_FAKE_RPCL_IT ((void *)0x2c0012bfUL)
static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck,
struct lookup_intent *it)
{
ENTRY;
if (it == NULL || (it->it_op != IT_GETATTR && it->it_op != IT_LOOKUP)) {
/* This would normally block until the existing request finishes.
* If fail_loc is set it will block until the regular request is
* done, then set rpcl_it to MDC_FAKE_RPCL_IT. Once that is set
* it will only be cleared when all fake requests are finished.
* Only when all fake requests are finished can normal requests
* be sent, to ensure they are recoverable again. */
cfs_down(&lck->rpcl_sem);
if (CFS_FAIL_CHECK(OBD_FAIL_MDC_RPCS_SEM)) {
lck->rpcl_it = MDC_FAKE_RPCL_IT;
lck->rpcl_fakes++
cfs_up(&lck->rpcl_sem);
} else {
/* This will only happen when the CFS_FAIL_CHECK() was
* just turned off but there are still requests in progress.
* Wait until they finish. It doesn't need to be efficient
* in this extremely rare case, just have low overhead in
* the common case when it isn't true. */
while (unlikely(lck->rpcl_it == MDC_FAKE_RPCL_IT))
cfs_schedule_timeout(cfs_time_seconds(1));
LASSERT(lck->rpcl_it == NULL);
lck->rpcl_it = it;
}
}
}
static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck,
struct lookup_intent *it)
{
if (it == NULL || (it->it_op != IT_GETATTR && it->it_op != IT_LOOKUP)) {
if (lck->rpcl_it == MDC_FAKE_RPCL_IT) {
cfs_down(&lck->rpcl_sem);
LASSERTF(lck->rpcl_fakes > 0, "%d\n", lck->rpcl_fakes);
if (--lck->rpcl_fakes == 0) {
lck->rpcl_it = NULL;
}
} else {
LASSERTF(it == lck->rpcl_it, "%p != %p\n", it, lck->rpcl_it);
lck->rpcl_it = NULL;
}
cfs_up(&lck->rpcl_sem);
}
EXIT;
}
Attachments
Issue Links
- is related to
-
LU-5319 Support multiple slots per client in last_rcvd file
-
- Resolved
-