patch-2.4.13 linux/fs/buffer.c
Next file: linux/fs/devfs/util.c
Previous file: linux/fs/block_dev.c
Back to the patch index
Back to the overall index
- Lines: 175
- Date:
Tue Oct 23 17:54:19 2001
- Orig file:
v2.4.12/linux/fs/buffer.c
- Orig date:
Tue Oct 9 17:06:53 2001
diff -u --recursive --new-file v2.4.12/linux/fs/buffer.c linux/fs/buffer.c
@@ -112,15 +112,16 @@
int dummy5; /* unused */
} b_un;
unsigned int data[N_PARAM];
-} bdf_prm = {{30, 64, 64, 256, 5*HZ, 30*HZ, 60, 0, 0}};
+} bdf_prm = {{40, 0, 0, 0, 5*HZ, 30*HZ, 60, 0, 0}};
/* These are the min and max parameter values that we will allow to be assigned */
int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 1*HZ, 0, 0, 0};
int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,10000*HZ, 6000*HZ, 100, 0, 0};
-inline void unlock_buffer(struct buffer_head *bh)
+void unlock_buffer(struct buffer_head *bh)
{
clear_bit(BH_Wait_IO, &bh->b_state);
+ clear_bit(BH_launder, &bh->b_state);
clear_bit(BH_Lock, &bh->b_state);
smp_mb__after_clear_bit();
if (waitqueue_active(&bh->b_wait))
@@ -480,10 +481,12 @@
static __inline__ void __hash_unlink(struct buffer_head *bh)
{
- if (bh->b_pprev) {
- if (bh->b_next)
- bh->b_next->b_pprev = bh->b_pprev;
- *(bh->b_pprev) = bh->b_next;
+ struct buffer_head **pprev = bh->b_pprev;
+ if (pprev) {
+ struct buffer_head *next = bh->b_next;
+ if (next)
+ next->b_pprev = pprev;
+ *pprev = next;
bh->b_pprev = NULL;
}
}
@@ -506,16 +509,22 @@
size_buffers_type[blist] += bh->b_size;
}
-static void __remove_from_lru_list(struct buffer_head * bh, int blist)
+static void __remove_from_lru_list(struct buffer_head * bh)
{
- if (bh->b_prev_free || bh->b_next_free) {
- bh->b_prev_free->b_next_free = bh->b_next_free;
- bh->b_next_free->b_prev_free = bh->b_prev_free;
- if (lru_list[blist] == bh)
- lru_list[blist] = bh->b_next_free;
- if (lru_list[blist] == bh)
- lru_list[blist] = NULL;
- bh->b_next_free = bh->b_prev_free = NULL;
+ struct buffer_head *next = bh->b_next_free;
+ if (next) {
+ struct buffer_head *prev = bh->b_prev_free;
+ int blist = bh->b_list;
+
+ prev->b_next_free = next;
+ next->b_prev_free = prev;
+ if (lru_list[blist] == bh) {
+ if (next == bh)
+ next = NULL;
+ lru_list[blist] = next;
+ }
+ bh->b_next_free = NULL;
+ bh->b_prev_free = NULL;
nr_buffers_type[blist]--;
size_buffers_type[blist] -= bh->b_size;
}
@@ -526,7 +535,7 @@
static void __remove_from_queues(struct buffer_head *bh)
{
__hash_unlink(bh);
- __remove_from_lru_list(bh, bh->b_list);
+ __remove_from_lru_list(bh);
}
struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
@@ -1095,7 +1104,7 @@
if (buffer_dirty(bh))
dispose = BUF_DIRTY;
if (dispose != bh->b_list) {
- __remove_from_lru_list(bh, bh->b_list);
+ __remove_from_lru_list(bh);
bh->b_list = dispose;
if (dispose == BUF_CLEAN)
remove_inode_queue(bh);
@@ -1123,13 +1132,12 @@
}
/*
- * bforget() is like brelse(), except it puts the buffer on the
- * free list if it can.. We can NOT free the buffer if:
- * - there are other users of it
- * - it is locked and thus can have active IO
+ * bforget() is like brelse(), except it discards any
+ * potentially dirty data.
*/
void __bforget(struct buffer_head * buf)
{
+ mark_buffer_clean(buf);
__brelse(buf);
}
@@ -1422,10 +1430,7 @@
mark_buffer_clean(old_bh);
wait_on_buffer(old_bh);
clear_bit(BH_Req, &old_bh->b_state);
- /* Here we could run brelse or bforget. We use
- bforget because it will try to put the buffer
- in the freelist. */
- __bforget(old_bh);
+ __brelse(old_bh);
}
}
@@ -2327,29 +2332,40 @@
return 1;
}
-static int sync_page_buffers(struct buffer_head *bh, unsigned int gfp_mask)
+static int sync_page_buffers(struct buffer_head *head, unsigned int gfp_mask)
{
- struct buffer_head * p = bh;
- int tryagain = 1;
+ struct buffer_head * bh = head;
+ int tryagain = 0;
do {
- if (buffer_dirty(p) || buffer_locked(p)) {
- if (test_and_set_bit(BH_Wait_IO, &p->b_state)) {
- if (buffer_dirty(p)) {
- ll_rw_block(WRITE, 1, &p);
- tryagain = 0;
- } else if (buffer_locked(p)) {
- if (gfp_mask & __GFP_WAITBUF) {
- wait_on_buffer(p);
- tryagain = 1;
- } else
- tryagain = 0;
- }
- } else
- tryagain = 0;
+ if (!buffer_dirty(bh) && !buffer_locked(bh))
+ continue;
+
+ /* Don't start IO first time around.. */
+ if (!test_and_set_bit(BH_Wait_IO, &bh->b_state))
+ continue;
+
+ /* Second time through we start actively writing out.. */
+ if (test_and_set_bit(BH_Lock, &bh->b_state)) {
+ if (!test_bit(BH_launder, &bh->b_state))
+ continue;
+ wait_on_buffer(bh);
+ tryagain = 1;
+ continue;
+ }
+
+ if (!atomic_set_buffer_clean(bh)) {
+ unlock_buffer(bh);
+ continue;
}
- p = p->b_this_page;
- } while (p != bh);
+
+ __mark_buffer_clean(bh);
+ get_bh(bh);
+ set_bit(BH_launder, &bh->b_state);
+ bh->b_end_io = end_buffer_io_sync;
+ submit_bh(WRITE, bh);
+ tryagain = 0;
+ } while ((bh = bh->b_this_page) != head);
return tryagain;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)