diff options
| author | David Teigland <teigland@redhat.com> | 2007-03-28 10:56:46 -0400 |
|---|---|---|
| committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-05-01 04:11:00 -0400 |
| commit | ef0c2bb05f40f9a0cd2deae63e199bfa62faa7fa (patch) | |
| tree | df73645f93cfec29fe5b854ff5990a69b03d5c1d | |
| parent | 032067270295cfca11975c0f7b467244aa170c14 (diff) | |
[DLM] overlapping cancel and unlock
Full cancel and force-unlock support. In the past, cancel and force-unlock
wouldn't work if there was another operation in progress on the lock. Now,
both cancel and unlock-force can overlap an operation on a lock, meaning there
may be 2 or 3 operations in progress on a lock in parallel. This support is
important not only because cancel and force-unlock are explicit operations
that an app can use, but both are used implicitly when a process exits while
holding locks.
Summary of changes:
- add-to and remove-from waiters functions were rewritten to handle situations
with more than one remote operation outstanding on a lock
- validate_unlock_args detects when an overlapping cancel/unlock-force
can be sent and when it needs to be delayed until a request/lookup
reply is received
- processing request/lookup replies detects when cancel/unlock-force
occured during the op, and carries out the delayed cancel/unlock-force
- manipulation of the "waiters" (remote operation) state of a lock moved under
the standard rsb mutex that protects all the other lock state
- the two recovery routines related to locks on the waiters list changed
according to the way lkb's are now locked before accessing waiters state
- waiters recovery detects when lkb's being recovered have overlapping
cancel/unlock-force, and may not recover such locks
- revert_lock (cancel) returns a value to distinguish cases where it did
nothing vs cases where it actually did a cancel; the cancel completion ast
should only be done when cancel did something
- orphaned locks put on new list so they can be found later for purging
- cancel must be called on a lock when making it an orphan
- flag user locks (ENDOFLIFE) at the end of their useful life (to the
application) so we can return an error for any further cancel/unlock-force
- we weren't setting COMP/BAST ast flags if one was already set, so we'd lose
either a completion or blocking ast
- clear an unread bast on a lock that's become unlocked
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
| -rw-r--r-- | fs/dlm/dlm_internal.h | 10 | ||||
| -rw-r--r-- | fs/dlm/lock.c | 710 | ||||
| -rw-r--r-- | fs/dlm/lockspace.c | 4 | ||||
| -rw-r--r-- | fs/dlm/user.c | 77 |
4 files changed, 577 insertions, 224 deletions
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index 61d93201e1b2..178931cca67c 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | ******************************************************************************* | 2 | ******************************************************************************* |
| 3 | ** | 3 | ** |
| 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
| 6 | ** | 6 | ** |
| 7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
| 8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
| @@ -210,6 +210,9 @@ struct dlm_args { | |||
| 210 | #define DLM_IFL_MSTCPY 0x00010000 | 210 | #define DLM_IFL_MSTCPY 0x00010000 |
| 211 | #define DLM_IFL_RESEND 0x00020000 | 211 | #define DLM_IFL_RESEND 0x00020000 |
| 212 | #define DLM_IFL_DEAD 0x00040000 | 212 | #define DLM_IFL_DEAD 0x00040000 |
| 213 | #define DLM_IFL_OVERLAP_UNLOCK 0x00080000 | ||
| 214 | #define DLM_IFL_OVERLAP_CANCEL 0x00100000 | ||
| 215 | #define DLM_IFL_ENDOFLIFE 0x00200000 | ||
| 213 | #define DLM_IFL_USER 0x00000001 | 216 | #define DLM_IFL_USER 0x00000001 |
| 214 | #define DLM_IFL_ORPHAN 0x00000002 | 217 | #define DLM_IFL_ORPHAN 0x00000002 |
| 215 | 218 | ||
| @@ -230,8 +233,8 @@ struct dlm_lkb { | |||
| 230 | int8_t lkb_grmode; /* granted lock mode */ | 233 | int8_t lkb_grmode; /* granted lock mode */ |
| 231 | int8_t lkb_bastmode; /* requested mode */ | 234 | int8_t lkb_bastmode; /* requested mode */ |
| 232 | int8_t lkb_highbast; /* highest mode bast sent for */ | 235 | int8_t lkb_highbast; /* highest mode bast sent for */ |
| 233 | |||
| 234 | int8_t lkb_wait_type; /* type of reply waiting for */ | 236 | int8_t lkb_wait_type; /* type of reply waiting for */ |
| 237 | int8_t lkb_wait_count; | ||
| 235 | int8_t lkb_ast_type; /* type of ast queued for */ | 238 | int8_t lkb_ast_type; /* type of ast queued for */ |
| 236 | 239 | ||
| 237 | struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ | 240 | struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ |
| @@ -440,6 +443,9 @@ struct dlm_ls { | |||
| 440 | struct mutex ls_waiters_mutex; | 443 | struct mutex ls_waiters_mutex; |
| 441 | struct list_head ls_waiters; /* lkbs needing a reply */ | 444 | struct list_head ls_waiters; /* lkbs needing a reply */ |
| 442 | 445 | ||
| 446 | struct mutex ls_orphans_mutex; | ||
| 447 | struct list_head ls_orphans; | ||
| 448 | |||
| 443 | struct list_head ls_nodes; /* current nodes in ls */ | 449 | struct list_head ls_nodes; /* current nodes in ls */ |
| 444 | struct list_head ls_nodes_gone; /* dead node list, recovery */ | 450 | struct list_head ls_nodes_gone; /* dead node list, recovery */ |
| 445 | int ls_num_nodes; /* number of nodes in ls */ | 451 | int ls_num_nodes; /* number of nodes in ls */ |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index e725005fafd0..b865a46059dd 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /****************************************************************************** | 1 | /****************************************************************************** |
| 2 | ******************************************************************************* | 2 | ******************************************************************************* |
| 3 | ** | 3 | ** |
| 4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. |
| 5 | ** | 5 | ** |
| 6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
| 7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
| @@ -254,6 +254,22 @@ static inline int down_conversion(struct dlm_lkb *lkb) | |||
| 254 | return (!middle_conversion(lkb) && lkb->lkb_rqmode < lkb->lkb_grmode); | 254 | return (!middle_conversion(lkb) && lkb->lkb_rqmode < lkb->lkb_grmode); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static inline int is_overlap_unlock(struct dlm_lkb *lkb) | ||
| 258 | { | ||
| 259 | return lkb->lkb_flags & DLM_IFL_OVERLAP_UNLOCK; | ||
| 260 | } | ||
| 261 | |||
| 262 | static inline int is_overlap_cancel(struct dlm_lkb *lkb) | ||
| 263 | { | ||
| 264 | return lkb->lkb_flags & DLM_IFL_OVERLAP_CANCEL; | ||
| 265 | } | ||
| 266 | |||
| 267 | static inline int is_overlap(struct dlm_lkb *lkb) | ||
| 268 | { | ||
| 269 | return (lkb->lkb_flags & (DLM_IFL_OVERLAP_UNLOCK | | ||
| 270 | DLM_IFL_OVERLAP_CANCEL)); | ||
| 271 | } | ||
| 272 | |||
| 257 | static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) | 273 | static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) |
| 258 | { | 274 | { |
| 259 | if (is_master_copy(lkb)) | 275 | if (is_master_copy(lkb)) |
| @@ -267,6 +283,12 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) | |||
| 267 | dlm_add_ast(lkb, AST_COMP); | 283 | dlm_add_ast(lkb, AST_COMP); |
| 268 | } | 284 | } |
| 269 | 285 | ||
| 286 | static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) | ||
| 287 | { | ||
| 288 | queue_cast(r, lkb, | ||
| 289 | is_overlap_unlock(lkb) ? -DLM_EUNLOCK : -DLM_ECANCEL); | ||
| 290 | } | ||
| 291 | |||
| 270 | static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode) | 292 | static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode) |
| 271 | { | 293 | { |
| 272 | if (is_master_copy(lkb)) | 294 | if (is_master_copy(lkb)) |
| @@ -547,6 +569,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | |||
| 547 | lkb->lkb_grmode = DLM_LOCK_IV; | 569 | lkb->lkb_grmode = DLM_LOCK_IV; |
| 548 | kref_init(&lkb->lkb_ref); | 570 | kref_init(&lkb->lkb_ref); |
| 549 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); | 571 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); |
| 572 | INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); | ||
| 550 | 573 | ||
| 551 | get_random_bytes(&bucket, sizeof(bucket)); | 574 | get_random_bytes(&bucket, sizeof(bucket)); |
| 552 | bucket &= (ls->ls_lkbtbl_size - 1); | 575 | bucket &= (ls->ls_lkbtbl_size - 1); |
| @@ -735,23 +758,75 @@ static void move_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int sts) | |||
| 735 | unhold_lkb(lkb); | 758 | unhold_lkb(lkb); |
| 736 | } | 759 | } |
| 737 | 760 | ||
| 761 | static int msg_reply_type(int mstype) | ||
| 762 | { | ||
| 763 | switch (mstype) { | ||
| 764 | case DLM_MSG_REQUEST: | ||
| 765 | return DLM_MSG_REQUEST_REPLY; | ||
| 766 | case DLM_MSG_CONVERT: | ||
| 767 | return DLM_MSG_CONVERT_REPLY; | ||
| 768 | case DLM_MSG_UNLOCK: | ||
| 769 | return DLM_MSG_UNLOCK_REPLY; | ||
| 770 | case DLM_MSG_CANCEL: | ||
| 771 | return DLM_MSG_CANCEL_REPLY; | ||
| 772 | case DLM_MSG_LOOKUP: | ||
| 773 | return DLM_MSG_LOOKUP_REPLY; | ||
| 774 | } | ||
| 775 | return -1; | ||
| 776 | } | ||
| 777 | |||
| 738 | /* add/remove lkb from global waiters list of lkb's waiting for | 778 | /* add/remove lkb from global waiters list of lkb's waiting for |
| 739 | a reply from a remote node */ | 779 | a reply from a remote node */ |
| 740 | 780 | ||
| 741 | static void add_to_waiters(struct dlm_lkb *lkb, int mstype) | 781 | static int add_to_waiters(struct dlm_lkb *lkb, int mstype) |
| 742 | { | 782 | { |
| 743 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | 783 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; |
| 784 | int error = 0; | ||
| 744 | 785 | ||
| 745 | mutex_lock(&ls->ls_waiters_mutex); | 786 | mutex_lock(&ls->ls_waiters_mutex); |
| 746 | if (lkb->lkb_wait_type) { | 787 | |
| 747 | log_print("add_to_waiters error %d", lkb->lkb_wait_type); | 788 | if (is_overlap_unlock(lkb) || |
| 789 | (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL))) { | ||
| 790 | error = -EINVAL; | ||
| 791 | goto out; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) { | ||
| 795 | switch (mstype) { | ||
| 796 | case DLM_MSG_UNLOCK: | ||
| 797 | lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; | ||
| 798 | break; | ||
| 799 | case DLM_MSG_CANCEL: | ||
| 800 | lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; | ||
| 801 | break; | ||
| 802 | default: | ||
| 803 | error = -EBUSY; | ||
| 804 | goto out; | ||
| 805 | } | ||
| 806 | lkb->lkb_wait_count++; | ||
| 807 | hold_lkb(lkb); | ||
| 808 | |||
| 809 | log_debug(ls, "add overlap %x cur %d new %d count %d flags %x", | ||
| 810 | lkb->lkb_id, lkb->lkb_wait_type, mstype, | ||
| 811 | lkb->lkb_wait_count, lkb->lkb_flags); | ||
| 748 | goto out; | 812 | goto out; |
| 749 | } | 813 | } |
| 814 | |||
| 815 | DLM_ASSERT(!lkb->lkb_wait_count, | ||
| 816 | dlm_print_lkb(lkb); | ||
| 817 | printk("wait_count %d\n", lkb->lkb_wait_count);); | ||
| 818 | |||
| 819 | lkb->lkb_wait_count++; | ||
| 750 | lkb->lkb_wait_type = mstype; | 820 | lkb->lkb_wait_type = mstype; |
| 751 | kref_get(&lkb->lkb_ref); | 821 | hold_lkb(lkb); |
| 752 | list_add(&lkb->lkb_wait_reply, &ls->ls_waiters); | 822 | list_add(&lkb->lkb_wait_reply, &ls->ls_waiters); |
| 753 | out: | 823 | out: |
| 824 | if (error) | ||
| 825 | log_error(ls, "add_to_waiters %x error %d flags %x %d %d %s", | ||
| 826 | lkb->lkb_id, error, lkb->lkb_flags, mstype, | ||
| 827 | lkb->lkb_wait_type, lkb->lkb_resource->res_name); | ||
| 754 | mutex_unlock(&ls->ls_waiters_mutex); | 828 | mutex_unlock(&ls->ls_waiters_mutex); |
| 829 | return error; | ||
| 755 | } | 830 | } |
| 756 | 831 | ||
| 757 | /* We clear the RESEND flag because we might be taking an lkb off the waiters | 832 | /* We clear the RESEND flag because we might be taking an lkb off the waiters |
| @@ -759,34 +834,85 @@ static void add_to_waiters(struct dlm_lkb *lkb, int mstype) | |||
| 759 | request reply on the requestqueue) between dlm_recover_waiters_pre() which | 834 | request reply on the requestqueue) between dlm_recover_waiters_pre() which |
| 760 | set RESEND and dlm_recover_waiters_post() */ | 835 | set RESEND and dlm_recover_waiters_post() */ |
| 761 | 836 | ||
| 762 | static int _remove_from_waiters(struct dlm_lkb *lkb) | 837 | static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype) |
| 763 | { | 838 | { |
| 764 | int error = 0; | 839 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; |
| 840 | int overlap_done = 0; | ||
| 765 | 841 | ||
| 766 | if (!lkb->lkb_wait_type) { | 842 | if (is_overlap_unlock(lkb) && (mstype == DLM_MSG_UNLOCK_REPLY)) { |
| 767 | log_print("remove_from_waiters error"); | 843 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; |
| 768 | error = -EINVAL; | 844 | overlap_done = 1; |
| 769 | goto out; | 845 | goto out_del; |
| 770 | } | 846 | } |
| 771 | lkb->lkb_wait_type = 0; | 847 | |
| 848 | if (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL_REPLY)) { | ||
| 849 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; | ||
| 850 | overlap_done = 1; | ||
| 851 | goto out_del; | ||
| 852 | } | ||
| 853 | |||
| 854 | /* N.B. type of reply may not always correspond to type of original | ||
| 855 | msg due to lookup->request optimization, verify others? */ | ||
| 856 | |||
| 857 | if (lkb->lkb_wait_type) { | ||
| 858 | lkb->lkb_wait_type = 0; | ||
| 859 | goto out_del; | ||
| 860 | } | ||
| 861 | |||
| 862 | log_error(ls, "remove_from_waiters lkid %x flags %x types %d %d", | ||
| 863 | lkb->lkb_id, lkb->lkb_flags, mstype, lkb->lkb_wait_type); | ||
| 864 | return -1; | ||
| 865 | |||
| 866 | out_del: | ||
| 867 | /* the force-unlock/cancel has completed and we haven't recvd a reply | ||
| 868 | to the op that was in progress prior to the unlock/cancel; we | ||
| 869 | give up on any reply to the earlier op. FIXME: not sure when/how | ||
| 870 | this would happen */ | ||
| 871 | |||
| 872 | if (overlap_done && lkb->lkb_wait_type) { | ||
| 873 | log_error(ls, "remove_from_waiters %x reply %d give up on %d", | ||
| 874 | lkb->lkb_id, mstype, lkb->lkb_wait_type); | ||
| 875 | lkb->lkb_wait_count--; | ||
| 876 | lkb->lkb_wait_type = 0; | ||
| 877 | } | ||
| 878 | |||
| 879 | DLM_ASSERT(lkb->lkb_wait_count, dlm_print_lkb(lkb);); | ||
| 880 | |||
| 772 | lkb->lkb_flags &= ~DLM_IFL_RESEND; | 881 | lkb->lkb_flags &= ~DLM_IFL_RESEND; |
| 773 | list_del(&lkb->lkb_wait_reply); | 882 | lkb->lkb_wait_count--; |
| 883 | if (!lkb->lkb_wait_count) | ||
| 884 | list_del_init(&lkb->lkb_wait_reply); | ||
| 774 | unhold_lkb(lkb); | 885 | unhold_lkb(lkb); |
| 775 | out: | 886 | return 0; |
| 776 | return error; | ||
| 777 | } | 887 | } |
| 778 | 888 | ||
| 779 | static int remove_from_waiters(struct dlm_lkb *lkb) | 889 | static int remove_from_waiters(struct dlm_lkb *lkb, int mstype) |
| 780 | { | 890 | { |
| 781 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | 891 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; |
| 782 | int error; | 892 | int error; |
| 783 | 893 | ||
| 784 | mutex_lock(&ls->ls_waiters_mutex); | 894 | mutex_lock(&ls->ls_waiters_mutex); |
| 785 | error = _remove_from_waiters(lkb); | 895 | error = _remove_from_waiters(lkb, mstype); |
| 786 | mutex_unlock(&ls->ls_waiters_mutex); | 896 | mutex_unlock(&ls->ls_waiters_mutex); |
| 787 | return error; | 897 | return error; |
| 788 | } | 898 | } |
| 789 | 899 | ||
| 900 | /* Handles situations where we might be processing a "fake" or "stub" reply in | ||
| 901 | which we can't try to take waiters_mutex again. */ | ||
| 902 | |||
| 903 | static int remove_from_waiters_ms(struct dlm_lkb *lkb, struct dlm_message *ms) | ||
| 904 | { | ||
| 905 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | ||
| 906 | int error; | ||
| 907 | |||
| 908 | if (ms != &ls->ls_stub_ms) | ||
| 909 | mutex_lock(&ls->ls_waiters_mutex); | ||
| 910 | error = _remove_from_waiters(lkb, ms->m_type); | ||
| 911 | if (ms != &ls->ls_stub_ms) | ||
| 912 | mutex_unlock(&ls->ls_waiters_mutex); | ||
| 913 | return error; | ||
| 914 | } | ||
| 915 | |||
| 790 | static void dir_remove(struct dlm_rsb *r) | 916 | static void dir_remove(struct dlm_rsb *r) |
| 791 | { | 917 | { |
| 792 | int to_nodeid; | 918 | int to_nodeid; |
| @@ -988,8 +1114,14 @@ static void remove_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 988 | _remove_lock(r, lkb); | 1114 | _remove_lock(r, lkb); |
| 989 | } | 1115 | } |
| 990 | 1116 | ||
| 991 | static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1117 | /* returns: 0 did nothing |
| 1118 | 1 moved lock to granted | ||
| 1119 | -1 removed lock */ | ||
| 1120 | |||
| 1121 | static int revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | ||
| 992 | { | 1122 | { |
| 1123 | int rv = 0; | ||
| 1124 | |||
| 993 | lkb->lkb_rqmode = DLM_LOCK_IV; | 1125 | lkb->lkb_rqmode = DLM_LOCK_IV; |
| 994 | 1126 | ||
| 995 | switch (lkb->lkb_status) { | 1127 | switch (lkb->lkb_status) { |
| @@ -997,6 +1129,7 @@ static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 997 | break; | 1129 | break; |
| 998 | case DLM_LKSTS_CONVERT: | 1130 | case DLM_LKSTS_CONVERT: |
| 999 | move_lkb(r, lkb, DLM_LKSTS_GRANTED); | 1131 | move_lkb(r, lkb, DLM_LKSTS_GRANTED); |
| 1132 | rv = 1; | ||
| 1000 | break; | 1133 | break; |
| 1001 | case DLM_LKSTS_WAITING: | 1134 | case DLM_LKSTS_WAITING: |
| 1002 | del_lkb(r, lkb); | 1135 | del_lkb(r, lkb); |
| @@ -1004,15 +1137,17 @@ static void revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 1004 | /* this unhold undoes the original ref from create_lkb() | 1137 | /* this unhold undoes the original ref from create_lkb() |
| 1005 | so this leads to the lkb being freed */ | 1138 | so this leads to the lkb being freed */ |
| 1006 | unhold_lkb(lkb); | 1139 | unhold_lkb(lkb); |
| 1140 | rv = -1; | ||
| 1007 | break; | 1141 | break; |
| 1008 | default: | 1142 | default: |
| 1009 | log_print("invalid status for revert %d", lkb->lkb_status); | 1143 | log_print("invalid status for revert %d", lkb->lkb_status); |
| 1010 | } | 1144 | } |
| 1145 | return rv; | ||
| 1011 | } | 1146 | } |
| 1012 | 1147 | ||
| 1013 | static void revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1148 | static int revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb) |
| 1014 | { | 1149 | { |
| 1015 | revert_lock(r, lkb); | 1150 | return revert_lock(r, lkb); |
| 1016 | } | 1151 | } |
| 1017 | 1152 | ||
| 1018 | static void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1153 | static void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) |
| @@ -1499,7 +1634,7 @@ static void process_lookup_list(struct dlm_rsb *r) | |||
| 1499 | struct dlm_lkb *lkb, *safe; | 1634 | struct dlm_lkb *lkb, *safe; |
| 1500 | 1635 | ||
| 1501 | list_for_each_entry_safe(lkb, safe, &r->res_lookup, lkb_rsb_lookup) { | 1636 | list_for_each_entry_safe(lkb, safe, &r->res_lookup, lkb_rsb_lookup) { |
| 1502 | list_del(&lkb->lkb_rsb_lookup); | 1637 | list_del_init(&lkb->lkb_rsb_lookup); |
| 1503 | _request_lock(r, lkb); | 1638 | _request_lock(r, lkb); |
| 1504 | schedule(); | 1639 | schedule(); |
| 1505 | } | 1640 | } |
| @@ -1530,7 +1665,7 @@ static void confirm_master(struct dlm_rsb *r, int error) | |||
| 1530 | if (!list_empty(&r->res_lookup)) { | 1665 | if (!list_empty(&r->res_lookup)) { |
| 1531 | lkb = list_entry(r->res_lookup.next, struct dlm_lkb, | 1666 | lkb = list_entry(r->res_lookup.next, struct dlm_lkb, |
| 1532 | lkb_rsb_lookup); | 1667 | lkb_rsb_lookup); |
| 1533 | list_del(&lkb->lkb_rsb_lookup); | 1668 | list_del_init(&lkb->lkb_rsb_lookup); |
| 1534 | r->res_first_lkid = lkb->lkb_id; | 1669 | r->res_first_lkid = lkb->lkb_id; |
| 1535 | _request_lock(r, lkb); | 1670 | _request_lock(r, lkb); |
| 1536 | } else | 1671 | } else |
| @@ -1614,6 +1749,9 @@ static int set_unlock_args(uint32_t flags, void *astarg, struct dlm_args *args) | |||
| 1614 | DLM_LKF_FORCEUNLOCK)) | 1749 | DLM_LKF_FORCEUNLOCK)) |
| 1615 | return -EINVAL; | 1750 | return -EINVAL; |
| 1616 | 1751 | ||
| 1752 | if (flags & DLM_LKF_CANCEL && flags & DLM_LKF_FORCEUNLOCK) | ||
| 1753 | return -EINVAL; | ||
| 1754 | |||
| 1617 | args->flags = flags; | 1755 | args->flags = flags; |
| 1618 | args->astparam = (long) astarg; | 1756 | args->astparam = (long) astarg; |
| 1619 | return 0; | 1757 | return 0; |
| @@ -1638,6 +1776,9 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
| 1638 | 1776 | ||
| 1639 | if (lkb->lkb_wait_type) | 1777 | if (lkb->lkb_wait_type) |
| 1640 | goto out; | 1778 | goto out; |
| 1779 | |||
| 1780 | if (is_overlap(lkb)) | ||
| 1781 | goto out; | ||
| 1641 | } | 1782 | } |
| 1642 | 1783 | ||
| 1643 | lkb->lkb_exflags = args->flags; | 1784 | lkb->lkb_exflags = args->flags; |
| @@ -1654,35 +1795,126 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
| 1654 | return rv; | 1795 | return rv; |
| 1655 | } | 1796 | } |
| 1656 | 1797 | ||
| 1798 | /* when dlm_unlock() sees -EBUSY with CANCEL/FORCEUNLOCK it returns 0 | ||
| 1799 | for success */ | ||
| 1800 | |||
| 1801 | /* note: it's valid for lkb_nodeid/res_nodeid to be -1 when we get here | ||
| 1802 | because there may be a lookup in progress and it's valid to do | ||
| 1803 | cancel/unlockf on it */ | ||
| 1804 | |||
| 1657 | static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) | 1805 | static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) |
| 1658 | { | 1806 | { |
| 1807 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | ||
| 1659 | int rv = -EINVAL; | 1808 | int rv = -EINVAL; |
| 1660 | 1809 | ||
| 1661 | if (lkb->lkb_flags & DLM_IFL_MSTCPY) | 1810 | if (lkb->lkb_flags & DLM_IFL_MSTCPY) { |
| 1811 | log_error(ls, "unlock on MSTCPY %x", lkb->lkb_id); | ||
| 1812 | dlm_print_lkb(lkb); | ||
| 1662 | goto out; | 1813 | goto out; |
| 1814 | } | ||
| 1663 | 1815 | ||
| 1664 | if (args->flags & DLM_LKF_FORCEUNLOCK) | 1816 | /* an lkb may still exist even though the lock is EOL'ed due to a |
| 1665 | goto out_ok; | 1817 | cancel, unlock or failed noqueue request; an app can't use these |
| 1818 | locks; return same error as if the lkid had not been found at all */ | ||
| 1666 | 1819 | ||
| 1667 | if (args->flags & DLM_LKF_CANCEL && | 1820 | if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) { |
| 1668 | lkb->lkb_status == DLM_LKSTS_GRANTED) | 1821 | log_debug(ls, "unlock on ENDOFLIFE %x", lkb->lkb_id); |
| 1822 | rv = -ENOENT; | ||
| 1669 | goto out; | 1823 | goto out; |
| 1824 | } | ||
| 1670 | 1825 | ||
| 1671 | if (!(args->flags & DLM_LKF_CANCEL) && | 1826 | /* an lkb may be waiting for an rsb lookup to complete where the |
| 1672 | lkb->lkb_status != DLM_LKSTS_GRANTED) | 1827 | lookup was initiated by another lock */ |
| 1673 | goto out; | 1828 | |
| 1829 | if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) { | ||
| 1830 | if (!list_empty(&lkb->lkb_rsb_lookup)) { | ||
| 1831 | log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id); | ||
| 1832 | list_del_init(&lkb->lkb_rsb_lookup); | ||
| 1833 | queue_cast(lkb->lkb_resource, lkb, | ||
| 1834 | args->flags & DLM_LKF_CANCEL ? | ||
| 1835 | -DLM_ECANCEL : -DLM_EUNLOCK); | ||
| 1836 | unhold_lkb(lkb); /* undoes create_lkb() */ | ||
| 1837 | rv = -EBUSY; | ||
| 1838 | goto out; | ||
| 1839 | } | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | /* cancel not allowed with another cancel/unlock in progress */ | ||
| 1843 | |||
| 1844 | if (args->flags & DLM_LKF_CANCEL) { | ||
| 1845 | if (lkb->lkb_exflags & DLM_LKF_CANCEL) | ||
| 1846 | goto out; | ||
| 1847 | |||
| 1848 | if (is_overlap(lkb)) | ||
| 1849 | goto out; | ||
| 1850 | |||
| 1851 | if (lkb->lkb_flags & DLM_IFL_RESEND) { | ||
| 1852 | lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; | ||
| 1853 | rv = -EBUSY; | ||
| 1854 | goto out; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | switch (lkb->lkb_wait_type) { | ||
| 1858 | case DLM_MSG_LOOKUP: | ||
| 1859 | case DLM_MSG_REQUEST: | ||
| 1860 | lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL; | ||
| 1861 | rv = -EBUSY; | ||
| 1862 | goto out; | ||
| 1863 | case DLM_MSG_UNLOCK: | ||
| 1864 | case DLM_MSG_CANCEL: | ||
| 1865 | goto out; | ||
| 1866 | } | ||
| 1867 | /* add_to_waiters() will set OVERLAP_CANCEL */ | ||
| 1868 | goto out_ok; | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | /* do we need to allow a force-unlock if there's a normal unlock | ||
| 1872 | already in progress? in what conditions could the normal unlock | ||
| 1873 | fail such that we'd want to send a force-unlock to be sure? */ | ||
| 1874 | |||
| 1875 | if (args->flags & DLM_LKF_FORCEUNLOCK) { | ||
| 1876 | if (lkb->lkb_exflags & DLM_LKF_FORCEUNLOCK) | ||
| 1877 | goto out; | ||
| 1878 | |||
| 1879 | if (is_overlap_unlock(lkb)) | ||
| 1880 | goto out; | ||
| 1674 | 1881 | ||
| 1882 | if (lkb->lkb_flags & DLM_IFL_RESEND) { | ||
| 1883 | lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; | ||
| 1884 | rv = -EBUSY; | ||
| 1885 | goto out; | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | switch (lkb->lkb_wait_type) { | ||
| 1889 | case DLM_MSG_LOOKUP: | ||
| 1890 | case DLM_MSG_REQUEST: | ||
| 1891 | lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK; | ||
| 1892 | rv = -EBUSY; | ||
| 1893 | goto out; | ||
| 1894 | case DLM_MSG_UNLOCK: | ||
| 1895 | goto out; | ||
| 1896 | } | ||
| 1897 | /* add_to_waiters() will set OVERLAP_UNLOCK */ | ||
| 1898 | goto out_ok; | ||
| 1899 | } | ||
| 1900 | |||
| 1901 | /* normal unlock not allowed if there's any op in progress */ | ||
| 1675 | rv = -EBUSY; | 1902 | rv = -EBUSY; |
| 1676 | if (lkb->lkb_wait_type) | 1903 | if (lkb->lkb_wait_type || lkb->lkb_wait_count) |
| 1677 | goto out; | 1904 | goto out; |
| 1678 | 1905 | ||
| 1679 | out_ok: | 1906 | out_ok: |
| 1680 | lkb->lkb_exflags = args->flags; | 1907 | /* an overlapping op shouldn't blow away exflags from other op */ |
| 1908 | lkb->lkb_exflags |= args->flags; | ||
| 1681 | lkb->lkb_sbflags = 0; | 1909 | lkb->lkb_sbflags = 0; |
| 1682 | lkb->lkb_astparam = args->astparam; | 1910 | lkb->lkb_astparam = args->astparam; |
| 1683 | |||
| 1684 | rv = 0; | 1911 | rv = 0; |
| 1685 | out: | 1912 | out: |
| 1913 | if (rv) | ||
| 1914 | log_debug(ls, "validate_unlock_args %d %x %x %x %x %d %s", rv, | ||
| 1915 | lkb->lkb_id, lkb->lkb_flags, lkb->lkb_exflags, | ||
| 1916 | args->flags, lkb->lkb_wait_type, | ||
| 1917 | lkb->lkb_resource->res_name); | ||
| 1686 | return rv; | 1918 | return rv; |
| 1687 | } | 1919 | } |
| 1688 | 1920 | ||
| @@ -1759,17 +1991,19 @@ static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 1759 | return -DLM_EUNLOCK; | 1991 | return -DLM_EUNLOCK; |
| 1760 | } | 1992 | } |
| 1761 | 1993 | ||
| 1762 | /* FIXME: if revert_lock() finds that the lkb is granted, we should | 1994 | /* returns: 0 did nothing, -DLM_ECANCEL canceled lock */ |
| 1763 | skip the queue_cast(ECANCEL). It indicates that the request/convert | ||
| 1764 | completed (and queued a normal ast) just before the cancel; we don't | ||
| 1765 | want to clobber the sb_result for the normal ast with ECANCEL. */ | ||
| 1766 | 1995 | ||
| 1767 | static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1996 | static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb) |
| 1768 | { | 1997 | { |
| 1769 | revert_lock(r, lkb); | 1998 | int error; |
| 1770 | queue_cast(r, lkb, -DLM_ECANCEL); | 1999 | |
| 1771 | grant_pending_locks(r); | 2000 | error = revert_lock(r, lkb); |
| 1772 | return -DLM_ECANCEL; | 2001 | if (error) { |
| 2002 | queue_cast(r, lkb, -DLM_ECANCEL); | ||
| 2003 | grant_pending_locks(r); | ||
| 2004 | return -DLM_ECANCEL; | ||
| 2005 | } | ||
| 2006 | return 0; | ||
| 1773 | } | 2007 | } |
| 1774 | 2008 | ||
| 1775 | /* | 2009 | /* |
| @@ -2035,6 +2269,8 @@ int dlm_unlock(dlm_lockspace_t *lockspace, | |||
| 2035 | 2269 | ||
| 2036 | if (error == -DLM_EUNLOCK || error == -DLM_ECANCEL) | 2270 | if (error == -DLM_EUNLOCK || error == -DLM_ECANCEL) |
| 2037 | error = 0; | 2271 | error = 0; |
| 2272 | if (error == -EBUSY && (flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK))) | ||
| 2273 | error = 0; | ||
| 2038 | out_put: | 2274 | out_put: |
| 2039 | dlm_put_lkb(lkb); | 2275 | dlm_put_lkb(lkb); |
| 2040 | out: | 2276 | out: |
| @@ -2176,7 +2412,9 @@ static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype) | |||
| 2176 | struct dlm_mhandle *mh; | 2412 | struct dlm_mhandle *mh; |
| 2177 | int to_nodeid, error; | 2413 | int to_nodeid, error; |
| 2178 | 2414 | ||
| 2179 | add_to_waiters(lkb, mstype); | 2415 | error = add_to_waiters(lkb, mstype); |
| 2416 | if (error) | ||
| 2417 | return error; | ||
| 2180 | 2418 | ||
| 2181 | to_nodeid = r->res_nodeid; | 2419 | to_nodeid = r->res_nodeid; |
| 2182 | 2420 | ||
| @@ -2192,7 +2430,7 @@ static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype) | |||
| 2192 | return 0; | 2430 | return 0; |
| 2193 | 2431 | ||
| 2194 | fail: | 2432 | fail: |
| 2195 | remove_from_waiters(lkb); | 2433 | remove_from_waiters(lkb, msg_reply_type(mstype)); |
| 2196 | return error; | 2434 | return error; |
| 2197 | } | 2435 | } |
| 2198 | 2436 | ||
| @@ -2209,7 +2447,8 @@ static int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 2209 | 2447 | ||
| 2210 | /* down conversions go without a reply from the master */ | 2448 | /* down conversions go without a reply from the master */ |
| 2211 | if (!error && down_conversion(lkb)) { | 2449 | if (!error && down_conversion(lkb)) { |
| 2212 | remove_from_waiters(lkb); | 2450 | remove_from_waiters(lkb, DLM_MSG_CONVERT_REPLY); |
| 2451 | r->res_ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; | ||
| 2213 | r->res_ls->ls_stub_ms.m_result = 0; | 2452 | r->res_ls->ls_stub_ms.m_result = 0; |
| 2214 | r->res_ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 2453 | r->res_ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
| 2215 | __receive_convert_reply(r, lkb, &r->res_ls->ls_stub_ms); | 2454 | __receive_convert_reply(r, lkb, &r->res_ls->ls_stub_ms); |
| @@ -2280,7 +2519,9 @@ static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 2280 | struct dlm_mhandle *mh; | 2519 | struct dlm_mhandle *mh; |
| 2281 | int to_nodeid, error; | 2520 | int to_nodeid, error; |
| 2282 | 2521 | ||
| 2283 | add_to_waiters(lkb, DLM_MSG_LOOKUP); | 2522 | error = add_to_waiters(lkb, DLM_MSG_LOOKUP); |
| 2523 | if (error) | ||
| 2524 | return error; | ||
| 2284 | 2525 | ||
| 2285 | to_nodeid = dlm_dir_nodeid(r); | 2526 | to_nodeid = dlm_dir_nodeid(r); |
| 2286 | 2527 | ||
| @@ -2296,7 +2537,7 @@ static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 2296 | return 0; | 2537 | return 0; |
| 2297 | 2538 | ||
| 2298 | fail: | 2539 | fail: |
| 2299 | remove_from_waiters(lkb); | 2540 | remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY); |
| 2300 | return error; | 2541 | return error; |
| 2301 | } | 2542 | } |
| 2302 | 2543 | ||
| @@ -2740,7 +2981,7 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2740 | { | 2981 | { |
| 2741 | struct dlm_lkb *lkb; | 2982 | struct dlm_lkb *lkb; |
| 2742 | struct dlm_rsb *r; | 2983 | struct dlm_rsb *r; |
| 2743 | int error, mstype; | 2984 | int error, mstype, result; |
| 2744 | 2985 | ||
| 2745 | error = find_lkb(ls, ms->m_remid, &lkb); | 2986 | error = find_lkb(ls, ms->m_remid, &lkb); |
| 2746 | if (error) { | 2987 | if (error) { |
| @@ -2749,20 +2990,15 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2749 | } | 2990 | } |
| 2750 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | 2991 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); |
| 2751 | 2992 | ||
| 2752 | mstype = lkb->lkb_wait_type; | ||
| 2753 | error = remove_from_waiters(lkb); | ||
| 2754 | if (error) { | ||
| 2755 | log_error(ls, "receive_request_reply not on waiters"); | ||
| 2756 | goto out; | ||
| 2757 | } | ||
| 2758 | |||
| 2759 | /* this is the value returned from do_request() on the master */ | ||
| 2760 | error = ms->m_result; | ||
| 2761 | |||
| 2762 | r = lkb->lkb_resource; | 2993 | r = lkb->lkb_resource; |
| 2763 | hold_rsb(r); | 2994 | hold_rsb(r); |
| 2764 | lock_rsb(r); | 2995 | lock_rsb(r); |
| 2765 | 2996 | ||
| 2997 | mstype = lkb->lkb_wait_type; | ||
| 2998 | error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY); | ||
| 2999 | if (error) | ||
| 3000 | goto out; | ||
| 3001 | |||
| 2766 | /* Optimization: the dir node was also the master, so it took our | 3002 | /* Optimization: the dir node was also the master, so it took our |
| 2767 | lookup as a request and sent request reply instead of lookup reply */ | 3003 | lookup as a request and sent request reply instead of lookup reply */ |
| 2768 | if (mstype == DLM_MSG_LOOKUP) { | 3004 | if (mstype == DLM_MSG_LOOKUP) { |
| @@ -2770,14 +3006,15 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2770 | lkb->lkb_nodeid = r->res_nodeid; | 3006 | lkb->lkb_nodeid = r->res_nodeid; |
| 2771 | } | 3007 | } |
| 2772 | 3008 | ||
| 2773 | switch (error) { | 3009 | /* this is the value returned from do_request() on the master */ |
| 3010 | result = ms->m_result; | ||
| 3011 | |||
| 3012 | switch (result) { | ||
| 2774 | case -EAGAIN: | 3013 | case -EAGAIN: |
| 2775 | /* request would block (be queued) on remote master; | 3014 | /* request would block (be queued) on remote master */ |
| 2776 | the unhold undoes the original ref from create_lkb() | ||
| 2777 | so it leads to the lkb being freed */ | ||
| 2778 | queue_cast(r, lkb, -EAGAIN); | 3015 | queue_cast(r, lkb, -EAGAIN); |
| 2779 | confirm_master(r, -EAGAIN); | 3016 | confirm_master(r, -EAGAIN); |
| 2780 | unhold_lkb(lkb); | 3017 | unhold_lkb(lkb); /* undoes create_lkb() */ |
| 2781 | break; | 3018 | break; |
| 2782 | 3019 | ||
| 2783 | case -EINPROGRESS: | 3020 | case -EINPROGRESS: |
| @@ -2785,41 +3022,62 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2785 | /* request was queued or granted on remote master */ | 3022 | /* request was queued or granted on remote master */ |
| 2786 | receive_flags_reply(lkb, ms); | 3023 | receive_flags_reply(lkb, ms); |
| 2787 | lkb->lkb_remid = ms->m_lkid; | 3024 | lkb->lkb_remid = ms->m_lkid; |
| 2788 | if (error) | 3025 | if (result) |
| 2789 | add_lkb(r, lkb, DLM_LKSTS_WAITING); | 3026 | add_lkb(r, lkb, DLM_LKSTS_WAITING); |
| 2790 | else { | 3027 | else { |
| 2791 | grant_lock_pc(r, lkb, ms); | 3028 | grant_lock_pc(r, lkb, ms); |
| 2792 | queue_cast(r, lkb, 0); | 3029 | queue_cast(r, lkb, 0); |
| 2793 | } | 3030 | } |
| 2794 | confirm_master(r, error); | 3031 | confirm_master(r, result); |
| 2795 | break; | 3032 | break; |
| 2796 | 3033 | ||
| 2797 | case -EBADR: | 3034 | case -EBADR: |
| 2798 | case -ENOTBLK: | 3035 | case -ENOTBLK: |
| 2799 | /* find_rsb failed to find rsb or rsb wasn't master */ | 3036 | /* find_rsb failed to find rsb or rsb wasn't master */ |
| 3037 | log_debug(ls, "receive_request_reply %x %x master diff %d %d", | ||
| 3038 | lkb->lkb_id, lkb->lkb_flags, r->res_nodeid, result); | ||
| 2800 | r->res_nodeid = -1; | 3039 | r->res_nodeid = -1; |
| 2801 | lkb->lkb_nodeid = -1; | 3040 | lkb->lkb_nodeid = -1; |
| 2802 | _request_lock(r, lkb); | 3041 | |
| 3042 | if (is_overlap(lkb)) { | ||
| 3043 | /* we'll ignore error in cancel/unlock reply */ | ||
| 3044 | queue_cast_overlap(r, lkb); | ||
| 3045 | unhold_lkb(lkb); /* undoes create_lkb() */ | ||
| 3046 | } else | ||
| 3047 | _request_lock(r, lkb); | ||
| 2803 | break; | 3048 | break; |
| 2804 | 3049 | ||
| 2805 | default: | 3050 | default: |
| 2806 | log_error(ls, "receive_request_reply error %d", error); | 3051 | log_error(ls, "receive_request_reply %x error %d", |
| 3052 | lkb->lkb_id, result); | ||
| 2807 | } | 3053 | } |
| 2808 | 3054 | ||
| 3055 | if (is_overlap_unlock(lkb) && (result == 0 || result == -EINPROGRESS)) { | ||
| 3056 | log_debug(ls, "receive_request_reply %x result %d unlock", | ||
| 3057 | lkb->lkb_id, result); | ||
| 3058 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; | ||
| 3059 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; | ||
| 3060 | send_unlock(r, lkb); | ||
| 3061 | } else if (is_overlap_cancel(lkb) && (result == -EINPROGRESS)) { | ||
| 3062 | log_debug(ls, "receive_request_reply %x cancel", lkb->lkb_id); | ||
| 3063 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; | ||
| 3064 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; | ||
| 3065 | send_cancel(r, lkb); | ||
| 3066 | } else { | ||
| 3067 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; | ||
| 3068 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; | ||
| 3069 | } | ||
| 3070 | out: | ||
| 2809 | unlock_rsb(r); | 3071 | unlock_rsb(r); |
| 2810 | put_rsb(r); | 3072 | put_rsb(r); |
| 2811 | out: | ||
| 2812 | dlm_put_lkb(lkb); | 3073 | dlm_put_lkb(lkb); |
| 2813 | } | 3074 | } |
| 2814 | 3075 | ||
| 2815 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | 3076 | static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, |
| 2816 | struct dlm_message *ms) | 3077 | struct dlm_message *ms) |
| 2817 | { | 3078 | { |
| 2818 | int error = ms->m_result; | ||
| 2819 | |||
| 2820 | /* this is the value returned from do_convert() on the master */ | 3079 | /* this is the value returned from do_convert() on the master */ |
| 2821 | 3080 | switch (ms->m_result) { | |
| 2822 | switch (error) { | ||
| 2823 | case -EAGAIN: | 3081 | case -EAGAIN: |
| 2824 | /* convert would block (be queued) on remote master */ | 3082 | /* convert would block (be queued) on remote master */ |
| 2825 | queue_cast(r, lkb, -EAGAIN); | 3083 | queue_cast(r, lkb, -EAGAIN); |
| @@ -2839,19 +3097,26 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
| 2839 | break; | 3097 | break; |
| 2840 | 3098 | ||
| 2841 | default: | 3099 | default: |
| 2842 | log_error(r->res_ls, "receive_convert_reply error %d", error); | 3100 | log_error(r->res_ls, "receive_convert_reply %x error %d", |
| 3101 | lkb->lkb_id, ms->m_result); | ||
| 2843 | } | 3102 | } |
| 2844 | } | 3103 | } |
| 2845 | 3104 | ||
| 2846 | static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | 3105 | static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms) |
| 2847 | { | 3106 | { |
| 2848 | struct dlm_rsb *r = lkb->lkb_resource; | 3107 | struct dlm_rsb *r = lkb->lkb_resource; |
| 3108 | int error; | ||
| 2849 | 3109 | ||
| 2850 | hold_rsb(r); | 3110 | hold_rsb(r); |
| 2851 | lock_rsb(r); | 3111 | lock_rsb(r); |
| 2852 | 3112 | ||
| 2853 | __receive_convert_reply(r, lkb, ms); | 3113 | /* stub reply can happen with waiters_mutex held */ |
| 3114 | error = remove_from_waiters_ms(lkb, ms); | ||
| 3115 | if (error) | ||
| 3116 | goto out; | ||
| 2854 | 3117 | ||
| 3118 | __receive_convert_reply(r, lkb, ms); | ||
| 3119 | out: | ||
| 2855 | unlock_rsb(r); | 3120 | unlock_rsb(r); |
| 2856 | put_rsb(r); | 3121 | put_rsb(r); |
| 2857 | } | 3122 | } |
| @@ -2868,37 +3133,38 @@ static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2868 | } | 3133 | } |
| 2869 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | 3134 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); |
| 2870 | 3135 | ||
| 2871 | error = remove_from_waiters(lkb); | ||
| 2872 | if (error) { | ||
| 2873 | log_error(ls, "receive_convert_reply not on waiters"); | ||
| 2874 | goto out; | ||
| 2875 | } | ||
| 2876 | |||
| 2877 | _receive_convert_reply(lkb, ms); | 3136 | _receive_convert_reply(lkb, ms); |
| 2878 | out: | ||
| 2879 | dlm_put_lkb(lkb); | 3137 | dlm_put_lkb(lkb); |
| 2880 | } | 3138 | } |
| 2881 | 3139 | ||
| 2882 | static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | 3140 | static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms) |
| 2883 | { | 3141 | { |
| 2884 | struct dlm_rsb *r = lkb->lkb_resource; | 3142 | struct dlm_rsb *r = lkb->lkb_resource; |
| 2885 | int error = ms->m_result; | 3143 | int error; |
| 2886 | 3144 | ||
| 2887 | hold_rsb(r); | 3145 | hold_rsb(r); |
| 2888 | lock_rsb(r); | 3146 | lock_rsb(r); |
| 2889 | 3147 | ||
| 3148 | /* stub reply can happen with waiters_mutex held */ | ||
| 3149 | error = remove_from_waiters_ms(lkb, ms); | ||
| 3150 | if (error) | ||
| 3151 | goto out; | ||
| 3152 | |||
| 2890 | /* this is the value returned from do_unlock() on the master */ | 3153 | /* this is the value returned from do_unlock() on the master */ |
| 2891 | 3154 | ||
| 2892 | switch (error) { | 3155 | switch (ms->m_result) { |
| 2893 | case -DLM_EUNLOCK: | 3156 | case -DLM_EUNLOCK: |
| 2894 | receive_flags_reply(lkb, ms); | 3157 | receive_flags_reply(lkb, ms); |
| 2895 | remove_lock_pc(r, lkb); | 3158 | remove_lock_pc(r, lkb); |
| 2896 | queue_cast(r, lkb, -DLM_EUNLOCK); | 3159 | queue_cast(r, lkb, -DLM_EUNLOCK); |
| 2897 | break; | 3160 | break; |
| 3161 | case -ENOENT: | ||
| 3162 | break; | ||
| 2898 | default: | 3163 | default: |
| 2899 | log_error(r->res_ls, "receive_unlock_reply error %d", error); | 3164 | log_error(r->res_ls, "receive_unlock_reply %x error %d", |
| 3165 | lkb->lkb_id, ms->m_result); | ||
| 2900 | } | 3166 | } |
| 2901 | 3167 | out: | |
| 2902 | unlock_rsb(r); | 3168 | unlock_rsb(r); |
| 2903 | put_rsb(r); | 3169 | put_rsb(r); |
| 2904 | } | 3170 | } |
| @@ -2915,37 +3181,39 @@ static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2915 | } | 3181 | } |
| 2916 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | 3182 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); |
| 2917 | 3183 | ||
| 2918 | error = remove_from_waiters(lkb); | ||
| 2919 | if (error) { | ||
| 2920 | log_error(ls, "receive_unlock_reply not on waiters"); | ||
| 2921 | goto out; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | _receive_unlock_reply(lkb, ms); | 3184 | _receive_unlock_reply(lkb, ms); |
| 2925 | out: | ||
| 2926 | dlm_put_lkb(lkb); | 3185 | dlm_put_lkb(lkb); |
| 2927 | } | 3186 | } |
| 2928 | 3187 | ||
| 2929 | static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | 3188 | static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms) |
| 2930 | { | 3189 | { |
| 2931 | struct dlm_rsb *r = lkb->lkb_resource; | 3190 | struct dlm_rsb *r = lkb->lkb_resource; |
| 2932 | int error = ms->m_result; | 3191 | int error; |
| 2933 | 3192 | ||
| 2934 | hold_rsb(r); | 3193 | hold_rsb(r); |
| 2935 | lock_rsb(r); | 3194 | lock_rsb(r); |
| 2936 | 3195 | ||
| 3196 | /* stub reply can happen with waiters_mutex held */ | ||
| 3197 | error = remove_from_waiters_ms(lkb, ms); | ||
| 3198 | if (error) | ||
| 3199 | goto out; | ||
| 3200 | |||
| 2937 | /* this is the value returned from do_cancel() on the master */ | 3201 | /* this is the value returned from do_cancel() on the master */ |
| 2938 | 3202 | ||
| 2939 | switch (error) { | 3203 | switch (ms->m_result) { |
| 2940 | case -DLM_ECANCEL: | 3204 | case -DLM_ECANCEL: |
| 2941 | receive_flags_reply(lkb, ms); | 3205 | receive_flags_reply(lkb, ms); |
| 2942 | revert_lock_pc(r, lkb); | 3206 | revert_lock_pc(r, lkb); |
| 2943 | queue_cast(r, lkb, -DLM_ECANCEL); | 3207 | if (ms->m_result) |
| 3208 | queue_cast(r, lkb, -DLM_ECANCEL); | ||
| 3209 | break; | ||
| 3210 | case 0: | ||
| 2944 | break; | 3211 | break; |
| 2945 | default: | 3212 | default: |
| 2946 | log_error(r->res_ls, "receive_cancel_reply error %d", error); | 3213 | log_error(r->res_ls, "receive_cancel_reply %x error %d", |
| 3214 | lkb->lkb_id, ms->m_result); | ||
| 2947 | } | 3215 | } |
| 2948 | 3216 | out: | |
| 2949 | unlock_rsb(r); | 3217 | unlock_rsb(r); |
| 2950 | put_rsb(r); | 3218 | put_rsb(r); |
| 2951 | } | 3219 | } |
| @@ -2962,14 +3230,7 @@ static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2962 | } | 3230 | } |
| 2963 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | 3231 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); |
| 2964 | 3232 | ||
| 2965 | error = remove_from_waiters(lkb); | ||
| 2966 | if (error) { | ||
| 2967 | log_error(ls, "receive_cancel_reply not on waiters"); | ||
| 2968 | goto out; | ||
| 2969 | } | ||
| 2970 | |||
| 2971 | _receive_cancel_reply(lkb, ms); | 3233 | _receive_cancel_reply(lkb, ms); |
| 2972 | out: | ||
| 2973 | dlm_put_lkb(lkb); | 3234 | dlm_put_lkb(lkb); |
| 2974 | } | 3235 | } |
| 2975 | 3236 | ||
| @@ -2985,20 +3246,17 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 2985 | return; | 3246 | return; |
| 2986 | } | 3247 | } |
| 2987 | 3248 | ||
| 2988 | error = remove_from_waiters(lkb); | 3249 | /* ms->m_result is the value returned by dlm_dir_lookup on dir node |
| 2989 | if (error) { | ||
| 2990 | log_error(ls, "receive_lookup_reply not on waiters"); | ||
| 2991 | goto out; | ||
| 2992 | } | ||
| 2993 | |||
| 2994 | /* this is the value returned by dlm_dir_lookup on dir node | ||
| 2995 | FIXME: will a non-zero error ever be returned? */ | 3250 | FIXME: will a non-zero error ever be returned? */ |
| 2996 | error = ms->m_result; | ||
| 2997 | 3251 | ||
| 2998 | r = lkb->lkb_resource; | 3252 | r = lkb->lkb_resource; |
| 2999 | hold_rsb(r); | 3253 | hold_rsb(r); |
| 3000 | lock_rsb(r); | 3254 | lock_rsb(r); |
| 3001 | 3255 | ||
| 3256 | error = remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY); | ||
| 3257 | if (error) | ||
| 3258 | goto out; | ||
| 3259 | |||
| 3002 | ret_nodeid = ms->m_nodeid; | 3260 | ret_nodeid = ms->m_nodeid; |
| 3003 | if (ret_nodeid == dlm_our_nodeid()) { | 3261 | if (ret_nodeid == dlm_our_nodeid()) { |
| 3004 | r->res_nodeid = 0; | 3262 | r->res_nodeid = 0; |
| @@ -3009,14 +3267,22 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
| 3009 | r->res_nodeid = ret_nodeid; | 3267 | r->res_nodeid = ret_nodeid; |
| 3010 | } | 3268 | } |
| 3011 | 3269 | ||
| 3270 | if (is_overlap(lkb)) { | ||
| 3271 | log_debug(ls, "receive_lookup_reply %x unlock %x", | ||
| 3272 | lkb->lkb_id, lkb->lkb_flags); | ||
| 3273 | queue_cast_overlap(r, lkb); | ||
| 3274 | unhold_lkb(lkb); /* undoes create_lkb() */ | ||
| 3275 | goto out_list; | ||
| 3276 | } | ||
| 3277 | |||
| 3012 | _request_lock(r, lkb); | 3278 | _request_lock(r, lkb); |
| 3013 | 3279 | ||
| 3280 | out_list: | ||
| 3014 | if (!ret_nodeid) | 3281 | if (!ret_nodeid) |
| 3015 | process_lookup_list(r); | 3282 | process_lookup_list(r); |
| 3016 | 3283 | out: | |
| 3017 | unlock_rsb(r); | 3284 | unlock_rsb(r); |
| 3018 | put_rsb(r); | 3285 | put_rsb(r); |
| 3019 | out: | ||
| 3020 | dlm_put_lkb(lkb); | 3286 | dlm_put_lkb(lkb); |
| 3021 | } | 3287 | } |
| 3022 | 3288 | ||
| @@ -3153,9 +3419,9 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
| 3153 | { | 3419 | { |
| 3154 | if (middle_conversion(lkb)) { | 3420 | if (middle_conversion(lkb)) { |
| 3155 | hold_lkb(lkb); | 3421 | hold_lkb(lkb); |
| 3422 | ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; | ||
| 3156 | ls->ls_stub_ms.m_result = -EINPROGRESS; | 3423 | ls->ls_stub_ms.m_result = -EINPROGRESS; |
| 3157 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3424 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
| 3158 | _remove_from_waiters(lkb); | ||
| 3159 | _receive_convert_reply(lkb, &ls->ls_stub_ms); | 3425 | _receive_convert_reply(lkb, &ls->ls_stub_ms); |
| 3160 | 3426 | ||
| 3161 | /* Same special case as in receive_rcom_lock_args() */ | 3427 | /* Same special case as in receive_rcom_lock_args() */ |
| @@ -3227,18 +3493,18 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) | |||
| 3227 | 3493 | ||
| 3228 | case DLM_MSG_UNLOCK: | 3494 | case DLM_MSG_UNLOCK: |
| 3229 | hold_lkb(lkb); | 3495 | hold_lkb(lkb); |
| 3496 | ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY; | ||
| 3230 | ls->ls_stub_ms.m_result = -DLM_EUNLOCK; | 3497 | ls->ls_stub_ms.m_result = -DLM_EUNLOCK; |
| 3231 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3498 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
| 3232 | _remove_from_waiters(lkb); | ||
| 3233 | _receive_unlock_reply(lkb, &ls->ls_stub_ms); | 3499 | _receive_unlock_reply(lkb, &ls->ls_stub_ms); |
| 3234 | dlm_put_lkb(lkb); | 3500 | dlm_put_lkb(lkb); |
| 3235 | break; | 3501 | break; |
| 3236 | 3502 | ||
| 3237 | case DLM_MSG_CANCEL: | 3503 | case DLM_MSG_CANCEL: |
| 3238 | hold_lkb(lkb); | 3504 | hold_lkb(lkb); |
| 3505 | ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY; | ||
| 3239 | ls->ls_stub_ms.m_result = -DLM_ECANCEL; | 3506 | ls->ls_stub_ms.m_result = -DLM_ECANCEL; |
| 3240 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3507 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
| 3241 | _remove_from_waiters(lkb); | ||
| 3242 | _receive_cancel_reply(lkb, &ls->ls_stub_ms); | 3508 | _receive_cancel_reply(lkb, &ls->ls_stub_ms); |
| 3243 | dlm_put_lkb(lkb); | 3509 | dlm_put_lkb(lkb); |
| 3244 | break; | 3510 | break; |
| @@ -3252,37 +3518,47 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) | |||
| 3252 | mutex_unlock(&ls->ls_waiters_mutex); | 3518 | mutex_unlock(&ls->ls_waiters_mutex); |
| 3253 | } | 3519 | } |
| 3254 | 3520 | ||
| 3255 | static int remove_resend_waiter(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | 3521 | static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls) |
| 3256 | { | 3522 | { |
| 3257 | struct dlm_lkb *lkb; | 3523 | struct dlm_lkb *lkb; |
| 3258 | int rv = 0; | 3524 | int found = 0; |
| 3259 | 3525 | ||
| 3260 | mutex_lock(&ls->ls_waiters_mutex); | 3526 | mutex_lock(&ls->ls_waiters_mutex); |
| 3261 | list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { | 3527 | list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { |
| 3262 | if (lkb->lkb_flags & DLM_IFL_RESEND) { | 3528 | if (lkb->lkb_flags & DLM_IFL_RESEND) { |
| 3263 | rv = lkb->lkb_wait_type; | 3529 | hold_lkb(lkb); |
| 3264 | _remove_from_waiters(lkb); | 3530 | found = 1; |
| 3265 | lkb->lkb_flags &= ~DLM_IFL_RESEND; | ||
| 3266 | break; | 3531 | break; |
| 3267 | } | 3532 | } |
| 3268 | } | 3533 | } |
| 3269 | mutex_unlock(&ls->ls_waiters_mutex); | 3534 | mutex_unlock(&ls->ls_waiters_mutex); |
| 3270 | 3535 | ||
| 3271 | if (!rv) | 3536 | if (!found) |
| 3272 | lkb = NULL; | 3537 | lkb = NULL; |
| 3273 | *lkb_ret = lkb; | 3538 | return lkb; |
| 3274 | return rv; | ||
| 3275 | } | 3539 | } |
| 3276 | 3540 | ||
| 3277 | /* Deal with lookups and lkb's marked RESEND from _pre. We may now be the | 3541 | /* Deal with lookups and lkb's marked RESEND from _pre. We may now be the |
| 3278 | master or dir-node for r. Processing the lkb may result in it being placed | 3542 | master or dir-node for r. Processing the lkb may result in it being placed |
| 3279 | back on waiters. */ | 3543 | back on waiters. */ |
| 3280 | 3544 | ||
| 3545 | /* We do this after normal locking has been enabled and any saved messages | ||
| 3546 | (in requestqueue) have been processed. We should be confident that at | ||
| 3547 | this point we won't get or process a reply to any of these waiting | ||
| 3548 | operations. But, new ops may be coming in on the rsbs/locks here from | ||
| 3549 | userspace or remotely. */ | ||
| 3550 | |||
| 3551 | /* there may have been an overlap unlock/cancel prior to recovery or after | ||
| 3552 | recovery. if before, the lkb may still have a pos wait_count; if after, the | ||
| 3553 | overlap flag would just have been set and nothing new sent. we can be | ||
| 3554 | confident here than any replies to either the initial op or overlap ops | ||
| 3555 | prior to recovery have been received. */ | ||
| 3556 | |||
| 3281 | int dlm_recover_waiters_post(struct dlm_ls *ls) | 3557 | int dlm_recover_waiters_post(struct dlm_ls *ls) |
| 3282 | { | 3558 | { |
| 3283 | struct dlm_lkb *lkb; | 3559 | struct dlm_lkb *lkb; |
| 3284 | struct dlm_rsb *r; | 3560 | struct dlm_rsb *r; |
| 3285 | int error = 0, mstype; | 3561 | int error = 0, mstype, err, oc, ou; |
| 3286 | 3562 | ||
| 3287 | while (1) { | 3563 | while (1) { |
| 3288 | if (dlm_locking_stopped(ls)) { | 3564 | if (dlm_locking_stopped(ls)) { |
| @@ -3291,48 +3567,78 @@ int dlm_recover_waiters_post(struct dlm_ls *ls) | |||
| 3291 | break; | 3567 | break; |
| 3292 | } | 3568 | } |
| 3293 | 3569 | ||
| 3294 | mstype = remove_resend_waiter(ls, &lkb); | 3570 | lkb = find_resend_waiter(ls); |
| 3295 | if (!mstype) | 3571 | if (!lkb) |
| 3296 | break; | 3572 | break; |
| 3297 | 3573 | ||
| 3298 | r = lkb->lkb_resource; | 3574 | r = lkb->lkb_resource; |
| 3575 | hold_rsb(r); | ||
| 3576 | lock_rsb(r); | ||
| 3577 | |||
| 3578 | mstype = lkb->lkb_wait_type; | ||
| 3579 | oc = is_overlap_cancel(lkb); | ||
| 3580 | ou = is_overlap_unlock(lkb); | ||
| 3581 | err = 0; | ||
| 3299 | 3582 | ||
| 3300 | log_debug(ls, "recover_waiters_post %x type %d flags %x %s", | 3583 | log_debug(ls, "recover_waiters_post %x type %d flags %x %s", |
| 3301 | lkb->lkb_id, mstype, lkb->lkb_flags, r->res_name); | 3584 | lkb->lkb_id, mstype, lkb->lkb_flags, r->res_name); |
| 3302 | 3585 | ||
| 3303 | switch (mstype) { | 3586 | /* At this point we assume that we won't get a reply to any |
| 3304 | 3587 | previous op or overlap op on this lock. First, do a big | |
| 3305 | case DLM_MSG_LOOKUP: | 3588 | remove_from_waiters() for all previous ops. */ |
| 3306 | hold_rsb(r); | 3589 | |
| 3307 | lock_rsb(r); | 3590 | lkb->lkb_flags &= ~DLM_IFL_RESEND; |
| 3308 | _request_lock(r, lkb); | 3591 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; |
| 3309 | if (is_master(r)) | 3592 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; |
| 3310 | confirm_master(r, 0); | 3593 | lkb->lkb_wait_type = 0; |
| 3311 | unlock_rsb(r); | 3594 | lkb->lkb_wait_count = 0; |
| 3312 | put_rsb(r); | 3595 | mutex_lock(&ls->ls_waiters_mutex); |
| 3313 | break; | 3596 | list_del_init(&lkb->lkb_wait_reply); |
| 3314 | 3597 | mutex_unlock(&ls->ls_waiters_mutex); | |
| 3315 | case DLM_MSG_REQUEST: | 3598 | unhold_lkb(lkb); /* for waiters list */ |
| 3316 | hold_rsb(r); | 3599 | |
| 3317 | lock_rsb(r); | 3600 | if (oc || ou) { |
| 3318 | _request_lock(r, lkb); | 3601 | /* do an unlock or cancel instead of resending */ |
| 3319 | if (is_master(r)) | 3602 | switch (mstype) { |
| 3320 | confirm_master(r, 0); | 3603 | case DLM_MSG_LOOKUP: |
| 3321 | unlock_rsb(r); | 3604 | case DLM_MSG_REQUEST: |
| 3322 | put_rsb(r); | 3605 | queue_cast(r, lkb, ou ? -DLM_EUNLOCK : |
| 3323 | break; | 3606 | -DLM_ECANCEL); |
| 3324 | 3607 | unhold_lkb(lkb); /* undoes create_lkb() */ | |
| 3325 | case DLM_MSG_CONVERT: | 3608 | break; |
| 3326 | hold_rsb(r); | 3609 | case DLM_MSG_CONVERT: |
| 3327 | lock_rsb(r); | 3610 | if (oc) { |
| 3328 | _convert_lock(r, lkb); | 3611 | queue_cast(r, lkb, -DLM_ECANCEL); |
| 3329 | unlock_rsb(r); | 3612 | } else { |
| 3330 | put_rsb(r); | 3613 | lkb->lkb_exflags |= DLM_LKF_FORCEUNLOCK; |
| 3331 | break; | 3614 | _unlock_lock(r, lkb); |
| 3332 | 3615 | } | |
| 3333 | default: | 3616 | break; |
| 3334 | log_error(ls, "recover_waiters_post type %d", mstype); | 3617 | default: |
| 3618 | err = 1; | ||
| 3619 | } | ||
| 3620 | } else { | ||
| 3621 | switch (mstype) { | ||
| 3622 | case DLM_MSG_LOOKUP: | ||
| 3623 | case DLM_MSG_REQUEST: | ||
| 3624 | _request_lock(r, lkb); | ||
| 3625 | if (is_master(r)) | ||
| 3626 | confirm_master(r, 0); | ||
| 3627 | break; | ||
| 3628 | case DLM_MSG_CONVERT: | ||
| 3629 | _convert_lock(r, lkb); | ||
| 3630 | break; | ||
| 3631 | default: | ||
| 3632 | err = 1; | ||
| 3633 | } | ||
| 3335 | } | 3634 | } |
| 3635 | |||
| 3636 | if (err) | ||
| 3637 | log_error(ls, "recover_waiters_post %x %d %x %d %d", | ||
| 3638 | lkb->lkb_id, mstype, lkb->lkb_flags, oc, ou); | ||
| 3639 | unlock_rsb(r); | ||
| 3640 | put_rsb(r); | ||
| 3641 | dlm_put_lkb(lkb); | ||
| 3336 | } | 3642 | } |
| 3337 | 3643 | ||
| 3338 | return error; | 3644 | return error; |
| @@ -3684,7 +3990,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
| 3684 | 3990 | ||
| 3685 | /* add this new lkb to the per-process list of locks */ | 3991 | /* add this new lkb to the per-process list of locks */ |
| 3686 | spin_lock(&ua->proc->locks_spin); | 3992 | spin_lock(&ua->proc->locks_spin); |
| 3687 | kref_get(&lkb->lkb_ref); | 3993 | hold_lkb(lkb); |
| 3688 | list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); | 3994 | list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); |
| 3689 | spin_unlock(&ua->proc->locks_spin); | 3995 | spin_unlock(&ua->proc->locks_spin); |
| 3690 | out: | 3996 | out: |
| @@ -3774,6 +4080,9 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
| 3774 | 4080 | ||
| 3775 | if (error == -DLM_EUNLOCK) | 4081 | if (error == -DLM_EUNLOCK) |
| 3776 | error = 0; | 4082 | error = 0; |
| 4083 | /* from validate_unlock_args() */ | ||
| 4084 | if (error == -EBUSY && (flags & DLM_LKF_FORCEUNLOCK)) | ||
| 4085 | error = 0; | ||
| 3777 | if (error) | 4086 | if (error) |
| 3778 | goto out_put; | 4087 | goto out_put; |
| 3779 | 4088 | ||
| @@ -3786,6 +4095,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
| 3786 | dlm_put_lkb(lkb); | 4095 | dlm_put_lkb(lkb); |
| 3787 | out: | 4096 | out: |
| 3788 | unlock_recovery(ls); | 4097 | unlock_recovery(ls); |
| 4098 | kfree(ua_tmp); | ||
| 3789 | return error; | 4099 | return error; |
| 3790 | } | 4100 | } |
| 3791 | 4101 | ||
| @@ -3815,33 +4125,37 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
| 3815 | 4125 | ||
| 3816 | if (error == -DLM_ECANCEL) | 4126 | if (error == -DLM_ECANCEL) |
| 3817 | error = 0; | 4127 | error = 0; |
| 3818 | if (error) | 4128 | /* from validate_unlock_args() */ |
| 3819 | goto out_put; | 4129 | if (error == -EBUSY) |
| 3820 | 4130 | error = 0; | |
| 3821 | /* this lkb was removed from the WAITING queue */ | ||
| 3822 | if (lkb->lkb_grmode == DLM_LOCK_IV) { | ||
| 3823 | spin_lock(&ua->proc->locks_spin); | ||
| 3824 | list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking); | ||
| 3825 | spin_unlock(&ua->proc->locks_spin); | ||
| 3826 | } | ||
| 3827 | out_put: | 4131 | out_put: |
| 3828 | dlm_put_lkb(lkb); | 4132 | dlm_put_lkb(lkb); |
| 3829 | out: | 4133 | out: |
| 3830 | unlock_recovery(ls); | 4134 | unlock_recovery(ls); |
| 4135 | kfree(ua_tmp); | ||
| 3831 | return error; | 4136 | return error; |
| 3832 | } | 4137 | } |
| 3833 | 4138 | ||
| 4139 | /* lkb's that are removed from the waiters list by revert are just left on the | ||
| 4140 | orphans list with the granted orphan locks, to be freed by purge */ | ||
| 4141 | |||
| 3834 | static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) | 4142 | static int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) |
| 3835 | { | 4143 | { |
| 3836 | struct dlm_user_args *ua = (struct dlm_user_args *)lkb->lkb_astparam; | 4144 | struct dlm_user_args *ua = (struct dlm_user_args *)lkb->lkb_astparam; |
| 4145 | struct dlm_args args; | ||
| 4146 | int error; | ||
| 3837 | 4147 | ||
| 3838 | if (ua->lksb.sb_lvbptr) | 4148 | hold_lkb(lkb); |
| 3839 | kfree(ua->lksb.sb_lvbptr); | 4149 | mutex_lock(&ls->ls_orphans_mutex); |
| 3840 | kfree(ua); | 4150 | list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); |
| 3841 | lkb->lkb_astparam = (long)NULL; | 4151 | mutex_unlock(&ls->ls_orphans_mutex); |
| 3842 | 4152 | ||
| 3843 | /* TODO: propogate to master if needed */ | 4153 | set_unlock_args(0, ua, &args); |
| 3844 | return 0; | 4154 | |
| 4155 | error = cancel_lock(ls, lkb, &args); | ||
| 4156 | if (error == -DLM_ECANCEL) | ||
| 4157 | error = 0; | ||
| 4158 | return error; | ||
| 3845 | } | 4159 | } |
| 3846 | 4160 | ||
| 3847 | /* The force flag allows the unlock to go ahead even if the lkb isn't granted. | 4161 | /* The force flag allows the unlock to go ahead even if the lkb isn't granted. |
| @@ -3853,10 +4167,6 @@ static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
| 3853 | struct dlm_args args; | 4167 | struct dlm_args args; |
| 3854 | int error; | 4168 | int error; |
| 3855 | 4169 | ||
| 3856 | /* FIXME: we need to handle the case where the lkb is in limbo | ||
| 3857 | while the rsb is being looked up, currently we assert in | ||
| 3858 | _unlock_lock/is_remote because rsb nodeid is -1. */ | ||
| 3859 | |||
| 3860 | set_unlock_args(DLM_LKF_FORCEUNLOCK, ua, &args); | 4170 | set_unlock_args(DLM_LKF_FORCEUNLOCK, ua, &args); |
| 3861 | 4171 | ||
| 3862 | error = unlock_lock(ls, lkb, &args); | 4172 | error = unlock_lock(ls, lkb, &args); |
| @@ -3865,6 +4175,31 @@ static int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
| 3865 | return error; | 4175 | return error; |
| 3866 | } | 4176 | } |
| 3867 | 4177 | ||
| 4178 | /* We have to release clear_proc_locks mutex before calling unlock_proc_lock() | ||
| 4179 | (which does lock_rsb) due to deadlock with receiving a message that does | ||
| 4180 | lock_rsb followed by dlm_user_add_ast() */ | ||
| 4181 | |||
| 4182 | static struct dlm_lkb *del_proc_lock(struct dlm_ls *ls, | ||
| 4183 | struct dlm_user_proc *proc) | ||
| 4184 | { | ||
| 4185 | struct dlm_lkb *lkb = NULL; | ||
| 4186 | |||
| 4187 | mutex_lock(&ls->ls_clear_proc_locks); | ||
| 4188 | if (list_empty(&proc->locks)) | ||
| 4189 | goto out; | ||
| 4190 | |||
| 4191 | lkb = list_entry(proc->locks.next, struct dlm_lkb, lkb_ownqueue); | ||
| 4192 | list_del_init(&lkb->lkb_ownqueue); | ||
| 4193 | |||
| 4194 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) | ||
| 4195 | lkb->lkb_flags |= DLM_IFL_ORPHAN; | ||
| 4196 | else | ||
| 4197 | lkb->lkb_flags |= DLM_IFL_DEAD; | ||
| 4198 | out: | ||
| 4199 | mutex_unlock(&ls->ls_clear_proc_locks); | ||
| 4200 | return lkb; | ||
| 4201 | } | ||
| 4202 | |||
| 3868 | /* The ls_clear_proc_locks mutex protects against dlm_user_add_asts() which | 4203 | /* The ls_clear_proc_locks mutex protects against dlm_user_add_asts() which |
| 3869 | 1) references lkb->ua which we free here and 2) adds lkbs to proc->asts, | 4204 | 1) references lkb->ua which we free here and 2) adds lkbs to proc->asts, |
| 3870 | which we clear here. */ | 4205 | which we clear here. */ |
| @@ -3880,18 +4215,15 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
| 3880 | struct dlm_lkb *lkb, *safe; | 4215 | struct dlm_lkb *lkb, *safe; |
| 3881 | 4216 | ||
| 3882 | lock_recovery(ls); | 4217 | lock_recovery(ls); |
| 3883 | mutex_lock(&ls->ls_clear_proc_locks); | ||
| 3884 | 4218 | ||
| 3885 | list_for_each_entry_safe(lkb, safe, &proc->locks, lkb_ownqueue) { | 4219 | while (1) { |
| 3886 | list_del_init(&lkb->lkb_ownqueue); | 4220 | lkb = del_proc_lock(ls, proc); |
| 3887 | 4221 | if (!lkb) | |
| 3888 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) { | 4222 | break; |
| 3889 | lkb->lkb_flags |= DLM_IFL_ORPHAN; | 4223 | if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) |
| 3890 | orphan_proc_lock(ls, lkb); | 4224 | orphan_proc_lock(ls, lkb); |
| 3891 | } else { | 4225 | else |
| 3892 | lkb->lkb_flags |= DLM_IFL_DEAD; | ||
| 3893 | unlock_proc_lock(ls, lkb); | 4226 | unlock_proc_lock(ls, lkb); |
| 3894 | } | ||
| 3895 | 4227 | ||
| 3896 | /* this removes the reference for the proc->locks list | 4228 | /* this removes the reference for the proc->locks list |
| 3897 | added by dlm_user_request, it may result in the lkb | 4229 | added by dlm_user_request, it may result in the lkb |
| @@ -3900,6 +4232,8 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
| 3900 | dlm_put_lkb(lkb); | 4232 | dlm_put_lkb(lkb); |
| 3901 | } | 4233 | } |
| 3902 | 4234 | ||
| 4235 | mutex_lock(&ls->ls_clear_proc_locks); | ||
| 4236 | |||
| 3903 | /* in-progress unlocks */ | 4237 | /* in-progress unlocks */ |
| 3904 | list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) { | 4238 | list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) { |
| 3905 | list_del_init(&lkb->lkb_ownqueue); | 4239 | list_del_init(&lkb->lkb_ownqueue); |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index f40817b53c6f..f607ca2f0792 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | ******************************************************************************* | 2 | ******************************************************************************* |
| 3 | ** | 3 | ** |
| 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
| 5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
| 6 | ** | 6 | ** |
| 7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
| 8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
| @@ -459,6 +459,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace, | |||
| 459 | 459 | ||
| 460 | INIT_LIST_HEAD(&ls->ls_waiters); | 460 | INIT_LIST_HEAD(&ls->ls_waiters); |
| 461 | mutex_init(&ls->ls_waiters_mutex); | 461 | mutex_init(&ls->ls_waiters_mutex); |
| 462 | INIT_LIST_HEAD(&ls->ls_orphans); | ||
| 463 | mutex_init(&ls->ls_orphans_mutex); | ||
| 462 | 464 | ||
| 463 | INIT_LIST_HEAD(&ls->ls_nodes); | 465 | INIT_LIST_HEAD(&ls->ls_nodes); |
| 464 | INIT_LIST_HEAD(&ls->ls_nodes_gone); | 466 | INIT_LIST_HEAD(&ls->ls_nodes_gone); |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 27a75ce571cf..c978c67b1eff 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2006 Red Hat, Inc. All rights reserved. | 2 | * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This copyrighted material is made available to anyone wishing to use, | 4 | * This copyrighted material is made available to anyone wishing to use, |
| 5 | * modify, copy, or redistribute it subject to the terms and conditions | 5 | * modify, copy, or redistribute it subject to the terms and conditions |
| @@ -128,35 +128,30 @@ static void compat_output(struct dlm_lock_result *res, | |||
| 128 | } | 128 | } |
| 129 | #endif | 129 | #endif |
| 130 | 130 | ||
| 131 | /* we could possibly check if the cancel of an orphan has resulted in the lkb | ||
| 132 | being removed and then remove that lkb from the orphans list and free it */ | ||
| 131 | 133 | ||
| 132 | void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | 134 | void dlm_user_add_ast(struct dlm_lkb *lkb, int type) |
| 133 | { | 135 | { |
| 134 | struct dlm_ls *ls; | 136 | struct dlm_ls *ls; |
| 135 | struct dlm_user_args *ua; | 137 | struct dlm_user_args *ua; |
| 136 | struct dlm_user_proc *proc; | 138 | struct dlm_user_proc *proc; |
| 137 | int remove_ownqueue = 0; | 139 | int eol = 0, ast_type; |
| 138 | 140 | ||
| 139 | /* dlm_clear_proc_locks() sets ORPHAN/DEAD flag on each | 141 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) |
| 140 | lkb before dealing with it. We need to check this | ||
| 141 | flag before taking ls_clear_proc_locks mutex because if | ||
| 142 | it's set, dlm_clear_proc_locks() holds the mutex. */ | ||
| 143 | |||
| 144 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) { | ||
| 145 | /* log_print("user_add_ast skip1 %x", lkb->lkb_flags); */ | ||
| 146 | return; | 142 | return; |
| 147 | } | ||
| 148 | 143 | ||
| 149 | ls = lkb->lkb_resource->res_ls; | 144 | ls = lkb->lkb_resource->res_ls; |
| 150 | mutex_lock(&ls->ls_clear_proc_locks); | 145 | mutex_lock(&ls->ls_clear_proc_locks); |
| 151 | 146 | ||
| 152 | /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast | 147 | /* If ORPHAN/DEAD flag is set, it means the process is dead so an ast |
| 153 | can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed | 148 | can't be delivered. For ORPHAN's, dlm_clear_proc_locks() freed |
| 154 | lkb->ua so we can't try to use it. */ | 149 | lkb->ua so we can't try to use it. This second check is necessary |
| 150 | for cases where a completion ast is received for an operation that | ||
| 151 | began before clear_proc_locks did its cancel/unlock. */ | ||
| 155 | 152 | ||
| 156 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) { | 153 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) |
| 157 | /* log_print("user_add_ast skip2 %x", lkb->lkb_flags); */ | ||
| 158 | goto out; | 154 | goto out; |
| 159 | } | ||
| 160 | 155 | ||
| 161 | DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb);); | 156 | DLM_ASSERT(lkb->lkb_astparam, dlm_print_lkb(lkb);); |
| 162 | ua = (struct dlm_user_args *)lkb->lkb_astparam; | 157 | ua = (struct dlm_user_args *)lkb->lkb_astparam; |
| @@ -166,28 +161,42 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
| 166 | goto out; | 161 | goto out; |
| 167 | 162 | ||
| 168 | spin_lock(&proc->asts_spin); | 163 | spin_lock(&proc->asts_spin); |
| 169 | if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) { | 164 | |
| 165 | ast_type = lkb->lkb_ast_type; | ||
| 166 | lkb->lkb_ast_type |= type; | ||
| 167 | |||
| 168 | if (!ast_type) { | ||
| 170 | kref_get(&lkb->lkb_ref); | 169 | kref_get(&lkb->lkb_ref); |
| 171 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); | 170 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); |
| 172 | lkb->lkb_ast_type |= type; | ||
| 173 | wake_up_interruptible(&proc->wait); | 171 | wake_up_interruptible(&proc->wait); |
| 174 | } | 172 | } |
| 175 | 173 | if (type == AST_COMP && (ast_type & AST_COMP)) | |
| 176 | /* noqueue requests that fail may need to be removed from the | 174 | log_debug(ls, "ast overlap %x status %x %x", |
| 177 | proc's locks list, there should be a better way of detecting | 175 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); |
| 178 | this situation than checking all these things... */ | 176 | |
| 179 | 177 | /* Figure out if this lock is at the end of its life and no longer | |
| 180 | if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV && | 178 | available for the application to use. The lkb still exists until |
| 181 | ua->lksb.sb_status == -EAGAIN && !list_empty(&lkb->lkb_ownqueue)) | 179 | the final ast is read. A lock becomes EOL in three situations: |
| 182 | remove_ownqueue = 1; | 180 | 1. a noqueue request fails with EAGAIN |
| 183 | 181 | 2. an unlock completes with EUNLOCK | |
| 184 | /* unlocks or cancels of waiting requests need to be removed from the | 182 | 3. a cancel of a waiting request completes with ECANCEL |
| 185 | proc's unlocking list, again there must be a better way... */ | 183 | An EOL lock needs to be removed from the process's list of locks. |
| 186 | 184 | And we can't allow any new operation on an EOL lock. This is | |
| 187 | if (ua->lksb.sb_status == -DLM_EUNLOCK || | 185 | not related to the lifetime of the lkb struct which is managed |
| 186 | entirely by refcount. */ | ||
| 187 | |||
| 188 | if (type == AST_COMP && | ||
| 189 | lkb->lkb_grmode == DLM_LOCK_IV && | ||
| 190 | ua->lksb.sb_status == -EAGAIN) | ||
| 191 | eol = 1; | ||
| 192 | else if (ua->lksb.sb_status == -DLM_EUNLOCK || | ||
| 188 | (ua->lksb.sb_status == -DLM_ECANCEL && | 193 | (ua->lksb.sb_status == -DLM_ECANCEL && |
| 189 | lkb->lkb_grmode == DLM_LOCK_IV)) | 194 | lkb->lkb_grmode == DLM_LOCK_IV)) |
| 190 | remove_ownqueue = 1; | 195 | eol = 1; |
| 196 | if (eol) { | ||
| 197 | lkb->lkb_ast_type &= ~AST_BAST; | ||
| 198 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | ||
| 199 | } | ||
| 191 | 200 | ||
| 192 | /* We want to copy the lvb to userspace when the completion | 201 | /* We want to copy the lvb to userspace when the completion |
| 193 | ast is read if the status is 0, the lock has an lvb and | 202 | ast is read if the status is 0, the lock has an lvb and |
| @@ -204,11 +213,13 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
| 204 | 213 | ||
| 205 | spin_unlock(&proc->asts_spin); | 214 | spin_unlock(&proc->asts_spin); |
| 206 | 215 | ||
| 207 | if (remove_ownqueue) { | 216 | if (eol) { |
| 208 | spin_lock(&ua->proc->locks_spin); | 217 | spin_lock(&ua->proc->locks_spin); |
| 209 | list_del_init(&lkb->lkb_ownqueue); | 218 | if (!list_empty(&lkb->lkb_ownqueue)) { |
| 219 | list_del_init(&lkb->lkb_ownqueue); | ||
| 220 | dlm_put_lkb(lkb); | ||
| 221 | } | ||
| 210 | spin_unlock(&ua->proc->locks_spin); | 222 | spin_unlock(&ua->proc->locks_spin); |
| 211 | dlm_put_lkb(lkb); | ||
| 212 | } | 223 | } |
| 213 | out: | 224 | out: |
| 214 | mutex_unlock(&ls->ls_clear_proc_locks); | 225 | mutex_unlock(&ls->ls_clear_proc_locks); |
