return EIO;
ext4_dir_en_set_inode(res.dentry, parent->index);
- ext4_bcache_set_dirty(res.block.buf);
+ ext4_trans_set_block_dirty(res.block.buf);
r = ext4_dir_destroy_result(ch, &res);
if (r != EOK)
return r;
}
return r;
}
+ bd->fs = &mp->fs;
return r;
}
r = ext4_fs_fini(&mp->fs);
if (r != EOK)
- return r;
+ goto Finish;
mp->mounted = 0;
ext4_bcache_fini_dynamic(mp->fs.bdev->bc);
free(mp->fs.bdev->bc);
}
-
- return ext4_block_fini(mp->fs.bdev);
+ r = ext4_block_fini(mp->fs.bdev);
+Finish:
+ mp->fs.bdev->fs = NULL;
+ return r;
}
static struct ext4_mountpoint *ext4_get_mount(const char *path)
}
}
-int ext4_trans_get_write_access(struct ext4_fs *fs,
- struct ext4_block *block)
-{
- int r = EOK;
- if (fs->jbd_journal && fs->curr_trans) {
- struct jbd_journal *journal = fs->jbd_journal;
- struct jbd_trans *trans = fs->curr_trans;
- r = jbd_trans_get_access(journal, trans, block);
- }
- return r;
-}
-
-int ext4_trans_set_block_dirty(struct ext4_fs *fs,
- struct ext4_block *block)
-{
- int r = EOK;
- if (fs->jbd_journal && fs->curr_trans) {
- struct jbd_trans *trans = fs->curr_trans;
- r = jbd_trans_set_block_dirty(trans, block);
- }
- return r;
-}
-
int ext4_mount_point_stats(const char *mount_point,
struct ext4_mount_stats *stats)
{
Finish:
ext4_block_cache_write_back(mp->fs.bdev, 0);
+
+ if (r != EOK)
+ ext4_trans_abort(mp);
+ else
+ ext4_trans_stop(mp);
+
EXT4_MP_UNLOCK(mp);
return r;
}
return EINVAL;
EXT4_MP_LOCK(mp);
+ ext4_trans_start(mp);
+
r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
if (r != EOK)
goto Finish;
ext4_fs_put_xattr_ref(&xattr_ref);
ext4_fs_put_inode_ref(&inode_ref);
Finish:
+ if (r != EOK)
+ ext4_trans_abort(mp);
+ else
+ ext4_trans_stop(mp);
+
EXT4_MP_UNLOCK(mp);
return r;
}
return EINVAL;
EXT4_MP_LOCK(mp);
+ ext4_trans_start(mp);
+
r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
if (r != EOK)
goto Finish;
ext4_fs_put_xattr_ref(&xattr_ref);
ext4_fs_put_inode_ref(&inode_ref);
Finish:
+ if (r != EOK)
+ ext4_trans_abort(mp);
+ else
+ ext4_trans_stop(mp);
+
EXT4_MP_UNLOCK(mp);
return r;
* @return standard error code */
int ext4_umount(const char *mount_point);
+int ext4_journal_start(const char *mount_point);
+
+int ext4_journal_stop(const char *mount_point);
/**@brief Journal recovery.
* @param mount_point mount point
struct ext4_block bitmap_block;
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
+ rc = ext4_trans_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
if (rc != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return rc;
/* Modify bitmap */
ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
ext4_balloc_set_bitmap_csum(sb, bg, bitmap_block.data);
- ext4_bcache_set_dirty(bitmap_block.buf);
+ ext4_trans_set_block_dirty(bitmap_block.buf);
/* Release block with bitmap */
rc = ext4_block_set(fs->bdev, &bitmap_block);
bg_ref.dirty = true;
+ rc = ext4_trans_try_revoke_block(fs->bdev, baddr);
+ if (rc != EOK) {
+ bg_ref.dirty = false;
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
ext4_bcache_invalidate_lba(fs->bdev->bc, baddr, 1);
/* Release block group reference */
return ext4_fs_put_block_group_ref(&bg_ref);
ext4_fsblk_t bitmap_blk = ext4_bg_get_block_bitmap(bg, sb);
struct ext4_block blk;
- rc = ext4_block_get(fs->bdev, &blk, bitmap_blk);
+ rc = ext4_trans_block_get(fs->bdev, &blk, bitmap_blk);
if (rc != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return rc;
/* Modify bitmap */
ext4_bmap_bits_free(blk.data, idx_in_bg_first, free_cnt);
ext4_balloc_set_bitmap_csum(sb, bg, blk.data);
- ext4_bcache_set_dirty(blk.buf);
+ ext4_trans_set_block_dirty(blk.buf);
count -= free_cnt;
first += free_cnt;
bg_first++;
}
+ uint32_t i;
+ for (i = 0;i < count;i++) {
+ rc = ext4_trans_try_revoke_block(fs->bdev, first + i);
+ if (rc != EOK)
+ return rc;
+
+ }
+
ext4_bcache_invalidate_lba(fs->bdev->bc, first, count);
/*All blocks should be released*/
ext4_assert(count == 0);
/* Load block with bitmap */
bmp_blk_adr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
- r = ext4_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
+ r = ext4_trans_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
if (r != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return r;
ext4_bmap_bit_set(b.data, idx_in_bg);
ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
r = ext4_block_set(inode_ref->fs->bdev, &b);
if (r != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
ext4_bmap_bit_set(b.data, tmp_idx);
ext4_balloc_set_bitmap_csum(sb, bg, b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
r = ext4_block_set(inode_ref->fs->bdev, &b);
if (r != EOK)
return r;
if (r == EOK) {
ext4_bmap_bit_set(b.data, rel_blk_idx);
ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group, b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
r = ext4_block_set(inode_ref->fs->bdev, &b);
if (r != EOK)
return r;
/* Load block with bitmap */
bmp_blk_adr = ext4_bg_get_block_bitmap(bg, sb);
- r = ext4_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
+ r = ext4_trans_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
if (r != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return r;
if (r == EOK) {
ext4_bmap_bit_set(b.data, rel_blk_idx);
ext4_balloc_set_bitmap_csum(sb, bg, b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
r = ext4_block_set(inode_ref->fs->bdev, &b);
if (r != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
bmp_blk_addr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
struct ext4_block b;
- rc = ext4_block_get(fs->bdev, &b, bmp_blk_addr);
+ rc = ext4_trans_block_get(fs->bdev, &b, bmp_blk_addr);
if (rc != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return rc;
if (*free) {
ext4_bmap_bit_set(b.data, index_in_group);
ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group, b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
}
/* Release block with bitmap */
buf->lba = lba;
buf->data = data;
+ buf->bc = bc;
return buf;
}
/**@brief Reference count table*/
uint32_t refctr;
+ /**@brief The block cache this buffer belongs to. */
+ struct ext4_bcache *bc;
+
/**@brief Whether or not buffer is on dirty list.*/
bool on_dirty_list;
#include "ext4_config.h"
#include "ext4_bcache.h"
+#include "ext4_trans.h"
#include "ext4_debug.h"
#include <stdbool.h>
/**@brief Cache write back mode reference counter*/
uint32_t cache_write_back;
+
+ /**@brief The filesystem this block device belongs to. */
+ struct ext4_fs *fs;
};
/**@brief Static initialization of the block device.*/
if (r != EOK)
return r;
- r = ext4_block_get(bdev, &it->curr_blk, next_blk);
+ r = ext4_trans_block_get(bdev, &it->curr_blk, next_blk);
if (r != EOK) {
it->curr_blk.lb_id = 0;
return r;
return r;
struct ext4_block block;
- r = ext4_block_get(fs->bdev, &block, fblock);
+ r = ext4_trans_block_get(fs->bdev, &block, fblock);
if (r != EOK)
return r;
/* Load new block */
struct ext4_block b;
- r = ext4_block_get_noread(fs->bdev, &b, fblock);
+ r = ext4_trans_block_get_noread(fs->bdev, &b, fblock);
if (r != EOK)
return r;
}
ext4_dir_set_csum(parent, (void *)b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
r = ext4_block_set(fs->bdev, &b);
return r;
/* Load data block */
struct ext4_block b;
- r = ext4_block_get(parent->fs->bdev, &b, fblock);
+ r = ext4_trans_block_get(parent->fs->bdev, &b, fblock);
if (r != EOK)
return r;
ext4_dir_set_csum(parent,
(struct ext4_dir_en *)result.block.data);
- ext4_bcache_set_dirty(result.block.buf);
+ ext4_trans_set_block_dirty(result.block.buf);
return ext4_dir_destroy_result(parent, &result);
}
ext4_dir_write_entry(sb, start, rec_len, child, name,
name_len);
ext4_dir_set_csum(inode_ref, (void *)dst_blk->data);
- ext4_bcache_set_dirty(dst_blk->buf);
+ ext4_trans_set_block_dirty(dst_blk->buf);
return EOK;
}
ext4_dir_set_csum(inode_ref,
(void *)dst_blk->data);
- ext4_bcache_set_dirty(dst_blk->buf);
+ ext4_trans_set_block_dirty(dst_blk->buf);
return EOK;
}
}
return rc;
struct ext4_block block;
- rc = ext4_block_get_noread(dir->fs->bdev, &block, fblock);
+ rc = ext4_trans_block_get_noread(dir->fs->bdev, &block, fblock);
if (rc != EOK)
return rc;
}
struct ext4_block new_block;
- rc = ext4_block_get_noread(dir->fs->bdev, &new_block, fblock);
+ rc = ext4_trans_block_get_noread(dir->fs->bdev, &new_block, fblock);
if (rc != EOK) {
ext4_block_set(dir->fs->bdev, &block);
return rc;
ext4_dir_en_set_inode(be, 0);
- ext4_bcache_set_dirty(new_block.buf);
+ ext4_trans_set_block_dirty(new_block.buf);
rc = ext4_block_set(dir->fs->bdev, &new_block);
if (rc != EOK) {
ext4_block_set(dir->fs->bdev, &block);
ext4_dir_dx_entry_set_block(entry, iblock);
ext4_dir_set_dx_csum(dir, (struct ext4_dir_en *)block.data);
- ext4_bcache_set_dirty(block.buf);
+ ext4_trans_set_block_dirty(block.buf);
return ext4_block_set(dir->fs->bdev, &block);
}
if (r != EOK)
return r;
- r = ext4_block_get(inode_ref->fs->bdev, tmp_blk, fblk);
+ r = ext4_trans_block_get(inode_ref->fs->bdev, tmp_blk, fblk);
if (r != EOK)
return r;
return r;
struct ext4_block b;
- r = ext4_block_get(inode_ref->fs->bdev, &b, blk_adr);
+ r = ext4_trans_block_get(inode_ref->fs->bdev, &b, blk_adr);
if (r != EOK)
return r;
struct ext4_fs *fs = inode_ref->fs;
struct ext4_block root_block;
- rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);
+ rc = ext4_trans_block_get(fs->bdev, &root_block, root_block_addr);
if (rc != EOK)
return rc;
if (rc != EOK)
goto cleanup;
- rc = ext4_block_get(fs->bdev, &b, leaf_block_addr);
+ rc = ext4_trans_block_get(fs->bdev, &b, leaf_block_addr);
if (rc != EOK)
goto cleanup;
ext4_dir_dx_entry_set_hash(new_index_entry, hash);
ext4_dir_dx_climit_set_count(climit, count + 1);
ext4_dir_set_dx_csum(inode_ref, (void *)index_block->b.data);
- ext4_bcache_set_dirty(index_block->b.buf);
+ ext4_trans_set_block_dirty(index_block->b.buf);
}
/**@brief Split directory entries to two parts preventing node overflow.
/* Load new block */
struct ext4_block new_data_block_tmp;
- rc = ext4_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp,
+ rc = ext4_trans_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp,
new_fblock);
if (rc != EOK) {
free(sort);
}
ext4_dir_set_csum(inode_ref, (void *)old_data_block->data);
ext4_dir_set_csum(inode_ref, (void *)new_data_block_tmp.data);
- ext4_bcache_set_dirty(old_data_block->buf);
- ext4_bcache_set_dirty(new_data_block_tmp.buf);
+ ext4_trans_set_block_dirty(old_data_block->buf);
+ ext4_trans_set_block_dirty(new_data_block_tmp.buf);
free(sort);
free(entry_buffer);
/* load new block */
struct ext4_block b;
- r = ext4_block_get_noread(ino_ref->fs->bdev, &b, new_fblk);
+ r = ext4_trans_block_get_noread(ino_ref->fs->bdev, &b, new_fblk);
if (r != EOK)
return r;
ino_ref,
(struct ext4_dir_en *)
dxb->b.data);
- ext4_bcache_set_dirty(dxb->b.buf);
+ ext4_trans_set_block_dirty(dxb->b.buf);
struct ext4_block block_tmp = dxb->b;
new_iblk);
ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[0].b.data);
ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[1].b.data);
- ext4_bcache_set_dirty(dx_blks[0].b.buf);
- ext4_bcache_set_dirty(dx_blks[1].b.buf);
+ ext4_trans_set_block_dirty(dx_blks[0].b.buf);
+ ext4_trans_set_block_dirty(dx_blks[1].b.buf);
ext4_dir_set_dx_csum(ino_ref, (void *)b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
return ext4_block_set(ino_ref->fs->bdev, &b);
} else {
size_t sz;
ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[0].b.data);
ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[1].b.data);
- ext4_bcache_set_dirty(dx_blks[0].b.buf);
- ext4_bcache_set_dirty(dx_blks[1].b.buf);
+ ext4_trans_set_block_dirty(dx_blks[0].b.buf);
+ ext4_trans_set_block_dirty(dx_blks[1].b.buf);
}
}
struct ext4_fs *fs = parent->fs;
struct ext4_block root_blk;
- r = ext4_block_get(fs->bdev, &root_blk, rblock_addr);
+ r = ext4_trans_block_get(fs->bdev, &root_blk, rblock_addr);
if (r != EOK)
return r;
goto release_target_index;
struct ext4_block target_block;
- r = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);
+ r = ext4_trans_block_get(fs->bdev, &target_block, leaf_block_addr);
if (r != EOK)
goto release_index;
return rc;
struct ext4_block block;
- rc = ext4_block_get(dir->fs->bdev, &block, fblock);
+ rc = ext4_trans_block_get(dir->fs->bdev, &block, fblock);
if (rc != EOK)
return rc;
ext4_dx_dot_en_set_inode(&root->dots[1], parent_inode);
ext4_dir_set_dx_csum(dir, (void *)block.data);
- ext4_bcache_set_dirty(block.buf);
+ ext4_trans_set_block_dirty(block.buf);
return ext4_block_set(dir->fs->bdev, &block);
}
return rc;
}
- int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);
+ int rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, child);
if (rc != EOK)
return rc;
if (!ext4_extent_verify_block_csum(inode_ref,
ext4_extent_index_get_leaf(tmp_path[pos].index);
struct ext4_block block;
- rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);
+ rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, fblock);
if (rc != EOK)
goto cleanup;
ext4_fsblk_t fblock = ext4_extent_index_get_leaf(index);
uint32_t i;
struct ext4_block block;
- int rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);
+ int rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, fblock);
if (rc != EOK)
return rc;
ext4_extent_header_set_entries_count(path_ptr->header, entries);
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
/* If leaf node is empty, parent entry must be modified */
bool remove_parent_record = false;
ext4_extent_header_set_entries_count(path_ptr->header, entries);
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
/* Free the node if it is empty */
if ((entries == 0) && (path_ptr != path)) {
struct ext4_block block;
rc =
- ext4_block_get_noread(inode_ref->fs->bdev, &block, fblock);
+ ext4_trans_block_get_noread(inode_ref->fs->bdev, &block, fblock);
if (rc != EOK) {
ext4_balloc_free_block(inode_ref, fblock);
return rc;
ext4_extent_header_set_generation(path_ptr->header, 0);
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
/* Jump to the preceding item */
path_ptr--;
ext4_extent_header_set_entries_count(path_ptr->header,
entries + 1);
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
/* No more splitting needed */
return EOK;
return rc;
struct ext4_block block;
- rc = ext4_block_get_noread(inode_ref->fs->bdev, &block, new_fblock);
+ rc = ext4_trans_block_get_noread(inode_ref->fs->bdev, &block, new_fblock);
if (rc != EOK)
return rc;
limit);
ext4_extent_block_csum_set(inode_ref, old_root->header);
- ext4_bcache_set_dirty(old_root->block.buf);
+ ext4_trans_set_block_dirty(old_root->block.buf);
/* Re-initialize new root metadata */
new_root->depth = root_depth + 1;
/* Since new_root belongs to on-disk inode,
* we don't do checksum here */
- ext4_bcache_set_dirty(new_root->block.buf);
+ ext4_trans_set_block_dirty(new_root->block.buf);
} else {
if (path->depth) {
path->index =
ext4_extent_header_set_entries_count(path->header, entries + 1);
/* Since new_root belongs to on-disk inode,
* we don't do checksum here */
- ext4_bcache_set_dirty(path->block.buf);
+ ext4_trans_set_block_dirty(path->block.buf);
}
return EOK;
}
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
goto finish;
} else {
}
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
goto finish;
}
}
ext4_extent_block_csum_set(inode_ref, path_ptr->header);
- ext4_bcache_set_dirty(path_ptr->block.buf);
+ ext4_trans_set_block_dirty(path_ptr->block.buf);
finish:
/* Set return values */
struct ext4_extent_path *path)
{
if (path->block.lb_id)
- ext4_bcache_set_dirty(path->block.buf);
+ ext4_trans_set_block_dirty(path->block.buf);
else
inode_ref->dirty = true;
{
int err;
- err = ext4_block_get(inode_ref->fs->bdev, bh, pblk);
+ err = ext4_trans_block_get(inode_ref->fs->bdev, bh, pblk);
if (err != EOK)
goto errout;
goto cleanup;
/* For write access.# */
- ret = ext4_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
+ ret = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
if (ret != EOK)
goto cleanup;
} else if (bh.lb_id) {
/* If we got a sibling leaf. */
ext4_extent_block_csum_set(inode_ref, ext_block_hdr(&bh));
- ext4_bcache_set_dirty(bh.buf);
+ ext4_trans_set_block_dirty(bh.buf);
spt->path.p_block = ext4_idx_pblock(ix);
spt->path.depth = to_le16(eh->depth);
} else if (bh.lb_id) {
/* If we got a sibling leaf. */
ext4_extent_block_csum_set(inode_ref, ext_block_hdr(&bh));
- ext4_bcache_set_dirty(bh.buf);
+ ext4_trans_set_block_dirty(bh.buf);
spt->path.p_block = ext4_ext_pblock(ex);
spt->path.depth = to_le16(eh->depth);
return err;
/* # */
- err = ext4_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
+ err = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
if (err != EOK) {
ext4_ext_free_blocks(inode_ref, newblock, 1, 0);
return err;
}
neh->depth = to_le16(to_le16(neh->depth) + 1);
- ext4_bcache_set_dirty(bh.buf);
+ ext4_trans_set_block_dirty(bh.buf);
inode_ref->dirty = true;
ext4_block_set(inode_ref->fs->bdev, &bh);
uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);
for (i = 0; i < blocks_count; i++) {
struct ext4_block bh = EXT4_BLOCK_ZERO();
- err = ext4_block_get_noread(inode_ref->fs->bdev, &bh, block + i);
+ err = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, block + i);
if (err != EOK)
break;
memset(bh.data, 0, block_size);
- ext4_bcache_set_dirty(bh.buf);
+ ext4_trans_set_block_dirty(bh.buf);
err = ext4_block_set(inode_ref->fs->bdev, &bh);
if (err != EOK)
break;
uint32_t inode_table_bcnt = inodes_per_group * inode_size / block_size;
struct ext4_block block_bitmap;
- rc = ext4_block_get_noread(bg_ref->fs->bdev, &block_bitmap, bmp_blk);
+ rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &block_bitmap, bmp_blk);
if (rc != EOK)
return rc;
* of bitmap ), set rest of the block bitmap to 1
*/
ext4_fs_mark_bitmap_end(group_blocks, block_size * 8, block_bitmap.data);
- ext4_bcache_set_dirty(block_bitmap.buf);
+ ext4_trans_set_block_dirty(block_bitmap.buf);
ext4_balloc_set_bitmap_csum(sb, bg_ref->block_group, block_bitmap.data);
bg_ref->dirty = true;
ext4_fsblk_t bitmap_block_addr = ext4_bg_get_inode_bitmap(bg, sb);
struct ext4_block b;
- rc = ext4_block_get_noread(bg_ref->fs->bdev, &b, bitmap_block_addr);
+ rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &b, bitmap_block_addr);
if (rc != EOK)
return rc;
if (i < end_bit)
memset(b.data + (i >> 3), 0xff, (end_bit - i) >> 3);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
ext4_ialloc_set_bitmap_csum(sb, bg, b.data);
bg_ref->dirty = true;
/* Initialization of all itable blocks */
for (fblock = first_block; fblock <= last_block; ++fblock) {
struct ext4_block b;
- int rc = ext4_block_get_noread(bg_ref->fs->bdev, &b, fblock);
+ int rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &b, fblock);
if (rc != EOK)
return rc;
memset(b.data, 0, block_size);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
ext4_block_set(bg_ref->fs->bdev, &b);
if (rc != EOK)
uint32_t offset = (bgid % dsc_cnt) * ext4_sb_get_desc_size(&fs->sb);
- int rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+ int rc = ext4_trans_block_get(fs->bdev, &ref->block, block_id);
if (rc != EOK)
return rc;
ref->block_group->checksum = to_le16(cs);
/* Mark block dirty for writing changes to physical device */
- ext4_bcache_set_dirty(ref->block.buf);
+ ext4_trans_set_block_dirty(ref->block.buf);
}
/* Put back block, that contains block group descriptor */
ext4_fsblk_t block_id =
inode_table_start + (byte_offset_in_group / block_size);
- rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+ rc = ext4_trans_block_get(fs->bdev, &ref->block, block_id);
if (rc != EOK) {
return rc;
}
if (ref->dirty) {
/* Mark block dirty for writing changes to physical device */
ext4_fs_set_inode_checksum(ref);
- ext4_bcache_set_dirty(ref->block.buf);
+ ext4_trans_set_block_dirty(ref->block.buf);
}
/* Put back block, that contains i-node */
/* 2) Double indirect */
fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
if (fblock != 0) {
- int rc = ext4_block_get(fs->bdev, &block, fblock);
+ int rc = ext4_trans_block_get(fs->bdev, &block, fblock);
if (rc != EOK)
return rc;
fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
if (fblock == 0)
goto finish;
- rc = ext4_block_get(fs->bdev, &block, fblock);
+ rc = ext4_trans_block_get(fs->bdev, &block, fblock);
if (rc != EOK)
return rc;
if (ind_block == 0)
continue;
- rc = ext4_block_get(fs->bdev, &subblock,
+ rc = ext4_trans_block_get(fs->bdev, &subblock,
ind_block);
if (rc != EOK) {
ext4_block_set(fs->bdev, &block);
if (current_block == 0)
return EOK;
- int rc = ext4_block_get(fs->bdev, &block, current_block);
+ int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
if (rc != EOK)
return rc;
/* Set zero if physical data block address found */
if (level == 1) {
((uint32_t *)block.data)[offset_in_block] = to_le32(0);
- ext4_bcache_set_dirty(block.buf);
+ ext4_trans_set_block_dirty(block.buf);
}
rc = ext4_block_set(fs->bdev, &block);
*/
while (l > 0) {
/* Load indirect block */
- int rc = ext4_block_get(fs->bdev, &block, current_block);
+ int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
if (rc != EOK)
return rc;
inode_ref->dirty = true;
/* Load newly allocated block */
- rc = ext4_block_get_noread(fs->bdev, &new_block, new_blk);
+ rc = ext4_trans_block_get_noread(fs->bdev, &new_block, new_blk);
if (rc != EOK) {
ext4_balloc_free_block(inode_ref, new_blk);
return rc;
/* Initialize new block */
memset(new_block.data, 0, block_size);
- ext4_bcache_set_dirty(new_block.buf);
+ ext4_trans_set_block_dirty(new_block.buf);
/* Put back the allocated block */
rc = ext4_block_set(fs->bdev, &new_block);
* or find null reference meaning we are dealing with sparse file
*/
while (l > 0) {
- int rc = ext4_block_get(fs->bdev, &block, current_block);
+ int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
if (rc != EOK)
return rc;
}
/* Load newly allocated block */
- rc = ext4_block_get_noread(fs->bdev, &new_block,
+ rc = ext4_trans_block_get_noread(fs->bdev, &new_block,
new_blk);
if (rc != EOK) {
/* Initialize allocated block */
memset(new_block.data, 0, block_size);
- ext4_bcache_set_dirty(new_block.buf);
+ ext4_trans_set_block_dirty(new_block.buf);
rc = ext4_block_set(fs->bdev, &new_block);
if (rc != EOK) {
/* Write block address to the parent */
uint32_t * p = (uint32_t * )block.data;
p[off_in_blk] = to_le32((uint32_t)new_blk);
- ext4_bcache_set_dirty(block.buf);
+ ext4_trans_set_block_dirty(block.buf);
current_block = new_blk;
}
if (l == 1) {
uint32_t * p = (uint32_t * )block.data;
p[off_in_blk] = to_le32((uint32_t)fblock);
- ext4_bcache_set_dirty(block.buf);
+ ext4_trans_set_block_dirty(block.buf);
}
rc = ext4_block_set(fs->bdev, &block);
ext4_bg_get_inode_bitmap(bg, sb);
struct ext4_block b;
- rc = ext4_block_get(fs->bdev, &b, bitmap_block_addr);
+ rc = ext4_trans_block_get(fs->bdev, &b, bitmap_block_addr);
if (rc != EOK)
return rc;
uint32_t index_in_group = ext4_ialloc_inode_to_bgidx(sb, index);
ext4_bmap_bit_clr(b.data, index_in_group);
ext4_ialloc_set_bitmap_csum(sb, bg, b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
/* Put back the block with bitmap */
rc = ext4_block_set(fs->bdev, &b);
uint32_t bmp_blk_add = ext4_bg_get_inode_bitmap(bg, sb);
struct ext4_block b;
- rc = ext4_block_get(fs->bdev, &b, bmp_blk_add);
+ rc = ext4_trans_block_get(fs->bdev, &b, bmp_blk_add);
if (rc != EOK) {
ext4_fs_put_block_group_ref(&bg_ref);
return rc;
/* Free i-node found, save the bitmap */
ext4_ialloc_set_bitmap_csum(sb,bg,
b.data);
- ext4_bcache_set_dirty(b.buf);
+ ext4_trans_set_block_dirty(b.buf);
ext4_block_set(fs->bdev, &b);
if (rc != EOK) {
--- /dev/null
+/*
+ * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup lwext4
+ * @{
+ */
+/**
+ * @file ext4.h
+ * @brief Ext4 transaction buffer operations.
+ */
+
+#include "ext4_config.h"
+#include "ext4_types.h"
+#include "ext4_journal.h"
+
+static int ext4_trans_get_write_access(struct ext4_fs *fs,
+ struct ext4_block *block)
+{
+ int r = EOK;
+ if (fs->jbd_journal && fs->curr_trans) {
+ struct jbd_journal *journal = fs->jbd_journal;
+ struct jbd_trans *trans = fs->curr_trans;
+ r = jbd_trans_get_access(journal, trans, block);
+ }
+ return r;
+}
+
+int ext4_trans_set_block_dirty(struct ext4_buf *buf)
+{
+ int r = EOK;
+ struct ext4_fs *fs = buf->bc->bdev->fs;
+ struct ext4_block block = {
+ .lb_id = buf->lba,
+ .data = buf->data,
+ .buf = buf
+ };
+
+ if (fs->jbd_journal && fs->curr_trans) {
+ struct jbd_trans *trans = fs->curr_trans;
+ r = jbd_trans_set_block_dirty(trans, &block);
+ } else
+ ext4_bcache_set_dirty(buf);
+
+ return r;
+}
+
+int ext4_trans_block_get_noread(struct ext4_blockdev *bdev,
+ struct ext4_block *b,
+ uint64_t lba)
+{
+ int r = ext4_block_get_noread(bdev, b, lba);
+ if (r != EOK)
+ return r;
+
+ if((r = ext4_trans_get_write_access(bdev->fs, b)) != EOK)
+ ext4_block_set(bdev, b);
+
+ return r;
+}
+
+int ext4_trans_block_get(struct ext4_blockdev *bdev,
+ struct ext4_block *b,
+ uint64_t lba)
+{
+ int r = ext4_block_get(bdev, b, lba);
+ if (r != EOK)
+ return r;
+
+ if((r = ext4_trans_get_write_access(bdev->fs, b)) != EOK)
+ ext4_block_set(bdev, b);
+
+ return r;
+}
+
+int ext4_trans_try_revoke_block(struct ext4_blockdev *bdev,
+ uint64_t lba)
+{
+ int r = EOK;
+ struct ext4_fs *fs = bdev->fs;
+ if (fs->jbd_journal && fs->curr_trans) {
+ struct jbd_trans *trans = fs->curr_trans;
+ jbd_trans_try_revoke_block(trans, lba);
+ }
+ return r;
+}
+
+/**
+ * @}
+ */
--- /dev/null
+/*
+ * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup lwext4
+ * @{
+ */
+/**
+ * @file ext4_trans.h
+ * @brief Transaction handle functions
+ */
+
+#ifndef EXT4_TRANS_H
+#define EXT4_TRANS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ext4_config.h"
+#include "ext4_types.h"
+
+
+/**@brief Mark a buffer dirty and add it to the current transaction.
+ * @param buf buffer
+ * @return standard error code*/
+int ext4_trans_set_block_dirty(struct ext4_buf *buf);
+
+/**@brief Block get function (through cache, don't read).
+ * jbd_trans_get_access would be called in order to
+ * get write access to the buffer.
+ * @param bdev block device descriptor
+ * @param b block descriptor
+ * @param lba logical block address
+ * @return standard error code*/
+int ext4_trans_block_get_noread(struct ext4_blockdev *bdev,
+ struct ext4_block *b,
+ uint64_t lba);
+
+/**@brief Block get function (through cache).
+ * jbd_trans_get_access would be called in order to
+ * get write access to the buffer.
+ * @param bdev block device descriptor
+ * @param b block descriptor
+ * @param lba logical block address
+ * @return standard error code*/
+int ext4_trans_block_get(struct ext4_blockdev *bdev,
+ struct ext4_block *b,
+ uint64_t lba);
+
+/**@brief Try to add block to be revoked to the current transaction.
+ * @param bdev block device descriptor
+ * @param lba logical block address
+ * @return standard error code*/
+int ext4_trans_try_revoke_block(struct ext4_blockdev *bdev,
+ uint64_t lba);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXT4_TRANS_H */
+
+/**
+ * @}
+ */
if (ret != EOK)
goto Finish;
- ret = ext4_block_get(xattr_ref->fs->bdev, &xattr_ref->block,
+ ret = ext4_trans_block_get(xattr_ref->fs->bdev, &xattr_ref->block,
xattr_block);
if (ret != EOK) {
ext4_balloc_free_block(xattr_ref->inode_ref,
block_data = (char *)block_header + block_size_rem;
block_size_rem -= sizeof(struct ext4_xattr_header);
- ext4_bcache_set_dirty(xattr_ref->block.buf);
+ ext4_trans_set_block_dirty(xattr_ref->block.buf);
} else {
/* We don't need an extra block.*/
if (xattr_ref->block_loaded) {
&xattr_ref->fs->sb, 0);
xattr_ref->inode_ref->dirty = true;
- ext4_bcache_set_dirty(xattr_ref->block.buf);
+ ext4_trans_set_block_dirty(xattr_ref->block.buf);
}
}
}
ext4_xattr_set_block_checksum(xattr_ref->inode_ref,
xattr_ref->block.lb_id,
block_header);
- ext4_bcache_set_dirty(xattr_ref->block.buf);
+ ext4_trans_set_block_dirty(xattr_ref->block.buf);
}
Finish:
ref->ea_size = 0;
ref->iter_from = NULL;
if (xattr_block) {
- rc = ext4_block_get(fs->bdev, &ref->block, xattr_block);
+ rc = ext4_trans_block_get(fs->bdev, &ref->block, xattr_block);
if (rc != EOK)
return EIO;