On Thu, 2024-03-28 at 16:33 +0000, David Howells wrote: > Update i_blocks when i_size is updated when we finish making a write to the > pagecache to reflect the amount of space we think will be consumed. > Umm ok, but why? I get that the i_size and i_blocks would be out of sync until we get back new attrs from the server, but is that a problem? I'm mainly curious as to what's paying attention to the i_blocks during this window. > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > cc: Steve French <sfrench@xxxxxxxxx> > cc: Shyam Prasad N <nspmangalore@xxxxxxxxx> > cc: Rohith Surabattula <rohiths.msft@xxxxxxxxx> > cc: Jeff Layton <jlayton@xxxxxxxxxx> > cc: linux-cifs@xxxxxxxxxxxxxxx > cc: netfs@xxxxxxxxxxxxxxx > cc: linux-fsdevel@xxxxxxxxxxxxxxx > cc: linux-mm@xxxxxxxxx > --- > fs/netfs/buffered_write.c | 45 +++++++++++++++++++++++++++++---------- > 1 file changed, 34 insertions(+), 11 deletions(-) > > diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c > index 9a0d32e4b422..c194655a6dcf 100644 > --- a/fs/netfs/buffered_write.c > +++ b/fs/netfs/buffered_write.c > @@ -130,6 +130,37 @@ static struct folio *netfs_grab_folio_for_write(struct address_space *mapping, > mapping_gfp_mask(mapping)); > } > > +/* > + * Update i_size and estimate the update to i_blocks to reflect the additional > + * data written into the pagecache until we can find out from the server what > + * the values actually are. > + */ > +static void netfs_update_i_size(struct netfs_inode *ctx, struct inode *inode, > + loff_t i_size, loff_t pos, size_t copied) > +{ > + blkcnt_t add; > + size_t gap; > + > + if (ctx->ops->update_i_size) { > + ctx->ops->update_i_size(inode, pos); > + return; > + } > + > + i_size_write(inode, pos); > +#if IS_ENABLED(CONFIG_FSCACHE) > + fscache_update_cookie(ctx->cache, NULL, &pos); > +#endif > + > + gap = SECTOR_SIZE - (i_size & (SECTOR_SIZE - 1)); > + if (copied > gap) { > + add = DIV_ROUND_UP(copied - gap, SECTOR_SIZE); > + > + inode->i_blocks = min_t(blkcnt_t, > + DIV_ROUND_UP(pos, SECTOR_SIZE), > + inode->i_blocks + add); > + } > +} > + > /** > * netfs_perform_write - Copy data into the pagecache. > * @iocb: The operation parameters > @@ -352,18 +383,10 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, > trace_netfs_folio(folio, trace); > > /* Update the inode size if we moved the EOF marker */ > - i_size = i_size_read(inode); > pos += copied; > - if (pos > i_size) { > - if (ctx->ops->update_i_size) { > - ctx->ops->update_i_size(inode, pos); > - } else { > - i_size_write(inode, pos); > -#if IS_ENABLED(CONFIG_FSCACHE) > - fscache_update_cookie(ctx->cache, NULL, &pos); > -#endif > - } > - } > + i_size = i_size_read(inode); > + if (pos > i_size) > + netfs_update_i_size(ctx, inode, i_size, pos, copied); > written += copied; > > if (likely(!wreq)) { > Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>