BACKPORT: f2fs: prevent writing without fallocate() for pinned files

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage. To make it consistent across
storage devices, we disallow it regardless of storage device types.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

Bug: 379813820
Change-Id: I47b9428d970004284c8de59665ba832f4df4cf13
Signed-off-by: Wu Bo <bo.wu@vivo.com>
(cherry picked from commit 3fdd89b452c2ea5e2195d6e315bef122769584c9)
[Wo Bo: Due to some applications pinning small files via ioctl, the fallocate call fails to allocate space when the system is upgraded. Therefore, it is forbidden to write data to pinned files through the normal write interface.]
This commit is contained in:
Daeho Jeong
2024-04-11 10:54:10 -07:00
committed by Todd Kjos
parent 8a225f954d
commit e09bed3008

View File

@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
bool need_alloc = true;
bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
if (unlikely(IS_IMMUTABLE(inode)))
@@ -111,19 +111,18 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
goto out_sem;
}
set_new_dnode(&dn, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
set_new_dnode(&dn, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(&dn, page->index);
}
#ifdef CONFIG_F2FS_FS_COMPRESSION
if (!need_alloc) {
set_new_dnode(&dn, inode, NULL, NULL, 0);
} else {
err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
f2fs_put_dnode(&dn);
if (f2fs_is_pinned_file(inode) &&
!__is_valid_data_blkaddr(dn.data_blkaddr))
err = -EIO;
}
#endif
if (err) {
unlock_page(page);
goto out_sem;
@@ -4831,6 +4830,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
bool dio;
bool may_need_sync = true;
int preallocated;
const loff_t pos = iocb->ki_pos;
const ssize_t count = iov_iter_count(from);
ssize_t ret;
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
@@ -4852,6 +4853,12 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
inode_lock(inode);
}
if (f2fs_is_pinned_file(inode) &&
!f2fs_overwrite_io(inode, pos, count)) {
ret = -EIO;
goto out_unlock;
}
ret = f2fs_write_checks(iocb, from);
if (ret <= 0)
goto out_unlock;