Re: [PATCH] ntfs: file extension before write submission
Hyunchul Lee <[email protected]> Fri, 17 Jul 2026 07:28:07 +0900
| Newsgroups | dev.linux.lists.ntfs,org.kernel.vger.linux-fsdevel |
|---|---|
| Message-ID | <CANFS6bZtvqDd+mGA9B1zJkCUXgHm_CvjkAfU8GP0gBKLS0r05Q@mail.gmail.com> |
2026=EB=85=84 7=EC=9B=94 16=EC=9D=BC (=EB=AA=A9) =EC=98=A4=EC=A0=84 11:47, = Namjae Jeon <[email protected]>=EB=8B=98=EC=9D=B4 =EC=9E=91=EC=84=B1: > > Prepare non-resident file allocation and initialized-size extension in > ->write_iter() before entering the buffered or direct iomap write paths. > > Previously, the iomap write callback extended initialized_size. When a > direct write started beyond initialized_size, > ntfs_extend_initialized_size() used iomap_zero_range() to zero the gap > through the page cache. This created dirty folios after iomap DIO had > invalidated its target cache range. The bsync path then had to > synchronously write back the entire zeroed gap to prevent the post-DIO > invalidation from encountering a dirty boundary folio. > > Move allocation and initialized-size preparation ahead of iomap submissio= n. > For DIO, kiocb_invalidate_pages() now sees any dirty boundary folio creat= ed > by iomap_zero_range(), writes it back when necessary, and invalidates it > before the direct I/O is issued. This removes the explicit synchronous > writeback of the zeroed gap while preserving the required boundary-folio > ordering. > > Keep compressed writes out of the early initialized-size extension so the= ir > existing write path can zero uninitialized data before compression. Move > compressed-file allocation expansion to write_iter as well, eliminating t= he > now-redundant expansion from ntfs_compress_write(). > > Signed-off-by: Namjae Jeon <[email protected]> Looks good to me. Reviewed-by: Hyunchul Lee <[email protected]> > --- > fs/ntfs/compress.c | 10 ---------- > fs/ntfs/file.c | 43 +++++++++++++++++++++++++++++++++++++++++-- > fs/ntfs/inode.c | 6 +----- > fs/ntfs/inode.h | 2 +- > fs/ntfs/iomap.c | 34 +--------------------------------- > 5 files changed, 44 insertions(+), 51 deletions(-) > > diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c > index e866f43ca30b..fe1877b86f49 100644 > --- a/fs/ntfs/compress.c > +++ b/fs/ntfs/compress.c > @@ -1459,16 +1459,6 @@ int ntfs_compress_write(struct ntfs_inode *ni, lof= f_t pos, size_t count, > size_t written =3D 0; > struct address_space *mapping =3D VFS_I(ni)->i_mapping; > > - if (NInoCompressed(ni) && pos + count > ni->allocated_size) { > - int err; > - loff_t end =3D pos + count; > - > - err =3D ntfs_attr_expand(ni, end, > - round_up(end, ni->itype.compressed.block_= size)); > - if (err) > - return err; > - } > - > pages =3D kmalloc_array(pages_per_cb, sizeof(struct page *), GFP_= NOFS); > if (!pages) > return -ENOMEM; > diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c > index 6a7b638e523d..9061f8f77f7e 100644 > --- a/fs/ntfs/file.c > +++ b/fs/ntfs/file.c > @@ -535,6 +535,31 @@ static ssize_t ntfs_dio_write_iter(struct kiocb *ioc= b, struct iov_iter *from) > return ret; > } > > +static int ntfs_expand_for_write(struct ntfs_inode *ni, loff_t end) > +{ > + struct ntfs_volume *vol =3D ni->vol; > + loff_t prealloc_size =3D 0; > + int err; > + > + if (end <=3D ni->data_size) > + return 0; > + > + if (NInoCompressed(ni)) { > + if (end > ni->allocated_size) > + prealloc_size =3D round_up(end, > + ni->itype.compressed.blo= ck_size); > + } else if (end > ni->allocated_size && > + end < ni->allocated_size + vol->preallocated_size) { > + prealloc_size =3D ni->allocated_size + vol->preallocated_= size; > + } > + > + mutex_lock(&ni->mrec_lock); > + err =3D ntfs_attr_expand(ni, end, prealloc_size); > + mutex_unlock(&ni->mrec_lock); > + > + return err; > +} > + > static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter = *from) > { > struct file *file =3D iocb->ki_filp; > @@ -543,7 +568,7 @@ static ssize_t ntfs_file_write_iter(struct kiocb *ioc= b, struct iov_iter *from) > struct ntfs_volume *vol =3D ni->vol; > ssize_t ret; > ssize_t count; > - loff_t pos; > + loff_t pos, end; > int err; > loff_t old_data_size, old_init_size; > > @@ -580,10 +605,24 @@ static ssize_t ntfs_file_write_iter(struct kiocb *i= ocb, struct iov_iter *from) > > pos =3D iocb->ki_pos; > count =3D ret; > + end =3D pos + count; > > old_data_size =3D ni->data_size; > old_init_size =3D ni->initialized_size; > > + if (end > old_data_size) { > + ret =3D ntfs_expand_for_write(ni, end); > + if (ret < 0) > + goto out; > + } > + > + if (NInoNonResident(ni) && !NInoCompressed(ni) && > + end > old_init_size) { > + ret =3D ntfs_extend_initialized_size(vi, pos, end); > + if (ret < 0) > + goto out; > + } > + > if (NInoNonResident(ni) && NInoCompressed(ni)) { > ret =3D ntfs_compress_write(ni, pos, count, from); > if (ret > 0) > @@ -655,7 +694,7 @@ static int ntfs_file_mmap_prepare(struct vm_area_desc= *desc) > from + desc->end - desc->start); > > if (NTFS_I(inode)->initialized_size < to) { > - err =3D ntfs_extend_initialized_size(inode, to, t= o, false); > + err =3D ntfs_extend_initialized_size(inode, to, t= o); > if (err) > return err; > } > diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c > index 7381a18cfadd..50e244aa372e 100644 > --- a/fs/ntfs/inode.c > +++ b/fs/ntfs/inode.c > @@ -2401,7 +2401,7 @@ int ntfs_show_options(struct seq_file *sf, struct d= entry *root) > } > > int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset, > - const loff_t new_size, bool bsync) > + const loff_t new_size) > { > struct ntfs_inode *ni =3D NTFS_I(vi); > loff_t old_init_size; > @@ -2428,10 +2428,6 @@ int ntfs_extend_initialized_size(struct inode *vi,= const loff_t offset, > &ntfs_iomap_folio_ops, NULL); > if (err) > return err; > - if (bsync) > - err =3D filemap_write_and_wait_range(vi->i_mappin= g, > - old_init_size, > - offset - 1); > } > > > diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h > index 9aacd5787ffe..c6d065aaecd5 100644 > --- a/fs/ntfs/inode.h > +++ b/fs/ntfs/inode.h > @@ -352,7 +352,7 @@ static inline void ntfs_commit_inode(struct inode *vi= ) > > int ntfs_inode_sync_filename(struct ntfs_inode *ni); > int ntfs_extend_initialized_size(struct inode *vi, const loff_t offset, > - const loff_t new_size, bool bsync); > + const loff_t new_size); > void ntfs_set_vfs_operations(struct inode *inode, mode_t mode, dev_t dev= ); > struct folio *ntfs_get_locked_folio(struct address_space *mapping, > pgoff_t index, pgoff_t end_index, struct file_ra_state *r= a); > diff --git a/fs/ntfs/iomap.c b/fs/ntfs/iomap.c > index 52eecf5cb256..26a1831a2c18 100644 > --- a/fs/ntfs/iomap.c > +++ b/fs/ntfs/iomap.c > @@ -675,21 +675,7 @@ static int ntfs_write_iomap_begin_non_resident(struc= t inode *inode, loff_t offse > loff_t length, unsigned in= t flags, > struct iomap *iomap, int n= tfs_iomap_flags) > { > - struct ntfs_inode *ni =3D NTFS_I(inode); > - > - if (ntfs_iomap_flags & (NTFS_IOMAP_FLAGS_BEGIN | NTFS_IOMAP_FLAGS= _DIO) && > - offset + length > ni->initialized_size) { > - int ret; > - > - ret =3D ntfs_extend_initialized_size(inode, offset, > - offset + length, > - ntfs_iomap_flags & > - NTFS_IOMAP_FLAGS_DIO); > - if (ret < 0) > - return ret; > - } > - > - mutex_lock(&ni->mrec_lock); > + mutex_lock(&NTFS_I(inode)->mrec_lock); > if (ntfs_iomap_flags & NTFS_IOMAP_FLAGS_BEGIN) > return ntfs_write_simple_iomap_begin_non_resident(inode,= offset, > length= , iomap); > @@ -705,28 +691,10 @@ static int __ntfs_write_iomap_begin(struct inode *i= node, loff_t offset, > struct iomap *iomap, int ntfs_iomap_f= lags) > { > struct ntfs_inode *ni =3D NTFS_I(inode); > - loff_t end =3D offset + length; > > if (NVolShutdown(ni->vol)) > return -EIO; > > - if (ntfs_iomap_flags & (NTFS_IOMAP_FLAGS_BEGIN | NTFS_IOMAP_FLAGS= _DIO) && > - end > ni->data_size) { > - struct ntfs_volume *vol =3D ni->vol; > - int ret; > - > - mutex_lock(&ni->mrec_lock); > - if (end > ni->allocated_size && > - end < ni->allocated_size + vol->preallocated_size) > - ret =3D ntfs_attr_expand(ni, end, > - ni->allocated_size + vol->preallo= cated_size); > - else > - ret =3D ntfs_attr_expand(ni, end, 0); > - mutex_unlock(&ni->mrec_lock); > - if (ret) > - return ret; > - } > - > if (!NInoNonResident(ni)) { > mutex_lock(&ni->mrec_lock); > return ntfs_write_iomap_begin_resident(inode, offset, iom= ap); > -- > 2.25.1 > --=20 Thanks, Hyunchul