From: Andrew Morton <akpm@osdl.org>
To: Oliver Xymoron <oxymoron@waste.org>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] [1/3] writes: report truncate and io errors on async writes
Date: Sat, 2 Aug 2003 03:47:56 -0700 [thread overview]
Message-ID: <20030802034756.11c7287c.akpm@osdl.org> (raw)
In-Reply-To: <20030802041731.GA22824@waste.org>
Oliver Xymoron <oxymoron@waste.org> wrote:
>
> These patches add the missing infrastructure for reporting
> asynchronous write errors to block devices to userspace. Errors are
> reported at the next fsync, fdatasync, or msync on the given file, and
> on close if the error occurs in time.
Thank you for persisting with this. I won't lose the patches this time.
I made some adjustments...
- code simplifications
- No need to lock the page to stabilise ->mapping in mpage.c
fs/mpage.c | 29 +++++++----------------------
fs/open.c | 10 ++++------
mm/filemap.c | 6 +++---
mm/vmscan.c | 38 +++++++++++++++++++++++---------------
4 files changed, 37 insertions(+), 46 deletions(-)
diff -puN fs/open.c~awe-core-fixes fs/open.c
--- 25/fs/open.c~awe-core-fixes 2003-08-02 03:33:28.000000000 -0700
+++ 25-akpm/fs/open.c 2003-08-02 03:33:28.000000000 -0700
@@ -955,20 +955,18 @@ int filp_close(struct file *filp, fl_own
}
err = mapping->error;
- if (err && !retval) {
- mapping->error = 0;
+ if (!retval)
retval = err;
- }
+ mapping->error = 0;
if (!file_count(filp)) {
printk(KERN_ERR "VFS: Close: file count is 0\n");
return retval;
}
- if (filp->f_op && filp->f_op->flush)
- {
+ if (filp->f_op && filp->f_op->flush) {
err = filp->f_op->flush(filp);
- if (err && !retval)
+ if (!retval)
retval = err;
}
diff -puN mm/vmscan.c~awe-core-fixes mm/vmscan.c
--- 25/mm/vmscan.c~awe-core-fixes 2003-08-02 03:33:28.000000000 -0700
+++ 25-akpm/mm/vmscan.c 2003-08-02 03:33:37.000000000 -0700
@@ -236,6 +236,27 @@ static int may_write_to_queue(struct bac
}
/*
+ * We detected a synchronous write error writing a page out. Probably
+ * -ENOSPC. We need to propagate that into the address_space for a subsequent
+ * fsync(), msync() or close().
+ *
+ * The tricky part is that after writepage we cannot touch the mapping: nothing
+ * prevents it from being freed up. But we have a ref on the page and once
+ * that page is locked, the mapping is pinned.
+ *
+ * We're allowed to run sleeping lock_page() here because we know the caller has
+ * __GFP_FS.
+ */
+static void handle_write_error(struct address_space *mapping,
+ struct page *page, int error)
+{
+ lock_page(page);
+ if (page->mapping == mapping)
+ mapping->error = error;
+ unlock_page(page);
+}
+
+/*
* shrink_list returns the number of reclaimed pages
*/
static int
@@ -362,21 +383,8 @@ shrink_list(struct list_head *page_list,
SetPageReclaim(page);
res = mapping->a_ops->writepage(page, &wbc);
-
- if (res < 0) {
- /*
- * lock the page to keep truncate away
- * then check that it is still on the
- * mapping.
- */
- lock_page(page);
- if (page->mapping == mapping)
- mapping->error = res;
- unlock_page(page);
- }
- if (res < 0) {
- mapping->error = res;
- }
+ if (res < 0)
+ handle_write_error(mapping, page, res);
if (res == WRITEPAGE_ACTIVATE) {
ClearPageReclaim(page);
goto activate_locked;
diff -puN mm/filemap.c~awe-core-fixes mm/filemap.c
--- 25/mm/filemap.c~awe-core-fixes 2003-08-02 03:33:28.000000000 -0700
+++ 25-akpm/mm/filemap.c 2003-08-02 03:33:28.000000000 -0700
@@ -199,9 +199,9 @@ restart:
spin_unlock(&mapping->page_lock);
/* Check for outstanding write errors */
- if (mapping->error)
- {
- ret = mapping->error;
+ if (mapping->error) {
+ if (!ret)
+ ret = mapping->error;
mapping->error = 0;
}
diff -puN fs/mpage.c~awe-core-fixes fs/mpage.c
--- 25/fs/mpage.c~awe-core-fixes 2003-08-02 03:33:28.000000000 -0700
+++ 25-akpm/fs/mpage.c 2003-08-02 03:33:28.000000000 -0700
@@ -563,17 +563,11 @@ confused:
if (bio)
bio = mpage_bio_submit(WRITE, bio);
*ret = page->mapping->a_ops->writepage(page, wbc);
- if (*ret < 0) {
- /*
- * lock the page to keep truncate away
- * then check that it is still on the
- * mapping.
- */
- lock_page(page);
- if (page->mapping == mapping)
- mapping->error = *ret;
- unlock_page(page);
- }
+ /*
+ * The caller has a ref on the inode, so *mapping is stable
+ */
+ if (*ret < 0)
+ mapping->error = *ret;
out:
return bio;
}
@@ -675,17 +669,8 @@ mpage_writepages(struct address_space *m
test_clear_page_dirty(page)) {
if (writepage) {
ret = (*writepage)(page, wbc);
- if (ret < 0) {
- /*
- * lock the page to keep truncate away
- * then check that it is still on the
- * mapping.
- */
- lock_page(page);
- if (page->mapping == mapping)
- mapping->error = ret;
- unlock_page(page);
- }
+ if (ret < 0)
+ mapping->error = ret;
} else {
bio = mpage_writepage(bio, page, get_block,
&last_block_in_bio, &ret, wbc);
_
next prev parent reply other threads:[~2003-08-02 10:47 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-08-02 4:17 [PATCH] [1/3] writes: report truncate and io errors on async writes Oliver Xymoron
2003-08-02 10:47 ` Andrew Morton [this message]
-- strict thread matches above, loose matches on Subject: below --
2003-08-02 4:13 Oliver Xymoron
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=20030802034756.11c7287c.akpm@osdl.org \
--to=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oxymoron@waste.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 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.