6 #include "ext4_config.h"
7 #include "ext4_types.h"
9 #include "ext4_super.h"
10 #include "ext4_errno.h"
11 #include "ext4_blockdev.h"
12 #include "ext4_crc32c.h"
13 #include "ext4_debug.h"
17 int jbd_inode_bmap(struct jbd_fs *jbd_fs,
19 ext4_fsblk_t *fblock);
21 int jbd_sb_write(struct jbd_fs *jbd_fs, struct jbd_sb *s)
24 struct ext4_fs *fs = jbd_fs->inode_ref.fs;
27 rc = jbd_inode_bmap(jbd_fs, 0, &fblock);
31 offset = fblock * ext4_sb_get_block_size(&fs->sb);
32 return ext4_block_writebytes(fs->bdev, offset, s,
33 EXT4_SUPERBLOCK_SIZE);
36 int jbd_sb_read(struct jbd_fs *jbd_fs, struct jbd_sb *s)
39 struct ext4_fs *fs = jbd_fs->inode_ref.fs;
42 rc = jbd_inode_bmap(jbd_fs, 0, &fblock);
46 offset = fblock * ext4_sb_get_block_size(&fs->sb);
47 return ext4_block_readbytes(fs->bdev, offset, s,
48 EXT4_SUPERBLOCK_SIZE);
51 static bool jbd_verify_sb(struct jbd_sb *sb)
53 struct jbd_bhdr *bhdr = &sb->header;
54 if (bhdr->magic != to_be32(JBD_MAGIC_NUMBER))
57 if (bhdr->blocktype != to_be32(JBD_SUPERBLOCK) &&
58 bhdr->blocktype != to_be32(JBD_SUPERBLOCK_V2))
64 int jbd_get_fs(struct ext4_fs *fs,
65 struct jbd_fs *jbd_fs)
70 memset(jbd_fs, 0, sizeof(struct jbd_fs));
71 journal_ino = ext4_get32(&fs->sb, journal_inode_number);
73 rc = ext4_fs_get_inode_ref(fs,
77 memset(jbd_fs, 0, sizeof(struct jbd_fs));
80 rc = jbd_sb_read(jbd_fs, &jbd_fs->sb);
82 memset(jbd_fs, 0, sizeof(struct jbd_fs));
83 ext4_fs_put_inode_ref(&jbd_fs->inode_ref);
89 int jbd_put_fs(struct jbd_fs *jbd_fs)
92 rc = ext4_fs_put_inode_ref(&jbd_fs->inode_ref);
96 int jbd_inode_bmap(struct jbd_fs *jbd_fs,
100 int rc = ext4_fs_get_inode_data_block_index(
108 int jbd_block_get(struct jbd_fs *jbd_fs,
109 struct ext4_block *block,
112 /* TODO: journal device. */
114 ext4_lblk_t iblock = (ext4_lblk_t)fblock;
115 rc = jbd_inode_bmap(jbd_fs, iblock,
120 struct ext4_blockdev *bdev = jbd_fs->inode_ref.fs->bdev;
121 rc = ext4_block_get(bdev, block, fblock);
125 int jbd_block_get_noread(struct jbd_fs *jbd_fs,
126 struct ext4_block *block,
129 /* TODO: journal device. */
131 ext4_lblk_t iblock = (ext4_lblk_t)fblock;
132 rc = jbd_inode_bmap(jbd_fs, iblock,
137 struct ext4_blockdev *bdev = jbd_fs->inode_ref.fs->bdev;
138 rc = ext4_block_get_noread(bdev, block, fblock);
142 int jbd_block_set(struct jbd_fs *jbd_fs,
143 struct ext4_block *block)
145 return ext4_block_set(jbd_fs->inode_ref.fs->bdev,
149 /* Make sure we wrap around the log correctly! */
150 #define wrap(sb, var) \
152 if (var >= to_be32((sb)->maxlen)) \
153 var -= (to_be32((sb)->maxlen) - to_be32((sb)->first)); \
156 #define ACTION_SCAN 0
157 #define ACTION_REVOKE 1
158 #define ACTION_RECOVER 2
160 struct recover_info {
161 uint32_t start_trans_id;
162 uint32_t last_trans_id;
165 int jbd_iterate_log(struct jbd_fs *jbd_fs,
166 struct recover_info *info,
170 bool log_end = false;
171 struct jbd_sb *sb = &jbd_fs->sb;
172 uint32_t start_trans_id, this_trans_id;
173 uint32_t start_block, this_block;
175 start_trans_id = this_trans_id = to_be32(sb->sequence);
176 start_block = this_block = to_be32(sb->start);
178 ext4_dbg(DEBUG_JBD, "Start of journal at trans id: %" PRIu32 "\n",
182 struct ext4_block block;
183 struct jbd_bhdr *header;
184 if (action != ACTION_SCAN)
185 if (this_trans_id > info->last_trans_id) {
190 r = jbd_block_get(jbd_fs, &block, this_block);
194 header = (struct jbd_bhdr *)block.data;
195 if (header->magic != to_be32(JBD_MAGIC_NUMBER)) {
196 jbd_block_set(jbd_fs, &block);
201 if (header->sequence != to_be32(this_trans_id)) {
202 if (this_trans_id <= info->last_trans_id)
205 jbd_block_set(jbd_fs, &block);
210 switch (header->blocktype) {
211 case JBD_DESCRIPTOR_BLOCK:
212 ext4_dbg(DEBUG_JBD, "Descriptor block: %u, "
214 this_block, this_trans_id);
216 case JBD_COMMIT_BLOCK:
217 ext4_dbg(DEBUG_JBD, "Commit block: %u, "
219 this_block, this_trans_id);
222 case JBD_REVOKE_BLOCK:
223 ext4_dbg(DEBUG_JBD, "Revoke block: %u, "
225 this_block, this_trans_id);
231 jbd_block_set(jbd_fs, &block);
233 wrap(sb, this_block);
234 if (this_block == start_block)
238 ext4_dbg(DEBUG_JBD, "End of journal.\n");
239 if (r == EOK && action == ACTION_SCAN) {
240 info->start_trans_id = start_trans_id;
241 if (this_trans_id > start_trans_id)
242 info->last_trans_id = this_trans_id - 1;
244 info->last_trans_id = this_trans_id;
250 int jbd_recover(struct jbd_fs *jbd_fs)
253 struct recover_info info;
254 struct jbd_sb *sb = &jbd_fs->sb;
258 r = jbd_iterate_log(jbd_fs, &info, ACTION_SCAN);