* [PATCH] fs: Remove obsolete logic in i_size_read/write
@ 2025-07-16 12:53 Alex
2025-07-16 13:12 ` Al Viro
2025-07-17 5:05 ` kernel test robot
0 siblings, 2 replies; 8+ messages in thread
From: Alex @ 2025-07-16 12:53 UTC (permalink / raw)
To: viro, brauner, jack, torvalds, paulmck; +Cc: linux-fsdevel, Alex
The logic is used to protect load/store tearing on 32 bit platforms,
for example, after i_size_read returned, there is no guarantee that
inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
is already implied by smp_load_acquire/smp_store_release.
Signed-off-by: Alex <alex.fcyrx@gmail.com>
---
include/linux/fs.h | 41 -----------------------------------------
1 file changed, 41 deletions(-)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4ec77da65f14..7f743881e20d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -952,39 +952,10 @@ void filemap_invalidate_lock_two(struct address_space *mapping1,
void filemap_invalidate_unlock_two(struct address_space *mapping1,
struct address_space *mapping2);
-
-/*
- * NOTE: in a 32bit arch with a preemptable kernel and
- * an UP compile the i_size_read/write must be atomic
- * with respect to the local cpu (unlike with preempt disabled),
- * but they don't need to be atomic with respect to other cpus like in
- * true SMP (so they need either to either locally disable irq around
- * the read or for example on x86 they can be still implemented as a
- * cmpxchg8b without the need of the lock prefix). For SMP compiles
- * and 64bit archs it makes no difference if preempt is enabled or not.
- */
static inline loff_t i_size_read(const struct inode *inode)
{
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
- loff_t i_size;
- unsigned int seq;
-
- do {
- seq = read_seqcount_begin(&inode->i_size_seqcount);
- i_size = inode->i_size;
- } while (read_seqcount_retry(&inode->i_size_seqcount, seq));
- return i_size;
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
- loff_t i_size;
-
- preempt_disable();
- i_size = inode->i_size;
- preempt_enable();
- return i_size;
-#else
/* Pairs with smp_store_release() in i_size_write() */
return smp_load_acquire(&inode->i_size);
-#endif
}
/*
@@ -994,24 +965,12 @@ static inline loff_t i_size_read(const struct inode *inode)
*/
static inline void i_size_write(struct inode *inode, loff_t i_size)
{
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
- preempt_disable();
- write_seqcount_begin(&inode->i_size_seqcount);
- inode->i_size = i_size;
- write_seqcount_end(&inode->i_size_seqcount);
- preempt_enable();
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
- preempt_disable();
- inode->i_size = i_size;
- preempt_enable();
-#else
/*
* Pairs with smp_load_acquire() in i_size_read() to ensure
* changes related to inode size (such as page contents) are
* visible before we see the changed inode size.
*/
smp_store_release(&inode->i_size, i_size);
-#endif
}
static inline unsigned iminor(const struct inode *inode)
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 12:53 [PATCH] fs: Remove obsolete logic in i_size_read/write Alex
@ 2025-07-16 13:12 ` Al Viro
2025-07-16 13:28 ` Alex
2025-07-17 5:05 ` kernel test robot
1 sibling, 1 reply; 8+ messages in thread
From: Al Viro @ 2025-07-16 13:12 UTC (permalink / raw)
To: Alex; +Cc: brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> The logic is used to protect load/store tearing on 32 bit platforms,
> for example, after i_size_read returned, there is no guarantee that
> inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> is already implied by smp_load_acquire/smp_store_release.
Sorry, what? The problem is not a _later_ change, it's getting the
upper and lower 32bit halves from different values.
Before: position is 0xffffffff
After: position is 0x100000000
The value that might be returned by your variant: 0x1ffffffff.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 13:12 ` Al Viro
@ 2025-07-16 13:28 ` Alex
2025-07-16 13:41 ` Matthew Wilcox
0 siblings, 1 reply; 8+ messages in thread
From: Alex @ 2025-07-16 13:28 UTC (permalink / raw)
To: Al Viro; +Cc: brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 9:12 PM Al Viro <viro@zeniv.linux.org.uk> wrote:
>
> On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> > The logic is used to protect load/store tearing on 32 bit platforms,
> > for example, after i_size_read returned, there is no guarantee that
> > inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> > is already implied by smp_load_acquire/smp_store_release.
>
> Sorry, what? The problem is not a _later_ change, it's getting the
> upper and lower 32bit halves from different values.
>
> Before: position is 0xffffffff
> After: position is 0x100000000
> The value that might be returned by your variant: 0x1ffffffff.
I mean the sequence lock here is used to only avoid load/store tearing,
smp_load_acquire/smp_store_release already protects that.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 13:28 ` Alex
@ 2025-07-16 13:41 ` Matthew Wilcox
2025-07-16 13:44 ` Alex
0 siblings, 1 reply; 8+ messages in thread
From: Matthew Wilcox @ 2025-07-16 13:41 UTC (permalink / raw)
To: Alex; +Cc: Al Viro, brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 09:28:29PM +0800, Alex wrote:
> On Wed, Jul 16, 2025 at 9:12 PM Al Viro <viro@zeniv.linux.org.uk> wrote:
> >
> > On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> > > The logic is used to protect load/store tearing on 32 bit platforms,
> > > for example, after i_size_read returned, there is no guarantee that
> > > inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> > > is already implied by smp_load_acquire/smp_store_release.
> >
> > Sorry, what? The problem is not a _later_ change, it's getting the
> > upper and lower 32bit halves from different values.
> >
> > Before: position is 0xffffffff
> > After: position is 0x100000000
> > The value that might be returned by your variant: 0x1ffffffff.
>
> I mean the sequence lock here is used to only avoid load/store tearing,
> smp_load_acquire/smp_store_release already protects that.
Why do you think that? You're wrong, but it'd be useful to understand
what misled you into thinking that.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 13:41 ` Matthew Wilcox
@ 2025-07-16 13:44 ` Alex
2025-07-16 13:57 ` Matthew Wilcox
0 siblings, 1 reply; 8+ messages in thread
From: Alex @ 2025-07-16 13:44 UTC (permalink / raw)
To: Matthew Wilcox; +Cc: Al Viro, brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 9:41 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Wed, Jul 16, 2025 at 09:28:29PM +0800, Alex wrote:
> > On Wed, Jul 16, 2025 at 9:12 PM Al Viro <viro@zeniv.linux.org.uk> wrote:
> > >
> > > On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> > > > The logic is used to protect load/store tearing on 32 bit platforms,
> > > > for example, after i_size_read returned, there is no guarantee that
> > > > inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> > > > is already implied by smp_load_acquire/smp_store_release.
> > >
> > > Sorry, what? The problem is not a _later_ change, it's getting the
> > > upper and lower 32bit halves from different values.
> > >
> > > Before: position is 0xffffffff
> > > After: position is 0x100000000
> > > The value that might be returned by your variant: 0x1ffffffff.
> >
> > I mean the sequence lock here is used to only avoid load/store tearing,
> > smp_load_acquire/smp_store_release already protects that.
>
> Why do you think that? You're wrong, but it'd be useful to understand
> what misled you into thinking that.
smp_load_acquire/smp_store_release implies READ_ONCE/WRITE_ONCE,
and READ_ONCE/WRITE_ONCE avoid load/store tearing.
What am I missing here?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 13:44 ` Alex
@ 2025-07-16 13:57 ` Matthew Wilcox
2025-07-16 14:38 ` Alex
0 siblings, 1 reply; 8+ messages in thread
From: Matthew Wilcox @ 2025-07-16 13:57 UTC (permalink / raw)
To: Alex; +Cc: Al Viro, brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 09:44:31PM +0800, Alex wrote:
> On Wed, Jul 16, 2025 at 9:41 PM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Wed, Jul 16, 2025 at 09:28:29PM +0800, Alex wrote:
> > > On Wed, Jul 16, 2025 at 9:12 PM Al Viro <viro@zeniv.linux.org.uk> wrote:
> > > >
> > > > On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> > > > > The logic is used to protect load/store tearing on 32 bit platforms,
> > > > > for example, after i_size_read returned, there is no guarantee that
> > > > > inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> > > > > is already implied by smp_load_acquire/smp_store_release.
> > > >
> > > > Sorry, what? The problem is not a _later_ change, it's getting the
> > > > upper and lower 32bit halves from different values.
> > > >
> > > > Before: position is 0xffffffff
> > > > After: position is 0x100000000
> > > > The value that might be returned by your variant: 0x1ffffffff.
> > >
> > > I mean the sequence lock here is used to only avoid load/store tearing,
> > > smp_load_acquire/smp_store_release already protects that.
> >
> > Why do you think that? You're wrong, but it'd be useful to understand
> > what misled you into thinking that.
>
> smp_load_acquire/smp_store_release implies READ_ONCE/WRITE_ONCE,
> and READ_ONCE/WRITE_ONCE avoid load/store tearing.
>
> What am I missing here?
They only avoid tearing for sizes <= word size. If you have a 32-bit
CPU, they cannot avoid tearing for 64-bit loads/stores.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 13:57 ` Matthew Wilcox
@ 2025-07-16 14:38 ` Alex
0 siblings, 0 replies; 8+ messages in thread
From: Alex @ 2025-07-16 14:38 UTC (permalink / raw)
To: Matthew Wilcox; +Cc: Al Viro, brauner, jack, torvalds, paulmck, linux-fsdevel
On Wed, Jul 16, 2025 at 9:57 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Wed, Jul 16, 2025 at 09:44:31PM +0800, Alex wrote:
> > On Wed, Jul 16, 2025 at 9:41 PM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > On Wed, Jul 16, 2025 at 09:28:29PM +0800, Alex wrote:
> > > > On Wed, Jul 16, 2025 at 9:12 PM Al Viro <viro@zeniv.linux.org.uk> wrote:
> > > > >
> > > > > On Wed, Jul 16, 2025 at 08:53:04PM +0800, Alex wrote:
> > > > > > The logic is used to protect load/store tearing on 32 bit platforms,
> > > > > > for example, after i_size_read returned, there is no guarantee that
> > > > > > inode->size won't be changed. Therefore, READ/WRITE_ONCE suffice, which
> > > > > > is already implied by smp_load_acquire/smp_store_release.
> > > > >
> > > > > Sorry, what? The problem is not a _later_ change, it's getting the
> > > > > upper and lower 32bit halves from different values.
> > > > >
> > > > > Before: position is 0xffffffff
> > > > > After: position is 0x100000000
> > > > > The value that might be returned by your variant: 0x1ffffffff.
> > > >
> > > > I mean the sequence lock here is used to only avoid load/store tearing,
> > > > smp_load_acquire/smp_store_release already protects that.
> > >
> > > Why do you think that? You're wrong, but it'd be useful to understand
> > > what misled you into thinking that.
> >
> > smp_load_acquire/smp_store_release implies READ_ONCE/WRITE_ONCE,
> > and READ_ONCE/WRITE_ONCE avoid load/store tearing.
> >
> > What am I missing here?
>
> They only avoid tearing for sizes <= word size. If you have a 32-bit
> CPU, they cannot avoid tearing for 64-bit loads/stores.
You’re right, I got that wrong.
Thanks for the clarification!
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] fs: Remove obsolete logic in i_size_read/write
2025-07-16 12:53 [PATCH] fs: Remove obsolete logic in i_size_read/write Alex
2025-07-16 13:12 ` Al Viro
@ 2025-07-17 5:05 ` kernel test robot
1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-07-17 5:05 UTC (permalink / raw)
To: Alex, viro, brauner, jack, torvalds, paulmck
Cc: oe-kbuild-all, linux-fsdevel, Alex
Hi Alex,
kernel test robot noticed the following build errors:
[auto build test ERROR on brauner-vfs/vfs.all]
[also build test ERROR on linus/master v6.16-rc6 next-20250716]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Alex/fs-Remove-obsolete-logic-in-i_size_read-write/20250716-205449
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/20250716125304.1189790-1-alex.fcyrx%40gmail.com
patch subject: [PATCH] fs: Remove obsolete logic in i_size_read/write
config: i386-buildonly-randconfig-001-20250717 (https://download.01.org/0day-ci/archive/20250717/202507171216.eCtc7zAl-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250717/202507171216.eCtc7zAl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507171216.eCtc7zAl-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from <command-line>:
In function 'i_size_read',
inlined from 'do_shmat' at ipc/shm.c:1614:9:
>> include/linux/compiler_types.h:568:45: error: call to '__compiletime_assert_451' declared with attribute error: Need native word sized stores/loads for atomicity.
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
include/linux/compiler_types.h:549:25: note: in definition of macro '__compiletime_assert'
549 | prefix ## suffix(); \
| ^~~~~~
include/linux/compiler_types.h:568:9: note: in expansion of macro '_compiletime_assert'
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:571:9: note: in expansion of macro 'compiletime_assert'
571 | compiletime_assert(__native_word(t), \
| ^~~~~~~~~~~~~~~~~~
arch/x86/include/asm/barrier.h:69:9: note: in expansion of macro 'compiletime_assert_atomic_type'
69 | compiletime_assert_atomic_type(*p); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/barrier.h:176:29: note: in expansion of macro '__smp_load_acquire'
176 | #define smp_load_acquire(p) __smp_load_acquire(p)
| ^~~~~~~~~~~~~~~~~~
include/linux/fs.h:960:16: note: in expansion of macro 'smp_load_acquire'
960 | return smp_load_acquire(&inode->i_size);
| ^~~~~~~~~~~~~~~~
In function 'i_size_read',
inlined from 'ksys_shmdt' at ipc/shm.c:1783:11:
>> include/linux/compiler_types.h:568:45: error: call to '__compiletime_assert_451' declared with attribute error: Need native word sized stores/loads for atomicity.
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
include/linux/compiler_types.h:549:25: note: in definition of macro '__compiletime_assert'
549 | prefix ## suffix(); \
| ^~~~~~
include/linux/compiler_types.h:568:9: note: in expansion of macro '_compiletime_assert'
568 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:571:9: note: in expansion of macro 'compiletime_assert'
571 | compiletime_assert(__native_word(t), \
| ^~~~~~~~~~~~~~~~~~
arch/x86/include/asm/barrier.h:69:9: note: in expansion of macro 'compiletime_assert_atomic_type'
69 | compiletime_assert_atomic_type(*p); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/barrier.h:176:29: note: in expansion of macro '__smp_load_acquire'
176 | #define smp_load_acquire(p) __smp_load_acquire(p)
| ^~~~~~~~~~~~~~~~~~
include/linux/fs.h:960:16: note: in expansion of macro 'smp_load_acquire'
960 | return smp_load_acquire(&inode->i_size);
| ^~~~~~~~~~~~~~~~
vim +/__compiletime_assert_451 +568 include/linux/compiler_types.h
eb5c2d4b45e3d2 Will Deacon 2020-07-21 554
eb5c2d4b45e3d2 Will Deacon 2020-07-21 555 #define _compiletime_assert(condition, msg, prefix, suffix) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21 556 __compiletime_assert(condition, msg, prefix, suffix)
eb5c2d4b45e3d2 Will Deacon 2020-07-21 557
eb5c2d4b45e3d2 Will Deacon 2020-07-21 558 /**
eb5c2d4b45e3d2 Will Deacon 2020-07-21 559 * compiletime_assert - break build and emit msg if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21 560 * @condition: a compile-time constant condition to check
eb5c2d4b45e3d2 Will Deacon 2020-07-21 561 * @msg: a message to emit if condition is false
eb5c2d4b45e3d2 Will Deacon 2020-07-21 562 *
eb5c2d4b45e3d2 Will Deacon 2020-07-21 563 * In tradition of POSIX assert, this macro will break the build if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21 564 * supplied condition is *false*, emitting the supplied error message if the
eb5c2d4b45e3d2 Will Deacon 2020-07-21 565 * compiler has support to do so.
eb5c2d4b45e3d2 Will Deacon 2020-07-21 566 */
eb5c2d4b45e3d2 Will Deacon 2020-07-21 567 #define compiletime_assert(condition, msg) \
eb5c2d4b45e3d2 Will Deacon 2020-07-21 @568 _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
eb5c2d4b45e3d2 Will Deacon 2020-07-21 569
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-07-17 5:06 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-16 12:53 [PATCH] fs: Remove obsolete logic in i_size_read/write Alex
2025-07-16 13:12 ` Al Viro
2025-07-16 13:28 ` Alex
2025-07-16 13:41 ` Matthew Wilcox
2025-07-16 13:44 ` Alex
2025-07-16 13:57 ` Matthew Wilcox
2025-07-16 14:38 ` Alex
2025-07-17 5:05 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).