diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-07 15:26:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-07 15:26:27 -0400 |
commit | 5cefcab3db2b13093480f2a42bf081574dd72d3d (patch) | |
tree | c3755a241553436a1b84d65ad3c00f77ce6d02ad /fs/gfs2 | |
parent | 5f757f91e70a97eda8f0cc13bddc853209b2d173 (diff) | |
parent | 37fde8ca6c60ea61f5e9d7cb877c25ac60e74167 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (34 commits)
[GFS2] Uncomment sprintf_symbol calling code
[DLM] lowcomms style
[GFS2] printk warning fixes
[GFS2] Patch to fix mmap of stuffed files
[GFS2] use lib/parser for parsing mount options
[DLM] Lowcomms nodeid range & initialisation fixes
[DLM] Fix dlm_lowcoms_stop hang
[DLM] fix mode munging
[GFS2] lockdump improvements
[GFS2] Patch to detect corrupt number of dir entries in leaf and/or inode blocks
[GFS2] bz 236008: Kernel gpf doing cat /debugfs/gfs2/xxx (lock dump)
[DLM] fs/dlm/ast.c should #include "ast.h"
[DLM] Consolidate transport protocols
[DLM] Remove redundant assignment
[GFS2] Fix bz 234168 (ignoring rgrp flags)
[DLM] change lkid format
[DLM] interface for purge (2/2)
[DLM] add orphan purging code (1/2)
[DLM] split create_message function
[GFS2] Set drop_count to 0 (off) by default
...
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/dir.c | 38 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 619 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 8 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 14 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/lock.c | 14 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/lock_dlm.h | 3 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 20 | ||||
-rw-r--r-- | fs/gfs2/main.c | 4 | ||||
-rw-r--r-- | fs/gfs2/mount.c | 239 | ||||
-rw-r--r-- | fs/gfs2/ops_address.c | 21 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 4 | ||||
-rw-r--r-- | fs/gfs2/ops_super.c | 28 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 12 |
13 files changed, 642 insertions, 382 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 82a1ac7895a2..a96fa07b3f3b 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1262,9 +1262,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1262 | u64 leaf_no) | 1262 | u64 leaf_no) |
1263 | { | 1263 | { |
1264 | struct gfs2_inode *ip = GFS2_I(inode); | 1264 | struct gfs2_inode *ip = GFS2_I(inode); |
1265 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1265 | struct buffer_head *bh; | 1266 | struct buffer_head *bh; |
1266 | struct gfs2_leaf *lf; | 1267 | struct gfs2_leaf *lf; |
1267 | unsigned entries = 0; | 1268 | unsigned entries = 0, entries2 = 0; |
1268 | unsigned leaves = 0; | 1269 | unsigned leaves = 0; |
1269 | const struct gfs2_dirent **darr, *dent; | 1270 | const struct gfs2_dirent **darr, *dent; |
1270 | struct dirent_gather g; | 1271 | struct dirent_gather g; |
@@ -1290,7 +1291,13 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1290 | return 0; | 1291 | return 0; |
1291 | 1292 | ||
1292 | error = -ENOMEM; | 1293 | error = -ENOMEM; |
1293 | larr = vmalloc((leaves + entries) * sizeof(void *)); | 1294 | /* |
1295 | * The extra 99 entries are not normally used, but are a buffer | ||
1296 | * zone in case the number of entries in the leaf is corrupt. | ||
1297 | * 99 is the maximum number of entries that can fit in a single | ||
1298 | * leaf block. | ||
1299 | */ | ||
1300 | larr = vmalloc((leaves + entries + 99) * sizeof(void *)); | ||
1294 | if (!larr) | 1301 | if (!larr) |
1295 | goto out; | 1302 | goto out; |
1296 | darr = (const struct gfs2_dirent **)(larr + leaves); | 1303 | darr = (const struct gfs2_dirent **)(larr + leaves); |
@@ -1305,10 +1312,20 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1305 | lf = (struct gfs2_leaf *)bh->b_data; | 1312 | lf = (struct gfs2_leaf *)bh->b_data; |
1306 | lfn = be64_to_cpu(lf->lf_next); | 1313 | lfn = be64_to_cpu(lf->lf_next); |
1307 | if (lf->lf_entries) { | 1314 | if (lf->lf_entries) { |
1315 | entries2 += be16_to_cpu(lf->lf_entries); | ||
1308 | dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, | 1316 | dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size, |
1309 | gfs2_dirent_gather, NULL, &g); | 1317 | gfs2_dirent_gather, NULL, &g); |
1310 | error = PTR_ERR(dent); | 1318 | error = PTR_ERR(dent); |
1311 | if (IS_ERR(dent)) { | 1319 | if (IS_ERR(dent)) |
1320 | goto out_kfree; | ||
1321 | if (entries2 != g.offset) { | ||
1322 | fs_warn(sdp, "Number of entries corrupt in dir " | ||
1323 | "leaf %llu, entries2 (%u) != " | ||
1324 | "g.offset (%u)\n", | ||
1325 | (unsigned long long)bh->b_blocknr, | ||
1326 | entries2, g.offset); | ||
1327 | |||
1328 | error = -EIO; | ||
1312 | goto out_kfree; | 1329 | goto out_kfree; |
1313 | } | 1330 | } |
1314 | error = 0; | 1331 | error = 0; |
@@ -1318,6 +1335,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1318 | } | 1335 | } |
1319 | } while(lfn); | 1336 | } while(lfn); |
1320 | 1337 | ||
1338 | BUG_ON(entries2 != entries); | ||
1321 | error = do_filldir_main(ip, offset, opaque, filldir, darr, | 1339 | error = do_filldir_main(ip, offset, opaque, filldir, darr, |
1322 | entries, copied); | 1340 | entries, copied); |
1323 | out_kfree: | 1341 | out_kfree: |
@@ -1401,6 +1419,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1401 | filldir_t filldir) | 1419 | filldir_t filldir) |
1402 | { | 1420 | { |
1403 | struct gfs2_inode *dip = GFS2_I(inode); | 1421 | struct gfs2_inode *dip = GFS2_I(inode); |
1422 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1404 | struct dirent_gather g; | 1423 | struct dirent_gather g; |
1405 | const struct gfs2_dirent **darr, *dent; | 1424 | const struct gfs2_dirent **darr, *dent; |
1406 | struct buffer_head *dibh; | 1425 | struct buffer_head *dibh; |
@@ -1423,8 +1442,8 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1423 | return error; | 1442 | return error; |
1424 | 1443 | ||
1425 | error = -ENOMEM; | 1444 | error = -ENOMEM; |
1426 | darr = kmalloc(dip->i_di.di_entries * sizeof(struct gfs2_dirent *), | 1445 | /* 96 is max number of dirents which can be stuffed into an inode */ |
1427 | GFP_KERNEL); | 1446 | darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_KERNEL); |
1428 | if (darr) { | 1447 | if (darr) { |
1429 | g.pdent = darr; | 1448 | g.pdent = darr; |
1430 | g.offset = 0; | 1449 | g.offset = 0; |
@@ -1434,6 +1453,15 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, | |||
1434 | error = PTR_ERR(dent); | 1453 | error = PTR_ERR(dent); |
1435 | goto out; | 1454 | goto out; |
1436 | } | 1455 | } |
1456 | if (dip->i_di.di_entries != g.offset) { | ||
1457 | fs_warn(sdp, "Number of entries corrupt in dir %llu, " | ||
1458 | "ip->i_di.di_entries (%u) != g.offset (%u)\n", | ||
1459 | (unsigned long long)dip->i_num.no_addr, | ||
1460 | dip->i_di.di_entries, | ||
1461 | g.offset); | ||
1462 | error = -EIO; | ||
1463 | goto out; | ||
1464 | } | ||
1437 | error = do_filldir_main(dip, offset, opaque, filldir, darr, | 1465 | error = do_filldir_main(dip, offset, opaque, filldir, darr, |
1438 | dip->i_di.di_entries, &copied); | 1466 | dip->i_di.di_entries, &copied); |
1439 | out: | 1467 | out: |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 12accb08fe02..1815429a2978 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -23,6 +23,10 @@ | |||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/rwsem.h> | 24 | #include <linux/rwsem.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/debugfs.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/kallsyms.h> | ||
26 | 30 | ||
27 | #include "gfs2.h" | 31 | #include "gfs2.h" |
28 | #include "incore.h" | 32 | #include "incore.h" |
@@ -40,20 +44,30 @@ struct gfs2_gl_hash_bucket { | |||
40 | struct hlist_head hb_list; | 44 | struct hlist_head hb_list; |
41 | }; | 45 | }; |
42 | 46 | ||
47 | struct glock_iter { | ||
48 | int hash; /* hash bucket index */ | ||
49 | struct gfs2_sbd *sdp; /* incore superblock */ | ||
50 | struct gfs2_glock *gl; /* current glock struct */ | ||
51 | struct hlist_head *hb_list; /* current hash bucket ptr */ | ||
52 | struct seq_file *seq; /* sequence file for debugfs */ | ||
53 | char string[512]; /* scratch space */ | ||
54 | }; | ||
55 | |||
43 | typedef void (*glock_examiner) (struct gfs2_glock * gl); | 56 | typedef void (*glock_examiner) (struct gfs2_glock * gl); |
44 | 57 | ||
45 | static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); | 58 | static int gfs2_dump_lockstate(struct gfs2_sbd *sdp); |
46 | static int dump_glock(struct gfs2_glock *gl); | 59 | static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl); |
47 | static int dump_inode(struct gfs2_inode *ip); | 60 | static void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh); |
48 | static void gfs2_glock_xmote_th(struct gfs2_holder *gh); | ||
49 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); | 61 | static void gfs2_glock_drop_th(struct gfs2_glock *gl); |
50 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | 62 | static DECLARE_RWSEM(gfs2_umount_flush_sem); |
63 | static struct dentry *gfs2_root; | ||
51 | 64 | ||
52 | #define GFS2_GL_HASH_SHIFT 15 | 65 | #define GFS2_GL_HASH_SHIFT 15 |
53 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) | 66 | #define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT) |
54 | #define GFS2_GL_HASH_MASK (GFS2_GL_HASH_SIZE - 1) | 67 | #define GFS2_GL_HASH_MASK (GFS2_GL_HASH_SIZE - 1) |
55 | 68 | ||
56 | static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE]; | 69 | static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE]; |
70 | static struct dentry *gfs2_root; | ||
57 | 71 | ||
58 | /* | 72 | /* |
59 | * Despite what you might think, the numbers below are not arbitrary :-) | 73 | * Despite what you might think, the numbers below are not arbitrary :-) |
@@ -202,7 +216,6 @@ int gfs2_glock_put(struct gfs2_glock *gl) | |||
202 | gfs2_assert(sdp, list_empty(&gl->gl_reclaim)); | 216 | gfs2_assert(sdp, list_empty(&gl->gl_reclaim)); |
203 | gfs2_assert(sdp, list_empty(&gl->gl_holders)); | 217 | gfs2_assert(sdp, list_empty(&gl->gl_holders)); |
204 | gfs2_assert(sdp, list_empty(&gl->gl_waiters1)); | 218 | gfs2_assert(sdp, list_empty(&gl->gl_waiters1)); |
205 | gfs2_assert(sdp, list_empty(&gl->gl_waiters2)); | ||
206 | gfs2_assert(sdp, list_empty(&gl->gl_waiters3)); | 219 | gfs2_assert(sdp, list_empty(&gl->gl_waiters3)); |
207 | glock_free(gl); | 220 | glock_free(gl); |
208 | rv = 1; | 221 | rv = 1; |
@@ -303,7 +316,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
303 | atomic_set(&gl->gl_ref, 1); | 316 | atomic_set(&gl->gl_ref, 1); |
304 | gl->gl_state = LM_ST_UNLOCKED; | 317 | gl->gl_state = LM_ST_UNLOCKED; |
305 | gl->gl_hash = hash; | 318 | gl->gl_hash = hash; |
306 | gl->gl_owner = NULL; | 319 | gl->gl_owner_pid = 0; |
307 | gl->gl_ip = 0; | 320 | gl->gl_ip = 0; |
308 | gl->gl_ops = glops; | 321 | gl->gl_ops = glops; |
309 | gl->gl_req_gh = NULL; | 322 | gl->gl_req_gh = NULL; |
@@ -367,7 +380,7 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags, | |||
367 | INIT_LIST_HEAD(&gh->gh_list); | 380 | INIT_LIST_HEAD(&gh->gh_list); |
368 | gh->gh_gl = gl; | 381 | gh->gh_gl = gl; |
369 | gh->gh_ip = (unsigned long)__builtin_return_address(0); | 382 | gh->gh_ip = (unsigned long)__builtin_return_address(0); |
370 | gh->gh_owner = current; | 383 | gh->gh_owner_pid = current->pid; |
371 | gh->gh_state = state; | 384 | gh->gh_state = state; |
372 | gh->gh_flags = flags; | 385 | gh->gh_flags = flags; |
373 | gh->gh_error = 0; | 386 | gh->gh_error = 0; |
@@ -389,7 +402,7 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder * | |||
389 | { | 402 | { |
390 | gh->gh_state = state; | 403 | gh->gh_state = state; |
391 | gh->gh_flags = flags; | 404 | gh->gh_flags = flags; |
392 | gh->gh_iflags &= 1 << HIF_ALLOCED; | 405 | gh->gh_iflags = 0; |
393 | gh->gh_ip = (unsigned long)__builtin_return_address(0); | 406 | gh->gh_ip = (unsigned long)__builtin_return_address(0); |
394 | } | 407 | } |
395 | 408 | ||
@@ -406,54 +419,8 @@ void gfs2_holder_uninit(struct gfs2_holder *gh) | |||
406 | gh->gh_ip = 0; | 419 | gh->gh_ip = 0; |
407 | } | 420 | } |
408 | 421 | ||
409 | /** | 422 | static void gfs2_holder_wake(struct gfs2_holder *gh) |
410 | * gfs2_holder_get - get a struct gfs2_holder structure | ||
411 | * @gl: the glock | ||
412 | * @state: the state we're requesting | ||
413 | * @flags: the modifier flags | ||
414 | * @gfp_flags: | ||
415 | * | ||
416 | * Figure out how big an impact this function has. Either: | ||
417 | * 1) Replace it with a cache of structures hanging off the struct gfs2_sbd | ||
418 | * 2) Leave it like it is | ||
419 | * | ||
420 | * Returns: the holder structure, NULL on ENOMEM | ||
421 | */ | ||
422 | |||
423 | static struct gfs2_holder *gfs2_holder_get(struct gfs2_glock *gl, | ||
424 | unsigned int state, | ||
425 | int flags, gfp_t gfp_flags) | ||
426 | { | ||
427 | struct gfs2_holder *gh; | ||
428 | |||
429 | gh = kmalloc(sizeof(struct gfs2_holder), gfp_flags); | ||
430 | if (!gh) | ||
431 | return NULL; | ||
432 | |||
433 | gfs2_holder_init(gl, state, flags, gh); | ||
434 | set_bit(HIF_ALLOCED, &gh->gh_iflags); | ||
435 | gh->gh_ip = (unsigned long)__builtin_return_address(0); | ||
436 | return gh; | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * gfs2_holder_put - get rid of a struct gfs2_holder structure | ||
441 | * @gh: the holder structure | ||
442 | * | ||
443 | */ | ||
444 | |||
445 | static void gfs2_holder_put(struct gfs2_holder *gh) | ||
446 | { | 423 | { |
447 | gfs2_holder_uninit(gh); | ||
448 | kfree(gh); | ||
449 | } | ||
450 | |||
451 | static void gfs2_holder_dispose_or_wake(struct gfs2_holder *gh) | ||
452 | { | ||
453 | if (test_bit(HIF_DEALLOC, &gh->gh_iflags)) { | ||
454 | gfs2_holder_put(gh); | ||
455 | return; | ||
456 | } | ||
457 | clear_bit(HIF_WAIT, &gh->gh_iflags); | 424 | clear_bit(HIF_WAIT, &gh->gh_iflags); |
458 | smp_mb(); | 425 | smp_mb(); |
459 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); | 426 | wake_up_bit(&gh->gh_iflags, HIF_WAIT); |
@@ -519,7 +486,7 @@ static int rq_promote(struct gfs2_holder *gh) | |||
519 | gfs2_reclaim_glock(sdp); | 486 | gfs2_reclaim_glock(sdp); |
520 | } | 487 | } |
521 | 488 | ||
522 | gfs2_glock_xmote_th(gh); | 489 | gfs2_glock_xmote_th(gh->gh_gl, gh); |
523 | spin_lock(&gl->gl_spin); | 490 | spin_lock(&gl->gl_spin); |
524 | } | 491 | } |
525 | return 1; | 492 | return 1; |
@@ -542,7 +509,7 @@ static int rq_promote(struct gfs2_holder *gh) | |||
542 | gh->gh_error = 0; | 509 | gh->gh_error = 0; |
543 | set_bit(HIF_HOLDER, &gh->gh_iflags); | 510 | set_bit(HIF_HOLDER, &gh->gh_iflags); |
544 | 511 | ||
545 | gfs2_holder_dispose_or_wake(gh); | 512 | gfs2_holder_wake(gh); |
546 | 513 | ||
547 | return 0; | 514 | return 0; |
548 | } | 515 | } |
@@ -554,32 +521,24 @@ static int rq_promote(struct gfs2_holder *gh) | |||
554 | * Returns: 1 if the queue is blocked | 521 | * Returns: 1 if the queue is blocked |
555 | */ | 522 | */ |
556 | 523 | ||
557 | static int rq_demote(struct gfs2_holder *gh) | 524 | static int rq_demote(struct gfs2_glock *gl) |
558 | { | 525 | { |
559 | struct gfs2_glock *gl = gh->gh_gl; | ||
560 | |||
561 | if (!list_empty(&gl->gl_holders)) | 526 | if (!list_empty(&gl->gl_holders)) |
562 | return 1; | 527 | return 1; |
563 | 528 | ||
564 | if (gl->gl_state == gh->gh_state || gl->gl_state == LM_ST_UNLOCKED) { | 529 | if (gl->gl_state == gl->gl_demote_state || |
565 | list_del_init(&gh->gh_list); | 530 | gl->gl_state == LM_ST_UNLOCKED) { |
566 | gh->gh_error = 0; | 531 | clear_bit(GLF_DEMOTE, &gl->gl_flags); |
567 | spin_unlock(&gl->gl_spin); | 532 | return 0; |
568 | gfs2_holder_dispose_or_wake(gh); | ||
569 | spin_lock(&gl->gl_spin); | ||
570 | } else { | ||
571 | gl->gl_req_gh = gh; | ||
572 | set_bit(GLF_LOCK, &gl->gl_flags); | ||
573 | spin_unlock(&gl->gl_spin); | ||
574 | |||
575 | if (gh->gh_state == LM_ST_UNLOCKED || | ||
576 | gl->gl_state != LM_ST_EXCLUSIVE) | ||
577 | gfs2_glock_drop_th(gl); | ||
578 | else | ||
579 | gfs2_glock_xmote_th(gh); | ||
580 | |||
581 | spin_lock(&gl->gl_spin); | ||
582 | } | 533 | } |
534 | set_bit(GLF_LOCK, &gl->gl_flags); | ||
535 | spin_unlock(&gl->gl_spin); | ||
536 | if (gl->gl_demote_state == LM_ST_UNLOCKED || | ||
537 | gl->gl_state != LM_ST_EXCLUSIVE) | ||
538 | gfs2_glock_drop_th(gl); | ||
539 | else | ||
540 | gfs2_glock_xmote_th(gl, NULL); | ||
541 | spin_lock(&gl->gl_spin); | ||
583 | 542 | ||
584 | return 0; | 543 | return 0; |
585 | } | 544 | } |
@@ -607,16 +566,8 @@ static void run_queue(struct gfs2_glock *gl) | |||
607 | else | 566 | else |
608 | gfs2_assert_warn(gl->gl_sbd, 0); | 567 | gfs2_assert_warn(gl->gl_sbd, 0); |
609 | 568 | ||
610 | } else if (!list_empty(&gl->gl_waiters2) && | 569 | } else if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { |
611 | !test_bit(GLF_SKIP_WAITERS2, &gl->gl_flags)) { | 570 | blocked = rq_demote(gl); |
612 | gh = list_entry(gl->gl_waiters2.next, | ||
613 | struct gfs2_holder, gh_list); | ||
614 | |||
615 | if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) | ||
616 | blocked = rq_demote(gh); | ||
617 | else | ||
618 | gfs2_assert_warn(gl->gl_sbd, 0); | ||
619 | |||
620 | } else if (!list_empty(&gl->gl_waiters3)) { | 571 | } else if (!list_empty(&gl->gl_waiters3)) { |
621 | gh = list_entry(gl->gl_waiters3.next, | 572 | gh = list_entry(gl->gl_waiters3.next, |
622 | struct gfs2_holder, gh_list); | 573 | struct gfs2_holder, gh_list); |
@@ -654,7 +605,7 @@ static void gfs2_glmutex_lock(struct gfs2_glock *gl) | |||
654 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { | 605 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { |
655 | list_add_tail(&gh.gh_list, &gl->gl_waiters1); | 606 | list_add_tail(&gh.gh_list, &gl->gl_waiters1); |
656 | } else { | 607 | } else { |
657 | gl->gl_owner = current; | 608 | gl->gl_owner_pid = current->pid; |
658 | gl->gl_ip = (unsigned long)__builtin_return_address(0); | 609 | gl->gl_ip = (unsigned long)__builtin_return_address(0); |
659 | clear_bit(HIF_WAIT, &gh.gh_iflags); | 610 | clear_bit(HIF_WAIT, &gh.gh_iflags); |
660 | smp_mb(); | 611 | smp_mb(); |
@@ -681,7 +632,7 @@ static int gfs2_glmutex_trylock(struct gfs2_glock *gl) | |||
681 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { | 632 | if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) { |
682 | acquired = 0; | 633 | acquired = 0; |
683 | } else { | 634 | } else { |
684 | gl->gl_owner = current; | 635 | gl->gl_owner_pid = current->pid; |
685 | gl->gl_ip = (unsigned long)__builtin_return_address(0); | 636 | gl->gl_ip = (unsigned long)__builtin_return_address(0); |
686 | } | 637 | } |
687 | spin_unlock(&gl->gl_spin); | 638 | spin_unlock(&gl->gl_spin); |
@@ -699,7 +650,7 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl) | |||
699 | { | 650 | { |
700 | spin_lock(&gl->gl_spin); | 651 | spin_lock(&gl->gl_spin); |
701 | clear_bit(GLF_LOCK, &gl->gl_flags); | 652 | clear_bit(GLF_LOCK, &gl->gl_flags); |
702 | gl->gl_owner = NULL; | 653 | gl->gl_owner_pid = 0; |
703 | gl->gl_ip = 0; | 654 | gl->gl_ip = 0; |
704 | run_queue(gl); | 655 | run_queue(gl); |
705 | BUG_ON(!spin_is_locked(&gl->gl_spin)); | 656 | BUG_ON(!spin_is_locked(&gl->gl_spin)); |
@@ -707,50 +658,24 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl) | |||
707 | } | 658 | } |
708 | 659 | ||
709 | /** | 660 | /** |
710 | * handle_callback - add a demote request to a lock's queue | 661 | * handle_callback - process a demote request |
711 | * @gl: the glock | 662 | * @gl: the glock |
712 | * @state: the state the caller wants us to change to | 663 | * @state: the state the caller wants us to change to |
713 | * | 664 | * |
714 | * Note: This may fail sliently if we are out of memory. | 665 | * There are only two requests that we are going to see in actual |
666 | * practise: LM_ST_SHARED and LM_ST_UNLOCKED | ||
715 | */ | 667 | */ |
716 | 668 | ||
717 | static void handle_callback(struct gfs2_glock *gl, unsigned int state) | 669 | static void handle_callback(struct gfs2_glock *gl, unsigned int state) |
718 | { | 670 | { |
719 | struct gfs2_holder *gh, *new_gh = NULL; | ||
720 | |||
721 | restart: | ||
722 | spin_lock(&gl->gl_spin); | 671 | spin_lock(&gl->gl_spin); |
723 | 672 | if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) { | |
724 | list_for_each_entry(gh, &gl->gl_waiters2, gh_list) { | 673 | gl->gl_demote_state = state; |
725 | if (test_bit(HIF_DEMOTE, &gh->gh_iflags) && | 674 | gl->gl_demote_time = jiffies; |
726 | gl->gl_req_gh != gh) { | 675 | } else if (gl->gl_demote_state != LM_ST_UNLOCKED) { |
727 | if (gh->gh_state != state) | 676 | gl->gl_demote_state = state; |
728 | gh->gh_state = LM_ST_UNLOCKED; | ||
729 | goto out; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | if (new_gh) { | ||
734 | list_add_tail(&new_gh->gh_list, &gl->gl_waiters2); | ||
735 | new_gh = NULL; | ||
736 | } else { | ||
737 | spin_unlock(&gl->gl_spin); | ||
738 | |||
739 | new_gh = gfs2_holder_get(gl, state, LM_FLAG_TRY, GFP_NOFS); | ||
740 | if (!new_gh) | ||
741 | return; | ||
742 | set_bit(HIF_DEMOTE, &new_gh->gh_iflags); | ||
743 | set_bit(HIF_DEALLOC, &new_gh->gh_iflags); | ||
744 | set_bit(HIF_WAIT, &new_gh->gh_iflags); | ||
745 | |||
746 | goto restart; | ||
747 | } | 677 | } |
748 | |||
749 | out: | ||
750 | spin_unlock(&gl->gl_spin); | 678 | spin_unlock(&gl->gl_spin); |
751 | |||
752 | if (new_gh) | ||
753 | gfs2_holder_put(new_gh); | ||
754 | } | 679 | } |
755 | 680 | ||
756 | /** | 681 | /** |
@@ -810,56 +735,37 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
810 | 735 | ||
811 | /* Deal with each possible exit condition */ | 736 | /* Deal with each possible exit condition */ |
812 | 737 | ||
813 | if (!gh) | 738 | if (!gh) { |
814 | gl->gl_stamp = jiffies; | 739 | gl->gl_stamp = jiffies; |
815 | else if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { | 740 | if (ret & LM_OUT_CANCELED) |
741 | op_done = 0; | ||
742 | else | ||
743 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | ||
744 | } else { | ||
816 | spin_lock(&gl->gl_spin); | 745 | spin_lock(&gl->gl_spin); |
817 | list_del_init(&gh->gh_list); | 746 | list_del_init(&gh->gh_list); |
818 | gh->gh_error = -EIO; | 747 | gh->gh_error = -EIO; |
819 | spin_unlock(&gl->gl_spin); | 748 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
820 | } else if (test_bit(HIF_DEMOTE, &gh->gh_iflags)) { | 749 | goto out; |
821 | spin_lock(&gl->gl_spin); | 750 | gh->gh_error = GLR_CANCELED; |
822 | list_del_init(&gh->gh_list); | 751 | if (ret & LM_OUT_CANCELED) |
823 | if (gl->gl_state == gh->gh_state || | 752 | goto out; |
824 | gl->gl_state == LM_ST_UNLOCKED) { | 753 | if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) { |
754 | list_add_tail(&gh->gh_list, &gl->gl_holders); | ||
825 | gh->gh_error = 0; | 755 | gh->gh_error = 0; |
826 | } else { | 756 | set_bit(HIF_HOLDER, &gh->gh_iflags); |
827 | if (gfs2_assert_warn(sdp, gh->gh_flags & | 757 | set_bit(HIF_FIRST, &gh->gh_iflags); |
828 | (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) == -1) | 758 | op_done = 0; |
829 | fs_warn(sdp, "ret = 0x%.8X\n", ret); | 759 | goto out; |
830 | gh->gh_error = GLR_TRYFAILED; | ||
831 | } | 760 | } |
832 | spin_unlock(&gl->gl_spin); | ||
833 | |||
834 | if (ret & LM_OUT_CANCELED) | ||
835 | handle_callback(gl, LM_ST_UNLOCKED); | ||
836 | |||
837 | } else if (ret & LM_OUT_CANCELED) { | ||
838 | spin_lock(&gl->gl_spin); | ||
839 | list_del_init(&gh->gh_list); | ||
840 | gh->gh_error = GLR_CANCELED; | ||
841 | spin_unlock(&gl->gl_spin); | ||
842 | |||
843 | } else if (relaxed_state_ok(gl->gl_state, gh->gh_state, gh->gh_flags)) { | ||
844 | spin_lock(&gl->gl_spin); | ||
845 | list_move_tail(&gh->gh_list, &gl->gl_holders); | ||
846 | gh->gh_error = 0; | ||
847 | set_bit(HIF_HOLDER, &gh->gh_iflags); | ||
848 | spin_unlock(&gl->gl_spin); | ||
849 | |||
850 | set_bit(HIF_FIRST, &gh->gh_iflags); | ||
851 | |||
852 | op_done = 0; | ||
853 | |||
854 | } else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) { | ||
855 | spin_lock(&gl->gl_spin); | ||
856 | list_del_init(&gh->gh_list); | ||
857 | gh->gh_error = GLR_TRYFAILED; | 761 | gh->gh_error = GLR_TRYFAILED; |
858 | spin_unlock(&gl->gl_spin); | 762 | if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) |
859 | 763 | goto out; | |
860 | } else { | 764 | gh->gh_error = -EINVAL; |
861 | if (gfs2_assert_withdraw(sdp, 0) == -1) | 765 | if (gfs2_assert_withdraw(sdp, 0) == -1) |
862 | fs_err(sdp, "ret = 0x%.8X\n", ret); | 766 | fs_err(sdp, "ret = 0x%.8X\n", ret); |
767 | out: | ||
768 | spin_unlock(&gl->gl_spin); | ||
863 | } | 769 | } |
864 | 770 | ||
865 | if (glops->go_xmote_bh) | 771 | if (glops->go_xmote_bh) |
@@ -877,7 +783,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
877 | gfs2_glock_put(gl); | 783 | gfs2_glock_put(gl); |
878 | 784 | ||
879 | if (gh) | 785 | if (gh) |
880 | gfs2_holder_dispose_or_wake(gh); | 786 | gfs2_holder_wake(gh); |
881 | } | 787 | } |
882 | 788 | ||
883 | /** | 789 | /** |
@@ -888,12 +794,11 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) | |||
888 | * | 794 | * |
889 | */ | 795 | */ |
890 | 796 | ||
891 | void gfs2_glock_xmote_th(struct gfs2_holder *gh) | 797 | void gfs2_glock_xmote_th(struct gfs2_glock *gl, struct gfs2_holder *gh) |
892 | { | 798 | { |
893 | struct gfs2_glock *gl = gh->gh_gl; | ||
894 | struct gfs2_sbd *sdp = gl->gl_sbd; | 799 | struct gfs2_sbd *sdp = gl->gl_sbd; |
895 | int flags = gh->gh_flags; | 800 | int flags = gh ? gh->gh_flags : 0; |
896 | unsigned state = gh->gh_state; | 801 | unsigned state = gh ? gh->gh_state : gl->gl_demote_state; |
897 | const struct gfs2_glock_operations *glops = gl->gl_ops; | 802 | const struct gfs2_glock_operations *glops = gl->gl_ops; |
898 | int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB | | 803 | int lck_flags = flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB | |
899 | LM_FLAG_NOEXP | LM_FLAG_ANY | | 804 | LM_FLAG_NOEXP | LM_FLAG_ANY | |
@@ -943,6 +848,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
943 | gfs2_assert_warn(sdp, !ret); | 848 | gfs2_assert_warn(sdp, !ret); |
944 | 849 | ||
945 | state_change(gl, LM_ST_UNLOCKED); | 850 | state_change(gl, LM_ST_UNLOCKED); |
851 | clear_bit(GLF_DEMOTE, &gl->gl_flags); | ||
946 | 852 | ||
947 | if (glops->go_inval) | 853 | if (glops->go_inval) |
948 | glops->go_inval(gl, DIO_METADATA); | 854 | glops->go_inval(gl, DIO_METADATA); |
@@ -964,7 +870,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) | |||
964 | gfs2_glock_put(gl); | 870 | gfs2_glock_put(gl); |
965 | 871 | ||
966 | if (gh) | 872 | if (gh) |
967 | gfs2_holder_dispose_or_wake(gh); | 873 | gfs2_holder_wake(gh); |
968 | } | 874 | } |
969 | 875 | ||
970 | /** | 876 | /** |
@@ -1097,18 +1003,32 @@ static int glock_wait_internal(struct gfs2_holder *gh) | |||
1097 | } | 1003 | } |
1098 | 1004 | ||
1099 | static inline struct gfs2_holder * | 1005 | static inline struct gfs2_holder * |
1100 | find_holder_by_owner(struct list_head *head, struct task_struct *owner) | 1006 | find_holder_by_owner(struct list_head *head, pid_t pid) |
1101 | { | 1007 | { |
1102 | struct gfs2_holder *gh; | 1008 | struct gfs2_holder *gh; |
1103 | 1009 | ||
1104 | list_for_each_entry(gh, head, gh_list) { | 1010 | list_for_each_entry(gh, head, gh_list) { |
1105 | if (gh->gh_owner == owner) | 1011 | if (gh->gh_owner_pid == pid) |
1106 | return gh; | 1012 | return gh; |
1107 | } | 1013 | } |
1108 | 1014 | ||
1109 | return NULL; | 1015 | return NULL; |
1110 | } | 1016 | } |
1111 | 1017 | ||
1018 | static void print_dbg(struct glock_iter *gi, const char *fmt, ...) | ||
1019 | { | ||
1020 | va_list args; | ||
1021 | |||
1022 | va_start(args, fmt); | ||
1023 | if (gi) { | ||
1024 | vsprintf(gi->string, fmt, args); | ||
1025 | seq_printf(gi->seq, gi->string); | ||
1026 | } | ||
1027 | else | ||
1028 | vprintk(fmt, args); | ||
1029 | va_end(args); | ||
1030 | } | ||
1031 | |||
1112 | /** | 1032 | /** |
1113 | * add_to_queue - Add a holder to the wait queue (but look for recursion) | 1033 | * add_to_queue - Add a holder to the wait queue (but look for recursion) |
1114 | * @gh: the holder structure to add | 1034 | * @gh: the holder structure to add |
@@ -1120,24 +1040,24 @@ static void add_to_queue(struct gfs2_holder *gh) | |||
1120 | struct gfs2_glock *gl = gh->gh_gl; | 1040 | struct gfs2_glock *gl = gh->gh_gl; |
1121 | struct gfs2_holder *existing; | 1041 | struct gfs2_holder *existing; |
1122 | 1042 | ||
1123 | BUG_ON(!gh->gh_owner); | 1043 | BUG_ON(!gh->gh_owner_pid); |
1124 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) | 1044 | if (test_and_set_bit(HIF_WAIT, &gh->gh_iflags)) |
1125 | BUG(); | 1045 | BUG(); |
1126 | 1046 | ||
1127 | existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner); | 1047 | existing = find_holder_by_owner(&gl->gl_holders, gh->gh_owner_pid); |
1128 | if (existing) { | 1048 | if (existing) { |
1129 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); | 1049 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); |
1130 | printk(KERN_INFO "pid : %d\n", existing->gh_owner->pid); | 1050 | printk(KERN_INFO "pid : %d\n", existing->gh_owner_pid); |
1131 | printk(KERN_INFO "lock type : %d lock state : %d\n", | 1051 | printk(KERN_INFO "lock type : %d lock state : %d\n", |
1132 | existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state); | 1052 | existing->gh_gl->gl_name.ln_type, existing->gh_gl->gl_state); |
1133 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | 1053 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); |
1134 | printk(KERN_INFO "pid : %d\n", gh->gh_owner->pid); | 1054 | printk(KERN_INFO "pid : %d\n", gh->gh_owner_pid); |
1135 | printk(KERN_INFO "lock type : %d lock state : %d\n", | 1055 | printk(KERN_INFO "lock type : %d lock state : %d\n", |
1136 | gl->gl_name.ln_type, gl->gl_state); | 1056 | gl->gl_name.ln_type, gl->gl_state); |
1137 | BUG(); | 1057 | BUG(); |
1138 | } | 1058 | } |
1139 | 1059 | ||
1140 | existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner); | 1060 | existing = find_holder_by_owner(&gl->gl_waiters3, gh->gh_owner_pid); |
1141 | if (existing) { | 1061 | if (existing) { |
1142 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); | 1062 | print_symbol(KERN_WARNING "original: %s\n", existing->gh_ip); |
1143 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); | 1063 | print_symbol(KERN_WARNING "new: %s\n", gh->gh_ip); |
@@ -1267,9 +1187,8 @@ void gfs2_glock_dq(struct gfs2_holder *gh) | |||
1267 | if (glops->go_unlock) | 1187 | if (glops->go_unlock) |
1268 | glops->go_unlock(gh); | 1188 | glops->go_unlock(gh); |
1269 | 1189 | ||
1270 | gl->gl_stamp = jiffies; | ||
1271 | |||
1272 | spin_lock(&gl->gl_spin); | 1190 | spin_lock(&gl->gl_spin); |
1191 | gl->gl_stamp = jiffies; | ||
1273 | } | 1192 | } |
1274 | 1193 | ||
1275 | clear_bit(GLF_LOCK, &gl->gl_flags); | 1194 | clear_bit(GLF_LOCK, &gl->gl_flags); |
@@ -1841,6 +1760,15 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait) | |||
1841 | * Diagnostic routines to help debug distributed deadlock | 1760 | * Diagnostic routines to help debug distributed deadlock |
1842 | */ | 1761 | */ |
1843 | 1762 | ||
1763 | static void gfs2_print_symbol(struct glock_iter *gi, const char *fmt, | ||
1764 | unsigned long address) | ||
1765 | { | ||
1766 | char buffer[KSYM_SYMBOL_LEN]; | ||
1767 | |||
1768 | sprint_symbol(buffer, address); | ||
1769 | print_dbg(gi, fmt, buffer); | ||
1770 | } | ||
1771 | |||
1844 | /** | 1772 | /** |
1845 | * dump_holder - print information about a glock holder | 1773 | * dump_holder - print information about a glock holder |
1846 | * @str: a string naming the type of holder | 1774 | * @str: a string naming the type of holder |
@@ -1849,31 +1777,37 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait) | |||
1849 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1777 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1850 | */ | 1778 | */ |
1851 | 1779 | ||
1852 | static int dump_holder(char *str, struct gfs2_holder *gh) | 1780 | static int dump_holder(struct glock_iter *gi, char *str, |
1781 | struct gfs2_holder *gh) | ||
1853 | { | 1782 | { |
1854 | unsigned int x; | 1783 | unsigned int x; |
1855 | int error = -ENOBUFS; | 1784 | struct task_struct *gh_owner; |
1856 | 1785 | ||
1857 | printk(KERN_INFO " %s\n", str); | 1786 | print_dbg(gi, " %s\n", str); |
1858 | printk(KERN_INFO " owner = %ld\n", | 1787 | if (gh->gh_owner_pid) { |
1859 | (gh->gh_owner) ? (long)gh->gh_owner->pid : -1); | 1788 | print_dbg(gi, " owner = %ld ", (long)gh->gh_owner_pid); |
1860 | printk(KERN_INFO " gh_state = %u\n", gh->gh_state); | 1789 | gh_owner = find_task_by_pid(gh->gh_owner_pid); |
1861 | printk(KERN_INFO " gh_flags ="); | 1790 | if (gh_owner) |
1791 | print_dbg(gi, "(%s)\n", gh_owner->comm); | ||
1792 | else | ||
1793 | print_dbg(gi, "(ended)\n"); | ||
1794 | } else | ||
1795 | print_dbg(gi, " owner = -1\n"); | ||
1796 | print_dbg(gi, " gh_state = %u\n", gh->gh_state); | ||
1797 | print_dbg(gi, " gh_flags ="); | ||
1862 | for (x = 0; x < 32; x++) | 1798 | for (x = 0; x < 32; x++) |
1863 | if (gh->gh_flags & (1 << x)) | 1799 | if (gh->gh_flags & (1 << x)) |
1864 | printk(" %u", x); | 1800 | print_dbg(gi, " %u", x); |
1865 | printk(" \n"); | 1801 | print_dbg(gi, " \n"); |
1866 | printk(KERN_INFO " error = %d\n", gh->gh_error); | 1802 | print_dbg(gi, " error = %d\n", gh->gh_error); |
1867 | printk(KERN_INFO " gh_iflags ="); | 1803 | print_dbg(gi, " gh_iflags ="); |
1868 | for (x = 0; x < 32; x++) | 1804 | for (x = 0; x < 32; x++) |
1869 | if (test_bit(x, &gh->gh_iflags)) | 1805 | if (test_bit(x, &gh->gh_iflags)) |
1870 | printk(" %u", x); | 1806 | print_dbg(gi, " %u", x); |
1871 | printk(" \n"); | 1807 | print_dbg(gi, " \n"); |
1872 | print_symbol(KERN_INFO " initialized at: %s\n", gh->gh_ip); | 1808 | gfs2_print_symbol(gi, " initialized at: %s\n", gh->gh_ip); |
1873 | |||
1874 | error = 0; | ||
1875 | 1809 | ||
1876 | return error; | 1810 | return 0; |
1877 | } | 1811 | } |
1878 | 1812 | ||
1879 | /** | 1813 | /** |
@@ -1883,25 +1817,20 @@ static int dump_holder(char *str, struct gfs2_holder *gh) | |||
1883 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1817 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1884 | */ | 1818 | */ |
1885 | 1819 | ||
1886 | static int dump_inode(struct gfs2_inode *ip) | 1820 | static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip) |
1887 | { | 1821 | { |
1888 | unsigned int x; | 1822 | unsigned int x; |
1889 | int error = -ENOBUFS; | ||
1890 | 1823 | ||
1891 | printk(KERN_INFO " Inode:\n"); | 1824 | print_dbg(gi, " Inode:\n"); |
1892 | printk(KERN_INFO " num = %llu %llu\n", | 1825 | print_dbg(gi, " num = %llu/%llu\n", |
1893 | (unsigned long long)ip->i_num.no_formal_ino, | 1826 | ip->i_num.no_formal_ino, ip->i_num.no_addr); |
1894 | (unsigned long long)ip->i_num.no_addr); | 1827 | print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode)); |
1895 | printk(KERN_INFO " type = %u\n", IF2DT(ip->i_inode.i_mode)); | 1828 | print_dbg(gi, " i_flags ="); |
1896 | printk(KERN_INFO " i_flags ="); | ||
1897 | for (x = 0; x < 32; x++) | 1829 | for (x = 0; x < 32; x++) |
1898 | if (test_bit(x, &ip->i_flags)) | 1830 | if (test_bit(x, &ip->i_flags)) |
1899 | printk(" %u", x); | 1831 | print_dbg(gi, " %u", x); |
1900 | printk(" \n"); | 1832 | print_dbg(gi, " \n"); |
1901 | 1833 | return 0; | |
1902 | error = 0; | ||
1903 | |||
1904 | return error; | ||
1905 | } | 1834 | } |
1906 | 1835 | ||
1907 | /** | 1836 | /** |
@@ -1912,74 +1841,86 @@ static int dump_inode(struct gfs2_inode *ip) | |||
1912 | * Returns: 0 on success, -ENOBUFS when we run out of space | 1841 | * Returns: 0 on success, -ENOBUFS when we run out of space |
1913 | */ | 1842 | */ |
1914 | 1843 | ||
1915 | static int dump_glock(struct gfs2_glock *gl) | 1844 | static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl) |
1916 | { | 1845 | { |
1917 | struct gfs2_holder *gh; | 1846 | struct gfs2_holder *gh; |
1918 | unsigned int x; | 1847 | unsigned int x; |
1919 | int error = -ENOBUFS; | 1848 | int error = -ENOBUFS; |
1849 | struct task_struct *gl_owner; | ||
1920 | 1850 | ||
1921 | spin_lock(&gl->gl_spin); | 1851 | spin_lock(&gl->gl_spin); |
1922 | 1852 | ||
1923 | printk(KERN_INFO "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type, | 1853 | print_dbg(gi, "Glock 0x%p (%u, %llu)\n", gl, gl->gl_name.ln_type, |
1924 | (unsigned long long)gl->gl_name.ln_number); | 1854 | (unsigned long long)gl->gl_name.ln_number); |
1925 | printk(KERN_INFO " gl_flags ="); | 1855 | print_dbg(gi, " gl_flags ="); |
1926 | for (x = 0; x < 32; x++) { | 1856 | for (x = 0; x < 32; x++) { |
1927 | if (test_bit(x, &gl->gl_flags)) | 1857 | if (test_bit(x, &gl->gl_flags)) |
1928 | printk(" %u", x); | 1858 | print_dbg(gi, " %u", x); |
1929 | } | 1859 | } |
1930 | printk(" \n"); | 1860 | if (!test_bit(GLF_LOCK, &gl->gl_flags)) |
1931 | printk(KERN_INFO " gl_ref = %d\n", atomic_read(&gl->gl_ref)); | 1861 | print_dbg(gi, " (unlocked)"); |
1932 | printk(KERN_INFO " gl_state = %u\n", gl->gl_state); | 1862 | print_dbg(gi, " \n"); |
1933 | printk(KERN_INFO " gl_owner = %s\n", gl->gl_owner->comm); | 1863 | print_dbg(gi, " gl_ref = %d\n", atomic_read(&gl->gl_ref)); |
1934 | print_symbol(KERN_INFO " gl_ip = %s\n", gl->gl_ip); | 1864 | print_dbg(gi, " gl_state = %u\n", gl->gl_state); |
1935 | printk(KERN_INFO " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); | 1865 | if (gl->gl_owner_pid) { |
1936 | printk(KERN_INFO " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); | 1866 | gl_owner = find_task_by_pid(gl->gl_owner_pid); |
1937 | printk(KERN_INFO " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); | 1867 | if (gl_owner) |
1938 | printk(KERN_INFO " object = %s\n", (gl->gl_object) ? "yes" : "no"); | 1868 | print_dbg(gi, " gl_owner = pid %d (%s)\n", |
1939 | printk(KERN_INFO " le = %s\n", | 1869 | gl->gl_owner_pid, gl_owner->comm); |
1870 | else | ||
1871 | print_dbg(gi, " gl_owner = %d (ended)\n", | ||
1872 | gl->gl_owner_pid); | ||
1873 | } else | ||
1874 | print_dbg(gi, " gl_owner = -1\n"); | ||
1875 | print_dbg(gi, " gl_ip = %lu\n", gl->gl_ip); | ||
1876 | print_dbg(gi, " req_gh = %s\n", (gl->gl_req_gh) ? "yes" : "no"); | ||
1877 | print_dbg(gi, " req_bh = %s\n", (gl->gl_req_bh) ? "yes" : "no"); | ||
1878 | print_dbg(gi, " lvb_count = %d\n", atomic_read(&gl->gl_lvb_count)); | ||
1879 | print_dbg(gi, " object = %s\n", (gl->gl_object) ? "yes" : "no"); | ||
1880 | print_dbg(gi, " le = %s\n", | ||
1940 | (list_empty(&gl->gl_le.le_list)) ? "no" : "yes"); | 1881 | (list_empty(&gl->gl_le.le_list)) ? "no" : "yes"); |
1941 | printk(KERN_INFO " reclaim = %s\n", | 1882 | print_dbg(gi, " reclaim = %s\n", |
1942 | (list_empty(&gl->gl_reclaim)) ? "no" : "yes"); | 1883 | (list_empty(&gl->gl_reclaim)) ? "no" : "yes"); |
1943 | if (gl->gl_aspace) | 1884 | if (gl->gl_aspace) |
1944 | printk(KERN_INFO " aspace = 0x%p nrpages = %lu\n", gl->gl_aspace, | 1885 | print_dbg(gi, " aspace = 0x%p nrpages = %lu\n", gl->gl_aspace, |
1945 | gl->gl_aspace->i_mapping->nrpages); | 1886 | gl->gl_aspace->i_mapping->nrpages); |
1946 | else | 1887 | else |
1947 | printk(KERN_INFO " aspace = no\n"); | 1888 | print_dbg(gi, " aspace = no\n"); |
1948 | printk(KERN_INFO " ail = %d\n", atomic_read(&gl->gl_ail_count)); | 1889 | print_dbg(gi, " ail = %d\n", atomic_read(&gl->gl_ail_count)); |
1949 | if (gl->gl_req_gh) { | 1890 | if (gl->gl_req_gh) { |
1950 | error = dump_holder("Request", gl->gl_req_gh); | 1891 | error = dump_holder(gi, "Request", gl->gl_req_gh); |
1951 | if (error) | 1892 | if (error) |
1952 | goto out; | 1893 | goto out; |
1953 | } | 1894 | } |
1954 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | 1895 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
1955 | error = dump_holder("Holder", gh); | 1896 | error = dump_holder(gi, "Holder", gh); |
1956 | if (error) | 1897 | if (error) |
1957 | goto out; | 1898 | goto out; |
1958 | } | 1899 | } |
1959 | list_for_each_entry(gh, &gl->gl_waiters1, gh_list) { | 1900 | list_for_each_entry(gh, &gl->gl_waiters1, gh_list) { |
1960 | error = dump_holder("Waiter1", gh); | 1901 | error = dump_holder(gi, "Waiter1", gh); |
1961 | if (error) | ||
1962 | goto out; | ||
1963 | } | ||
1964 | list_for_each_entry(gh, &gl->gl_waiters2, gh_list) { | ||
1965 | error = dump_holder("Waiter2", gh); | ||
1966 | if (error) | 1902 | if (error) |
1967 | goto out; | 1903 | goto out; |
1968 | } | 1904 | } |
1969 | list_for_each_entry(gh, &gl->gl_waiters3, gh_list) { | 1905 | list_for_each_entry(gh, &gl->gl_waiters3, gh_list) { |
1970 | error = dump_holder("Waiter3", gh); | 1906 | error = dump_holder(gi, "Waiter3", gh); |
1971 | if (error) | 1907 | if (error) |
1972 | goto out; | 1908 | goto out; |
1973 | } | 1909 | } |
1910 | if (test_bit(GLF_DEMOTE, &gl->gl_flags)) { | ||
1911 | print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n", | ||
1912 | gl->gl_demote_state, | ||
1913 | (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ)); | ||
1914 | } | ||
1974 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { | 1915 | if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) { |
1975 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && | 1916 | if (!test_bit(GLF_LOCK, &gl->gl_flags) && |
1976 | list_empty(&gl->gl_holders)) { | 1917 | list_empty(&gl->gl_holders)) { |
1977 | error = dump_inode(gl->gl_object); | 1918 | error = dump_inode(gi, gl->gl_object); |
1978 | if (error) | 1919 | if (error) |
1979 | goto out; | 1920 | goto out; |
1980 | } else { | 1921 | } else { |
1981 | error = -ENOBUFS; | 1922 | error = -ENOBUFS; |
1982 | printk(KERN_INFO " Inode: busy\n"); | 1923 | print_dbg(gi, " Inode: busy\n"); |
1983 | } | 1924 | } |
1984 | } | 1925 | } |
1985 | 1926 | ||
@@ -2014,7 +1955,7 @@ static int gfs2_dump_lockstate(struct gfs2_sbd *sdp) | |||
2014 | if (gl->gl_sbd != sdp) | 1955 | if (gl->gl_sbd != sdp) |
2015 | continue; | 1956 | continue; |
2016 | 1957 | ||
2017 | error = dump_glock(gl); | 1958 | error = dump_glock(NULL, gl); |
2018 | if (error) | 1959 | if (error) |
2019 | break; | 1960 | break; |
2020 | } | 1961 | } |
@@ -2043,3 +1984,189 @@ int __init gfs2_glock_init(void) | |||
2043 | return 0; | 1984 | return 0; |
2044 | } | 1985 | } |
2045 | 1986 | ||
1987 | static int gfs2_glock_iter_next(struct glock_iter *gi) | ||
1988 | { | ||
1989 | read_lock(gl_lock_addr(gi->hash)); | ||
1990 | while (1) { | ||
1991 | if (!gi->hb_list) { /* If we don't have a hash bucket yet */ | ||
1992 | gi->hb_list = &gl_hash_table[gi->hash].hb_list; | ||
1993 | if (hlist_empty(gi->hb_list)) { | ||
1994 | read_unlock(gl_lock_addr(gi->hash)); | ||
1995 | gi->hash++; | ||
1996 | read_lock(gl_lock_addr(gi->hash)); | ||
1997 | gi->hb_list = NULL; | ||
1998 | if (gi->hash >= GFS2_GL_HASH_SIZE) { | ||
1999 | read_unlock(gl_lock_addr(gi->hash)); | ||
2000 | return 1; | ||
2001 | } | ||
2002 | else | ||
2003 | continue; | ||
2004 | } | ||
2005 | if (!hlist_empty(gi->hb_list)) { | ||
2006 | gi->gl = list_entry(gi->hb_list->first, | ||
2007 | struct gfs2_glock, | ||
2008 | gl_list); | ||
2009 | } | ||
2010 | } else { | ||
2011 | if (gi->gl->gl_list.next == NULL) { | ||
2012 | read_unlock(gl_lock_addr(gi->hash)); | ||
2013 | gi->hash++; | ||
2014 | read_lock(gl_lock_addr(gi->hash)); | ||
2015 | gi->hb_list = NULL; | ||
2016 | continue; | ||
2017 | } | ||
2018 | gi->gl = list_entry(gi->gl->gl_list.next, | ||
2019 | struct gfs2_glock, gl_list); | ||
2020 | } | ||
2021 | if (gi->gl) | ||
2022 | break; | ||
2023 | } | ||
2024 | read_unlock(gl_lock_addr(gi->hash)); | ||
2025 | return 0; | ||
2026 | } | ||
2027 | |||
2028 | static void gfs2_glock_iter_free(struct glock_iter *gi) | ||
2029 | { | ||
2030 | kfree(gi); | ||
2031 | } | ||
2032 | |||
2033 | static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp) | ||
2034 | { | ||
2035 | struct glock_iter *gi; | ||
2036 | |||
2037 | gi = kmalloc(sizeof (*gi), GFP_KERNEL); | ||
2038 | if (!gi) | ||
2039 | return NULL; | ||
2040 | |||
2041 | gi->sdp = sdp; | ||
2042 | gi->hash = 0; | ||
2043 | gi->gl = NULL; | ||
2044 | gi->hb_list = NULL; | ||
2045 | gi->seq = NULL; | ||
2046 | memset(gi->string, 0, sizeof(gi->string)); | ||
2047 | |||
2048 | if (gfs2_glock_iter_next(gi)) { | ||
2049 | gfs2_glock_iter_free(gi); | ||
2050 | return NULL; | ||
2051 | } | ||
2052 | |||
2053 | return gi; | ||
2054 | } | ||
2055 | |||
2056 | static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos) | ||
2057 | { | ||
2058 | struct glock_iter *gi; | ||
2059 | loff_t n = *pos; | ||
2060 | |||
2061 | gi = gfs2_glock_iter_init(file->private); | ||
2062 | if (!gi) | ||
2063 | return NULL; | ||
2064 | |||
2065 | while (n--) { | ||
2066 | if (gfs2_glock_iter_next(gi)) { | ||
2067 | gfs2_glock_iter_free(gi); | ||
2068 | return NULL; | ||
2069 | } | ||
2070 | } | ||
2071 | |||
2072 | return gi; | ||
2073 | } | ||
2074 | |||
2075 | static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr, | ||
2076 | loff_t *pos) | ||
2077 | { | ||
2078 | struct glock_iter *gi = iter_ptr; | ||
2079 | |||
2080 | (*pos)++; | ||
2081 | |||
2082 | if (gfs2_glock_iter_next(gi)) { | ||
2083 | gfs2_glock_iter_free(gi); | ||
2084 | return NULL; | ||
2085 | } | ||
2086 | |||
2087 | return gi; | ||
2088 | } | ||
2089 | |||
2090 | static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr) | ||
2091 | { | ||
2092 | /* nothing for now */ | ||
2093 | } | ||
2094 | |||
2095 | static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr) | ||
2096 | { | ||
2097 | struct glock_iter *gi = iter_ptr; | ||
2098 | |||
2099 | gi->seq = file; | ||
2100 | dump_glock(gi, gi->gl); | ||
2101 | |||
2102 | return 0; | ||
2103 | } | ||
2104 | |||
2105 | static struct seq_operations gfs2_glock_seq_ops = { | ||
2106 | .start = gfs2_glock_seq_start, | ||
2107 | .next = gfs2_glock_seq_next, | ||
2108 | .stop = gfs2_glock_seq_stop, | ||
2109 | .show = gfs2_glock_seq_show, | ||
2110 | }; | ||
2111 | |||
2112 | static int gfs2_debugfs_open(struct inode *inode, struct file *file) | ||
2113 | { | ||
2114 | struct seq_file *seq; | ||
2115 | int ret; | ||
2116 | |||
2117 | ret = seq_open(file, &gfs2_glock_seq_ops); | ||
2118 | if (ret) | ||
2119 | return ret; | ||
2120 | |||
2121 | seq = file->private_data; | ||
2122 | seq->private = inode->i_private; | ||
2123 | |||
2124 | return 0; | ||
2125 | } | ||
2126 | |||
2127 | static const struct file_operations gfs2_debug_fops = { | ||
2128 | .owner = THIS_MODULE, | ||
2129 | .open = gfs2_debugfs_open, | ||
2130 | .read = seq_read, | ||
2131 | .llseek = seq_lseek, | ||
2132 | .release = seq_release | ||
2133 | }; | ||
2134 | |||
2135 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp) | ||
2136 | { | ||
2137 | sdp->debugfs_dir = debugfs_create_dir(sdp->sd_table_name, gfs2_root); | ||
2138 | if (!sdp->debugfs_dir) | ||
2139 | return -ENOMEM; | ||
2140 | sdp->debugfs_dentry_glocks = debugfs_create_file("glocks", | ||
2141 | S_IFREG | S_IRUGO, | ||
2142 | sdp->debugfs_dir, sdp, | ||
2143 | &gfs2_debug_fops); | ||
2144 | if (!sdp->debugfs_dentry_glocks) | ||
2145 | return -ENOMEM; | ||
2146 | |||
2147 | return 0; | ||
2148 | } | ||
2149 | |||
2150 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp) | ||
2151 | { | ||
2152 | if (sdp && sdp->debugfs_dir) { | ||
2153 | if (sdp->debugfs_dentry_glocks) { | ||
2154 | debugfs_remove(sdp->debugfs_dentry_glocks); | ||
2155 | sdp->debugfs_dentry_glocks = NULL; | ||
2156 | } | ||
2157 | debugfs_remove(sdp->debugfs_dir); | ||
2158 | sdp->debugfs_dir = NULL; | ||
2159 | } | ||
2160 | } | ||
2161 | |||
2162 | int gfs2_register_debugfs(void) | ||
2163 | { | ||
2164 | gfs2_root = debugfs_create_dir("gfs2", NULL); | ||
2165 | return gfs2_root ? 0 : -ENOMEM; | ||
2166 | } | ||
2167 | |||
2168 | void gfs2_unregister_debugfs(void) | ||
2169 | { | ||
2170 | debugfs_remove(gfs2_root); | ||
2171 | gfs2_root = NULL; | ||
2172 | } | ||
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index f50e40ceca43..11477ca3a3c0 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -38,7 +38,7 @@ static inline int gfs2_glock_is_locked_by_me(struct gfs2_glock *gl) | |||
38 | /* Look in glock's list of holders for one with current task as owner */ | 38 | /* Look in glock's list of holders for one with current task as owner */ |
39 | spin_lock(&gl->gl_spin); | 39 | spin_lock(&gl->gl_spin); |
40 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | 40 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { |
41 | if (gh->gh_owner == current) { | 41 | if (gh->gh_owner_pid == current->pid) { |
42 | locked = 1; | 42 | locked = 1; |
43 | break; | 43 | break; |
44 | } | 44 | } |
@@ -67,7 +67,7 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) | |||
67 | { | 67 | { |
68 | int ret; | 68 | int ret; |
69 | spin_lock(&gl->gl_spin); | 69 | spin_lock(&gl->gl_spin); |
70 | ret = !list_empty(&gl->gl_waiters2) || !list_empty(&gl->gl_waiters3); | 70 | ret = test_bit(GLF_DEMOTE, &gl->gl_flags) || !list_empty(&gl->gl_waiters3); |
71 | spin_unlock(&gl->gl_spin); | 71 | spin_unlock(&gl->gl_spin); |
72 | return ret; | 72 | return ret; |
73 | } | 73 | } |
@@ -135,5 +135,9 @@ void gfs2_scand_internal(struct gfs2_sbd *sdp); | |||
135 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); | 135 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp, int wait); |
136 | 136 | ||
137 | int __init gfs2_glock_init(void); | 137 | int __init gfs2_glock_init(void); |
138 | int gfs2_create_debugfs_file(struct gfs2_sbd *sdp); | ||
139 | void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp); | ||
140 | int gfs2_register_debugfs(void); | ||
141 | void gfs2_unregister_debugfs(void); | ||
138 | 142 | ||
139 | #endif /* __GLOCK_DOT_H__ */ | 143 | #endif /* __GLOCK_DOT_H__ */ |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 49f0dbf40d86..d995441373ab 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -115,11 +115,8 @@ enum { | |||
115 | /* Actions */ | 115 | /* Actions */ |
116 | HIF_MUTEX = 0, | 116 | HIF_MUTEX = 0, |
117 | HIF_PROMOTE = 1, | 117 | HIF_PROMOTE = 1, |
118 | HIF_DEMOTE = 2, | ||
119 | 118 | ||
120 | /* States */ | 119 | /* States */ |
121 | HIF_ALLOCED = 4, | ||
122 | HIF_DEALLOC = 5, | ||
123 | HIF_HOLDER = 6, | 120 | HIF_HOLDER = 6, |
124 | HIF_FIRST = 7, | 121 | HIF_FIRST = 7, |
125 | HIF_ABORTED = 9, | 122 | HIF_ABORTED = 9, |
@@ -130,7 +127,7 @@ struct gfs2_holder { | |||
130 | struct list_head gh_list; | 127 | struct list_head gh_list; |
131 | 128 | ||
132 | struct gfs2_glock *gh_gl; | 129 | struct gfs2_glock *gh_gl; |
133 | struct task_struct *gh_owner; | 130 | pid_t gh_owner_pid; |
134 | unsigned int gh_state; | 131 | unsigned int gh_state; |
135 | unsigned gh_flags; | 132 | unsigned gh_flags; |
136 | 133 | ||
@@ -142,8 +139,8 @@ struct gfs2_holder { | |||
142 | enum { | 139 | enum { |
143 | GLF_LOCK = 1, | 140 | GLF_LOCK = 1, |
144 | GLF_STICKY = 2, | 141 | GLF_STICKY = 2, |
142 | GLF_DEMOTE = 3, | ||
145 | GLF_DIRTY = 5, | 143 | GLF_DIRTY = 5, |
146 | GLF_SKIP_WAITERS2 = 6, | ||
147 | }; | 144 | }; |
148 | 145 | ||
149 | struct gfs2_glock { | 146 | struct gfs2_glock { |
@@ -156,11 +153,12 @@ struct gfs2_glock { | |||
156 | 153 | ||
157 | unsigned int gl_state; | 154 | unsigned int gl_state; |
158 | unsigned int gl_hash; | 155 | unsigned int gl_hash; |
159 | struct task_struct *gl_owner; | 156 | unsigned int gl_demote_state; /* state requested by remote node */ |
157 | unsigned long gl_demote_time; /* time of first demote request */ | ||
158 | pid_t gl_owner_pid; | ||
160 | unsigned long gl_ip; | 159 | unsigned long gl_ip; |
161 | struct list_head gl_holders; | 160 | struct list_head gl_holders; |
162 | struct list_head gl_waiters1; /* HIF_MUTEX */ | 161 | struct list_head gl_waiters1; /* HIF_MUTEX */ |
163 | struct list_head gl_waiters2; /* HIF_DEMOTE */ | ||
164 | struct list_head gl_waiters3; /* HIF_PROMOTE */ | 162 | struct list_head gl_waiters3; /* HIF_PROMOTE */ |
165 | 163 | ||
166 | const struct gfs2_glock_operations *gl_ops; | 164 | const struct gfs2_glock_operations *gl_ops; |
@@ -611,6 +609,8 @@ struct gfs2_sbd { | |||
611 | 609 | ||
612 | unsigned long sd_last_warning; | 610 | unsigned long sd_last_warning; |
613 | struct vfsmount *sd_gfs2mnt; | 611 | struct vfsmount *sd_gfs2mnt; |
612 | struct dentry *debugfs_dir; /* debugfs directory */ | ||
613 | struct dentry *debugfs_dentry_glocks; /* for debugfs */ | ||
614 | }; | 614 | }; |
615 | 615 | ||
616 | #endif /* __INCORE_DOT_H__ */ | 616 | #endif /* __INCORE_DOT_H__ */ |
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c index b167addf9fd1..c305255bfe8a 100644 --- a/fs/gfs2/locking/dlm/lock.c +++ b/fs/gfs2/locking/dlm/lock.c | |||
@@ -151,7 +151,7 @@ static inline unsigned int make_flags(struct gdlm_lock *lp, | |||
151 | 151 | ||
152 | /* make_strname - convert GFS lock numbers to a string */ | 152 | /* make_strname - convert GFS lock numbers to a string */ |
153 | 153 | ||
154 | static inline void make_strname(struct lm_lockname *lockname, | 154 | static inline void make_strname(const struct lm_lockname *lockname, |
155 | struct gdlm_strname *str) | 155 | struct gdlm_strname *str) |
156 | { | 156 | { |
157 | sprintf(str->name, "%8x%16llx", lockname->ln_type, | 157 | sprintf(str->name, "%8x%16llx", lockname->ln_type, |
@@ -169,6 +169,7 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name, | |||
169 | return -ENOMEM; | 169 | return -ENOMEM; |
170 | 170 | ||
171 | lp->lockname = *name; | 171 | lp->lockname = *name; |
172 | make_strname(name, &lp->strname); | ||
172 | lp->ls = ls; | 173 | lp->ls = ls; |
173 | lp->cur = DLM_LOCK_IV; | 174 | lp->cur = DLM_LOCK_IV; |
174 | lp->lvb = NULL; | 175 | lp->lvb = NULL; |
@@ -227,7 +228,6 @@ void gdlm_put_lock(void *lock) | |||
227 | unsigned int gdlm_do_lock(struct gdlm_lock *lp) | 228 | unsigned int gdlm_do_lock(struct gdlm_lock *lp) |
228 | { | 229 | { |
229 | struct gdlm_ls *ls = lp->ls; | 230 | struct gdlm_ls *ls = lp->ls; |
230 | struct gdlm_strname str; | ||
231 | int error, bast = 1; | 231 | int error, bast = 1; |
232 | 232 | ||
233 | /* | 233 | /* |
@@ -249,8 +249,6 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp) | |||
249 | if (test_bit(LFL_NOBAST, &lp->flags)) | 249 | if (test_bit(LFL_NOBAST, &lp->flags)) |
250 | bast = 0; | 250 | bast = 0; |
251 | 251 | ||
252 | make_strname(&lp->lockname, &str); | ||
253 | |||
254 | set_bit(LFL_ACTIVE, &lp->flags); | 252 | set_bit(LFL_ACTIVE, &lp->flags); |
255 | 253 | ||
256 | log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type, | 254 | log_debug("lk %x,%llx id %x %d,%d %x", lp->lockname.ln_type, |
@@ -258,8 +256,8 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp) | |||
258 | lp->cur, lp->req, lp->lkf); | 256 | lp->cur, lp->req, lp->lkf); |
259 | 257 | ||
260 | error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf, | 258 | error = dlm_lock(ls->dlm_lockspace, lp->req, &lp->lksb, lp->lkf, |
261 | str.name, str.namelen, 0, gdlm_ast, lp, | 259 | lp->strname.name, lp->strname.namelen, 0, gdlm_ast, |
262 | bast ? gdlm_bast : NULL); | 260 | lp, bast ? gdlm_bast : NULL); |
263 | 261 | ||
264 | if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { | 262 | if ((error == -EAGAIN) && (lp->lkf & DLM_LKF_NOQUEUE)) { |
265 | lp->lksb.sb_status = -EAGAIN; | 263 | lp->lksb.sb_status = -EAGAIN; |
@@ -268,7 +266,7 @@ unsigned int gdlm_do_lock(struct gdlm_lock *lp) | |||
268 | } | 266 | } |
269 | 267 | ||
270 | if (error) { | 268 | if (error) { |
271 | log_debug("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x " | 269 | log_error("%s: gdlm_lock %x,%llx err=%d cur=%d req=%d lkf=%x " |
272 | "flags=%lx", ls->fsname, lp->lockname.ln_type, | 270 | "flags=%lx", ls->fsname, lp->lockname.ln_type, |
273 | (unsigned long long)lp->lockname.ln_number, error, | 271 | (unsigned long long)lp->lockname.ln_number, error, |
274 | lp->cur, lp->req, lp->lkf, lp->flags); | 272 | lp->cur, lp->req, lp->lkf, lp->flags); |
@@ -296,7 +294,7 @@ static unsigned int gdlm_do_unlock(struct gdlm_lock *lp) | |||
296 | error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp); | 294 | error = dlm_unlock(ls->dlm_lockspace, lp->lksb.sb_lkid, lkf, NULL, lp); |
297 | 295 | ||
298 | if (error) { | 296 | if (error) { |
299 | log_debug("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x " | 297 | log_error("%s: gdlm_unlock %x,%llx err=%d cur=%d req=%d lkf=%x " |
300 | "flags=%lx", ls->fsname, lp->lockname.ln_type, | 298 | "flags=%lx", ls->fsname, lp->lockname.ln_type, |
301 | (unsigned long long)lp->lockname.ln_number, error, | 299 | (unsigned long long)lp->lockname.ln_number, error, |
302 | lp->cur, lp->req, lp->lkf, lp->flags); | 300 | lp->cur, lp->req, lp->lkf, lp->flags); |
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h index a87c7bf3c568..d074c6e6f9bf 100644 --- a/fs/gfs2/locking/dlm/lock_dlm.h +++ b/fs/gfs2/locking/dlm/lock_dlm.h | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | #define GDLM_STRNAME_BYTES 24 | 37 | #define GDLM_STRNAME_BYTES 24 |
38 | #define GDLM_LVB_SIZE 32 | 38 | #define GDLM_LVB_SIZE 32 |
39 | #define GDLM_DROP_COUNT 200000 | 39 | #define GDLM_DROP_COUNT 0 |
40 | #define GDLM_DROP_PERIOD 60 | 40 | #define GDLM_DROP_PERIOD 60 |
41 | #define GDLM_NAME_LEN 128 | 41 | #define GDLM_NAME_LEN 128 |
42 | 42 | ||
@@ -106,6 +106,7 @@ enum { | |||
106 | struct gdlm_lock { | 106 | struct gdlm_lock { |
107 | struct gdlm_ls *ls; | 107 | struct gdlm_ls *ls; |
108 | struct lm_lockname lockname; | 108 | struct lm_lockname lockname; |
109 | struct gdlm_strname strname; | ||
109 | char *lvb; | 110 | char *lvb; |
110 | struct dlm_lksb lksb; | 111 | struct dlm_lksb lksb; |
111 | 112 | ||
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 16bb4b4561ae..f82d84d05d23 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -33,16 +33,17 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
33 | 33 | ||
34 | tr->tr_touched = 1; | 34 | tr->tr_touched = 1; |
35 | 35 | ||
36 | if (!list_empty(&le->le_list)) | ||
37 | return; | ||
38 | |||
39 | gl = container_of(le, struct gfs2_glock, gl_le); | 36 | gl = container_of(le, struct gfs2_glock, gl_le); |
40 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) | 37 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) |
41 | return; | 38 | return; |
42 | gfs2_glock_hold(gl); | ||
43 | set_bit(GLF_DIRTY, &gl->gl_flags); | ||
44 | 39 | ||
45 | gfs2_log_lock(sdp); | 40 | gfs2_log_lock(sdp); |
41 | if (!list_empty(&le->le_list)){ | ||
42 | gfs2_log_unlock(sdp); | ||
43 | return; | ||
44 | } | ||
45 | gfs2_glock_hold(gl); | ||
46 | set_bit(GLF_DIRTY, &gl->gl_flags); | ||
46 | sdp->sd_log_num_gl++; | 47 | sdp->sd_log_num_gl++; |
47 | list_add(&le->le_list, &sdp->sd_log_le_gl); | 48 | list_add(&le->le_list, &sdp->sd_log_le_gl); |
48 | gfs2_log_unlock(sdp); | 49 | gfs2_log_unlock(sdp); |
@@ -415,13 +416,14 @@ static void rg_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
415 | 416 | ||
416 | tr->tr_touched = 1; | 417 | tr->tr_touched = 1; |
417 | 418 | ||
418 | if (!list_empty(&le->le_list)) | ||
419 | return; | ||
420 | |||
421 | rgd = container_of(le, struct gfs2_rgrpd, rd_le); | 419 | rgd = container_of(le, struct gfs2_rgrpd, rd_le); |
422 | gfs2_rgrp_bh_hold(rgd); | ||
423 | 420 | ||
424 | gfs2_log_lock(sdp); | 421 | gfs2_log_lock(sdp); |
422 | if (!list_empty(&le->le_list)){ | ||
423 | gfs2_log_unlock(sdp); | ||
424 | return; | ||
425 | } | ||
426 | gfs2_rgrp_bh_hold(rgd); | ||
425 | sdp->sd_log_num_rg++; | 427 | sdp->sd_log_num_rg++; |
426 | list_add(&le->le_list, &sdp->sd_log_le_rg); | 428 | list_add(&le->le_list, &sdp->sd_log_le_rg); |
427 | gfs2_log_unlock(sdp); | 429 | gfs2_log_unlock(sdp); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index e2bffae683cc..e460487c0557 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -43,7 +43,6 @@ static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned | |||
43 | spin_lock_init(&gl->gl_spin); | 43 | spin_lock_init(&gl->gl_spin); |
44 | INIT_LIST_HEAD(&gl->gl_holders); | 44 | INIT_LIST_HEAD(&gl->gl_holders); |
45 | INIT_LIST_HEAD(&gl->gl_waiters1); | 45 | INIT_LIST_HEAD(&gl->gl_waiters1); |
46 | INIT_LIST_HEAD(&gl->gl_waiters2); | ||
47 | INIT_LIST_HEAD(&gl->gl_waiters3); | 46 | INIT_LIST_HEAD(&gl->gl_waiters3); |
48 | gl->gl_lvb = NULL; | 47 | gl->gl_lvb = NULL; |
49 | atomic_set(&gl->gl_lvb_count, 0); | 48 | atomic_set(&gl->gl_lvb_count, 0); |
@@ -101,6 +100,8 @@ static int __init init_gfs2_fs(void) | |||
101 | if (error) | 100 | if (error) |
102 | goto fail_unregister; | 101 | goto fail_unregister; |
103 | 102 | ||
103 | gfs2_register_debugfs(); | ||
104 | |||
104 | printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); | 105 | printk("GFS2 (built %s %s) installed\n", __DATE__, __TIME__); |
105 | 106 | ||
106 | return 0; | 107 | return 0; |
@@ -128,6 +129,7 @@ fail: | |||
128 | 129 | ||
129 | static void __exit exit_gfs2_fs(void) | 130 | static void __exit exit_gfs2_fs(void) |
130 | { | 131 | { |
132 | gfs2_unregister_debugfs(); | ||
131 | unregister_filesystem(&gfs2_fs_type); | 133 | unregister_filesystem(&gfs2_fs_type); |
132 | unregister_filesystem(&gfs2meta_fs_type); | 134 | unregister_filesystem(&gfs2meta_fs_type); |
133 | 135 | ||
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c index 32caecd20300..4864659555d4 100644 --- a/fs/gfs2/mount.c +++ b/fs/gfs2/mount.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
14 | #include <linux/gfs2_ondisk.h> | 14 | #include <linux/gfs2_ondisk.h> |
15 | #include <linux/lm_interface.h> | 15 | #include <linux/lm_interface.h> |
16 | #include <linux/parser.h> | ||
16 | 17 | ||
17 | #include "gfs2.h" | 18 | #include "gfs2.h" |
18 | #include "incore.h" | 19 | #include "incore.h" |
@@ -20,6 +21,52 @@ | |||
20 | #include "sys.h" | 21 | #include "sys.h" |
21 | #include "util.h" | 22 | #include "util.h" |
22 | 23 | ||
24 | enum { | ||
25 | Opt_lockproto, | ||
26 | Opt_locktable, | ||
27 | Opt_hostdata, | ||
28 | Opt_spectator, | ||
29 | Opt_ignore_local_fs, | ||
30 | Opt_localflocks, | ||
31 | Opt_localcaching, | ||
32 | Opt_debug, | ||
33 | Opt_nodebug, | ||
34 | Opt_upgrade, | ||
35 | Opt_num_glockd, | ||
36 | Opt_acl, | ||
37 | Opt_noacl, | ||
38 | Opt_quota_off, | ||
39 | Opt_quota_account, | ||
40 | Opt_quota_on, | ||
41 | Opt_suiddir, | ||
42 | Opt_nosuiddir, | ||
43 | Opt_data_writeback, | ||
44 | Opt_data_ordered, | ||
45 | }; | ||
46 | |||
47 | static match_table_t tokens = { | ||
48 | {Opt_lockproto, "lockproto=%s"}, | ||
49 | {Opt_locktable, "locktable=%s"}, | ||
50 | {Opt_hostdata, "hostdata=%s"}, | ||
51 | {Opt_spectator, "spectator"}, | ||
52 | {Opt_ignore_local_fs, "ignore_local_fs"}, | ||
53 | {Opt_localflocks, "localflocks"}, | ||
54 | {Opt_localcaching, "localcaching"}, | ||
55 | {Opt_debug, "debug"}, | ||
56 | {Opt_nodebug, "nodebug"}, | ||
57 | {Opt_upgrade, "upgrade"}, | ||
58 | {Opt_num_glockd, "num_glockd=%d"}, | ||
59 | {Opt_acl, "acl"}, | ||
60 | {Opt_noacl, "noacl"}, | ||
61 | {Opt_quota_off, "quota=off"}, | ||
62 | {Opt_quota_account, "quota=account"}, | ||
63 | {Opt_quota_on, "quota=on"}, | ||
64 | {Opt_suiddir, "suiddir"}, | ||
65 | {Opt_nosuiddir, "nosuiddir"}, | ||
66 | {Opt_data_writeback, "data=writeback"}, | ||
67 | {Opt_data_ordered, "data=ordered"} | ||
68 | }; | ||
69 | |||
23 | /** | 70 | /** |
24 | * gfs2_mount_args - Parse mount options | 71 | * gfs2_mount_args - Parse mount options |
25 | * @sdp: | 72 | * @sdp: |
@@ -54,146 +101,150 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
54 | process them */ | 101 | process them */ |
55 | 102 | ||
56 | for (options = data; (o = strsep(&options, ",")); ) { | 103 | for (options = data; (o = strsep(&options, ",")); ) { |
104 | int token, option; | ||
105 | substring_t tmp[MAX_OPT_ARGS]; | ||
106 | |||
57 | if (!*o) | 107 | if (!*o) |
58 | continue; | 108 | continue; |
59 | 109 | ||
60 | v = strchr(o, '='); | 110 | token = match_token(o, tokens, tmp); |
61 | if (v) | 111 | switch (token) { |
62 | *v++ = 0; | 112 | case Opt_lockproto: |
113 | v = match_strdup(&tmp[0]); | ||
114 | if (!v) { | ||
115 | fs_info(sdp, "no memory for lockproto\n"); | ||
116 | error = -ENOMEM; | ||
117 | goto out_error; | ||
118 | } | ||
63 | 119 | ||
64 | if (!strcmp(o, "lockproto")) { | 120 | if (remount && strcmp(v, args->ar_lockproto)) { |
65 | if (!v) | 121 | kfree(v); |
66 | goto need_value; | ||
67 | if (remount && strcmp(v, args->ar_lockproto)) | ||
68 | goto cant_remount; | 122 | goto cant_remount; |
123 | } | ||
124 | |||
69 | strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); | 125 | strncpy(args->ar_lockproto, v, GFS2_LOCKNAME_LEN); |
70 | args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; | 126 | args->ar_lockproto[GFS2_LOCKNAME_LEN - 1] = 0; |
71 | } | 127 | kfree(v); |
128 | break; | ||
129 | case Opt_locktable: | ||
130 | v = match_strdup(&tmp[0]); | ||
131 | if (!v) { | ||
132 | fs_info(sdp, "no memory for locktable\n"); | ||
133 | error = -ENOMEM; | ||
134 | goto out_error; | ||
135 | } | ||
72 | 136 | ||
73 | else if (!strcmp(o, "locktable")) { | 137 | if (remount && strcmp(v, args->ar_locktable)) { |
74 | if (!v) | 138 | kfree(v); |
75 | goto need_value; | ||
76 | if (remount && strcmp(v, args->ar_locktable)) | ||
77 | goto cant_remount; | 139 | goto cant_remount; |
140 | } | ||
141 | |||
78 | strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); | 142 | strncpy(args->ar_locktable, v, GFS2_LOCKNAME_LEN); |
79 | args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; | 143 | args->ar_locktable[GFS2_LOCKNAME_LEN - 1] = 0; |
80 | } | 144 | kfree(v); |
145 | break; | ||
146 | case Opt_hostdata: | ||
147 | v = match_strdup(&tmp[0]); | ||
148 | if (!v) { | ||
149 | fs_info(sdp, "no memory for hostdata\n"); | ||
150 | error = -ENOMEM; | ||
151 | goto out_error; | ||
152 | } | ||
81 | 153 | ||
82 | else if (!strcmp(o, "hostdata")) { | 154 | if (remount && strcmp(v, args->ar_hostdata)) { |
83 | if (!v) | 155 | kfree(v); |
84 | goto need_value; | ||
85 | if (remount && strcmp(v, args->ar_hostdata)) | ||
86 | goto cant_remount; | 156 | goto cant_remount; |
157 | } | ||
158 | |||
87 | strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); | 159 | strncpy(args->ar_hostdata, v, GFS2_LOCKNAME_LEN); |
88 | args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; | 160 | args->ar_hostdata[GFS2_LOCKNAME_LEN - 1] = 0; |
89 | } | 161 | kfree(v); |
90 | 162 | break; | |
91 | else if (!strcmp(o, "spectator")) { | 163 | case Opt_spectator: |
92 | if (remount && !args->ar_spectator) | 164 | if (remount && !args->ar_spectator) |
93 | goto cant_remount; | 165 | goto cant_remount; |
94 | args->ar_spectator = 1; | 166 | args->ar_spectator = 1; |
95 | sdp->sd_vfs->s_flags |= MS_RDONLY; | 167 | sdp->sd_vfs->s_flags |= MS_RDONLY; |
96 | } | 168 | break; |
97 | 169 | case Opt_ignore_local_fs: | |
98 | else if (!strcmp(o, "ignore_local_fs")) { | ||
99 | if (remount && !args->ar_ignore_local_fs) | 170 | if (remount && !args->ar_ignore_local_fs) |
100 | goto cant_remount; | 171 | goto cant_remount; |
101 | args->ar_ignore_local_fs = 1; | 172 | args->ar_ignore_local_fs = 1; |
102 | } | 173 | break; |
103 | 174 | case Opt_localflocks: | |
104 | else if (!strcmp(o, "localflocks")) { | ||
105 | if (remount && !args->ar_localflocks) | 175 | if (remount && !args->ar_localflocks) |
106 | goto cant_remount; | 176 | goto cant_remount; |
107 | args->ar_localflocks = 1; | 177 | args->ar_localflocks = 1; |
108 | } | 178 | break; |
109 | 179 | case Opt_localcaching: | |
110 | else if (!strcmp(o, "localcaching")) { | ||
111 | if (remount && !args->ar_localcaching) | 180 | if (remount && !args->ar_localcaching) |
112 | goto cant_remount; | 181 | goto cant_remount; |
113 | args->ar_localcaching = 1; | 182 | args->ar_localcaching = 1; |
114 | } | 183 | break; |
115 | 184 | case Opt_debug: | |
116 | else if (!strcmp(o, "debug")) | ||
117 | args->ar_debug = 1; | 185 | args->ar_debug = 1; |
118 | 186 | break; | |
119 | else if (!strcmp(o, "nodebug")) | 187 | case Opt_nodebug: |
120 | args->ar_debug = 0; | 188 | args->ar_debug = 0; |
121 | 189 | break; | |
122 | else if (!strcmp(o, "upgrade")) { | 190 | case Opt_upgrade: |
123 | if (remount && !args->ar_upgrade) | 191 | if (remount && !args->ar_upgrade) |
124 | goto cant_remount; | 192 | goto cant_remount; |
125 | args->ar_upgrade = 1; | 193 | args->ar_upgrade = 1; |
126 | } | 194 | break; |
195 | case Opt_num_glockd: | ||
196 | if ((error = match_int(&tmp[0], &option))) { | ||
197 | fs_info(sdp, "problem getting num_glockd\n"); | ||
198 | goto out_error; | ||
199 | } | ||
127 | 200 | ||
128 | else if (!strcmp(o, "num_glockd")) { | 201 | if (remount && option != args->ar_num_glockd) |
129 | unsigned int x; | ||
130 | if (!v) | ||
131 | goto need_value; | ||
132 | sscanf(v, "%u", &x); | ||
133 | if (remount && x != args->ar_num_glockd) | ||
134 | goto cant_remount; | 202 | goto cant_remount; |
135 | if (!x || x > GFS2_GLOCKD_MAX) { | 203 | if (!option || option > GFS2_GLOCKD_MAX) { |
136 | fs_info(sdp, "0 < num_glockd <= %u (not %u)\n", | 204 | fs_info(sdp, "0 < num_glockd <= %u (not %u)\n", |
137 | GFS2_GLOCKD_MAX, x); | 205 | GFS2_GLOCKD_MAX, option); |
138 | error = -EINVAL; | 206 | error = -EINVAL; |
139 | break; | 207 | goto out_error; |
140 | } | 208 | } |
141 | args->ar_num_glockd = x; | 209 | args->ar_num_glockd = option; |
142 | } | 210 | break; |
143 | 211 | case Opt_acl: | |
144 | else if (!strcmp(o, "acl")) { | ||
145 | args->ar_posix_acl = 1; | 212 | args->ar_posix_acl = 1; |
146 | sdp->sd_vfs->s_flags |= MS_POSIXACL; | 213 | sdp->sd_vfs->s_flags |= MS_POSIXACL; |
147 | } | 214 | break; |
148 | 215 | case Opt_noacl: | |
149 | else if (!strcmp(o, "noacl")) { | ||
150 | args->ar_posix_acl = 0; | 216 | args->ar_posix_acl = 0; |
151 | sdp->sd_vfs->s_flags &= ~MS_POSIXACL; | 217 | sdp->sd_vfs->s_flags &= ~MS_POSIXACL; |
152 | } | 218 | break; |
153 | 219 | case Opt_quota_off: | |
154 | else if (!strcmp(o, "quota")) { | 220 | args->ar_quota = GFS2_QUOTA_OFF; |
155 | if (!v) | 221 | break; |
156 | goto need_value; | 222 | case Opt_quota_account: |
157 | if (!strcmp(v, "off")) | 223 | args->ar_quota = GFS2_QUOTA_ACCOUNT; |
158 | args->ar_quota = GFS2_QUOTA_OFF; | 224 | break; |
159 | else if (!strcmp(v, "account")) | 225 | case Opt_quota_on: |
160 | args->ar_quota = GFS2_QUOTA_ACCOUNT; | 226 | args->ar_quota = GFS2_QUOTA_ON; |
161 | else if (!strcmp(v, "on")) | 227 | break; |
162 | args->ar_quota = GFS2_QUOTA_ON; | 228 | case Opt_suiddir: |
163 | else { | ||
164 | fs_info(sdp, "invalid value for quota\n"); | ||
165 | error = -EINVAL; | ||
166 | break; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | else if (!strcmp(o, "suiddir")) | ||
171 | args->ar_suiddir = 1; | 229 | args->ar_suiddir = 1; |
172 | 230 | break; | |
173 | else if (!strcmp(o, "nosuiddir")) | 231 | case Opt_nosuiddir: |
174 | args->ar_suiddir = 0; | 232 | args->ar_suiddir = 0; |
175 | 233 | break; | |
176 | else if (!strcmp(o, "data")) { | 234 | case Opt_data_writeback: |
177 | if (!v) | 235 | args->ar_data = GFS2_DATA_WRITEBACK; |
178 | goto need_value; | 236 | break; |
179 | if (!strcmp(v, "writeback")) | 237 | case Opt_data_ordered: |
180 | args->ar_data = GFS2_DATA_WRITEBACK; | 238 | args->ar_data = GFS2_DATA_ORDERED; |
181 | else if (!strcmp(v, "ordered")) | 239 | break; |
182 | args->ar_data = GFS2_DATA_ORDERED; | 240 | default: |
183 | else { | ||
184 | fs_info(sdp, "invalid value for data\n"); | ||
185 | error = -EINVAL; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | else { | ||
191 | fs_info(sdp, "unknown option: %s\n", o); | 241 | fs_info(sdp, "unknown option: %s\n", o); |
192 | error = -EINVAL; | 242 | error = -EINVAL; |
193 | break; | 243 | goto out_error; |
194 | } | 244 | } |
195 | } | 245 | } |
196 | 246 | ||
247 | out_error: | ||
197 | if (error) | 248 | if (error) |
198 | fs_info(sdp, "invalid mount option(s)\n"); | 249 | fs_info(sdp, "invalid mount option(s)\n"); |
199 | 250 | ||
@@ -202,10 +253,6 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) | |||
202 | 253 | ||
203 | return error; | 254 | return error; |
204 | 255 | ||
205 | need_value: | ||
206 | fs_info(sdp, "need value for option %s\n", o); | ||
207 | return -EINVAL; | ||
208 | |||
209 | cant_remount: | 256 | cant_remount: |
210 | fs_info(sdp, "can't remount with option %s\n", o); | 257 | fs_info(sdp, "can't remount with option %s\n", o); |
211 | return -EINVAL; | 258 | return -EINVAL; |
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index b3b7e8475359..30c15622174f 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -197,7 +197,19 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) | |||
197 | void *kaddr; | 197 | void *kaddr; |
198 | int error; | 198 | int error; |
199 | 199 | ||
200 | BUG_ON(page->index); | 200 | /* |
201 | * Due to the order of unstuffing files and ->nopage(), we can be | ||
202 | * asked for a zero page in the case of a stuffed file being extended, | ||
203 | * so we need to supply one here. It doesn't happen often. | ||
204 | */ | ||
205 | if (unlikely(page->index)) { | ||
206 | kaddr = kmap_atomic(page, KM_USER0); | ||
207 | memset(kaddr, 0, PAGE_CACHE_SIZE); | ||
208 | kunmap_atomic(kaddr, KM_USER0); | ||
209 | flush_dcache_page(page); | ||
210 | SetPageUptodate(page); | ||
211 | return 0; | ||
212 | } | ||
201 | 213 | ||
202 | error = gfs2_meta_inode_buffer(ip, &dibh); | 214 | error = gfs2_meta_inode_buffer(ip, &dibh); |
203 | if (error) | 215 | if (error) |
@@ -208,9 +220,8 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) | |||
208 | ip->i_di.di_size); | 220 | ip->i_di.di_size); |
209 | memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size); | 221 | memset(kaddr + ip->i_di.di_size, 0, PAGE_CACHE_SIZE - ip->i_di.di_size); |
210 | kunmap_atomic(kaddr, KM_USER0); | 222 | kunmap_atomic(kaddr, KM_USER0); |
211 | 223 | flush_dcache_page(page); | |
212 | brelse(dibh); | 224 | brelse(dibh); |
213 | |||
214 | SetPageUptodate(page); | 225 | SetPageUptodate(page); |
215 | 226 | ||
216 | return 0; | 227 | return 0; |
@@ -507,7 +518,9 @@ static int gfs2_commit_write(struct file *file, struct page *page, | |||
507 | gfs2_quota_unlock(ip); | 518 | gfs2_quota_unlock(ip); |
508 | gfs2_alloc_put(ip); | 519 | gfs2_alloc_put(ip); |
509 | } | 520 | } |
521 | unlock_page(page); | ||
510 | gfs2_glock_dq_m(1, &ip->i_gh); | 522 | gfs2_glock_dq_m(1, &ip->i_gh); |
523 | lock_page(page); | ||
511 | gfs2_holder_uninit(&ip->i_gh); | 524 | gfs2_holder_uninit(&ip->i_gh); |
512 | return 0; | 525 | return 0; |
513 | 526 | ||
@@ -520,7 +533,9 @@ fail_endtrans: | |||
520 | gfs2_quota_unlock(ip); | 533 | gfs2_quota_unlock(ip); |
521 | gfs2_alloc_put(ip); | 534 | gfs2_alloc_put(ip); |
522 | } | 535 | } |
536 | unlock_page(page); | ||
523 | gfs2_glock_dq_m(1, &ip->i_gh); | 537 | gfs2_glock_dq_m(1, &ip->i_gh); |
538 | lock_page(page); | ||
524 | gfs2_holder_uninit(&ip->i_gh); | 539 | gfs2_holder_uninit(&ip->i_gh); |
525 | fail_nounlock: | 540 | fail_nounlock: |
526 | ClearPageUptodate(page); | 541 | ClearPageUptodate(page); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ee54cb667083..2c5f8e7def0d 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -690,6 +690,8 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
690 | if (error) | 690 | if (error) |
691 | goto fail; | 691 | goto fail; |
692 | 692 | ||
693 | gfs2_create_debugfs_file(sdp); | ||
694 | |||
693 | error = gfs2_sys_fs_add(sdp); | 695 | error = gfs2_sys_fs_add(sdp); |
694 | if (error) | 696 | if (error) |
695 | goto fail; | 697 | goto fail; |
@@ -754,6 +756,7 @@ fail_lm: | |||
754 | fail_sys: | 756 | fail_sys: |
755 | gfs2_sys_fs_del(sdp); | 757 | gfs2_sys_fs_del(sdp); |
756 | fail: | 758 | fail: |
759 | gfs2_delete_debugfs_file(sdp); | ||
757 | kfree(sdp); | 760 | kfree(sdp); |
758 | sb->s_fs_info = NULL; | 761 | sb->s_fs_info = NULL; |
759 | return error; | 762 | return error; |
@@ -896,6 +899,7 @@ error: | |||
896 | 899 | ||
897 | static void gfs2_kill_sb(struct super_block *sb) | 900 | static void gfs2_kill_sb(struct super_block *sb) |
898 | { | 901 | { |
902 | gfs2_delete_debugfs_file(sb->s_fs_info); | ||
899 | kill_block_super(sb); | 903 | kill_block_super(sb); |
900 | } | 904 | } |
901 | 905 | ||
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index b89999d3a767..485ce3d49923 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -284,6 +284,31 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
284 | } | 284 | } |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * gfs2_drop_inode - Drop an inode (test for remote unlink) | ||
288 | * @inode: The inode to drop | ||
289 | * | ||
290 | * If we've received a callback on an iopen lock then its because a | ||
291 | * remote node tried to deallocate the inode but failed due to this node | ||
292 | * still having the inode open. Here we mark the link count zero | ||
293 | * since we know that it must have reached zero if the GLF_DEMOTE flag | ||
294 | * is set on the iopen glock. If we didn't do a disk read since the | ||
295 | * remote node removed the final link then we might otherwise miss | ||
296 | * this event. This check ensures that this node will deallocate the | ||
297 | * inode's blocks, or alternatively pass the baton on to another | ||
298 | * node for later deallocation. | ||
299 | */ | ||
300 | static void gfs2_drop_inode(struct inode *inode) | ||
301 | { | ||
302 | if (inode->i_private && inode->i_nlink) { | ||
303 | struct gfs2_inode *ip = GFS2_I(inode); | ||
304 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | ||
305 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | ||
306 | clear_nlink(inode); | ||
307 | } | ||
308 | generic_drop_inode(inode); | ||
309 | } | ||
310 | |||
311 | /** | ||
287 | * gfs2_clear_inode - Deallocate an inode when VFS is done with it | 312 | * gfs2_clear_inode - Deallocate an inode when VFS is done with it |
288 | * @inode: The VFS inode | 313 | * @inode: The VFS inode |
289 | * | 314 | * |
@@ -441,7 +466,7 @@ out_unlock: | |||
441 | out_uninit: | 466 | out_uninit: |
442 | gfs2_holder_uninit(&ip->i_iopen_gh); | 467 | gfs2_holder_uninit(&ip->i_iopen_gh); |
443 | gfs2_glock_dq_uninit(&gh); | 468 | gfs2_glock_dq_uninit(&gh); |
444 | if (error) | 469 | if (error && error != GLR_TRYFAILED) |
445 | fs_warn(sdp, "gfs2_delete_inode: %d\n", error); | 470 | fs_warn(sdp, "gfs2_delete_inode: %d\n", error); |
446 | out: | 471 | out: |
447 | truncate_inode_pages(&inode->i_data, 0); | 472 | truncate_inode_pages(&inode->i_data, 0); |
@@ -481,6 +506,7 @@ const struct super_operations gfs2_super_ops = { | |||
481 | .statfs = gfs2_statfs, | 506 | .statfs = gfs2_statfs, |
482 | .remount_fs = gfs2_remount_fs, | 507 | .remount_fs = gfs2_remount_fs, |
483 | .clear_inode = gfs2_clear_inode, | 508 | .clear_inode = gfs2_clear_inode, |
509 | .drop_inode = gfs2_drop_inode, | ||
484 | .show_options = gfs2_show_options, | 510 | .show_options = gfs2_show_options, |
485 | }; | 511 | }; |
486 | 512 | ||
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 8d9c08b5c4b6..1727f5012efe 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "trans.h" | 27 | #include "trans.h" |
28 | #include "ops_file.h" | 28 | #include "ops_file.h" |
29 | #include "util.h" | 29 | #include "util.h" |
30 | #include "log.h" | ||
30 | 31 | ||
31 | #define BFITNOENT ((u32)~0) | 32 | #define BFITNOENT ((u32)~0) |
32 | 33 | ||
@@ -697,8 +698,6 @@ struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip) | |||
697 | * @al: the struct gfs2_alloc structure describing the reservation | 698 | * @al: the struct gfs2_alloc structure describing the reservation |
698 | * | 699 | * |
699 | * If there's room for the requested blocks to be allocated from the RG: | 700 | * If there's room for the requested blocks to be allocated from the RG: |
700 | * Sets the $al_reserved_data field in @al. | ||
701 | * Sets the $al_reserved_meta field in @al. | ||
702 | * Sets the $al_rgd field in @al. | 701 | * Sets the $al_rgd field in @al. |
703 | * | 702 | * |
704 | * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) | 703 | * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) |
@@ -709,6 +708,9 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
709 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 708 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
710 | int ret = 0; | 709 | int ret = 0; |
711 | 710 | ||
711 | if (rgd->rd_rg.rg_flags & GFS2_RGF_NOALLOC) | ||
712 | return 0; | ||
713 | |||
712 | spin_lock(&sdp->sd_rindex_spin); | 714 | spin_lock(&sdp->sd_rindex_spin); |
713 | if (rgd->rd_free_clone >= al->al_requested) { | 715 | if (rgd->rd_free_clone >= al->al_requested) { |
714 | al->al_rgd = rgd; | 716 | al->al_rgd = rgd; |
@@ -941,9 +943,13 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
941 | rgd = gfs2_rgrpd_get_first(sdp); | 943 | rgd = gfs2_rgrpd_get_first(sdp); |
942 | 944 | ||
943 | if (rgd == begin) { | 945 | if (rgd == begin) { |
944 | if (++loops >= 2 || !skipped) | 946 | if (++loops >= 3) |
945 | return -ENOSPC; | 947 | return -ENOSPC; |
948 | if (!skipped) | ||
949 | loops++; | ||
946 | flags = 0; | 950 | flags = 0; |
951 | if (loops == 2) | ||
952 | gfs2_log_flush(sdp, NULL); | ||
947 | } | 953 | } |
948 | } | 954 | } |
949 | 955 | ||