* [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).