Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 20:37:39 +0000 (13:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 20:37:39 +0000 (13:37 -0700)
Pull ext4 updates from Ted Ts'o:
 "Added new ext4 debugging ioctls to allow userspace to get information
  about the state of the extent status cache.

  Dropped workaround for pre-1970 dates which were encoded incorrectly
  in pre-4.4 kernels. Since both the kernel correctly generates, and
  e2fsck detects and fixes this issue for the past four years, it'e time
  to drop the workaround. (Also, it's not like files with dates in the
  distant past were all that common in the first place.)

  A lot of miscellaneous bug fixes and cleanups, including some ext4
  Documentation fixes. Also included are two minor bug fixes in
  fs/unicode"

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (21 commits)
  unicode: make array 'token' static const, makes object smaller
  unicode: Move static keyword to the front of declarations
  ext4: add missing bigalloc documentation.
  ext4: fix kernel oops caused by spurious casefold flag
  ext4: fix integer overflow when calculating commit interval
  ext4: use percpu_counters for extent_status cache hits/misses
  ext4: fix potential use after free after remounting with noblock_validity
  jbd2: add missing tracepoint for reserved handle
  ext4: fix punch hole for inline_data file systems
  ext4: rework reserved cluster accounting when invalidating pages
  ext4: documentation fixes
  ext4: treat buffers with write errors as containing valid data
  ext4: fix warning inside ext4_convert_unwritten_extents_endio
  ext4: set error return correctly when ext4_htree_store_dirent fails
  ext4: drop legacy pre-1970 encoding workaround
  ext4: add new ioctl EXT4_IOC_GET_ES_CACHE
  ext4: add a new ioctl EXT4_IOC_GETSTATE
  ext4: add a new ioctl EXT4_IOC_CLEAR_ES_CACHE
  jbd2: flush_descriptor(): Do not decrease buffer head's ref count
  ext4: remove unnecessary error check
  ...

1  2 
Documentation/filesystems/ext4/inodes.rst
Documentation/filesystems/ext4/super.rst
fs/ext4/ext4.h
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/super.c

index e851e6ca31fa0e3952e95616e6da350b332206f8,34f62928cebc574e23ac79106fb6fb559ca50d48..a65baffb4ebf8cf17bafe3d8567547a2ec644502
@@@ -277,8 -277,6 +277,8 @@@ The ``i_flags`` field is a combination 
       - This is a huge file (EXT4\_HUGE\_FILE\_FL).
     * - 0x80000
       - Inode uses extents (EXT4\_EXTENTS\_FL).
 +   * - 0x100000
 +     - Verity protected file (EXT4\_VERITY\_FL).
     * - 0x200000
       - Inode stores a large extended attribute value in its data blocks
         (EXT4\_EA\_INODE\_FL).
       - Reserved for ext4 library (EXT4\_RESERVED\_FL).
     * -
       - Aggregate flags:
 -   * - 0x4BDFFF
 +   * - 0x705BDFFF
       - User-visible flags.
 -   * - 0x4B80FF
 +   * - 0x604BC0FF
       - User-modifiable flags. Note that while EXT4\_JOURNAL\_DATA\_FL and
         EXT4\_EXTENTS\_FL can be set with setattr, they are not in the kernel's
         EXT4\_FL\_USER\_MODIFIABLE mask, since it needs to handle the setting of
@@@ -472,8 -470,8 +472,8 @@@ inode, which allows struct ext4\_inode 
  having to upgrade all of the on-disk inodes. Access to fields beyond
  EXT2\_GOOD\_OLD\_INODE\_SIZE should be verified to be within
  ``i_extra_isize``. By default, ext4 inode records are 256 bytes, and (as
- of October 2013) the inode structure is 156 bytes
- (``i_extra_isize = 28``). The extra space between the end of the inode
+ of August 2019) the inode structure is 160 bytes
+ (``i_extra_isize = 32``). The extra space between the end of the inode
  structure and the end of the inode record can be used to store extended
  attributes. Each inode record can be as large as the filesystem block
  size, though this is not terribly efficient.
index 6eae9205482787a7d9ecb86f956fe5871ffaf8c0,48b6c78fc38e3574f7056caac0e657071ad087c7..93e55d7c1d4055960b987076ca82e2c9c04af73f
@@@ -58,7 -58,7 +58,7 @@@ The ext4 superblock is laid out as foll
     * - 0x1C
       - \_\_le32
       - s\_log\_cluster\_size
-      - Cluster size is (2 ^ s\_log\_cluster\_size) blocks if bigalloc is
+      - Cluster size is 2 ^ (10 + s\_log\_cluster\_size) blocks if bigalloc is
         enabled. Otherwise s\_log\_cluster\_size must equal s\_log\_block\_size.
     * - 0x20
       - \_\_le32
       - Upper 8 bits of the s_wtime field.
     * - 0x275
       - \_\_u8
-      - s\_wtime_hi
+      - s\_mtime_hi
       - Upper 8 bits of the s_mtime field.
     * - 0x276
       - \_\_u8
       - s\_last_error_time_hi
       - Upper 8 bits of the s_last_error_time_hi field.
     * - 0x27A
-      - \_\_u8[2]
-      - s\_pad
+      - \_\_u8
+      - s\_pad[2]
       - Zero padding.
     * - 0x27C
+      - \_\_le16
+      - s\_encoding
+      - Filename charset encoding.
+    * - 0x27E
+      - \_\_le16
+      - s\_encoding_flags
+      - Filename charset encoding flags.
+    * - 0x280
       - \_\_le32
-      - s\_reserved[96]
+      - s\_reserved[95]
       - Padding to the end of the block.
     * - 0x3FC
       - \_\_le32
@@@ -617,7 -625,7 +625,7 @@@ following
     * - 0x80
       - Enable a filesystem size of 2^64 blocks (INCOMPAT\_64BIT).
     * - 0x100
-      - Multiple mount protection. Not implemented (INCOMPAT\_MMP).
+      - Multiple mount protection (INCOMPAT\_MMP).
     * - 0x200
       - Flexible block groups. See the earlier discussion of this feature
         (INCOMPAT\_FLEX\_BG).
@@@ -696,8 -704,6 +704,8 @@@ the following
         (RO\_COMPAT\_READONLY)
     * - 0x2000
       - Filesystem tracks project quotas. (RO\_COMPAT\_PROJECT)
 +   * - 0x8000
 +     - Verity inodes may be present on the filesystem. (RO\_COMPAT\_VERITY)
  
  .. _super_def_hash:
  
diff --combined fs/ext4/ext4.h
index 42c6e4a5e673f7c2de8f1d7c182cf3979a78c007,c35bb8d734df6a3b694d1e4c5100aa0166921f52..03db3e71676ce1d79a65761f102c4bef6660d01e
@@@ -41,7 -41,6 +41,7 @@@
  #endif
  
  #include <linux/fscrypt.h>
 +#include <linux/fsverity.h>
  
  #include <linux/compiler.h>
  
@@@ -185,6 -184,14 +185,14 @@@ struct ext4_map_blocks 
        unsigned int m_flags;
  };
  
+ /*
+  * Block validity checking, system zone rbtree.
+  */
+ struct ext4_system_blocks {
+       struct rb_root root;
+       struct rcu_head rcu;
+ };
  /*
   * Flags for ext4_io_end->flags
   */
@@@ -285,6 -292,9 +293,9 @@@ struct ext4_io_submit 
                                  ~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
  #define EXT4_LBLK_CMASK(s, lblk) ((lblk) &                            \
                                  ~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
+ /* Fill in the low bits to get the last block of the cluster */
+ #define EXT4_LBLK_CFILL(sbi, lblk) ((lblk) |                          \
+                                   ((ext4_lblk_t) (sbi)->s_cluster_ratio - 1))
  /* Get the cluster offset */
  #define EXT4_PBLK_COFF(s, pblk) ((pblk) &                             \
                                 ((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
@@@ -396,7 -406,6 +407,7 @@@ struct flex_groups 
  #define EXT4_TOPDIR_FL                        0x00020000 /* Top of directory hierarchies*/
  #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
  #define EXT4_EXTENTS_FL                       0x00080000 /* Inode uses extents */
 +#define EXT4_VERITY_FL                        0x00100000 /* Verity protected inode */
  #define EXT4_EA_INODE_FL              0x00200000 /* Inode used for large EA */
  #define EXT4_EOFBLOCKS_FL             0x00400000 /* Blocks allocated beyond EOF */
  #define EXT4_INLINE_DATA_FL           0x10000000 /* Inode has inline data. */
  #define EXT4_CASEFOLD_FL              0x40000000 /* Casefolded file */
  #define EXT4_RESERVED_FL              0x80000000 /* reserved for ext4 lib */
  
 -#define EXT4_FL_USER_VISIBLE          0x704BDFFF /* User visible flags */
 +#define EXT4_FL_USER_VISIBLE          0x705BDFFF /* User visible flags */
  #define EXT4_FL_USER_MODIFIABLE               0x604BC0FF /* User modifiable flags */
  
  /* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
@@@ -469,7 -478,6 +480,7 @@@ enum 
        EXT4_INODE_TOPDIR       = 17,   /* Top of directory hierarchies*/
        EXT4_INODE_HUGE_FILE    = 18,   /* Set to each huge file */
        EXT4_INODE_EXTENTS      = 19,   /* Inode uses extents */
 +      EXT4_INODE_VERITY       = 20,   /* Verity protected inode */
        EXT4_INODE_EA_INODE     = 21,   /* Inode used for large EA */
        EXT4_INODE_EOFBLOCKS    = 22,   /* Blocks allocated beyond EOF */
        EXT4_INODE_INLINE_DATA  = 28,   /* Data in inode. */
@@@ -515,7 -523,6 +526,7 @@@ static inline void ext4_check_flag_valu
        CHECK_FLAG_VALUE(TOPDIR);
        CHECK_FLAG_VALUE(HUGE_FILE);
        CHECK_FLAG_VALUE(EXTENTS);
 +      CHECK_FLAG_VALUE(VERITY);
        CHECK_FLAG_VALUE(EA_INODE);
        CHECK_FLAG_VALUE(EOFBLOCKS);
        CHECK_FLAG_VALUE(INLINE_DATA);
@@@ -653,6 -660,10 +664,10 @@@ enum 
  #define EXT4_IOC_SET_ENCRYPTION_POLICY        FS_IOC_SET_ENCRYPTION_POLICY
  #define EXT4_IOC_GET_ENCRYPTION_PWSALT        FS_IOC_GET_ENCRYPTION_PWSALT
  #define EXT4_IOC_GET_ENCRYPTION_POLICY        FS_IOC_GET_ENCRYPTION_POLICY
+ /* ioctl codes 19--39 are reserved for fscrypt */
+ #define EXT4_IOC_CLEAR_ES_CACHE               _IO('f', 40)
+ #define EXT4_IOC_GETSTATE             _IOW('f', 41, __u32)
+ #define EXT4_IOC_GET_ES_CACHE         _IOWR('f', 42, struct fiemap)
  
  #define EXT4_IOC_FSGETXATTR           FS_IOC_FSGETXATTR
  #define EXT4_IOC_FSSETXATTR           FS_IOC_FSSETXATTR
  #define EXT4_GOING_FLAGS_LOGFLUSH             0x1     /* flush log but not data */
  #define EXT4_GOING_FLAGS_NOLOGFLUSH           0x2     /* don't flush log nor data */
  
+ /*
+  * Flags returned by EXT4_IOC_GETSTATE
+  *
+  * We only expose to userspace a subset of the state flags in
+  * i_state_flags
+  */
+ #define EXT4_STATE_FLAG_EXT_PRECACHED 0x00000001
+ #define EXT4_STATE_FLAG_NEW           0x00000002
+ #define EXT4_STATE_FLAG_NEWENTRY      0x00000004
+ #define EXT4_STATE_FLAG_DA_ALLOC_CLOSE        0x00000008
  
  #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
  /*
  #define EXT4_IOC32_SETVERSION_OLD     FS_IOC32_SETVERSION
  #endif
  
+ /*
+  * Returned by EXT4_IOC_GET_ES_CACHE as an additional possible flag.
+  * It indicates that the entry in extent status cache is for a hole.
+  */
+ #define EXT4_FIEMAP_EXTENT_HOLE               0x08000000
  /* Max physical block we can address w/o extents */
  #define EXT4_MAX_BLOCK_FILE_PHYS      0xFFFFFFFF
  
@@@ -812,33 -839,18 +843,20 @@@ static inline __le32 ext4_encode_extra_
  static inline void ext4_decode_extra_time(struct timespec64 *time,
                                          __le32 extra)
  {
-       if (unlikely(extra & cpu_to_le32(EXT4_EPOCH_MASK))) {
- #if 1
-               /* Handle legacy encoding of pre-1970 dates with epoch
-                * bits 1,1. (This backwards compatibility may be removed
-                * at the discretion of the ext4 developers.)
-                */
-               u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
-               if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
-                       extra_bits = 0;
-               time->tv_sec += extra_bits << 32;
- #else
+       if (unlikely(extra & cpu_to_le32(EXT4_EPOCH_MASK)))
                time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
- #endif
-       }
        time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
  }
  
  #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)                         \
  do {                                                                          \
 -      (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);                \
        if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))     {\
 +              (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);        \
                (raw_inode)->xtime ## _extra =                                  \
                                ext4_encode_extra_time(&(inode)->xtime);        \
                }                                                               \
 +      else    \
 +              (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (inode)->xtime.tv_sec, S32_MIN, S32_MAX));    \
  } while (0)
  
  #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode)                              \
@@@ -1427,7 -1439,7 +1445,7 @@@ struct ext4_sb_info 
        int s_jquota_fmt;                       /* Format of quota to use */
  #endif
        unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
-       struct rb_root system_blks;
+       struct ext4_system_blocks __rcu *system_blks;
  
  #ifdef EXTENTS_STATS
        /* ext4 extents stats */
@@@ -1566,7 -1578,6 +1584,7 @@@ enum 
        EXT4_STATE_MAY_INLINE_DATA,     /* may have in-inode data */
        EXT4_STATE_EXT_PRECACHED,       /* extents have been precached */
        EXT4_STATE_LUSTRE_EA_INODE,     /* Lustre-style ea_inode */
 +      EXT4_STATE_VERITY_IN_PROGRESS,  /* building fs-verity Merkle tree */
  };
  
  #define EXT4_INODE_BIT_FNS(name, field, offset)                               \
@@@ -1617,12 -1628,6 +1635,12 @@@ static inline void ext4_clear_state_fla
  #define EXT4_SB(sb)   (sb)
  #endif
  
 +static inline bool ext4_verity_in_progress(struct inode *inode)
 +{
 +      return IS_ENABLED(CONFIG_FS_VERITY) &&
 +             ext4_test_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
 +}
 +
  #define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
  
  /*
  
  #define EXT4_GOOD_OLD_INODE_SIZE 128
  
 +#define EXT4_EXTRA_TIMESTAMP_MAX      (((s64)1 << 34) - 1  + S32_MIN)
 +#define EXT4_NON_EXTRA_TIMESTAMP_MAX  S32_MAX
 +#define EXT4_TIMESTAMP_MIN            S32_MIN
 +
  /*
   * Feature set definitions
   */
  #define EXT4_FEATURE_RO_COMPAT_METADATA_CSUM  0x0400
  #define EXT4_FEATURE_RO_COMPAT_READONLY               0x1000
  #define EXT4_FEATURE_RO_COMPAT_PROJECT                0x2000
 +#define EXT4_FEATURE_RO_COMPAT_VERITY         0x8000
  
  #define EXT4_FEATURE_INCOMPAT_COMPRESSION     0x0001
  #define EXT4_FEATURE_INCOMPAT_FILETYPE                0x0002
@@@ -1774,7 -1774,6 +1792,7 @@@ EXT4_FEATURE_RO_COMPAT_FUNCS(bigalloc
  EXT4_FEATURE_RO_COMPAT_FUNCS(metadata_csum,   METADATA_CSUM)
  EXT4_FEATURE_RO_COMPAT_FUNCS(readonly,                READONLY)
  EXT4_FEATURE_RO_COMPAT_FUNCS(project,         PROJECT)
 +EXT4_FEATURE_RO_COMPAT_FUNCS(verity,          VERITY)
  
  EXT4_FEATURE_INCOMPAT_FUNCS(compression,      COMPRESSION)
  EXT4_FEATURE_INCOMPAT_FUNCS(filetype,         FILETYPE)
@@@ -1832,8 -1831,7 +1850,8 @@@ EXT4_FEATURE_INCOMPAT_FUNCS(casefold,           
                                         EXT4_FEATURE_RO_COMPAT_BIGALLOC |\
                                         EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
                                         EXT4_FEATURE_RO_COMPAT_QUOTA |\
 -                                       EXT4_FEATURE_RO_COMPAT_PROJECT)
 +                                       EXT4_FEATURE_RO_COMPAT_PROJECT |\
 +                                       EXT4_FEATURE_RO_COMPAT_VERITY)
  
  #define EXTN_FEATURE_FUNCS(ver) \
  static inline bool ext4_has_unknown_ext##ver##_compat_features(struct super_block *sb) \
@@@ -3197,8 -3195,6 +3215,8 @@@ static inline void ext4_set_de_type(str
  extern int ext4_mpage_readpages(struct address_space *mapping,
                                struct list_head *pages, struct page *page,
                                unsigned nr_pages, bool is_readahead);
 +extern int __init ext4_init_post_read_processing(void);
 +extern void ext4_exit_post_read_processing(void);
  
  /* symlink.c */
  extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
@@@ -3267,6 -3263,9 +3285,9 @@@ extern int ext4_ext_check_inode(struct 
  extern ext4_lblk_t ext4_ext_next_allocated_block(struct ext4_ext_path *path);
  extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                        __u64 start, __u64 len);
+ extern int ext4_get_es_cache(struct inode *inode,
+                            struct fiemap_extent_info *fieinfo,
+                            __u64 start, __u64 len);
  extern int ext4_ext_precache(struct inode *inode);
  extern int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len);
  extern int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len);
@@@ -3305,9 -3304,6 +3326,9 @@@ extern int ext4_bio_write_page(struct e
  /* mmp.c */
  extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
  
 +/* verity.c */
 +extern const struct fsverity_operations ext4_verityops;
 +
  /*
   * Add new method to test whether block and inode bitmaps are properly
   * initialized. With uninit_bg reading the block from disk is not enough
@@@ -3359,6 -3355,19 +3380,19 @@@ static inline void ext4_clear_io_unwrit
  
  extern const struct iomap_ops ext4_iomap_ops;
  
+ static inline int ext4_buffer_uptodate(struct buffer_head *bh)
+ {
+       /*
+        * If the buffer has the write error flag, we have failed
+        * to write out data in the block.  In this  case, we don't
+        * have to read the block because we may read the old data
+        * successfully.
+        */
+       if (!buffer_uptodate(bh) && buffer_write_io_error(bh))
+               set_buffer_uptodate(bh);
+       return buffer_uptodate(bh);
+ }
  #endif        /* __KERNEL__ */
  
  #define EFSBADCRC     EBADMSG         /* Bad CRC detected */
diff --combined fs/ext4/file.c
index b8a20bb9a14534cfbc7f86d36791cc371a4868e0,bc378a7ac9503f3dabf7b6a592cb77d7976aa97b..8d2bbcc2d8133d6e43544e08fc4bd16f05a449fe
@@@ -230,8 -230,6 +230,6 @@@ ext4_file_write_iter(struct kiocb *iocb
        if (IS_DAX(inode))
                return ext4_dax_write_iter(iocb, from);
  #endif
-       if (!o_direct && (iocb->ki_flags & IOCB_NOWAIT))
-               return -EOPNOTSUPP;
  
        if (!inode_trylock(inode)) {
                if (iocb->ki_flags & IOCB_NOWAIT)
@@@ -455,10 -453,6 +453,10 @@@ static int ext4_file_open(struct inode 
  
        ret = fscrypt_file_open(inode, filp);
        if (ret)
 +              return ret;
 +
 +      ret = fsverity_file_open(inode, filp);
 +      if (ret)
                return ret;
  
        /*
diff --combined fs/ext4/inode.c
index d0dc0e3463db83bea66fb14540d0275ceadd0347,4e271b509af18c1a36d937ba61ae144e339e900d..123e3dee7733b693451b1f563461e4aac60ae05b
@@@ -527,7 -527,7 +527,7 @@@ int ext4_map_blocks(handle_t *handle, s
                return -EFSCORRUPTED;
  
        /* Lookup extent status tree firstly */
-       if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
+       if (ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
                if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) {
                        map->m_pblk = ext4_es_pblock(&es) +
                                        map->m_lblk - es.es_lblk;
@@@ -695,7 -695,7 +695,7 @@@ found
                 * extent status tree.
                 */
                if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
-                   ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
+                   ext4_es_lookup_extent(inode, map->m_lblk, NULL, &es)) {
                        if (ext4_es_is_written(&es))
                                goto out_sem;
                }
@@@ -1024,7 -1024,7 +1024,7 @@@ struct buffer_head *ext4_bread(handle_
        bh = ext4_getblk(handle, inode, block, map_flags);
        if (IS_ERR(bh))
                return bh;
-       if (!bh || buffer_uptodate(bh))
+       if (!bh || ext4_buffer_uptodate(bh))
                return bh;
        ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh);
        wait_on_buffer(bh);
@@@ -1051,7 -1051,7 +1051,7 @@@ int ext4_bread_batch(struct inode *inod
  
        for (i = 0; i < bh_count; i++)
                /* Note that NULL bhs[i] is valid because of holes. */
-               if (bhs[i] && !buffer_uptodate(bhs[i]))
+               if (bhs[i] && !ext4_buffer_uptodate(bhs[i]))
                        ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1,
                                    &bhs[i]);
  
@@@ -1340,9 -1340,6 +1340,9 @@@ retry_journal
        }
  
        if (ret) {
 +              bool extended = (pos + len > inode->i_size) &&
 +                              !ext4_verity_in_progress(inode);
 +
                unlock_page(page);
                /*
                 * __block_write_begin may have instantiated a few blocks
                 * Add inode to orphan list in case we crash before
                 * truncate finishes
                 */
 -              if (pos + len > inode->i_size && ext4_can_truncate(inode))
 +              if (extended && ext4_can_truncate(inode))
                        ext4_orphan_add(handle, inode);
  
                ext4_journal_stop(handle);
 -              if (pos + len > inode->i_size) {
 +              if (extended) {
                        ext4_truncate_failed_write(inode);
                        /*
                         * If truncate failed early the inode might
@@@ -1409,7 -1406,6 +1409,7 @@@ static int ext4_write_end(struct file *
        int ret = 0, ret2;
        int i_size_changed = 0;
        int inline_data = ext4_has_inline_data(inode);
 +      bool verity = ext4_verity_in_progress(inode);
  
        trace_ext4_write_end(inode, pos, len, copied);
        if (inline_data) {
        /*
         * it's important to update i_size while still holding page lock:
         * page writeout could otherwise come in and zero beyond i_size.
 +       *
 +       * If FS_IOC_ENABLE_VERITY is running on this inode, then Merkle tree
 +       * blocks are being written past EOF, so skip the i_size update.
         */
 -      i_size_changed = ext4_update_inode_size(inode, pos + copied);
 +      if (!verity)
 +              i_size_changed = ext4_update_inode_size(inode, pos + copied);
        unlock_page(page);
        put_page(page);
  
 -      if (old_size < pos)
 +      if (old_size < pos && !verity)
                pagecache_isize_extended(inode, old_size, pos);
        /*
         * Don't mark the inode dirty under page lock. First, it unnecessarily
        if (i_size_changed || inline_data)
                ext4_mark_inode_dirty(handle, inode);
  
 -      if (pos + len > inode->i_size && ext4_can_truncate(inode))
 +      if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
                /* if we have allocated more blocks and copied
                 * less. We will have blocks allocated outside
                 * inode->i_size. So truncate them
@@@ -1458,7 -1450,7 +1458,7 @@@ errout
        if (!ret)
                ret = ret2;
  
 -      if (pos + len > inode->i_size) {
 +      if (pos + len > inode->i_size && !verity) {
                ext4_truncate_failed_write(inode);
                /*
                 * If truncate failed early the inode might still be
@@@ -1519,7 -1511,6 +1519,7 @@@ static int ext4_journalled_write_end(st
        unsigned from, to;
        int size_changed = 0;
        int inline_data = ext4_has_inline_data(inode);
 +      bool verity = ext4_verity_in_progress(inode);
  
        trace_ext4_journalled_write_end(inode, pos, len, copied);
        from = pos & (PAGE_SIZE - 1);
                if (!partial)
                        SetPageUptodate(page);
        }
 -      size_changed = ext4_update_inode_size(inode, pos + copied);
 +      if (!verity)
 +              size_changed = ext4_update_inode_size(inode, pos + copied);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
        EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
        unlock_page(page);
        put_page(page);
  
 -      if (old_size < pos)
 +      if (old_size < pos && !verity)
                pagecache_isize_extended(inode, old_size, pos);
  
        if (size_changed || inline_data) {
                        ret = ret2;
        }
  
 -      if (pos + len > inode->i_size && ext4_can_truncate(inode))
 +      if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode))
                /* if we have allocated more blocks and copied
                 * less. We will have blocks allocated outside
                 * inode->i_size. So truncate them
@@@ -1576,7 -1566,7 +1576,7 @@@ errout
        ret2 = ext4_journal_stop(handle);
        if (!ret)
                ret = ret2;
 -      if (pos + len > inode->i_size) {
 +      if (pos + len > inode->i_size && !verity) {
                ext4_truncate_failed_write(inode);
                /*
                 * If truncate failed early the inode might still be
@@@ -1656,49 -1646,6 +1656,6 @@@ void ext4_da_release_space(struct inod
        dquot_release_reservation_block(inode, EXT4_C2B(sbi, to_free));
  }
  
- static void ext4_da_page_release_reservation(struct page *page,
-                                            unsigned int offset,
-                                            unsigned int length)
- {
-       int contiguous_blks = 0;
-       struct buffer_head *head, *bh;
-       unsigned int curr_off = 0;
-       struct inode *inode = page->mapping->host;
-       unsigned int stop = offset + length;
-       ext4_fsblk_t lblk;
-       BUG_ON(stop > PAGE_SIZE || stop < length);
-       head = page_buffers(page);
-       bh = head;
-       do {
-               unsigned int next_off = curr_off + bh->b_size;
-               if (next_off > stop)
-                       break;
-               if ((offset <= curr_off) && (buffer_delay(bh))) {
-                       contiguous_blks++;
-                       clear_buffer_delay(bh);
-               } else if (contiguous_blks) {
-                       lblk = page->index <<
-                              (PAGE_SHIFT - inode->i_blkbits);
-                       lblk += (curr_off >> inode->i_blkbits) -
-                               contiguous_blks;
-                       ext4_es_remove_blks(inode, lblk, contiguous_blks);
-                       contiguous_blks = 0;
-               }
-               curr_off = next_off;
-       } while ((bh = bh->b_this_page) != head);
-       if (contiguous_blks) {
-               lblk = page->index << (PAGE_SHIFT - inode->i_blkbits);
-               lblk += (curr_off >> inode->i_blkbits) - contiguous_blks;
-               ext4_es_remove_blks(inode, lblk, contiguous_blks);
-       }
- }
  /*
   * Delayed allocation stuff
   */
@@@ -1878,7 -1825,7 +1835,7 @@@ static int ext4_da_map_blocks(struct in
                  (unsigned long) map->m_lblk);
  
        /* Lookup extent status tree firstly */
-       if (ext4_es_lookup_extent(inode, iblock, &es)) {
+       if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) {
                if (ext4_es_is_hole(&es)) {
                        retval = 0;
                        down_read(&EXT4_I(inode)->i_data_sem);
@@@ -2172,8 -2119,7 +2129,8 @@@ static int ext4_writepage(struct page *
  
        trace_ext4_writepage(page);
        size = i_size_read(inode);
 -      if (page->index == size >> PAGE_SHIFT)
 +      if (page->index == size >> PAGE_SHIFT &&
 +          !ext4_verity_in_progress(inode))
                len = size & ~PAGE_MASK;
        else
                len = PAGE_SIZE;
@@@ -2257,8 -2203,7 +2214,8 @@@ static int mpage_submit_page(struct mpa
         * after page tables are updated.
         */
        size = i_size_read(mpd->inode);
 -      if (page->index == size >> PAGE_SHIFT)
 +      if (page->index == size >> PAGE_SHIFT &&
 +          !ext4_verity_in_progress(mpd->inode))
                len = size & ~PAGE_MASK;
        else
                len = PAGE_SIZE;
@@@ -2357,9 -2302,6 +2314,9 @@@ static int mpage_process_page_bufs(stru
        ext4_lblk_t blocks = (i_size_read(inode) + i_blocksize(inode) - 1)
                                                        >> inode->i_blkbits;
  
 +      if (ext4_verity_in_progress(inode))
 +              blocks = EXT_MAX_BLOCKS;
 +
        do {
                BUG_ON(buffer_locked(bh));
  
@@@ -2800,15 -2742,6 +2757,6 @@@ static int ext4_writepages(struct addre
                goto out_writepages;
        }
  
-       if (ext4_should_dioread_nolock(inode)) {
-               /*
-                * We may need to convert up to one extent per block in
-                * the page and we may dirty the inode.
-                */
-               rsv_blocks = 1 + ext4_chunk_trans_blocks(inode,
-                                               PAGE_SIZE >> inode->i_blkbits);
-       }
        /*
         * If we have inline data and arrive here, it means that
         * we will soon create the block for the 1st page, so
                ext4_journal_stop(handle);
        }
  
+       if (ext4_should_dioread_nolock(inode)) {
+               /*
+                * We may need to convert up to one extent per block in
+                * the page and we may dirty the inode.
+                */
+               rsv_blocks = 1 + ext4_chunk_trans_blocks(inode,
+                                               PAGE_SIZE >> inode->i_blkbits);
+       }
        if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
                range_whole = 1;
  
@@@ -3076,8 -3018,8 +3033,8 @@@ static int ext4_da_write_begin(struct f
  
        index = pos >> PAGE_SHIFT;
  
 -      if (ext4_nonda_switch(inode->i_sb) ||
 -          S_ISLNK(inode->i_mode)) {
 +      if (ext4_nonda_switch(inode->i_sb) || S_ISLNK(inode->i_mode) ||
 +          ext4_verity_in_progress(inode)) {
                *fsdata = (void *)FALL_BACK_TO_NONDELALLOC;
                return ext4_write_begin(file, mapping, pos,
                                        len, flags, pagep, fsdata);
@@@ -3242,24 -3184,6 +3199,6 @@@ static int ext4_da_write_end(struct fil
        return ret ? ret : copied;
  }
  
- static void ext4_da_invalidatepage(struct page *page, unsigned int offset,
-                                  unsigned int length)
- {
-       /*
-        * Drop reserved blocks
-        */
-       BUG_ON(!PageLocked(page));
-       if (!page_has_buffers(page))
-               goto out;
-       ext4_da_page_release_reservation(page, offset, length);
- out:
-       ext4_invalidatepage(page, offset, length);
-       return;
- }
  /*
   * Force all delayed allocation blocks to be allocated for a given inode.
   */
@@@ -3912,8 -3836,6 +3851,8 @@@ static ssize_t ext4_direct_IO(struct ki
        if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
                return 0;
  #endif
 +      if (fsverity_active(inode))
 +              return 0;
  
        /*
         * If we are doing data journalling we don't support O_DIRECT
@@@ -4002,7 -3924,7 +3941,7 @@@ static const struct address_space_opera
        .write_end              = ext4_da_write_end,
        .set_page_dirty         = ext4_set_page_dirty,
        .bmap                   = ext4_bmap,
-       .invalidatepage         = ext4_da_invalidatepage,
+       .invalidatepage         = ext4_invalidatepage,
        .releasepage            = ext4_releasepage,
        .direct_IO              = ext4_direct_IO,
        .migratepage            = buffer_migrate_page,
@@@ -4314,6 -4236,15 +4253,15 @@@ int ext4_punch_hole(struct inode *inode
  
        trace_ext4_punch_hole(inode, offset, length, 0);
  
+       ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
+       if (ext4_has_inline_data(inode)) {
+               down_write(&EXT4_I(inode)->i_mmap_sem);
+               ret = ext4_convert_inline_data(inode);
+               up_write(&EXT4_I(inode)->i_mmap_sem);
+               if (ret)
+                       return ret;
+       }
        /*
         * Write out all dirty pages to avoid race conditions
         * Then release them.
@@@ -4603,6 -4534,7 +4551,6 @@@ static int __ext4_get_inode_loc(struct 
        struct buffer_head      *bh;
        struct super_block      *sb = inode->i_sb;
        ext4_fsblk_t            block;
 -      struct blk_plug         plug;
        int                     inodes_per_block, inode_offset;
  
        iloc->bh = NULL;
@@@ -4691,6 -4623,7 +4639,6 @@@ make_io
                 * If we need to do any I/O, try to pre-readahead extra
                 * blocks from the inode table.
                 */
 -              blk_start_plug(&plug);
                if (EXT4_SB(sb)->s_inode_readahead_blks) {
                        ext4_fsblk_t b, end, table;
                        unsigned num;
                get_bh(bh);
                bh->b_end_io = end_buffer_read_sync;
                submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
 -              blk_finish_plug(&plug);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        EXT4_ERROR_INODE_BLOCK(inode, block,
@@@ -4753,8 -4687,6 +4701,8 @@@ static bool ext4_should_use_dax(struct 
                return false;
        if (ext4_test_inode_flag(inode, EXT4_INODE_ENCRYPT))
                return false;
 +      if (ext4_test_inode_flag(inode, EXT4_INODE_VERITY))
 +              return false;
        return true;
  }
  
@@@ -4779,11 -4711,9 +4727,11 @@@ void ext4_set_inode_flags(struct inode 
                new_fl |= S_ENCRYPTED;
        if (flags & EXT4_CASEFOLD_FL)
                new_fl |= S_CASEFOLD;
 +      if (flags & EXT4_VERITY_FL)
 +              new_fl |= S_VERITY;
        inode_set_flags(inode, new_fl,
                        S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX|
 -                      S_ENCRYPTED|S_CASEFOLD);
 +                      S_ENCRYPTED|S_CASEFOLD|S_VERITY);
  }
  
  static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode,
@@@ -5137,6 -5067,9 +5085,9 @@@ struct inode *__ext4_iget(struct super_
                                 "iget: bogus i_mode (%o)", inode->i_mode);
                goto bad_inode;
        }
+       if (IS_CASEFOLDED(inode) && !ext4_has_feature_casefold(inode->i_sb))
+               ext4_error_inode(inode, function, line, 0,
+                                "casefold flag without casefold feature");
        brelse(iloc.bh);
  
        unlock_new_inode(inode);
@@@ -5573,10 -5506,6 +5524,10 @@@ int ext4_setattr(struct dentry *dentry
        if (error)
                return error;
  
 +      error = fsverity_prepare_setattr(dentry, attr);
 +      if (error)
 +              return error;
 +
        if (is_quota_modification(inode, attr)) {
                error = dquot_initialize(inode);
                if (error)
diff --combined fs/ext4/ioctl.c
index 5444d49cbf09de4a44861088c90b2c33a1b144b0,d6242b7b8718202fdff3136efd398d9a427f4dc4..0b7f316fd30f41391f9587487dbc41e204d5efae
@@@ -745,6 -745,74 +745,74 @@@ static void ext4_fill_fsxattr(struct in
                fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
  }
  
+ /* copied from fs/ioctl.c */
+ static int fiemap_check_ranges(struct super_block *sb,
+                              u64 start, u64 len, u64 *new_len)
+ {
+       u64 maxbytes = (u64) sb->s_maxbytes;
+       *new_len = len;
+       if (len == 0)
+               return -EINVAL;
+       if (start > maxbytes)
+               return -EFBIG;
+       /*
+        * Shrink request scope to what the fs can actually handle.
+        */
+       if (len > maxbytes || (maxbytes - len) < start)
+               *new_len = maxbytes - start;
+       return 0;
+ }
+ /* So that the fiemap access checks can't overflow on 32 bit machines. */
+ #define FIEMAP_MAX_EXTENTS    (UINT_MAX / sizeof(struct fiemap_extent))
+ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
+ {
+       struct fiemap fiemap;
+       struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
+       struct fiemap_extent_info fieinfo = { 0, };
+       struct inode *inode = file_inode(filp);
+       struct super_block *sb = inode->i_sb;
+       u64 len;
+       int error;
+       if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
+               return -EFAULT;
+       if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
+               return -EINVAL;
+       error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
+                                   &len);
+       if (error)
+               return error;
+       fieinfo.fi_flags = fiemap.fm_flags;
+       fieinfo.fi_extents_max = fiemap.fm_extent_count;
+       fieinfo.fi_extents_start = ufiemap->fm_extents;
+       if (fiemap.fm_extent_count != 0 &&
+           !access_ok(fieinfo.fi_extents_start,
+                      fieinfo.fi_extents_max * sizeof(struct fiemap_extent)))
+               return -EFAULT;
+       if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
+               filemap_write_and_wait(inode->i_mapping);
+       error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start, len);
+       fiemap.fm_flags = fieinfo.fi_flags;
+       fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
+       if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
+               error = -EFAULT;
+       return error;
+ }
  long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
        struct inode *inode = file_inode(filp);
@@@ -1113,35 -1181,35 +1181,62 @@@ resizefs_out
  #endif
        }
        case EXT4_IOC_GET_ENCRYPTION_POLICY:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
                return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
  
 +      case FS_IOC_GET_ENCRYPTION_POLICY_EX:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
 +              return fscrypt_ioctl_get_policy_ex(filp, (void __user *)arg);
 +
 +      case FS_IOC_ADD_ENCRYPTION_KEY:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
 +              return fscrypt_ioctl_add_key(filp, (void __user *)arg);
 +
 +      case FS_IOC_REMOVE_ENCRYPTION_KEY:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
 +              return fscrypt_ioctl_remove_key(filp, (void __user *)arg);
 +
 +      case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
 +              return fscrypt_ioctl_remove_key_all_users(filp,
 +                                                        (void __user *)arg);
 +      case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
 +              if (!ext4_has_feature_encrypt(sb))
 +                      return -EOPNOTSUPP;
 +              return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
 +
+       case EXT4_IOC_CLEAR_ES_CACHE:
+       {
+               if (!inode_owner_or_capable(inode))
+                       return -EACCES;
+               ext4_clear_inode_es(inode);
+               return 0;
+       }
+       case EXT4_IOC_GETSTATE:
+       {
+               __u32   state = 0;
+               if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED))
+                       state |= EXT4_STATE_FLAG_EXT_PRECACHED;
+               if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
+                       state |= EXT4_STATE_FLAG_NEW;
+               if (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
+                       state |= EXT4_STATE_FLAG_NEWENTRY;
+               if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE))
+                       state |= EXT4_STATE_FLAG_DA_ALLOC_CLOSE;
+               return put_user(state, (__u32 __user *) arg);
+       }
+       case EXT4_IOC_GET_ES_CACHE:
+               return ext4_ioctl_get_es_cache(filp, arg);
        case EXT4_IOC_FSGETXATTR:
        {
                struct fsxattr fa;
        }
        case EXT4_IOC_SHUTDOWN:
                return ext4_shutdown(sb, arg);
 +
 +      case FS_IOC_ENABLE_VERITY:
 +              if (!ext4_has_feature_verity(sb))
 +                      return -EOPNOTSUPP;
 +              return fsverity_ioctl_enable(filp, (const void __user *)arg);
 +
 +      case FS_IOC_MEASURE_VERITY:
 +              if (!ext4_has_feature_verity(sb))
 +                      return -EOPNOTSUPP;
 +              return fsverity_ioctl_measure(filp, (void __user *)arg);
 +
        default:
                return -ENOTTY;
        }
@@@ -1269,15 -1326,11 +1364,18 @@@ long ext4_compat_ioctl(struct file *fil
        case EXT4_IOC_SET_ENCRYPTION_POLICY:
        case EXT4_IOC_GET_ENCRYPTION_PWSALT:
        case EXT4_IOC_GET_ENCRYPTION_POLICY:
 +      case FS_IOC_GET_ENCRYPTION_POLICY_EX:
 +      case FS_IOC_ADD_ENCRYPTION_KEY:
 +      case FS_IOC_REMOVE_ENCRYPTION_KEY:
 +      case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
 +      case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
        case EXT4_IOC_SHUTDOWN:
        case FS_IOC_GETFSMAP:
 +      case FS_IOC_ENABLE_VERITY:
 +      case FS_IOC_MEASURE_VERITY:
+       case EXT4_IOC_CLEAR_ES_CACHE:
+       case EXT4_IOC_GETSTATE:
+       case EXT4_IOC_GET_ES_CACHE:
                break;
        default:
                return -ENOIOCTLCMD;
diff --combined fs/ext4/super.c
index 3db5f17228b7691f9208252e937c16349d486e12,7310facffa9d7a9d7bcb24d2a051714309f8a49c..dd654e53ba3d982d99c05b2336dd4de9132b0978
@@@ -1107,9 -1107,6 +1107,9 @@@ static int ext4_drop_inode(struct inod
  {
        int drop = generic_drop_inode(inode);
  
 +      if (!drop)
 +              drop = fscrypt_drop_inode(inode);
 +
        trace_ext4_drop_inode(inode, drop);
        return drop;
  }
@@@ -1182,7 -1179,6 +1182,7 @@@ void ext4_clear_inode(struct inode *ino
                EXT4_I(inode)->jinode = NULL;
        }
        fscrypt_put_encryption_info(inode);
 +      fsverity_cleanup_inode(inode);
  }
  
  static struct inode *ext4_nfs_get_inode(struct super_block *sb,
@@@ -1878,6 -1874,13 +1878,13 @@@ static int handle_mount_opt(struct supe
        } else if (token == Opt_commit) {
                if (arg == 0)
                        arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
+               else if (arg > INT_MAX / HZ) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Invalid commit interval %d, "
+                                "must be smaller than %d",
+                                arg, INT_MAX / HZ);
+                       return -1;
+               }
                sbi->s_commit_interval = HZ * arg;
        } else if (token == Opt_debug_want_extra_isize) {
                sbi->s_want_extra_isize = arg;
@@@ -4039,21 -4042,8 +4046,21 @@@ static int ext4_fill_super(struct super
                               sbi->s_inode_size);
                        goto failed_mount;
                }
 -              if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE)
 -                      sb->s_time_gran = 1 << (EXT4_EPOCH_BITS - 2);
 +              /*
 +               * i_atime_extra is the last extra field available for [acm]times in
 +               * struct ext4_inode. Checking for that field should suffice to ensure
 +               * we have extra space for all three.
 +               */
 +              if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
 +                      sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
 +                      sb->s_time_gran = 1;
 +                      sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
 +              } else {
 +                      sb->s_time_gran = NSEC_PER_SEC;
 +                      sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
 +              }
 +
 +              sb->s_time_min = EXT4_TIMESTAMP_MIN;
        }
  
        sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
  #ifdef CONFIG_FS_ENCRYPTION
        sb->s_cop = &ext4_cryptops;
  #endif
 +#ifdef CONFIG_FS_VERITY
 +      sb->s_vop = &ext4_verityops;
 +#endif
  #ifdef CONFIG_QUOTA
        sb->dq_op = &ext4_quota_operations;
        if (ext4_has_feature_quota(sb))
@@@ -4439,11 -4426,6 +4446,11 @@@ no_journal
                goto failed_mount_wq;
        }
  
 +      if (ext4_has_feature_verity(sb) && blocksize != PAGE_SIZE) {
 +              ext4_msg(sb, KERN_ERR, "Unsupported blocksize for fs-verity");
 +              goto failed_mount_wq;
 +      }
 +
        if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
            !ext4_has_feature_encrypt(sb)) {
                ext4_set_feature_encrypt(sb);
@@@ -6119,10 -6101,6 +6126,10 @@@ static int __init ext4_init_fs(void
                return err;
  
        err = ext4_init_pending();
 +      if (err)
 +              goto out7;
 +
 +      err = ext4_init_post_read_processing();
        if (err)
                goto out6;
  
@@@ -6164,10 -6142,8 +6171,10 @@@ out3
  out4:
        ext4_exit_pageio();
  out5:
 -      ext4_exit_pending();
 +      ext4_exit_post_read_processing();
  out6:
 +      ext4_exit_pending();
 +out7:
        ext4_exit_es();
  
        return err;
@@@ -6184,7 -6160,6 +6191,7 @@@ static void __exit ext4_exit_fs(void
        ext4_exit_sysfs();
        ext4_exit_system_zone();
        ext4_exit_pageio();
 +      ext4_exit_post_read_processing();
        ext4_exit_es();
        ext4_exit_pending();
  }