* Attempt to record an edge from lock x to lock y. Return EDEADLK if * the new edge would cause a cycle in the owner graph. */
| 903 | * the new edge would cause a cycle in the owner graph. |
| 904 | */ |
| 905 | static int |
| 906 | lf_add_edge(struct lockf_entry *x, struct lockf_entry *y) |
| 907 | { |
| 908 | struct owner_graph *g = &lf_owner_graph; |
| 909 | struct lockf_edge *e; |
| 910 | int error; |
| 911 | |
| 912 | #ifdef DIAGNOSTIC |
| 913 | LIST_FOREACH(e, &x->lf_outedges, le_outlink) |
| 914 | KASSERT(e->le_to != y, ("adding lock edge twice")); |
| 915 | #endif |
| 916 | |
| 917 | /* |
| 918 | * Make sure the two owners have entries in the owner graph. |
| 919 | */ |
| 920 | lf_alloc_vertex(x); |
| 921 | lf_alloc_vertex(y); |
| 922 | |
| 923 | error = graph_add_edge(g, x->lf_owner->lo_vertex, |
| 924 | y->lf_owner->lo_vertex); |
| 925 | if (error) |
| 926 | return (error); |
| 927 | |
| 928 | e = lf_alloc_edge(); |
| 929 | LIST_INSERT_HEAD(&x->lf_outedges, e, le_outlink); |
| 930 | LIST_INSERT_HEAD(&y->lf_inedges, e, le_inlink); |
| 931 | e->le_from = x; |
| 932 | e->le_to = y; |
| 933 | |
| 934 | return (0); |
| 935 | } |
| 936 | |
| 937 | /* |
| 938 | * Remove an edge from the lock graph. |
no test coverage detected