ext4_journal: try to read jbd superblock when loading jbd.
[lwext4.git] / lwext4 / ext4_blockdev.c
index 57e8f895e19273aa851d89faccf841bf09b7b1d5..1b0e2b23c534563e56d5fc501af23d9b6775ca7a 100644 (file)
@@ -85,11 +85,9 @@ int ext4_block_fini(struct ext4_blockdev *bdev)
        return bdev->close(bdev);
 }
 
-int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
-                  uint64_t lba)
+int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b,
+                         uint64_t lba)
 {
-       uint64_t pba;
-       uint32_t pb_cnt;
        uint32_t i;
        bool is_new;
        int r;
@@ -149,14 +147,27 @@ int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
        if (r != EOK)
                return r;
 
-       if (!is_new) {
-               /*Block is in cache. Read from physical device is not required*/
-               return EOK;
-       }
-
        if (!b->data)
                return ENOMEM;
 
+       return EOK;
+}
+
+int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
+                  uint64_t lba)
+{
+       uint64_t pba;
+       uint32_t pb_cnt;
+       int r = ext4_block_get_noread(bdev, b, lba);
+       if (r != EOK)
+               return r;
+
+       if (b->uptodate) {
+               /* Data in the cache is up-to-date.
+                * Reading from physical device is not required */
+               return EOK;
+       }
+
        pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
        pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
 
@@ -168,6 +179,10 @@ int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
                return r;
        }
 
+       /* Mark buffer up-to-date, since
+        * fresh data is read from physical device just now. */
+       ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+       b->uptodate = true;
        bdev->bread_ctr++;
        return EOK;
 }
@@ -183,11 +198,18 @@ int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
        if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
                return EIO;
 
+       /*Buffer is not marked dirty and is stale*/
+       if (!b->uptodate && !b->dirty)
+               ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
+
        /*No need to write.*/
-       if (!b->dirty && !bdev->bc->dirty[b->cache_id]) {
+       if (!b->dirty &&
+           !ext4_bcache_test_flag(bdev->bc, b->cache_id, BC_DIRTY)) {
                ext4_bcache_free(bdev->bc, b, 0);
                return EOK;
        }
+       /* Data is valid, so mark buffer up-to-date. */
+       ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_UPTODATE);
 
        /*Free cache delay mode*/
        if (bdev->cache_write_back) {
@@ -197,7 +219,7 @@ int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
        }
 
        if (bdev->bc->refctr[b->cache_id] > 1) {
-               bdev->bc->dirty[b->cache_id] = true;
+               ext4_bcache_set_flag(bdev->bc, b->cache_id, BC_DIRTY);
                return ext4_bcache_free(bdev->bc, b, 0);
        }
 
@@ -205,9 +227,10 @@ int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
        pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
 
        r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
-       bdev->bc->dirty[b->cache_id] = false;
+       ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_DIRTY);
        if (r != EOK) {
                b->dirty = false;
+               ext4_bcache_clear_flag(bdev->bc, b->cache_id, BC_UPTODATE);
                ext4_bcache_free(bdev->bc, b, 0);
                return r;
        }
@@ -280,7 +303,6 @@ int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off,
                                    : (bdev->ph_bsize - unalg);
 
                r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
-
                if (r != EOK)
                        return r;
 
@@ -298,7 +320,6 @@ int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off,
        /*Aligned data*/
        blen = len / bdev->ph_bsize;
        r = bdev->bwrite(bdev, p, block_idx, blen);
-
        if (r != EOK)
                return r;
 
@@ -316,7 +337,6 @@ int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off,
                memcpy(bdev->ph_bbuf, p, len);
 
                r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
-
                if (r != EOK)
                        return r;
        }
@@ -369,7 +389,6 @@ int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf,
        blen = len / bdev->ph_bsize;
 
        r = bdev->bread(bdev, p, block_idx, blen);
-
        if (r != EOK)
                return r;
 
@@ -401,33 +420,35 @@ int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off)
        if (!on_off && bdev->cache_write_back)
                bdev->cache_write_back--;
 
+
+       if (bdev->cache_write_back)
+               return EOK;
+
        /*Flush all delayed cache blocks*/
-       if (!bdev->cache_write_back) {
-               for (i = 0; i < bdev->bc->cnt; ++i) {
+       for (i = 0; i < bdev->bc->cnt; ++i) {
 
-                       /*Check if buffer free was delayed.*/
-                       if (!bdev->bc->free_delay[i])
-                               continue;
+               /*Check if buffer free was delayed.*/
+               if (!bdev->bc->free_delay[i])
+                       continue;
 
-                       /*Check reference counter.*/
-                       if (bdev->bc->refctr[i])
-                               continue;
+               /*Check reference counter.*/
+               if (bdev->bc->refctr[i])
+                       continue;
 
-                       /*Buffer free was delayed and have no reference. Flush
-                        * it.*/
-                       r = ext4_blocks_set_direct(
-                           bdev, bdev->bc->data + bdev->bc->itemsize * i,
-                           bdev->bc->lba[i], 1);
-                       if (r != EOK)
-                               return r;
+               /*Buffer free was delayed and have no reference. Flush
+                * it.*/
+               r = ext4_blocks_set_direct(bdev, bdev->bc->data +
+                               bdev->bc->itemsize * i, bdev->bc->lba[i], 1);
+               if (r != EOK)
+                       return r;
 
-                       /*No delayed anymore*/
-                       bdev->bc->free_delay[i] = 0;
+               /*No delayed anymore*/
+               bdev->bc->free_delay[i] = 0;
 
-                       /*Reduce reference counter*/
-                       bdev->bc->ref_blocks--;
-               }
+               /*Reduce reference counter*/
+               bdev->bc->ref_blocks--;
        }
+
        return EOK;
 }