Merge tag 'for_v4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Oct 2018 16:19:53 +0000 (09:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Oct 2018 16:19:53 +0000 (09:19 -0700)
Pull fsnotify updates from Jan Kara:
 "Amir's patches to implement superblock fanotify watches, Xiaoming's
  patch to enable reporting of thread IDs in fanotify events instead of
  TGIDs (sadly the patch got mis-attributed to Amir and I've noticed
  only now), and a fix of possible oops on umount caused by fsnotify
  infrastructure"

* tag 'for_v4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: Fix busy inodes during unmount
  fs: group frequently accessed fields of struct super_block together
  fanotify: support reporting thread id instead of process id
  fanotify: add BUILD_BUG_ON() to count the bits of fanotify constants
  fsnotify: convert runtime BUG_ON() to BUILD_BUG_ON()
  fanotify: deprecate uapi FAN_ALL_* constants
  fanotify: simplify handling of FAN_ONDIR
  fsnotify: generalize handling of extra event flags
  fanotify: fix collision of internal and uapi mark flags
  fanotify: store fanotify_init() flags in group's fanotify_data
  fanotify: add API to attach/detach super block mark
  fsnotify: send path type events to group with super block marks
  fsnotify: add super block object type

1  2 
include/linux/fs.h

diff --combined include/linux/fs.h
index 771341470bcebd249b023be7cc8f6a22e09b2d31,00b23b21e78af61425e2ccfac6e402670fb0e174..8252df30b9a16afe53c269b912b47e17edac7b41
@@@ -403,40 -403,24 +403,40 @@@ int pagecache_write_end(struct file *, 
                                loff_t pos, unsigned len, unsigned copied,
                                struct page *page, void *fsdata);
  
 +/**
 + * struct address_space - Contents of a cacheable, mappable object.
 + * @host: Owner, either the inode or the block_device.
 + * @i_pages: Cached pages.
 + * @gfp_mask: Memory allocation flags to use for allocating pages.
 + * @i_mmap_writable: Number of VM_SHARED mappings.
 + * @i_mmap: Tree of private and shared mappings.
 + * @i_mmap_rwsem: Protects @i_mmap and @i_mmap_writable.
 + * @nrpages: Number of page entries, protected by the i_pages lock.
 + * @nrexceptional: Shadow or DAX entries, protected by the i_pages lock.
 + * @writeback_index: Writeback starts here.
 + * @a_ops: Methods.
 + * @flags: Error bits and flags (AS_*).
 + * @wb_err: The most recent error which has occurred.
 + * @private_lock: For use by the owner of the address_space.
 + * @private_list: For use by the owner of the address_space.
 + * @private_data: For use by the owner of the address_space.
 + */
  struct address_space {
 -      struct inode            *host;          /* owner: inode, block_device */
 -      struct radix_tree_root  i_pages;        /* cached pages */
 -      atomic_t                i_mmap_writable;/* count VM_SHARED mappings */
 -      struct rb_root_cached   i_mmap;         /* tree of private and shared mappings */
 -      struct rw_semaphore     i_mmap_rwsem;   /* protect tree, count, list */
 -      /* Protected by the i_pages lock */
 -      unsigned long           nrpages;        /* number of total pages */
 -      /* number of shadow or DAX exceptional entries */
 +      struct inode            *host;
 +      struct xarray           i_pages;
 +      gfp_t                   gfp_mask;
 +      atomic_t                i_mmap_writable;
 +      struct rb_root_cached   i_mmap;
 +      struct rw_semaphore     i_mmap_rwsem;
 +      unsigned long           nrpages;
        unsigned long           nrexceptional;
 -      pgoff_t                 writeback_index;/* writeback starts here */
 -      const struct address_space_operations *a_ops;   /* methods */
 -      unsigned long           flags;          /* error bits */
 -      spinlock_t              private_lock;   /* for use by the address_space */
 -      gfp_t                   gfp_mask;       /* implicit gfp mask for allocations */
 -      struct list_head        private_list;   /* for use by the address_space */
 -      void                    *private_data;  /* ditto */
 +      pgoff_t                 writeback_index;
 +      const struct address_space_operations *a_ops;
 +      unsigned long           flags;
        errseq_t                wb_err;
 +      spinlock_t              private_lock;
 +      struct list_head        private_list;
 +      void                    *private_data;
  } __attribute__((aligned(sizeof(long)))) __randomize_layout;
        /*
         * On most architectures that alignment is already the case; but
@@@ -483,18 -467,15 +483,18 @@@ struct block_device 
        struct mutex            bd_fsfreeze_mutex;
  } __randomize_layout;
  
 +/* XArray tags, for tagging dirty and writeback pages in the pagecache. */
 +#define PAGECACHE_TAG_DIRTY   XA_MARK_0
 +#define PAGECACHE_TAG_WRITEBACK       XA_MARK_1
 +#define PAGECACHE_TAG_TOWRITE XA_MARK_2
 +
  /*
 - * Radix-tree tags, for tagging dirty and writeback pages within the pagecache
 - * radix trees
 + * Returns true if any of the pages in the mapping are marked with the tag.
   */
 -#define PAGECACHE_TAG_DIRTY   0
 -#define PAGECACHE_TAG_WRITEBACK       1
 -#define PAGECACHE_TAG_TOWRITE 2
 -
 -int mapping_tagged(struct address_space *mapping, int tag);
 +static inline bool mapping_tagged(struct address_space *mapping, xa_mark_t tag)
 +{
 +      return xa_marked(&mapping->i_pages, tag);
 +}
  
  static inline void i_mmap_lock_write(struct address_space *mapping)
  {
@@@ -1412,17 -1393,26 +1412,26 @@@ struct super_block 
  
        struct sb_writers       s_writers;
  
+       /*
+        * Keep s_fs_info, s_time_gran, s_fsnotify_mask, and
+        * s_fsnotify_marks together for cache efficiency. They are frequently
+        * accessed and rarely modified.
+        */
+       void                    *s_fs_info;     /* Filesystem private info */
+       /* Granularity of c/m/atime in ns (cannot be worse than a second) */
+       u32                     s_time_gran;
+ #ifdef CONFIG_FSNOTIFY
+       __u32                   s_fsnotify_mask;
+       struct fsnotify_mark_connector __rcu    *s_fsnotify_marks;
+ #endif
        char                    s_id[32];       /* Informational name */
        uuid_t                  s_uuid;         /* UUID */
  
-       void                    *s_fs_info;     /* Filesystem private info */
        unsigned int            s_max_links;
        fmode_t                 s_mode;
  
-       /* Granularity of c/m/atime in ns.
-          Cannot be worse than a second */
-       u32                s_time_gran;
        /*
         * The next field is for VFS *only*. No filesystems have any business
         * even looking at it. You had been warned.
        /* Number of inodes with nlink == 0 but still referenced */
        atomic_long_t s_remove_count;
  
+       /* Pending fsnotify inode refs */
+       atomic_long_t s_fsnotify_inode_refs;
        /* Being remounted read-only */
        int s_readonly_remount;
  
@@@ -1782,7 -1775,6 +1794,7 @@@ struct file_operations 
                        u64);
        int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t,
                        u64);
 +      int (*fadvise)(struct file *, loff_t, loff_t, int);
  } __randomize_layout;
  
  struct inode_operations {
@@@ -1847,10 -1839,8 +1859,10 @@@ extern ssize_t vfs_copy_file_range(stru
  extern int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
                                      struct inode *inode_out, loff_t pos_out,
                                      u64 *len, bool is_dedupe);
 +extern int do_clone_file_range(struct file *file_in, loff_t pos_in,
 +                             struct file *file_out, loff_t pos_out, u64 len);
  extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
 -              struct file *file_out, loff_t pos_out, u64 len);
 +                              struct file *file_out, loff_t pos_out, u64 len);
  extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
                                         struct inode *dest, loff_t destoff,
                                         loff_t len, bool *is_same);
@@@ -2794,6 -2784,19 +2806,6 @@@ static inline void file_end_write(struc
        __sb_end_write(file_inode(file)->i_sb, SB_FREEZE_WRITE);
  }
  
 -static inline int do_clone_file_range(struct file *file_in, loff_t pos_in,
 -                                    struct file *file_out, loff_t pos_out,
 -                                    u64 len)
 -{
 -      int ret;
 -
 -      file_start_write(file_out);
 -      ret = vfs_clone_file_range(file_in, pos_in, file_out, pos_out, len);
 -      file_end_write(file_out);
 -
 -      return ret;
 -}
 -
  /*
   * get_write_access() gets write permission for a file.
   * put_write_access() releases this write permission.
@@@ -3468,8 -3471,4 +3480,8 @@@ static inline bool dir_relax_shared(str
  extern bool path_noexec(const struct path *path);
  extern void inode_nohighmem(struct inode *inode);
  
 +/* mm/fadvise.c */
 +extern int vfs_fadvise(struct file *file, loff_t offset, loff_t len,
 +                     int advice);
 +
  #endif /* _LINUX_FS_H */