diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 22cb32de5515..1386149916bb 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -804,6 +804,19 @@ static int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size) return ret; } +/* + * The clusters for a write are allocated before the data is copied. Free the + * ones that a failed or short write has left beyond the end of the file. + */ +static void exfat_write_failed(struct inode *inode) +{ + inode_dio_wait(inode); + filemap_invalidate_lock(inode->i_mapping); + truncate_pagecache(inode, i_size_read(inode)); + exfat_truncate(inode); + filemap_invalidate_unlock(inode->i_mapping); +} + static ssize_t exfat_fallback_buffered_write(struct kiocb *iocb, struct iov_iter *from) { @@ -862,7 +875,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); struct exfat_inode_info *ei = EXFAT_I(inode); - loff_t pos, valid_size; + loff_t pos, valid_size, end; int err; if (unlikely(exfat_forced_shutdown(inode->i_sb))) @@ -881,6 +894,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) } pos = iocb->ki_pos; + end = pos + iov_iter_count(iter); if (pos > i_size_read(inode)) truncate_pagecache(inode, i_size_read(inode)); @@ -909,6 +923,8 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter) ret = iomap_file_buffered_write(iocb, iter, &exfat_write_iomap_ops, NULL, NULL); } + if (ret != -EIOCBQUEUED && end > i_size_read(inode)) + exfat_write_failed(inode); if (ret < 0) goto unlock;