From eafb70c1802c469f5d8276a92d41e0b4593e9ae8 Mon Sep 17 00:00:00 2001 From: Bryant Duffy-Ly Date: Wed, 16 Mar 2022 19:04:34 -0400 Subject: [PATCH] Fix truncate for O_DIRECT In the buffered case page tail zeroing happens automatically. In the O_DIRECT case it does not so we need to add it in our setattr path just like EXT2. We want to zero the end of the block that contains i_size during truncate, so we just call block_truncate_page in set_inode_size. --- kmod/src/data.c | 4 ++-- kmod/src/data.h | 2 ++ kmod/src/inode.c | 11 ++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/kmod/src/data.c b/kmod/src/data.c index 7b908bd7c..7d8d6a8a3 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -663,8 +663,8 @@ static int scoutfs_get_block_read(struct inode *inode, sector_t iblock, return ret; } -static int scoutfs_get_block_write(struct inode *inode, sector_t iblock, - struct buffer_head *bh, int create) +int scoutfs_get_block_write(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) { struct scoutfs_inode_info *si = SCOUTFS_I(inode); int ret; diff --git a/kmod/src/data.h b/kmod/src/data.h index c056915e2..2d4a119a9 100644 --- a/kmod/src/data.h +++ b/kmod/src/data.h @@ -49,6 +49,8 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode, int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len); long scoutfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len); +int scoutfs_get_block_write(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create); int scoutfs_data_init_offline_extent(struct inode *inode, u64 size, struct scoutfs_lock *lock); int scoutfs_data_move_blocks(struct inode *from, u64 from_off, diff --git a/kmod/src/inode.c b/kmod/src/inode.c index 9d22f52a7..7d007688b 100644 --- a/kmod/src/inode.c +++ b/kmod/src/inode.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "format.h" #include "super.h" @@ -354,15 +355,22 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock, { struct scoutfs_inode_info *si = SCOUTFS_I(inode); struct super_block *sb = inode->i_sb; + SCOUTFS_DECLARE_PER_TASK_ENTRY(pt_ent); LIST_HEAD(ind_locks); int ret; if (!S_ISREG(inode->i_mode)) return 0; + scoutfs_per_task_add(&si->pt_data_lock, &pt_ent, lock); + ret = block_truncate_page(inode->i_mapping, new_size, scoutfs_get_block_write); + scoutfs_per_task_del(&si->pt_data_lock, &pt_ent); + if (ret) + goto out; + ret = scoutfs_inode_index_lock_hold(inode, &ind_locks, true, false); if (ret) - return ret; + goto out; if (new_size != i_size_read(inode)) scoutfs_inode_inc_data_version(inode); @@ -378,6 +386,7 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock, scoutfs_release_trans(sb); scoutfs_inode_index_unlock(sb, &ind_locks); +out: return ret; }