diff options
author | Amir Goldstein <amir73il@gmail.com> | 2019-06-07 10:24:38 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@kernel.org> | 2019-06-19 08:49:38 -0400 |
commit | 387e3746d01c34457d6a73688acd90428725070b (patch) | |
tree | 575796428aac6a85321113d53a75abe9cfdccbcf /include/linux/fs.h | |
parent | d51f527f44f96276a94c191bc160de051f64aeea (diff) |
locks: eliminate false positive conflicts for write lease
check_conflicting_open() is checking for existing fd's open for read or
for write before allowing to take a write lease. The check that was
implemented using i_count and d_count is an approximation that has
several false positives. For example, overlayfs since v4.19, takes an
extra reference on the dentry; An open with O_PATH takes a reference on
the dentry although the file cannot be read nor written.
Change the implementation to use i_readcount and i_writecount to
eliminate the false positive conflicts and allow a write lease to be
taken on an overlayfs file.
The change of behavior with existing fd's open with O_PATH is symmetric
w.r.t. current behavior of lease breakers - an open with O_PATH currently
does not break a write lease.
This increases the size of struct inode by 4 bytes on 32bit archs when
CONFIG_FILE_LOCKING is defined and CONFIG_IMA was not already
defined.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Diffstat (limited to 'include/linux/fs.h')
-rw-r--r-- | include/linux/fs.h | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index f7fdfe93e25d..419e327022de 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -694,7 +694,7 @@ struct inode { | |||
694 | atomic_t i_count; | 694 | atomic_t i_count; |
695 | atomic_t i_dio_count; | 695 | atomic_t i_dio_count; |
696 | atomic_t i_writecount; | 696 | atomic_t i_writecount; |
697 | #ifdef CONFIG_IMA | 697 | #if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING) |
698 | atomic_t i_readcount; /* struct files open RO */ | 698 | atomic_t i_readcount; /* struct files open RO */ |
699 | #endif | 699 | #endif |
700 | union { | 700 | union { |
@@ -2890,7 +2890,7 @@ static inline bool inode_is_open_for_write(const struct inode *inode) | |||
2890 | return atomic_read(&inode->i_writecount) > 0; | 2890 | return atomic_read(&inode->i_writecount) > 0; |
2891 | } | 2891 | } |
2892 | 2892 | ||
2893 | #ifdef CONFIG_IMA | 2893 | #if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING) |
2894 | static inline void i_readcount_dec(struct inode *inode) | 2894 | static inline void i_readcount_dec(struct inode *inode) |
2895 | { | 2895 | { |
2896 | BUG_ON(!atomic_read(&inode->i_readcount)); | 2896 | BUG_ON(!atomic_read(&inode->i_readcount)); |