summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuezhang Mo <Yuezhang.Mo@sony.com>2025-03-06 15:02:07 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-10 14:39:26 +0200
commit4a9595eb024b8319957c178be3cdeed613ac0795 (patch)
tree661315c150327f9c18f08bbc785cb00515a54bed
parent6a14075325006dad7fef2f980f60dea8acb097a2 (diff)
exfat: fix missing shutdown check
[ Upstream commit 47e35366bc6fa3cf189a8305bce63992495f3efa ] xfstests generic/730 test failed because after deleting the device that still had dirty data, the file could still be read without returning an error. The reason is the missing shutdown check in ->read_iter. I also noticed that shutdown checks were missing from ->write_iter, ->splice_read, and ->mmap. This commit adds shutdown checks to all of them. Fixes: f761fcdd289d ("exfat: Implement sops->shutdown and ioctl") Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/exfat/file.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 807349d8ea05..841a5b18e3df 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -582,6 +582,9 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
loff_t pos = iocb->ki_pos;
loff_t valid_size;
+ if (unlikely(exfat_forced_shutdown(inode->i_sb)))
+ return -EIO;
+
inode_lock(inode);
valid_size = ei->valid_size;
@@ -635,6 +638,16 @@ unlock:
return ret;
}
+static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct inode *inode = file_inode(iocb->ki_filp);
+
+ if (unlikely(exfat_forced_shutdown(inode->i_sb)))
+ return -EIO;
+
+ return generic_file_read_iter(iocb, iter);
+}
+
static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
{
int err;
@@ -672,14 +685,26 @@ static const struct vm_operations_struct exfat_file_vm_ops = {
static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
{
+ if (unlikely(exfat_forced_shutdown(file_inode(file)->i_sb)))
+ return -EIO;
+
file_accessed(file);
vma->vm_ops = &exfat_file_vm_ops;
return 0;
}
+static ssize_t exfat_splice_read(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len, unsigned int flags)
+{
+ if (unlikely(exfat_forced_shutdown(file_inode(in)->i_sb)))
+ return -EIO;
+
+ return filemap_splice_read(in, ppos, pipe, len, flags);
+}
+
const struct file_operations exfat_file_operations = {
.llseek = generic_file_llseek,
- .read_iter = generic_file_read_iter,
+ .read_iter = exfat_file_read_iter,
.write_iter = exfat_file_write_iter,
.unlocked_ioctl = exfat_ioctl,
#ifdef CONFIG_COMPAT
@@ -687,7 +712,7 @@ const struct file_operations exfat_file_operations = {
#endif
.mmap = exfat_file_mmap,
.fsync = exfat_file_fsync,
- .splice_read = filemap_splice_read,
+ .splice_read = exfat_splice_read,
.splice_write = iter_file_splice_write,
};