All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kara <jack@suse.com>
To: Ted Tso <tytso@mit.edu>
Cc: linux-ext4@vger.kernel.org,
	Ross Zwisler <ross.zwisler@linux.intel.com>,
	dan.j.williams@intel.com, brian.boylston@hpe.com,
	Jan Kara <jack@suse.com>
Subject: [PATCH 4/9] ext4: Fix races of writeback with punch hole and zero range
Date: Tue, 10 Nov 2015 20:50:54 +0100	[thread overview]
Message-ID: <1447185059-16166-5-git-send-email-jack@suse.com> (raw)
In-Reply-To: <1447185059-16166-1-git-send-email-jack@suse.com>

When doing delayed allocation, update of on-disk inode size is postponed
until IO submission time. However hole punch or zero range fallocate
calls can end up discarding the tail page cache page and thus on-disk
inode size would never be properly updated.

Make sure the on-disk inode size is updated before truncating page
cache.

Signed-off-by: Jan Kara <jack@suse.com>
---
 fs/ext4/ext4.h    |  3 +++
 fs/ext4/extents.c |  5 +++++
 fs/ext4/inode.c   | 35 ++++++++++++++++++++++++++++++++++-
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0e42b9d69f18..d049fc76efcd 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2821,6 +2821,9 @@ static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
 	return changed;
 }
 
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+				      loff_t len);
+
 struct ext4_group_info {
 	unsigned long   bb_state;
 	struct rb_root  bb_free_root;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 3fafdb0a17ed..f76db53eddc4 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4847,6 +4847,11 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 		 * released from page cache.
 		 */
 		down_write(&EXT4_I(inode)->i_mmap_sem);
+		ret = ext4_update_disksize_before_punch(inode, offset, len);
+		if (ret) {
+			up_write(&EXT4_I(inode)->i_mmap_sem);
+			goto out_dio;
+		}
 		/* Now release the pages and zero block aligned part of pages */
 		truncate_pagecache_range(inode, start, end - 1);
 		inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7292d3b0af9c..fcd4ab065e4a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3559,6 +3559,35 @@ int ext4_can_truncate(struct inode *inode)
 }
 
 /*
+ * We have to make sure i_disksize gets properly updated before we truncate
+ * page cache due to hole punching or zero range. Otherwise i_disksize update
+ * can get lost as it may have been postponed to submission of writeback but
+ * that will never happen after we truncate page cache.
+ */
+int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
+				      loff_t len)
+{
+	handle_t *handle;
+	loff_t size = i_size_read(inode);
+
+	WARN_ON(!mutex_is_locked(&inode->i_mutex));
+	if (offset > size || offset + len < size)
+		return 0;
+
+	if (EXT4_I(inode)->i_disksize >= size)
+		return 0;
+
+	handle = ext4_journal_start(inode, EXT4_HT_MISC, 1);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	ext4_update_i_disksize(inode, size);
+	ext4_mark_inode_dirty(handle, inode);
+	ext4_journal_stop(handle);
+
+	return 0;
+}
+
+/*
  * ext4_punch_hole: punches a hole in a file by releaseing the blocks
  * associated with the given offset and length
  *
@@ -3636,9 +3665,13 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 	last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
 
 	/* Now release the pages and zero block aligned part of pages*/
-	if (last_block_offset > first_block_offset)
+	if (last_block_offset > first_block_offset) {
+		ret = ext4_update_disksize_before_punch(inode, offset, length);
+		if (ret)
+			goto out_dio;
 		truncate_pagecache_range(inode, first_block_offset,
 					 last_block_offset);
+	}
 
 	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
 		credits = ext4_writepage_trans_blocks(inode);
-- 
2.1.4


  parent reply	other threads:[~2015-11-10 19:51 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-10 19:50 [PATCH 0/9 v4] ext4: Punch hole and DAX fixes Jan Kara
2015-11-10 19:50 ` [PATCH 1/9] ext4: Fix races between page faults and hole punching Jan Kara
2015-11-10 19:50 ` [PATCH 2/9] ext4: Move unlocked dio protection from ext4_alloc_file_blocks() Jan Kara
2015-11-10 19:50 ` [PATCH 3/9] ext4: Fix races between buffered IO and collapse / insert range Jan Kara
2015-11-18  1:39   ` Elliott, Robert (Persistent Memory)
2015-11-18 15:16     ` Jan Kara
2015-11-10 19:50 ` Jan Kara [this message]
2015-11-10 19:50 ` [PATCH 5/9] ext4: Document lock ordering Jan Kara
2015-11-10 19:50 ` [PATCH 6/9] ext4: Get rid of EXT4_GET_BLOCKS_NO_LOCK flag Jan Kara
2015-11-10 19:50 ` [PATCH 7/9] ext4: Provide ext4_issue_zeroout() Jan Kara
2015-11-10 19:50 ` [PATCH 8/9] ext4: Implement allocation of pre-zeroed blocks Jan Kara
2015-11-10 19:50 ` [PATCH 9/9] ext4: Use pre-zeroed blocks for DAX page faults Jan Kara
2015-11-17 17:41 ` [PATCH 0/9 v4] ext4: Punch hole and DAX fixes Boylston, Brian
2015-11-18 15:13   ` Jan Kara
2015-12-08  1:08 ` Theodore Ts'o
     [not found]   ` <20151209235518.GA31235@linux.intel.com>
2015-12-10 16:26     ` Theodore Ts'o
2015-12-10 17:10       ` Ross Zwisler
  -- strict thread matches above, loose matches on Subject: below --
2015-11-04 16:18 [PATCH 0/9 v3] " Jan Kara
2015-11-04 16:18 ` [PATCH 4/9] ext4: Fix races of writeback with punch hole and zero range Jan Kara
2015-10-22  8:15 [PATCH 0/9 v2] ext4: Punch hole and DAX fixes Jan Kara
2015-10-22  8:15 ` [PATCH 4/9] ext4: Fix races of writeback with punch hole and zero range Jan Kara

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=1447185059-16166-5-git-send-email-jack@suse.com \
    --to=jack@suse.com \
    --cc=brian.boylston@hpe.com \
    --cc=dan.j.williams@intel.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=ross.zwisler@linux.intel.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.