From: Andrew Morton <akpm@zip.com.au>
To: Alexander Viro <viro@math.psu.edu>
Cc: Andrea Arcangeli <andrea@suse.de>,
Linus Torvalds <torvalds@transmeta.com>,
torrey.hoffman@myrio.com, linux-kernel@vger.kernel.org,
Marcelo Tosatti <marcelo@conectiva.com.br>,
"Stephen C. Tweedie" <sct@redhat.com>
Subject: Re: ramdisk corruption problems - was: RE: pivot_root and initrdkern el panic woes
Date: Sat, 29 Dec 2001 23:59:22 -0800 [thread overview]
Message-ID: <3C2EC95A.79868A85@zip.com.au> (raw)
In-Reply-To: <3C2EBD62.6A98F670@zip.com.au> <Pine.GSO.4.21.0112300220490.8523-100000@weyl.math.psu.edu>
Alexander Viro wrote:
>
> Erm... I don't think so. Come on - vmtruncate() is obvious candidate
> for out-of-line. Please, look how it was done in 2.4.9-ac*.
Yeah, I thought that was just too damn ugly to make it out of my
ethernet port. Oh well, let's try it anyway.
> BTW, fs/buffer.c part of patch looks mangled.
Looks OK to me.
Here's the latest. It includes the block_write_full_page()
chunk (minus the access-bh-after-submit_bh bug which was in
the original).
So we have three chunks:
generic_file_write(): truncate the blocks when prepare_write()
fails. This is for ENOSPC on write-to-end-of-file.
block_write_full_page(): submit the blocks which we managed
to map. To prevent exposure of old data.
__block_prepare_write(): zero out and dirty the blocks which
we managed to instantiate. This is to prevent exposure of
stale data on ENOSPC during write() to mid-file.
Question: is the block_write_full_page() change correct? We
mark the page not-up-to-date, but end_buffer_io_async() is
going to mark it uptodate anyway.
And what should we do with BH_New?
--- linux-2.4.18-pre1/fs/buffer.c Fri Dec 21 11:19:14 2001
+++ linux-akpm/fs/buffer.c Sat Dec 29 23:39:11 2001
@@ -1512,6 +1512,7 @@ static int __block_write_full_page(struc
int err, i;
unsigned long block;
struct buffer_head *bh, *head;
+ int need_unlock;
if (!PageLocked(page))
BUG();
@@ -1567,8 +1568,34 @@ static int __block_write_full_page(struc
return 0;
out:
+ /*
+ * ENOSPC, or some other error. We may already have added some
+ * blocks to the file, so we need to write these out to avoid
+ * exposing stale data.
+ */
ClearPageUptodate(page);
- UnlockPage(page);
+ bh = head;
+ need_unlock = 1;
+ /* Recovery: lock and submit the mapped buffers */
+ do {
+ if (buffer_mapped(bh)) {
+ lock_buffer(bh);
+ need_unlock = 0;
+ }
+ bh = bh->b_this_page;
+ } while (bh != head);
+ do {
+ struct buffer_head *next = bh->b_this_page;
+ if (buffer_mapped(bh)) {
+ set_buffer_async_io(bh);
+ set_bit(BH_Uptodate, &bh->b_state);
+ clear_bit(BH_Dirty, &bh->b_state);
+ submit_bh(WRITE, bh);
+ }
+ bh = next;
+ } while (bh != head);
+ if (need_unlock)
+ UnlockPage(page);
return err;
}
@@ -1639,6 +1666,17 @@ static int __block_prepare_write(struct
}
return 0;
out:
+ bh = head;
+ block_start = 0;
+ do {
+ if (buffer_new(bh) && !buffer_uptodate(bh)) {
+ memset(kaddr+block_start, 0, bh->b_size);
+ set_bit(BH_Uptodate, &bh->b_state);
+ mark_buffer_dirty(bh);
+ }
+ block_start += bh->b_size;
+ bh = bh->b_this_page;
+ } while (bh != head);
return err;
}
--- linux-2.4.18-pre1/mm/filemap.c Wed Dec 26 11:47:41 2001
+++ linux-akpm/mm/filemap.c Sat Dec 29 23:44:03 2001
@@ -3004,7 +3004,7 @@ generic_file_write(struct file *file,con
kaddr = kmap(page);
status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);
if (status)
- goto unlock;
+ goto sync_failure;
page_fault = __copy_from_user(kaddr+offset, buf, bytes);
flush_dcache_page(page);
status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
@@ -3029,6 +3029,7 @@ unlock:
if (status < 0)
break;
} while (count);
+done:
*ppos = pos;
if (cached_page)
@@ -3050,6 +3051,18 @@ out:
fail_write:
status = -EFAULT;
goto unlock;
+
+sync_failure:
+ /*
+ * If blocksize < pagesize, prepare_write() may have instantiated a
+ * few blocks outside i_size. Trim these off again.
+ */
+ kunmap(page);
+ UnlockPage(page);
+ page_cache_release(page);
+ if (pos + bytes > inode->i_size)
+ vmtruncate(inode, inode->i_size);
+ goto done;
o_direct:
written = generic_file_direct_IO(WRITE, file, (char *) buf, count, pos);
next prev parent reply other threads:[~2001-12-30 8:03 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-12-20 19:06 ramdisk corruption problems - was: RE: pivot_root and initrd kern el panic woes Torrey Hoffman
2001-12-20 19:46 ` Linus Torvalds
2001-12-20 22:56 ` Alexander Viro
2001-12-20 23:42 ` Andrea Arcangeli
2001-12-21 1:49 ` Andrea Arcangeli
[not found] ` <3C22CF16.C78B1F19@zip.com.au>
2001-12-29 15:40 ` Andrea Arcangeli
2001-12-30 6:19 ` Andrew Morton
2001-12-30 6:33 ` Alexander Viro
2001-12-30 6:38 ` Andrew Morton
2001-12-30 7:17 ` Alexander Viro
2001-12-30 10:15 ` ramdisk corruption problems - was: RE: pivot_root and initrd Alan Cox
2001-12-31 0:08 ` ramdisk corruption problems - was: RE: pivot_root and initrd kern el panic woes Andrea Arcangeli
2001-12-30 7:08 ` Andrew Morton
2001-12-30 7:29 ` Alexander Viro
2001-12-30 7:59 ` Andrew Morton [this message]
2001-12-30 17:40 ` ramdisk corruption problems - was: RE: pivot_root and initrdkern " Linus Torvalds
2001-12-31 0:28 ` Andrea Arcangeli
2001-12-31 0:35 ` Linus Torvalds
2001-12-31 1:00 ` Andrea Arcangeli
2001-12-31 0:05 ` ramdisk corruption problems - was: RE: pivot_root and initrd kern " Andrea Arcangeli
2002-01-05 11:43 ` Andrew Morton
2002-01-05 14:04 ` Trond Myklebust
2002-01-07 3:08 ` Andrea Arcangeli
2002-01-07 3:49 ` Andrew Morton
2002-01-07 4:31 ` Andrea Arcangeli
2001-12-30 23:56 ` Andrea Arcangeli
2001-12-31 10:06 ` Daniel Phillips
2002-01-04 16:38 ` Stephen C. Tweedie
2002-01-05 7:53 ` Andrew Morton
2002-01-07 1:08 ` Andrea Arcangeli
2001-12-21 1:38 ` Tachino Nobuhiro
2001-12-21 1:51 ` Everyone else but TWO Andre Hedrick
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=3C2EC95A.79868A85@zip.com.au \
--to=akpm@zip.com.au \
--cc=andrea@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=marcelo@conectiva.com.br \
--cc=sct@redhat.com \
--cc=torrey.hoffman@myrio.com \
--cc=torvalds@transmeta.com \
--cc=viro@math.psu.edu \
/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.