diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2007-08-27 08:54:05 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2007-10-10 03:56:00 -0400 |
commit | 9b9107a5a8b190e6cf09bbdf893869c6a9c482cc (patch) | |
tree | 77016dd5476f6ba72605ac0cdcbccec3ce794057 /fs/gfs2 | |
parent | eaf965270ffff3086ef929e660ace45e862cfd2d (diff) |
[GFS2] Move pin/unpin into lops.c, clean up locking
gfs2_pin and gfs2_unpin are only used in lops.c, despite being
defined in meta_io.c, so this patch moves them into lops.c and
makes them static. At the same time, its possible to clean up
the locking in the buf and databuf _lo_add() functions so that
we only need to grab the spinlock once. Also we have to move
lock_buffer() around the _lo_add() functions since we can't
do that in gfs2_pin() any more since we hold the spinlock
for the duration of that function.
As a result, the code shrinks by 12 lines and we do far fewer
operations when adding buffers to the log. It also makes the
code somewhat easier to read & understand.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/lops.c | 117 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 70 | ||||
-rw-r--r-- | fs/gfs2/meta_io.h | 3 |
3 files changed, 89 insertions, 101 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 7ef335623373..3ec587135d46 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -27,7 +27,71 @@ | |||
27 | #include "trans.h" | 27 | #include "trans.h" |
28 | #include "util.h" | 28 | #include "util.h" |
29 | 29 | ||
30 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | 30 | /** |
31 | * gfs2_pin - Pin a buffer in memory | ||
32 | * @sdp: The superblock | ||
33 | * @bh: The buffer to be pinned | ||
34 | * | ||
35 | * The log lock must be held when calling this function | ||
36 | */ | ||
37 | static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
38 | { | ||
39 | struct gfs2_bufdata *bd; | ||
40 | |||
41 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | ||
42 | |||
43 | clear_buffer_dirty(bh); | ||
44 | if (test_set_buffer_pinned(bh)) | ||
45 | gfs2_assert_withdraw(sdp, 0); | ||
46 | if (!buffer_uptodate(bh)) | ||
47 | gfs2_io_error_bh(sdp, bh); | ||
48 | bd = bh->b_private; | ||
49 | /* If this buffer is in the AIL and it has already been written | ||
50 | * to in-place disk block, remove it from the AIL. | ||
51 | */ | ||
52 | if (bd->bd_ail) | ||
53 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | ||
54 | get_bh(bh); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * gfs2_unpin - Unpin a buffer | ||
59 | * @sdp: the filesystem the buffer belongs to | ||
60 | * @bh: The buffer to unpin | ||
61 | * @ai: | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
66 | struct gfs2_ail *ai) | ||
67 | { | ||
68 | struct gfs2_bufdata *bd = bh->b_private; | ||
69 | |||
70 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | ||
71 | |||
72 | if (!buffer_pinned(bh)) | ||
73 | gfs2_assert_withdraw(sdp, 0); | ||
74 | |||
75 | lock_buffer(bh); | ||
76 | mark_buffer_dirty(bh); | ||
77 | clear_buffer_pinned(bh); | ||
78 | |||
79 | gfs2_log_lock(sdp); | ||
80 | if (bd->bd_ail) { | ||
81 | list_del(&bd->bd_ail_st_list); | ||
82 | brelse(bh); | ||
83 | } else { | ||
84 | struct gfs2_glock *gl = bd->bd_gl; | ||
85 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | ||
86 | atomic_inc(&gl->gl_ail_count); | ||
87 | } | ||
88 | bd->bd_ail = ai; | ||
89 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | ||
90 | gfs2_log_unlock(sdp); | ||
91 | unlock_buffer(bh); | ||
92 | } | ||
93 | |||
94 | static void __glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
31 | { | 95 | { |
32 | struct gfs2_glock *gl; | 96 | struct gfs2_glock *gl; |
33 | struct gfs2_trans *tr = current->journal_info; | 97 | struct gfs2_trans *tr = current->journal_info; |
@@ -38,15 +102,19 @@ static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
38 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) | 102 | if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(gl))) |
39 | return; | 103 | return; |
40 | 104 | ||
41 | gfs2_log_lock(sdp); | 105 | if (!list_empty(&le->le_list)) |
42 | if (!list_empty(&le->le_list)){ | ||
43 | gfs2_log_unlock(sdp); | ||
44 | return; | 106 | return; |
45 | } | 107 | |
46 | gfs2_glock_hold(gl); | 108 | gfs2_glock_hold(gl); |
47 | set_bit(GLF_DIRTY, &gl->gl_flags); | 109 | set_bit(GLF_DIRTY, &gl->gl_flags); |
48 | sdp->sd_log_num_gl++; | 110 | sdp->sd_log_num_gl++; |
49 | list_add(&le->le_list, &sdp->sd_log_le_gl); | 111 | list_add(&le->le_list, &sdp->sd_log_le_gl); |
112 | } | ||
113 | |||
114 | static void glock_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | ||
115 | { | ||
116 | gfs2_log_lock(sdp); | ||
117 | __glock_lo_add(sdp, le); | ||
50 | gfs2_log_unlock(sdp); | 118 | gfs2_log_unlock(sdp); |
51 | } | 119 | } |
52 | 120 | ||
@@ -71,30 +139,25 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
71 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); | 139 | struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); |
72 | struct gfs2_trans *tr; | 140 | struct gfs2_trans *tr; |
73 | 141 | ||
142 | lock_buffer(bd->bd_bh); | ||
74 | gfs2_log_lock(sdp); | 143 | gfs2_log_lock(sdp); |
75 | if (!list_empty(&bd->bd_list_tr)) { | 144 | if (!list_empty(&bd->bd_list_tr)) |
76 | gfs2_log_unlock(sdp); | 145 | goto out; |
77 | return; | ||
78 | } | ||
79 | tr = current->journal_info; | 146 | tr = current->journal_info; |
80 | tr->tr_touched = 1; | 147 | tr->tr_touched = 1; |
81 | tr->tr_num_buf++; | 148 | tr->tr_num_buf++; |
82 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 149 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
83 | gfs2_log_unlock(sdp); | ||
84 | |||
85 | if (!list_empty(&le->le_list)) | 150 | if (!list_empty(&le->le_list)) |
86 | return; | 151 | goto out; |
87 | 152 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); | |
88 | gfs2_trans_add_gl(bd->bd_gl); | ||
89 | |||
90 | gfs2_meta_check(sdp, bd->bd_bh); | 153 | gfs2_meta_check(sdp, bd->bd_bh); |
91 | gfs2_pin(sdp, bd->bd_bh); | 154 | gfs2_pin(sdp, bd->bd_bh); |
92 | gfs2_log_lock(sdp); | ||
93 | sdp->sd_log_num_buf++; | 155 | sdp->sd_log_num_buf++; |
94 | list_add(&le->le_list, &sdp->sd_log_le_buf); | 156 | list_add(&le->le_list, &sdp->sd_log_le_buf); |
95 | gfs2_log_unlock(sdp); | ||
96 | |||
97 | tr->tr_num_buf_new++; | 157 | tr->tr_num_buf_new++; |
158 | out: | ||
159 | gfs2_log_unlock(sdp); | ||
160 | unlock_buffer(bd->bd_bh); | ||
98 | } | 161 | } |
99 | 162 | ||
100 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) | 163 | static void buf_lo_incore_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr) |
@@ -476,31 +539,29 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
476 | struct address_space *mapping = bd->bd_bh->b_page->mapping; | 539 | struct address_space *mapping = bd->bd_bh->b_page->mapping; |
477 | struct gfs2_inode *ip = GFS2_I(mapping->host); | 540 | struct gfs2_inode *ip = GFS2_I(mapping->host); |
478 | 541 | ||
542 | lock_buffer(bd->bd_bh); | ||
479 | gfs2_log_lock(sdp); | 543 | gfs2_log_lock(sdp); |
480 | if (!list_empty(&bd->bd_list_tr)) { | 544 | if (!list_empty(&bd->bd_list_tr)) |
481 | gfs2_log_unlock(sdp); | 545 | goto out; |
482 | return; | ||
483 | } | ||
484 | tr->tr_touched = 1; | 546 | tr->tr_touched = 1; |
485 | if (gfs2_is_jdata(ip)) { | 547 | if (gfs2_is_jdata(ip)) { |
486 | tr->tr_num_buf++; | 548 | tr->tr_num_buf++; |
487 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); | 549 | list_add(&bd->bd_list_tr, &tr->tr_list_buf); |
488 | } | 550 | } |
489 | gfs2_log_unlock(sdp); | ||
490 | if (!list_empty(&le->le_list)) | 551 | if (!list_empty(&le->le_list)) |
491 | return; | 552 | goto out; |
492 | 553 | ||
493 | gfs2_trans_add_gl(bd->bd_gl); | 554 | __glock_lo_add(sdp, &bd->bd_gl->gl_le); |
494 | if (gfs2_is_jdata(ip)) { | 555 | if (gfs2_is_jdata(ip)) { |
495 | gfs2_pin(sdp, bd->bd_bh); | 556 | gfs2_pin(sdp, bd->bd_bh); |
496 | tr->tr_num_databuf_new++; | 557 | tr->tr_num_databuf_new++; |
497 | } | ||
498 | gfs2_log_lock(sdp); | ||
499 | if (gfs2_is_jdata(ip)) | ||
500 | sdp->sd_log_num_jdata++; | 558 | sdp->sd_log_num_jdata++; |
559 | } | ||
501 | sdp->sd_log_num_databuf++; | 560 | sdp->sd_log_num_databuf++; |
502 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | 561 | list_add(&le->le_list, &sdp->sd_log_le_databuf); |
562 | out: | ||
503 | gfs2_log_unlock(sdp); | 563 | gfs2_log_unlock(sdp); |
564 | unlock_buffer(bd->bd_bh); | ||
504 | } | 565 | } |
505 | 566 | ||
506 | static int gfs2_check_magic(struct buffer_head *bh) | 567 | static int gfs2_check_magic(struct buffer_head *bh) |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 8da343b34ae7..d762e4f7044e 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -298,76 +298,6 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
298 | } | 298 | } |
299 | 299 | ||
300 | /** | 300 | /** |
301 | * gfs2_pin - Pin a buffer in memory | ||
302 | * @sdp: the filesystem the buffer belongs to | ||
303 | * @bh: The buffer to be pinned | ||
304 | * | ||
305 | */ | ||
306 | |||
307 | void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh) | ||
308 | { | ||
309 | struct gfs2_bufdata *bd = bh->b_private; | ||
310 | |||
311 | gfs2_assert_withdraw(sdp, test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)); | ||
312 | |||
313 | if (test_set_buffer_pinned(bh)) | ||
314 | gfs2_assert_withdraw(sdp, 0); | ||
315 | |||
316 | wait_on_buffer(bh); | ||
317 | |||
318 | /* If this buffer is in the AIL and it has already been written | ||
319 | to in-place disk block, remove it from the AIL. */ | ||
320 | |||
321 | gfs2_log_lock(sdp); | ||
322 | if (bd->bd_ail && !buffer_in_io(bh)) | ||
323 | list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list); | ||
324 | gfs2_log_unlock(sdp); | ||
325 | |||
326 | clear_buffer_dirty(bh); | ||
327 | wait_on_buffer(bh); | ||
328 | |||
329 | if (!buffer_uptodate(bh)) | ||
330 | gfs2_io_error_bh(sdp, bh); | ||
331 | |||
332 | get_bh(bh); | ||
333 | } | ||
334 | |||
335 | /** | ||
336 | * gfs2_unpin - Unpin a buffer | ||
337 | * @sdp: the filesystem the buffer belongs to | ||
338 | * @bh: The buffer to unpin | ||
339 | * @ai: | ||
340 | * | ||
341 | */ | ||
342 | |||
343 | void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
344 | struct gfs2_ail *ai) | ||
345 | { | ||
346 | struct gfs2_bufdata *bd = bh->b_private; | ||
347 | |||
348 | gfs2_assert_withdraw(sdp, buffer_uptodate(bh)); | ||
349 | |||
350 | if (!buffer_pinned(bh)) | ||
351 | gfs2_assert_withdraw(sdp, 0); | ||
352 | |||
353 | mark_buffer_dirty(bh); | ||
354 | clear_buffer_pinned(bh); | ||
355 | |||
356 | gfs2_log_lock(sdp); | ||
357 | if (bd->bd_ail) { | ||
358 | list_del(&bd->bd_ail_st_list); | ||
359 | brelse(bh); | ||
360 | } else { | ||
361 | struct gfs2_glock *gl = bd->bd_gl; | ||
362 | list_add(&bd->bd_ail_gl_list, &gl->gl_ail_list); | ||
363 | atomic_inc(&gl->gl_ail_count); | ||
364 | } | ||
365 | bd->bd_ail = ai; | ||
366 | list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list); | ||
367 | gfs2_log_unlock(sdp); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * gfs2_meta_wipe - make inode's buffers so they aren't dirty/pinned anymore | 301 | * gfs2_meta_wipe - make inode's buffers so they aren't dirty/pinned anymore |
372 | * @ip: the inode who owns the buffers | 302 | * @ip: the inode who owns the buffers |
373 | * @bstart: the first buffer in the run | 303 | * @bstart: the first buffer in the run |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index 527bf19d9690..fd67f07cd60e 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -50,9 +50,6 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); | |||
50 | 50 | ||
51 | void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | 51 | void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, |
52 | int meta); | 52 | int meta); |
53 | void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); | ||
54 | void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh, | ||
55 | struct gfs2_ail *ai); | ||
56 | 53 | ||
57 | void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); | 54 | void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); |
58 | 55 | ||