All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
To: Theodore Tso <tytso@mit.edu>
Cc: cmm@us.ibm.com, sandeen@redhat.com, linux-ext4@vger.kernel.org,
	Jan Kara <jack@suse.cz>
Subject: Re: [PATCH -V2 2/2] ext4: truncate the file properly if we fail to copy data from userspace
Date: Mon, 8 Jun 2009 22:13:57 +0530	[thread overview]
Message-ID: <20090608164357.GA23723@skywalker> (raw)
In-Reply-To: <20090608162959.GJ23883@mit.edu>

On Mon, Jun 08, 2009 at 12:29:59PM -0400, Theodore Tso wrote:
> I had also already fixed this up in the patch queue.  This is what is
> currently there.
> 
> 						- Ted
> 
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
> 
> ext4: truncate the file properly if we fail to copy data from userspace
> 
> In generic_perform_write if we fail to copy the user data we don't
> update the inode->i_size.  We should truncate the file in the above
> case so that we don't have blocks allocated outside inode->i_size.  Add
> the inode to orphan list in the same transaction as block allocation
> This ensures that if we crash in between the recovery would do the
> truncate.
> 
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> CC:  Jan Kara <jack@suse.cz>
> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 50ef1a2..8225f21 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -1551,6 +1551,52 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
>  	return ext4_handle_dirty_metadata(handle, NULL, bh);
>  }
> 
> +static int ext4_generic_write_end(struct file *file,
> +				struct address_space *mapping,
> +				loff_t pos, unsigned len, unsigned copied,
> +				struct page *page, void *fsdata)
> +{
> +	int i_size_changed = 0;
> +	struct inode *inode = mapping->host;
> +	handle_t *handle = ext4_journal_current_handle();
> +
> +	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
> +
> +	/*
> +	 * No need to use i_size_read() here, the i_size
> +	 * cannot change under us because we hold i_mutex.
> +	 *
> +	 * But it's important to update i_size while still holding page lock:
> +	 * page writeout could otherwise come in and zero beyond i_size.
> +	 */
> +	if (pos + copied > inode->i_size) {
> +		i_size_write(inode, pos + copied);
> +		i_size_changed = 1;
> +	}
> +
> +	if (pos + copied >  EXT4_I(inode)->i_disksize) {
> +		/* We need to mark inode dirty even if
> +		 * new_i_size is less that inode->i_size
> +		 * bu greater than i_disksize.(hint delalloc)
> +		 */
> +		ext4_update_i_disksize(inode, (pos + copied));
> +		i_size_changed = 1;
> +	}
> +	unlock_page(page);
> +	page_cache_release(page);


You missed a block_unlock_hole_extend here. So you need to either fix
jan's patches or move this patch after jan's patch 


> +
> +	/*
> +	 * Don't mark the inode dirty under page lock. First, it unnecessarily
> +	 * makes the holding time of page lock longer. Second, it forces lock
> +	 * ordering of page lock and transaction start for journaling
> +	 * filesystems.
> +	 */
> +	if (i_size_changed)
> +		ext4_mark_inode_dirty(handle, inode);
> +
> +	return copied;
> +}
> +
>  /*
>   * We need to pick up the new inode size which generic_commit_write gave us
>   * `file' can be NULL - eg, when called from page_symlink().
> @@ -1574,21 +1620,15 @@ static int ext4_ordered_write_end(struct file *file,
>  	ret = ext4_jbd2_file_inode(handle, inode);
> 
>  	if (ret == 0) {
> -		loff_t new_i_size;
> -
> -		new_i_size = pos + copied;
> -		if (new_i_size > EXT4_I(inode)->i_disksize) {
> -			ext4_update_i_disksize(inode, new_i_size);
> -			/* We need to mark inode dirty even if
> -			 * new_i_size is less that inode->i_size
> -			 * bu greater than i_disksize.(hint delalloc)
> -			 */
> -			ext4_mark_inode_dirty(handle, inode);
> -		}
> -
> -		ret2 = generic_write_end(file, mapping, pos, len, copied,
> +		ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
>  							page, fsdata);
>  		copied = ret2;
> +		if (pos + len > inode->i_size)
> +			/* if we have allocated more blocks and copied
> +			 * less. We will have blocks allocated outside
> +			 * inode->i_size. So truncate them
> +			 */
> +			ext4_orphan_add(handle, inode);
>  		if (ret2 < 0)
>  			ret = ret2;
>  	}
> @@ -1596,6 +1636,18 @@ static int ext4_ordered_write_end(struct file *file,
>  	if (!ret)
>  		ret = ret2;
> 
> +	if (pos + len > inode->i_size) {
> +		vmtruncate(inode, inode->i_size);
> +		/* 
> +		 * If vmtruncate failed early the inode might still be
> +		 * on the orphan list; we need to make sure the inode
> +		 * is removed from the orphan list in that case.
> +		 */
> +		if (inode->i_nlink)
> +			ext4_orphan_del(NULL, inode);
> +	}
> +
> +
>  	return ret ? ret : copied;
>  }
> 
> @@ -1607,25 +1659,21 @@ static int ext4_writeback_write_end(struct file *file,
>  	handle_t *handle = ext4_journal_current_handle();
>  	struct inode *inode = mapping->host;
>  	int ret = 0, ret2;
> -	loff_t new_i_size;
> 
>  	trace_mark(ext4_writeback_write_end,
>  		   "dev %s ino %lu pos %llu len %u copied %u",
>  		   inode->i_sb->s_id, inode->i_ino,
>  		   (unsigned long long) pos, len, copied);
> -	new_i_size = pos + copied;
> -	if (new_i_size > EXT4_I(inode)->i_disksize) {
> -		ext4_update_i_disksize(inode, new_i_size);
> -		/* We need to mark inode dirty even if
> -		 * new_i_size is less that inode->i_size
> -		 * bu greater than i_disksize.(hint delalloc)
> -		 */
> -		ext4_mark_inode_dirty(handle, inode);
> -	}
> -
> -	ret2 = generic_write_end(file, mapping, pos, len, copied,
> +	ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
>  							page, fsdata);
>  	copied = ret2;
> +	if (pos + len > inode->i_size)
> +		/* if we have allocated more blocks and copied
> +		 * less. We will have blocks allocated outside
> +		 * inode->i_size. So truncate them
> +		 */
> +		ext4_orphan_add(handle, inode);
> +
>  	if (ret2 < 0)
>  		ret = ret2;
> 
> @@ -1633,6 +1681,17 @@ static int ext4_writeback_write_end(struct file *file,
>  	if (!ret)
>  		ret = ret2;
> 
> +	if (pos + len > inode->i_size) {
> +		vmtruncate(inode, inode->i_size);
> +		/* 
> +		 * If vmtruncate failed early the inode might still be
> +		 * on the orphan list; we need to make sure the inode
> +		 * is removed from the orphan list in that case.
> +		 */
> +		if (inode->i_nlink)
> +			ext4_orphan_del(NULL, inode);
> +	}
> +
>  	return ret ? ret : copied;
>  }
> 
> @@ -1677,10 +1736,27 @@ static int ext4_journalled_write_end(struct file *file,
>  	}
> 
>  	unlock_page(page);
> +	page_cache_release(page);
> +	if (pos + len > inode->i_size)
> +		/* if we have allocated more blocks and copied
> +		 * less. We will have blocks allocated outside
> +		 * inode->i_size. So truncate them
> +		 */
> +		ext4_orphan_add(handle, inode);
> +
>  	ret2 = ext4_journal_stop(handle);
>  	if (!ret)
>  		ret = ret2;
> -	page_cache_release(page);
> +	if (pos + len > inode->i_size) {
> +		vmtruncate(inode, inode->i_size);
> +		/* 
> +		 * If vmtruncate failed early the inode might still be
> +		 * on the orphan list; we need to make sure the inode
> +		 * is removed from the orphan list in that case.
> +		 */
> +		if (inode->i_nlink)
> +			ext4_orphan_del(NULL, inode);
> +	}

Here also need special care with block_unlock_hole_extend. We need to do
a vmtruncate outside block_unlock_hole_extend.


> 
>  	return ret ? ret : copied;
>  }

I think i both the case Jan's patch
allocate-blocks-correctly-with-subpage-blocksize need an update ? Since you have put
the patch before Jan's changes.

-aneesh

  reply	other threads:[~2009-06-08 16:44 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-26 18:21 [PATCH] ext3: Avoid false EIO errors Jan Kara
2009-03-27 18:08 ` Aneesh Kumar K.V
2009-03-27 20:24   ` Jan Kara
2009-03-30  8:25     ` Aneesh Kumar K.V
2009-03-30 10:32       ` Jan Kara
2009-03-30 10:58         ` Aneesh Kumar K.V
2009-03-30 16:05           ` Jan Kara
2009-03-31  4:45             ` Aneesh Kumar K.V
2009-03-31  9:29               ` [PATCH 1/2] [PATCH] ext4: Add inode to the orphan list during block allocation failure Aneesh Kumar K.V
2009-03-31  9:29                 ` [PATCH 2/2] [PATCH] ext4: truncate the file properly if we fail to copy data from userspace Aneesh Kumar K.V
2009-03-31  9:38                   ` Jan Kara
2009-04-05  3:22                   ` Theodore Tso
2009-04-06 10:07                     ` Jan Kara
2009-03-31  9:34                 ` [PATCH 1/2] [PATCH] ext4: Add inode to the orphan list during block allocation failure Jan Kara
2009-04-05  3:11                 ` Theodore Tso
2009-04-06 10:05                   ` Jan Kara
2009-06-05  4:31                     ` Theodore Tso
2009-06-05  6:22                       ` Theodore Tso
2009-06-05  7:24                         ` Theodore Tso
2009-06-05 23:42                           ` Jan Kara
2009-06-05 23:44                       ` Jan Kara
2009-06-08  4:35                         ` [PATCH -V2 1/2] " Aneesh Kumar K.V
2009-06-08  4:35                           ` [PATCH -V2 2/2] ext4: truncate the file properly if we fail to copy data from userspace Aneesh Kumar K.V
2009-06-08 16:29                             ` Theodore Tso
2009-06-08 16:43                               ` Aneesh Kumar K.V [this message]
2009-06-08 19:14                                 ` Theodore Tso
2009-06-08 19:23                                   ` Jan Kara
2009-06-08 20:20                                   ` Aneesh Kumar K.V
2009-06-09 10:12                                     ` Jan Kara
2009-06-08 16:29                           ` [PATCH -V2 1/2] ext4: Add inode to the orphan list during block allocation failure Theodore Tso
2009-03-31  9:46               ` [PATCH] ext3: Avoid false EIO errors (version 4) Jan Kara
2009-04-01  0:06                 ` Andrew Morton
2009-04-01  9:49                   ` Jan Kara
2009-03-30 13:53       ` [PATCH] ext3: Avoid false EIO errors Eric Sandeen
2009-03-30 14:45         ` Aneesh Kumar K.V
2009-03-30 15:12           ` Eric Sandeen

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=20090608164357.GA23723@skywalker \
    --to=aneesh.kumar@linux.vnet.ibm.com \
    --cc=cmm@us.ibm.com \
    --cc=jack@suse.cz \
    --cc=linux-ext4@vger.kernel.org \
    --cc=sandeen@redhat.com \
    --cc=tytso@mit.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.