Commit 33a266dd authored by David Chinner's avatar David Chinner Committed by Linus Torvalds

[PATCH] Make BH_Unwritten a first class bufferhead flag V2

Currently, XFS uses BH_PrivateStart for flagging unwritten extent state in a
bufferhead.  Recently, I found the long standing mmap/unwritten extent
conversion bug, and it was to do with partial page invalidation not clearing
the unwritten flag from bufferheads attached to the page but beyond EOF.  See
here for a full explaination:

The solution I have checked into the XFS dev tree involves duplicating code
from block_invalidatepage to clear the unwritten flag from the bufferhead(s),
and then calling block_invalidatepage() to do the rest.

Christoph suggested that this would be better solved by pushing the unwritten
flag into the common buffer head flags and just adding the call to

The following patch makes BH_Unwritten a first class citizen.
Signed-off-by: default avatarDave Chinner <>
Acked-by: default avatarChristoph Hellwig <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent 42da9cbd
......@@ -1440,6 +1440,7 @@ static void discard_buffer(struct buffer_head * bh)
......@@ -1823,6 +1824,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
!buffer_unwritten(bh) &&
(block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
......@@ -2544,7 +2546,7 @@ int block_truncate_page(struct address_space *mapping,
if (PageUptodate(page))
if (!buffer_uptodate(bh) && !buffer_delay(bh)) {
if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
err = -EIO;
ll_rw_block(READ, 1, &bh);
......@@ -109,16 +109,6 @@
#undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
* State flag for unwritten extent buffers.
* We need to be able to distinguish between these and delayed
* allocate buffers within XFS. The generic IO path code does
* not need to distinguish - we use the BH_Delay flag for both
* delalloc and these ondisk-uninitialised buffers.
BUFFER_FNS(PrivateStart, unwritten);
#define restricted_chown xfs_params.restrict_chown.val
#define irix_sgid_inherit xfs_params.sgid_inherit.val
#define irix_symlink_mode xfs_params.symlink_mode.val
......@@ -34,6 +34,7 @@ enum bh_state_bits {
BH_Write_EIO, /* I/O error on write */
BH_Ordered, /* ordered write */
BH_Eopnotsupp, /* operation not supported (barrier) */
BH_Unwritten, /* Buffer is allocated on disk but not written */
BH_PrivateStart,/* not a state bit, but the first bit available
* for private allocation by other entities
......@@ -126,6 +127,7 @@ BUFFER_FNS(Boundary, boundary)
BUFFER_FNS(Write_EIO, write_io_error)
BUFFER_FNS(Ordered, ordered)
BUFFER_FNS(Eopnotsupp, eopnotsupp)
BUFFER_FNS(Unwritten, unwritten)
#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK)
#define touch_buffer(bh) mark_page_accessed(bh->b_page)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment