linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Wilcox <matthew.r.wilcox@intel.com>
To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-mm@kvack.org, linux-ext4@vger.kernel.org
Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Subject: [PATCH v5 22/22] XIP: Add support for unwritten extents
Date: Wed, 15 Jan 2014 20:24:40 -0500	[thread overview]
Message-ID: <21d60639d747cdd683831ce57e7c753c9fa29ac1.1389779962.git.matthew.r.wilcox@intel.com> (raw)
In-Reply-To: <cover.1389779961.git.matthew.r.wilcox@intel.com>
In-Reply-To: <cover.1389779961.git.matthew.r.wilcox@intel.com>

For read() and pagefault, we treat unwritten extents as holes.
For write(), we have to zero parts of the block that we're not going to
write to.  For holepunches, something's gone quite strangely wrong if we
get an unwritten extent from get_block, considering that the filesystem's
calling us to write zeroes to a partially written extent ...

Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
---
 Documentation/filesystems/xip.txt |  7 +++----
 fs/xip.c                          | 44 +++++++++++++++++++++++++++------------
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt
index b158de6..5e9a0c76 100644
--- a/Documentation/filesystems/xip.txt
+++ b/Documentation/filesystems/xip.txt
@@ -60,10 +60,9 @@ Filesystem support consists of
   truncates and page faults
 
 The get_block() callback passed to xip_do_io(), xip_fault(), xip_mkwrite()
-and xip_truncate_page() must not return uninitialised extents.  It must zero
-any blocks that it returns, and it must ensure that simultaneous calls to
-get_block() (for example by a page-fault racing with a read() or a write())
-work correctly.
+and xip_truncate_page() may return uninitialised extents.  If it does, it
+must ensure that simultaneous calls to get_block() (for example by a
+page-fault racing with a read() or a write()) work correctly.
 
 These filesystems may be used for inspiration:
 - ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
diff --git a/fs/xip.c b/fs/xip.c
index 88a516b..d160320 100644
--- a/fs/xip.c
+++ b/fs/xip.c
@@ -79,6 +79,12 @@ static long xip_get_pfn(struct inode *inode, struct buffer_head *bh,
 	return ops->direct_access(bdev, sector, &addr, pfn, bh->b_size);
 }
 
+/* true if a buffer_head represents written data */
+static bool buffer_written(struct buffer_head *bh)
+{
+	return buffer_mapped(bh) && !buffer_unwritten(bh);
+}
+
 static ssize_t xip_io(int rw, struct inode *inode, const struct iovec *iov,
 			loff_t start, loff_t end, unsigned nr_segs,
 			get_block_t get_block, struct buffer_head *bh)
@@ -103,21 +109,29 @@ static ssize_t xip_io(int rw, struct inode *inode, const struct iovec *iov,
 			retval = get_block(inode, block, bh, rw == WRITE);
 			if (retval)
 				break;
-			if (buffer_mapped(bh)) {
-				retval = xip_get_addr(inode, bh, &addr);
-				if (retval < 0)
-					break;
-				addr += offset - (block << inode->i_blkbits);
-				hole = false;
-				size = retval;
-			} else {
-				if (rw == WRITE) {
+			if (rw == WRITE) {
+				if (!buffer_mapped(bh)) {
 					retval = -EIO;
 					break;
 				}
+				hole = false;
+			} else {
+				hole = !buffer_written(bh);
+			}
+
+			if (hole) {
 				addr = NULL;
-				hole = true;
 				size = bh->b_size;
+			} else {
+				unsigned first;
+				retval = xip_get_addr(inode, bh, &addr);
+				if (retval < 0)
+					break;
+				size = retval;
+				first = offset - (block << inode->i_blkbits);
+				if (buffer_unwritten(bh))
+					memset(addr, 0, first);
+				addr += first;
 			}
 			max = offset + size;
 		}
@@ -265,7 +279,7 @@ static int do_xip_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
 	if (error || bh.b_size < PAGE_SIZE)
 		return VM_FAULT_SIGBUS;
 
-	if (!buffer_mapped(&bh) && !vmf->cow_page) {
+	if (!buffer_written(&bh) && !vmf->cow_page) {
 		if (vmf->flags & FAULT_FLAG_WRITE) {
 			error = get_block(inode, block, &bh, 1);
 			count_vm_event(PGMAJFAULT);
@@ -286,7 +300,7 @@ static int do_xip_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
 		return VM_FAULT_SIGBUS;
 	}
 	if (vmf->cow_page) {
-		if (buffer_mapped(&bh))
+		if (buffer_written(&bh))
 			copy_user_bh(vmf->cow_page, inode, &bh, vaddr);
 		else
 			clear_user_highpage(vmf->cow_page, vaddr);
@@ -397,7 +411,11 @@ int xip_zero_page_range(struct inode *inode, loff_t from, unsigned length,
 	err = get_block(inode, index, &bh, 0);
 	if (err < 0)
 		return err;
-	if (buffer_mapped(&bh)) {
+	if (buffer_written(&bh)) {
+		/*
+		 * Should this be BUG_ON(!buffer_mapped)?  Surely we should
+		 * never be called for an unmapped block ...
+		 */
 		void *addr;
 		err = xip_get_addr(inode, &bh, &addr);
 		if (err)
-- 
1.8.5.2


  parent reply	other threads:[~2014-01-16  1:27 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-16  1:24 [PATCH v5 00/22] Rewrite XIP code and add XIP support to ext4 Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 01/22] Fix XIP fault vs truncate race Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 02/22] Allow page fault handlers to perform the COW Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 03/22] axonram: Fix bug in direct_access Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 04/22] Change direct_access calling convention Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 05/22] Introduce IS_XIP(inode) Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 06/22] Treat XIP like O_DIRECT Matthew Wilcox
2014-01-31 16:59   ` Jan Kara
2014-01-16  1:24 ` [PATCH v5 07/22] Rewrite XIP page fault handling Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 08/22] Change xip_truncate_page to take a get_block parameter Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 09/22] Remove mm/filemap_xip.c Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 10/22] Remove get_xip_mem Matthew Wilcox
2014-01-16  1:46   ` Randy Dunlap
2014-01-27 13:26     ` Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 11/22] Replace ext2_clear_xip_target with xip_clear_blocks Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 12/22] ext2: Remove ext2_xip_verify_sb() Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 13/22] ext2: Remove ext2_use_xip Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 14/22] ext2: Remove xip.c and xip.h Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 15/22] Remove CONFIG_EXT2_FS_XIP Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 16/22] ext2: Remove ext2_aops_xip Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 17/22] xip: Add xip_zero_page_range Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 18/22] ext4: Make ext4_block_zero_page_range static Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 19/22] ext4: Add XIP functionality Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 20/22] ext4: Fix typos Matthew Wilcox
2014-01-16  1:24 ` [PATCH v5 21/22] xip: Add reporting of major faults Matthew Wilcox
2014-01-16  1:24 ` Matthew Wilcox [this message]
     [not found] ` <CEFDA737.22F87%matthew.r.wilcox@intel.com>
2014-01-17  0:00   ` [PATCH v5 19/22] ext4: Add XIP functionality Ross Zwisler
     [not found] ` <CEFD7DAD.22F65%matthew.r.wilcox@intel.com>
2014-01-22 22:51   ` [PATCH v5 22/22] XIP: Add support for unwritten extents Ross Zwisler
2014-01-23 12:08     ` Matthew Wilcox
2014-01-23 19:13       ` Ross Zwisler
     [not found]     ` <CF0C370C.235F1%willy@linux.intel.com>
2014-01-27 23:32       ` Ross Zwisler
2014-01-28  3:49         ` Matthew Wilcox
2014-01-23  7:48 ` [PATCH v5 00/22] Rewrite XIP code and add XIP support to ext4 Dave Chinner
2014-01-23  7:53   ` Dave Chinner
2014-01-23  9:01 ` Dave Chinner
2014-01-23 12:12   ` Wilcox, Matthew R
2014-01-28  6:06     ` Dave Chinner
2014-01-30  6:42 ` Dave Chinner
2014-01-30  9:25   ` Dave Chinner
2014-01-31  3:06     ` Dave Chinner
2014-01-31  5:45       ` Ross Zwisler
2014-01-31 13:04         ` Dave Chinner
     [not found] ` <CF1FF3EB.24114%matthew.r.wilcox@intel.com>
2014-02-11 23:12   ` [PATCH v5 19/22] ext4: Add XIP functionality Ross Zwisler
2014-02-13  0:00     ` Ross Zwisler
     [not found] ` <CF215477.24281%matthew.r.wilcox@intel.com>
2014-02-12 23:53   ` [PATCH v5 06/22] Treat XIP like O_DIRECT Ross Zwisler

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=21d60639d747cdd683831ce57e7c753c9fa29ac1.1389779962.git.matthew.r.wilcox@intel.com \
    --to=matthew.r.wilcox@intel.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).