diff options
Diffstat (limited to 'fs/gfs2/log.c')
-rw-r--r-- | fs/gfs2/log.c | 34 |
1 files changed, 6 insertions, 28 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index e6a84f7a9b71..16c14441a371 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/completion.h> | 13 | #include <linux/completion.h> |
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/gfs2_ondisk.h> | 15 | #include <linux/gfs2_ondisk.h> |
16 | #include <linux/crc32.h> | ||
16 | #include <asm/semaphore.h> | 17 | #include <asm/semaphore.h> |
17 | 18 | ||
18 | #include "gfs2.h" | 19 | #include "gfs2.h" |
@@ -24,18 +25,13 @@ | |||
24 | #include "lops.h" | 25 | #include "lops.h" |
25 | #include "meta_io.h" | 26 | #include "meta_io.h" |
26 | #include "util.h" | 27 | #include "util.h" |
28 | #include "dir.h" | ||
27 | 29 | ||
28 | #define PULL 1 | 30 | #define PULL 1 |
29 | 31 | ||
30 | static void do_lock_wait(struct gfs2_sbd *sdp, wait_queue_head_t *wq, | ||
31 | atomic_t *a) | ||
32 | { | ||
33 | wait_event(*wq, atomic_read(a) ? 0 : 1); | ||
34 | } | ||
35 | |||
36 | static void lock_for_trans(struct gfs2_sbd *sdp) | 32 | static void lock_for_trans(struct gfs2_sbd *sdp) |
37 | { | 33 | { |
38 | do_lock_wait(sdp, &sdp->sd_log_trans_wq, &sdp->sd_log_flush_count); | 34 | wait_event(sdp->sd_log_trans_wq, atomic_read(&sdp->sd_log_flush_count) ? 0 : 1); |
39 | atomic_inc(&sdp->sd_log_trans_count); | 35 | atomic_inc(&sdp->sd_log_trans_count); |
40 | } | 36 | } |
41 | 37 | ||
@@ -49,7 +45,7 @@ static void unlock_from_trans(struct gfs2_sbd *sdp) | |||
49 | static void gfs2_lock_for_flush(struct gfs2_sbd *sdp) | 45 | static void gfs2_lock_for_flush(struct gfs2_sbd *sdp) |
50 | { | 46 | { |
51 | atomic_inc(&sdp->sd_log_flush_count); | 47 | atomic_inc(&sdp->sd_log_flush_count); |
52 | do_lock_wait(sdp, &sdp->sd_log_flush_wq, &sdp->sd_log_trans_count); | 48 | wait_event(sdp->sd_log_flush_wq, atomic_read(&sdp->sd_log_trans_count) ? 0 : 1); |
53 | } | 49 | } |
54 | 50 | ||
55 | static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp) | 51 | static void gfs2_unlock_from_flush(struct gfs2_sbd *sdp) |
@@ -191,37 +187,19 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail) | |||
191 | 187 | ||
192 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) | 188 | int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks) |
193 | { | 189 | { |
194 | LIST_HEAD(list); | ||
195 | unsigned int try = 0; | 190 | unsigned int try = 0; |
196 | 191 | ||
197 | if (gfs2_assert_warn(sdp, blks) || | 192 | if (gfs2_assert_warn(sdp, blks) || |
198 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) | 193 | gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks)) |
199 | return -EINVAL; | 194 | return -EINVAL; |
200 | 195 | ||
196 | mutex_lock(&sdp->sd_log_reserve_mutex); | ||
201 | for (;;) { | 197 | for (;;) { |
202 | gfs2_log_lock(sdp); | 198 | gfs2_log_lock(sdp); |
203 | if (list_empty(&list)) { | ||
204 | list_add_tail(&list, &sdp->sd_log_blks_list); | ||
205 | while (sdp->sd_log_blks_list.next != &list) { | ||
206 | DECLARE_WAITQUEUE(__wait_chan, current); | ||
207 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
208 | add_wait_queue(&sdp->sd_log_blks_wait, | ||
209 | &__wait_chan); | ||
210 | gfs2_log_unlock(sdp); | ||
211 | schedule(); | ||
212 | gfs2_log_lock(sdp); | ||
213 | remove_wait_queue(&sdp->sd_log_blks_wait, | ||
214 | &__wait_chan); | ||
215 | set_current_state(TASK_RUNNING); | ||
216 | } | ||
217 | } | ||
218 | /* Never give away the last block so we can | ||
219 | always pull the tail if we need to. */ | ||
220 | if (sdp->sd_log_blks_free > blks) { | 199 | if (sdp->sd_log_blks_free > blks) { |
221 | sdp->sd_log_blks_free -= blks; | 200 | sdp->sd_log_blks_free -= blks; |
222 | list_del(&list); | ||
223 | gfs2_log_unlock(sdp); | 201 | gfs2_log_unlock(sdp); |
224 | wake_up(&sdp->sd_log_blks_wait); | 202 | mutex_unlock(&sdp->sd_log_reserve_mutex); |
225 | break; | 203 | break; |
226 | } | 204 | } |
227 | 205 | ||