patch-2.2.2 linux/fs/buffer.c

Next file: linux/fs/coda/sysctl.c
Previous file: linux/fs/autofs/waitq.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.1/linux/fs/buffer.c linux/fs/buffer.c
@@ -74,6 +74,7 @@
 
 static int nr_buffers = 0;
 static int nr_buffers_type[NR_LIST] = {0,};
+static int size_buffers_type[NR_LIST] = {0,};
 static int nr_buffer_heads = 0;
 static int nr_unused_buffer_heads = 0;
 
@@ -99,7 +100,8 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int dummy1;    /* unused */
+		int pct_dirt;    /* Max %age of mem for dirty buffers before
+				    activating bdflush */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
@@ -383,7 +385,9 @@
 		goto out_putf;
 
 	/* this needs further work, at the moment it is identical to fsync() */
+	down(&inode->i_sem);
 	err = file->f_op->fsync(file, dentry);
+	up(&inode->i_sem);
 
 out_putf:
 	fput(file);
@@ -478,6 +482,7 @@
 		return;
 	}
 	nr_buffers_type[bh->b_list]--;
+	size_buffers_type[bh->b_list] -= bh->b_size;
 	remove_from_hash_queue(bh);
 	remove_from_lru_list(bh);
 }
@@ -551,6 +556,7 @@
 		(*bhp)->b_prev_free = bh;
 
 		nr_buffers_type[bh->b_list]++;
+		size_buffers_type[bh->b_list] += bh->b_size;
 
 		/* Put the buffer in new hash-queue if it has a device. */
 		bh->b_next = NULL;
@@ -802,13 +808,19 @@
 		file_buffer(buf, dispose);
 		if(dispose == BUF_DIRTY) {
 			int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
+			int too_large = (num_physpages * bdf_prm.b_un.pct_dirt/100);
 
 			/* This buffer is dirty, maybe we need to start flushing.
 			 * If too high a percentage of the buffers are dirty...
 			 */
-			if (nr_buffers_type[BUF_DIRTY] > too_many)
-				wakeup_bdflush(0);
-
+			if (nr_buffers_type[BUF_DIRTY] > too_many ||
+			    size_buffers_type[BUF_DIRTY]/PAGE_SIZE > too_large) {
+				if (nr_buffers_type[BUF_LOCKED] > 3 * bdf_prm.b_un.ndirty)
+					wakeup_bdflush(1);
+				else
+					wakeup_bdflush(0);
+			}
+			
 			/* If this is a loop device, and
 			 * more than half of the buffers are dirty...
 			 * (Prevents no-free-buffers deadlock with loop device.)
@@ -1604,7 +1616,7 @@
 #ifdef DEBUG
 	for(nlist = 0; nlist < NR_LIST; nlist++)
 #else
-	for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+	for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
 #endif
 	{
 		ndirty = 0;
@@ -1623,8 +1635,13 @@
 				 }
 				 
 				 /* Clean buffer on dirty list?  Refile it */
-				 if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh))
-				  {
+				 if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
+					 refile_buffer(bh);
+					 continue;
+				 }
+				  
+				  /* Unlocked buffer on locked list?  Refile it */
+				  if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
 					  refile_buffer(bh);
 					  continue;
 				  }
@@ -1752,7 +1769,7 @@
 #ifdef DEBUG
 		for(nlist = 0; nlist < NR_LIST; nlist++)
 #else
-		for(nlist = BUF_DIRTY; nlist <= BUF_DIRTY; nlist++)
+		for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
 #endif
 		 {
 			 ndirty = 0;
@@ -1771,11 +1788,16 @@
 					  }
 					  
 					  /* Clean buffer on dirty list?  Refile it */
-					  if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh))
-					   {
-						   refile_buffer(bh);
-						   continue;
-					   }
+					  if (nlist == BUF_DIRTY && !buffer_dirty(bh)) {
+						  refile_buffer(bh);
+						  continue;
+					  }
+					  
+					  /* Unlocked buffer on locked list?  Refile it */
+					  if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
+						  refile_buffer(bh);
+						  continue;
+					  }
 					  
 					  if (buffer_locked(bh) || !buffer_dirty(bh))
 						   continue;

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