linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).