From 8778446b6f20ca901a666266b056abd2390452a3 Mon Sep 17 00:00:00 2001 From: Simon Gerber Date: Tue, 2 May 2017 17:30:22 +0200 Subject: [PATCH] T245: capops: fix distributed delete Fix distributed delete for the case where the cap to delete is already locked when we enter capops_delete(). In that case we need to actually continue the delete and queue it for retrying rather than returning the error to the caller. Closes T245. Signed-off-by: Simon Gerber --- usr/monitor/capops/delete.c | 28 ++++++++++++++++++++++------ 1 files changed, 22 insertions(+), 6 deletions(-) diff --git a/usr/monitor/capops/delete.c b/usr/monitor/capops/delete.c index 2deba51..104ebc4 100644 --- a/usr/monitor/capops/delete.c +++ b/usr/monitor/capops/delete.c @@ -410,8 +410,17 @@ delete_trylock_cont(void *st) // entry), but only this function is executed on every unlock event err = dom_cnode_delete(del_st->capref); if (err_no(err) != SYS_ERR_RETRY_THROUGH_MONITOR) { + // If cap is already locked, just enqueue for retry + if (err_no(err) == SYS_ERR_CAP_LOCKED) { + DEBUG_CAPOPS("%s: from cnode_delete(): cap already locked, queuing retry\n", __FUNCTION__); + caplock_wait(del_st->capref, &del_st->lock_qn, + MKCLOSURE(delete_trylock_cont, del_st)); + return; + } + // If cap not found, it has been deleted elsewhere, return OK if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) { - err = SYS_ERR_OK; + DEBUG_CAPOPS("%s: from cnode_delete(): cap not found, got deleted from elsewhere\n", __FUNCTION__); + err = err_push(SYS_ERR_OK, err); } goto report_error; } @@ -487,14 +496,21 @@ capops_delete(struct domcapref cap, // try a simple delete DEBUG_CAPOPS("%s: trying simple delete\n", __FUNCTION__); err = dom_cnode_delete(cap); - if (err_no(err) != SYS_ERR_RETRY_THROUGH_MONITOR) { - DEBUG_CAPOPS("%s: err != RETRY\n", __FUNCTION__); + // We can also continue here if we get SYS_ERR_CAP_LOCKED, as we're going + // to handle already locked caps correctly in delete_trylock_cont(). + // -SG, 2017-05-02 + if (err_no(err) != SYS_ERR_RETRY_THROUGH_MONITOR && + err_no(err) != SYS_ERR_CAP_LOCKED) + { + DEBUG_CAPOPS("%s: err != RETRY && err != LOCKED\n", __FUNCTION__); goto err_cont; } - // simple delete was not able to delete cap as it was last copy and: - // - may have remote copies, need to move or revoke cap - // - contains further slots which need to be cleared + // simple delete was not able to delete cap as: + // * it was last copy and: + // - may have remote copies, need to move or revoke cap + // - contains further slots which need to be cleared + // * currently locked struct delete_st *del_st; err = calloce(1, sizeof(*del_st), &del_st); -- 1.7.2.5