mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: linux-cachefs@redhat.com, nfsv4@linux-nfs.org,
	linux-kernel@vger.kernel.org
Cc: dhowells@redhat.com, steved@redhat.com
Subject: [PATCH 24/28] CacheFiles: Handle truncate unlocking the page we're reading
Date: Thu, 19 Nov 2009 17:22:37 +0000	[thread overview]
Message-ID: <20091119172237.1679.96864.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20091119172033.1679.87046.stgit@warthog.procyon.org.uk>

Handle truncate unlocking the page we're attempting to read from the backing
device before the read has completed.

This was causing reports like the following to occur:

	Pid: 4765, comm: kslowd Not tainted 2.6.30.1 #1
	Call Trace:
	 [<ffffffffa0331d7a>] ? cachefiles_read_waiter+0xd9/0x147 [cachefiles]
	 [<ffffffff804b74bd>] ? __wait_on_bit+0x60/0x6f
	 [<ffffffff8022bbbb>] ? __wake_up_common+0x3f/0x71
	 [<ffffffff8022cc32>] ? __wake_up+0x30/0x44
	 [<ffffffff8024a41f>] ? __wake_up_bit+0x28/0x2d
	 [<ffffffffa003a793>] ? ext3_truncate+0x4d7/0x8ed [ext3]
	 [<ffffffff80281f90>] ? pagevec_lookup+0x17/0x1f
	 [<ffffffff8028c2ff>] ? unmap_mapping_range+0x59/0x1ff
	 [<ffffffff8022cc32>] ? __wake_up+0x30/0x44
	 [<ffffffff8028e286>] ? vmtruncate+0xc2/0xe2
	 [<ffffffff802b82cf>] ? inode_setattr+0x22/0x10a
	 [<ffffffffa003baa5>] ? ext3_setattr+0x17b/0x1e6 [ext3]
	 [<ffffffff802b853d>] ? notify_change+0x186/0x2c9
	 [<ffffffffa032d9de>] ? cachefiles_attr_changed+0x133/0x1cd [cachefiles]
	 [<ffffffffa032df7f>] ? cachefiles_lookup_object+0xcf/0x12a [cachefiles]
	 [<ffffffffa0318165>] ? fscache_lookup_object+0x110/0x122 [fscache]
	 [<ffffffffa03188c3>] ? fscache_object_slow_work_execute+0x590/0x6bc
	[fscache]
	 [<ffffffff80278f82>] ? slow_work_thread+0x285/0x43a
	 [<ffffffff8024a446>] ? autoremove_wake_function+0x0/0x2e
	 [<ffffffff80278cfd>] ? slow_work_thread+0x0/0x43a
	 [<ffffffff8024a317>] ? kthread+0x54/0x81
	 [<ffffffff8020c93a>] ? child_rip+0xa/0x20
	 [<ffffffff8024a2c3>] ? kthread+0x0/0x81
	 [<ffffffff8020c930>] ? child_rip+0x0/0x20
	CacheFiles: I/O Error: Readpage failed on backing file 200000000000810
	FS-Cache: Cache cachefiles stopped due to I/O error

Reported-by: Christian Kujau <lists@nerdbynature.de>
Reported-by: Takashi Iwai <tiwai@suse.de>
Reported-by: Duc Le Minh <duclm.vn@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/cachefiles/rdwr.c |   99 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index 5a84fd7..1d83325 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -40,8 +40,10 @@ static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode,
 
 	_debug("--- monitor %p %lx ---", page, page->flags);
 
-	if (!PageUptodate(page) && !PageError(page))
-		dump_stack();
+	if (!PageUptodate(page) && !PageError(page)) {
+		/* unlocked, not uptodate and not erronous? */
+		_debug("page probably truncated");
+	}
 
 	/* remove from the waitqueue */
 	list_del(&wait->task_list);
@@ -61,6 +63,84 @@ static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode,
 }
 
 /*
+ * handle a probably truncated page
+ * - check to see if the page is still relevant and reissue the read if
+ *   possible
+ * - return -EIO on error, -ENODATA if the page is gone, -EINPROGRESS if we
+ *   must wait again and 0 if successful
+ */
+static int cachefiles_read_reissue(struct cachefiles_object *object,
+				   struct cachefiles_one_read *monitor)
+{
+	struct address_space *bmapping = object->backer->d_inode->i_mapping;
+	struct page *backpage = monitor->back_page, *backpage2;
+	int ret;
+
+	kenter("{ino=%lx},{%lx,%lx}",
+	       object->backer->d_inode->i_ino,
+	       backpage->index, backpage->flags);
+
+	/* skip if the page was truncated away completely */
+	if (backpage->mapping != bmapping) {
+		kleave(" = -ENODATA [mapping]");
+		return -ENODATA;
+	}
+
+	backpage2 = find_get_page(bmapping, backpage->index);
+	if (!backpage2) {
+		kleave(" = -ENODATA [gone]");
+		return -ENODATA;
+	}
+
+	if (backpage != backpage2) {
+		put_page(backpage2);
+		kleave(" = -ENODATA [different]");
+		return -ENODATA;
+	}
+
+	/* the page is still there and we already have a ref on it, so we don't
+	 * need a second */
+	put_page(backpage2);
+
+	INIT_LIST_HEAD(&monitor->op_link);
+	add_page_wait_queue(backpage, &monitor->monitor);
+
+	if (trylock_page(backpage)) {
+		ret = -EIO;
+		if (PageError(backpage))
+			goto unlock_discard;
+		ret = 0;
+		if (PageUptodate(backpage))
+			goto unlock_discard;
+
+		kdebug("reissue read");
+		ret = bmapping->a_ops->readpage(NULL, backpage);
+		if (ret < 0)
+			goto unlock_discard;
+	}
+
+	/* but the page may have been read before the monitor was installed, so
+	 * the monitor may miss the event - so we have to ensure that we do get
+	 * one in such a case */
+	if (trylock_page(backpage)) {
+		_debug("jumpstart %p {%lx}", backpage, backpage->flags);
+		unlock_page(backpage);
+	}
+
+	/* it'll reappear on the todo list */
+	kleave(" = -EINPROGRESS");
+	return -EINPROGRESS;
+
+unlock_discard:
+	unlock_page(backpage);
+	spin_lock_irq(&object->work_lock);
+	list_del(&monitor->op_link);
+	spin_unlock_irq(&object->work_lock);
+	kleave(" = %d", ret);
+	return ret;
+}
+
+/*
  * copy data from backing pages to netfs pages to complete a read operation
  * - driven by FS-Cache's thread pool
  */
@@ -92,20 +172,26 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
 
 		_debug("- copy {%lu}", monitor->back_page->index);
 
-		error = -EIO;
+	recheck:
 		if (PageUptodate(monitor->back_page)) {
 			copy_highpage(monitor->netfs_page, monitor->back_page);
 
 			pagevec_add(&pagevec, monitor->netfs_page);
 			fscache_mark_pages_cached(monitor->op, &pagevec);
 			error = 0;
-		}
-
-		if (error)
+		} else if (!PageError(monitor->back_page)) {
+			/* the page has probably been truncated */
+			error = cachefiles_read_reissue(object, monitor);
+			if (error == -EINPROGRESS)
+				goto next;
+			goto recheck;
+		} else {
 			cachefiles_io_error_obj(
 				object,
 				"Readpage failed on backing file %lx",
 				(unsigned long) monitor->back_page->flags);
+			error = -EIO;
+		}
 
 		page_cache_release(monitor->back_page);
 
@@ -114,6 +200,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
 		fscache_put_retrieval(op);
 		kfree(monitor);
 
+	next:
 		/* let the thread pool have some air occasionally */
 		max--;
 		if (max < 0 || need_resched()) {


  parent reply	other threads:[~2009-11-19 17:22 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-19 17:20 [PATCH 00/28] Fixes for FS-Cache and CacheFiles David Howells
2009-11-19 17:20 ` [PATCH 01/28] SLOW_WORK: Wait for outstanding work items belonging to a module to clear David Howells
2009-11-20  9:19   ` steve
2009-11-19 17:20 ` [PATCH 02/28] SLOW_WORK: Make slow_work_ops ->get_ref/->put_ref optional David Howells
2009-11-19 17:20 ` [PATCH 03/28] SLOW_WORK: Add support for cancellation of slow work David Howells
2009-11-19 17:20 ` [PATCH 04/28] SLOW_WORK: Add delayed_slow_work support David Howells
2009-11-19 17:20 ` [PATCH 05/28] SLOW_WORK: Allow the work items to be viewed through a /proc file David Howells
2009-11-19 17:21 ` [PATCH 06/28] SLOW_WORK: Allow the owner of a work item to determine if it is queued or not David Howells
2009-11-19 17:21 ` [PATCH 07/28] SLOW_WORK: Allow a requeueable work item to sleep till the thread is needed David Howells
2009-11-19 17:21 ` [PATCH 08/28] FS-Cache: Annotate slow-work runqueue proc lines for FS-Cache work items David Howells
2009-11-19 17:21 ` [PATCH 09/28] FS-Cache: Allow the current state of all objects to be dumped David Howells
2009-11-19 17:21 ` [PATCH 10/28] FS-Cache: Add counters for entry/exit to/from cache operation functions David Howells
2009-11-19 17:21 ` [PATCH 11/28] FS-Cache: Clear netfs pointers in cookie after detaching object, not before David Howells
2009-11-19 17:21 ` [PATCH 12/28] FS-Cache: Use radix tree preload correctly in tracking of pages to be stored David Howells
2009-11-19 17:21 ` [PATCH 13/28] FS-Cache: Permit cache retrieval ops to be interrupted in the initial wait phase David Howells
2009-11-19 17:21 ` [PATCH 14/28] FS-Cache: The object-available state can't rely on the cookie to be available David Howells
2009-11-19 17:21 ` [PATCH 15/28] FS-Cache: Fix lock misorder in fscache_write_op() David Howells
2009-11-19 17:21 ` [PATCH 16/28] FS-Cache: Don't delete pending pages from the page-store tracking tree David Howells
2009-11-19 17:22 ` [PATCH 17/28] FS-Cache: Handle read request vs lookup, creation or other cache failure David Howells
2009-11-19 17:22 ` [PATCH 18/28] FS-Cache: Handle pages pending storage that get evicted under OOM conditions David Howells
2009-11-19 17:22 ` [PATCH 19/28] FS-Cache: Add a retirement stat counter David Howells
2009-11-19 17:22 ` [PATCH 20/28] FS-Cache: Make sure FSCACHE_COOKIE_LOOKING_UP cleared on lookup failure David Howells
2009-11-19 17:22 ` [PATCH 21/28] FS-Cache: Start processing an object's operations on that object's death David Howells
2009-11-19 17:22 ` [PATCH 22/28] FS-Cache: Actually requeue an object when requested David Howells
2009-11-19 17:22 ` [PATCH 23/28] CacheFiles: Don't write a full page if there's only a partial page to cache David Howells
2009-11-19 17:22 ` David Howells [this message]
2009-11-19 17:22 ` [PATCH 25/28] CacheFiles: Mark parent directory locks as I_MUTEX_PARENT to keep lockdep happy David Howells
2009-11-19 17:22 ` [PATCH 26/28] CacheFiles: Better showing of debugging information in active object problems David Howells
2009-11-19 17:22 ` [PATCH 27/28] CacheFiles: Catch an overly long wait for an old active object David Howells
2009-11-19 17:22 ` [PATCH 28/28] CacheFiles: Don't log lookup/create failing with ENOBUFS David Howells
2009-11-20  8:16 ` [PATCH 00/28] Fixes for FS-Cache and CacheFiles David Howells
2009-11-20 21:54   ` [PATCH 0/3] " David Howells
2009-11-20 21:54     ` [PATCH 1/3] SLOW_WORK: Fix CIFS to pass THIS_MODULE to slow_work_register_user() David Howells
2009-11-20 21:54     ` [PATCH 2/3] SLOW_WORK: Fix GFS2 to #include <linux/module.h> before using THIS_MODULE David Howells
2009-11-20 21:54     ` [PATCH 3/3] FS-Cache: Provide nop fscache_stat_d() if CONFIG_FSCACHE_STATS=n David Howells
2009-11-20  8:18 ` [PATCH 00/28] Fixes for FS-Cache and CacheFiles David Howells

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=20091119172237.1679.96864.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=linux-cachefs@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nfsv4@linux-nfs.org \
    --cc=steved@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®