From: Mingming Cao <cmm@us.ibm.com>
To: Gary Hawco <ghawco@cox.net>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>,
Theodore Tso <tytso@mit.edu>,
"linux-ext4@vger.kernel.org" <linux-ext4@vger.kernel.org>
Subject: Re: Gentoo with ext4-patch-queue snapshots
Date: Wed, 02 Jul 2008 13:33:57 -0700 [thread overview]
Message-ID: <1215030837.6788.37.camel@mingming-laptop> (raw)
In-Reply-To: <1215019194.6788.10.camel@mingming-laptop>
[-- Attachment #1: Type: text/plain, Size: 3279 bytes --]
On Wed, 2008-07-02 at 10:19 -0700, Mingming Cao wrote:
> On Tue, 2008-07-01 at 17:50 +0000, Gary Hawco wrote:
> > Mingming,
> >
> > Can you post that patch somewhere for download? I access my email using
> > Windows Vista, not in linux, so it would be very laborious to hand copy
> > this patch and recreate it in linux.
> >
> Patch attached.
Please use this patch instead, after discuss with Ted, I found an issue
with the patch I sent to the list. ext4 patch queue is also updated with
latest patch.
Ext4: fix delalloc i_disksize early update issue
From: Mingming Cao <cmm@us.ibm.com>
Ext4_da_write_end() uses ext4_bh_unmapped_or_delay() function to check
if it extend the file size without need for allocation. But at that time
the buffer has not being dirtied yet (done in code later in
block_commit_write()), so it always return true and update i_disksize
(before block allocation). we could fix that ext4_da_write_end() to not
use this helper function.
This also fixed another issue:
The i_disksize is updated at ext4_da_write_end() time if
writes to the end of file, and the buffers are all have
blocks allocated. But in the case blocksize < pagesize, and
if the page has, say, the first buffer marked
as buffer_delay, and the write is to EOF and on the third buffer, which
has block already allocated, we certainly need to extend the i_disksize.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
---
fs/ext4/inode.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
Index: linux-2.6.26-rc8/fs/ext4/inode.c
===================================================================
--- linux-2.6.26-rc8.orig/fs/ext4/inode.c 2008-07-02 09:53:42.000000000 -0700
+++ linux-2.6.26-rc8/fs/ext4/inode.c 2008-07-02 13:22:52.000000000 -0700
@@ -1891,6 +1891,32 @@ out:
return ret;
}
+/*
+ * Check if we should update i_disksize
+ * when write to the end of file but not require block allocation
+ */
+static int ext4_da_should_update_i_disksize(struct page *page,
+ unsigned long offset)
+{
+ struct buffer_head *head, *bh;
+ unsigned int curr_off = 0;
+
+ head = page_buffers(page);
+ bh = head;
+ do {
+ unsigned int next_off = curr_off + bh->b_size;
+
+ if (curr_off <= offset && offset < next_off)
+ if (!buffer_mapped(bh) || (buffer_delay(bh)))
+ return 0;
+ else
+ return 1;
+ curr_off = next_off;
+ } while ((bh = bh->b_this_page) != head);
+
+ return 1;
+}
+
static int ext4_da_write_end(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
@@ -1900,6 +1926,10 @@ static int ext4_da_write_end(struct file
int ret = 0, ret2;
handle_t *handle = ext4_journal_current_handle();
loff_t new_i_size;
+ unsigned long start, end;
+
+ start = pos & (PAGE_CACHE_SIZE - 1);
+ end = start + copied;
/*
* generic_write_end() will run mark_inode_dirty() if i_size
@@ -1909,8 +1939,7 @@ static int ext4_da_write_end(struct file
new_i_size = pos + copied;
if (new_i_size > EXT4_I(inode)->i_disksize)
- if (!walk_page_buffers(NULL, page_buffers(page),
- 0, len, NULL, ext4_bh_unmapped_or_delay)){
+ if (ext4_da_should_update_i_disksize(page, end)) {
/*
* Updating i_disksize when extending file without
* need block allocation
[-- Attachment #2: delalloc_i_disksize_update-fix.patch --]
[-- Type: text/x-patch, Size: 2703 bytes --]
Ext4: fix delalloc i_disksize early update issue
From: Mingming Cao <cmm@us.ibm.com>
Ext4_da_write_end() uses ext4_bh_unmapped_or_delay() function to check
if it extend the file size without need for allocation. But at that time
the buffer has not being dirtied yet (done in code later in
block_commit_write()), so it always return true and update i_disksize
(before block allocation). we could fix that ext4_da_write_end() to not
use this helper function.
This also fixed another issue:
The i_disksize is updated at ext4_da_write_end() time if
writes to the end of file, and the buffers are all have
blocks allocated. But if the page had one buffer marked
as buffer_delay, and the write is at EOF and on a buffer has block
already allocated, we certainly need to extend the i_disksize.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
---
fs/ext4/inode.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
Index: linux-2.6.26-rc8/fs/ext4/inode.c
===================================================================
--- linux-2.6.26-rc8.orig/fs/ext4/inode.c 2008-07-02 09:53:42.000000000 -0700
+++ linux-2.6.26-rc8/fs/ext4/inode.c 2008-07-02 13:22:52.000000000 -0700
@@ -1891,6 +1891,32 @@ out:
return ret;
}
+/*
+ * Check if we should update i_disksize
+ * when write to the end of file but not require block allocation
+ */
+static int ext4_da_should_update_i_disksize(struct page *page,
+ unsigned long offset)
+{
+ struct buffer_head *head, *bh;
+ unsigned int curr_off = 0;
+
+ head = page_buffers(page);
+ bh = head;
+ do {
+ unsigned int next_off = curr_off + bh->b_size;
+
+ if (curr_off <= offset && offset < next_off)
+ if (!buffer_mapped(bh) || (buffer_delay(bh)))
+ return 0;
+ else
+ return 1;
+ curr_off = next_off;
+ } while ((bh = bh->b_this_page) != head);
+
+ return 1;
+}
+
static int ext4_da_write_end(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
@@ -1900,6 +1926,10 @@ static int ext4_da_write_end(struct file
int ret = 0, ret2;
handle_t *handle = ext4_journal_current_handle();
loff_t new_i_size;
+ unsigned long start, end;
+
+ start = pos & (PAGE_CACHE_SIZE - 1);
+ end = start + copied;
/*
* generic_write_end() will run mark_inode_dirty() if i_size
@@ -1909,8 +1939,7 @@ static int ext4_da_write_end(struct file
new_i_size = pos + copied;
if (new_i_size > EXT4_I(inode)->i_disksize)
- if (!walk_page_buffers(NULL, page_buffers(page),
- 0, len, NULL, ext4_bh_unmapped_or_delay)){
+ if (ext4_da_should_update_i_disksize(page, end)) {
/*
* Updating i_disksize when extending file without
* need block allocation
next prev parent reply other threads:[~2008-07-02 20:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-25 13:53 Segmentation Faults with 062508 ext4-patch-queue snapshot Gary Hawco
2008-06-26 4:14 ` Eric Sandeen
2008-06-26 22:12 ` Segmentation Faults with both 062608 snapshots Gary Hawco
2008-07-01 2:32 ` Theodore Tso
2008-07-01 0:00 ` More ext4dev snapshot weirdness Gary Hawco
2008-07-01 16:02 ` Theodore Tso
2008-07-01 10:54 ` delalloc filesystem corruption Gary Hawco
2008-07-01 23:00 ` Mingming Cao
2008-07-01 17:50 ` Gentoo with ext4-patch-queue snapshots Gary Hawco
2008-07-02 17:19 ` Mingming Cao
2008-07-02 20:33 ` Mingming Cao [this message]
2008-07-03 14:07 ` Aneesh Kumar
2008-07-03 17:38 ` Mingming Cao
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=1215030837.6788.37.camel@mingming-laptop \
--to=cmm@us.ibm.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=ghawco@cox.net \
--cc=linux-ext4@vger.kernel.org \
--cc=tytso@mit.edu \
/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.