diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-02-10 00:29:41 -0800 |
|---|---|---|
| committer | Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> | 2003-02-10 00:29:41 -0800 |
| commit | 8d49bf3f9d4f6d61f0f759f75e79caaee6dcc6e4 (patch) | |
| tree | a664f0a82eae712c1051157d38c3ed15714a8a19 /include/linux/buffer_head.h | |
| parent | 3d9d68595649eacc0fee8d6cae3081ee78cd9c4a (diff) | |
[PATCH] Fix synchronous writers to wait properly for the result
Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> points out a bug in
ll_rw_block() usage.
Typical usage is:
mark_buffer_dirty(bh);
ll_rw_block(WRITE, 1, &bh);
wait_on_buffer(bh);
the problem is that if the buffer was locked on entry to this code sequence
(due to in-progress I/O), ll_rw_block() will not wait, and start new I/O. So
this code will wait on the _old_ I/O, and will then continue execution,
leaving the buffer dirty.
It turns out that all callers were only writing one buffer, and they were all
waiting on that writeout. So I added a new sync_dirty_buffer() function:
void sync_dirty_buffer(struct buffer_head *bh)
{
lock_buffer(bh);
if (test_clear_buffer_dirty(bh)) {
get_bh(bh);
bh->b_end_io = end_buffer_io_sync;
submit_bh(WRITE, bh);
} else {
unlock_buffer(bh);
}
}
which allowed a fair amount of code to be removed, while adding the desired
data-integrity guarantees.
UFS has its own wrappers around ll_rw_block() which got in the way, so this
operation was open-coded in that case.
Diffstat (limited to 'include/linux/buffer_head.h')
| -rw-r--r-- | include/linux/buffer_head.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index aaefe4e964b7..8def67e47d28 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -169,6 +169,7 @@ struct buffer_head *alloc_buffer_head(void); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); void ll_rw_block(int, int, struct buffer_head * bh[]); +void sync_dirty_buffer(struct buffer_head *bh); int submit_bh(int, struct buffer_head *); void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); |
