linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dmitri Monakhov <dmonakhov@openvz.org>
To: linux-kernel@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org, Dmitri Monakhov <dmonakhov@openvz.org>
Subject: [PATCH 1/2] fs: truncate blocks outside i_size after generic_file_direct_write error
Date: Sun, 19 Oct 2008 18:03:00 +0400	[thread overview]
Message-ID: <1224424981-5144-1-git-send-email-dmonakhov@openvz.org> (raw)
In-Reply-To: <>

We need to remove block that was allocated in generic_file_direct_write()
if we fail. We have to do it *regardless* to blocksize. At least ext2,
ext3 and reiserfs interpret (i_size < biggest block) condition as error.
Fsck will complain about wrong i_size. Then fsck will fix the error
by changing i_size according to the biggest block. This is bad because
this blocks contain gurbage from previous write attempt. And result in
data corruption.

In order to call vmtruncate() we have to hold host->i_mutex. This is true
for generic_file_aio_write(). In fact occasionally it is also true for all
generic_file_aio_write_nolock() callers except blockdev. But this situation
may change someday. This patch fix only generic_write_aio_write() case.
BTW: update generic_file_direct_write's comment with currently outdated.

Signed-off-by: Dmitri Monakhov <dmonakhov@openvz.org>
---
 mm/filemap.c |   26 ++++++++++++++++++++------
 1 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/mm/filemap.c b/mm/filemap.c
index 3d5a2e7..1e911e5 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2186,8 +2186,10 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
 	/*
 	 * Sync the fs metadata but not the minor inode changes and
 	 * of course not the data as we did direct DMA for the IO.
-	 * i_mutex is held, which protects generic_osync_inode() from
-	 * livelocking.  AIO O_DIRECT ops attempt to sync metadata here.
+	 * i_mutex is held in case of DIO_LOCKING, which protects
+	 * generic_osync_inode() from livelocking. If it is not held, then
+	 * the filesystem must prevent this livelock by its own meaner.
+	 * AIO O_DIRECT ops attempt to sync metadata here.
 	 */
 out:
 	if ((written >= 0 || written == -EIOCBQUEUED) &&
@@ -2529,7 +2531,8 @@ EXPORT_SYMBOL(generic_file_buffered_write);
 
 static ssize_t
 __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos)
+				unsigned long nr_segs, loff_t *ppos,
+				int lock_type)
 {
 	struct file *file = iocb->ki_filp;
 	struct address_space * mapping = file->f_mapping;
@@ -2574,7 +2577,18 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
 
 		written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
 							ppos, count, ocount);
-		if (written < 0 || written == count)
+		if (written < 0) {
+			if (lock_type == DIO_LOCKING) {
+				/*
+				 * direct write may have instantiated a few
+				 * blocks outside i_size. Trim these off again.
+				 */
+				if (pos + count > inode->i_size)
+					vmtruncate(inode, inode->i_size);
+			}
+			goto out;
+		}
+		if (written == count)
 			goto out;
 		/*
 		 * direct-io write to a hole: fall through to buffered I/O
@@ -2638,7 +2652,7 @@ ssize_t generic_file_aio_write_nolock(struct kiocb *iocb,
 	BUG_ON(iocb->ki_pos != pos);
 
 	ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
-			&iocb->ki_pos);
+					&iocb->ki_pos, DIO_OWN_LOCKING);
 
 	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
 		ssize_t err;
@@ -2663,7 +2677,7 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
 	mutex_lock(&inode->i_mutex);
 	ret = __generic_file_aio_write_nolock(iocb, iov, nr_segs,
-			&iocb->ki_pos);
+					&iocb->ki_pos, DIO_LOCKING);
 	mutex_unlock(&inode->i_mutex);
 
 	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
-- 
1.5.4.3

             reply	other threads:[~2008-10-19 14:03 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-19 14:03 Dmitri Monakhov [this message]
2008-10-19 14:03 ` [PATCH 2/2] ocfs2: truncate outstanding block after direct io failure Dmitri Monakhov
2008-10-20 12:47 ` [PATCH 1/2] fs: truncate blocks outside i_size after generic_file_direct_write error Jeff Moyer
2008-10-20 13:43   ` Dmitri Monakhov

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=1224424981-5144-1-git-send-email-dmonakhov@openvz.org \
    --to=dmonakhov@openvz.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.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).