exfat_setattr() did not call inode_dio_wait() before performing a size
change, leaving a window where a concurrent in-flight DIO write could be
operating on clusters that the truncate is about to free.
Add inode_dio_wait() before the truncate_setsize()/exfat_truncate()
sequence so that any in-flight DIO completes before cluster freeing
begins.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Adds exfat_file_llseek() that implements these whence values via
the iomap layer (iomap_seek_hole() and iomap_seek_data()) using the
existing exfat_read_iomap_ops.
Unlike many other modern filesystems, exFAT does not support sparse files
with unallocated clusters (holes). In exFAT, clusters are always fully
allocated once they are written or preallocated. In addition, exFAT
maintains a separate "Valid Data Length" (valid_size) that is distinct
from the logical file size. This affects how holes are reported during
seeking. In exfat_iomap_begin(), ranges where the offset is greater
than or equal to ei->valid_size are mapped as IOMAP_UNWRITTEN, while ranges
below valid_size are mapped as IOMAP_MAPPED. This mapping behavior is used
by the iomap seek functions to correctly report SEEK_HOLE and SEEK_DATA
positions.
- Ranges with offset >= ei->valid_size are mapped as IOMAP_HOLE.
- Ranges with offset < ei->valid_size are mapped as IOMAP_MAPPED.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add iomap-based direct I/O support to the exfat filesystem. This replaces
the previous exfat_direct_IO() implementation that used
blockdev_direct_IO() with iomap_dio_rw() interface.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add full buffered I/O support using the iomap framework to the exfat
filesystem. This will replaces the old exfat_get_block(),
exfat_write_begin(), exfat_write_end(), and exfat_block_truncate_page()
with their iomap equivalents. Buffered writes now use
iomap_file_buffered_write(), read uses iomap_bio_read_folio() and
iomap_bio_readahead(), and writeback is handled through iomap_writepages().
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Currently exfat_map_cluster() allocates and returns only one cluster
at a time even when more clusters are needed. This causes multiple
FAT walks and repeated allocation calls during large sequential writes
or when using iomap for writes. This change exfat_map_cluster() and
exfat_alloc_cluster() to be able to allocate multiple contiguous
clusters.
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add exfat_file_open() to handle file open operation for exFAT.
This change is a preparation step before introducing iomap-based direct
IO support.
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
The current exFAT driver relies on various macros for unit conversions
between clusters, blocks, sectors, and directory entries. These macros
are structurally unsafe as they lack type enforcement and are prone to
potential integer overflows during bit-shift operations, especially
on 64-bit architectures. Replace all arithmetic macros with static inline
functions to provide strict type checking and explicit casting.
Acked-by: Christoph Hellwig <hch@lst.de>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Report exFAT's case sensitivity behavior via the FS_XFLAG_CASEFOLD
flag. exFAT compares names through the volume's upcase table; in
practice that table folds case, and case is preserved at rest.
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://github.com/exfatprogs/exfatprogs/issues/313
Link: https://patch.msgid.link/20260507-case-sensitivity-v14-4-e62cc8200435@oracle.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
- Implement FALLOC_FL_ALLOCATE_RANGE to add support for preallocating
clusters without zeroing, helping to reduce file fragmentation.
- Add a unified block readahead helper for FAT chain conversion, bitmap
allocation, and directory entry lookups.
- Optimize exfat_chain_cont_cluster() by caching buffer heads to minimize
mark_buffer_dirty() and mirroring overhead during NO_FAT_CHAIN to
FAT_CHAIN conversion.
- Switch to truncate_inode_pages_final() in evict_inode() to prevent
BUG_ON caused by shadow entries during reclaim.
- Fix a 32-bit truncation bug in directory entry calculations by ensuring
proper bitwise coercion.
- Fix sb->s_maxbytes calculation to correctly reflect the maximum possible
volume size for a given cluster size, resolving xfstests generic/213.
- Introduced exfat_cluster_walk() helper to traverse FAT chains by
a specified step, handling both ALLOC_NO_FAT_CHAIN and ALLOC_FAT_CHAIN
modes.
- Introduced exfat_chain_advance() helper to advance an exfat_chain
structure, updating both the current cluster and remaining size.
- Remove dead assignments and fix Smatch warnings.
-----BEGIN PGP SIGNATURE-----
iQJKBAABCgA0FiEE6NzKS6Uv/XAAGHgyZwv7A1FEIQgFAmnbHMUWHGxpbmtpbmpl
b25Aa2VybmVsLm9yZwAKCRBnC/sDUUQhCHXZEACDyb7s63to6V0tdry1D+/Q0hrX
blgUDnD+oGM5J+rFsvmfU+GhUJhe3hIgvLReUpBzrjegdVXCc6wBn+pBzQkjq81A
emJOIjOzyTgwusLuneSMGBZ3oCBJDiREGWqFeoeV1IHZoXvL4oqVr11V4b+8l2ms
Y2FqMljg8AYsgD/Wf3nXPJ1kph/5qpxeKQB4O1RIMEqJp5uoU0byDAtJSjde7oKy
cBRyYeGxcJ0UkQNX3pOfJHe2+Hb2wvCOPWpZ7fw4OfsOYcJMM7IFEKoT2tH67sx9
fo3J/Q74A2Gd0pwyWUwX2xK70uSkoLCR6TxInIgLaKK2IHmgpSHUJa+F5Nz9QFED
PDsBMedt38QXlI4jHNfYTIZuFXgFpIuDJyiphX7tQ72n+JVTiWNnKEF9mRRpRzZ+
2AV6h6YXN0Sd4/EJts+hf1S5admwEKNYpaBXgNTUBD/BbUQcKmvw8JQNk5/tYjU4
9jr4ab1jj1tvWtw9r2Ceu/W71W3l+Ys8gxcJB2DJB1vvo9h23NyHoNwnBMAwmNRv
5ykE7LFFHzwt8QUTMiGlMy5NFpd9cwcVKjzXd+Iogxqa1pDW/lFXrEYxzfvsqPwo
cBNIu2hUf2ESqctAmOWbpCRZwSWMQjh7cUwIHPqNcG2f3JMCzxxVlQC6SUJYr1qv
LoSPVMnQU/ReqFfK6w==
=JG0E
-----END PGP SIGNATURE-----
Merge tag 'exfat-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon:
- Implement FALLOC_FL_ALLOCATE_RANGE to add support for preallocating
clusters without zeroing, helping to reduce file fragmentation
- Add a unified block readahead helper for FAT chain conversion, bitmap
allocation, and directory entry lookups
- Optimize exfat_chain_cont_cluster() by caching buffer heads to
minimize mark_buffer_dirty() and mirroring overhead during
NO_FAT_CHAIN to FAT_CHAIN conversion
- Switch to truncate_inode_pages_final() in evict_inode() to prevent
BUG_ON caused by shadow entries during reclaim
- Fix a 32-bit truncation bug in directory entry calculations by
ensuring proper bitwise coercion
- Fix sb->s_maxbytes calculation to correctly reflect the maximum
possible volume size for a given cluster size, resolving xfstests
generic/213
- Introduced exfat_cluster_walk() helper to traverse FAT chains by a
specified step, handling both ALLOC_NO_FAT_CHAIN and ALLOC_FAT_CHAIN
modes
- Introduced exfat_chain_advance() helper to advance an exfat_chain
structure, updating both the current cluster and remaining size
- Remove dead assignments and fix Smatch warnings
* tag 'exfat-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat:
exfat: use exfat_chain_advance helper
exfat: introduce exfat_chain_advance helper
exfat: remove NULL cache pointer case in exfat_ent_get
exfat: use exfat_cluster_walk helper
exfat: introduce exfat_cluster_walk helper
exfat: fix incorrect directory checksum after rename to shorter name
exfat: fix s_maxbytes
exfat: fix passing zero to ERR_PTR() in exfat_mkdir()
exfat: fix error handling for FAT table operations
exfat: optimize exfat_chain_cont_cluster with cached buffer heads
exfat: drop redundant sec parameter from exfat_mirror_bh
exfat: use readahead helper in exfat_get_dentry
exfat: use readahead helper in exfat_allocate_bitmap
exfat: add block readahead in exfat_chain_cont_cluster
exfat: add fallocate FALLOC_FL_ALLOCATE_RANGE support
exfat: Fix bitwise operation having different size
exfat: Drop dead assignment of num_clusters
exfat: use truncate_inode_pages_final() at evict_inode()
With fallocate support, xfstest unit generic/213 fails with
QA output created by 213
We should get: fallocate: No space left on device
Strangely, xfs_io sometimes says "Success" when something went wrong
-fallocate: No space left on device
+fallocate: File too large
because sb->s_maxbytes is set to the volume size.
To be in line with other non-extent-based filesystems, set to max volume
size possible with the cluster size of the volume.
Signed-off-by: David Timber <dxdt@dev.snart.me>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
The implementation is now really basic so rename generic_file_fsync()
simple_fsync() and __generic_file_fsync() to simple_fsync_noflush().
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260326095354.16340-56-jack@suse.cz
Signed-off-by: Christian Brauner <brauner@kernel.org>
Currently, the Linux (ex)FAT drivers do not employ any cluster
allocation strategy to keep fragmentation at bay. As a result, when
multiple processes are competing for new clusters to expand files in
exfat filesystem on Linux simultaneously, the files end up heavily
fragmented. HDDs are most impacted, but this could also have some
negative impact on various forms of flash memory depending on the
type of underlying technology.
For instance, modern digital cameras produce multiple media files for a
single video stream. If the application does not take the fragmentation
issue into account or the system is under memory pressure, the kernel
end up allocating clusters in said files in a interleaved manner.
Demo script:
for (( i = 0; i < 4; i += 1 ));
do
dd if=/dev/urandom iflag=fullblock bs=1M count=64 of=frag-$i &
done
for (( i = 0; i < 4; i += 1 ));
do
wait
done
filefrag frag-*
Result - Linux kernel native exfat, async mount:
780 extents found
740 extents found
809 extents found
712 extents found
Result - Linux kernel native exfat, sync mount:
1852 extents found
1836 extents found
1846 extents found
1881 extents found
Result - Windows XP:
3 extents found
3 extents found
3 extents found
2 extents found
Windows kernel, on the other hand, regardless of the underlying storage
interface or the medium, seems to space out clusters for each file.
Similar strategy has to be employed by Linux fat filesystems for
efficient utilisation of storage backend.
In the meantime, userspace applications like rsync may
use fallocate to combat this issue.
This patch may introduce a regression-like behaviour to some niche
filesystem-agnostic applications that use fallocate and proceed to
non-sequentially write to the file. Examples:
- libtorrent's use of posix_fallocate() and the first fragment from a
peer is near the end of the file
- "Download accelerators" that do partial content requests(HTTP 206)
in multiple threads writing to the same file
The delay incurred in such use cases is documented in WinAPI. Patches
that add the ioctl equivalents to the WinAPI function
SetFileValidData() and `fsutil file queryvaliddata ...` will follow.
Signed-off-by: David Timber <dxdt@dev.snart.me>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add a blank line after variable declarations in fatent.c and file.c.
This improves readability and makes code style more consistent
across the exfat subsystem.
Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
During mmap write, exfat_page_mkwrite() currently extends
valid_size to the end of the VMA range. For a large mapping,
this can push valid_size far beyond the page that actually
triggered the fault, resulting in unnecessary writes.
valid_size only needs to extend to the end of the page
being written.
Signed-off-by: Yuling Dong <yuling-dong@qq.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add the setlease file_operation to exfat_file_operations and
exfat_dir_operations, pointing to generic_setlease. A future patch
will change the default behavior to reject lease attempts with -EINVAL
when there is no setlease file operation defined. Add generic_setlease
to retain the ability to set leases on this filesystem.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260108-setlease-6-20-v1-7-ea4dec9b67fa@kernel.org
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
xfstests generic/363 was failing due to unzeroed post-EOF page
cache that allowed mmap writes beyond EOF to become visible
after file extension.
For example, in following xfs_io sequence, 0x22 should not be
written to the file but would become visible after the extension:
xfs_io -f -t -c "pwrite -S 0x11 0 8" \
-c "mmap 0 4096" \
-c "mwrite -S 0x22 32 32" \
-c "munmap" \
-c "pwrite -S 0x33 512 32" \
$testfile
This violates the expected behavior where writes beyond EOF via
mmap should not persist after the file is extended. Instead, the
extended region should contain zeros.
Fix this by using truncate_pagecache() to truncate the page cache
after the current EOF when extending the file.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Since the len argument value passed to exfat_ioctl_set_volume_label()
from exfat_nls_to_utf16() is passed 1 too large, an out-of-bounds read
occurs when dereferencing p_cstring in exfat_nls_to_ucs2() later.
And because of the NLS_NAME_OVERLEN macro, another error occurs when
creating a file with a period at the end using utf8 and other iocharsets.
So to avoid this, you should remove the code that uses NLS_NAME_OVERLEN
macro and make the len argument value be the length of the label string,
but with a maximum length of FSLABEL_MAX - 1.
Reported-by: syzbot+98cc76a76de46b3714d4@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=98cc76a76de46b3714d4
Fixes: d01579d590 ("exfat: Add support for FS_IOC_{GET,SET}FSLABEL")
Suggested-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Jeongjun Park <aha310510@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add support for reading / writing to the exfat volume label from the
FS_IOC_GETFSLABEL and FS_IOC_SETFSLABEL ioctls
Co-developed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Ethan Ferguson <ethan.ferguson@zetier.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Test: androbench by default setting, use 64GB sdcard.
the random write speed:
without this patch 3.5MB/s
with this patch 7MB/s
After patch "11a347fb6cef", the random write speed decreased significantly.
the .write_iter() interface had been modified, and check the differences
with generic_file_write_iter(), when calling generic_write_sync() and
exfat_file_write_iter() to call vfs_fsync_range(), the fdatasync flag is
wrong, and make not use the fdatasync mode, and make random write speed
decreased. So use generic_write_sync() instead of vfs_fsync_range().
Fixes: 11a347fb6c ("exfat: change to get file size from DataLength")
Signed-off-by: Zhengxu Zhang <zhengxu.zhang@unisoc.com>
Acked-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaINCgQAKCRCRxhvAZXjc
os+nAP9LFHUwWO6EBzHJJGEVjJvvzsbzqeYrRFamYiMc5ulPJwD+KW4RIgJa/MWO
pcYE40CacaekD8rFWwYUyszpgmv6ewc=
=wCwp
-----END PGP SIGNATURE-----
Merge tag 'vfs-6.17-rc1.mmap_prepare' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull mmap_prepare updates from Christian Brauner:
"Last cycle we introduce f_op->mmap_prepare() in c84bf6dd2b ("mm:
introduce new .mmap_prepare() file callback").
This is preferred to the existing f_op->mmap() hook as it does require
a VMA to be established yet, thus allowing the mmap logic to invoke
this hook far, far earlier, prior to inserting a VMA into the virtual
address space, or performing any other heavy handed operations.
This allows for much simpler unwinding on error, and for there to be a
single attempt at merging a VMA rather than having to possibly
reattempt a merge based on potentially altered VMA state.
Far more importantly, it prevents inappropriate manipulation of
incompletely initialised VMA state, which is something that has been
the cause of bugs and complexity in the past.
The intent is to gradually deprecate f_op->mmap, and in that vein this
series coverts the majority of file systems to using f_op->mmap_prepare.
Prerequisite steps are taken - firstly ensuring all checks for mmap
capabilities use the file_has_valid_mmap_hooks() helper rather than
directly checking for f_op->mmap (which is now not a valid check) and
secondly updating daxdev_mapping_supported() to not require a VMA
parameter to allow ext4 and xfs to be converted.
Commit bb666b7c27 ("mm: add mmap_prepare() compatibility layer for
nested file systems") handles the nasty edge-case of nested file
systems like overlayfs, which introduces a compatibility shim to allow
f_op->mmap_prepare() to be invoked from an f_op->mmap() callback.
This allows for nested filesystems to continue to function correctly
with all file systems regardless of which callback is used. Once we
finally convert all file systems, this shim can be removed.
As a result, ecryptfs, fuse, and overlayfs remain unaltered so they
can nest all other file systems.
We additionally do not update resctl - as this requires an update to
remap_pfn_range() (or an alternative to it) which we defer to a later
series, equally we do not update cramfs which needs a mixed mapping
insertion with the same issue, nor do we update procfs, hugetlbfs,
syfs or kernfs all of which require VMAs for internal state and hooks.
We shall return to all of these later"
* tag 'vfs-6.17-rc1.mmap_prepare' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
doc: update porting, vfs documentation to describe mmap_prepare()
fs: replace mmap hook with .mmap_prepare for simple mappings
fs: convert most other generic_file_*mmap() users to .mmap_prepare()
fs: convert simple use of generic_file_*_mmap() to .mmap_prepare()
mm/filemap: introduce generic_file_*_mmap_prepare() helpers
fs/xfs: transition from deprecated .mmap hook to .mmap_prepare
fs/ext4: transition from deprecated .mmap hook to .mmap_prepare
fs/dax: make it possible to check dev dax support without a VMA
fs: consistently use can_mmap_file() helper
mm/nommu: use file_has_valid_mmap_hooks() helper
mm: rename call_mmap/mmap_prepare to vfs_mmap/mmap_prepare
Change the address_space_operations callbacks write_begin() and
write_end() to take struct kiocb * as the first argument instead of
struct file *.
Update all affected function prototypes, implementations, call sites,
and related documentation across VFS, filesystems, and block layer.
Part of a series refactoring address_space_operations write_begin and
write_end callbacks to use struct kiocb for passing write context and
flags.
Signed-off-by: Taotao Chen <chentaotao@didiglobal.com>
Link: https://lore.kernel.org/20250716093559.217344-4-chentaotao@didiglobal.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
Since commit c84bf6dd2b ("mm: introduce new .mmap_prepare() file
callback"), the f_op->mmap() hook has been deprecated in favour of
f_op->mmap_prepare().
This callback is invoked in the mmap() logic far earlier, so error handling
can be performed more safely without complicated and bug-prone state
unwinding required should an error arise.
This hook also avoids passing a pointer to a not-yet-correctly-established
VMA avoiding any issues with referencing this data structure.
It rather provides a pointer to the new struct vm_area_desc descriptor type
which contains all required state and allows easy setting of required
parameters without any consideration needing to be paid to locking or
reference counts.
Note that nested filesystems like overlayfs are compatible with an
.mmap_prepare() callback since commit bb666b7c27 ("mm: add mmap_prepare()
compatibility layer for nested file systems").
In this patch we apply this change to file systems with relatively simple
mmap() hook logic - exfat, ceph, f2fs, bcachefs, zonefs, btrfs, ocfs2,
orangefs, nilfs2, romfs, ramfs and aio.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Link: https://lore.kernel.org/f528ac4f35b9378931bd800920fee53fc0c5c74d.1750099179.git.lorenzo.stoakes@oracle.com
Acked-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
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: f761fcdd28 ("exfat: Implement sops->shutdown and ioctl")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
When generic_write_checks() returns zero, it means that
iov_iter_count() is zero, and there is no work to do.
Simply return success like all other filesystems do, rather than
proceeding down the write path, which today yields an -EFAULT in
generic_perform_write() via the
(fault_in_iov_iter_readable(i, bytes) == bytes) check when bytes
== 0.
Fixes: 11a347fb6c ("exfat: change to get file size from DataLength")
Reported-by: Noah <kernel-org-10@maxgrass.eu>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Unaligned direct writes are invalid and should return an error
without making any changes, rather than extending ->valid_size
and then returning an error. Therefore, alignment checking is
required before extending ->valid_size.
Fixes: 11a347fb6c ("exfat: change to get file size from DataLength")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Co-developed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
It is not a good way to extend valid_size to the end of the
mmap area by writing zeros in mmap. Because after calling mmap,
no data may be written, or only a small amount of data may be
written to the head of the mmap area.
This commit moves extending valid_size to exfat_page_mkwrite().
In exfat_page_mkwrite() only extend valid_size to the starting
position of new data writing, which reduces unnecessary writing
of zeros.
If the block is not mapped and is marked as new after being
mapped for writing, block_write_begin() will zero the page
cache corresponding to the block, so there is no need to call
zero_user_segment() in exfat_file_zeroed_range(). And after moving
extending valid_size to exfat_page_mkwrite(), the data written by
mmap will be copied to the page cache but the page cache may be
not mapped to the disk. Calling zero_user_segment() will cause
the data written by mmap to be cleared. So this commit removes
calling zero_user_segment() from exfat_file_zeroed_range() and
renames exfat_file_zeroed_range() to exfat_extend_valid_size().
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
We found that when writing a large file through buffer write, if the
disk is inaccessible, exFAT does not return an error normally, which
leads to the writing process not stopping properly.
To easily reproduce this issue, you can follow the steps below:
1. format a device to exFAT and then mount (with a full disk erase)
2. dd if=/dev/zero of=/exfat_mount/test.img bs=1M count=8192
3. eject the device
You may find that the dd process does not stop immediately and may
continue for a long time.
The root cause of this issue is that during buffer write process,
exFAT does not need to access the disk to look up directory entries
or the FAT table (whereas FAT would do) every time data is written.
Instead, exFAT simply marks the buffer as dirty and returns,
delegating the writeback operation to the writeback process.
If the disk cannot be accessed at this time, the error will only be
returned to the writeback process, and the original process will not
receive the error, so it cannot be returned to the user side.
When the disk cannot be accessed normally, an error should be returned
to stop the writing process.
Implement sops->shutdown and ioctl to shut down the file system
when underlying block device is marked dead.
Signed-off-by: Dongliang Cui <dongliang.cui@unisoc.com>
Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
After commit(11a347fb6c exfat: change to get file size from
DataLength), the remaining area or hole had been filled with
zeros before calling exfat_direct_IO(), so there is no need to
fallback to buffered write, and ->i_size_aligned is no longer
needed, drop it.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
->i_size_ondisk is no longer used by exfat_write_begin() after
commit(11a347fb6c exfat: change to get file size from DataLength),
drop it.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Convert all callers from working on a page to working on one page
of a folio (support for working on an entire folio can come later).
Removes a lot of folio->page->folio conversions.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Most callers have a folio, and most implementations operate on a folio,
so remove the conversion from folio->page->folio to fit through this
interface.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Pass the idmapped mount information to the different helper
functions. Adapt the uid/gid checks in exfat_setattr to use the
vfsuid/vfsgid helpers.
Based on the fat implementation in commit 4b78993681
("fat: handle idmapped mounts") by Christian Brauner.
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Commit(f55c096f62 exfat: do not zero the extended part) changed
the timing of synchronizing bitmap and inode in exfat_cont_expand().
The change caused xfstests generic/013 to fail if 'dirsync' or 'sync'
is enabled. So this commit restores the timing.
Fixes: f55c096f62 ("exfat: do not zero the extended part")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Eric Hong found that when using ftruncate to expand an empty file,
exfat_ent_set() will fail if discontinuous clusters are allocated.
The reason is that the empty file does not have a cluster chain,
but exfat_ent_set() attempts to append the newly allocated cluster
to the cluster chain. In addition, exfat_find_last_cluster() only
supports finding the last cluster in a non-empty file.
So this commit adds a check whether the file is empty. If the file
is empty, exfat_find_last_cluster() and exfat_ent_set() are no longer
called as they do not need to be called.
Fixes: f55c096f62 ("exfat: do not zero the extended part")
Reported-by: Eric Hong <erichong@qnap.com>
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Since the read operation beyond the ValidDataLength returns zero,
if we just extend the size of the file, we don't need to zero the
extended part, but only change the DataLength without changing
the ValidDataLength.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
In stream extension directory entry, the ValidDataLength
field describes how far into the data stream user data has
been written, and the DataLength field describes the file
size.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Commit 4c72a36edd ("exfat: convert to new timestamp accessors")
removed attr_copy() from exfat_set_attr().
It causes xfstests generic/221 to fail. In xfstests generic/221,
it tests ctime should be updated even if futimens() update atime
only. But in this case, ctime will not be updated if attr_copy()
is removed.
attr_copy() may also update other attributes, and removing it may
cause other bugs, so this commit restores to call attr_copy() in
exfat_set_attr().
Fixes: 4c72a36edd ("exfat: convert to new timestamp accessors")
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Add GET and SET attributes ioctls to enable attribute modification.
We already do this in FAT and a few userspace utils made for it would
benefit from this also working on exFAT, namely fatattr.
Signed-off-by: Jan Cincera <hcincera@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
generic_fillattr just fills in the entire stat struct indiscriminately
today, copying data from the inode. There is at least one attribute
(STATX_CHANGE_COOKIE) that can have side effects when it is reported,
and we're looking at adding more with the addition of multigrain
timestamps.
Add a request_mask argument to generic_fillattr and have most callers
just pass in the value that is passed to getattr. Have other callers
(e.g. ksmbd) just pass in STATX_BASIC_STATS. Also move the setting of
STATX_CHANGE_COOKIE into generic_fillattr.
Acked-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: "Paulo Alcantara (SUSE)" <pc@manguebit.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Message-Id: <20230807-mgctime-v7-2-d1dec143a704@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
In later patches, we're going to change how the inode's ctime field is
used. Switch to using accessor functions instead of raw accesses of
inode->i_ctime.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Message-Id: <20230705190309.579783-38-jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
- Handle vendor extension and allocation entries as unrecognized benign secondary entries.
- Fix wrong ->i_blocks on devices with non-512 byte sector.
- Add the check to avoid returning -EIO from exfat_readdir() at current position exceeding the directory size.
- Fix a bug that reach the end of the directory stream at a position not aligned with the dentry size.
- Redefine DIR_DELETED as 0xFFFFFFF7, the bad cluster number.
- Two cleanup fixes and fix cluster leakage in error handling.
-----BEGIN PGP SIGNATURE-----
iQJKBAABCgA0FiEE6NzKS6Uv/XAAGHgyZwv7A1FEIQgFAmP/MaMWHGxpbmtpbmpl
b25Aa2VybmVsLm9yZwAKCRBnC/sDUUQhCI8WEADJpjyqM7eZ4FI2+16Ws7C8DaIG
Kk77yXhI9c79+fSLLCcP7vneZYDPAsu4ELuFaHukT6yQ90t87RyWDJOBO/qJhibn
jf89EbaO8U7L5AwU8ETsSsQ46MKi6ZdU5EUzqvcm4Tz5ZBCbMd6o+4uwMJ6VD/e/
uj+gyZi5XSNWxbEq/sj4oGugFjz7hfDapvlseE9gqHpX4lZftwt7qpGlX3WRWiGS
QJpqi4C4QwP6+62LI107fWFAGF6SWmzPYUPhsWZmjeIoKTwFWOD3KPfOxlTBh73M
RI8QxJHF9g5slDHjLDW0NmeXPCDTUxCkMXRFljXBtmsiejIutEpdJS24RbBpxNGX
69W6k/kg+EQRyzMBqLKAqrITZZTUSEDeneHfOLBly1sRIOhwxHa9JZ4Y/9TH9Eaj
/e9KN1jbKzQDovDLaBdVJXb5zU1QC1S+D0ZEMX3BUNSR+lgnfE8jJVoQm3fXCYAo
9GqkRFeItD5vJW4zYf05yIRFS/4TpNytGCetogBbfB2XGq4X66bwOuDi9QvUidwK
MKuEL7Y22cMxe7tLPeVndUF3r1FuAprrOyrzNuqQDINitEEzwq4hNwCYkL2WClmT
5ZfVWW5vMI+hn4XbzRIN20shBAPV1pXzpC4/2kbNQ64xXGAL/97JUjntVfhWgGkr
TDRr0bNuYLIyBiWQaQ==
=AbjH
-----END PGP SIGNATURE-----
Merge tag 'exfat-for-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon:
- Handle vendor extension and allocation entries as unrecognized benign
secondary entries
- Fix wrong ->i_blocks on devices with non-512 byte sector
- Add the check to avoid returning -EIO from exfat_readdir() at current
position exceeding the directory size
- Fix a bug that reach the end of the directory stream at a position
not aligned with the dentry size
- Redefine DIR_DELETED as 0xFFFFFFF7, the bad cluster number
- Two cleanup fixes and fix cluster leakage in error handling
* tag 'exfat-for-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat:
exfat: fix the newly allocated clusters are not freed in error handling
exfat: don't print error log in normal case
exfat: remove unneeded code from exfat_alloc_cluster()
exfat: handle unreconized benign secondary entries
exfat: fix inode->i_blocks for non-512 byte sector size device
exfat: redefine DIR_DELETED as the bad cluster number
exfat: fix reporting fs error when reading dir beyond EOF
exfat: fix unexpected EOF while reading dir
inode->i_blocks is not real number of blocks, but 512 byte ones.
Fixes: 98d917047e ("exfat: add file operations")
Cc: stable@vger.kernel.org # v5.7+
Reported-by: Wang Yugui <wangyugui@e16-tech.com>
Tested-by: Wang Yugui <wangyugui@e16-tech.com>
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Convert to struct mnt_idmap.
Last cycle we merged the necessary infrastructure in
256c8aed2b ("fs: introduce dedicated idmap type for mounts").
This is just the conversion to struct mnt_idmap.
Currently we still pass around the plain namespace that was attached to a
mount. This is in general pretty convenient but it makes it easy to
conflate namespaces that are relevant on the filesystem with namespaces
that are relevent on the mount level. Especially for non-vfs developers
without detailed knowledge in this area this can be a potential source for
bugs.
Once the conversion to struct mnt_idmap is done all helpers down to the
really low-level helpers will take a struct mnt_idmap argument instead of
two namespace arguments. This way it becomes impossible to conflate the two
eliminating the possibility of any bugs. All of the vfs and all filesystems
only operate on struct mnt_idmap.
Acked-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Convert to struct mnt_idmap.
Last cycle we merged the necessary infrastructure in
256c8aed2b ("fs: introduce dedicated idmap type for mounts").
This is just the conversion to struct mnt_idmap.
Currently we still pass around the plain namespace that was attached to a
mount. This is in general pretty convenient but it makes it easy to
conflate namespaces that are relevant on the filesystem with namespaces
that are relevent on the mount level. Especially for non-vfs developers
without detailed knowledge in this area this can be a potential source for
bugs.
Once the conversion to struct mnt_idmap is done all helpers down to the
really low-level helpers will take a struct mnt_idmap argument instead of
two namespace arguments. This way it becomes impossible to conflate the two
eliminating the possibility of any bugs. All of the vfs and all filesystems
only operate on struct mnt_idmap.
Acked-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
The file/directory size is updated into inode by i_size_write()
before __exfat_truncate() is called, so it is redundant to
re-update by i_size_write() in __exfat_truncate().
Code refinement, no functional changes.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
argument 'size' is not used in exfat_truncate(), remove it.
Code refinement, no functional changes.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit moves updating file attributes and timestamps before
calling __exfat_write_inode(), so that all updates of the inode
had been written by __exfat_write_inode(), mark_inode_dirty() is
unneeded.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: Daniel Palmer <daniel.palmer@sony.com>
Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>