* [BK] 2.4 ReiserFS Direct IO bugfix patch
@ 2003-02-13 18:31 Hans Reiser
0 siblings, 0 replies; only message in thread
From: Hans Reiser @ 2003-02-13 18:31 UTC (permalink / raw)
To: Marcelo Tosatti; +Cc: Linux Kernel Mailing List
[-- Attachment #1: Type: text/plain, Size: 11 bytes --]
--
Hans
[-- Attachment #2: 2.4 patch to forward --]
[-- Type: message/rfc822, Size: 5314 bytes --]
From: Oleg Drokin <green@namesys.com>
To: reiser@namesys.com
Subject: 2.4 patch to forward
Date: Thu, 13 Feb 2003 16:33:06 +0300
Message-ID: <20030213163305.A4419@namesys.com>
Hello!
This is the fix for the problem where DIRECT IO on a file that
later will be tail-packed can cause reiserfs to crash
in 2.4 kernels.
It can be pulled from bk://namesys.com/bk/reiser3-linux-2.4-directio-fix
Please apply, thanks.
Diffstat:
inode.c | 43 +++++++++++++++++++++++++++++++++++--------
tail_conversion.c | 4 +++-
2 files changed, 38 insertions(+), 9 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.967 -> 1.968
# fs/reiserfs/inode.c 1.41 -> 1.42
# fs/reiserfs/tail_conversion.c 1.15 -> 1.16
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/13 green@angband.namesys.com 1.968
# reiserfs: Fix DIRECT IO interference with tail packing
# --------------------------------------------
#
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c Thu Feb 13 16:22:56 2003
+++ b/fs/reiserfs/inode.c Thu Feb 13 16:22:56 2003
@@ -418,6 +418,7 @@
struct buffer_head * bh_result, int create) {
int ret ;
+ bh_result->b_page = NULL;
ret = reiserfs_get_block(inode, block, bh_result, create) ;
/* don't allow direct io onto tail pages */
@@ -428,6 +429,14 @@
reiserfs_unmap_buffer(bh_result);
ret = -EINVAL ;
}
+ /* Possible unpacked tail. Flush the data before pages have
+ disappeared */
+ if (inode->u.reiserfs_i.i_flags & i_pack_on_close_mask) {
+ lock_kernel();
+ reiserfs_commit_for_inode(inode);
+ inode->u.reiserfs_i.i_flags &= ~i_pack_on_close_mask;
+ unlock_kernel();
+ }
return ret ;
}
@@ -566,7 +575,12 @@
return ret;
}
- inode->u.reiserfs_i.i_flags |= i_pack_on_close_mask;
+ /* If file is of such a size, that it might have a tail and tails are enabled
+ ** we should mark it as possibly needing tail packing on close
+ */
+ if ( (have_large_tails (inode->i_sb) && inode->i_size < block_size (inode)*4) ||
+ (have_small_tails (inode->i_sb) && inode->i_size < block_size(inode)) )
+ inode->u.reiserfs_i.i_flags |= i_pack_on_close_mask;
windex = push_journal_writer("reiserfs_get_block") ;
@@ -757,15 +771,21 @@
*/
mark_buffer_uptodate (unbh, 1);
- /* we've converted the tail, so we must
- ** flush unbh before the transaction commits
+ /* unbh->b_page == NULL in case of DIRECT_IO request, this means
+ buffer will disappear shortly, so it should not be added to
+ any of our lists.
*/
- add_to_flushlist(inode, unbh) ;
+ if ( unbh->b_page ) {
+ /* we've converted the tail, so we must
+ ** flush unbh before the transaction commits
+ */
+ add_to_flushlist(inode, unbh) ;
- /* mark it dirty now to prevent commit_write from adding
- ** this buffer to the inode's dirty buffer list
- */
- __mark_buffer_dirty(unbh) ;
+ /* mark it dirty now to prevent commit_write from adding
+ ** this buffer to the inode's dirty buffer list
+ */
+ __mark_buffer_dirty(unbh) ;
+ }
//inode->i_blocks += inode->i_sb->s_blocksize / 512;
//mark_tail_converted (inode);
@@ -2062,6 +2082,13 @@
if (pos > inode->i_size) {
struct reiserfs_transaction_handle th ;
lock_kernel();
+ /* If the file have grown beyond the border where it
+ can have a tail, unmark it as needing a tail
+ packing */
+ if ( (have_large_tails (inode->i_sb) && inode->i_size < block_size (inode)*4) ||
+ (have_small_tails (inode->i_sb) && inode->i_size < block_size(inode)) )
+ inode->u.reiserfs_i.i_flags &= ~i_pack_on_close_mask;
+
journal_begin(&th, inode->i_sb, 1) ;
reiserfs_update_inode_transaction(inode) ;
inode->i_size = pos ;
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c Thu Feb 13 16:22:56 2003
+++ b/fs/reiserfs/tail_conversion.c Thu Feb 13 16:22:56 2003
@@ -105,8 +105,10 @@
/* we only send the unbh pointer if the buffer is not up to date.
** this avoids overwriting good data from writepage() with old data
** from the disk or buffer cache
+ ** Special case: unbh->b_page will be NULL if we are coming through
+ ** DIRECT_IO handler here.
*/
- if (buffer_uptodate(unbh) || Page_Uptodate(unbh->b_page)) {
+ if ( !unbh->b_page || buffer_uptodate(unbh) || Page_Uptodate(unbh->b_page)) {
up_to_date_bh = NULL ;
} else {
up_to_date_bh = unbh ;
Bye,
Oleg
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2003-02-13 18:22 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-02-13 18:31 [BK] 2.4 ReiserFS Direct IO bugfix patch Hans Reiser
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.