[PATCH] kill code duplication in buffer handling

From: Christoph Hellwig (hch@infradead.org)
Date: Mon Apr 29 2002 - 08:30:25 EST


Loosely spoken this is a backport of a patch from Al that went into
early 2.5, I got into this because a patch (lock_break) changed those
in different ways and thus broke JFS, the only filesystem using the
inodes i_dirty_data_buffers list for normal operation (i.e. not O_DIRECT).

Currently fs/buffer.c contains some functions twice, with the only
difference beein that one uses inode->i_dirty_buffers and the other
inode->i_dirty_data_buffers.

This patch replaces osync_inode_buffers and osync_inode_data_buffers
with osync_buffers_list that takes a struct list_head and is static as
not used outside buffer.c. Also the bodies of fsync_inode_buffers and
fsync_inode_data_buffers are merged into fsync_buffers_list, but as it
has many external users static inlines in fs.h are added to stay source
compatible. In addition there is some minor cleanup in the surrounding
area whithout behaviour change.

        Christoph

diff -uNr -Xdontdiff linux-2.4.19-pre7/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.19-pre7/fs/buffer.c Tue Apr 16 20:46:42 2002
+++ linux/fs/buffer.c Mon Apr 29 13:20:58 2002
@@ -84,6 +84,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 static int grow_buffers(kdev_t dev, unsigned long block, int size);
+static int osync_buffers_list(struct list_head *);
 static void __refile_buffer(struct buffer_head *);
 
 /* This is used by some architectures to estimate available memory. */
@@ -801,9 +802,10 @@
         return;
 }
 
-inline void set_buffer_async_io(struct buffer_head *bh) {
- bh->b_end_io = end_buffer_io_async ;
- mark_buffer_async(bh, 1);
+inline void set_buffer_async_io(struct buffer_head *bh)
+{
+ bh->b_end_io = end_buffer_io_async;
+ mark_buffer_async(bh, 1);
 }
 
 /*
@@ -825,8 +827,7 @@
  * the osync code to catch these locked, dirty buffers without requeuing
  * any newly dirty buffers for write.
  */
-
-int fsync_inode_buffers(struct inode *inode)
+int fsync_buffers_list(struct list_head *list)
 {
         struct buffer_head *bh;
         struct inode tmp;
@@ -836,8 +837,8 @@
         
         spin_lock(&lru_list_lock);
 
- while (!list_empty(&inode->i_dirty_buffers)) {
- bh = BH_ENTRY(inode->i_dirty_buffers.next);
+ while (!list_empty(list)) {
+ bh = BH_ENTRY(list->next);
                 list_del(&bh->b_inode_buffers);
                 if (!buffer_dirty(bh) && !buffer_locked(bh))
                         bh->b_inode = NULL;
@@ -867,56 +868,7 @@
         }
         
         spin_unlock(&lru_list_lock);
- err2 = osync_inode_buffers(inode);
-
- if (err)
- return err;
- else
- return err2;
-}
-
-int fsync_inode_data_buffers(struct inode *inode)
-{
- struct buffer_head *bh;
- struct inode tmp;
- int err = 0, err2;
-
- INIT_LIST_HEAD(&tmp.i_dirty_data_buffers);
-
- spin_lock(&lru_list_lock);
-
- 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);
- if (buffer_dirty(bh)) {
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- ll_rw_block(WRITE, 1, &bh);
- brelse(bh);
- spin_lock(&lru_list_lock);
- }
- }
- }
-
- while (!list_empty(&tmp.i_dirty_data_buffers)) {
- bh = BH_ENTRY(tmp.i_dirty_data_buffers.prev);
- remove_inode_queue(bh);
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- err = -EIO;
- brelse(bh);
- spin_lock(&lru_list_lock);
- }
-
- spin_unlock(&lru_list_lock);
- err2 = osync_inode_data_buffers(inode);
+ err2 = osync_buffers_list(list);
 
         if (err)
                 return err;
@@ -930,24 +882,21 @@
  * writes to the disk.
  *
  * To do O_SYNC writes, just queue the buffer writes with ll_rw_block as
- * you dirty the buffers, and then use osync_inode_buffers to wait for
+ * you dirty the buffers, and then use osync_buffers_list to wait for
  * completion. Any other dirty buffers which are not yet queued for
  * write will not be flushed to disk by the osync.
  */
-
-int osync_inode_buffers(struct inode *inode)
+static int osync_buffers_list(struct list_head *list)
 {
         struct buffer_head *bh;
- struct list_head *list;
+ struct list_head *p;
         int err = 0;
 
         spin_lock(&lru_list_lock);
         
  repeat:
-
- for (list = inode->i_dirty_buffers.prev;
- bh = BH_ENTRY(list), list != &inode->i_dirty_buffers;
- list = bh->b_inode_buffers.prev) {
+ list_for_each_prev(p, list) {
+ bh = BH_ENTRY(p);
                 if (buffer_locked(bh)) {
                         get_bh(bh);
                         spin_unlock(&lru_list_lock);
@@ -964,36 +913,6 @@
         return err;
 }
 
-int osync_inode_data_buffers(struct inode *inode)
-{
- struct buffer_head *bh;
- struct list_head *list;
- int err = 0;
-
- spin_lock(&lru_list_lock);
-
- repeat:
-
- for (list = inode->i_dirty_data_buffers.prev;
- bh = BH_ENTRY(list), list != &inode->i_dirty_data_buffers;
- list = bh->b_inode_buffers.prev) {
- if (buffer_locked(bh)) {
- get_bh(bh);
- spin_unlock(&lru_list_lock);
- wait_on_buffer(bh);
- if (!buffer_uptodate(bh))
- err = -EIO;
- brelse(bh);
- spin_lock(&lru_list_lock);
- goto repeat;
- }
- }
-
- spin_unlock(&lru_list_lock);
- return err;
-}
-
-
 /*
  * Invalidate any and all dirty buffers on a given inode. We are
  * probably unmounting the fs, but that doesn't mean we have already
diff -uNr -Xdontdiff linux-2.4.19-pre7/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.19-pre7/include/linux/fs.h Tue Apr 16 20:48:18 2002
+++ linux/include/linux/fs.h Mon Apr 29 13:22:55 2002
@@ -1163,9 +1163,13 @@
 extern void FASTCALL(__mark_dirty(struct buffer_head *bh));
 extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh));
 extern void FASTCALL(mark_buffer_dirty(struct buffer_head *bh));
+extern void FASTCALL(buffer_insert_inode_queue(struct buffer_head *, struct inode *));
 extern void FASTCALL(buffer_insert_inode_data_queue(struct buffer_head *, struct inode *));
 
-#define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state)
+static inline int atomic_set_buffer_dirty(struct buffer_head *bh)
+{
+ return test_and_set_bit(BH_Dirty, &bh->b_state);
+}
 
 static inline void mark_buffer_async(struct buffer_head * bh, int on)
 {
@@ -1190,7 +1194,6 @@
         bh->b_end_io(bh, 0);
 }
 
-extern void buffer_insert_inode_queue(struct buffer_head *, struct inode *);
 static inline void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
 {
         mark_buffer_dirty(bh);
@@ -1218,10 +1221,15 @@
 extern int fsync_super(struct super_block *);
 extern int fsync_no_super(kdev_t);
 extern void sync_inodes_sb(struct super_block *);
-extern int osync_inode_buffers(struct inode *);
-extern int osync_inode_data_buffers(struct inode *);
-extern int fsync_inode_buffers(struct inode *);
-extern int fsync_inode_data_buffers(struct inode *);
+extern int fsync_buffers_list(struct list_head *);
+static inline int fsync_inode_buffers(struct inode *inode)
+{
+ return fsync_buffers_list(&inode->i_dirty_buffers);
+}
+static inline int fsync_inode_data_buffers(struct inode *inode)
+{
+ return fsync_buffers_list(&inode->i_dirty_data_buffers);
+}
 extern int inode_has_buffers(struct inode *);
 extern int filemap_fdatasync(struct address_space *);
 extern int filemap_fdatawait(struct address_space *);
diff -uNr -Xdontdiff linux-2.4.19-pre7/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.19-pre7/kernel/ksyms.c Tue Apr 16 20:46:39 2002
+++ linux/kernel/ksyms.c Mon Apr 29 13:22:26 2002
@@ -504,8 +504,7 @@
 /* Added to make file system as module */
 EXPORT_SYMBOL(sys_tz);
 EXPORT_SYMBOL(file_fsync);
-EXPORT_SYMBOL(fsync_inode_buffers);
-EXPORT_SYMBOL(fsync_inode_data_buffers);
+EXPORT_SYMBOL(fsync_buffers_list);
 EXPORT_SYMBOL(clear_inode);
 EXPORT_SYMBOL(___strtok);
 EXPORT_SYMBOL(init_special_inode);
@@ -515,6 +514,7 @@
 EXPORT_SYMBOL(insert_inode_hash);
 EXPORT_SYMBOL(remove_inode_hash);
 EXPORT_SYMBOL(buffer_insert_inode_queue);
+EXPORT_SYMBOL(buffer_insert_inode_data_queue);
 EXPORT_SYMBOL(make_bad_inode);
 EXPORT_SYMBOL(is_bad_inode);
 EXPORT_SYMBOL(event);
-
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 : Tue Apr 30 2002 - 22:00:17 EST