diff options
Diffstat (limited to 'fs/gfs2/glock.c')
| -rw-r--r-- | fs/gfs2/glock.c | 75 | 
1 files changed, 24 insertions, 51 deletions
| diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f42663325931..454d4b4eb36b 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/list.h> | 19 | #include <linux/list.h> | 
| 20 | #include <linux/wait.h> | 20 | #include <linux/wait.h> | 
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> | 
| 22 | #include <linux/rwsem.h> | ||
| 23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> | 
| 24 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> | 
| 25 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> | 
| @@ -60,7 +59,6 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); | |||
| 60 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) | 59 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) | 
| 61 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); | 60 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); | 
| 62 | 61 | ||
| 63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | ||
| 64 | static struct dentry *gfs2_root; | 62 | static struct dentry *gfs2_root; | 
| 65 | static struct workqueue_struct *glock_workqueue; | 63 | static struct workqueue_struct *glock_workqueue; | 
| 66 | struct workqueue_struct *gfs2_delete_workqueue; | 64 | struct workqueue_struct *gfs2_delete_workqueue; | 
| @@ -154,12 +152,14 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, | |||
| 154 | static void glock_free(struct gfs2_glock *gl) | 152 | static void glock_free(struct gfs2_glock *gl) | 
| 155 | { | 153 | { | 
| 156 | struct gfs2_sbd *sdp = gl->gl_sbd; | 154 | struct gfs2_sbd *sdp = gl->gl_sbd; | 
| 157 | struct inode *aspace = gl->gl_aspace; | 155 | struct address_space *mapping = gfs2_glock2aspace(gl); | 
| 156 | struct kmem_cache *cachep = gfs2_glock_cachep; | ||
| 158 | 157 | ||
| 159 | if (aspace) | 158 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); | 
| 160 | gfs2_aspace_put(aspace); | ||
| 161 | trace_gfs2_glock_put(gl); | 159 | trace_gfs2_glock_put(gl); | 
| 162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl); | 160 | if (mapping) | 
| 161 | cachep = gfs2_glock_aspace_cachep; | ||
| 162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl); | ||
| 163 | } | 163 | } | 
| 164 | 164 | ||
| 165 | /** | 165 | /** | 
| @@ -712,7 +712,6 @@ static void glock_work_func(struct work_struct *work) | |||
| 712 | finish_xmote(gl, gl->gl_reply); | 712 | finish_xmote(gl, gl->gl_reply); | 
| 713 | drop_ref = 1; | 713 | drop_ref = 1; | 
| 714 | } | 714 | } | 
| 715 | down_read(&gfs2_umount_flush_sem); | ||
| 716 | spin_lock(&gl->gl_spin); | 715 | spin_lock(&gl->gl_spin); | 
| 717 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && | 716 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && | 
| 718 | gl->gl_state != LM_ST_UNLOCKED && | 717 | gl->gl_state != LM_ST_UNLOCKED && | 
| @@ -725,7 +724,6 @@ static void glock_work_func(struct work_struct *work) | |||
| 725 | } | 724 | } | 
| 726 | run_queue(gl, 0); | 725 | run_queue(gl, 0); | 
| 727 | spin_unlock(&gl->gl_spin); | 726 | spin_unlock(&gl->gl_spin); | 
| 728 | up_read(&gfs2_umount_flush_sem); | ||
| 729 | if (!delay || | 727 | if (!delay || | 
| 730 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | 728 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | 
| 731 | gfs2_glock_put(gl); | 729 | gfs2_glock_put(gl); | 
| @@ -750,10 +748,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 750 | const struct gfs2_glock_operations *glops, int create, | 748 | const struct gfs2_glock_operations *glops, int create, | 
| 751 | struct gfs2_glock **glp) | 749 | struct gfs2_glock **glp) | 
| 752 | { | 750 | { | 
| 751 | struct super_block *s = sdp->sd_vfs; | ||
| 753 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; | 752 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; | 
| 754 | struct gfs2_glock *gl, *tmp; | 753 | struct gfs2_glock *gl, *tmp; | 
| 755 | unsigned int hash = gl_hash(sdp, &name); | 754 | unsigned int hash = gl_hash(sdp, &name); | 
| 756 | int error; | 755 | struct address_space *mapping; | 
| 757 | 756 | ||
| 758 | read_lock(gl_lock_addr(hash)); | 757 | read_lock(gl_lock_addr(hash)); | 
| 759 | gl = search_bucket(hash, sdp, &name); | 758 | gl = search_bucket(hash, sdp, &name); | 
| @@ -765,7 +764,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 765 | if (!create) | 764 | if (!create) | 
| 766 | return -ENOENT; | 765 | return -ENOENT; | 
| 767 | 766 | ||
| 768 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | 767 | if (glops->go_flags & GLOF_ASPACE) | 
| 768 | gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL); | ||
| 769 | else | ||
| 770 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | ||
| 769 | if (!gl) | 771 | if (!gl) | 
| 770 | return -ENOMEM; | 772 | return -ENOMEM; | 
| 771 | 773 | ||
| @@ -784,18 +786,18 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 784 | gl->gl_tchange = jiffies; | 786 | gl->gl_tchange = jiffies; | 
| 785 | gl->gl_object = NULL; | 787 | gl->gl_object = NULL; | 
| 786 | gl->gl_sbd = sdp; | 788 | gl->gl_sbd = sdp; | 
| 787 | gl->gl_aspace = NULL; | ||
| 788 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 789 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 
| 789 | INIT_WORK(&gl->gl_delete, delete_work_func); | 790 | INIT_WORK(&gl->gl_delete, delete_work_func); | 
| 790 | 791 | ||
| 791 | /* If this glock protects actual on-disk data or metadata blocks, | 792 | mapping = gfs2_glock2aspace(gl); | 
| 792 | create a VFS inode to manage the pages/buffers holding them. */ | 793 | if (mapping) { | 
| 793 | if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) { | 794 | mapping->a_ops = &gfs2_meta_aops; | 
| 794 | gl->gl_aspace = gfs2_aspace_get(sdp); | 795 | mapping->host = s->s_bdev->bd_inode; | 
| 795 | if (!gl->gl_aspace) { | 796 | mapping->flags = 0; | 
| 796 | error = -ENOMEM; | 797 | mapping_set_gfp_mask(mapping, GFP_NOFS); | 
| 797 | goto fail; | 798 | mapping->assoc_mapping = NULL; | 
| 798 | } | 799 | mapping->backing_dev_info = s->s_bdi; | 
| 800 | mapping->writeback_index = 0; | ||
| 799 | } | 801 | } | 
| 800 | 802 | ||
| 801 | write_lock(gl_lock_addr(hash)); | 803 | write_lock(gl_lock_addr(hash)); | 
| @@ -812,10 +814,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
| 812 | *glp = gl; | 814 | *glp = gl; | 
| 813 | 815 | ||
| 814 | return 0; | 816 | return 0; | 
| 815 | |||
| 816 | fail: | ||
| 817 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
| 818 | return error; | ||
| 819 | } | 817 | } | 
| 820 | 818 | ||
| 821 | /** | 819 | /** | 
| @@ -1510,35 +1508,10 @@ void gfs2_glock_thaw(struct gfs2_sbd *sdp) | |||
| 1510 | 1508 | ||
| 1511 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | 1509 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | 
| 1512 | { | 1510 | { | 
| 1513 | unsigned long t; | ||
| 1514 | unsigned int x; | 1511 | unsigned int x; | 
| 1515 | int cont; | ||
| 1516 | 1512 | ||
| 1517 | t = jiffies; | 1513 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) | 
| 1518 | 1514 | examine_bucket(clear_glock, sdp, x); | |
| 1519 | for (;;) { | ||
| 1520 | cont = 0; | ||
| 1521 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) { | ||
| 1522 | if (examine_bucket(clear_glock, sdp, x)) | ||
| 1523 | cont = 1; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | if (!cont) | ||
| 1527 | break; | ||
| 1528 | |||
| 1529 | if (time_after_eq(jiffies, | ||
| 1530 | t + gfs2_tune_get(sdp, gt_stall_secs) * HZ)) { | ||
| 1531 | fs_warn(sdp, "Unmount seems to be stalled. " | ||
| 1532 | "Dumping lock state...\n"); | ||
| 1533 | gfs2_dump_lockstate(sdp); | ||
| 1534 | t = jiffies; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | down_write(&gfs2_umount_flush_sem); | ||
| 1538 | invalidate_inodes(sdp->sd_vfs); | ||
| 1539 | up_write(&gfs2_umount_flush_sem); | ||
| 1540 | msleep(10); | ||
| 1541 | } | ||
| 1542 | flush_workqueue(glock_workqueue); | 1515 | flush_workqueue(glock_workqueue); | 
| 1543 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); | 1516 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); | 
| 1544 | gfs2_dump_lockstate(sdp); | 1517 | gfs2_dump_lockstate(sdp); | 
| @@ -1685,7 +1658,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) | |||
| 1685 | dtime *= 1000000/HZ; /* demote time in uSec */ | 1658 | dtime *= 1000000/HZ; /* demote time in uSec */ | 
| 1686 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1659 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) | 
| 1687 | dtime = 0; | 1660 | dtime = 0; | 
| 1688 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n", | 1661 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d r:%d\n", | 
| 1689 | state2str(gl->gl_state), | 1662 | state2str(gl->gl_state), | 
| 1690 | gl->gl_name.ln_type, | 1663 | gl->gl_name.ln_type, | 
| 1691 | (unsigned long long)gl->gl_name.ln_number, | 1664 | (unsigned long long)gl->gl_name.ln_number, | 
