--- ../../linux-2.4.2/linux/fs/buffer.c Fri Feb 9 11:29:44 2001 +++ fs/buffer.c Thu Mar 1 11:02:01 2001 @@ -161,6 +161,40 @@ atomic_dec(&bh->b_count); } + +#define buffer_delay_busy(bh) \ + (test_bit(BH_Delay, &bh->b_state) && bh->b_page && PageLocked(bh->b_page)) + +static void +_write_buffer(struct buffer_head *bh) +{ + struct page *page = bh->b_page; + + if (!page || TryLockPage(page)) { + if (current->need_resched) + schedule(); + return; + } + /* + * Raced with someone? + */ + if (page->buffers != bh || !buffer_delay(bh) || !buffer_dirty(bh)) { + UnlockPage(page); + return; + } + page->mapping->a_ops->writepage(page); +} + +static inline void +write_buffer(struct buffer_head *bh) +{ + if (!buffer_delay(bh)) + ll_rw_block(WRITE, 1, &bh); + else + _write_buffer(bh); +} + + /* Call sync_buffers with wait!=0 to ensure that the call does not * return until all buffer writes have completed. Sync() may return * before the writes have finished; fsync() may not. @@ -232,7 +266,7 @@ atomic_inc(&bh->b_count); spin_unlock(&lru_list_lock); - ll_rw_block(WRITE, 1, &bh); + write_buffer(bh); atomic_dec(&bh->b_count); retry = 1; goto repeat; @@ -507,6 +541,8 @@ struct bh_free_head *head = &free_list[BUFSIZE_INDEX(bh->b_size)]; struct buffer_head **bhp = &head->list; + if (test_bit(BH_Delay, &bh->b_state)) + BUG(); bh->b_state = 0; spin_lock(&head->lock); @@ -879,7 +915,7 @@ if (buffer_dirty(bh)) { atomic_inc(&bh->b_count); spin_unlock(&lru_list_lock); - ll_rw_block(WRITE, 1, &bh); + write_buffer(bh); brelse(bh); spin_lock(&lru_list_lock); } @@ -1394,6 +1430,11 @@ head = page->buffers; bh = head; + + if (buffer_delay(bh)) { + page->mapping->a_ops->writepage_nounlock(page); + return 0; /* just started I/O ... likely didn't complete */ + } do { unsigned int next_off = curr_off + bh->b_size; next = bh->b_this_page; @@ -2334,7 +2375,7 @@ if (wait > 1) __wait_on_buffer(p); } else if (buffer_dirty(p)) - ll_rw_block(WRITE, 1, &p); + write_buffer(p); } while (tmp != bh); } @@ -2361,6 +2402,11 @@ int index = BUFSIZE_INDEX(bh->b_size); int loop = 0; + if (buffer_delay(bh)) { + if (wait) + page->mapping->a_ops->writepage_nounlock(page); + return 0; /* just started I/O ... likely didn't complete */ + } cleaned_buffers_try_again: spin_lock(&lru_list_lock); write_lock(&hash_table_lock); @@ -2562,7 +2608,7 @@ __refile_buffer(bh); continue; } - if (buffer_locked(bh)) + if (buffer_locked(bh) || buffer_delay_busy(bh)) continue; if (check_flushtime) { @@ -2580,7 +2626,7 @@ /* OK, now we are committed to write it out. */ atomic_inc(&bh->b_count); spin_unlock(&lru_list_lock); - ll_rw_block(WRITE, 1, &bh); + write_buffer(bh); atomic_dec(&bh->b_count); if (current->need_resched)