ext4_journal: forcibly flush data to disk when stop journalling.
[lwext4.git] / lwext4 / ext4_extent.c
index 84756135e504c1eec7e39ea389d5469555fe688b..d6f373bb0f5846afc3ed4cf1f539a3ecbcb8c7ba 100644 (file)
@@ -90,7 +90,7 @@ static uint32_t ext4_ext_block_csum(struct ext4_inode_ref *inode_ref,
                                     sizeof(ino_index));
                checksum = ext4_crc32c(checksum, &ino_gen,
                                     sizeof(ino_gen));
-               /* Finally calculate crc32 checksum against 
+               /* Finally calculate crc32 checksum against
                 * the entire extent block up to the checksum field */
                checksum = ext4_crc32c(checksum, eh,
                                EXT4_EXTENT_TAIL_OFFSET(eh));
@@ -101,16 +101,13 @@ static uint32_t ext4_ext_block_csum(struct ext4_inode_ref *inode_ref,
 #define ext4_ext_block_csum(...) 0
 #endif
 
-/*
- * BIG FAT NOTES:
- *       Currently we do not verify the checksum of extent
- *       (only the case in ext4_extent.c)
- */
-
 static void ext4_extent_block_csum_set(struct ext4_inode_ref *inode_ref,
                                       struct ext4_extent_header *eh)
 {
        struct ext4_extent_tail *tail;
+       if (!ext4_sb_feature_ro_com(&inode_ref->fs->sb,
+                                   EXT4_FRO_COM_METADATA_CSUM))
+               return;
 
        if (to_le16(eh->depth) < ext_depth(inode_ref->inode)) {
                tail = find_ext4_extent_tail(eh);
@@ -118,6 +115,30 @@ static void ext4_extent_block_csum_set(struct ext4_inode_ref *inode_ref,
        }
 }
 
+#if CONFIG_META_CSUM_ENABLE
+static bool
+ext4_extent_verify_block_csum(struct ext4_inode_ref *inode_ref,
+                             struct ext4_block *block)
+{
+       struct ext4_extent_header *eh;
+       struct ext4_extent_tail *tail;
+       eh = (struct ext4_extent_header *)block->data;
+       if (!ext4_sb_feature_ro_com(&inode_ref->fs->sb,
+                                   EXT4_FRO_COM_METADATA_CSUM))
+               return true;
+
+       if (to_le16(eh->depth) < ext_depth(inode_ref->inode)) {
+               tail = find_ext4_extent_tail(eh);
+               return tail->et_checksum ==
+                       to_le32(ext4_ext_block_csum(inode_ref, eh));
+       }
+
+       return true;
+}
+#else
+#define ext4_extent_verify_block_csum(...) true
+#endif
+
 /**@brief Binary search in extent index node.
  * @param header Extent header of index node
  * @param index  Output value - found index will be set here
@@ -239,6 +260,13 @@ ext4_extent_find_block(struct ext4_inode_ref *inode_ref, uint32_t iblock,
                int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);
                if (rc != EOK)
                        return rc;
+               if (!ext4_extent_verify_block_csum(inode_ref,
+                                                  &block)) {
+                       ext4_dbg(DEBUG_EXTENT,
+                                DBG_WARN "Extent block checksum failed."
+                                "Blocknr: %" PRIu64"\n",
+                                child);
+               }
 
                header = (struct ext4_extent_header *)block.data;
        }
@@ -318,6 +346,14 @@ static int ext4_extent_find_extent(struct ext4_inode_ref *inode_ref,
                if (rc != EOK)
                        goto cleanup;
 
+               if (!ext4_extent_verify_block_csum(inode_ref,
+                                                  &block)) {
+                       ext4_dbg(DEBUG_EXTENT,
+                                DBG_WARN "Extent block checksum failed."
+                                "Blocknr: %" PRIu64"\n",
+                                fblock);
+               }
+
                pos++;
 
                eh = (struct ext4_extent_header *)block.data;
@@ -387,6 +423,14 @@ static int ext4_extent_release_branch(struct ext4_inode_ref *inode_ref,
        if (rc != EOK)
                return rc;
 
+       if (!ext4_extent_verify_block_csum(inode_ref,
+                               &block)) {
+               ext4_dbg(DEBUG_EXTENT,
+                        DBG_WARN "Extent block checksum failed."
+                        "Blocknr: %" PRIu64"\n",
+                        fblock);
+       }
+
        struct ext4_extent_header *header = (void *)block.data;
 
        if (ext4_extent_header_get_depth(header)) {
@@ -490,7 +534,7 @@ int ext4_extent_remove_space(struct ext4_inode_ref *inode_ref, ext4_lblk_t from,
 
        ext4_extent_header_set_entries_count(path_ptr->header, entries);
        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-       path_ptr->block.dirty = true;
+       ext4_bcache_set_dirty(path_ptr->block.buf);
 
        /* If leaf node is empty, parent entry must be modified */
        bool remove_parent_record = false;
@@ -532,7 +576,7 @@ int ext4_extent_remove_space(struct ext4_inode_ref *inode_ref, ext4_lblk_t from,
 
                ext4_extent_header_set_entries_count(path_ptr->header, entries);
                ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-               path_ptr->block.dirty = true;
+               ext4_bcache_set_dirty(path_ptr->block.buf);
 
                /* Free the node if it is empty */
                if ((entries == 0) && (path_ptr != path)) {
@@ -607,7 +651,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
 
                        struct ext4_block block;
                        rc =
-                           ext4_block_get(inode_ref->fs->bdev, &block, fblock);
+                           ext4_block_get_noread(inode_ref->fs->bdev, &block, fblock);
                        if (rc != EOK) {
                                ext4_balloc_free_block(inode_ref, fblock);
                                return rc;
@@ -660,7 +704,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
                        ext4_extent_header_set_generation(path_ptr->header, 0);
 
                        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-                       path_ptr->block.dirty = true;
+                       ext4_bcache_set_dirty(path_ptr->block.buf);
 
                        /* Jump to the preceding item */
                        path_ptr--;
@@ -686,7 +730,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
                        ext4_extent_header_set_entries_count(path_ptr->header,
                                                             entries + 1);
                        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-                       path_ptr->block.dirty = true;
+                       ext4_bcache_set_dirty(path_ptr->block.buf);
 
                        /* No more splitting needed */
                        return EOK;
@@ -711,7 +755,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
                        return rc;
 
                struct ext4_block block;
-               rc = ext4_block_get(inode_ref->fs->bdev, &block, new_fblock);
+               rc = ext4_block_get_noread(inode_ref->fs->bdev, &block, new_fblock);
                if (rc != EOK)
                        return rc;
 
@@ -769,7 +813,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
                                                         limit);
 
                ext4_extent_block_csum_set(inode_ref, old_root->header);
-               old_root->block.dirty = true;
+               ext4_bcache_set_dirty(old_root->block.buf);
 
                /* Re-initialize new root metadata */
                new_root->depth = root_depth + 1;
@@ -787,7 +831,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
 
                /* Since new_root belongs to on-disk inode,
                 * we don't do checksum here */
-               new_root->block.dirty = true;
+               ext4_bcache_set_dirty(new_root->block.buf);
        } else {
                if (path->depth) {
                        path->index =
@@ -804,7 +848,7 @@ static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,
                ext4_extent_header_set_entries_count(path->header, entries + 1);
                /* Since new_root belongs to on-disk inode,
                 * we don't do checksum here */
-               path->block.dirty = true;
+               ext4_bcache_set_dirty(path->block.buf);
        }
 
        return EOK;
@@ -884,7 +928,7 @@ ext4_extent_append_block(struct ext4_inode_ref *inode_ref, uint32_t *iblock,
                        }
 
                        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-                       path_ptr->block.dirty = true;
+                       ext4_bcache_set_dirty(path_ptr->block.buf);
 
                        goto finish;
                } else {
@@ -926,7 +970,7 @@ ext4_extent_append_block(struct ext4_inode_ref *inode_ref, uint32_t *iblock,
                        }
 
                        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-                       path_ptr->block.dirty = true;
+                       ext4_bcache_set_dirty(path_ptr->block.buf);
 
                        goto finish;
                }
@@ -967,7 +1011,7 @@ append_extent:
        }
 
        ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-       path_ptr->block.dirty = true;
+       ext4_bcache_set_dirty(path_ptr->block.buf);
 
 finish:
        /* Set return values */