[patch] remove buffer_head.b_inode

From: Andrew Morton (akpm@zip.com.au)
Date: Wed Nov 28 2001 - 22:38:48 EST


It's only ever used as a boolean, so we can use the list_emptiness
of buffer_head.b_inode_buffers for the same thing.

This code does assume that a list_del on an empty list_head
is safe - I think Red Hat kernels have a list_head poisoning
trick which will explode over this. Easily fixed, if desired.

--- linux-2.5.1-pre3/fs/buffer.c Wed Nov 28 15:54:42 2001
+++ 25/fs/buffer.c Wed Nov 28 19:26:19 2001
@@ -574,38 +574,32 @@ struct buffer_head * get_hash_table(kdev
         return bh;
 }
 
-void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
+static inline void
+__buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
 {
- spin_lock(&lru_list_lock);
- if (bh->b_inode)
- list_del(&bh->b_inode_buffers);
- bh->b_inode = inode;
+ list_del(&bh->b_inode_buffers);
         list_add(&bh->b_inode_buffers, &inode->i_dirty_buffers);
- spin_unlock(&lru_list_lock);
 }
 
-void buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode)
+void buffer_insert_inode_queue(struct buffer_head *bh, struct inode *inode)
 {
         spin_lock(&lru_list_lock);
- if (bh->b_inode)
- list_del(&bh->b_inode_buffers);
- bh->b_inode = inode;
- list_add(&bh->b_inode_buffers, &inode->i_dirty_data_buffers);
+ __buffer_insert_inode_queue(bh, inode);
         spin_unlock(&lru_list_lock);
 }
 
-/* The caller must have the lru_list lock before calling the
- remove_inode_queue functions. */
-static void __remove_inode_queue(struct buffer_head *bh)
+void buffer_insert_inode_data_queue(struct buffer_head *bh, struct inode *inode)
 {
- bh->b_inode = NULL;
+ spin_lock(&lru_list_lock);
         list_del(&bh->b_inode_buffers);
+ list_add(&bh->b_inode_buffers, &inode->i_dirty_data_buffers);
+ spin_unlock(&lru_list_lock);
 }
 
-static inline void remove_inode_queue(struct buffer_head *bh)
+/* lru_list_lock must be held */
+static inline void __remove_inode_queue(struct buffer_head *bh)
 {
- if (bh->b_inode)
- __remove_inode_queue(bh);
+ list_del_init(&bh->b_inode_buffers);
 }
 
 int inode_has_buffers(struct inode *inode)
@@ -690,7 +684,7 @@ void invalidate_bdev(struct block_device
                                 printk("invalidate: dirty buffer\n");
                         if (!atomic_read(&bh->b_count)) {
                                 if (destroy_dirty_buffers || !buffer_dirty(bh)) {
- remove_inode_queue(bh);
+ __remove_inode_queue(bh);
                                 }
                         } else
                                 printk("invalidate: busy buffer\n");
@@ -831,12 +825,9 @@ int fsync_inode_buffers(struct inode *in
 
         while (!list_empty(&inode->i_dirty_buffers)) {
                 bh = BH_ENTRY(inode->i_dirty_buffers.next);
- list_del(&bh->b_inode_buffers);
- if (!buffer_dirty(bh) && !buffer_locked(bh))
- bh->b_inode = NULL;
- else {
- bh->b_inode = &tmp;
- list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
+ __remove_inode_queue(bh);
+ if (buffer_dirty(bh) || buffer_locked(bh)) {
+ __buffer_insert_inode_queue(bh, &tmp);
                         if (buffer_dirty(bh)) {
                                 get_bh(bh);
                                 spin_unlock(&lru_list_lock);
@@ -849,7 +840,7 @@ int fsync_inode_buffers(struct inode *in
 
         while (!list_empty(&tmp.i_dirty_buffers)) {
                 bh = BH_ENTRY(tmp.i_dirty_buffers.prev);
- remove_inode_queue(bh);
+ __remove_inode_queue(bh);
                 get_bh(bh);
                 spin_unlock(&lru_list_lock);
                 wait_on_buffer(bh);
@@ -880,12 +871,9 @@ int fsync_inode_data_buffers(struct inod
 
         while (!list_empty(&inode->i_dirty_data_buffers)) {
                 bh = BH_ENTRY(inode->i_dirty_data_buffers.next);
- list_del(&bh->b_inode_buffers);
- if (!buffer_dirty(bh) && !buffer_locked(bh))
- bh->b_inode = NULL;
- else {
- bh->b_inode = &tmp;
- list_add(&bh->b_inode_buffers, &tmp.i_dirty_data_buffers);
+ __remove_inode_queue(bh);
+ if (buffer_dirty(bh) || buffer_locked(bh)) {
+ __buffer_insert_inode_queue(bh, &tmp);
                         if (buffer_dirty(bh)) {
                                 get_bh(bh);
                                 spin_unlock(&lru_list_lock);
@@ -898,7 +886,7 @@ int fsync_inode_data_buffers(struct inod
 
         while (!list_empty(&tmp.i_dirty_data_buffers)) {
                 bh = BH_ENTRY(tmp.i_dirty_data_buffers.prev);
- remove_inode_queue(bh);
+ __remove_inode_queue(bh);
                 get_bh(bh);
                 spin_unlock(&lru_list_lock);
                 wait_on_buffer(bh);
@@ -998,9 +986,9 @@ void invalidate_inode_buffers(struct ino
         
         spin_lock(&lru_list_lock);
         while ((entry = inode->i_dirty_buffers.next) != &inode->i_dirty_buffers)
- remove_inode_queue(BH_ENTRY(entry));
+ __remove_inode_queue(BH_ENTRY(entry));
         while ((entry = inode->i_dirty_data_buffers.next) != &inode->i_dirty_data_buffers)
- remove_inode_queue(BH_ENTRY(entry));
+ __remove_inode_queue(BH_ENTRY(entry));
         spin_unlock(&lru_list_lock);
 }
 
@@ -1126,7 +1114,7 @@ static void __refile_buffer(struct buffe
                 __remove_from_lru_list(bh);
                 bh->b_list = dispose;
                 if (dispose == BUF_CLEAN)
- remove_inode_queue(bh);
+ __remove_inode_queue(bh);
                 __insert_into_lru_list(bh, dispose);
         }
 }
@@ -1189,7 +1177,7 @@ struct buffer_head * bread(kdev_t dev, i
  */
 static void __put_unused_buffer_head(struct buffer_head * bh)
 {
- if (bh->b_inode)
+ if (!list_empty(&bh->b_inode_buffers))
                 BUG();
         if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) {
                 kmem_cache_free(bh_cachep, bh);
@@ -1219,7 +1207,7 @@ EXPORT_SYMBOL(put_unused_buffer_head);
  */
 struct buffer_head * get_unused_buffer_head(int async)
 {
- struct buffer_head * bh;
+ struct buffer_head *bh;
 
         spin_lock(&unused_list_lock);
         if (nr_unused_buffer_heads > NR_RESERVED) {
@@ -1227,7 +1215,7 @@ struct buffer_head * get_unused_buffer_h
                 unused_list = bh->b_next_free;
                 nr_unused_buffer_heads--;
                 spin_unlock(&unused_list_lock);
- return bh;
+ goto ret_bh;
         }
         spin_unlock(&unused_list_lock);
 
@@ -1238,7 +1226,7 @@ struct buffer_head * get_unused_buffer_h
         if((bh = kmem_cache_alloc(bh_cachep, SLAB_NOFS)) != NULL) {
                 bh->b_blocknr = -1;
                 bh->b_this_page = NULL;
- return bh;
+ goto ret_bh;
         }
 
         /*
@@ -1251,12 +1239,15 @@ struct buffer_head * get_unused_buffer_h
                         unused_list = bh->b_next_free;
                         nr_unused_buffer_heads--;
                         spin_unlock(&unused_list_lock);
- return bh;
+ goto ret_bh;
                 }
                 spin_unlock(&unused_list_lock);
         }
 
         return NULL;
+ret_bh:
+ INIT_LIST_HEAD(&bh->b_inode_buffers);
+ return bh;
 }
 EXPORT_SYMBOL(get_unused_buffer_head);
 
@@ -2390,7 +2381,7 @@ cleaned_buffers_try_again:
 
                 if (p->b_dev == B_FREE) BUG();
 
- remove_inode_queue(p);
+ __remove_inode_queue(p);
                 __remove_from_queues(p);
                 __put_unused_buffer_head(p);
         } while (tmp != bh);
--- linux-2.5.1-pre3/include/linux/fs.h Wed Nov 28 15:54:42 2001
+++ 25/include/linux/fs.h Wed Nov 28 19:26:19 2001
@@ -261,8 +261,9 @@ struct buffer_head {
 
         wait_queue_head_t b_wait;
 
- struct inode * b_inode;
- struct list_head b_inode_buffers; /* doubly linked list of inode dirty buffers */
+ /* Dirty buffers against an inode. Must be in list_empty()
+ * state when this buffer is not on an inode's i_dirty_buffers */
+ struct list_head b_inode_buffers;
 };
 
 typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Nov 30 2001 - 21:00:33 EST