diff -urNp --exclude CVS --exclude BitKeeper x-ref/fs/buffer.c x/fs/buffer.c --- x-ref/fs/buffer.c 2003-07-17 08:37:42.000000000 +0200 +++ x/fs/buffer.c 2003-07-17 08:37:44.000000000 +0200 @@ -123,6 +123,36 @@ union bdflush_param { int bdflush_min[N_PARAM] = { 0, 1, 0, 0, 0, 1*HZ, 0, 0, 0}; int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,10000*HZ, 10000*HZ, 100, 100, 0}; +static inline int write_buffer_delay(struct buffer_head *bh) +{ + struct page *page = bh->b_page; + + if (!TryLockPage(page)) { + spin_unlock(&lru_list_lock); + unlock_buffer(bh); + page->mapping->a_ops->writepage(page); + return 1; + } + + return 0; +} + +static inline void write_buffer(struct buffer_head *bh) +{ + if (buffer_delay(bh)) { + struct page *page = bh->b_page; + + lock_page(page); + if (buffer_delay(bh)) { + page->mapping->a_ops->writepage(page); + return; + } + unlock_page(page); + } + + ll_rw_block(WRITE, 1, &bh); +} + void unlock_buffer(struct buffer_head *bh) { clear_bit(BH_Wait_IO, &bh->b_state); @@ -226,7 +256,13 @@ static int write_some_buffers(kdev_t dev continue; if (test_and_set_bit(BH_Lock, &bh->b_state)) continue; - if (atomic_set_buffer_clean(bh)) { + if (buffer_delay(bh)) { + if (write_buffer_delay(bh)) { + if (count) + write_locked_buffers(array, count); + return -EAGAIN; + } + } else if (atomic_set_buffer_clean(bh)) { __refile_buffer(bh); get_bh(bh); array[count++] = bh; @@ -872,7 +908,7 @@ int fsync_buffers_list(struct list_head * a noop) */ wait_on_buffer(bh); - ll_rw_block(WRITE, 1, &bh); + write_buffer(bh); brelse(bh); spin_lock(&lru_list_lock); } @@ -1325,6 +1361,7 @@ static void discard_buffer(struct buffer clear_bit(BH_Mapped, &bh->b_state); clear_bit(BH_Req, &bh->b_state); clear_bit(BH_New, &bh->b_state); + clear_bit(BH_Delay, &bh->b_state); remove_from_queues(bh); unlock_buffer(bh); } @@ -2770,7 +2807,7 @@ void show_buffers(void) { #ifdef CONFIG_SMP struct buffer_head * bh; - int found = 0, locked = 0, dirty = 0, used = 0, lastused = 0; + int delalloc = 0, found = 0, locked = 0, dirty = 0, used = 0, lastused = 0; int nlist; static char *buf_types[NR_LIST] = { "CLEAN", "LOCKED", "DIRTY", }; #endif @@ -2785,7 +2822,7 @@ void show_buffers(void) if (!spin_trylock(&lru_list_lock)) return; for(nlist = 0; nlist < NR_LIST; nlist++) { - found = locked = dirty = used = lastused = 0; + delalloc = found = locked = dirty = used = lastused = 0; bh = lru_list[nlist]; if(!bh) continue; @@ -2795,6 +2832,8 @@ void show_buffers(void) locked++; if (buffer_dirty(bh)) dirty++; + if (buffer_delay(bh)) + delalloc++; if (atomic_read(&bh->b_count)) used++, lastused = found; bh = bh->b_next_free; @@ -2805,10 +2844,10 @@ void show_buffers(void) printk("%9s: BUG -> found %d, reported %d\n", buf_types[nlist], found, tmp); } - printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), " - "%d locked, %d dirty\n", + printk("%7s: %d buffers, %lu kbyte, %d used (last=%d), " + "%d locked, %d dirty %d delay\n", buf_types[nlist], found, size_buffers_type[nlist]>>10, - used, lastused, locked, dirty); + used, lastused, locked, dirty, delalloc); } spin_unlock(&lru_list_lock); #endif diff -urNp --exclude CVS --exclude BitKeeper x-ref/include/linux/fs.h x/include/linux/fs.h --- x-ref/include/linux/fs.h 2003-07-17 08:37:43.000000000 +0200 +++ x/include/linux/fs.h 2003-07-17 08:37:54.000000000 +0200 @@ -222,6 +222,7 @@ enum bh_state_bits { BH_Attached, /* 1 if b_inode_buffers is linked into a list */ BH_JBD, /* 1 if it has an attached journal_head */ BH_Sync, /* 1 if the buffer is a sync read */ + BH_Delay, /* 1 if the buffer is delayed allocate */ BH_PrivateStart,/* not a state bit, but the first bit available * for private allocation by other entities @@ -284,6 +285,7 @@ void init_buffer(struct buffer_head *, b #define buffer_new(bh) __buffer_state(bh,New) #define buffer_async(bh) __buffer_state(bh,Async) #define buffer_launder(bh) __buffer_state(bh,Launder) +#define buffer_delay(bh) __buffer_state(bh,Delay) #define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)