* Cancel a pending lock request, either as a result of a signal or a * cancel request for an async lock. */
| 1324 | * cancel request for an async lock. |
| 1325 | */ |
| 1326 | static void |
| 1327 | lf_cancel_lock(struct lockf *state, struct lockf_entry *lock) |
| 1328 | { |
| 1329 | struct lockf_entry_list granted; |
| 1330 | |
| 1331 | /* |
| 1332 | * Note it is theoretically possible that cancelling this lock |
| 1333 | * may allow some other pending lock to become |
| 1334 | * active. Consider this case: |
| 1335 | * |
| 1336 | * Owner Action Result Dependencies |
| 1337 | * |
| 1338 | * A: lock [0..0] succeeds |
| 1339 | * B: lock [2..2] succeeds |
| 1340 | * C: lock [1..2] blocked C->B |
| 1341 | * D: lock [0..1] blocked C->B,D->A,D->C |
| 1342 | * A: unlock [0..0] C->B,D->C |
| 1343 | * C: cancel [1..2] |
| 1344 | */ |
| 1345 | |
| 1346 | LIST_REMOVE(lock, lf_link); |
| 1347 | |
| 1348 | /* |
| 1349 | * Removing out-going edges is simple. |
| 1350 | */ |
| 1351 | sx_xlock(&lf_owner_graph_lock); |
| 1352 | lf_remove_outgoing(lock); |
| 1353 | sx_xunlock(&lf_owner_graph_lock); |
| 1354 | |
| 1355 | /* |
| 1356 | * Removing in-coming edges may allow some other lock to |
| 1357 | * become active - we use lf_update_dependancies to figure |
| 1358 | * this out. |
| 1359 | */ |
| 1360 | LIST_INIT(&granted); |
| 1361 | lf_update_dependancies(state, lock, TRUE, &granted); |
| 1362 | lf_free_lock(lock); |
| 1363 | |
| 1364 | /* |
| 1365 | * Feed any newly active locks to lf_activate_lock. |
| 1366 | */ |
| 1367 | while (!LIST_EMPTY(&granted)) { |
| 1368 | lock = LIST_FIRST(&granted); |
| 1369 | LIST_REMOVE(lock, lf_link); |
| 1370 | lf_activate_lock(state, lock); |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1374 | /* |
| 1375 | * Set a byte-range lock. |
no test coverage detected