diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:55:11 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:55:11 -0400 |
| commit | 99f4065bac7b8c3f829334b4218a5c2e68cbe440 (patch) | |
| tree | a7a675dc9cdc386abad4c7ce27ef5a8b59e18507 | |
| parent | f539abece1b7e36fae6add4f9ea29203d40badcb (diff) | |
| parent | e43f055a953721ed1787a039ab5e720755596ea2 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm:
dlm: use alloc_workqueue function
dlm: increase default hash table sizes
dlm: record full callback state
| -rw-r--r-- | fs/dlm/ast.c | 257 | ||||
| -rw-r--r-- | fs/dlm/ast.h | 7 | ||||
| -rw-r--r-- | fs/dlm/config.c | 4 | ||||
| -rw-r--r-- | fs/dlm/debug_fs.c | 4 | ||||
| -rw-r--r-- | fs/dlm/dlm_internal.h | 35 | ||||
| -rw-r--r-- | fs/dlm/lock.c | 38 | ||||
| -rw-r--r-- | fs/dlm/lowcomms.c | 6 | ||||
| -rw-r--r-- | fs/dlm/rcom.c | 4 | ||||
| -rw-r--r-- | fs/dlm/user.c | 185 | ||||
| -rw-r--r-- | fs/dlm/user.h | 3 |
10 files changed, 317 insertions, 226 deletions
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c index 4314f0d48d85..abc49f292454 100644 --- a/fs/dlm/ast.c +++ b/fs/dlm/ast.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #define WAKE_ASTS 0 | 19 | #define WAKE_ASTS 0 |
| 20 | 20 | ||
| 21 | static uint64_t ast_seq_count; | ||
| 21 | static struct list_head ast_queue; | 22 | static struct list_head ast_queue; |
| 22 | static spinlock_t ast_queue_lock; | 23 | static spinlock_t ast_queue_lock; |
| 23 | static struct task_struct * astd_task; | 24 | static struct task_struct * astd_task; |
| @@ -25,40 +26,186 @@ static unsigned long astd_wakeflags; | |||
| 25 | static struct mutex astd_running; | 26 | static struct mutex astd_running; |
| 26 | 27 | ||
| 27 | 28 | ||
| 29 | static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb) | ||
| 30 | { | ||
| 31 | int i; | ||
| 32 | |||
| 33 | log_print("last_bast %x %llu flags %x mode %d sb %d %x", | ||
| 34 | lkb->lkb_id, | ||
| 35 | (unsigned long long)lkb->lkb_last_bast.seq, | ||
| 36 | lkb->lkb_last_bast.flags, | ||
| 37 | lkb->lkb_last_bast.mode, | ||
| 38 | lkb->lkb_last_bast.sb_status, | ||
| 39 | lkb->lkb_last_bast.sb_flags); | ||
| 40 | |||
| 41 | log_print("last_cast %x %llu flags %x mode %d sb %d %x", | ||
| 42 | lkb->lkb_id, | ||
| 43 | (unsigned long long)lkb->lkb_last_cast.seq, | ||
| 44 | lkb->lkb_last_cast.flags, | ||
| 45 | lkb->lkb_last_cast.mode, | ||
| 46 | lkb->lkb_last_cast.sb_status, | ||
| 47 | lkb->lkb_last_cast.sb_flags); | ||
| 48 | |||
| 49 | for (i = 0; i < DLM_CALLBACKS_SIZE; i++) { | ||
| 50 | log_print("cb %x %llu flags %x mode %d sb %d %x", | ||
| 51 | lkb->lkb_id, | ||
| 52 | (unsigned long long)lkb->lkb_callbacks[i].seq, | ||
| 53 | lkb->lkb_callbacks[i].flags, | ||
| 54 | lkb->lkb_callbacks[i].mode, | ||
| 55 | lkb->lkb_callbacks[i].sb_status, | ||
| 56 | lkb->lkb_callbacks[i].sb_flags); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 28 | void dlm_del_ast(struct dlm_lkb *lkb) | 60 | void dlm_del_ast(struct dlm_lkb *lkb) |
| 29 | { | 61 | { |
| 30 | spin_lock(&ast_queue_lock); | 62 | spin_lock(&ast_queue_lock); |
| 31 | if (lkb->lkb_ast_type & (AST_COMP | AST_BAST)) | 63 | if (!list_empty(&lkb->lkb_astqueue)) |
| 32 | list_del(&lkb->lkb_astqueue); | 64 | list_del_init(&lkb->lkb_astqueue); |
| 33 | spin_unlock(&ast_queue_lock); | 65 | spin_unlock(&ast_queue_lock); |
| 34 | } | 66 | } |
| 35 | 67 | ||
| 36 | void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode) | 68 | int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode, |
| 69 | int status, uint32_t sbflags, uint64_t seq) | ||
| 37 | { | 70 | { |
| 71 | struct dlm_ls *ls = lkb->lkb_resource->res_ls; | ||
| 72 | uint64_t prev_seq; | ||
| 73 | int prev_mode; | ||
| 74 | int i; | ||
| 75 | |||
| 76 | for (i = 0; i < DLM_CALLBACKS_SIZE; i++) { | ||
| 77 | if (lkb->lkb_callbacks[i].seq) | ||
| 78 | continue; | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Suppress some redundant basts here, do more on removal. | ||
| 82 | * Don't even add a bast if the callback just before it | ||
| 83 | * is a bast for the same mode or a more restrictive mode. | ||
| 84 | * (the addional > PR check is needed for PR/CW inversion) | ||
| 85 | */ | ||
| 86 | |||
| 87 | if ((i > 0) && (flags & DLM_CB_BAST) && | ||
| 88 | (lkb->lkb_callbacks[i-1].flags & DLM_CB_BAST)) { | ||
| 89 | |||
| 90 | prev_seq = lkb->lkb_callbacks[i-1].seq; | ||
| 91 | prev_mode = lkb->lkb_callbacks[i-1].mode; | ||
| 92 | |||
| 93 | if ((prev_mode == mode) || | ||
| 94 | (prev_mode > mode && prev_mode > DLM_LOCK_PR)) { | ||
| 95 | |||
| 96 | log_debug(ls, "skip %x add bast %llu mode %d " | ||
| 97 | "for bast %llu mode %d", | ||
| 98 | lkb->lkb_id, | ||
| 99 | (unsigned long long)seq, | ||
| 100 | mode, | ||
| 101 | (unsigned long long)prev_seq, | ||
| 102 | prev_mode); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | lkb->lkb_callbacks[i].seq = seq; | ||
| 108 | lkb->lkb_callbacks[i].flags = flags; | ||
| 109 | lkb->lkb_callbacks[i].mode = mode; | ||
| 110 | lkb->lkb_callbacks[i].sb_status = status; | ||
| 111 | lkb->lkb_callbacks[i].sb_flags = (sbflags & 0x000000FF); | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | |||
| 115 | if (i == DLM_CALLBACKS_SIZE) { | ||
| 116 | log_error(ls, "no callbacks %x %llu flags %x mode %d sb %d %x", | ||
| 117 | lkb->lkb_id, (unsigned long long)seq, | ||
| 118 | flags, mode, status, sbflags); | ||
| 119 | dlm_dump_lkb_callbacks(lkb); | ||
| 120 | return -1; | ||
| 121 | } | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb, | ||
| 127 | struct dlm_callback *cb, int *resid) | ||
| 128 | { | ||
| 129 | int i; | ||
| 130 | |||
| 131 | *resid = 0; | ||
| 132 | |||
| 133 | if (!lkb->lkb_callbacks[0].seq) | ||
| 134 | return -ENOENT; | ||
| 135 | |||
| 136 | /* oldest undelivered cb is callbacks[0] */ | ||
| 137 | |||
| 138 | memcpy(cb, &lkb->lkb_callbacks[0], sizeof(struct dlm_callback)); | ||
| 139 | memset(&lkb->lkb_callbacks[0], 0, sizeof(struct dlm_callback)); | ||
| 140 | |||
| 141 | /* shift others down */ | ||
| 142 | |||
| 143 | for (i = 1; i < DLM_CALLBACKS_SIZE; i++) { | ||
| 144 | if (!lkb->lkb_callbacks[i].seq) | ||
| 145 | break; | ||
| 146 | memcpy(&lkb->lkb_callbacks[i-1], &lkb->lkb_callbacks[i], | ||
| 147 | sizeof(struct dlm_callback)); | ||
| 148 | memset(&lkb->lkb_callbacks[i], 0, sizeof(struct dlm_callback)); | ||
| 149 | (*resid)++; | ||
| 150 | } | ||
| 151 | |||
| 152 | /* if cb is a bast, it should be skipped if the blocking mode is | ||
| 153 | compatible with the last granted mode */ | ||
| 154 | |||
| 155 | if ((cb->flags & DLM_CB_BAST) && lkb->lkb_last_cast.seq) { | ||
| 156 | if (dlm_modes_compat(cb->mode, lkb->lkb_last_cast.mode)) { | ||
| 157 | cb->flags |= DLM_CB_SKIP; | ||
| 158 | |||
| 159 | log_debug(ls, "skip %x bast %llu mode %d " | ||
| 160 | "for cast %llu mode %d", | ||
| 161 | lkb->lkb_id, | ||
| 162 | (unsigned long long)cb->seq, | ||
| 163 | cb->mode, | ||
| 164 | (unsigned long long)lkb->lkb_last_cast.seq, | ||
| 165 | lkb->lkb_last_cast.mode); | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | if (cb->flags & DLM_CB_CAST) { | ||
| 171 | memcpy(&lkb->lkb_last_cast, cb, sizeof(struct dlm_callback)); | ||
| 172 | lkb->lkb_last_cast_time = ktime_get(); | ||
| 173 | } | ||
| 174 | |||
| 175 | if (cb->flags & DLM_CB_BAST) { | ||
| 176 | memcpy(&lkb->lkb_last_bast, cb, sizeof(struct dlm_callback)); | ||
| 177 | lkb->lkb_last_bast_time = ktime_get(); | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status, | ||
| 184 | uint32_t sbflags) | ||
| 185 | { | ||
| 186 | uint64_t seq; | ||
| 187 | int rv; | ||
| 188 | |||
| 189 | spin_lock(&ast_queue_lock); | ||
| 190 | |||
| 191 | seq = ++ast_seq_count; | ||
| 192 | |||
| 38 | if (lkb->lkb_flags & DLM_IFL_USER) { | 193 | if (lkb->lkb_flags & DLM_IFL_USER) { |
| 39 | dlm_user_add_ast(lkb, type, mode); | 194 | spin_unlock(&ast_queue_lock); |
| 195 | dlm_user_add_ast(lkb, flags, mode, status, sbflags, seq); | ||
| 40 | return; | 196 | return; |
| 41 | } | 197 | } |
| 42 | 198 | ||
| 43 | spin_lock(&ast_queue_lock); | 199 | rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq); |
| 44 | if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) { | 200 | if (rv < 0) { |
| 201 | spin_unlock(&ast_queue_lock); | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (list_empty(&lkb->lkb_astqueue)) { | ||
| 45 | kref_get(&lkb->lkb_ref); | 206 | kref_get(&lkb->lkb_ref); |
| 46 | list_add_tail(&lkb->lkb_astqueue, &ast_queue); | 207 | list_add_tail(&lkb->lkb_astqueue, &ast_queue); |
| 47 | lkb->lkb_ast_first = type; | ||
| 48 | } | 208 | } |
| 49 | |||
| 50 | /* sanity check, this should not happen */ | ||
| 51 | |||
| 52 | if ((type == AST_COMP) && (lkb->lkb_ast_type & AST_COMP)) | ||
| 53 | log_print("repeat cast %d castmode %d lock %x %s", | ||
| 54 | mode, lkb->lkb_castmode, | ||
| 55 | lkb->lkb_id, lkb->lkb_resource->res_name); | ||
| 56 | |||
| 57 | lkb->lkb_ast_type |= type; | ||
| 58 | if (type == AST_BAST) | ||
| 59 | lkb->lkb_bastmode = mode; | ||
| 60 | else | ||
| 61 | lkb->lkb_castmode = mode; | ||
| 62 | spin_unlock(&ast_queue_lock); | 209 | spin_unlock(&ast_queue_lock); |
| 63 | 210 | ||
| 64 | set_bit(WAKE_ASTS, &astd_wakeflags); | 211 | set_bit(WAKE_ASTS, &astd_wakeflags); |
| @@ -72,7 +219,8 @@ static void process_asts(void) | |||
| 72 | struct dlm_lkb *lkb; | 219 | struct dlm_lkb *lkb; |
| 73 | void (*castfn) (void *astparam); | 220 | void (*castfn) (void *astparam); |
| 74 | void (*bastfn) (void *astparam, int mode); | 221 | void (*bastfn) (void *astparam, int mode); |
| 75 | int type, first, bastmode, castmode, do_bast, do_cast, last_castmode; | 222 | struct dlm_callback callbacks[DLM_CALLBACKS_SIZE]; |
| 223 | int i, rv, resid; | ||
| 76 | 224 | ||
| 77 | repeat: | 225 | repeat: |
| 78 | spin_lock(&ast_queue_lock); | 226 | spin_lock(&ast_queue_lock); |
| @@ -83,54 +231,45 @@ repeat: | |||
| 83 | if (dlm_locking_stopped(ls)) | 231 | if (dlm_locking_stopped(ls)) |
| 84 | continue; | 232 | continue; |
| 85 | 233 | ||
| 86 | list_del(&lkb->lkb_astqueue); | 234 | /* we remove from astqueue list and remove everything in |
| 87 | type = lkb->lkb_ast_type; | 235 | lkb_callbacks before releasing the spinlock so empty |
| 88 | lkb->lkb_ast_type = 0; | 236 | lkb_astqueue is always consistent with empty lkb_callbacks */ |
| 89 | first = lkb->lkb_ast_first; | 237 | |
| 90 | lkb->lkb_ast_first = 0; | 238 | list_del_init(&lkb->lkb_astqueue); |
| 91 | bastmode = lkb->lkb_bastmode; | 239 | |
| 92 | castmode = lkb->lkb_castmode; | ||
| 93 | castfn = lkb->lkb_astfn; | 240 | castfn = lkb->lkb_astfn; |
| 94 | bastfn = lkb->lkb_bastfn; | 241 | bastfn = lkb->lkb_bastfn; |
| 95 | spin_unlock(&ast_queue_lock); | ||
| 96 | 242 | ||
| 97 | do_cast = (type & AST_COMP) && castfn; | 243 | memset(&callbacks, 0, sizeof(callbacks)); |
| 98 | do_bast = (type & AST_BAST) && bastfn; | ||
| 99 | 244 | ||
| 100 | /* Skip a bast if its blocking mode is compatible with the | 245 | for (i = 0; i < DLM_CALLBACKS_SIZE; i++) { |
| 101 | granted mode of the preceding cast. */ | 246 | rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid); |
| 247 | if (rv < 0) | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | spin_unlock(&ast_queue_lock); | ||
| 102 | 251 | ||
| 103 | if (do_bast) { | 252 | if (resid) { |
| 104 | if (first == AST_COMP) | 253 | /* shouldn't happen, for loop should have removed all */ |
| 105 | last_castmode = castmode; | 254 | log_error(ls, "callback resid %d lkb %x", |
| 106 | else | 255 | resid, lkb->lkb_id); |
| 107 | last_castmode = lkb->lkb_castmode_done; | ||
| 108 | if (dlm_modes_compat(bastmode, last_castmode)) | ||
| 109 | do_bast = 0; | ||
| 110 | } | 256 | } |
| 111 | 257 | ||
| 112 | if (first == AST_COMP) { | 258 | for (i = 0; i < DLM_CALLBACKS_SIZE; i++) { |
| 113 | if (do_cast) | 259 | if (!callbacks[i].seq) |
| 114 | castfn(lkb->lkb_astparam); | 260 | break; |
| 115 | if (do_bast) | 261 | if (callbacks[i].flags & DLM_CB_SKIP) { |
| 116 | bastfn(lkb->lkb_astparam, bastmode); | 262 | continue; |
| 117 | } else if (first == AST_BAST) { | 263 | } else if (callbacks[i].flags & DLM_CB_BAST) { |
| 118 | if (do_bast) | 264 | bastfn(lkb->lkb_astparam, callbacks[i].mode); |
| 119 | bastfn(lkb->lkb_astparam, bastmode); | 265 | } else if (callbacks[i].flags & DLM_CB_CAST) { |
| 120 | if (do_cast) | 266 | lkb->lkb_lksb->sb_status = callbacks[i].sb_status; |
| 267 | lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags; | ||
| 121 | castfn(lkb->lkb_astparam); | 268 | castfn(lkb->lkb_astparam); |
| 122 | } else { | 269 | } |
| 123 | log_error(ls, "bad ast_first %d ast_type %d", | ||
| 124 | first, type); | ||
| 125 | } | 270 | } |
| 126 | 271 | ||
| 127 | if (do_cast) | 272 | /* removes ref for ast_queue, may cause lkb to be freed */ |
| 128 | lkb->lkb_castmode_done = castmode; | ||
| 129 | if (do_bast) | ||
| 130 | lkb->lkb_bastmode_done = bastmode; | ||
| 131 | |||
| 132 | /* this removes the reference added by dlm_add_ast | ||
| 133 | and may result in the lkb being freed */ | ||
| 134 | dlm_put_lkb(lkb); | 273 | dlm_put_lkb(lkb); |
| 135 | 274 | ||
| 136 | cond_resched(); | 275 | cond_resched(); |
diff --git a/fs/dlm/ast.h b/fs/dlm/ast.h index bcb1aaba519d..8aa89c9b5611 100644 --- a/fs/dlm/ast.h +++ b/fs/dlm/ast.h | |||
| @@ -13,8 +13,13 @@ | |||
| 13 | #ifndef __ASTD_DOT_H__ | 13 | #ifndef __ASTD_DOT_H__ |
| 14 | #define __ASTD_DOT_H__ | 14 | #define __ASTD_DOT_H__ |
| 15 | 15 | ||
| 16 | void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode); | ||
| 17 | void dlm_del_ast(struct dlm_lkb *lkb); | 16 | void dlm_del_ast(struct dlm_lkb *lkb); |
| 17 | int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode, | ||
| 18 | int status, uint32_t sbflags, uint64_t seq); | ||
| 19 | int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb, | ||
| 20 | struct dlm_callback *cb, int *resid); | ||
| 21 | void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status, | ||
| 22 | uint32_t sbflags); | ||
| 18 | 23 | ||
| 19 | void dlm_astd_wake(void); | 24 | void dlm_astd_wake(void); |
| 20 | int dlm_astd_start(void); | 25 | int dlm_astd_start(void); |
diff --git a/fs/dlm/config.c b/fs/dlm/config.c index b54bca03d92f..0d329ff8ed4c 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c | |||
| @@ -977,9 +977,9 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num) | |||
| 977 | /* Config file defaults */ | 977 | /* Config file defaults */ |
| 978 | #define DEFAULT_TCP_PORT 21064 | 978 | #define DEFAULT_TCP_PORT 21064 |
| 979 | #define DEFAULT_BUFFER_SIZE 4096 | 979 | #define DEFAULT_BUFFER_SIZE 4096 |
| 980 | #define DEFAULT_RSBTBL_SIZE 256 | 980 | #define DEFAULT_RSBTBL_SIZE 1024 |
| 981 | #define DEFAULT_LKBTBL_SIZE 1024 | 981 | #define DEFAULT_LKBTBL_SIZE 1024 |
| 982 | #define DEFAULT_DIRTBL_SIZE 512 | 982 | #define DEFAULT_DIRTBL_SIZE 1024 |
| 983 | #define DEFAULT_RECOVER_TIMER 5 | 983 | #define DEFAULT_RECOVER_TIMER 5 |
| 984 | #define DEFAULT_TOSS_SECS 10 | 984 | #define DEFAULT_TOSS_SECS 10 |
| 985 | #define DEFAULT_SCAN_SECS 5 | 985 | #define DEFAULT_SCAN_SECS 5 |
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c index 6b42ba807dfd..59779237e2b4 100644 --- a/fs/dlm/debug_fs.c +++ b/fs/dlm/debug_fs.c | |||
| @@ -257,12 +257,12 @@ static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb, | |||
| 257 | lkb->lkb_status, | 257 | lkb->lkb_status, |
| 258 | lkb->lkb_grmode, | 258 | lkb->lkb_grmode, |
| 259 | lkb->lkb_rqmode, | 259 | lkb->lkb_rqmode, |
| 260 | lkb->lkb_bastmode, | 260 | lkb->lkb_last_bast.mode, |
| 261 | rsb_lookup, | 261 | rsb_lookup, |
| 262 | lkb->lkb_wait_type, | 262 | lkb->lkb_wait_type, |
| 263 | lkb->lkb_lvbseq, | 263 | lkb->lkb_lvbseq, |
| 264 | (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), | 264 | (unsigned long long)ktime_to_ns(lkb->lkb_timestamp), |
| 265 | (unsigned long long)ktime_to_ns(lkb->lkb_time_bast)); | 265 | (unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time)); |
| 266 | return rv; | 266 | return rv; |
| 267 | } | 267 | } |
| 268 | 268 | ||
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index f632b58cd222..b94204913011 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
| @@ -192,11 +192,6 @@ struct dlm_args { | |||
| 192 | * lkb is a process copy, the nodeid specifies the lock master. | 192 | * lkb is a process copy, the nodeid specifies the lock master. |
| 193 | */ | 193 | */ |
| 194 | 194 | ||
| 195 | /* lkb_ast_type */ | ||
| 196 | |||
| 197 | #define AST_COMP 1 | ||
| 198 | #define AST_BAST 2 | ||
| 199 | |||
| 200 | /* lkb_status */ | 195 | /* lkb_status */ |
| 201 | 196 | ||
| 202 | #define DLM_LKSTS_WAITING 1 | 197 | #define DLM_LKSTS_WAITING 1 |
| @@ -217,6 +212,20 @@ struct dlm_args { | |||
| 217 | #define DLM_IFL_USER 0x00000001 | 212 | #define DLM_IFL_USER 0x00000001 |
| 218 | #define DLM_IFL_ORPHAN 0x00000002 | 213 | #define DLM_IFL_ORPHAN 0x00000002 |
| 219 | 214 | ||
| 215 | #define DLM_CALLBACKS_SIZE 6 | ||
| 216 | |||
| 217 | #define DLM_CB_CAST 0x00000001 | ||
| 218 | #define DLM_CB_BAST 0x00000002 | ||
| 219 | #define DLM_CB_SKIP 0x00000004 | ||
| 220 | |||
| 221 | struct dlm_callback { | ||
| 222 | uint64_t seq; | ||
| 223 | uint32_t flags; /* DLM_CBF_ */ | ||
| 224 | int sb_status; /* copy to lksb status */ | ||
| 225 | uint8_t sb_flags; /* copy to lksb flags */ | ||
| 226 | int8_t mode; /* rq mode of bast, gr mode of cast */ | ||
| 227 | }; | ||
| 228 | |||
| 220 | struct dlm_lkb { | 229 | struct dlm_lkb { |
| 221 | struct dlm_rsb *lkb_resource; /* the rsb */ | 230 | struct dlm_rsb *lkb_resource; /* the rsb */ |
| 222 | struct kref lkb_ref; | 231 | struct kref lkb_ref; |
| @@ -236,13 +245,6 @@ struct dlm_lkb { | |||
| 236 | 245 | ||
| 237 | int8_t lkb_wait_type; /* type of reply waiting for */ | 246 | int8_t lkb_wait_type; /* type of reply waiting for */ |
| 238 | int8_t lkb_wait_count; | 247 | int8_t lkb_wait_count; |
| 239 | int8_t lkb_ast_type; /* type of ast queued for */ | ||
| 240 | int8_t lkb_ast_first; /* type of first ast queued */ | ||
| 241 | |||
| 242 | int8_t lkb_bastmode; /* req mode of queued bast */ | ||
| 243 | int8_t lkb_castmode; /* gr mode of queued cast */ | ||
| 244 | int8_t lkb_bastmode_done; /* last delivered bastmode */ | ||
| 245 | int8_t lkb_castmode_done; /* last delivered castmode */ | ||
| 246 | 248 | ||
| 247 | struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ | 249 | struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ |
| 248 | struct list_head lkb_statequeue; /* rsb g/c/w list */ | 250 | struct list_head lkb_statequeue; /* rsb g/c/w list */ |
| @@ -251,10 +253,15 @@ struct dlm_lkb { | |||
| 251 | struct list_head lkb_astqueue; /* need ast to be sent */ | 253 | struct list_head lkb_astqueue; /* need ast to be sent */ |
| 252 | struct list_head lkb_ownqueue; /* list of locks for a process */ | 254 | struct list_head lkb_ownqueue; /* list of locks for a process */ |
| 253 | struct list_head lkb_time_list; | 255 | struct list_head lkb_time_list; |
| 254 | ktime_t lkb_time_bast; /* for debugging */ | ||
| 255 | ktime_t lkb_timestamp; | 256 | ktime_t lkb_timestamp; |
| 256 | unsigned long lkb_timeout_cs; | 257 | unsigned long lkb_timeout_cs; |
| 257 | 258 | ||
| 259 | struct dlm_callback lkb_callbacks[DLM_CALLBACKS_SIZE]; | ||
| 260 | struct dlm_callback lkb_last_cast; | ||
| 261 | struct dlm_callback lkb_last_bast; | ||
| 262 | ktime_t lkb_last_cast_time; /* for debugging */ | ||
| 263 | ktime_t lkb_last_bast_time; /* for debugging */ | ||
| 264 | |||
| 258 | char *lkb_lvbptr; | 265 | char *lkb_lvbptr; |
| 259 | struct dlm_lksb *lkb_lksb; /* caller's status block */ | 266 | struct dlm_lksb *lkb_lksb; /* caller's status block */ |
| 260 | void (*lkb_astfn) (void *astparam); | 267 | void (*lkb_astfn) (void *astparam); |
| @@ -544,8 +551,6 @@ struct dlm_user_args { | |||
| 544 | (dlm_user_proc) on the struct file, | 551 | (dlm_user_proc) on the struct file, |
| 545 | the process's locks point back to it*/ | 552 | the process's locks point back to it*/ |
| 546 | struct dlm_lksb lksb; | 553 | struct dlm_lksb lksb; |
| 547 | int old_mode; | ||
| 548 | int update_user_lvb; | ||
| 549 | struct dlm_lksb __user *user_lksb; | 554 | struct dlm_lksb __user *user_lksb; |
| 550 | void __user *castparam; | 555 | void __user *castparam; |
| 551 | void __user *castaddr; | 556 | void __user *castaddr; |
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 64e5f3efdd81..04b8c449303f 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -160,10 +160,10 @@ static const int __quecvt_compat_matrix[8][8] = { | |||
| 160 | void dlm_print_lkb(struct dlm_lkb *lkb) | 160 | void dlm_print_lkb(struct dlm_lkb *lkb) |
| 161 | { | 161 | { |
| 162 | printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x\n" | 162 | printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x\n" |
| 163 | " status %d rqmode %d grmode %d wait_type %d ast_type %d\n", | 163 | " status %d rqmode %d grmode %d wait_type %d\n", |
| 164 | lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags, | 164 | lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags, |
| 165 | lkb->lkb_flags, lkb->lkb_status, lkb->lkb_rqmode, | 165 | lkb->lkb_flags, lkb->lkb_status, lkb->lkb_rqmode, |
| 166 | lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_ast_type); | 166 | lkb->lkb_grmode, lkb->lkb_wait_type); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | static void dlm_print_rsb(struct dlm_rsb *r) | 169 | static void dlm_print_rsb(struct dlm_rsb *r) |
| @@ -305,10 +305,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) | |||
| 305 | rv = -EDEADLK; | 305 | rv = -EDEADLK; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | lkb->lkb_lksb->sb_status = rv; | 308 | dlm_add_ast(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags); |
| 309 | lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags; | ||
| 310 | |||
| 311 | dlm_add_ast(lkb, AST_COMP, lkb->lkb_grmode); | ||
| 312 | } | 309 | } |
| 313 | 310 | ||
| 314 | static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) | 311 | static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) |
| @@ -319,13 +316,10 @@ static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
| 319 | 316 | ||
| 320 | static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode) | 317 | static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode) |
| 321 | { | 318 | { |
| 322 | lkb->lkb_time_bast = ktime_get(); | ||
| 323 | |||
| 324 | if (is_master_copy(lkb)) { | 319 | if (is_master_copy(lkb)) { |
| 325 | lkb->lkb_bastmode = rqmode; /* printed by debugfs */ | ||
| 326 | send_bast(r, lkb, rqmode); | 320 | send_bast(r, lkb, rqmode); |
| 327 | } else { | 321 | } else { |
| 328 | dlm_add_ast(lkb, AST_BAST, rqmode); | 322 | dlm_add_ast(lkb, DLM_CB_BAST, rqmode, 0, 0); |
| 329 | } | 323 | } |
| 330 | } | 324 | } |
| 331 | 325 | ||
| @@ -600,6 +594,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | |||
| 600 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); | 594 | INIT_LIST_HEAD(&lkb->lkb_ownqueue); |
| 601 | INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); | 595 | INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); |
| 602 | INIT_LIST_HEAD(&lkb->lkb_time_list); | 596 | INIT_LIST_HEAD(&lkb->lkb_time_list); |
| 597 | INIT_LIST_HEAD(&lkb->lkb_astqueue); | ||
| 603 | 598 | ||
| 604 | get_random_bytes(&bucket, sizeof(bucket)); | 599 | get_random_bytes(&bucket, sizeof(bucket)); |
| 605 | bucket &= (ls->ls_lkbtbl_size - 1); | 600 | bucket &= (ls->ls_lkbtbl_size - 1); |
| @@ -2819,9 +2814,9 @@ static void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
| 2819 | not from lkb fields */ | 2814 | not from lkb fields */ |
| 2820 | 2815 | ||
| 2821 | if (lkb->lkb_bastfn) | 2816 | if (lkb->lkb_bastfn) |
| 2822 | ms->m_asts |= AST_BAST; | 2817 | ms->m_asts |= DLM_CB_BAST; |
| 2823 | if (lkb->lkb_astfn) | 2818 | if (lkb->lkb_astfn) |
| 2824 | ms->m_asts |= AST_COMP; | 2819 | ms->m_asts |= DLM_CB_CAST; |
| 2825 | 2820 | ||
| 2826 | /* compare with switch in create_message; send_remove() doesn't | 2821 | /* compare with switch in create_message; send_remove() doesn't |
| 2827 | use send_args() */ | 2822 | use send_args() */ |
| @@ -3122,8 +3117,8 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
| 3122 | lkb->lkb_grmode = DLM_LOCK_IV; | 3117 | lkb->lkb_grmode = DLM_LOCK_IV; |
| 3123 | lkb->lkb_rqmode = ms->m_rqmode; | 3118 | lkb->lkb_rqmode = ms->m_rqmode; |
| 3124 | 3119 | ||
| 3125 | lkb->lkb_bastfn = (ms->m_asts & AST_BAST) ? &fake_bastfn : NULL; | 3120 | lkb->lkb_bastfn = (ms->m_asts & DLM_CB_BAST) ? &fake_bastfn : NULL; |
| 3126 | lkb->lkb_astfn = (ms->m_asts & AST_COMP) ? &fake_astfn : NULL; | 3121 | lkb->lkb_astfn = (ms->m_asts & DLM_CB_CAST) ? &fake_astfn : NULL; |
| 3127 | 3122 | ||
| 3128 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { | 3123 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { |
| 3129 | /* lkb was just created so there won't be an lvb yet */ | 3124 | /* lkb was just created so there won't be an lvb yet */ |
| @@ -4412,8 +4407,8 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
| 4412 | lkb->lkb_grmode = rl->rl_grmode; | 4407 | lkb->lkb_grmode = rl->rl_grmode; |
| 4413 | /* don't set lkb_status because add_lkb wants to itself */ | 4408 | /* don't set lkb_status because add_lkb wants to itself */ |
| 4414 | 4409 | ||
| 4415 | lkb->lkb_bastfn = (rl->rl_asts & AST_BAST) ? &fake_bastfn : NULL; | 4410 | lkb->lkb_bastfn = (rl->rl_asts & DLM_CB_BAST) ? &fake_bastfn : NULL; |
| 4416 | lkb->lkb_astfn = (rl->rl_asts & AST_COMP) ? &fake_astfn : NULL; | 4411 | lkb->lkb_astfn = (rl->rl_asts & DLM_CB_CAST) ? &fake_astfn : NULL; |
| 4417 | 4412 | ||
| 4418 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { | 4413 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { |
| 4419 | int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - | 4414 | int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - |
| @@ -4589,7 +4584,6 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
| 4589 | error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs, | 4584 | error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs, |
| 4590 | fake_astfn, ua, fake_bastfn, &args); | 4585 | fake_astfn, ua, fake_bastfn, &args); |
| 4591 | lkb->lkb_flags |= DLM_IFL_USER; | 4586 | lkb->lkb_flags |= DLM_IFL_USER; |
| 4592 | ua->old_mode = DLM_LOCK_IV; | ||
| 4593 | 4587 | ||
| 4594 | if (error) { | 4588 | if (error) { |
| 4595 | __put_lkb(ls, lkb); | 4589 | __put_lkb(ls, lkb); |
| @@ -4658,7 +4652,6 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, | |||
| 4658 | ua->bastparam = ua_tmp->bastparam; | 4652 | ua->bastparam = ua_tmp->bastparam; |
| 4659 | ua->bastaddr = ua_tmp->bastaddr; | 4653 | ua->bastaddr = ua_tmp->bastaddr; |
| 4660 | ua->user_lksb = ua_tmp->user_lksb; | 4654 | ua->user_lksb = ua_tmp->user_lksb; |
| 4661 | ua->old_mode = lkb->lkb_grmode; | ||
| 4662 | 4655 | ||
| 4663 | error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs, | 4656 | error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs, |
| 4664 | fake_astfn, ua, fake_bastfn, &args); | 4657 | fake_astfn, ua, fake_bastfn, &args); |
| @@ -4917,8 +4910,9 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
| 4917 | } | 4910 | } |
| 4918 | 4911 | ||
| 4919 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { | 4912 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { |
| 4920 | lkb->lkb_ast_type = 0; | 4913 | memset(&lkb->lkb_callbacks, 0, |
| 4921 | list_del(&lkb->lkb_astqueue); | 4914 | sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE); |
| 4915 | list_del_init(&lkb->lkb_astqueue); | ||
| 4922 | dlm_put_lkb(lkb); | 4916 | dlm_put_lkb(lkb); |
| 4923 | } | 4917 | } |
| 4924 | 4918 | ||
| @@ -4958,7 +4952,9 @@ static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
| 4958 | 4952 | ||
| 4959 | spin_lock(&proc->asts_spin); | 4953 | spin_lock(&proc->asts_spin); |
| 4960 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { | 4954 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { |
| 4961 | list_del(&lkb->lkb_astqueue); | 4955 | memset(&lkb->lkb_callbacks, 0, |
| 4956 | sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE); | ||
| 4957 | list_del_init(&lkb->lkb_astqueue); | ||
| 4962 | dlm_put_lkb(lkb); | 4958 | dlm_put_lkb(lkb); |
| 4963 | } | 4959 | } |
| 4964 | spin_unlock(&proc->asts_spin); | 4960 | spin_unlock(&proc->asts_spin); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 2d8c87b951c2..bffa1e73b9a9 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
| @@ -1468,13 +1468,15 @@ static void work_stop(void) | |||
| 1468 | 1468 | ||
| 1469 | static int work_start(void) | 1469 | static int work_start(void) |
| 1470 | { | 1470 | { |
| 1471 | recv_workqueue = create_singlethread_workqueue("dlm_recv"); | 1471 | recv_workqueue = alloc_workqueue("dlm_recv", |
| 1472 | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
| 1472 | if (!recv_workqueue) { | 1473 | if (!recv_workqueue) { |
| 1473 | log_print("can't start dlm_recv"); | 1474 | log_print("can't start dlm_recv"); |
| 1474 | return -ENOMEM; | 1475 | return -ENOMEM; |
| 1475 | } | 1476 | } |
| 1476 | 1477 | ||
| 1477 | send_workqueue = create_singlethread_workqueue("dlm_send"); | 1478 | send_workqueue = alloc_workqueue("dlm_send", |
| 1479 | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); | ||
| 1478 | if (!send_workqueue) { | 1480 | if (!send_workqueue) { |
| 1479 | log_print("can't start dlm_send"); | 1481 | log_print("can't start dlm_send"); |
| 1480 | destroy_workqueue(recv_workqueue); | 1482 | destroy_workqueue(recv_workqueue); |
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index 3c83a49a48a3..f10a50f24e8f 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
| @@ -321,9 +321,9 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
| 321 | rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type); | 321 | rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type); |
| 322 | 322 | ||
| 323 | if (lkb->lkb_bastfn) | 323 | if (lkb->lkb_bastfn) |
| 324 | rl->rl_asts |= AST_BAST; | 324 | rl->rl_asts |= DLM_CB_BAST; |
| 325 | if (lkb->lkb_astfn) | 325 | if (lkb->lkb_astfn) |
| 326 | rl->rl_asts |= AST_COMP; | 326 | rl->rl_asts |= DLM_CB_CAST; |
| 327 | 327 | ||
| 328 | rl->rl_namelen = cpu_to_le16(r->res_length); | 328 | rl->rl_namelen = cpu_to_le16(r->res_length); |
| 329 | memcpy(rl->rl_name, r->res_name, r->res_length); | 329 | memcpy(rl->rl_name, r->res_name, r->res_length); |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 66d6c16bf440..d5ab3fe7c198 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "lock.h" | 24 | #include "lock.h" |
| 25 | #include "lvb_table.h" | 25 | #include "lvb_table.h" |
| 26 | #include "user.h" | 26 | #include "user.h" |
| 27 | #include "ast.h" | ||
| 27 | 28 | ||
| 28 | static const char name_prefix[] = "dlm"; | 29 | static const char name_prefix[] = "dlm"; |
| 29 | static const struct file_operations device_fops; | 30 | static const struct file_operations device_fops; |
| @@ -152,19 +153,16 @@ static void compat_output(struct dlm_lock_result *res, | |||
| 152 | not related to the lifetime of the lkb struct which is managed | 153 | not related to the lifetime of the lkb struct which is managed |
| 153 | entirely by refcount. */ | 154 | entirely by refcount. */ |
| 154 | 155 | ||
| 155 | static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type) | 156 | static int lkb_is_endoflife(int mode, int status) |
| 156 | { | 157 | { |
| 157 | switch (sb_status) { | 158 | switch (status) { |
| 158 | case -DLM_EUNLOCK: | 159 | case -DLM_EUNLOCK: |
| 159 | return 1; | 160 | return 1; |
| 160 | case -DLM_ECANCEL: | 161 | case -DLM_ECANCEL: |
| 161 | case -ETIMEDOUT: | 162 | case -ETIMEDOUT: |
| 162 | case -EDEADLK: | 163 | case -EDEADLK: |
| 163 | if (lkb->lkb_grmode == DLM_LOCK_IV) | ||
| 164 | return 1; | ||
| 165 | break; | ||
| 166 | case -EAGAIN: | 164 | case -EAGAIN: |
| 167 | if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV) | 165 | if (mode == DLM_LOCK_IV) |
| 168 | return 1; | 166 | return 1; |
| 169 | break; | 167 | break; |
| 170 | } | 168 | } |
| @@ -174,12 +172,13 @@ static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type) | |||
| 174 | /* we could possibly check if the cancel of an orphan has resulted in the lkb | 172 | /* we could possibly check if the cancel of an orphan has resulted in the lkb |
| 175 | being removed and then remove that lkb from the orphans list and free it */ | 173 | being removed and then remove that lkb from the orphans list and free it */ |
| 176 | 174 | ||
| 177 | void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode) | 175 | void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, |
| 176 | int status, uint32_t sbflags, uint64_t seq) | ||
| 178 | { | 177 | { |
| 179 | struct dlm_ls *ls; | 178 | struct dlm_ls *ls; |
| 180 | struct dlm_user_args *ua; | 179 | struct dlm_user_args *ua; |
| 181 | struct dlm_user_proc *proc; | 180 | struct dlm_user_proc *proc; |
| 182 | int eol = 0, ast_type; | 181 | int rv; |
| 183 | 182 | ||
| 184 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) | 183 | if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD)) |
| 185 | return; | 184 | return; |
| @@ -200,49 +199,29 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode) | |||
| 200 | ua = lkb->lkb_ua; | 199 | ua = lkb->lkb_ua; |
| 201 | proc = ua->proc; | 200 | proc = ua->proc; |
| 202 | 201 | ||
| 203 | if (type == AST_BAST && ua->bastaddr == NULL) | 202 | if ((flags & DLM_CB_BAST) && ua->bastaddr == NULL) |
| 204 | goto out; | 203 | goto out; |
| 205 | 204 | ||
| 205 | if ((flags & DLM_CB_CAST) && lkb_is_endoflife(mode, status)) | ||
| 206 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | ||
| 207 | |||
| 206 | spin_lock(&proc->asts_spin); | 208 | spin_lock(&proc->asts_spin); |
| 207 | 209 | ||
| 208 | ast_type = lkb->lkb_ast_type; | 210 | rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq); |
| 209 | lkb->lkb_ast_type |= type; | 211 | if (rv < 0) { |
| 210 | if (type == AST_BAST) | 212 | spin_unlock(&proc->asts_spin); |
| 211 | lkb->lkb_bastmode = mode; | 213 | goto out; |
| 212 | else | 214 | } |
| 213 | lkb->lkb_castmode = mode; | ||
| 214 | 215 | ||
| 215 | if (!ast_type) { | 216 | if (list_empty(&lkb->lkb_astqueue)) { |
| 216 | kref_get(&lkb->lkb_ref); | 217 | kref_get(&lkb->lkb_ref); |
| 217 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); | 218 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); |
| 218 | lkb->lkb_ast_first = type; | ||
| 219 | wake_up_interruptible(&proc->wait); | 219 | wake_up_interruptible(&proc->wait); |
| 220 | } | 220 | } |
| 221 | if (type == AST_COMP && (ast_type & AST_COMP)) | ||
| 222 | log_debug(ls, "ast overlap %x status %x %x", | ||
| 223 | lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags); | ||
| 224 | |||
| 225 | eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); | ||
| 226 | if (eol) { | ||
| 227 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* We want to copy the lvb to userspace when the completion | ||
| 231 | ast is read if the status is 0, the lock has an lvb and | ||
| 232 | lvb_ops says we should. We could probably have set_lvb_lock() | ||
| 233 | set update_user_lvb instead and not need old_mode */ | ||
| 234 | |||
| 235 | if ((lkb->lkb_ast_type & AST_COMP) && | ||
| 236 | (lkb->lkb_lksb->sb_status == 0) && | ||
| 237 | lkb->lkb_lksb->sb_lvbptr && | ||
| 238 | dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1]) | ||
| 239 | ua->update_user_lvb = 1; | ||
| 240 | else | ||
| 241 | ua->update_user_lvb = 0; | ||
| 242 | |||
| 243 | spin_unlock(&proc->asts_spin); | 221 | spin_unlock(&proc->asts_spin); |
| 244 | 222 | ||
| 245 | if (eol) { | 223 | if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) { |
| 224 | /* N.B. spin_lock locks_spin, not asts_spin */ | ||
| 246 | spin_lock(&proc->locks_spin); | 225 | spin_lock(&proc->locks_spin); |
| 247 | if (!list_empty(&lkb->lkb_ownqueue)) { | 226 | if (!list_empty(&lkb->lkb_ownqueue)) { |
| 248 | list_del_init(&lkb->lkb_ownqueue); | 227 | list_del_init(&lkb->lkb_ownqueue); |
| @@ -705,8 +684,9 @@ static int device_close(struct inode *inode, struct file *file) | |||
| 705 | return 0; | 684 | return 0; |
| 706 | } | 685 | } |
| 707 | 686 | ||
| 708 | static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | 687 | static int copy_result_to_user(struct dlm_user_args *ua, int compat, |
| 709 | int mode, char __user *buf, size_t count) | 688 | uint32_t flags, int mode, int copy_lvb, |
| 689 | char __user *buf, size_t count) | ||
| 710 | { | 690 | { |
| 711 | #ifdef CONFIG_COMPAT | 691 | #ifdef CONFIG_COMPAT |
| 712 | struct dlm_lock_result32 result32; | 692 | struct dlm_lock_result32 result32; |
| @@ -730,7 +710,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
| 730 | notes that a new blocking AST address and parameter are set even if | 710 | notes that a new blocking AST address and parameter are set even if |
| 731 | the conversion fails, so maybe we should just do that. */ | 711 | the conversion fails, so maybe we should just do that. */ |
| 732 | 712 | ||
| 733 | if (type == AST_BAST) { | 713 | if (flags & DLM_CB_BAST) { |
| 734 | result.user_astaddr = ua->bastaddr; | 714 | result.user_astaddr = ua->bastaddr; |
| 735 | result.user_astparam = ua->bastparam; | 715 | result.user_astparam = ua->bastparam; |
| 736 | result.bast_mode = mode; | 716 | result.bast_mode = mode; |
| @@ -750,8 +730,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
| 750 | /* copy lvb to userspace if there is one, it's been updated, and | 730 | /* copy lvb to userspace if there is one, it's been updated, and |
| 751 | the user buffer has space for it */ | 731 | the user buffer has space for it */ |
| 752 | 732 | ||
| 753 | if (ua->update_user_lvb && ua->lksb.sb_lvbptr && | 733 | if (copy_lvb && ua->lksb.sb_lvbptr && count >= len + DLM_USER_LVB_LEN) { |
| 754 | count >= len + DLM_USER_LVB_LEN) { | ||
| 755 | if (copy_to_user(buf+len, ua->lksb.sb_lvbptr, | 734 | if (copy_to_user(buf+len, ua->lksb.sb_lvbptr, |
| 756 | DLM_USER_LVB_LEN)) { | 735 | DLM_USER_LVB_LEN)) { |
| 757 | error = -EFAULT; | 736 | error = -EFAULT; |
| @@ -801,13 +780,12 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 801 | struct dlm_user_proc *proc = file->private_data; | 780 | struct dlm_user_proc *proc = file->private_data; |
| 802 | struct dlm_lkb *lkb; | 781 | struct dlm_lkb *lkb; |
| 803 | DECLARE_WAITQUEUE(wait, current); | 782 | DECLARE_WAITQUEUE(wait, current); |
| 804 | int error = 0, removed; | 783 | struct dlm_callback cb; |
| 805 | int ret_type, ret_mode; | 784 | int rv, resid, copy_lvb = 0; |
| 806 | int bastmode, castmode, do_bast, do_cast; | ||
| 807 | 785 | ||
| 808 | if (count == sizeof(struct dlm_device_version)) { | 786 | if (count == sizeof(struct dlm_device_version)) { |
| 809 | error = copy_version_to_user(buf, count); | 787 | rv = copy_version_to_user(buf, count); |
| 810 | return error; | 788 | return rv; |
| 811 | } | 789 | } |
| 812 | 790 | ||
| 813 | if (!proc) { | 791 | if (!proc) { |
| @@ -854,92 +832,57 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 854 | } | 832 | } |
| 855 | } | 833 | } |
| 856 | 834 | ||
| 857 | /* there may be both completion and blocking asts to return for | 835 | /* if we empty lkb_callbacks, we don't want to unlock the spinlock |
| 858 | the lkb, don't remove lkb from asts list unless no asts remain */ | 836 | without removing lkb_astqueue; so empty lkb_astqueue is always |
| 837 | consistent with empty lkb_callbacks */ | ||
| 859 | 838 | ||
| 860 | lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue); | 839 | lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue); |
| 861 | 840 | ||
| 862 | removed = 0; | 841 | rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid); |
| 863 | ret_type = 0; | 842 | if (rv < 0) { |
| 864 | ret_mode = 0; | 843 | /* this shouldn't happen; lkb should have been removed from |
| 865 | do_bast = lkb->lkb_ast_type & AST_BAST; | 844 | list when resid was zero */ |
| 866 | do_cast = lkb->lkb_ast_type & AST_COMP; | 845 | log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id); |
| 867 | bastmode = lkb->lkb_bastmode; | 846 | list_del_init(&lkb->lkb_astqueue); |
| 868 | castmode = lkb->lkb_castmode; | 847 | spin_unlock(&proc->asts_spin); |
| 869 | 848 | /* removes ref for proc->asts, may cause lkb to be freed */ | |
| 870 | /* when both are queued figure out which to do first and | 849 | dlm_put_lkb(lkb); |
| 871 | switch first so the other goes in the next read */ | 850 | goto try_another; |
| 872 | |||
| 873 | if (do_cast && do_bast) { | ||
| 874 | if (lkb->lkb_ast_first == AST_COMP) { | ||
| 875 | ret_type = AST_COMP; | ||
| 876 | ret_mode = castmode; | ||
| 877 | lkb->lkb_ast_type &= ~AST_COMP; | ||
| 878 | lkb->lkb_ast_first = AST_BAST; | ||
| 879 | } else { | ||
| 880 | ret_type = AST_BAST; | ||
| 881 | ret_mode = bastmode; | ||
| 882 | lkb->lkb_ast_type &= ~AST_BAST; | ||
| 883 | lkb->lkb_ast_first = AST_COMP; | ||
| 884 | } | ||
| 885 | } else { | ||
| 886 | ret_type = lkb->lkb_ast_first; | ||
| 887 | ret_mode = (ret_type == AST_COMP) ? castmode : bastmode; | ||
| 888 | lkb->lkb_ast_type &= ~ret_type; | ||
| 889 | lkb->lkb_ast_first = 0; | ||
| 890 | } | 851 | } |
| 852 | if (!resid) | ||
| 853 | list_del_init(&lkb->lkb_astqueue); | ||
| 854 | spin_unlock(&proc->asts_spin); | ||
| 891 | 855 | ||
| 892 | /* if we're doing a bast but the bast is unnecessary, then | 856 | if (cb.flags & DLM_CB_SKIP) { |
| 893 | switch to do nothing or do a cast if that was needed next */ | 857 | /* removes ref for proc->asts, may cause lkb to be freed */ |
| 894 | 858 | if (!resid) | |
| 895 | if ((ret_type == AST_BAST) && | 859 | dlm_put_lkb(lkb); |
| 896 | dlm_modes_compat(bastmode, lkb->lkb_castmode_done)) { | 860 | goto try_another; |
| 897 | ret_type = 0; | ||
| 898 | ret_mode = 0; | ||
| 899 | |||
| 900 | if (do_cast) { | ||
| 901 | ret_type = AST_COMP; | ||
| 902 | ret_mode = castmode; | ||
| 903 | lkb->lkb_ast_type &= ~AST_COMP; | ||
| 904 | lkb->lkb_ast_first = 0; | ||
| 905 | } | ||
| 906 | } | 861 | } |
| 907 | 862 | ||
| 908 | if (lkb->lkb_ast_first != lkb->lkb_ast_type) { | 863 | if (cb.flags & DLM_CB_CAST) { |
| 909 | log_print("device_read %x ast_first %x ast_type %x", | 864 | int old_mode, new_mode; |
| 910 | lkb->lkb_id, lkb->lkb_ast_first, lkb->lkb_ast_type); | ||
| 911 | } | ||
| 912 | 865 | ||
| 913 | if (!lkb->lkb_ast_type) { | 866 | old_mode = lkb->lkb_last_cast.mode; |
| 914 | list_del(&lkb->lkb_astqueue); | 867 | new_mode = cb.mode; |
| 915 | removed = 1; | ||
| 916 | } | ||
| 917 | spin_unlock(&proc->asts_spin); | ||
| 918 | 868 | ||
| 919 | if (ret_type) { | 869 | if (!cb.sb_status && lkb->lkb_lksb->sb_lvbptr && |
| 920 | error = copy_result_to_user(lkb->lkb_ua, | 870 | dlm_lvb_operations[old_mode + 1][new_mode + 1]) |
| 921 | test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), | 871 | copy_lvb = 1; |
| 922 | ret_type, ret_mode, buf, count); | ||
| 923 | 872 | ||
| 924 | if (ret_type == AST_COMP) | 873 | lkb->lkb_lksb->sb_status = cb.sb_status; |
| 925 | lkb->lkb_castmode_done = castmode; | 874 | lkb->lkb_lksb->sb_flags = cb.sb_flags; |
| 926 | if (ret_type == AST_BAST) | ||
| 927 | lkb->lkb_bastmode_done = bastmode; | ||
| 928 | } | 875 | } |
| 929 | 876 | ||
| 930 | /* removes reference for the proc->asts lists added by | 877 | rv = copy_result_to_user(lkb->lkb_ua, |
| 931 | dlm_user_add_ast() and may result in the lkb being freed */ | 878 | test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), |
| 879 | cb.flags, cb.mode, copy_lvb, buf, count); | ||
| 932 | 880 | ||
| 933 | if (removed) | 881 | /* removes ref for proc->asts, may cause lkb to be freed */ |
| 882 | if (!resid) | ||
| 934 | dlm_put_lkb(lkb); | 883 | dlm_put_lkb(lkb); |
| 935 | 884 | ||
| 936 | /* the bast that was queued was eliminated (see unnecessary above), | 885 | return rv; |
| 937 | leaving nothing to return */ | ||
| 938 | |||
| 939 | if (!ret_type) | ||
| 940 | goto try_another; | ||
| 941 | |||
| 942 | return error; | ||
| 943 | } | 886 | } |
| 944 | 887 | ||
| 945 | static unsigned int device_poll(struct file *file, poll_table *wait) | 888 | static unsigned int device_poll(struct file *file, poll_table *wait) |
diff --git a/fs/dlm/user.h b/fs/dlm/user.h index f196091dd7ff..00499ab8835f 100644 --- a/fs/dlm/user.h +++ b/fs/dlm/user.h | |||
| @@ -9,7 +9,8 @@ | |||
| 9 | #ifndef __USER_DOT_H__ | 9 | #ifndef __USER_DOT_H__ |
| 10 | #define __USER_DOT_H__ | 10 | #define __USER_DOT_H__ |
| 11 | 11 | ||
| 12 | void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode); | 12 | void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, |
| 13 | int status, uint32_t sbflags, uint64_t seq); | ||
| 13 | int dlm_user_init(void); | 14 | int dlm_user_init(void); |
| 14 | void dlm_user_exit(void); | 15 | void dlm_user_exit(void); |
| 15 | int dlm_device_deregister(struct dlm_ls *ls); | 16 | int dlm_device_deregister(struct dlm_ls *ls); |
