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 | ||
