T245: capops: fix distributed delete
[barrelfish] / usr / monitor / capops / delete.c
index 2deba51..104ebc4 100644 (file)
@@ -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);