summaryrefslogtreecommitdiffstats
path: root/include/linux/fs.h
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2019-06-07 10:24:38 -0400
committerJeff Layton <jlayton@kernel.org>2019-06-19 08:49:38 -0400
commit387e3746d01c34457d6a73688acd90428725070b (patch)
tree575796428aac6a85321113d53a75abe9cfdccbcf /include/linux/fs.h
parentd51f527f44f96276a94c191bc160de051f64aeea (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.h4
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)
2894static inline void i_readcount_dec(struct inode *inode) 2894static 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));