Skip to contentSkip to conversation

[2.4] reiserfs: fix one more directio vs tails problem]

BK Hans Reiser 1 participant 1 message May 3, 2003

lore
Share & tools
lore
#0 lore raw

Please apply, Oleg wants this in before the next real release, as it looks like their bug fix turned off tail packing by mistake.

Signature · 1 line
Hans

Hello!

This changeset fixes another set problems related to directio vs packed tails. Thanks to Mingming Cao <[email protected]> for bringing the issue to our attention. Most of the patch was made by Chris Mason.

Please pull from bk://namesys.com/bk/reiser3-linux-2.4-directiofix2

Diffstat:

 fs/reiserfs/inode.c           |   12 ++++++-
 fs/reiserfs/journal.c         |   66 +++++++++++++++++++++++++++---------------
 fs/reiserfs/tail_conversion.c |    1
 include/linux/reiserfs_fs.h   |    2 +
 include/linux/reiserfs_fs_i.h |    7 ++++
 5 files changed, 63 insertions(+), 25 deletions(-)

Plain text patch:

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas:
# ChangeSet 1.1158 -> 1.1159
# include/linux/reiserfs_fs_i.h 1.8 -> 1.9
# fs/reiserfs/inode.c 1.42 -> 1.43
# fs/reiserfs/tail_conversion.c 1.16 -> 1.17
# fs/reiserfs/journal.c 1.28 -> 1.29
# include/linux/reiserfs_fs.h 1.26 -> 1.27
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/05/03 [email protected] 1.1159
# reiserfs: Fix another O_DIRECT vs tails problem. Mostly by Chris Mason. # Thanks to Mingming Cao <[email protected]> for bringing the issue to our attention. # --------------------------------------------
#

fs/reiserfs/inode.c +10 -2
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
@@ -469,7 +469,7 @@
     tail_end = (tail_start | (bh_result->b_size - 1)) + 1 ;
 
     index = tail_offset >> PAGE_CACHE_SHIFT ;
-    if (index != hole_page->index) {
+    if ( !hole_page || index != hole_page->index) {
 	tail_page = grab_cache_page(inode->i_mapping, index) ;
 	retval = -ENOMEM;
 	if (!tail_page) {
@@ -1810,7 +1810,12 @@
 	    flush_dcache_page(page) ;
 	    kunmap(page) ;
 	    if (buffer_mapped(bh) && bh->b_blocknr != 0) {
-	        mark_buffer_dirty(bh) ;
+	        if (!atomic_set_buffer_dirty(bh)) {
+			set_buffer_flushtime(bh);
+			refile_buffer(bh);
+			buffer_insert_inode_data_queue(bh, p_s_inode);
+			balance_dirty();
+		}
 	    }
 	}
 	UnlockPage(page) ;
@@ -2158,6 +2163,9 @@
                               struct kiobuf *iobuf, unsigned long blocknr,
 			      int blocksize) 
 {
+    lock_kernel();
+    reiserfs_commit_for_tail(inode);
+    unlock_kernel();
     return generic_direct_IO(rw, inode, iobuf, blocknr, blocksize,
                              reiserfs_get_block_direct_io) ;
 }
fs/reiserfs/journal.c +43 -23

75 lines not on this page · raw message

fs/reiserfs/tail_conversion.c +1 -0
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
@@ -133,6 +133,7 @@
 
     inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;
 
+    reiserfs_update_tail_transaction(inode);
     return 0;
 }
 
include/linux/reiserfs_fs.h +2 -0
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
@@ -1558,7 +1558,9 @@
 #define JOURNAL_BUFFER(j,n) ((j)->j_ap_blocks[((j)->j_start + (n)) % JOURNAL_BLOCK_COUNT])
 
 void reiserfs_commit_for_inode(struct inode *) ;
+void reiserfs_commit_for_tail(struct inode *) ;
 void reiserfs_update_inode_transaction(struct inode *) ;
+void reiserfs_update_tail_transaction(struct inode *) ;
 void reiserfs_wait_on_write_block(struct super_block *s) ;
 void reiserfs_block_writes(struct reiserfs_transaction_handle *th) ;
 void reiserfs_allow_writes(struct super_block *s) ;
include/linux/reiserfs_fs_i.h +7 -0
diff -Nru a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
@@ -53,6 +53,13 @@
     ** flushed */
     unsigned long i_trans_id ;
     unsigned long i_trans_index ;
+
+    /* direct io needs to make sure the tail is on disk to avoid
+     * buffer alias problems.  This records the transaction last
+     * involved in a direct->indirect conversion for this file
+     */
+    unsigned long i_tail_trans_id;
+    unsigned long i_tail_trans_index;
 };
 
 #endif