struct extent_buffer *eb = bbio->private;
        struct btrfs_fs_info *fs_info = eb->fs_info;
        u64 found_start = btrfs_header_bytenr(eb);
+       u64 last_trans;
        u8 result[BTRFS_CSUM_SIZE];
        int ret;
 
         * Also check the generation, the eb reached here must be newer than
         * last committed. Or something seriously wrong happened.
         */
-       if (unlikely(btrfs_header_generation(eb) <= fs_info->last_trans_committed)) {
+       last_trans = btrfs_get_last_trans_committed(fs_info);
+       if (unlikely(btrfs_header_generation(eb) <= last_trans)) {
                ret = -EUCLEAN;
                btrfs_err(fs_info,
                        "block=%llu bad generation, have %llu expect > %llu",
-                         eb->start, btrfs_header_generation(eb),
-                         fs_info->last_trans_committed);
+                         eb->start, btrfs_header_generation(eb), last_trans);
                goto error;
        }
        write_extent_buffer(eb, result, 0, fs_info->csum_size);
 
                /* All successful */
                fs_info->generation = btrfs_header_generation(tree_root->node);
-               fs_info->last_trans_committed = fs_info->generation;
+               btrfs_set_last_trans_committed(fs_info, fs_info->generation);
                fs_info->last_reloc_trans = 0;
 
                /* Always begin writing backup roots after the one being used */
 
         * and for a fast fsync we don't wait for that, we only wait for the
         * writeback to complete.
         */
-       if (inode->last_trans <= fs_info->last_trans_committed &&
+       if (inode->last_trans <= btrfs_get_last_trans_committed(fs_info) &&
            (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags) ||
             list_empty(&ctx->ordered_extents)))
                return true;
 
         * Should always be updated using btrfs_set_fs_generation().
         */
        u64 generation;
+       /*
+        * Always use btrfs_get_last_trans_committed() and
+        * btrfs_set_last_trans_committed() to read and update this field.
+        */
        u64 last_trans_committed;
        /*
         * Generation of the last transaction used for block group relocation
        WRITE_ONCE(fs_info->generation, gen);
 }
 
+static inline u64 btrfs_get_last_trans_committed(const struct btrfs_fs_info *fs_info)
+{
+       return READ_ONCE(fs_info->last_trans_committed);
+}
+
+static inline void btrfs_set_last_trans_committed(struct btrfs_fs_info *fs_info, u64 gen)
+{
+       WRITE_ONCE(fs_info->last_trans_committed, gen);
+}
+
 static inline void btrfs_set_last_root_drop_gen(struct btrfs_fs_info *fs_info,
                                                u64 gen)
 {
 
                        return PTR_ERR(trans);
 
                /* No running transaction, don't bother */
-               transid = root->fs_info->last_trans_committed;
+               transid = btrfs_get_last_trans_committed(root->fs_info);
                goto out;
        }
        transid = trans->transid;
 
        if (scrub_dev->fs_devices != fs_info->fs_devices)
                gen = scrub_dev->generation;
        else
-               gen = fs_info->last_trans_committed;
+               gen = btrfs_get_last_trans_committed(fs_info);
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                bytenr = btrfs_sb_offset(i);
 
 {
        struct btrfs_fs_info *fs_info = dev->fs_info;
        struct btrfs_super_block *sb;
+       u64 last_trans;
        u16 csum_type;
        int ret = 0;
 
        if (ret < 0)
                goto out;
 
-       if (btrfs_super_generation(sb) != fs_info->last_trans_committed) {
+       last_trans = btrfs_get_last_trans_committed(fs_info);
+       if (btrfs_super_generation(sb) != last_trans) {
                btrfs_err(fs_info, "transid mismatch, has %llu expect %llu",
-                       btrfs_super_generation(sb),
-                       fs_info->last_trans_committed);
+                         btrfs_super_generation(sb), last_trans);
                ret = -EUCLEAN;
                goto out;
        }
 
        int ret = 0;
 
        if (transid) {
-               if (transid <= fs_info->last_trans_committed)
+               if (transid <= btrfs_get_last_trans_committed(fs_info))
                        goto out;
 
                /* find specified transaction */
                 * raced with btrfs_commit_transaction
                 */
                if (!cur_trans) {
-                       if (transid > fs_info->last_trans_committed)
+                       if (transid > btrfs_get_last_trans_committed(fs_info))
                                ret = -EINVAL;
                        goto out;
                }
        if (test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &cur_trans->flags))
                btrfs_clear_space_info_full(fs_info);
 
-       fs_info->last_trans_committed = cur_trans->transid;
+       btrfs_set_last_trans_committed(fs_info, cur_trans->transid);
        /*
         * We needn't acquire the lock here because there is no other task
         * which can change it.
 
         * So we only checks tree blocks which is read from disk, whose
         * generation <= fs_info->last_trans_committed.
         */
-       if (btrfs_header_generation(eb) > fs_info->last_trans_committed)
+       if (btrfs_header_generation(eb) > btrfs_get_last_trans_committed(fs_info))
                return 0;
 
        /* We have @first_key, so this @eb must have at least one item */