| 760 | } |
| 761 | |
| 762 | void |
| 763 | lf_purgelocks(struct vnode *vp, struct lockf **statep) |
| 764 | { |
| 765 | struct lockf *state; |
| 766 | struct lockf_entry *lock, *nlock; |
| 767 | |
| 768 | /* |
| 769 | * For this to work correctly, the caller must ensure that no |
| 770 | * other threads enter the locking system for this vnode, |
| 771 | * e.g. by checking VIRF_DOOMED. We wake up any threads that are |
| 772 | * sleeping waiting for locks on this vnode and then free all |
| 773 | * the remaining locks. |
| 774 | */ |
| 775 | VI_LOCK(vp); |
| 776 | KASSERT(VN_IS_DOOMED(vp), |
| 777 | ("lf_purgelocks: vp %p has not vgone yet", vp)); |
| 778 | state = *statep; |
| 779 | if (state == NULL) { |
| 780 | VI_UNLOCK(vp); |
| 781 | return; |
| 782 | } |
| 783 | *statep = NULL; |
| 784 | if (LIST_EMPTY(&state->ls_active) && state->ls_threads == 0) { |
| 785 | KASSERT(LIST_EMPTY(&state->ls_pending), |
| 786 | ("freeing state with pending locks")); |
| 787 | VI_UNLOCK(vp); |
| 788 | goto out_free; |
| 789 | } |
| 790 | MPASS(state->ls_threads >= 0); |
| 791 | state->ls_threads++; |
| 792 | VI_UNLOCK(vp); |
| 793 | |
| 794 | sx_xlock(&state->ls_lock); |
| 795 | sx_xlock(&lf_owner_graph_lock); |
| 796 | LIST_FOREACH_SAFE(lock, &state->ls_pending, lf_link, nlock) { |
| 797 | LIST_REMOVE(lock, lf_link); |
| 798 | lf_remove_outgoing(lock); |
| 799 | lf_remove_incoming(lock); |
| 800 | |
| 801 | /* |
| 802 | * If its an async lock, we can just free it |
| 803 | * here, otherwise we let the sleeping thread |
| 804 | * free it. |
| 805 | */ |
| 806 | if (lock->lf_async_task) { |
| 807 | lf_free_lock(lock); |
| 808 | } else { |
| 809 | lock->lf_flags |= F_INTR; |
| 810 | wakeup(lock); |
| 811 | } |
| 812 | } |
| 813 | sx_xunlock(&lf_owner_graph_lock); |
| 814 | sx_xunlock(&state->ls_lock); |
| 815 | |
| 816 | /* |
| 817 | * Wait for all other threads, sleeping and otherwise |
| 818 | * to leave. |
| 819 | */ |
no test coverage detected