[f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-07-15 Thread Jan Kara
Convert ext4 to use mapping->invalidate_lock instead of its private
EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
conversion we fix a long standing race between hole punching and read(2)
/ readahead(2) paths that can lead to stale page cache contents.

CC: 
CC: Ted Tso 
Acked-by: Theodore Ts'o 
Reviewed-by: Darrick J. Wong 
Signed-off-by: Jan Kara 
---
 fs/ext4/ext4.h | 10 --
 fs/ext4/extents.c  | 25 +---
 fs/ext4/file.c | 13 +++--
 fs/ext4/inode.c| 47 +-
 fs/ext4/ioctl.c|  4 ++--
 fs/ext4/super.c| 13 +
 fs/ext4/truncate.h |  8 +---
 7 files changed, 50 insertions(+), 70 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3c51e243450d..7ebaf66b6e31 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1086,15 +1086,6 @@ struct ext4_inode_info {
 * by other means, so we have i_data_sem.
 */
struct rw_semaphore i_data_sem;
-   /*
-* i_mmap_sem is for serializing page faults with truncate / punch hole
-* operations. We have to make sure that new page cannot be faulted in
-* a section of the inode that is being punched. We cannot easily use
-* i_data_sem for this since we need protection for the whole punch
-* operation and i_data_sem ranks below transaction start so we have
-* to occasionally drop it.
-*/
-   struct rw_semaphore i_mmap_sem;
struct inode vfs_inode;
struct jbd2_inode *jinode;
 
@@ -2972,7 +2963,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, int 
nrblocks);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
 loff_t lstart, loff_t lend);
 extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
-extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
 extern void ext4_da_release_space(struct inode *inode, int to_free);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 92ad64b89d9b..c33e0a2cb6c3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4474,6 +4474,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
loff_t len, int mode)
 {
struct inode *inode = file_inode(file);
+   struct address_space *mapping = file->f_mapping;
handle_t *handle = NULL;
unsigned int max_blocks;
loff_t new_size = 0;
@@ -4560,17 +4561,17 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 * Prevent page faults from reinstantiating pages we have
 * released from page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
 
ret = ext4_update_disksize_before_punch(inode, offset, len);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
/* Now release the pages and zero block aligned part of pages */
@@ -4579,7 +4580,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 flags);
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
if (ret)
goto out_mutex;
}
@@ -5221,6 +5222,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
*handle,
 static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 {
struct super_block *sb = inode->i_sb;
+   struct address_space *mapping = inode->i_mapping;
ext4_lblk_t punch_start, punch_stop;
handle_t *handle;
unsigned int credits;
@@ -5274,7 +5276,7 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Prevent page faults from reinstantiating pages we have released from
 * page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret)
@@ -5289,15 +5291,15 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Write tail of the last page before removed range since it will get
 * removed from the page cache below.
 */
-   ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+   ret = 

[f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-07-12 Thread Jan Kara
Convert ext4 to use mapping->invalidate_lock instead of its private
EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
conversion we fix a long standing race between hole punching and read(2)
/ readahead(2) paths that can lead to stale page cache contents.

CC: 
CC: Ted Tso 
Acked-by: Theodore Ts'o 
Reviewed-by: Darrick J. Wong 
Signed-off-by: Jan Kara 
---
 fs/ext4/ext4.h | 10 --
 fs/ext4/extents.c  | 25 +---
 fs/ext4/file.c | 13 +++--
 fs/ext4/inode.c| 47 +-
 fs/ext4/ioctl.c|  4 ++--
 fs/ext4/super.c| 13 +
 fs/ext4/truncate.h |  8 +---
 7 files changed, 50 insertions(+), 70 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3c51e243450d..7ebaf66b6e31 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1086,15 +1086,6 @@ struct ext4_inode_info {
 * by other means, so we have i_data_sem.
 */
struct rw_semaphore i_data_sem;
-   /*
-* i_mmap_sem is for serializing page faults with truncate / punch hole
-* operations. We have to make sure that new page cannot be faulted in
-* a section of the inode that is being punched. We cannot easily use
-* i_data_sem for this since we need protection for the whole punch
-* operation and i_data_sem ranks below transaction start so we have
-* to occasionally drop it.
-*/
-   struct rw_semaphore i_mmap_sem;
struct inode vfs_inode;
struct jbd2_inode *jinode;
 
@@ -2972,7 +2963,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, int 
nrblocks);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
 loff_t lstart, loff_t lend);
 extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
-extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
 extern void ext4_da_release_space(struct inode *inode, int to_free);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 92ad64b89d9b..c33e0a2cb6c3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4474,6 +4474,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
loff_t len, int mode)
 {
struct inode *inode = file_inode(file);
+   struct address_space *mapping = file->f_mapping;
handle_t *handle = NULL;
unsigned int max_blocks;
loff_t new_size = 0;
@@ -4560,17 +4561,17 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 * Prevent page faults from reinstantiating pages we have
 * released from page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
 
ret = ext4_update_disksize_before_punch(inode, offset, len);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
/* Now release the pages and zero block aligned part of pages */
@@ -4579,7 +4580,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 flags);
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
if (ret)
goto out_mutex;
}
@@ -5221,6 +5222,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
*handle,
 static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 {
struct super_block *sb = inode->i_sb;
+   struct address_space *mapping = inode->i_mapping;
ext4_lblk_t punch_start, punch_stop;
handle_t *handle;
unsigned int credits;
@@ -5274,7 +5276,7 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Prevent page faults from reinstantiating pages we have released from
 * page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret)
@@ -5289,15 +5291,15 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Write tail of the last page before removed range since it will get
 * removed from the page cache below.
 */
-   ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+   ret = 

Re: [f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-06-22 Thread Theodore Ts'o
Sorry, forgot to send it out.

Acked-by: Theodore Ts'o 



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


Re: [f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-06-22 Thread Jan Kara
On Thu 17-06-21 09:22:40, Darrick J. Wong wrote:
> On Tue, Jun 15, 2021 at 11:17:55AM +0200, Jan Kara wrote:
> > Convert ext4 to use mapping->invalidate_lock instead of its private
> > EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
> > conversion we fix a long standing race between hole punching and read(2)
> > / readahead(2) paths that can lead to stale page cache contents.
> > 
> > CC: 
> > CC: Ted Tso 
> 
> Hmm, still no ACK from Ted?

On ext4 call he mentioned he's fine with the patches and testing has passed
for him but he has not given an official tag...

> This looks like a pretty straightforward i_mmap_sem conversion, though
> in general I'd like /some/ kind of response from anyone in the ext4
> community who has been writing code more recently than me...
> 
> Reviewed-by: Darrick J. Wong 

Yeah, this was basically search-and-replace. Thanks for review!

Honza


> 
> --D
> 
> > Signed-off-by: Jan Kara 
> > ---
> >  fs/ext4/ext4.h | 10 --
> >  fs/ext4/extents.c  | 25 +---
> >  fs/ext4/file.c | 13 +++--
> >  fs/ext4/inode.c| 47 +-
> >  fs/ext4/ioctl.c|  4 ++--
> >  fs/ext4/super.c| 13 +
> >  fs/ext4/truncate.h |  8 +---
> >  7 files changed, 50 insertions(+), 70 deletions(-)
> > 
> > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> > index 37002663d521..ed64b4b217a1 100644
> > --- a/fs/ext4/ext4.h
> > +++ b/fs/ext4/ext4.h
> > @@ -1077,15 +1077,6 @@ struct ext4_inode_info {
> >  * by other means, so we have i_data_sem.
> >  */
> > struct rw_semaphore i_data_sem;
> > -   /*
> > -* i_mmap_sem is for serializing page faults with truncate / punch hole
> > -* operations. We have to make sure that new page cannot be faulted in
> > -* a section of the inode that is being punched. We cannot easily use
> > -* i_data_sem for this since we need protection for the whole punch
> > -* operation and i_data_sem ranks below transaction start so we have
> > -* to occasionally drop it.
> > -*/
> > -   struct rw_semaphore i_mmap_sem;
> > struct inode vfs_inode;
> > struct jbd2_inode *jinode;
> >  
> > @@ -2962,7 +2953,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, 
> > int nrblocks);
> >  extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
> >  loff_t lstart, loff_t lend);
> >  extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
> > -extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
> >  extern qsize_t *ext4_get_reserved_space(struct inode *inode);
> >  extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
> >  extern void ext4_da_release_space(struct inode *inode, int to_free);
> > diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> > index cbf37b2cf871..db5d38af9ba8 100644
> > --- a/fs/ext4/extents.c
> > +++ b/fs/ext4/extents.c
> > @@ -4470,6 +4470,7 @@ static long ext4_zero_range(struct file *file, loff_t 
> > offset,
> > loff_t len, int mode)
> >  {
> > struct inode *inode = file_inode(file);
> > +   struct address_space *mapping = file->f_mapping;
> > handle_t *handle = NULL;
> > unsigned int max_blocks;
> > loff_t new_size = 0;
> > @@ -4556,17 +4557,17 @@ static long ext4_zero_range(struct file *file, 
> > loff_t offset,
> >  * Prevent page faults from reinstantiating pages we have
> >  * released from page cache.
> >  */
> > -   down_write(_I(inode)->i_mmap_sem);
> > +   filemap_invalidate_lock(mapping);
> >  
> > ret = ext4_break_layouts(inode);
> > if (ret) {
> > -   up_write(_I(inode)->i_mmap_sem);
> > +   filemap_invalidate_unlock(mapping);
> > goto out_mutex;
> > }
> >  
> > ret = ext4_update_disksize_before_punch(inode, offset, len);
> > if (ret) {
> > -   up_write(_I(inode)->i_mmap_sem);
> > +   filemap_invalidate_unlock(mapping);
> > goto out_mutex;
> > }
> > /* Now release the pages and zero block aligned part of pages */
> > @@ -4575,7 +4576,7 @@ static long ext4_zero_range(struct file *file, loff_t 
> > offset,
> >  
> > ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
> >  flags);
> > -   up_write(_I(inode)->i_mmap_sem);
> > +   filemap_invalidate_unlock(mapping);
> > if (ret)
> > goto out_mutex;
> > }
> > @@ -5217,6 +5218,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
> > *handle,
> >  static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t 
> > len)
> >  {
> > struct super_block *sb = inode->i_sb;
> > +   struct address_space *mapping = 

Re: [f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-06-17 Thread Darrick J. Wong
On Tue, Jun 15, 2021 at 11:17:55AM +0200, Jan Kara wrote:
> Convert ext4 to use mapping->invalidate_lock instead of its private
> EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
> conversion we fix a long standing race between hole punching and read(2)
> / readahead(2) paths that can lead to stale page cache contents.
> 
> CC: 
> CC: Ted Tso 

Hmm, still no ACK from Ted?

This looks like a pretty straightforward i_mmap_sem conversion, though
in general I'd like /some/ kind of response from anyone in the ext4
community who has been writing code more recently than me...

Reviewed-by: Darrick J. Wong 

--D

> Signed-off-by: Jan Kara 
> ---
>  fs/ext4/ext4.h | 10 --
>  fs/ext4/extents.c  | 25 +---
>  fs/ext4/file.c | 13 +++--
>  fs/ext4/inode.c| 47 +-
>  fs/ext4/ioctl.c|  4 ++--
>  fs/ext4/super.c| 13 +
>  fs/ext4/truncate.h |  8 +---
>  7 files changed, 50 insertions(+), 70 deletions(-)
> 
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 37002663d521..ed64b4b217a1 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -1077,15 +1077,6 @@ struct ext4_inode_info {
>* by other means, so we have i_data_sem.
>*/
>   struct rw_semaphore i_data_sem;
> - /*
> -  * i_mmap_sem is for serializing page faults with truncate / punch hole
> -  * operations. We have to make sure that new page cannot be faulted in
> -  * a section of the inode that is being punched. We cannot easily use
> -  * i_data_sem for this since we need protection for the whole punch
> -  * operation and i_data_sem ranks below transaction start so we have
> -  * to occasionally drop it.
> -  */
> - struct rw_semaphore i_mmap_sem;
>   struct inode vfs_inode;
>   struct jbd2_inode *jinode;
>  
> @@ -2962,7 +2953,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, int 
> nrblocks);
>  extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
>loff_t lstart, loff_t lend);
>  extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
> -extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
>  extern qsize_t *ext4_get_reserved_space(struct inode *inode);
>  extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
>  extern void ext4_da_release_space(struct inode *inode, int to_free);
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index cbf37b2cf871..db5d38af9ba8 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -4470,6 +4470,7 @@ static long ext4_zero_range(struct file *file, loff_t 
> offset,
>   loff_t len, int mode)
>  {
>   struct inode *inode = file_inode(file);
> + struct address_space *mapping = file->f_mapping;
>   handle_t *handle = NULL;
>   unsigned int max_blocks;
>   loff_t new_size = 0;
> @@ -4556,17 +4557,17 @@ static long ext4_zero_range(struct file *file, loff_t 
> offset,
>* Prevent page faults from reinstantiating pages we have
>* released from page cache.
>*/
> - down_write(_I(inode)->i_mmap_sem);
> + filemap_invalidate_lock(mapping);
>  
>   ret = ext4_break_layouts(inode);
>   if (ret) {
> - up_write(_I(inode)->i_mmap_sem);
> + filemap_invalidate_unlock(mapping);
>   goto out_mutex;
>   }
>  
>   ret = ext4_update_disksize_before_punch(inode, offset, len);
>   if (ret) {
> - up_write(_I(inode)->i_mmap_sem);
> + filemap_invalidate_unlock(mapping);
>   goto out_mutex;
>   }
>   /* Now release the pages and zero block aligned part of pages */
> @@ -4575,7 +4576,7 @@ static long ext4_zero_range(struct file *file, loff_t 
> offset,
>  
>   ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
>flags);
> - up_write(_I(inode)->i_mmap_sem);
> + filemap_invalidate_unlock(mapping);
>   if (ret)
>   goto out_mutex;
>   }
> @@ -5217,6 +5218,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
> *handle,
>  static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t 
> len)
>  {
>   struct super_block *sb = inode->i_sb;
> + struct address_space *mapping = inode->i_mapping;
>   ext4_lblk_t punch_start, punch_stop;
>   handle_t *handle;
>   unsigned int credits;
> @@ -5270,7 +5272,7 @@ static int ext4_collapse_range(struct inode *inode, 
> loff_t offset, loff_t len)
>* Prevent page faults from reinstantiating pages we have released from
>* page cache.
>*/
> - down_write(_I(inode)->i_mmap_sem);
> + filemap_invalidate_lock(mapping);
>  
>   ret = 

[f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-06-15 Thread Jan Kara
Convert ext4 to use mapping->invalidate_lock instead of its private
EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
conversion we fix a long standing race between hole punching and read(2)
/ readahead(2) paths that can lead to stale page cache contents.

CC: 
CC: Ted Tso 
Signed-off-by: Jan Kara 
---
 fs/ext4/ext4.h | 10 --
 fs/ext4/extents.c  | 25 +---
 fs/ext4/file.c | 13 +++--
 fs/ext4/inode.c| 47 +-
 fs/ext4/ioctl.c|  4 ++--
 fs/ext4/super.c| 13 +
 fs/ext4/truncate.h |  8 +---
 7 files changed, 50 insertions(+), 70 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 37002663d521..ed64b4b217a1 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1077,15 +1077,6 @@ struct ext4_inode_info {
 * by other means, so we have i_data_sem.
 */
struct rw_semaphore i_data_sem;
-   /*
-* i_mmap_sem is for serializing page faults with truncate / punch hole
-* operations. We have to make sure that new page cannot be faulted in
-* a section of the inode that is being punched. We cannot easily use
-* i_data_sem for this since we need protection for the whole punch
-* operation and i_data_sem ranks below transaction start so we have
-* to occasionally drop it.
-*/
-   struct rw_semaphore i_mmap_sem;
struct inode vfs_inode;
struct jbd2_inode *jinode;
 
@@ -2962,7 +2953,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, int 
nrblocks);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
 loff_t lstart, loff_t lend);
 extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
-extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
 extern void ext4_da_release_space(struct inode *inode, int to_free);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cbf37b2cf871..db5d38af9ba8 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4470,6 +4470,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
loff_t len, int mode)
 {
struct inode *inode = file_inode(file);
+   struct address_space *mapping = file->f_mapping;
handle_t *handle = NULL;
unsigned int max_blocks;
loff_t new_size = 0;
@@ -4556,17 +4557,17 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 * Prevent page faults from reinstantiating pages we have
 * released from page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
 
ret = ext4_update_disksize_before_punch(inode, offset, len);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
/* Now release the pages and zero block aligned part of pages */
@@ -4575,7 +4576,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 flags);
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
if (ret)
goto out_mutex;
}
@@ -5217,6 +5218,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
*handle,
 static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 {
struct super_block *sb = inode->i_sb;
+   struct address_space *mapping = inode->i_mapping;
ext4_lblk_t punch_start, punch_stop;
handle_t *handle;
unsigned int credits;
@@ -5270,7 +5272,7 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Prevent page faults from reinstantiating pages we have released from
 * page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret)
@@ -5285,15 +5287,15 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Write tail of the last page before removed range since it will get
 * removed from the page cache below.
 */
-   ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+   ret = filemap_write_and_wait_range(mapping, ioffset, offset);
   

[f2fs-dev] [PATCH 05/14] ext4: Convert to use mapping->invalidate_lock

2021-06-07 Thread Jan Kara
Convert ext4 to use mapping->invalidate_lock instead of its private
EXT4_I(inode)->i_mmap_sem. This is mostly search-and-replace. By this
conversion we fix a long standing race between hole punching and read(2)
/ readahead(2) paths that can lead to stale page cache contents.

CC: 
CC: Ted Tso 
Signed-off-by: Jan Kara 
---
 fs/ext4/ext4.h | 10 --
 fs/ext4/extents.c  | 25 +---
 fs/ext4/file.c | 13 +++--
 fs/ext4/inode.c| 47 +-
 fs/ext4/ioctl.c|  4 ++--
 fs/ext4/super.c| 13 +
 fs/ext4/truncate.h |  8 +---
 7 files changed, 50 insertions(+), 70 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 37002663d521..ed64b4b217a1 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1077,15 +1077,6 @@ struct ext4_inode_info {
 * by other means, so we have i_data_sem.
 */
struct rw_semaphore i_data_sem;
-   /*
-* i_mmap_sem is for serializing page faults with truncate / punch hole
-* operations. We have to make sure that new page cannot be faulted in
-* a section of the inode that is being punched. We cannot easily use
-* i_data_sem for this since we need protection for the whole punch
-* operation and i_data_sem ranks below transaction start so we have
-* to occasionally drop it.
-*/
-   struct rw_semaphore i_mmap_sem;
struct inode vfs_inode;
struct jbd2_inode *jinode;
 
@@ -2962,7 +2953,6 @@ extern int ext4_chunk_trans_blocks(struct inode *, int 
nrblocks);
 extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode,
 loff_t lstart, loff_t lend);
 extern vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf);
-extern vm_fault_t ext4_filemap_fault(struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
 extern int ext4_get_projid(struct inode *inode, kprojid_t *projid);
 extern void ext4_da_release_space(struct inode *inode, int to_free);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 77c84d6f1af6..194b8af2b31d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4467,6 +4467,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
loff_t len, int mode)
 {
struct inode *inode = file_inode(file);
+   struct address_space *mapping = file->f_mapping;
handle_t *handle = NULL;
unsigned int max_blocks;
loff_t new_size = 0;
@@ -4553,17 +4554,17 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 * Prevent page faults from reinstantiating pages we have
 * released from page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
 
ret = ext4_update_disksize_before_punch(inode, offset, len);
if (ret) {
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
goto out_mutex;
}
/* Now release the pages and zero block aligned part of pages */
@@ -4572,7 +4573,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
 
ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
 flags);
-   up_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_unlock(mapping);
if (ret)
goto out_mutex;
}
@@ -5214,6 +5215,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t 
*handle,
 static int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 {
struct super_block *sb = inode->i_sb;
+   struct address_space *mapping = inode->i_mapping;
ext4_lblk_t punch_start, punch_stop;
handle_t *handle;
unsigned int credits;
@@ -5267,7 +5269,7 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Prevent page faults from reinstantiating pages we have released from
 * page cache.
 */
-   down_write(_I(inode)->i_mmap_sem);
+   filemap_invalidate_lock(mapping);
 
ret = ext4_break_layouts(inode);
if (ret)
@@ -5282,15 +5284,15 @@ static int ext4_collapse_range(struct inode *inode, 
loff_t offset, loff_t len)
 * Write tail of the last page before removed range since it will get
 * removed from the page cache below.
 */
-   ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, offset);
+   ret = filemap_write_and_wait_range(mapping, ioffset, offset);