diff options
Diffstat (limited to 'fs/dlm/user.c')
-rw-r--r-- | fs/dlm/user.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 37aad3fe8949..329da1b5285f 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -138,6 +138,35 @@ static void compat_output(struct dlm_lock_result *res, | |||
138 | } | 138 | } |
139 | #endif | 139 | #endif |
140 | 140 | ||
141 | /* Figure out if this lock is at the end of its life and no longer | ||
142 | available for the application to use. The lkb still exists until | ||
143 | the final ast is read. A lock becomes EOL in three situations: | ||
144 | 1. a noqueue request fails with EAGAIN | ||
145 | 2. an unlock completes with EUNLOCK | ||
146 | 3. a cancel of a waiting request completes with ECANCEL/EDEADLK | ||
147 | An EOL lock needs to be removed from the process's list of locks. | ||
148 | And we can't allow any new operation on an EOL lock. This is | ||
149 | not related to the lifetime of the lkb struct which is managed | ||
150 | entirely by refcount. */ | ||
151 | |||
152 | static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type) | ||
153 | { | ||
154 | switch (sb_status) { | ||
155 | case -DLM_EUNLOCK: | ||
156 | return 1; | ||
157 | case -DLM_ECANCEL: | ||
158 | case -ETIMEDOUT: | ||
159 | if (lkb->lkb_grmode == DLM_LOCK_IV) | ||
160 | return 1; | ||
161 | break; | ||
162 | case -EAGAIN: | ||
163 | if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV) | ||
164 | return 1; | ||
165 | break; | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
141 | /* we could possibly check if the cancel of an orphan has resulted in the lkb | 170 | /* we could possibly check if the cancel of an orphan has resulted in the lkb |
142 | being removed and then remove that lkb from the orphans list and free it */ | 171 | being removed and then remove that lkb from the orphans list and free it */ |
143 | 172 | ||
@@ -184,25 +213,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
184 | log_debug(ls, "ast overlap %x status %x %x", | 213 | log_debug(ls, "ast overlap %x status %x %x", |
185 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); | 214 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); |
186 | 215 | ||
187 | /* Figure out if this lock is at the end of its life and no longer | 216 | eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); |
188 | available for the application to use. The lkb still exists until | ||
189 | the final ast is read. A lock becomes EOL in three situations: | ||
190 | 1. a noqueue request fails with EAGAIN | ||
191 | 2. an unlock completes with EUNLOCK | ||
192 | 3. a cancel of a waiting request completes with ECANCEL | ||
193 | An EOL lock needs to be removed from the process's list of locks. | ||
194 | And we can't allow any new operation on an EOL lock. This is | ||
195 | not related to the lifetime of the lkb struct which is managed | ||
196 | entirely by refcount. */ | ||
197 | |||
198 | if (type == AST_COMP && | ||
199 | lkb->lkb_grmode == DLM_LOCK_IV && | ||
200 | ua->lksb.sb_status == -EAGAIN) | ||
201 | eol = 1; | ||
202 | else if (ua->lksb.sb_status == -DLM_EUNLOCK || | ||
203 | (ua->lksb.sb_status == -DLM_ECANCEL && | ||
204 | lkb->lkb_grmode == DLM_LOCK_IV)) | ||
205 | eol = 1; | ||
206 | if (eol) { | 217 | if (eol) { |
207 | lkb->lkb_ast_type &= ~AST_BAST; | 218 | lkb->lkb_ast_type &= ~AST_BAST; |
208 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | 219 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; |