DAOS-18891 object: retry if vos_update_end return -DER_AGAIN#18245
DAOS-18891 object: retry if vos_update_end return -DER_AGAIN#18245Nasf-Fan wants to merge 1 commit into
Conversation
|
Ticket title is 'osa/online_extend.py:OSAOnlineExtend.test_osa_online_extend_drain_after_rebuild - DER_TX_RESTART(-2025)' |
b48fc43 to
3746ad2
Compare
|
Ping reviewers, thanks! |
| end: | ||
| rc = vos_update_end(ioh, ioc.ioc_map_ver, dkey, rc, &ioc.ioc_io_size, NULL); | ||
| if (rc) { | ||
| if (rc == -DER_AGAIN) { |
There was a problem hiding this comment.
It's not accurate to retry on -DER_AGAIN error, the -DER_AGAIN could be returned in some other error code paths. For example: vos_obj_acquire(), vos_dtx_validation(), etc.
What about DER_OVERLOAD_RETRY or a new error code?
There was a problem hiding this comment.
No, it should be -DER_AGAIN, because the object eviction needs not special handling than from vos_obj_acquire() or others, just yield and retry.
There was a problem hiding this comment.
Is it ok to retry when vos_dtx_validation() returns -DER_AGAIN?
There was a problem hiding this comment.
Yes, because the DTX has been aborted by race, for example, the original RPC is timeout and leader abort it. Then when -DER_AGAIN returns back to the leader, leader will retry. If related DTX has already been processed via subsequent resent RPC, then when retry, that can be detected.
So, at least, in theory, it can be retried.
| if (rc == -DER_AGAIN) { | ||
| uint64_t now = daos_gettime_coarse(); | ||
|
|
||
| if (now - ts > 30) { |
There was a problem hiding this comment.
Print warning if retry happened after 30 seconds? That doesn't make sense to me. Why don't we log warning on a certain number of retries?
There was a problem hiding this comment.
Retry number depends on system load and schedule, for example, retrying 100 times may take 10 seconds or may take 1 minute, that is not easy to control, instead, time based warning is more controllable.
| ts = now; | ||
| } | ||
|
|
||
| ABT_thread_yield(); |
There was a problem hiding this comment.
It's not necessary to call this function.
There was a problem hiding this comment.
-DER_AGAIN also can be returned from other cases that someone may still hold reference agains the trouble object. So yield will give chance to them to release related reference. On the other hand, to be safe, yield will avoid system being blocked even if something wrong as to -DER_AGAIN repeatedly returned. So I prefer to keep ABT_thread_yield();.
| if (rc == 0) | ||
| rc = rc1; | ||
|
|
||
| if (rc == -DER_AGAIN) { |
There was a problem hiding this comment.
just confirm that there are some calling of vos_obj_update(), which with call vos_obj_update_ex() -> vos_update_end(). Is it possible get DER_AGAIN for that vos_update_end() and need it handle the err code there?
There was a problem hiding this comment.
Right. I will go through the code and enhance related logic.
There was a problem hiding this comment.
suppose it will be refined in a following PR? thx
3746ad2 to
e0d2a2d
Compare
| entry->ae_cur_stripe.as_hi_epoch, 0, VOS_OF_CRIT, | ||
| &entry->ae_dkey, 1, &iod, iod_csums, &sgl); | ||
|
|
||
| OBJ_CHECK_EAGAIN(rc, ts, "vos_obj_update", entry->ae_oid, again1); |
There was a problem hiding this comment.
for vos_obj_update() and vos_obj_array_remove(), can it just retry inside vos_obj_update_ex() then need not change it everywhere?
There was a problem hiding this comment.
In theory, that is possible, but it is afraid that explicitly yield inside VOS maybe not good practice. That is why I put them inside object module for unification.
| recx.rx_idx = (oer->er_stripenum * recx.rx_nr) | PARITY_INDICATOR; | ||
| rc = vos_obj_array_remove(ioc.ioc_coc->sc_hdl, oer->er_oid, &oer->er_epoch_range, dkey, | ||
| &iod->iod_name, &recx); | ||
| OBJ_CHECK_EAGAIN(rc, ts, "vos_obj_array_remove", oer->er_oid, again); |
There was a problem hiding this comment.
here can retry from "remove_parity"?
| &oea->ea_epoch_range, dkey, | ||
| &iod->iod_name, &recx); | ||
|
|
||
| OBJ_CHECK_EAGAIN(rc1, ts, "vos_obj_array_remove", oea->ea_oid, again); |
There was a problem hiding this comment.
same here, seems only need to retry the vos_obj_array_remove()?
ab09902 to
c4dc277
Compare
|
Ping reviewers! Thanks! |
302ecce to
ae50963
Compare
On server side, for an update operation, there may be CPU yield between related vos_update_begin() and vos_update_end(). During yield interval, the object that is held via vos_update_begin() maybe evicted by others, such as by another failed modification against the same object shard or evicted under md-on-ssd mode. So vos_update_end() logic will check such case and return -DER_AGAIN instead of -DER_TX_RESTART to the caller for notification. And then related caller needs to retry update instead of fail out. The patch also adds initialization for some local varilables in object module to avoid random corruption when handle some failure cases. Signed-off-by: Fan Yong <fan.yong@hpe.com>
ae50963 to
8296fcb
Compare
On server side, for an update operation, there may be CPU yield between related vos_update_begin() and vos_update_end(). During yield interval, the object that is held via vos_update_begin() maybe evicted by others, such as by another failed modification against the same object shard or evicted under md-on-ssd mode. So vos_update_end() logic will check such case and return -DER_AGAIN instead of -DER_TX_RESTART to the caller for notification. And then related caller needs to retry update instead of fail out.
The patch also adds initialization for some local varilables in object module to avoid random corruption when handle some failure cases.
Steps for the author:
After all prior steps are complete: