* linux-next: manual merge of the vfs-brauner tree with the exfat tree
@ 2026-10-13 13:21 Mark Brown
0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2026-10-13 13:21 UTC (permalink / raw)
To: Christian Brauner
Cc: Joanne Koong, Linux Kernel Mailing List, Linux Next Mailing List,
Namjae Jeon
[-- Attachment #1: Type: text/plain, Size: 3244 bytes --]
Hi all,
Today's linux-next merge of the vfs-brauner tree got a conflict in:
fs/exfat/iomap.c
between commit:
80e764ecaf029 ("exfat: map allocated extents for swap activation")
from the exfat tree and commit:
d874f8060847c ("iomap: pass iomap_iter_next_fn directly instead of struct iomap_ops")
from the vfs-brauner tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
diff --cc fs/exfat/iomap.c
index e50ecbfbfbe0f,72cdfe37bcf91..0000000000000
--- a/fs/exfat/iomap.c
+++ b/fs/exfat/iomap.c
@@@ -160,56 -148,11 +160,52 @@@ static int exfat_iomap_begin(struct ino
static int exfat_write_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
{
- return __exfat_iomap_begin(inode, offset, length, flags, iomap, true);
+ struct exfat_inode_info *ei = EXFAT_I(inode);
+ loff_t valid_size = exfat_get_valid_size(ei);
+ loff_t end;
+ int err;
+
+ err = __exfat_iomap_begin(inode, offset, length, flags, iomap, true);
+ if (err || flags & (IOMAP_DIRECT | IOMAP_FAULT) ||
+ iomap->flags & IOMAP_F_NEW)
+ return err;
+
+ end = iomap->offset + iomap->length;
+ if (end >= valid_size ||
+ round_up(end, i_blocksize(inode)) <= valid_size)
+ return 0;
+
+ /*
+ * Zero the invalid bytes from valid_size to the end of the block
+ * to prevent stale data from being exposed through the page cache.
+ */
+ return iomap_truncate_page(inode, valid_size, NULL, &exfat_iomap_ops,
+ NULL, NULL);
}
- static DEFINE_IOMAP_ITER_NEXT(exfat_iomap_next, exfat_iomap_begin);
-
- const struct iomap_ops exfat_iomap_ops = {
- .iomap_next = exfat_iomap_next,
- };
+ DEFINE_IOMAP_ITER_NEXT(exfat_iomap_next, exfat_iomap_begin);
+#ifdef CONFIG_SWAP
+static int exfat_swap_iomap_begin(struct inode *inode, loff_t offset,
+ loff_t length, unsigned int flags, struct iomap *iomap,
+ struct iomap *srcmap)
+{
+ /*
+ * Swap activation needs the physical mappings of preallocated
+ * ranges. Do not report the VDL tail as a hole.
+ */
+ return __exfat_iomap_begin(inode, offset, length,
+ flags & ~IOMAP_REPORT, iomap, false);
+}
+
+static DEFINE_IOMAP_ITER_NEXT(exfat_swap_iomap_next,
+ exfat_swap_iomap_begin);
+
+static const struct iomap_ops exfat_swap_iomap_ops = {
+ .iomap_next = exfat_swap_iomap_next,
+};
+#endif
+
/*
* exfat_write_iomap_end - Update the state after write
*
@@@ -325,10 -267,5 +317,9 @@@ const struct iomap_read_ops exfat_iomap
int exfat_iomap_swap_activate(struct swap_info_struct *sis,
struct file *file, sector_t *span)
{
+#ifdef CONFIG_SWAP
- return iomap_swapfile_activate(sis, file, span,
- &exfat_swap_iomap_ops);
+ return iomap_swapfile_activate(sis, file, span, exfat_iomap_next);
+#else
+ return -EIO;
+#endif
}
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* linux-next: manual merge of the vfs-brauner tree with the exfat tree
@ 2026-10-13 13:21 Mark Brown
0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2026-10-13 13:21 UTC (permalink / raw)
To: Christian Brauner
Cc: Jiale Yao, Joanne Koong, Linux Kernel Mailing List,
Linux Next Mailing List, Namjae Jeon
[-- Attachment #1: Type: text/plain, Size: 5863 bytes --]
Hi all,
Today's linux-next merge of the vfs-brauner tree got a conflict in:
fs/exfat/file.c
between commit:
9965754d857fc ("exfat: drain in-flight DIO before buffered writes")
from the exfat tree and commit:
d874f8060847c ("iomap: pass iomap_iter_next_fn directly instead of struct iomap_ops")
from the vfs-brauner tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
The fixup below is obviously part done, and I had to do subsequent
fixups on top of that due to wider semantic changes. Together with all
the other conflicts today this merge has been an absolute mess, it seems
like we could use better coordination here.
diff --cc fs/exfat/file.c
index f106db945d8dd,188d921aacd13..0000000000000
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@@ -712,42 -654,98 +712,102 @@@ int exfat_file_fsync(struct file *filp
}
/*
- * exfat_zero_new_range - zero [start, end) without overwriting uptodate blocks
+ * exfat_prepare_valid_range - populate and dirty folios covering [start, end)
*
- * Uptodate blocks may contain data written through a shared mapping beyond
- * valid_size.
+ * Populate missing blocks via the read path, which zero-fills data
+ * beyond the current valid_size and skips uptodate blocks.
+ * Mark entire folios dirty so the newly valid range is written back.
+ *
+ * Call before advancing valid_size.
*/
-static int exfat_zero_new_range(struct inode *inode, loff_t start, loff_t end)
+static int exfat_prepare_valid_range(struct inode *inode, loff_t start,
+ loff_t end)
{
struct address_space *mapping = inode->i_mapping;
- unsigned int blocksize = i_blocksize(inode);
- loff_t pos = start;
- int err;
+ loff_t next, pos = start;
+ struct folio *folio;
+ pgoff_t index;
+
+ if (pos >= end)
+ return 0;
while (pos < end) {
- loff_t next = min_t(loff_t,
- round_down(pos, PAGE_SIZE) + PAGE_SIZE, end);
- struct folio *folio;
- loff_t bpos;
+ index = pos >> PAGE_SHIFT;
+ next = min(((loff_t)index + 1) << PAGE_SHIFT, end);
++<<<<<<< HEAD
+ balance_dirty_pages_ratelimited(mapping);
++=======
+ folio = filemap_get_folio(mapping, pos >> PAGE_SHIFT);
+ if (IS_ERR(folio)) {
+ err = iomap_zero_range(inode, pos, next - pos, NULL,
+ exfat_iomap_next, NULL, NULL);
+ if (err < 0)
+ return err;
+ pos = next;
+ continue;
+ }
++>>>>>>> vfs-brauner/vfs.all
- if (folio_test_uptodate(folio)) {
- folio_lock(folio);
- if (folio->mapping == mapping)
- folio_mark_dirty(folio);
- folio_unlock(folio);
- folio_put(folio);
- pos = next;
- continue;
- }
+ folio = read_mapping_folio(mapping, index, NULL);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- /*
- * Zero not-uptodate block runs. iomap_zero_range() requires an
- * unlocked folio, so recheck ->mapping after each call.
- */
folio_lock(folio);
++<<<<<<< HEAD
+ if (folio->mapping == mapping) {
++=======
+ bpos = pos;
+ while (bpos < next) {
+ loff_t rstart, rend;
+
+ if (folio->mapping != mapping) {
+ folio_unlock(folio);
+ err = iomap_zero_range(inode, bpos, next - bpos,
+ NULL, exfat_iomap_next, NULL, NULL);
+ if (err < 0) {
+ folio_put(folio);
+ return err;
+ }
+ folio_lock(folio);
+ break;
+ }
+
+ if (iomap_is_partially_uptodate(folio,
+ offset_in_folio(folio, bpos), blocksize)) {
+ bpos += blocksize;
+ continue;
+ }
+
+ rstart = bpos;
+ rend = min_t(loff_t, bpos + blocksize, next);
+ while (rend < next &&
+ !iomap_is_partially_uptodate(folio,
+ offset_in_folio(folio, rend), blocksize))
+ rend = min_t(loff_t, rend + blocksize, next);
+
+ folio_unlock(folio);
+ err = iomap_zero_range(inode, rstart, rend - rstart,
+ NULL, exfat_iomap_next, NULL, NULL);
+ if (err < 0) {
+ folio_put(folio);
+ return err;
+ }
+ folio_lock(folio);
+ bpos = rend;
+ }
+
+ /*
+ * Dirty only a fully uptodate folio. Dirtying a partial folio could
+ * write uninitialised cache contents over valid on-disk blocks.
+ */
+ if (folio->mapping == mapping && folio_test_uptodate(folio))
++>>>>>>> vfs-brauner/vfs.all
folio_mark_dirty(folio);
+ pos = next;
+ }
folio_unlock(folio);
folio_put(folio);
- pos = next;
}
return 0;
@@@ -813,9 -807,7 +873,9 @@@ static ssize_t exfat_fallback_buffered_
iocb->ki_flags &= ~IOCB_DIRECT;
+ inode_dio_wait(file_inode(iocb->ki_filp));
+
- written = iomap_file_buffered_write(iocb, from, &exfat_write_iomap_ops,
+ written = iomap_file_buffered_write(iocb, from, exfat_write_iomap_next,
NULL, NULL);
if (written < 0)
return written;
@@@ -894,21 -887,13 +954,22 @@@ static ssize_t exfat_file_write_iter(st
}
if (ret < 0)
goto unlock;
+
+ pos = valid_size;
}
- if (iocb->ki_flags & IOCB_DIRECT)
+ if (iocb->ki_flags & IOCB_DIRECT) {
ret = exfat_dio_write_iter(iocb, iter);
- else
+ } else {
+ /*
+ * Prevent concurrent direct I/O and buffered I/O to the same file
+ * range. Wait for in-flight DIO to finish before dirtying pages.
+ */
+ inode_dio_wait(inode);
ret = iomap_file_buffered_write(iocb, iter,
+ &exfat_write_iomap_ops, NULL, NULL);
+ exfat_write_iomap_next, NULL, NULL);
+ }
if (ret < 0)
goto unlock;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* linux-next: manual merge of the vfs-brauner tree with the exfat tree
@ 2026-03-27 17:35 Mark Brown
2026-03-28 1:01 ` Namjae Jeon
0 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2026-03-27 17:35 UTC (permalink / raw)
To: Christian Brauner
Cc: Jan Kara, Linux Kernel Mailing List, Linux Next Mailing List,
Namjae Jeon
[-- Attachment #1: Type: text/plain, Size: 12558 bytes --]
Hi all,
Today's linux-next merge of the vfs-brauner tree got a conflict in:
fs/exfat/file.c
between commit:
9b373eacd6e6c4 ("exfat: add iomap buffered I/O support")
from the exfat tree and commit:
5f36c9ca333360 ("fs: Rename generic_file_fsync() to simple_fsync()")
from the vfs-brauner tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
diff --combined fs/exfat/file.c
index 9a30c32b3a0526,4e8d34a75b6638..00000000000000
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@@ -13,12 -13,9 +13,12 @@@
#include <linux/msdos_fs.h>
#include <linux/writeback.h>
#include <linux/filelock.h>
+#include <linux/falloc.h>
+#include <linux/iomap.h>
#include "exfat_raw.h"
#include "exfat_fs.h"
+#include "iomap.h"
static int exfat_cont_expand(struct inode *inode, loff_t size)
{
@@@ -57,7 -54,7 +57,7 @@@
clu.flags = ei->flags;
ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
- &clu, inode_needs_sync(inode));
+ &clu, inode_needs_sync(inode), false);
if (ret)
return ret;
@@@ -93,45 -90,6 +93,45 @@@ free_clu
return -EIO;
}
+/*
+ * Preallocate space for a file. This implements exfat's fallocate file
+ * operation, which gets called from sys_fallocate system call. User space
+ * requests len bytes at offset. In contrary to fat, we only support
+ * FALLOC_FL_ALLOCATE_RANGE because by leaving the valid data length(VDL)
+ * field, it is unnecessary to zero out the newly allocated clusters.
+ */
+static long exfat_fallocate(struct file *file, int mode,
+ loff_t offset, loff_t len)
+{
+ struct inode *inode = file->f_mapping->host;
+ loff_t newsize = offset + len;
+ int err = 0;
+
+ /* No support for other modes */
+ if (mode != FALLOC_FL_ALLOCATE_RANGE)
+ return -EOPNOTSUPP;
+
+ /* No support for dir */
+ if (!S_ISREG(inode->i_mode))
+ return -EOPNOTSUPP;
+
+ if (unlikely(exfat_forced_shutdown(inode->i_sb)))
+ return -EIO;
+
+ inode_lock(inode);
+
+ if (newsize <= i_size_read(inode))
+ goto error;
+
+ /* This is just an expanding truncate */
+ err = exfat_cont_expand(inode, newsize);
+
+error:
+ inode_unlock(inode);
+
+ return err;
+}
+
static bool exfat_allow_set_time(struct mnt_idmap *idmap,
struct exfat_sb_info *sbi, struct inode *inode)
{
@@@ -337,18 -295,7 +337,18 @@@ int exfat_setattr(struct mnt_idmap *idm
if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size > i_size_read(inode)) {
+ loff_t old_size = i_size_read(inode);
+
error = exfat_cont_expand(inode, attr->ia_size);
+ if (!error && attr->ia_size > old_size &&
+ old_size % PAGE_SIZE != 0) {
+ loff_t len = min_t(loff_t,
+ round_up(old_size, PAGE_SIZE) - old_size,
+ attr->ia_size - old_size);
+ error = iomap_zero_range(inode, old_size, len,
+ NULL, &exfat_read_iomap_ops,
+ &exfat_iomap_folio_ops, NULL);
+ }
if (error || attr->ia_valid == ATTR_SIZE)
return error;
attr->ia_valid &= ~ATTR_SIZE;
@@@ -395,10 -342,7 +395,10 @@@
exfat_truncate_inode_atime(inode);
if (attr->ia_valid & ATTR_SIZE) {
- error = exfat_block_truncate_page(inode, attr->ia_size);
+ inode_dio_wait(inode);
+ error = iomap_truncate_page(inode, attr->ia_size, NULL,
+ &exfat_read_iomap_ops,
+ &exfat_iomap_folio_ops, NULL);
if (error)
goto out;
@@@ -633,14 -577,10 +633,14 @@@ int exfat_file_fsync(struct file *filp
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
return -EIO;
- err = simple_fsync_noflush(filp, start, end, datasync);
+ err = file_write_and_wait_range(filp, start, end);
if (err)
return err;
+ if (!datasync)
+ err = __exfat_write_inode(inode, 1);
+ write_inode_now(inode, !datasync);
+
err = sync_blockdev(inode->i_sb->s_bdev);
if (err)
return err;
@@@ -648,72 -588,44 +648,72 @@@
return blkdev_issue_flush(inode->i_sb->s_bdev);
}
-static int exfat_extend_valid_size(struct inode *inode, loff_t new_valid_size)
+int exfat_extend_valid_size(struct inode *inode, loff_t off, bool bsync)
{
- int err;
- loff_t pos;
struct exfat_inode_info *ei = EXFAT_I(inode);
- struct address_space *mapping = inode->i_mapping;
- const struct address_space_operations *ops = mapping->a_ops;
+ struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
+ loff_t old_valid_size;
+ int ret = 0;
- pos = ei->valid_size;
- while (pos < new_valid_size) {
- u32 len;
- struct folio *folio;
- unsigned long off;
+ mutex_lock(&sbi->s_lock);
+ old_valid_size = ei->valid_size;
+ mutex_unlock(&sbi->s_lock);
- len = PAGE_SIZE - (pos & (PAGE_SIZE - 1));
- if (pos + len > new_valid_size)
- len = new_valid_size - pos;
-
- err = ops->write_begin(NULL, mapping, pos, len, &folio, NULL);
- if (err)
- goto out;
-
- off = offset_in_folio(folio, pos);
- folio_zero_new_buffers(folio, off, off + len);
-
- err = ops->write_end(NULL, mapping, pos, len, len, folio, NULL);
- if (err < 0)
- goto out;
- pos += len;
-
- balance_dirty_pages_ratelimited(mapping);
- cond_resched();
+ if (old_valid_size < off) {
+ ret = iomap_zero_range(inode, old_valid_size,
+ off - old_valid_size, NULL,
+ &exfat_write_iomap_ops, &exfat_iomap_folio_ops,
+ NULL);
+ if (!ret && bsync)
+ ret = filemap_write_and_wait_range(inode->i_mapping,
+ old_valid_size,
+ off - 1);
}
- return 0;
+ return ret;
+}
+static ssize_t exfat_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+ ssize_t ret;
+
+ ret = iomap_dio_rw(iocb, from, &exfat_write_iomap_ops,
+ &exfat_write_dio_ops, 0, NULL, 0);
+ if (ret == -ENOTBLK)
+ ret = 0;
+ else if (ret < 0)
+ goto out;
+
+ if (iov_iter_count(from)) {
+ loff_t offset, end;
+ ssize_t written;
+ int ret2;
+
+ offset = iocb->ki_pos;
+ iocb->ki_flags &= ~IOCB_DIRECT;
+ written = iomap_file_buffered_write(iocb, from,
+ &exfat_write_iomap_ops, &exfat_iomap_folio_ops,
+ NULL);
+ if (written < 0) {
+ ret = written;
+ goto out;
+ }
+
+ ret += written;
+ end = iocb->ki_pos + written - 1;
+ ret2 = filemap_write_and_wait_range(iocb->ki_filp->f_mapping,
+ offset, end);
+ if (ret2) {
+ ret = -EIO;
+ goto out;
+ }
+ if (!ret2)
+ invalidate_mapping_pages(iocb->ki_filp->f_mapping,
+ offset >> PAGE_SHIFT,
+ end >> PAGE_SHIFT);
+ }
out:
- return err;
+ return ret;
}
static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
@@@ -724,7 -636,6 +724,7 @@@
struct exfat_inode_info *ei = EXFAT_I(inode);
loff_t pos = iocb->ki_pos;
loff_t valid_size;
+ int err;
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
return -EIO;
@@@ -740,18 -651,28 +740,18 @@@
if (ret <= 0)
goto unlock;
- if (iocb->ki_flags & IOCB_DIRECT) {
- unsigned long align = pos | iov_iter_alignment(iter);
-
- if (!IS_ALIGNED(align, i_blocksize(inode)) &&
- !IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) {
- ret = -EINVAL;
- goto unlock;
- }
+ err = file_modified(iocb->ki_filp);
+ if (err) {
+ ret = err;
+ goto unlock;
}
- if (pos > valid_size) {
- ret = exfat_extend_valid_size(inode, pos);
- if (ret < 0 && ret != -ENOSPC) {
- exfat_err(inode->i_sb,
- "write: fail to zero from %llu to %llu(%zd)",
- valid_size, pos, ret);
- }
- if (ret < 0)
- goto unlock;
- }
-
- ret = __generic_file_write_iter(iocb, iter);
+ if (iocb->ki_flags & IOCB_DIRECT)
+ ret = exfat_dio_write_iter(iocb, iter);
+ else
+ ret = iomap_file_buffered_write(iocb, iter,
+ &exfat_write_iomap_ops, &exfat_iomap_folio_ops,
+ NULL);
if (ret < 0)
goto unlock;
@@@ -778,52 -699,37 +778,52 @@@ unlock
static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{
struct inode *inode = file_inode(iocb->ki_filp);
+ ssize_t ret;
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
return -EIO;
- return generic_file_read_iter(iocb, iter);
+ inode_lock_shared(inode);
+
+ if (iocb->ki_flags & IOCB_DIRECT) {
+ size_t count = iov_iter_count(iter);
+
+ if ((iocb->ki_pos | count) & (inode->i_sb->s_blocksize - 1)) {
+ ret = -EINVAL;
+ goto inode_unlock;
+ }
+
+ file_accessed(iocb->ki_filp);
+ ret = iomap_dio_rw(iocb, iter, &exfat_read_iomap_ops, NULL, 0,
+ NULL, 0);
+ } else {
+ ret = generic_file_read_iter(iocb, iter);
+ }
+
+inode_unlock:
+ inode_unlock_shared(inode);
+
+ return ret;
}
static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
{
- int err;
struct inode *inode = file_inode(vmf->vma->vm_file);
- struct exfat_inode_info *ei = EXFAT_I(inode);
- loff_t new_valid_size;
+ vm_fault_t ret;
if (!inode_trylock(inode))
return VM_FAULT_RETRY;
- new_valid_size = ((loff_t)vmf->pgoff + 1) << PAGE_SHIFT;
- new_valid_size = min(new_valid_size, i_size_read(inode));
-
- if (ei->valid_size < new_valid_size) {
- err = exfat_extend_valid_size(inode, new_valid_size);
- if (err < 0) {
- inode_unlock(inode);
- return vmf_fs_error(err);
- }
- }
+ sb_start_pagefault(inode->i_sb);
+ file_update_time(vmf->vma->vm_file);
+ filemap_invalidate_lock_shared(inode->i_mapping);
+ ret = iomap_page_mkwrite(vmf, &exfat_mkwrite_iomap_ops, NULL);
+ filemap_invalidate_unlock_shared(inode->i_mapping);
+ sb_end_pagefault(inode->i_sb);
inode_unlock(inode);
- return filemap_page_mkwrite(vmf);
+ return ret;
}
static const struct vm_operations_struct exfat_file_vm_ops = {
@@@ -839,21 -745,6 +839,21 @@@ static int exfat_file_mmap_prepare(stru
if (unlikely(exfat_forced_shutdown(file_inode(desc->file)->i_sb)))
return -EIO;
+ if (vma_desc_test_flags(desc, VMA_WRITE_BIT)) {
+ struct inode *inode = file_inode(file);
+ loff_t from, to;
+ int err;
+
+ from = ((loff_t)desc->pgoff << PAGE_SHIFT);
+ to = min_t(loff_t, i_size_read(inode),
+ from + vma_desc_size(desc));
+ if (EXFAT_I(inode)->valid_size < to) {
+ err = exfat_extend_valid_size(inode, to, false);
+ if (err)
+ return err;
+ }
+ }
+
file_accessed(file);
desc->vm_ops = &exfat_file_vm_ops;
return 0;
@@@ -868,50 -759,8 +868,50 @@@ static ssize_t exfat_splice_read(struc
return filemap_splice_read(in, ppos, pipe, len, flags);
}
+static int exfat_file_open(struct inode *inode, struct file *filp)
+{
+ int err;
+
+ if (unlikely(exfat_forced_shutdown(inode->i_sb)))
+ return -EIO;
+
+ err = generic_file_open(inode, filp);
+ if (err)
+ return err;
+
+ filp->f_mode |= FMODE_CAN_ODIRECT;
+
+ return 0;
+}
+
+static loff_t exfat_file_llseek(struct file *file, loff_t offset, int whence)
+{
+ struct inode *inode = file->f_mapping->host;
+
+ switch (whence) {
+ case SEEK_HOLE:
+ inode_lock_shared(inode);
+ offset = iomap_seek_hole(inode, offset, &exfat_read_iomap_ops);
+ inode_unlock_shared(inode);
+ break;
+ case SEEK_DATA:
+ inode_lock_shared(inode);
+ offset = iomap_seek_data(inode, offset, &exfat_read_iomap_ops);
+ inode_unlock_shared(inode);
+ break;
+ default:
+ return generic_file_llseek_size(file, offset, whence,
+ inode->i_sb->s_maxbytes,
+ i_size_read(inode));
+ }
+ if (offset < 0)
+ return offset;
+ return vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
+}
+
const struct file_operations exfat_file_operations = {
- .llseek = generic_file_llseek,
+ .open = exfat_file_open,
+ .llseek = exfat_file_llseek,
.read_iter = exfat_file_read_iter,
.write_iter = exfat_file_write_iter,
.unlocked_ioctl = exfat_ioctl,
@@@ -922,7 -771,6 +922,7 @@@
.fsync = exfat_file_fsync,
.splice_read = exfat_splice_read,
.splice_write = iter_file_splice_write,
+ .fallocate = exfat_fallocate,
.setlease = generic_setlease,
};
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: linux-next: manual merge of the vfs-brauner tree with the exfat tree
2026-03-27 17:35 Mark Brown
@ 2026-03-28 1:01 ` Namjae Jeon
0 siblings, 0 replies; 8+ messages in thread
From: Namjae Jeon @ 2026-03-28 1:01 UTC (permalink / raw)
To: Mark Brown
Cc: Christian Brauner, Jan Kara, Linux Kernel Mailing List,
Linux Next Mailing List
On Sat, Mar 28, 2026 at 2:35 AM Mark Brown <broonie@kernel.org> wrote:
>
> Hi all,
>
> Today's linux-next merge of the vfs-brauner tree got a conflict in:
>
> fs/exfat/file.c
>
> between commit:
>
> 9b373eacd6e6c4 ("exfat: add iomap buffered I/O support")
>
> from the exfat tree and commit:
>
> 5f36c9ca333360 ("fs: Rename generic_file_fsync() to simple_fsync()")
>
> from the vfs-brauner tree.
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
@@@ -633,14 -577,10 +633,14 @@@ int exfat_file_fsync(struct file *filp
if (unlikely(exfat_forced_shutdown(inode->i_sb)))
return -EIO;
- err = simple_fsync_noflush(filp, start, end, datasync);
+ err = file_write_and_wait_range(filp, start, end);
if (err)
return err;
Looks good to me:)
To avoid merge conflicts, I will wait for Christian to send his PR to
Linus first. I’ll then include this change and submit exfat's PR
afterward.
Thanks!
^ permalink raw reply [flat|nested] 8+ messages in thread
* linux-next: manual merge of the vfs-brauner tree with the exfat tree
@ 2024-08-11 22:10 Stephen Rothwell
2024-08-12 0:54 ` Namjae Jeon
2024-09-16 22:22 ` Stephen Rothwell
0 siblings, 2 replies; 8+ messages in thread
From: Stephen Rothwell @ 2024-08-11 22:10 UTC (permalink / raw)
To: Christian Brauner, Namjae Jeon
Cc: Dongliang Cui, Linux Kernel Mailing List, Linux Next Mailing List,
Matthew Wilcox (Oracle), Yuezhang Mo, Zhiguo Niu
[-- Attachment #1: Type: text/plain, Size: 1959 bytes --]
Hi all,
Today's linux-next merge of the vfs-brauner tree got a conflict in:
fs/exfat/inode.c
between commits:
3e491faa7648 ("exfat: do not fallback to buffered write")
98ad7b9012b5 ("exfat: Implement sops->shutdown and ioctl")
from the exfat tree and commits:
a225800f322a ("fs: Convert aops->write_end to take a folio")
1da86618bdce ("fs: Convert aops->write_begin to take a folio")
from the vfs-brauner tree.
I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging. You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.
--
Cheers,
Stephen Rothwell
diff --cc fs/exfat/inode.c
index 7d43a0942911,05f0e07b01d0..000000000000
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@@ -428,11 -452,7 +428,10 @@@ static int exfat_write_begin(struct fil
{
int ret;
+ if (unlikely(exfat_forced_shutdown(mapping->host->i_sb)))
+ return -EIO;
+
- *pagep = NULL;
- ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
+ ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
if (ret < 0)
exfat_write_failed(mapping, pos+len);
@@@ -448,7 -468,15 +447,7 @@@ static int exfat_write_end(struct file
struct exfat_inode_info *ei = EXFAT_I(inode);
int err;
- err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
+ err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
-
- if (ei->i_size_aligned < i_size_read(inode)) {
- exfat_fs_error(inode->i_sb,
- "invalid size(size(%llu) > aligned(%llu)\n",
- i_size_read(inode), ei->i_size_aligned);
- return -EIO;
- }
-
if (err < len)
exfat_write_failed(mapping, pos+len);
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: linux-next: manual merge of the vfs-brauner tree with the exfat tree
2024-08-11 22:10 Stephen Rothwell
@ 2024-08-12 0:54 ` Namjae Jeon
2024-09-16 22:22 ` Stephen Rothwell
1 sibling, 0 replies; 8+ messages in thread
From: Namjae Jeon @ 2024-08-12 0:54 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Christian Brauner, Dongliang Cui, Linux Kernel Mailing List,
Linux Next Mailing List, Matthew Wilcox (Oracle), Yuezhang Mo,
Zhiguo Niu
2024년 8월 12일 (월) 오전 7:10, Stephen Rothwell <sfr@canb.auug.org.au>님이 작성:
>
> Hi all,
>
> Today's linux-next merge of the vfs-brauner tree got a conflict in:
>
> fs/exfat/inode.c
>
> between commits:
>
> 3e491faa7648 ("exfat: do not fallback to buffered write")
> 98ad7b9012b5 ("exfat: Implement sops->shutdown and ioctl")
>
> from the exfat tree and commits:
>
> a225800f322a ("fs: Convert aops->write_end to take a folio")
> 1da86618bdce ("fs: Convert aops->write_begin to take a folio")
>
> from the vfs-brauner tree.
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
Thanks for your work, Looks good to me:)
I'll send an exfat PR after making sure it doesn't conflict with these patches.
>
> --
> Cheers,
> Stephen Rothwell
>
> diff --cc fs/exfat/inode.c
> index 7d43a0942911,05f0e07b01d0..000000000000
> --- a/fs/exfat/inode.c
> +++ b/fs/exfat/inode.c
> @@@ -428,11 -452,7 +428,10 @@@ static int exfat_write_begin(struct fil
> {
> int ret;
>
> + if (unlikely(exfat_forced_shutdown(mapping->host->i_sb)))
> + return -EIO;
> +
> - *pagep = NULL;
> - ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
> + ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
>
> if (ret < 0)
> exfat_write_failed(mapping, pos+len);
> @@@ -448,7 -468,15 +447,7 @@@ static int exfat_write_end(struct file
> struct exfat_inode_info *ei = EXFAT_I(inode);
> int err;
>
> - err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
> + err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
> -
> - if (ei->i_size_aligned < i_size_read(inode)) {
> - exfat_fs_error(inode->i_sb,
> - "invalid size(size(%llu) > aligned(%llu)\n",
> - i_size_read(inode), ei->i_size_aligned);
> - return -EIO;
> - }
> -
> if (err < len)
> exfat_write_failed(mapping, pos+len);
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: linux-next: manual merge of the vfs-brauner tree with the exfat tree
2024-08-11 22:10 Stephen Rothwell
2024-08-12 0:54 ` Namjae Jeon
@ 2024-09-16 22:22 ` Stephen Rothwell
2024-09-17 6:44 ` Namjae Jeon
1 sibling, 1 reply; 8+ messages in thread
From: Stephen Rothwell @ 2024-09-16 22:22 UTC (permalink / raw)
To: Namjae Jeon
Cc: Christian Brauner, Dongliang Cui, Linux Kernel Mailing List,
Linux Next Mailing List, Matthew Wilcox (Oracle), Yuezhang Mo,
Zhiguo Niu
[-- Attachment #1: Type: text/plain, Size: 2267 bytes --]
Hi all,
On Mon, 12 Aug 2024 08:10:46 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Today's linux-next merge of the vfs-brauner tree got a conflict in:
>
> fs/exfat/inode.c
>
> between commits:
>
> 3e491faa7648 ("exfat: do not fallback to buffered write")
> 98ad7b9012b5 ("exfat: Implement sops->shutdown and ioctl")
>
> from the exfat tree and commits:
>
> a225800f322a ("fs: Convert aops->write_end to take a folio")
> 1da86618bdce ("fs: Convert aops->write_begin to take a folio")
>
> from the vfs-brauner tree.
>
> I fixed it up (see below) and can carry the fix as necessary. This
> is now fixed as far as linux-next is concerned, but any non trivial
> conflicts should be mentioned to your upstream maintainer when your tree
> is submitted for merging. You may also want to consider cooperating
> with the maintainer of the conflicting tree to minimise any particularly
> complex conflicts.
>
> --
> Cheers,
> Stephen Rothwell
>
> diff --cc fs/exfat/inode.c
> index 7d43a0942911,05f0e07b01d0..000000000000
> --- a/fs/exfat/inode.c
> +++ b/fs/exfat/inode.c
> @@@ -428,11 -452,7 +428,10 @@@ static int exfat_write_begin(struct fil
> {
> int ret;
>
> + if (unlikely(exfat_forced_shutdown(mapping->host->i_sb)))
> + return -EIO;
> +
> - *pagep = NULL;
> - ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
> + ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
>
> if (ret < 0)
> exfat_write_failed(mapping, pos+len);
> @@@ -448,7 -468,15 +447,7 @@@ static int exfat_write_end(struct file
> struct exfat_inode_info *ei = EXFAT_I(inode);
> int err;
>
> - err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
> + err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
> -
> - if (ei->i_size_aligned < i_size_read(inode)) {
> - exfat_fs_error(inode->i_sb,
> - "invalid size(size(%llu) > aligned(%llu)\n",
> - i_size_read(inode), ei->i_size_aligned);
> - return -EIO;
> - }
> -
> if (err < len)
> exfat_write_failed(mapping, pos+len);
>
This is now a conflict between the exfat tree and Linus' tree.
--
Cheers,
Stephen Rothwell
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: linux-next: manual merge of the vfs-brauner tree with the exfat tree
2024-09-16 22:22 ` Stephen Rothwell
@ 2024-09-17 6:44 ` Namjae Jeon
0 siblings, 0 replies; 8+ messages in thread
From: Namjae Jeon @ 2024-09-17 6:44 UTC (permalink / raw)
To: Stephen Rothwell
Cc: Christian Brauner, Dongliang Cui, Linux Kernel Mailing List,
Linux Next Mailing List, Matthew Wilcox (Oracle), Yuezhang Mo,
Zhiguo Niu
On Tue, Sep 17, 2024 at 7:22 AM Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> Hi all,
Hi Stephen,
>
> On Mon, 12 Aug 2024 08:10:46 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> >
> > Today's linux-next merge of the vfs-brauner tree got a conflict in:
> >
> > fs/exfat/inode.c
> >
> > between commits:
> >
> > 3e491faa7648 ("exfat: do not fallback to buffered write")
> > 98ad7b9012b5 ("exfat: Implement sops->shutdown and ioctl")
> >
> > from the exfat tree and commits:
> >
> > a225800f322a ("fs: Convert aops->write_end to take a folio")
> > 1da86618bdce ("fs: Convert aops->write_begin to take a folio")
> >
> > from the vfs-brauner tree.
> >
> > I fixed it up (see below) and can carry the fix as necessary. This
> > is now fixed as far as linux-next is concerned, but any non trivial
> > conflicts should be mentioned to your upstream maintainer when your tree
> > is submitted for merging. You may also want to consider cooperating
> > with the maintainer of the conflicting tree to minimise any particularly
> > complex conflicts.
> >
> > --
> > Cheers,
> > Stephen Rothwell
> >
> > diff --cc fs/exfat/inode.c
> > index 7d43a0942911,05f0e07b01d0..000000000000
> > --- a/fs/exfat/inode.c
> > +++ b/fs/exfat/inode.c
> > @@@ -428,11 -452,7 +428,10 @@@ static int exfat_write_begin(struct fil
> > {
> > int ret;
> >
> > + if (unlikely(exfat_forced_shutdown(mapping->host->i_sb)))
> > + return -EIO;
> > +
> > - *pagep = NULL;
> > - ret = block_write_begin(mapping, pos, len, pagep, exfat_get_block);
> > + ret = block_write_begin(mapping, pos, len, foliop, exfat_get_block);
> >
> > if (ret < 0)
> > exfat_write_failed(mapping, pos+len);
> > @@@ -448,7 -468,15 +447,7 @@@ static int exfat_write_end(struct file
> > struct exfat_inode_info *ei = EXFAT_I(inode);
> > int err;
> >
> > - err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
> > + err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
> > -
> > - if (ei->i_size_aligned < i_size_read(inode)) {
> > - exfat_fs_error(inode->i_sb,
> > - "invalid size(size(%llu) > aligned(%llu)\n",
> > - i_size_read(inode), ei->i_size_aligned);
> > - return -EIO;
> > - }
> > -
> > if (err < len)
> > exfat_write_failed(mapping, pos+len);
> >
>
> This is now a conflict between the exfat tree and Linus' tree.
I have updated the exfat tree now. There will be no more conflicts.
Please remove your temporary fixes.
Thank you!
>
> --
> Cheers,
> Stephen Rothwell
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-13 13:21 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 13:21 linux-next: manual merge of the vfs-brauner tree with the exfat tree Mark Brown
-- strict thread matches above, loose matches on Subject: below --
2026-10-13 13:21 Mark Brown
2026-03-27 17:35 Mark Brown
2026-03-28 1:01 ` Namjae Jeon
2024-08-11 22:10 Stephen Rothwell
2024-08-12 0:54 ` Namjae Jeon
2024-09-16 22:22 ` Stephen Rothwell
2024-09-17 6:44 ` Namjae Jeon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.