summaryrefslogtreecommitdiffstats
path: root/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch
diff options
context:
space:
mode:
Diffstat (limited to 'ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch')
-rw-r--r--ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch110
1 files changed, 0 insertions, 110 deletions
diff --git a/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch b/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch
deleted file mode 100644
index 9ff9e2761..000000000
--- a/ext4-fix-races-of-writeback-with-punch-hole-and-zero.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-From 011278485ecc3cd2a3954b5d4c73101d919bf1fa Mon Sep 17 00:00:00 2001
-From: Jan Kara <jack@suse.com>
-Date: Mon, 7 Dec 2015 14:34:49 -0500
-Subject: [PATCH 4/4] ext4: fix races of writeback with punch hole and zero
- range
-
-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>
-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
----
- 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 348a5ff4a0e2..80f76f092079 100644
---- a/fs/ext4/ext4.h
-+++ b/fs/ext4/ext4.h
-@@ -2858,6 +2858,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 4b105c96df08..3578b25fccfd 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 d1207d03c961..472e608da13d 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.5.5
-