aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/ast.c74
-rw-r--r--fs/dlm/ast.h4
-rw-r--r--fs/dlm/config.c1
-rw-r--r--fs/dlm/debug_fs.c3
-rw-r--r--fs/dlm/dlm_internal.h10
-rw-r--r--fs/dlm/lock.c126
-rw-r--r--fs/dlm/lockspace.c16
-rw-r--r--fs/dlm/lowcomms.c1
-rw-r--r--fs/dlm/member.c2
-rw-r--r--fs/dlm/netlink.c1
-rw-r--r--fs/dlm/plock.c1
-rw-r--r--fs/dlm/user.c99
-rw-r--r--fs/dlm/user.h4
13 files changed, 264 insertions, 78 deletions
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index dc2ad6008b2d..4314f0d48d85 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.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-2008 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2010 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
@@ -33,10 +33,10 @@ void dlm_del_ast(struct dlm_lkb *lkb)
33 spin_unlock(&ast_queue_lock); 33 spin_unlock(&ast_queue_lock);
34} 34}
35 35
36void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode) 36void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode)
37{ 37{
38 if (lkb->lkb_flags & DLM_IFL_USER) { 38 if (lkb->lkb_flags & DLM_IFL_USER) {
39 dlm_user_add_ast(lkb, type, bastmode); 39 dlm_user_add_ast(lkb, type, mode);
40 return; 40 return;
41 } 41 }
42 42
@@ -44,10 +44,21 @@ void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
44 if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) { 44 if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
45 kref_get(&lkb->lkb_ref); 45 kref_get(&lkb->lkb_ref);
46 list_add_tail(&lkb->lkb_astqueue, &ast_queue); 46 list_add_tail(&lkb->lkb_astqueue, &ast_queue);
47 lkb->lkb_ast_first = type;
47 } 48 }
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
48 lkb->lkb_ast_type |= type; 57 lkb->lkb_ast_type |= type;
49 if (bastmode) 58 if (type == AST_BAST)
50 lkb->lkb_bastmode = bastmode; 59 lkb->lkb_bastmode = mode;
60 else
61 lkb->lkb_castmode = mode;
51 spin_unlock(&ast_queue_lock); 62 spin_unlock(&ast_queue_lock);
52 63
53 set_bit(WAKE_ASTS, &astd_wakeflags); 64 set_bit(WAKE_ASTS, &astd_wakeflags);
@@ -59,9 +70,9 @@ static void process_asts(void)
59 struct dlm_ls *ls = NULL; 70 struct dlm_ls *ls = NULL;
60 struct dlm_rsb *r = NULL; 71 struct dlm_rsb *r = NULL;
61 struct dlm_lkb *lkb; 72 struct dlm_lkb *lkb;
62 void (*cast) (void *astparam); 73 void (*castfn) (void *astparam);
63 void (*bast) (void *astparam, int mode); 74 void (*bastfn) (void *astparam, int mode);
64 int type = 0, bastmode; 75 int type, first, bastmode, castmode, do_bast, do_cast, last_castmode;
65 76
66repeat: 77repeat:
67 spin_lock(&ast_queue_lock); 78 spin_lock(&ast_queue_lock);
@@ -75,17 +86,48 @@ repeat:
75 list_del(&lkb->lkb_astqueue); 86 list_del(&lkb->lkb_astqueue);
76 type = lkb->lkb_ast_type; 87 type = lkb->lkb_ast_type;
77 lkb->lkb_ast_type = 0; 88 lkb->lkb_ast_type = 0;
89 first = lkb->lkb_ast_first;
90 lkb->lkb_ast_first = 0;
78 bastmode = lkb->lkb_bastmode; 91 bastmode = lkb->lkb_bastmode;
79 92 castmode = lkb->lkb_castmode;
93 castfn = lkb->lkb_astfn;
94 bastfn = lkb->lkb_bastfn;
80 spin_unlock(&ast_queue_lock); 95 spin_unlock(&ast_queue_lock);
81 cast = lkb->lkb_astfn;
82 bast = lkb->lkb_bastfn;
83
84 if ((type & AST_COMP) && cast)
85 cast(lkb->lkb_astparam);
86 96
87 if ((type & AST_BAST) && bast) 97 do_cast = (type & AST_COMP) && castfn;
88 bast(lkb->lkb_astparam, bastmode); 98 do_bast = (type & AST_BAST) && bastfn;
99
100 /* Skip a bast if its blocking mode is compatible with the
101 granted mode of the preceding cast. */
102
103 if (do_bast) {
104 if (first == AST_COMP)
105 last_castmode = castmode;
106 else
107 last_castmode = lkb->lkb_castmode_done;
108 if (dlm_modes_compat(bastmode, last_castmode))
109 do_bast = 0;
110 }
111
112 if (first == AST_COMP) {
113 if (do_cast)
114 castfn(lkb->lkb_astparam);
115 if (do_bast)
116 bastfn(lkb->lkb_astparam, bastmode);
117 } else if (first == AST_BAST) {
118 if (do_bast)
119 bastfn(lkb->lkb_astparam, bastmode);
120 if (do_cast)
121 castfn(lkb->lkb_astparam);
122 } else {
123 log_error(ls, "bad ast_first %d ast_type %d",
124 first, type);
125 }
126
127 if (do_cast)
128 lkb->lkb_castmode_done = castmode;
129 if (do_bast)
130 lkb->lkb_bastmode_done = bastmode;
89 131
90 /* this removes the reference added by dlm_add_ast 132 /* this removes the reference added by dlm_add_ast
91 and may result in the lkb being freed */ 133 and may result in the lkb being freed */
diff --git a/fs/dlm/ast.h b/fs/dlm/ast.h
index 1b5fc5f428fd..bcb1aaba519d 100644
--- a/fs/dlm/ast.h
+++ b/fs/dlm/ast.h
@@ -1,7 +1,7 @@
1/****************************************************************************** 1/******************************************************************************
2******************************************************************************* 2*******************************************************************************
3** 3**
4** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 4** Copyright (C) 2005-2010 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
@@ -13,7 +13,7 @@
13#ifndef __ASTD_DOT_H__ 13#ifndef __ASTD_DOT_H__
14#define __ASTD_DOT_H__ 14#define __ASTD_DOT_H__
15 15
16void dlm_add_ast(struct dlm_lkb *lkb, int type, int bastmode); 16void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode);
17void dlm_del_ast(struct dlm_lkb *lkb); 17void dlm_del_ast(struct dlm_lkb *lkb);
18 18
19void dlm_astd_wake(void); 19void dlm_astd_wake(void);
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 0df243850818..b54bca03d92f 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/configfs.h> 16#include <linux/configfs.h>
17#include <linux/slab.h>
17#include <linux/in.h> 18#include <linux/in.h>
18#include <linux/in6.h> 19#include <linux/in6.h>
19#include <net/ipv6.h> 20#include <net/ipv6.h>
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 375a2359b3bf..c6cf25158746 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -15,6 +15,7 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/ctype.h> 16#include <linux/ctype.h>
17#include <linux/debugfs.h> 17#include <linux/debugfs.h>
18#include <linux/slab.h>
18 19
19#include "dlm_internal.h" 20#include "dlm_internal.h"
20#include "lock.h" 21#include "lock.h"
@@ -256,7 +257,7 @@ static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
256 lkb->lkb_status, 257 lkb->lkb_status,
257 lkb->lkb_grmode, 258 lkb->lkb_grmode,
258 lkb->lkb_rqmode, 259 lkb->lkb_rqmode,
259 lkb->lkb_highbast, 260 lkb->lkb_bastmode,
260 rsb_lookup, 261 rsb_lookup,
261 lkb->lkb_wait_type, 262 lkb->lkb_wait_type,
262 lkb->lkb_lvbseq, 263 lkb->lkb_lvbseq,
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 826d3dc6e0ab..f632b58cd222 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-2008 Red Hat, Inc. All rights reserved. 5** Copyright (C) 2004-2010 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
@@ -232,11 +232,17 @@ struct dlm_lkb {
232 int8_t lkb_status; /* granted, waiting, convert */ 232 int8_t lkb_status; /* granted, waiting, convert */
233 int8_t lkb_rqmode; /* requested lock mode */ 233 int8_t lkb_rqmode; /* requested lock mode */
234 int8_t lkb_grmode; /* granted lock mode */ 234 int8_t lkb_grmode; /* granted lock mode */
235 int8_t lkb_bastmode; /* requested mode */
236 int8_t lkb_highbast; /* highest mode bast sent for */ 235 int8_t lkb_highbast; /* highest mode bast sent for */
236
237 int8_t lkb_wait_type; /* type of reply waiting for */ 237 int8_t lkb_wait_type; /* type of reply waiting for */
238 int8_t lkb_wait_count; 238 int8_t lkb_wait_count;
239 int8_t lkb_ast_type; /* type of ast queued for */ 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 */
240 246
241 struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ 247 struct list_head lkb_idtbl_list; /* lockspace lkbtbl */
242 struct list_head lkb_statequeue; /* rsb g/c/w list */ 248 struct list_head lkb_statequeue; /* rsb g/c/w list */
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 9c0c1db1e105..031dbe3a15ca 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-2008 Red Hat, Inc. All rights reserved. 4** Copyright (C) 2005-2010 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
@@ -56,6 +56,7 @@
56 L: receive_xxxx_reply() <- R: send_xxxx_reply() 56 L: receive_xxxx_reply() <- R: send_xxxx_reply()
57*/ 57*/
58#include <linux/types.h> 58#include <linux/types.h>
59#include <linux/slab.h>
59#include "dlm_internal.h" 60#include "dlm_internal.h"
60#include <linux/dlm_device.h> 61#include <linux/dlm_device.h>
61#include "memory.h" 62#include "memory.h"
@@ -307,7 +308,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
307 lkb->lkb_lksb->sb_status = rv; 308 lkb->lkb_lksb->sb_status = rv;
308 lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags; 309 lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
309 310
310 dlm_add_ast(lkb, AST_COMP, 0); 311 dlm_add_ast(lkb, AST_COMP, lkb->lkb_grmode);
311} 312}
312 313
313static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) 314static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -320,10 +321,12 @@ static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
320{ 321{
321 lkb->lkb_time_bast = ktime_get(); 322 lkb->lkb_time_bast = ktime_get();
322 323
323 if (is_master_copy(lkb)) 324 if (is_master_copy(lkb)) {
325 lkb->lkb_bastmode = rqmode; /* printed by debugfs */
324 send_bast(r, lkb, rqmode); 326 send_bast(r, lkb, rqmode);
325 else 327 } else {
326 dlm_add_ast(lkb, AST_BAST, rqmode); 328 dlm_add_ast(lkb, AST_BAST, rqmode);
329 }
327} 330}
328 331
329/* 332/*
@@ -730,10 +733,7 @@ static void lkb_add_ordered(struct list_head *new, struct list_head *head,
730 if (lkb->lkb_rqmode < mode) 733 if (lkb->lkb_rqmode < mode)
731 break; 734 break;
732 735
733 if (!lkb) 736 __list_add(new, lkb->lkb_statequeue.prev, &lkb->lkb_statequeue);
734 list_add_tail(new, head);
735 else
736 __list_add(new, lkb->lkb_statequeue.prev, &lkb->lkb_statequeue);
737} 737}
738 738
739/* add/remove lkb to rsb's grant/convert/wait queue */ 739/* add/remove lkb to rsb's grant/convert/wait queue */
@@ -2280,20 +2280,30 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
2280 if (can_be_queued(lkb)) { 2280 if (can_be_queued(lkb)) {
2281 error = -EINPROGRESS; 2281 error = -EINPROGRESS;
2282 add_lkb(r, lkb, DLM_LKSTS_WAITING); 2282 add_lkb(r, lkb, DLM_LKSTS_WAITING);
2283 send_blocking_asts(r, lkb);
2284 add_timeout(lkb); 2283 add_timeout(lkb);
2285 goto out; 2284 goto out;
2286 } 2285 }
2287 2286
2288 error = -EAGAIN; 2287 error = -EAGAIN;
2289 if (force_blocking_asts(lkb))
2290 send_blocking_asts_all(r, lkb);
2291 queue_cast(r, lkb, -EAGAIN); 2288 queue_cast(r, lkb, -EAGAIN);
2292
2293 out: 2289 out:
2294 return error; 2290 return error;
2295} 2291}
2296 2292
2293static void do_request_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
2294 int error)
2295{
2296 switch (error) {
2297 case -EAGAIN:
2298 if (force_blocking_asts(lkb))
2299 send_blocking_asts_all(r, lkb);
2300 break;
2301 case -EINPROGRESS:
2302 send_blocking_asts(r, lkb);
2303 break;
2304 }
2305}
2306
2297static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) 2307static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2298{ 2308{
2299 int error = 0; 2309 int error = 0;
@@ -2304,7 +2314,6 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2304 if (can_be_granted(r, lkb, 1, &deadlk)) { 2314 if (can_be_granted(r, lkb, 1, &deadlk)) {
2305 grant_lock(r, lkb); 2315 grant_lock(r, lkb);
2306 queue_cast(r, lkb, 0); 2316 queue_cast(r, lkb, 0);
2307 grant_pending_locks(r);
2308 goto out; 2317 goto out;
2309 } 2318 }
2310 2319
@@ -2334,7 +2343,6 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2334 if (_can_be_granted(r, lkb, 1)) { 2343 if (_can_be_granted(r, lkb, 1)) {
2335 grant_lock(r, lkb); 2344 grant_lock(r, lkb);
2336 queue_cast(r, lkb, 0); 2345 queue_cast(r, lkb, 0);
2337 grant_pending_locks(r);
2338 goto out; 2346 goto out;
2339 } 2347 }
2340 /* else fall through and move to convert queue */ 2348 /* else fall through and move to convert queue */
@@ -2344,28 +2352,47 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
2344 error = -EINPROGRESS; 2352 error = -EINPROGRESS;
2345 del_lkb(r, lkb); 2353 del_lkb(r, lkb);
2346 add_lkb(r, lkb, DLM_LKSTS_CONVERT); 2354 add_lkb(r, lkb, DLM_LKSTS_CONVERT);
2347 send_blocking_asts(r, lkb);
2348 add_timeout(lkb); 2355 add_timeout(lkb);
2349 goto out; 2356 goto out;
2350 } 2357 }
2351 2358
2352 error = -EAGAIN; 2359 error = -EAGAIN;
2353 if (force_blocking_asts(lkb))
2354 send_blocking_asts_all(r, lkb);
2355 queue_cast(r, lkb, -EAGAIN); 2360 queue_cast(r, lkb, -EAGAIN);
2356
2357 out: 2361 out:
2358 return error; 2362 return error;
2359} 2363}
2360 2364
2365static void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
2366 int error)
2367{
2368 switch (error) {
2369 case 0:
2370 grant_pending_locks(r);
2371 /* grant_pending_locks also sends basts */
2372 break;
2373 case -EAGAIN:
2374 if (force_blocking_asts(lkb))
2375 send_blocking_asts_all(r, lkb);
2376 break;
2377 case -EINPROGRESS:
2378 send_blocking_asts(r, lkb);
2379 break;
2380 }
2381}
2382
2361static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) 2383static int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
2362{ 2384{
2363 remove_lock(r, lkb); 2385 remove_lock(r, lkb);
2364 queue_cast(r, lkb, -DLM_EUNLOCK); 2386 queue_cast(r, lkb, -DLM_EUNLOCK);
2365 grant_pending_locks(r);
2366 return -DLM_EUNLOCK; 2387 return -DLM_EUNLOCK;
2367} 2388}
2368 2389
2390static void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
2391 int error)
2392{
2393 grant_pending_locks(r);
2394}
2395
2369/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */ 2396/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */
2370 2397
2371static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb) 2398static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -2375,12 +2402,18 @@ static int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb)
2375 error = revert_lock(r, lkb); 2402 error = revert_lock(r, lkb);
2376 if (error) { 2403 if (error) {
2377 queue_cast(r, lkb, -DLM_ECANCEL); 2404 queue_cast(r, lkb, -DLM_ECANCEL);
2378 grant_pending_locks(r);
2379 return -DLM_ECANCEL; 2405 return -DLM_ECANCEL;
2380 } 2406 }
2381 return 0; 2407 return 0;
2382} 2408}
2383 2409
2410static void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb,
2411 int error)
2412{
2413 if (error)
2414 grant_pending_locks(r);
2415}
2416
2384/* 2417/*
2385 * Four stage 3 varieties: 2418 * Four stage 3 varieties:
2386 * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock() 2419 * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock()
@@ -2402,11 +2435,15 @@ static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
2402 goto out; 2435 goto out;
2403 } 2436 }
2404 2437
2405 if (is_remote(r)) 2438 if (is_remote(r)) {
2406 /* receive_request() calls do_request() on remote node */ 2439 /* receive_request() calls do_request() on remote node */
2407 error = send_request(r, lkb); 2440 error = send_request(r, lkb);
2408 else 2441 } else {
2409 error = do_request(r, lkb); 2442 error = do_request(r, lkb);
2443 /* for remote locks the request_reply is sent
2444 between do_request and do_request_effects */
2445 do_request_effects(r, lkb, error);
2446 }
2410 out: 2447 out:
2411 return error; 2448 return error;
2412} 2449}
@@ -2417,11 +2454,15 @@ static int _convert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
2417{ 2454{
2418 int error; 2455 int error;
2419 2456
2420 if (is_remote(r)) 2457 if (is_remote(r)) {
2421 /* receive_convert() calls do_convert() on remote node */ 2458 /* receive_convert() calls do_convert() on remote node */
2422 error = send_convert(r, lkb); 2459 error = send_convert(r, lkb);
2423 else 2460 } else {
2424 error = do_convert(r, lkb); 2461 error = do_convert(r, lkb);
2462 /* for remote locks the convert_reply is sent
2463 between do_convert and do_convert_effects */
2464 do_convert_effects(r, lkb, error);
2465 }
2425 2466
2426 return error; 2467 return error;
2427} 2468}
@@ -2432,11 +2473,15 @@ static int _unlock_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
2432{ 2473{
2433 int error; 2474 int error;
2434 2475
2435 if (is_remote(r)) 2476 if (is_remote(r)) {
2436 /* receive_unlock() calls do_unlock() on remote node */ 2477 /* receive_unlock() calls do_unlock() on remote node */
2437 error = send_unlock(r, lkb); 2478 error = send_unlock(r, lkb);
2438 else 2479 } else {
2439 error = do_unlock(r, lkb); 2480 error = do_unlock(r, lkb);
2481 /* for remote locks the unlock_reply is sent
2482 between do_unlock and do_unlock_effects */
2483 do_unlock_effects(r, lkb, error);
2484 }
2440 2485
2441 return error; 2486 return error;
2442} 2487}
@@ -2447,11 +2492,15 @@ static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
2447{ 2492{
2448 int error; 2493 int error;
2449 2494
2450 if (is_remote(r)) 2495 if (is_remote(r)) {
2451 /* receive_cancel() calls do_cancel() on remote node */ 2496 /* receive_cancel() calls do_cancel() on remote node */
2452 error = send_cancel(r, lkb); 2497 error = send_cancel(r, lkb);
2453 else 2498 } else {
2454 error = do_cancel(r, lkb); 2499 error = do_cancel(r, lkb);
2500 /* for remote locks the cancel_reply is sent
2501 between do_cancel and do_cancel_effects */
2502 do_cancel_effects(r, lkb, error);
2503 }
2455 2504
2456 return error; 2505 return error;
2457} 2506}
@@ -3191,6 +3240,7 @@ static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
3191 attach_lkb(r, lkb); 3240 attach_lkb(r, lkb);
3192 error = do_request(r, lkb); 3241 error = do_request(r, lkb);
3193 send_request_reply(r, lkb, error); 3242 send_request_reply(r, lkb, error);
3243 do_request_effects(r, lkb, error);
3194 3244
3195 unlock_rsb(r); 3245 unlock_rsb(r);
3196 put_rsb(r); 3246 put_rsb(r);
@@ -3226,15 +3276,19 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
3226 goto out; 3276 goto out;
3227 3277
3228 receive_flags(lkb, ms); 3278 receive_flags(lkb, ms);
3279
3229 error = receive_convert_args(ls, lkb, ms); 3280 error = receive_convert_args(ls, lkb, ms);
3230 if (error) 3281 if (error) {
3231 goto out_reply; 3282 send_convert_reply(r, lkb, error);
3283 goto out;
3284 }
3285
3232 reply = !down_conversion(lkb); 3286 reply = !down_conversion(lkb);
3233 3287
3234 error = do_convert(r, lkb); 3288 error = do_convert(r, lkb);
3235 out_reply:
3236 if (reply) 3289 if (reply)
3237 send_convert_reply(r, lkb, error); 3290 send_convert_reply(r, lkb, error);
3291 do_convert_effects(r, lkb, error);
3238 out: 3292 out:
3239 unlock_rsb(r); 3293 unlock_rsb(r);
3240 put_rsb(r); 3294 put_rsb(r);
@@ -3266,13 +3320,16 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
3266 goto out; 3320 goto out;
3267 3321
3268 receive_flags(lkb, ms); 3322 receive_flags(lkb, ms);
3323
3269 error = receive_unlock_args(ls, lkb, ms); 3324 error = receive_unlock_args(ls, lkb, ms);
3270 if (error) 3325 if (error) {
3271 goto out_reply; 3326 send_unlock_reply(r, lkb, error);
3327 goto out;
3328 }
3272 3329
3273 error = do_unlock(r, lkb); 3330 error = do_unlock(r, lkb);
3274 out_reply:
3275 send_unlock_reply(r, lkb, error); 3331 send_unlock_reply(r, lkb, error);
3332 do_unlock_effects(r, lkb, error);
3276 out: 3333 out:
3277 unlock_rsb(r); 3334 unlock_rsb(r);
3278 put_rsb(r); 3335 put_rsb(r);
@@ -3307,6 +3364,7 @@ static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
3307 3364
3308 error = do_cancel(r, lkb); 3365 error = do_cancel(r, lkb);
3309 send_cancel_reply(r, lkb, error); 3366 send_cancel_reply(r, lkb, error);
3367 do_cancel_effects(r, lkb, error);
3310 out: 3368 out:
3311 unlock_rsb(r); 3369 unlock_rsb(r);
3312 put_rsb(r); 3370 put_rsb(r);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index c010ecfc0d29..f994a7dfda85 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -148,7 +148,7 @@ static void lockspace_kobj_release(struct kobject *k)
148 kfree(ls); 148 kfree(ls);
149} 149}
150 150
151static struct sysfs_ops dlm_attr_ops = { 151static const struct sysfs_ops dlm_attr_ops = {
152 .show = dlm_attr_show, 152 .show = dlm_attr_show,
153 .store = dlm_attr_store, 153 .store = dlm_attr_store,
154}; 154};
@@ -191,6 +191,18 @@ static int do_uevent(struct dlm_ls *ls, int in)
191 return error; 191 return error;
192} 192}
193 193
194static int dlm_uevent(struct kset *kset, struct kobject *kobj,
195 struct kobj_uevent_env *env)
196{
197 struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
198
199 add_uevent_var(env, "LOCKSPACE=%s", ls->ls_name);
200 return 0;
201}
202
203static struct kset_uevent_ops dlm_uevent_ops = {
204 .uevent = dlm_uevent,
205};
194 206
195int __init dlm_lockspace_init(void) 207int __init dlm_lockspace_init(void)
196{ 208{
@@ -199,7 +211,7 @@ int __init dlm_lockspace_init(void)
199 INIT_LIST_HEAD(&lslist); 211 INIT_LIST_HEAD(&lslist);
200 spin_lock_init(&lslist_lock); 212 spin_lock_init(&lslist_lock);
201 213
202 dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj); 214 dlm_kset = kset_create_and_add("dlm", &dlm_uevent_ops, kernel_kobj);
203 if (!dlm_kset) { 215 if (!dlm_kset) {
204 printk(KERN_WARNING "%s: can not create kset\n", __func__); 216 printk(KERN_WARNING "%s: can not create kset\n", __func__);
205 return -ENOMEM; 217 return -ENOMEM;
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 52cab160893c..c0d35c620526 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -51,6 +51,7 @@
51#include <linux/file.h> 51#include <linux/file.h>
52#include <linux/mutex.h> 52#include <linux/mutex.h>
53#include <linux/sctp.h> 53#include <linux/sctp.h>
54#include <linux/slab.h>
54#include <net/sctp/user.h> 55#include <net/sctp/user.h>
55#include <net/ipv6.h> 56#include <net/ipv6.h>
56 57
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 84f70bfb0baf..b12532e553f8 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -312,7 +312,7 @@ int dlm_ls_stop(struct dlm_ls *ls)
312 /* 312 /*
313 * This in_recovery lock does two things: 313 * This in_recovery lock does two things:
314 * 1) Keeps this function from returning until all threads are out 314 * 1) Keeps this function from returning until all threads are out
315 * of locking routines and locking is truely stopped. 315 * of locking routines and locking is truly stopped.
316 * 2) Keeps any new requests from being processed until it's unlocked 316 * 2) Keeps any new requests from being processed until it's unlocked
317 * when recovery is complete. 317 * when recovery is complete.
318 */ 318 */
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
index 052095cd592f..2c6ad518100d 100644
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@ -9,6 +9,7 @@
9#include <net/genetlink.h> 9#include <net/genetlink.h>
10#include <linux/dlm.h> 10#include <linux/dlm.h>
11#include <linux/dlm_netlink.h> 11#include <linux/dlm_netlink.h>
12#include <linux/gfp.h>
12 13
13#include "dlm_internal.h" 14#include "dlm_internal.h"
14 15
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index b5f89aef3b29..d45c02db6943 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -11,6 +11,7 @@
11#include <linux/poll.h> 11#include <linux/poll.h>
12#include <linux/dlm.h> 12#include <linux/dlm.h>
13#include <linux/dlm_plock.h> 13#include <linux/dlm_plock.h>
14#include <linux/slab.h>
14 15
15#include "dlm_internal.h" 16#include "dlm_internal.h"
16#include "lockspace.h" 17#include "lockspace.h"
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index e73a4bb572aa..b6272853130c 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. 2 * Copyright (C) 2006-2010 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
@@ -17,6 +17,7 @@
17#include <linux/spinlock.h> 17#include <linux/spinlock.h>
18#include <linux/dlm.h> 18#include <linux/dlm.h>
19#include <linux/dlm_device.h> 19#include <linux/dlm_device.h>
20#include <linux/slab.h>
20 21
21#include "dlm_internal.h" 22#include "dlm_internal.h"
22#include "lockspace.h" 23#include "lockspace.h"
@@ -173,7 +174,7 @@ static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
173/* we could possibly check if the cancel of an orphan has resulted in the lkb 174/* we could possibly check if the cancel of an orphan has resulted in the lkb
174 being removed and then remove that lkb from the orphans list and free it */ 175 being removed and then remove that lkb from the orphans list and free it */
175 176
176void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode) 177void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
177{ 178{
178 struct dlm_ls *ls; 179 struct dlm_ls *ls;
179 struct dlm_user_args *ua; 180 struct dlm_user_args *ua;
@@ -206,12 +207,15 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
206 207
207 ast_type = lkb->lkb_ast_type; 208 ast_type = lkb->lkb_ast_type;
208 lkb->lkb_ast_type |= type; 209 lkb->lkb_ast_type |= type;
209 if (bastmode) 210 if (type == AST_BAST)
210 lkb->lkb_bastmode = bastmode; 211 lkb->lkb_bastmode = mode;
212 else
213 lkb->lkb_castmode = mode;
211 214
212 if (!ast_type) { 215 if (!ast_type) {
213 kref_get(&lkb->lkb_ref); 216 kref_get(&lkb->lkb_ref);
214 list_add_tail(&lkb->lkb_astqueue, &proc->asts); 217 list_add_tail(&lkb->lkb_astqueue, &proc->asts);
218 lkb->lkb_ast_first = type;
215 wake_up_interruptible(&proc->wait); 219 wake_up_interruptible(&proc->wait);
216 } 220 }
217 if (type == AST_COMP && (ast_type & AST_COMP)) 221 if (type == AST_COMP && (ast_type & AST_COMP))
@@ -220,7 +224,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode)
220 224
221 eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); 225 eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
222 if (eol) { 226 if (eol) {
223 lkb->lkb_ast_type &= ~AST_BAST;
224 lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; 227 lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
225 } 228 }
226 229
@@ -703,7 +706,7 @@ static int device_close(struct inode *inode, struct file *file)
703} 706}
704 707
705static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, 708static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
706 int bmode, char __user *buf, size_t count) 709 int mode, char __user *buf, size_t count)
707{ 710{
708#ifdef CONFIG_COMPAT 711#ifdef CONFIG_COMPAT
709 struct dlm_lock_result32 result32; 712 struct dlm_lock_result32 result32;
@@ -730,7 +733,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
730 if (type == AST_BAST) { 733 if (type == AST_BAST) {
731 result.user_astaddr = ua->bastaddr; 734 result.user_astaddr = ua->bastaddr;
732 result.user_astparam = ua->bastparam; 735 result.user_astparam = ua->bastparam;
733 result.bast_mode = bmode; 736 result.bast_mode = mode;
734 } else { 737 } else {
735 result.user_astaddr = ua->castaddr; 738 result.user_astaddr = ua->castaddr;
736 result.user_astparam = ua->castparam; 739 result.user_astparam = ua->castparam;
@@ -798,7 +801,9 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
798 struct dlm_user_proc *proc = file->private_data; 801 struct dlm_user_proc *proc = file->private_data;
799 struct dlm_lkb *lkb; 802 struct dlm_lkb *lkb;
800 DECLARE_WAITQUEUE(wait, current); 803 DECLARE_WAITQUEUE(wait, current);
801 int error, type=0, bmode=0, removed = 0; 804 int error = 0, removed;
805 int ret_type, ret_mode;
806 int bastmode, castmode, do_bast, do_cast;
802 807
803 if (count == sizeof(struct dlm_device_version)) { 808 if (count == sizeof(struct dlm_device_version)) {
804 error = copy_version_to_user(buf, count); 809 error = copy_version_to_user(buf, count);
@@ -817,6 +822,8 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
817#endif 822#endif
818 return -EINVAL; 823 return -EINVAL;
819 824
825 try_another:
826
820 /* do we really need this? can a read happen after a close? */ 827 /* do we really need this? can a read happen after a close? */
821 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags)) 828 if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags))
822 return -EINVAL; 829 return -EINVAL;
@@ -852,13 +859,55 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
852 859
853 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue); 860 lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
854 861
855 if (lkb->lkb_ast_type & AST_COMP) { 862 removed = 0;
856 lkb->lkb_ast_type &= ~AST_COMP; 863 ret_type = 0;
857 type = AST_COMP; 864 ret_mode = 0;
858 } else if (lkb->lkb_ast_type & AST_BAST) { 865 do_bast = lkb->lkb_ast_type & AST_BAST;
859 lkb->lkb_ast_type &= ~AST_BAST; 866 do_cast = lkb->lkb_ast_type & AST_COMP;
860 type = AST_BAST; 867 bastmode = lkb->lkb_bastmode;
861 bmode = lkb->lkb_bastmode; 868 castmode = lkb->lkb_castmode;
869
870 /* when both are queued figure out which to do first and
871 switch first so the other goes in the next read */
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 }
891
892 /* if we're doing a bast but the bast is unnecessary, then
893 switch to do nothing or do a cast if that was needed next */
894
895 if ((ret_type == AST_BAST) &&
896 dlm_modes_compat(bastmode, lkb->lkb_castmode_done)) {
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 }
907
908 if (lkb->lkb_ast_first != lkb->lkb_ast_type) {
909 log_print("device_read %x ast_first %x ast_type %x",
910 lkb->lkb_id, lkb->lkb_ast_first, lkb->lkb_ast_type);
862 } 911 }
863 912
864 if (!lkb->lkb_ast_type) { 913 if (!lkb->lkb_ast_type) {
@@ -867,15 +916,29 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
867 } 916 }
868 spin_unlock(&proc->asts_spin); 917 spin_unlock(&proc->asts_spin);
869 918
870 error = copy_result_to_user(lkb->lkb_ua, 919 if (ret_type) {
871 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), 920 error = copy_result_to_user(lkb->lkb_ua,
872 type, bmode, buf, count); 921 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
922 ret_type, ret_mode, buf, count);
923
924 if (ret_type == AST_COMP)
925 lkb->lkb_castmode_done = castmode;
926 if (ret_type == AST_BAST)
927 lkb->lkb_bastmode_done = bastmode;
928 }
873 929
874 /* removes reference for the proc->asts lists added by 930 /* removes reference for the proc->asts lists added by
875 dlm_user_add_ast() and may result in the lkb being freed */ 931 dlm_user_add_ast() and may result in the lkb being freed */
932
876 if (removed) 933 if (removed)
877 dlm_put_lkb(lkb); 934 dlm_put_lkb(lkb);
878 935
936 /* the bast that was queued was eliminated (see unnecessary above),
937 leaving nothing to return */
938
939 if (!ret_type)
940 goto try_another;
941
879 return error; 942 return error;
880} 943}
881 944
diff --git a/fs/dlm/user.h b/fs/dlm/user.h
index 1c9686492286..f196091dd7ff 100644
--- a/fs/dlm/user.h
+++ b/fs/dlm/user.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. 2 * Copyright (C) 2006-2010 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
@@ -9,7 +9,7 @@
9#ifndef __USER_DOT_H__ 9#ifndef __USER_DOT_H__
10#define __USER_DOT_H__ 10#define __USER_DOT_H__
11 11
12void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int bastmode); 12void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode);
13int dlm_user_init(void); 13int dlm_user_init(void);
14void dlm_user_exit(void); 14void dlm_user_exit(void);
15int dlm_device_deregister(struct dlm_ls *ls); 15int dlm_device_deregister(struct dlm_ls *ls);