aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-08-19 12:30:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-08-19 12:30:12 -0400
commitd6a5e06cd17a3f901231e345e4acc1c3dab9fbb8 (patch)
tree4181f24300881fb9de4846ce2bb0edfda2a3b60d
parent7067552dfb382cef040326ab6dd0b8d642af3e64 (diff)
parent7bd9ee58a4fe026514266757e812cb89c3c945eb (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
Pull gfs2 fixes from Steven Whitehouse: "Out of these five patches, the one for ensuring that the number of revokes is not exceeded, and the one for checking the glock is not already held in gfs2_getxattr are the two most important. The latter can be triggered by selinux. The other three patches are very small and fix mostly fairly trivial issues" * git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes: GFS2: Check for glock already held in gfs2_getxattr GFS2: alloc_workqueue() doesn't return an ERR_PTR GFS2: don't overrun reserved revokes GFS2: WQ_NON_REENTRANT is meaningless and going away GFS2: Fix typo in gfs2_create_inode()
-rw-r--r--fs/gfs2/glock.c8
-rw-r--r--fs/gfs2/glops.c18
-rw-r--r--fs/gfs2/inode.c6
-rw-r--r--fs/gfs2/main.c2
4 files changed, 23 insertions, 11 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 9435384562a2..544a809819c3 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1838,14 +1838,14 @@ int __init gfs2_glock_init(void)
1838 1838
1839 glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM | 1839 glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
1840 WQ_HIGHPRI | WQ_FREEZABLE, 0); 1840 WQ_HIGHPRI | WQ_FREEZABLE, 0);
1841 if (IS_ERR(glock_workqueue)) 1841 if (!glock_workqueue)
1842 return PTR_ERR(glock_workqueue); 1842 return -ENOMEM;
1843 gfs2_delete_workqueue = alloc_workqueue("delete_workqueue", 1843 gfs2_delete_workqueue = alloc_workqueue("delete_workqueue",
1844 WQ_MEM_RECLAIM | WQ_FREEZABLE, 1844 WQ_MEM_RECLAIM | WQ_FREEZABLE,
1845 0); 1845 0);
1846 if (IS_ERR(gfs2_delete_workqueue)) { 1846 if (!gfs2_delete_workqueue) {
1847 destroy_workqueue(glock_workqueue); 1847 destroy_workqueue(glock_workqueue);
1848 return PTR_ERR(gfs2_delete_workqueue); 1848 return -ENOMEM;
1849 } 1849 }
1850 1850
1851 register_shrinker(&glock_shrinker); 1851 register_shrinker(&glock_shrinker);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 5f2e5224c51c..e2e0a90396e7 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -47,7 +47,8 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
47 * None of the buffers should be dirty, locked, or pinned. 47 * None of the buffers should be dirty, locked, or pinned.
48 */ 48 */
49 49
50static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync) 50static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
51 unsigned int nr_revokes)
51{ 52{
52 struct gfs2_sbd *sdp = gl->gl_sbd; 53 struct gfs2_sbd *sdp = gl->gl_sbd;
53 struct list_head *head = &gl->gl_ail_list; 54 struct list_head *head = &gl->gl_ail_list;
@@ -57,7 +58,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
57 58
58 gfs2_log_lock(sdp); 59 gfs2_log_lock(sdp);
59 spin_lock(&sdp->sd_ail_lock); 60 spin_lock(&sdp->sd_ail_lock);
60 list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) { 61 list_for_each_entry_safe_reverse(bd, tmp, head, bd_ail_gl_list) {
62 if (nr_revokes == 0)
63 break;
61 bh = bd->bd_bh; 64 bh = bd->bd_bh;
62 if (bh->b_state & b_state) { 65 if (bh->b_state & b_state) {
63 if (fsync) 66 if (fsync)
@@ -65,6 +68,7 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
65 gfs2_ail_error(gl, bh); 68 gfs2_ail_error(gl, bh);
66 } 69 }
67 gfs2_trans_add_revoke(sdp, bd); 70 gfs2_trans_add_revoke(sdp, bd);
71 nr_revokes--;
68 } 72 }
69 GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); 73 GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
70 spin_unlock(&sdp->sd_ail_lock); 74 spin_unlock(&sdp->sd_ail_lock);
@@ -91,7 +95,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
91 WARN_ON_ONCE(current->journal_info); 95 WARN_ON_ONCE(current->journal_info);
92 current->journal_info = &tr; 96 current->journal_info = &tr;
93 97
94 __gfs2_ail_flush(gl, 0); 98 __gfs2_ail_flush(gl, 0, tr.tr_revokes);
95 99
96 gfs2_trans_end(sdp); 100 gfs2_trans_end(sdp);
97 gfs2_log_flush(sdp, NULL); 101 gfs2_log_flush(sdp, NULL);
@@ -101,15 +105,19 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
101{ 105{
102 struct gfs2_sbd *sdp = gl->gl_sbd; 106 struct gfs2_sbd *sdp = gl->gl_sbd;
103 unsigned int revokes = atomic_read(&gl->gl_ail_count); 107 unsigned int revokes = atomic_read(&gl->gl_ail_count);
108 unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
104 int ret; 109 int ret;
105 110
106 if (!revokes) 111 if (!revokes)
107 return; 112 return;
108 113
109 ret = gfs2_trans_begin(sdp, 0, revokes); 114 while (revokes > max_revokes)
115 max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);
116
117 ret = gfs2_trans_begin(sdp, 0, max_revokes);
110 if (ret) 118 if (ret)
111 return; 119 return;
112 __gfs2_ail_flush(gl, fsync); 120 __gfs2_ail_flush(gl, fsync, max_revokes);
113 gfs2_trans_end(sdp); 121 gfs2_trans_end(sdp);
114 gfs2_log_flush(sdp, NULL); 122 gfs2_log_flush(sdp, NULL);
115} 123}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index bbb2715171cd..64915eeae5a7 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -594,7 +594,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
594 } 594 }
595 gfs2_glock_dq_uninit(ghs); 595 gfs2_glock_dq_uninit(ghs);
596 if (IS_ERR(d)) 596 if (IS_ERR(d))
597 return PTR_RET(d); 597 return PTR_ERR(d);
598 return error; 598 return error;
599 } else if (error != -ENOENT) { 599 } else if (error != -ENOENT) {
600 goto fail_gunlock; 600 goto fail_gunlock;
@@ -1750,6 +1750,10 @@ static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
1750 struct gfs2_holder gh; 1750 struct gfs2_holder gh;
1751 int ret; 1751 int ret;
1752 1752
1753 /* For selinux during lookup */
1754 if (gfs2_glock_is_locked_by_me(ip->i_gl))
1755 return generic_getxattr(dentry, name, data, size);
1756
1753 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); 1757 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh);
1754 ret = gfs2_glock_nq(&gh); 1758 ret = gfs2_glock_nq(&gh);
1755 if (ret == 0) { 1759 if (ret == 0) {
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index e04d0e09ee7b..7b0f5043cf24 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -155,7 +155,7 @@ static int __init init_gfs2_fs(void)
155 goto fail_wq; 155 goto fail_wq;
156 156
157 gfs2_control_wq = alloc_workqueue("gfs2_control", 157 gfs2_control_wq = alloc_workqueue("gfs2_control",
158 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_FREEZABLE, 0); 158 WQ_UNBOUND | WQ_FREEZABLE, 0);
159 if (!gfs2_control_wq) 159 if (!gfs2_control_wq)
160 goto fail_recovery; 160 goto fail_recovery;
161 161