patch-2.4.25 linux-2.4.25/fs/buffer.c

Next file: linux-2.4.25/fs/dquot.c
Previous file: linux-2.4.25/fs/binfmt_elf.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/fs/buffer.c linux-2.4.25/fs/buffer.c
@@ -130,6 +130,36 @@
 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);
@@ -233,7 +263,13 @@
 			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;
@@ -765,7 +801,7 @@
 	bh->b_private = private;
 }
 
-static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
+void end_buffer_io_async(struct buffer_head * bh, int uptodate)
 {
 	static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
 	unsigned long flags;
@@ -880,7 +916,7 @@
 			 * a noop)
 			 */
 				wait_on_buffer(bh);
-				ll_rw_block(WRITE, 1, &bh);
+				write_buffer(bh);
 				brelse(bh);
 				spin_lock(&lru_list_lock);
 			}
@@ -1336,13 +1372,14 @@
  */
 static void discard_buffer(struct buffer_head * bh)
 {
-	if (buffer_mapped(bh)) {
+	if (buffer_mapped(bh) || buffer_delay(bh)) {
 		mark_buffer_clean(bh);
 		lock_buffer(bh);
 		clear_bit(BH_Uptodate, &bh->b_state);
 		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);
 	}
@@ -1634,7 +1671,7 @@
 			set_bit(BH_Uptodate, &bh->b_state);
 			continue; 
 		}
-		if (!buffer_uptodate(bh) &&
+		if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
 		     (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
@@ -2032,7 +2069,7 @@
 	if (Page_Uptodate(page))
 		set_bit(BH_Uptodate, &bh->b_state);
 
-	if (!buffer_uptodate(bh)) {
+	if (!buffer_uptodate(bh) && !buffer_delay(bh)) {
 		err = -EIO;
 		ll_rw_block(READ, 1, &bh);
 		wait_on_buffer(bh);
@@ -2226,8 +2263,8 @@
 	mark_buffer_uptodate(bh, uptodate);
 
 	kiobuf = bh->b_private;
-	unlock_buffer(bh);
 	end_kio_request(kiobuf, uptodate);
+	unlock_buffer(bh);
 }
 
 /*
@@ -2761,7 +2798,7 @@
 {
 #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
@@ -2776,7 +2813,7 @@
 	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;
 
@@ -2786,6 +2823,8 @@
 				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;
@@ -2797,9 +2836,9 @@
 				       buf_types[nlist], found, tmp);
 		}
 		printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), "
-		       "%d locked, %d dirty\n",
+		       "%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

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)