Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.4.13 /fs/buffer.c

Filename:/fs/buffer.c
Lines Added:60
Lines Deleted:44
Also changed in: (Previous) 2.4.13-pre6  2.4.13-pre5  2.4.13-pre4  2.4.13-pre3  2.4.13-pre2  2.4.12-ac6 
(Following) 2.4.13-ac1  2.4.13-ac2  2.4.13-ac3  2.4.13-ac4  2.4.13-ac5  2.4.13-ac6 

Location
[  2.4.13
  [  fs
     o  buffer.c

Patch

diff -u --recursive --new-file v2.4.12/linux/fs/buffer.c linux/fs/buffer.c
--- v2.4.12/linux/fs/buffer.c   Tue Oct  9 17:06:53 2001
+++ linux/fs/buffer.c   Tue Oct 23 17:54:19 2001
@@ -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;
 }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.