From: fs <fs@ercist.iscas.ac.cn>
To: reiserfs-list <reiserfs-list@namesys.com>
Cc: Hans Reiser <reiser@namesys.com>,
Vladimir Saveliev <vs@namesys.com>,
iscas-linaccident <iscas-linaccident@intellilink.co.jp>
Subject: [PATCH] ReiserFS file.c several bug-fix
Date: Thu, 23 Jun 2005 15:27:11 -0400 [thread overview]
Message-ID: <1119554831.3026.99.camel@CoolQ> (raw)
[-- Attachment #1: Type: text/plain, Size: 1869 bytes --]
Related FS:
ReiserFS
Related Files:
fs/reiserfs/file.c
Bug description:
Make a ReiserFS partition in USB storage HDD, create a test file
with enough size.
Write a program, do: open(O_SYNC/O_DSYNC) - read - close. After each
operation, pause for a while, such as 3s. Between open and read, unlug
the USB wire. open returns zero-filled buffer, no error returns.
Bug analysis:
reiserfs_file_write will claim some blocks, commit the I/O request,
if O_SYNC and O_DSYNC is used, it will
if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
res = generic_osync_inode(inode, file->f_mapping,
OSYNC_METADATA|OSYNC_DATA);
The question is, if I/O error occurs,
res = reiserfs_allocate_blocks_for_region fails with -EIO, so
it will exit the loop, no I/O request, no page marked as dirty.
If run generic_osync_inode, it returns 0(no dirty page), res will be
overwritten from -EIO to 0, thus no error report.
Also, reiserfs_file_write contains a serious bug, see here
blocks_to_allocate = reiserfs_prepare_file_region_for_write
(inode, pos, num_pages, write_bytes, prepared_pages);
Here blocks_to_allocate is defined as size_t, i.e. unsigned int, but
reiserfs_prepare_file_region_for_write is declared as int, so sometimes
it will return -EIO, -ENOENT, etc, take a look at this line
if ( blocks_to_allocate < 0 ) { <- This will never happen
res = blocks_to_allocate;
reiserfs_release_claimed_blocks(inode->i_sb,
num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
break;
}
Way around:
1) if already_written is zero, don't do generic_osync_inode
2) tell the result of reiserfs_prepare_file_region_for_write with IS_ERR
macro or cast it to size_t
Signed-off-by: Qu Fuping<fs@ercist.iscas.ac.cn>
Patch:
diff -uNp linux-2.6.12/fs/reiserfs/file.c
linux-2.6.12-new/fs/reiserfs/file.c
[-- Attachment #2: reiserfs_write.diff --]
[-- Type: text/x-patch, Size: 1628 bytes --]
--- linux-2.6.12/fs/reiserfs/file.c 2005-06-23 14:59:27.000000000 -0400
+++ linux-2.6.12-new/fs/reiserfs/file.c 2005-06-23 15:18:09.000000000 -0400
@@ -225,12 +225,6 @@ static int reiserfs_allocate_blocks_for_
hint.preallocate = will_prealloc;
/* Call block allocator to allocate blocks */
- res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate);
- if ( res != CARRY_ON ) {
- if ( res == NO_DISK_SPACE ) {
- /* We flush the transaction in case of no space. This way some
- blocks might become free */
- SB_JOURNAL(inode->i_sb)->j_must_wait = 1;
res = restart_transaction(th, inode, &path);
if (res)
goto error_exit;
@@ -1306,7 +1300,7 @@ static ssize_t reiserfs_file_write( stru
so that nobody else can access these until we are done.
We get number of actual blocks needed as a result.*/
blocks_to_allocate = reiserfs_prepare_file_region_for_write(inode, pos, num_pages, write_bytes, prepared_pages);
- if ( blocks_to_allocate < 0 ) {
+ if ( IS_ERROR((const void *)blocks_to_allocate) ) {
res = blocks_to_allocate;
reiserfs_release_claimed_blocks(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits));
break;
@@ -1363,6 +1357,10 @@ static ssize_t reiserfs_file_write( stru
}
}
+ /* If nothing is written, no need(actually, mustn't) to sync pages, just return res */
+ if( already_written == 0 )
+ goto out;
+
if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
res = generic_osync_inode(inode, file->f_mapping, OSYNC_METADATA|OSYNC_DATA);
next reply other threads:[~2005-06-23 19:27 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-06-23 19:27 fs [this message]
2005-06-23 9:16 ` [PATCH] ReiserFS file.c several bug-fix Vladimir Saveliev
2005-06-23 11:54 ` [iscas-linaccident 55] " qufuping
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1119554831.3026.99.camel@CoolQ \
--to=fs@ercist.iscas.ac.cn \
--cc=iscas-linaccident@intellilink.co.jp \
--cc=reiser@namesys.com \
--cc=reiserfs-list@namesys.com \
--cc=vs@namesys.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.