2011-08-21 02:26:40

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 0/6 v5] ext4: fix 1k block bugs

This patch set corrects serveral bugs that occur
when blocksize = 1k.

The first bug appears in xfstests 75, 112, 127 and occurs
because the partial pages appearing at the head and tail
of a hole are not properly zeroed and unmapped

A second bug in test 127 occurs when i_size and the end of
the hole appear in the same page. Because punch hole needs
to flush the pages in the hole, it will need to properly
unmap the partial page appearing after i_size.

Another bug occurred during extra fsx testing for the
first two patches. This bug happens because truncate also
does not zero and unmap the partial page at the end of the
file.

Similar bugs also occurred when a write operation begins or
ends in a hole or extends EOF. The partial page of the write
operation needs to be zeroed and unmapped.

These bugs are corrected using a new ext4_discard_partial_page_buffers
routine that zeros a specified region of a page, and unmaps buffer
heads for any block aligned region of the page that was completely
zeroed.

Lastly this set also contains a fix for bug reported by Lukas while
working on a new patch to add discard support to loop devices using
punch hole. This bug occurs when calculating the byte offset for
very large holes because the block number needs to be cast to a wider
data type before cacluating the offset.

This patch set has passed the following tests
(for both 1k and 4k blocksizes):
xfstests 75, 112, 127, 252 and 256
fsx stress test (12 hours)

v1 -> v2
Added EXT4_BLOCK_ZERO_DISCARD_BUFFER flag

v2 -> v3
Moved code out of ext4_zero_block_page_range and in
to new ext4_unmap_page_range function

v3 -> v4
Renamed ext4_unmap_page_range to ext4_unmap_partial_page_buffers
Moved ext4_unmap_partial_page_buffers from inode.c to extents.c
Corrected comments for non block/page aligned handling
Added checks to avoid unnecessary page unmaps
Removed unneeded journaling and mapping from new routine

v4 -> v5
Renamed ext4_unmap_partial_page_buffers to
ext4_discard_partial_page_buffers_no_lock and added
new ext4_discard_partial_page_buffers wrapper function

Modified ext4_discard_partial_page_buffers_no_lock to
zero the page as well as unmap buffers

Moved ext4_discard_partial_page_buffers functions
back to inode.c, and also put in a seperate patch.

Added extra patches for write bugs and truncate bugs

Added extra patch for large hole calculation

Allison Henderson (6):
ext4: Add new ext4_discard_partial_page_buffers routines
ext4: fix xfstests 75, 112, 127 punch hole failure
ext4: fix 2nd xfstests 127 punch hole failure
ext4: Correct large hole offset calcuation
ext4: fix fsx truncate failure
ext4: fix partial page writes

fs/ext4/ext4.h | 11 ++++
fs/ext4/extents.c | 103 +++++++++++++++++++++++--------
fs/ext4/inode.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 262 insertions(+), 26 deletions(-)



2011-08-21 02:26:41

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 1/6 v5] ext4: Add new ext4_discard_partial_page_buffers routines

This patch adds two new routines: ext4_discard_partial_page_buffers
and ext4_discard_partial_page_buffers_no_lock.

The ext4_discard_partial_page_buffers routine is a wrapper
function to ext4_discard_partial_page_buffers_no_lock.
The wrapper function locks the page and passes it to
ext4_discard_partial_page_buffers_no_lock.
Calling functions that already have the page locked can call
ext4_discard_partial_page_buffers_no_lock directly.

The ext4_discard_partial_page_buffers_no_lock function
zeros a specified range in a page, and unmaps the
corresponding buffer heads. This function is meant to
be used to update a page and its buffer heads to be zeroed
and unmaped when the corresponding blocks have been released
or will be released.

This routine is used in the following scenarios:
* A hole is punched and the non page aligned regions
of the head and tail of the hole need to be discarded

* The file is truncated and the partial page beyond EOF needs
to be discarded

* The end of a hole is in the same page as EOF. After the
page is flushed, the partial page beyond EOF needs to be
discarded.

* A write operation begins or ends inside a hole and the partial
page appearing before or after the write needs to be discarded

* A write operation extends EOF and the partial page beyond EOF
needs to be discarded

This function takes a flag EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED
which is used when a write operation begins or ends in a hole.
When the EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED flag is used, only
buffer heads that are already unmapped will have the corresponding
regions of the page zeroed.

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 040b3fa... c386f8d... M fs/ext4/ext4.h
:100644 100644 8fdc298... c1b42cb... M fs/ext4/inode.c
fs/ext4/ext4.h | 11 ++++
fs/ext4/inode.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 040b3fa..c386f8d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -529,6 +529,11 @@ struct ext4_new_group_data {
#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008

/*
+ * Flags used by ext4_discard_partial_page_buffers
+ */
+#define EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED 0x0001
+
+/*
* ioctl commands
*/
#define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS
@@ -1836,6 +1841,12 @@ extern int ext4_block_truncate_page(handle_t *handle,
struct address_space *mapping, loff_t from);
extern int ext4_block_zero_page_range(handle_t *handle,
struct address_space *mapping, loff_t from, loff_t length);
+extern int ext4_discard_partial_page_buffers(handle_t *handle,
+ struct address_space *mapping, loff_t from,
+ loff_t length, int flags);
+extern int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
+ struct inode *inode, struct page *page, loff_t from,
+ loff_t length, int flags);
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
extern qsize_t *ext4_get_reserved_space(struct inode *inode);
extern void ext4_da_update_reserve_space(struct inode *inode,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 8fdc298..c1b42cb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2911,6 +2911,165 @@ void ext4_set_aops(struct inode *inode)
inode->i_mapping->a_ops = &ext4_journalled_aops;
}

+
+/*
+ * ext4_discard_partial_page_buffers()
+ * Wrapper function for ext4_discard_partial_page_buffers_no_lock.
+ * This function finds and locks the page containing the offset
+ * "from" and passes it to ext4_discard_partial_page_buffers_no_lock.
+ * Calling functions that already have the page locked should call
+ * ext4_discard_partial_page_buffers_no_lock directly.
+ */
+int ext4_discard_partial_page_buffers(handle_t *handle,
+ struct address_space *mapping, loff_t from,
+ loff_t length, int flags)
+{
+ struct inode *inode = mapping->host;
+ struct page *page;
+ int err = 0;
+
+ page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,
+ mapping_gfp_mask(mapping) & ~__GFP_FS);
+ if (!page)
+ return -EINVAL;
+
+ err = ext4_discard_partial_page_buffers_no_lock(handle, inode, page,
+ from, length, flags);
+
+ unlock_page(page);
+ page_cache_release(page);
+ return err;
+}
+
+/*
+ * ext4_discard_partial_page_buffers_no_lock()
+ * Zeros a page range of length 'length' starting from offset 'from'
+ * and unmaps the buffer heads that correspond to the block aligned
+ * regions of the page that were fully zeroed. This function assumes
+ * that page has already been locked. The range to be discarded
+ * must be contained with in the given page. If the specified range
+ * exceeds the end of the page it will be shortened to the end
+ * of the page that corresponds to 'from'. This function is appropriate
+ * for updateing a page and it buffer heads to be unmaped and zeroed
+ * for blocks that have been either released, or are going to be released.
+ *
+ * handle: The journal handle
+ * inode: The files inode
+ * page: A locked page that contains the offset "from"
+ * from: The starting byte offset (from the begining of the file)
+ * to begin discarding
+ * len: The length of bytes to discard
+ * flags: Optional flags that may be used:
+ *
+ * EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED
+ * Only zero the regions of the page whose buffer heads
+ * have already been unmapped. This flag is appropriate
+ * for updateing the contents of a page whose blocks may
+ * have already been released, and we only want to zero
+ * out the regions that correspond to those released blocks.
+ *
+ * Returns zero on sucess or negative on failure.
+ */
+int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
+ struct inode *inode, struct page *page, loff_t from,
+ loff_t length, int flags)
+{
+ ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT;
+ unsigned int offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned int blocksize, max, pos;
+ unsigned int end_of_block, range_to_discard;
+ ext4_lblk_t iblock;
+ struct buffer_head *bh;
+ int err = 0;
+
+ blocksize = inode->i_sb->s_blocksize;
+ max = PAGE_CACHE_SIZE - offset;
+
+ if (index != page->index)
+ return -EINVAL;
+
+ /*
+ * correct length if it does not fall between
+ * 'from' and the end of the page
+ */
+ if (length > max || length < 0)
+ length = max;
+
+ iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+
+ if (!page_has_buffers(page))
+ return 0;
+
+ /* Find the buffer that contains "offset" */
+ bh = page_buffers(page);
+ pos = blocksize;
+ while (offset >= pos) {
+ bh = bh->b_this_page;
+ iblock++;
+ pos += blocksize;
+ }
+
+ pos = offset;
+ while (pos < offset + length) {
+ err = 0;
+
+ /* The length of space left to zero and unmap */
+ range_to_discard = offset + length - pos;
+
+ /* The length of space until the end of the block */
+ end_of_block = blocksize - (pos & (blocksize-1));
+
+ /* Do not unmap or zero past end of block */
+ if (range_to_discard > end_of_block)
+ range_to_discard = end_of_block;
+
+
+ if (flags & EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED &&
+ buffer_mapped(bh))
+ goto next;
+
+ if (ext4_should_journal_data(inode)) {
+ BUFFER_TRACE(bh, "get write access");
+ err = ext4_journal_get_write_access(handle, bh);
+ if (err)
+ goto unmap;
+ }
+
+ zero_user(page, pos, range_to_discard);
+
+ BUFFER_TRACE(bh, "buffer discarded");
+
+ err = 0;
+ if (ext4_should_journal_data(inode)) {
+ err = ext4_handle_dirty_metadata(handle, inode, bh);
+ } else {
+ if (ext4_should_order_data(inode) &&
+ EXT4_I(inode)->jinode)
+ err = ext4_jbd2_file_inode(handle, inode);
+ }
+unmap:
+
+ /* If the range is block aligned, unmap */
+ if (range_to_discard == blocksize) {
+ clear_buffer_dirty(bh);
+ bh->b_bdev = NULL;
+ clear_buffer_mapped(bh);
+ clear_buffer_req(bh);
+ clear_buffer_new(bh);
+ clear_buffer_delay(bh);
+ clear_buffer_unwritten(bh);
+ clear_buffer_uptodate(bh);
+ ClearPageUptodate(page);
+ }
+next:
+ bh = bh->b_this_page;
+ iblock++;
+ pos += range_to_discard;
+ }
+
+ return err;
+}
+
/*
* ext4_block_truncate_page() zeroes out a mapping from file offset `from'
* up to the end of the block which corresponds to `from'.
--
1.7.1


2011-08-21 02:26:42

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 3/6 v5] ext4: fix 2nd xfstests 127 punch hole failure

This patch fixes a second punch hole bug found by xfstests 127.

This bug happens because punch hole needs to flush the pages
of the hole to avoid race conditions. But if the end of the
hole is in the same page as i_size, the buffer heads beyond
i_size need to be unmapped and the page needs to be zeroed
after it is flushed.

To correct this, the new ext4_discard_partial_page_buffers
routine is used to zero and unmap the partial page
beyond i_size if the end of the hole appears in the same
page as i_size.

The code has also been optimized to set the end of the hole
to the page after i_size if the specified hole exceeds i_size,
and the code that flushes the pages has been simplified.

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 cd58117... 0d7617d... M fs/ext4/extents.c
fs/ext4/extents.c | 38 ++++++++++++++++++++++++++++++++++----
1 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cd58117..0d7617d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4161,6 +4161,20 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
loff_t first_page, last_page, first_page_offset, last_page_offset;
int ret, credits, blocks_released, err = 0;

+ /* No need to punch hole beyond i_size */
+ if (offset >= inode->i_size)
+ return 0;
+
+ /*
+ * If the hole extends beyond i_size, set the hole
+ * to end after the page that contains i_size
+ */
+ if (offset + length > inode->i_size) {
+ length = inode->i_size +
+ PAGE_CACHE_SIZE - (inode->i_size & (PAGE_CACHE_SIZE - 1)) -
+ offset;
+ }
+
first_block = (offset + sb->s_blocksize - 1) >>
EXT4_BLOCK_SIZE_BITS(sb);
last_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
@@ -4180,11 +4194,10 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
*/
if (mapping->nrpages && mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
err = filemap_write_and_wait_range(mapping,
- first_page_offset == 0 ? 0 : first_page_offset-1,
- last_page_offset);
+ offset, offset + length - 1);

- if (err)
- return err;
+ if (err)
+ return err;
}

/* Now release the pages */
@@ -4239,6 +4252,23 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
}
}

+
+ /*
+ * If i_size is contained in the last page, we need to
+ * unmap and zero the partial page after i_size
+ */
+ if (inode->i_size >> PAGE_CACHE_SHIFT == last_page &&
+ inode->i_size % PAGE_CACHE_SIZE != 0) {
+
+ page_len = PAGE_CACHE_SIZE -
+ (inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+ if (page_len > 0) {
+ ext4_discard_partial_page_buffers(handle,
+ mapping, inode->i_size, page_len, 0);
+ }
+ }
+
/* If there are no blocks to remove, return now */
if (first_block >= last_block)
goto out;
--
1.7.1


2011-08-21 02:26:42

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 2/6 v5] ext4: fix xfstests 75, 112, 127 punch hole failure

This patch addresses a bug found by xfstests 75, 112, 127
when blocksize = 1k

This bug happens because the punch hole code only zeros
out non block aligned regions of the page. This means that if the
blocks are smaller than a page, then the block aligned regions of
the page inside the hole are left un-zeroed, and their buffer heads
are still mapped. This bug is corrected by using
ext4_discard_partial_page_buffers to properly zero the partial page
at the head and tail of the hole, and unmap the corresponding buffer
heads

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 4d73e11... cd58117... M fs/ext4/extents.c
fs/ext4/extents.c | 48 ++++++++++++++++++++++++++++++------------------
1 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 4d73e11..cd58117 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4157,7 +4157,7 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
struct address_space *mapping = inode->i_mapping;
struct ext4_map_blocks map;
handle_t *handle;
- loff_t first_block_offset, last_block_offset, block_len;
+ loff_t first_block_offset, last_block_offset, page_len;
loff_t first_page, last_page, first_page_offset, last_page_offset;
int ret, credits, blocks_released, err = 0;

@@ -4206,24 +4206,36 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
goto out;

/*
- * Now we need to zero out the un block aligned data.
- * If the file is smaller than a block, just
- * zero out the middle
+ * Now we need to zero out the non-page-aligned data in the
+ * pages at the start and tail of the hole, and unmap the buffer
+ * heads for the block aligned regions of the page that were
+ * completely zeroed.
*/
- if (first_block > last_block)
- ext4_block_zero_page_range(handle, mapping, offset, length);
- else {
- /* zero out the head of the hole before the first block */
- block_len = first_block_offset - offset;
- if (block_len > 0)
- ext4_block_zero_page_range(handle, mapping,
- offset, block_len);
-
- /* zero out the tail of the hole after the last block */
- block_len = offset + length - last_block_offset;
- if (block_len > 0) {
- ext4_block_zero_page_range(handle, mapping,
- last_block_offset, block_len);
+ if (first_page > last_page) {
+ /*
+ * If the file space being truncated is contained within a page
+ * just zero out and unmap the middle of that page
+ */
+ ext4_discard_partial_page_buffers(handle,
+ mapping, offset, length, 0);
+ } else {
+ /*
+ * zero out and unmap the partial page that contains
+ * the start of the hole
+ */
+ page_len = first_page_offset - offset;
+ if (page_len > 0)
+ ext4_discard_partial_page_buffers(handle, mapping,
+ offset, page_len, 0);
+
+ /*
+ * zero out and unmap the partial page that contains
+ * the end of the hole
+ */
+ page_len = offset + length - last_page_offset;
+ if (page_len > 0) {
+ ext4_discard_partial_page_buffers(handle, mapping,
+ last_page_offset, page_len, 0);
}
}

--
1.7.1


2011-08-21 02:26:43

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 4/6 v5] ext4: Correct large hole offset calcuation

This bug was reported by Lukas Czerner while working on a
new patch to add discard support for loop devices using
punch hole.

The bug is happens because the data type for logical blocks is
not large enough to calculate the block offset for holes that are
very large. This bug is resolved by casting the ext4_lblk_t
to an loff_t before calculating the byte offset of the block.

Reviewed-and-Tested-by: Lukas Czerner <[email protected]>

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 0d7617d... b417e47... M fs/ext4/extents.c
fs/ext4/extents.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 0d7617d..b417e47 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4179,8 +4179,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
EXT4_BLOCK_SIZE_BITS(sb);
last_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);

- first_block_offset = first_block << EXT4_BLOCK_SIZE_BITS(sb);
- last_block_offset = last_block << EXT4_BLOCK_SIZE_BITS(sb);
+ first_block_offset = ((loff_t)first_block) << EXT4_BLOCK_SIZE_BITS(sb);
+ last_block_offset = ((loff_t)last_block) << EXT4_BLOCK_SIZE_BITS(sb);

first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
last_page = (offset + length) >> PAGE_CACHE_SHIFT;
--
1.7.1


2011-08-21 02:26:44

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 6/6 v5] ext4: fix partial page writes

These bugs were also found during extended fsx testing
for blocksize = 1k.

When ever a write operation begins or ends in a hole,
or extends EOF, the partial page contained in the hole
or beyond EOF needs to be zeroed out.

To correct this the new ext4_discard_partial_page_buffers_no_lock
routine is used to zero out the partial page, but only for buffer
heads that are already unmapped.

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 c1b42cb... 78c723b... M fs/ext4/inode.c
fs/ext4/inode.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c1b42cb..78c723b 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2214,6 +2214,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
pgoff_t index;
struct inode *inode = mapping->host;
handle_t *handle;
+ loff_t page_len;

index = pos >> PAGE_CACHE_SHIFT;

@@ -2260,6 +2261,11 @@ retry:
*/
if (pos + len > inode->i_size)
ext4_truncate_failed_write(inode);
+ } else {
+ page_len = pos & (PAGE_CACHE_SIZE - 1);
+ ext4_discard_partial_page_buffers_no_lock(handle,
+ inode, page, pos - page_len, page_len,
+ EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED);
}

if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -2302,6 +2308,7 @@ static int ext4_da_write_end(struct file *file,
loff_t new_i_size;
unsigned long start, end;
int write_mode = (int)(unsigned long)fsdata;
+ loff_t page_len;

if (write_mode == FALL_BACK_TO_NONDELALLOC) {
if (ext4_should_order_data(inode)) {
@@ -2350,6 +2357,14 @@ static int ext4_da_write_end(struct file *file,
}
ret2 = generic_write_end(file, mapping, pos, len, copied,
page, fsdata);
+
+ page_len = PAGE_CACHE_SIZE -
+ ((pos + copied) & (PAGE_CACHE_SIZE - 1));
+
+ ext4_discard_partial_page_buffers_no_lock(handle,
+ inode, page, pos + copied, page_len,
+ EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED);
+
copied = ret2;
if (ret2 < 0)
ret = ret2;
--
1.7.1


2011-08-21 02:26:43

by Allison Henderson

[permalink] [raw]
Subject: [PATCH 5/6 v5] ext4: fix fsx truncate failure

This patch corrects a bug found during extended fsx
testing for the first two patches.

This bug is caused because the truncate routine only zeros
the unblock aligned portion of the last page. This means
that the block aligned portions of the page appearing after
i_size are left unzeroed, and the buffer heads still mapped.

This bug is corrected by using ext4_discard_partial_page_buffers
in the truncate routine to zero the partial page and unmap
the buffer headers

Signed-off-by: Allison Henderson <[email protected]>
---
:100644 100644 b417e47... fe421bf... M fs/ext4/extents.c
fs/ext4/extents.c | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index b417e47..fe421bf 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3644,6 +3644,7 @@ void ext4_ext_truncate(struct inode *inode)
struct super_block *sb = inode->i_sb;
ext4_lblk_t last_block;
handle_t *handle;
+ loff_t page_len;
int err = 0;

/*
@@ -3660,8 +3661,16 @@ void ext4_ext_truncate(struct inode *inode)
if (IS_ERR(handle))
return;

- if (inode->i_size & (sb->s_blocksize - 1))
- ext4_block_truncate_page(handle, mapping, inode->i_size);
+ if (inode->i_size % PAGE_CACHE_SIZE != 0) {
+
+ page_len = PAGE_CACHE_SIZE -
+ (inode->i_size & (PAGE_CACHE_SIZE - 1));
+
+ if (page_len >= sb->s_blocksize) {
+ ext4_discard_partial_page_buffers(handle,
+ mapping, inode->i_size, page_len, 0);
+ }
+ }

if (ext4_orphan_add(handle, inode))
goto out_stop;
--
1.7.1


2011-08-22 02:38:16

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 1/6 v5] ext4: Add new ext4_discard_partial_page_buffers routines

On Sat, Aug 20, 2011 at 07:29:42PM -0700, Allison Henderson wrote:
> + /* If the range is block aligned, unmap */
> + if (range_to_discard == blocksize) {
> + clear_buffer_dirty(bh);
> + bh->b_bdev = NULL;
> + clear_buffer_mapped(bh);
> + clear_buffer_req(bh);
> + clear_buffer_new(bh);
> + clear_buffer_delay(bh);
> + clear_buffer_unwritten(bh);
> + clear_buffer_uptodate(bh);
> + ClearPageUptodate(page);

Is this ClearPageUptodate() necessary? If the page is uptodate, and
we've zero'ed out the relevant space, why do we need to force the page
to read in from disk again? (In fact, if we want to avoid forcing the
whole punched region to be written to disk, we'll need to get rid of
the ClearPageUptodate() sooner or later --- and I'm not sure I see why
it's needed now. Am I missing something?)

- Ted

2011-08-22 14:33:19

by Allison Henderson

[permalink] [raw]
Subject: Re: [PATCH 1/6 v5] ext4: Add new ext4_discard_partial_page_buffers routines

On 08/21/2011 07:38 PM, Ted Ts'o wrote:
> On Sat, Aug 20, 2011 at 07:29:42PM -0700, Allison Henderson wrote:
>> + /* If the range is block aligned, unmap */
>> + if (range_to_discard == blocksize) {
>> + clear_buffer_dirty(bh);
>> + bh->b_bdev = NULL;
>> + clear_buffer_mapped(bh);
>> + clear_buffer_req(bh);
>> + clear_buffer_new(bh);
>> + clear_buffer_delay(bh);
>> + clear_buffer_unwritten(bh);
>> + clear_buffer_uptodate(bh);
>> + ClearPageUptodate(page);
>
> Is this ClearPageUptodate() necessary? If the page is uptodate, and
> we've zero'ed out the relevant space, why do we need to force the page
> to read in from disk again? (In fact, if we want to avoid forcing the
> whole punched region to be written to disk, we'll need to get rid of
> the ClearPageUptodate() sooner or later --- and I'm not sure I see why
> it's needed now. Am I missing something?)
>
> - Ted

Oh, I see, maybe we can take this out now then. Initially we put this
in there when all we were doing was unmapping the buffer heads. The
idea was that if we just unmap the buffer heads and set the page not
uptodate we wouldnt have to zero the page, but since that didnt work out
for the mapped reads, we added the zeroing back in. I'll run some more
tests to see if we can take it out. Thx!

Allison Henderson

2011-08-22 15:50:34

by Eric Sandeen

[permalink] [raw]
Subject: Re: [PATCH 4/6 v5] ext4: Correct large hole offset calcuation

On 8/20/11 9:29 PM, Allison Henderson wrote:
> This bug was reported by Lukas Czerner while working on a
> new patch to add discard support for loop devices using
> punch hole.
>
> The bug is happens because the data type for logical blocks is

s/is //

> not large enough to calculate the block offset for holes that are

Should that be "the _byte_ offset for holes ...?"

> very large. This bug is resolved by casting the ext4_lblk_t
> to an loff_t before calculating the byte offset of the block.
>
> Reviewed-and-Tested-by: Lukas Czerner <[email protected]>
>
> Signed-off-by: Allison Henderson <[email protected]>


I wonder if it'd be more straightforward to just use a mask
to compute these rather than the right shift / left shift, but
no big deal I guess esp. since we need the intermediate value
anyway?

Aside from the question about the commit message,

Reviewed-by: Eric Sandeen <[email protected]>

> ---
> :100644 100644 0d7617d... b417e47... M fs/ext4/extents.c
> fs/ext4/extents.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 0d7617d..b417e47 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -4179,8 +4179,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
> EXT4_BLOCK_SIZE_BITS(sb);
> last_block = (offset + length) >> EXT4_BLOCK_SIZE_BITS(sb);
>
> - first_block_offset = first_block << EXT4_BLOCK_SIZE_BITS(sb);
> - last_block_offset = last_block << EXT4_BLOCK_SIZE_BITS(sb);
> + first_block_offset = ((loff_t)first_block) << EXT4_BLOCK_SIZE_BITS(sb);
> + last_block_offset = ((loff_t)last_block) << EXT4_BLOCK_SIZE_BITS(sb);
>
> first_page = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
> last_page = (offset + length) >> PAGE_CACHE_SHIFT;


2011-08-22 17:19:45

by Allison Henderson

[permalink] [raw]
Subject: Re: [PATCH 4/6 v5] ext4: Correct large hole offset calcuation

On 08/22/2011 08:50 AM, Eric Sandeen wrote:
> On 8/20/11 9:29 PM, Allison Henderson wrote:
>> This bug was reported by Lukas Czerner while working on a
>> new patch to add discard support for loop devices using
>> punch hole.
>>
>> The bug is happens because the data type for logical blocks is
>
> s/is //
>
>> not large enough to calculate the block offset for holes that are
>
> Should that be "the _byte_ offset for holes ...?"
>
>> very large. This bug is resolved by casting the ext4_lblk_t
>> to an loff_t before calculating the byte offset of the block.
>>
>> Reviewed-and-Tested-by: Lukas Czerner<[email protected]>
>>
>> Signed-off-by: Allison Henderson<[email protected]>
>
>
> I wonder if it'd be more straightforward to just use a mask
> to compute these rather than the right shift / left shift, but
> no big deal I guess esp. since we need the intermediate value
> anyway?

Ah! Now that you point it out, I realized that patch 2 removed the need
for the intermediate values since things are now calculated from the
byte offsets of pages rather than byte offsets of blocks. At the time I
was looking at the bug Lukas had reported, I hadn't finished this set
yet, so this is the patch that resolved the problem when things were
still using block offsets. I added the patch to this set, but it's
probably not really makeing any sort of differnce now. Maybe I can get
rid this patch and just remove these values in patch 2. I will try that
and retest for the bug that Lukas reported.

Also, maybe when the patch for the loop discard support is done, we
could use the steps that Lukas outlined to recreate this bug as a good
punch hole test for xfstests. (Re:[PATCH] loop: add discard support for
loop devices, 8/11/2011) It would probably be a good way to quickly pick
up any punch hole oddness.

Allison Henderson

>
> Aside from the question about the commit message,
>
> Reviewed-by: Eric Sandeen<[email protected]>
>
>> ---
>> :100644 100644 0d7617d... b417e47... M fs/ext4/extents.c
>> fs/ext4/extents.c | 4 ++--
>> 1 files changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index 0d7617d..b417e47 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
>> @@ -4179,8 +4179,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
>> EXT4_BLOCK_SIZE_BITS(sb);
>> last_block = (offset + length)>> EXT4_BLOCK_SIZE_BITS(sb);
>>
>> - first_block_offset = first_block<< EXT4_BLOCK_SIZE_BITS(sb);
>> - last_block_offset = last_block<< EXT4_BLOCK_SIZE_BITS(sb);
>> + first_block_offset = ((loff_t)first_block)<< EXT4_BLOCK_SIZE_BITS(sb);
>> + last_block_offset = ((loff_t)last_block)<< EXT4_BLOCK_SIZE_BITS(sb);
>>
>> first_page = (offset + PAGE_CACHE_SIZE - 1)>> PAGE_CACHE_SHIFT;
>> last_page = (offset + length)>> PAGE_CACHE_SHIFT;
>


2011-08-23 02:36:24

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 5/6 v5] ext4: fix fsx truncate failure

On Sat, Aug 20, 2011 at 07:29:46PM -0700, Allison Henderson wrote:
> This patch corrects a bug found during extended fsx
> testing for the first two patches.
>
> This bug is caused because the truncate routine only zeros
> the unblock aligned portion of the last page. This means
> that the block aligned portions of the page appearing after
> i_size are left unzeroed, and the buffer heads still mapped.
>
> This bug is corrected by using ext4_discard_partial_page_buffers
> in the truncate routine to zero the partial page and unmap
> the buffer headers
>
> Signed-off-by: Allison Henderson <[email protected]>

This patch is causing a failure in xfstests #130. When I bisected it,
the "git bisect finger of blame" pointed to this commit. (This is
commit 83eb170d4 on the "dev" branch on the ext4.git tree at the moment).

- Ted


Running local boot scripts (/etc/rc.local)
FSTESTCFG is "all"
FSTESTSET is "130"
umount: /dev/vdb: not mounted
umount: /dev/vdd: not mounted
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
BEGIN TEST: Ext4 4k block Mon Aug 22 22:27:54 EDT 2011
Device: /dev/vdb
mke2fs options: -q
mount options: -o block_validity
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity /dev/vdc /vdc

130 11s ... - output mismatch (see 130.out.bad)
--- 130.out 2011-08-12 00:06:32.000000000 -0400
+++ 130.out.bad 2011-08-22 22:27:57.550000003 -0400
@@ -4,8 +4,9 @@
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
-00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
+*
+00001000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
*
Ran: 130
Failures: 130
Failed 1 of 1 tests
END TEST: Ext4 4k block Mon Aug 22 22:27:57 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
BEGIN TEST: Ext4 4k block w/nodelalloc and no extents Mon Aug 22 22:27:58 EDT 2011
Device: /dev/vdd
mke2fs options: -q -O ^extents
mount options: -o block_validity,nodelalloc
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q -O ^extents /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,nodelalloc /dev/vdc /vdc

130 11s ... 3s
Ran: 130
Passed all 1 tests
END TEST: Ext4 4k block w/nodelalloc and no extents Mon Aug 22 22:28:01 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdd: 11/327680 files (0.0% non-contiguous), 55935/1310720 blocks
BEGIN TEST: Ext4 4k block w/ no journal Mon Aug 22 22:28:01 EDT 2011
Device: /dev/vdb
mke2fs options: -q -O ^has_journal
mount options: -o block_validity,noload
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q -O ^has_journal /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,noload /dev/vdc /vdc

130 3s ... - output mismatch (see 130.out.bad)
--- 130.out 2011-08-12 00:06:32.000000000 -0400
+++ 130.out.bad 2011-08-22 22:28:04.490000003 -0400
@@ -4,8 +4,9 @@
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
-00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
+*
+00001000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
*
Ran: 130
Failures: 130
Failed 1 of 1 tests
END TEST: Ext4 4k block w/ no journal Mon Aug 22 22:28:04 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
BEGIN TEST: Ext4 1k block Mon Aug 22 22:28:05 EDT 2011
Device: /dev/vdd
mke2fs options: -q -b 1024
mount options: -o block_validity
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q -b 1024 /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity /dev/vdc /vdc

130 3s ... - output mismatch (see 130.out.bad)
--- 130.out 2011-08-12 00:06:32.000000000 -0400
+++ 130.out.bad 2011-08-22 22:28:08.160000004 -0400
@@ -4,8 +4,9 @@
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
-00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
+*
+00000400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*
00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
*
Ran: 130
Failures: 130
Failed 1 of 1 tests
END TEST: Ext4 1k block Mon Aug 22 22:28:08 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdd: 11/327680 files (0.0% non-contiguous), 119861/5242880 blocks
BEGIN TEST: Ext4 4k block w/bigalloc Mon Aug 22 22:28:08 EDT 2011
Device: /dev/vdd
mke2fs options: -q -O bigalloc
mount options: -o block_validity
000 - unknown test, ignored
[1825745.459201] EXT4-fs (vdd): couldn't mount RDWR because of unsupported optional features (200)
mount: wrong fs type, bad option, bad superblock on /dev/vdd,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so

common.rc: retrying test device mount with external set
[1825745.488666] EXT4-fs (vdd): couldn't mount RDWR because of unsupported optional features (200)
mount: wrong fs type, bad option, bad superblock on /dev/vdd,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so

common.rc: could not mount /dev/vdd on /vdd
END TEST: Ext4 4k block w/bigalloc Mon Aug 22 22:28:08 EDT 2011
umount: /dev/vdd: not mounted
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdd: 11/81936 files (0.0% non-contiguous), 38032/1310720 blocks
BEGIN TEST: Ext4 4k block w/data=journal Mon Aug 22 22:28:08 EDT 2011
Device: /dev/vdb
mke2fs options: -q
mount options: -o block_validity,data=journal
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,data=journal /dev/vdc /vdc

[1825745.927937] EXT4-fs: Warning: mounting with data=journal disables delayed allocation and O_DIRECT support!
130 3s ... 2s
Ran: 130
Passed all 1 tests
END TEST: Ext4 4k block w/data=journal Mon Aug 22 22:28:12 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
BEGIN TEST: Ext4 4k block w/dioread_nolock Mon Aug 22 22:28:12 EDT 2011
Device: /dev/vdb
mke2fs options: -q
mount options: -o block_validity,dioread_nolock
000 - unknown test, ignored
FSTYP -- ext4
PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
MKFS_OPTIONS -- -q /dev/vdc
MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,dioread_nolock /dev/vdc /vdc

[1825749.476751] EXT4-fs (vdc): can't mount with dioread_nolock if block size != PAGE_SIZE
our local mount routine ...
mount: wrong fs type, bad option, bad superblock on /dev/vdc,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so

check: failed to mount $SCRATCH_DEV using specified options
Passed all 0 tests
END TEST: Ext4 4k block w/dioread_nolock Mon Aug 22 22:28:12 EDT 2011
e2fsck 1.42-WIP (02-Jul-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
INIT: Switching to runlevel: 0
INIT: Sending processes the TERM signal
error: 'stop-bootlogd' exited outside the expected code flow.
Using makefile-style concurrent boot in runlevel 0.
Saving random seed...done.
Stopping quota service: rpc.rquotad.
Turning off quotas...quotaoff: Warning: No quota format detected in the kernel.
done.
Asking all remaining processes to terminate...done.
All processes ended within 1 seconds....done.
Deconfiguring network interfaces...done.
Cleaning up ifupdown....
Saving the system clock.
Hardware Clock updated to Mon Aug 22 22:28:15 EDT 2011.
Will now unmount temporary filesystems:tmpfs has been unmounted
.
Will now deactivate swap:.
Mounting root filesystem read-only...done.
Will now halt.
[1825755.423049] Power down.
EXIT_SUCCESS

2011-08-23 02:51:33

by Allison Henderson

[permalink] [raw]
Subject: Re: [PATCH 5/6 v5] ext4: fix fsx truncate failure

On 08/22/2011 07:36 PM, Ted Ts'o wrote:
> On Sat, Aug 20, 2011 at 07:29:46PM -0700, Allison Henderson wrote:
>> This patch corrects a bug found during extended fsx
>> testing for the first two patches.
>>
>> This bug is caused because the truncate routine only zeros
>> the unblock aligned portion of the last page. This means
>> that the block aligned portions of the page appearing after
>> i_size are left unzeroed, and the buffer heads still mapped.
>>
>> This bug is corrected by using ext4_discard_partial_page_buffers
>> in the truncate routine to zero the partial page and unmap
>> the buffer headers
>>
>> Signed-off-by: Allison Henderson<[email protected]>
>
> This patch is causing a failure in xfstests #130. When I bisected it,
> the "git bisect finger of blame" pointed to this commit. (This is
> commit 83eb170d4 on the "dev" branch on the ext4.git tree at the moment).
>
> - Ted
Alrighty, I'll take a look at it, thx!

Allison Henderson

>
>
> Running local boot scripts (/etc/rc.local)
> FSTESTCFG is "all"
> FSTESTSET is "130"
> umount: /dev/vdb: not mounted
> umount: /dev/vdd: not mounted
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
> BEGIN TEST: Ext4 4k block Mon Aug 22 22:27:54 EDT 2011
> Device: /dev/vdb
> mke2fs options: -q
> mount options: -o block_validity
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity /dev/vdc /vdc
>
> 130 11s ... - output mismatch (see 130.out.bad)
> --- 130.out 2011-08-12 00:06:32.000000000 -0400
> +++ 130.out.bad 2011-08-22 22:27:57.550000003 -0400
> @@ -4,8 +4,9 @@
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> wrote 65536/65536 bytes at offset 65536
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> -00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
> -00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> +00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
> +*
> +00001000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> *
> 00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
> *
> Ran: 130
> Failures: 130
> Failed 1 of 1 tests
> END TEST: Ext4 4k block Mon Aug 22 22:27:57 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
> BEGIN TEST: Ext4 4k block w/nodelalloc and no extents Mon Aug 22 22:27:58 EDT 2011
> Device: /dev/vdd
> mke2fs options: -q -O ^extents
> mount options: -o block_validity,nodelalloc
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q -O ^extents /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,nodelalloc /dev/vdc /vdc
>
> 130 11s ... 3s
> Ran: 130
> Passed all 1 tests
> END TEST: Ext4 4k block w/nodelalloc and no extents Mon Aug 22 22:28:01 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdd: 11/327680 files (0.0% non-contiguous), 55935/1310720 blocks
> BEGIN TEST: Ext4 4k block w/ no journal Mon Aug 22 22:28:01 EDT 2011
> Device: /dev/vdb
> mke2fs options: -q -O ^has_journal
> mount options: -o block_validity,noload
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q -O ^has_journal /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,noload /dev/vdc /vdc
>
> 130 3s ... - output mismatch (see 130.out.bad)
> --- 130.out 2011-08-12 00:06:32.000000000 -0400
> +++ 130.out.bad 2011-08-22 22:28:04.490000003 -0400
> @@ -4,8 +4,9 @@
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> wrote 65536/65536 bytes at offset 65536
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> -00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
> -00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> +00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
> +*
> +00001000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> *
> 00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
> *
> Ran: 130
> Failures: 130
> Failed 1 of 1 tests
> END TEST: Ext4 4k block w/ no journal Mon Aug 22 22:28:04 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
> BEGIN TEST: Ext4 1k block Mon Aug 22 22:28:05 EDT 2011
> Device: /dev/vdd
> mke2fs options: -q -b 1024
> mount options: -o block_validity
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q -b 1024 /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity /dev/vdc /vdc
>
> 130 3s ... - output mismatch (see 130.out.bad)
> --- 130.out 2011-08-12 00:06:32.000000000 -0400
> +++ 130.out.bad 2011-08-22 22:28:08.160000004 -0400
> @@ -4,8 +4,9 @@
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> wrote 65536/65536 bytes at offset 65536
> XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> -00000000: 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c...............
> -00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> +00000000: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 cccccccccccccccc
> +*
> +00000400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> *
> 00010000: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
> *
> Ran: 130
> Failures: 130
> Failed 1 of 1 tests
> END TEST: Ext4 1k block Mon Aug 22 22:28:08 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdd: 11/327680 files (0.0% non-contiguous), 119861/5242880 blocks
> BEGIN TEST: Ext4 4k block w/bigalloc Mon Aug 22 22:28:08 EDT 2011
> Device: /dev/vdd
> mke2fs options: -q -O bigalloc
> mount options: -o block_validity
> 000 - unknown test, ignored
> [1825745.459201] EXT4-fs (vdd): couldn't mount RDWR because of unsupported optional features (200)
> mount: wrong fs type, bad option, bad superblock on /dev/vdd,
> missing codepage or helper program, or other error
> In some cases useful info is found in syslog - try
> dmesg | tail or so
>
> common.rc: retrying test device mount with external set
> [1825745.488666] EXT4-fs (vdd): couldn't mount RDWR because of unsupported optional features (200)
> mount: wrong fs type, bad option, bad superblock on /dev/vdd,
> missing codepage or helper program, or other error
> In some cases useful info is found in syslog - try
> dmesg | tail or so
>
> common.rc: could not mount /dev/vdd on /vdd
> END TEST: Ext4 4k block w/bigalloc Mon Aug 22 22:28:08 EDT 2011
> umount: /dev/vdd: not mounted
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdd: 11/81936 files (0.0% non-contiguous), 38032/1310720 blocks
> BEGIN TEST: Ext4 4k block w/data=journal Mon Aug 22 22:28:08 EDT 2011
> Device: /dev/vdb
> mke2fs options: -q
> mount options: -o block_validity,data=journal
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,data=journal /dev/vdc /vdc
>
> [1825745.927937] EXT4-fs: Warning: mounting with data=journal disables delayed allocation and O_DIRECT support!
> 130 3s ... 2s
> Ran: 130
> Passed all 1 tests
> END TEST: Ext4 4k block w/data=journal Mon Aug 22 22:28:12 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
> BEGIN TEST: Ext4 4k block w/dioread_nolock Mon Aug 22 22:28:12 EDT 2011
> Device: /dev/vdb
> mke2fs options: -q
> mount options: -o block_validity,dioread_nolock
> 000 - unknown test, ignored
> FSTYP -- ext4
> PLATFORM -- Linux/x86_64 candygram 3.1.0-gcg-DEV
> MKFS_OPTIONS -- -q /dev/vdc
> MOUNT_OPTIONS -- -o acl,user_xattr -o block_validity,dioread_nolock /dev/vdc /vdc
>
> [1825749.476751] EXT4-fs (vdc): can't mount with dioread_nolock if block size != PAGE_SIZE
> our local mount routine ...
> mount: wrong fs type, bad option, bad superblock on /dev/vdc,
> missing codepage or helper program, or other error
> In some cases useful info is found in syslog - try
> dmesg | tail or so
>
> check: failed to mount $SCRATCH_DEV using specified options
> Passed all 0 tests
> END TEST: Ext4 4k block w/dioread_nolock Mon Aug 22 22:28:12 EDT 2011
> e2fsck 1.42-WIP (02-Jul-2011)
> Pass 1: Checking inodes, blocks, and sizes
> Pass 2: Checking directory structure
> Pass 3: Checking directory connectivity
> Pass 4: Checking reference counts
> Pass 5: Checking group summary information
> /dev/vdb: 6030/327680 files (3.1% non-contiguous), 77032/1310720 blocks
> INIT: Switching to runlevel: 0
> INIT: Sending processes the TERM signal
> error: 'stop-bootlogd' exited outside the expected code flow.
> Using makefile-style concurrent boot in runlevel 0.
> Saving random seed...done.
> Stopping quota service: rpc.rquotad.
> Turning off quotas...quotaoff: Warning: No quota format detected in the kernel.
> done.
> Asking all remaining processes to terminate...done.
> All processes ended within 1 seconds....done.
> Deconfiguring network interfaces...done.
> Cleaning up ifupdown....
> Saving the system clock.
> Hardware Clock updated to Mon Aug 22 22:28:15 EDT 2011.
> Will now unmount temporary filesystems:tmpfs has been unmounted
> .
> Will now deactivate swap:.
> Mounting root filesystem read-only...done.
> Will now halt.
> [1825755.423049] Power down.
> EXIT_SUCCESS