]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - include/linux/fs.h
locks: add a dedicated spinlock to protect i_flctx lists
[mirror_ubuntu-jammy-kernel.git] / include / linux / fs.h
index f90c0282c11493f94a84095f61db94ac90974cc4..32eafa9b5c9f73f5b8efd0d75d53e61b8cd9ed80 100644 (file)
@@ -135,7 +135,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define FMODE_CAN_WRITE         ((__force fmode_t)0x40000)
 
 /* File was opened by fanotify and shouldn't generate fanotify events */
-#define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
+#define FMODE_NONOTIFY         ((__force fmode_t)0x4000000)
 
 /*
  * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
@@ -625,7 +625,7 @@ struct inode {
        atomic_t                i_readcount; /* struct files open RO */
 #endif
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
-       struct file_lock        *i_flock;
+       struct file_lock_context        *i_flctx;
        struct address_space    i_data;
        struct list_head        i_devices;
        union {
@@ -885,6 +885,8 @@ static inline struct file *get_file(struct file *f)
 /* legacy typedef, should eventually be removed */
 typedef void *fl_owner_t;
 
+struct file_lock;
+
 struct file_lock_operations {
        void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
        void (*fl_release_private)(struct file_lock *);
@@ -934,6 +936,7 @@ int locks_in_grace(struct net *);
  */
 struct file_lock {
        struct file_lock *fl_next;      /* singly linked list for this inode  */
+       struct list_head fl_list;       /* link into file_lock_context */
        struct hlist_node fl_link;      /* node in global lists */
        struct list_head fl_block;      /* circular list of blocked processes */
        fl_owner_t fl_owner;
@@ -964,6 +967,13 @@ struct file_lock {
        } fl_u;
 };
 
+struct file_lock_context {
+       spinlock_t              flc_lock;
+       struct list_head        flc_flock;
+       struct list_head        flc_posix;
+       struct list_head        flc_lease;
+};
+
 /* The following constant reflects the upper bound of the file/locking space */
 #ifndef OFFSET_MAX
 #define INT_LIMIT(x)   (~((x)1 << (sizeof(x)*8 - 1)))
@@ -990,6 +1000,7 @@ extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
 extern int fcntl_getlease(struct file *filp);
 
 /* fs/locks.c */
+void locks_free_lock_context(struct file_lock_context *ctx);
 void locks_free_lock(struct file_lock *fl);
 extern void locks_init_lock(struct file_lock *);
 extern struct file_lock * locks_alloc_lock(void);
@@ -1047,6 +1058,11 @@ static inline int fcntl_getlease(struct file *filp)
        return F_UNLCK;
 }
 
+static inline void
+locks_free_lock_context(struct file_lock_context *ctx)
+{
+}
+
 static inline void locks_init_lock(struct file_lock *fl)
 {
        return;
@@ -1959,7 +1975,7 @@ static inline int locks_verify_truncate(struct inode *inode,
                                    struct file *filp,
                                    loff_t size)
 {
-       if (inode->i_flock && mandatory_lock(inode))
+       if (inode->i_flctx && mandatory_lock(inode))
                return locks_mandatory_area(
                        FLOCK_VERIFY_WRITE, inode, filp,
                        size < inode->i_size ? size : inode->i_size,
@@ -1977,7 +1993,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
         * end up racing with tasks trying to set a new lease on this file.
         */
        smp_mb();
-       if (inode->i_flock)
+       if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease))
                return __break_lease(inode, mode, FL_LEASE);
        return 0;
 }
@@ -1990,7 +2006,7 @@ static inline int break_deleg(struct inode *inode, unsigned int mode)
         * end up racing with tasks trying to set a new lease on this file.
         */
        smp_mb();
-       if (inode->i_flock)
+       if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease))
                return __break_lease(inode, mode, FL_DELEG);
        return 0;
 }