* Walk the list of locks for the file and create an out-going edge * from lock to each blocking lock. */
| 983 | * from lock to each blocking lock. |
| 984 | */ |
| 985 | static int |
| 986 | lf_add_outgoing(struct lockf *state, struct lockf_entry *lock) |
| 987 | { |
| 988 | struct lockf_entry *overlap; |
| 989 | int error; |
| 990 | |
| 991 | LIST_FOREACH(overlap, &state->ls_active, lf_link) { |
| 992 | /* |
| 993 | * We may assume that the active list is sorted by |
| 994 | * lf_start. |
| 995 | */ |
| 996 | if (overlap->lf_start > lock->lf_end) |
| 997 | break; |
| 998 | if (!lf_blocks(lock, overlap)) |
| 999 | continue; |
| 1000 | |
| 1001 | /* |
| 1002 | * We've found a blocking lock. Add the corresponding |
| 1003 | * edge to the graphs and see if it would cause a |
| 1004 | * deadlock. |
| 1005 | */ |
| 1006 | error = lf_add_edge(lock, overlap); |
| 1007 | |
| 1008 | /* |
| 1009 | * The only error that lf_add_edge returns is EDEADLK. |
| 1010 | * Remove any edges we added and return the error. |
| 1011 | */ |
| 1012 | if (error) { |
| 1013 | lf_remove_outgoing(lock); |
| 1014 | return (error); |
| 1015 | } |
| 1016 | } |
| 1017 | |
| 1018 | /* |
| 1019 | * We also need to add edges to sleeping locks that block |
| 1020 | * us. This ensures that lf_wakeup_lock cannot grant two |
| 1021 | * mutually blocking locks simultaneously and also enforces a |
| 1022 | * 'first come, first served' fairness model. Note that this |
| 1023 | * only happens if we are blocked by at least one active lock |
| 1024 | * due to the call to lf_getblock in lf_setlock below. |
| 1025 | */ |
| 1026 | LIST_FOREACH(overlap, &state->ls_pending, lf_link) { |
| 1027 | if (!lf_blocks(lock, overlap)) |
| 1028 | continue; |
| 1029 | /* |
| 1030 | * We've found a blocking lock. Add the corresponding |
| 1031 | * edge to the graphs and see if it would cause a |
| 1032 | * deadlock. |
| 1033 | */ |
| 1034 | error = lf_add_edge(lock, overlap); |
| 1035 | |
| 1036 | /* |
| 1037 | * The only error that lf_add_edge returns is EDEADLK. |
| 1038 | * Remove any edges we added and return the error. |
| 1039 | */ |
| 1040 | if (error) { |
| 1041 | lf_remove_outgoing(lock); |
| 1042 | return (error); |
no test coverage detected