2
* do_journal.c --- Scribble onto the journal!
4
* Copyright (C) 2014 Oracle. This file may be redistributed
5
* under the terms of the GNU Public License.
18
#ifdef HAVE_SYS_TIME_H
24
#include "ext2fs/kernel-jbd.h"
27
errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j);
28
errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j);
29
errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
30
void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh);
31
void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh);
32
void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh);
33
void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
34
struct buffer_head *bh, __u32 sequence);
39
# define dbg_printf(f, a...) do {printf("JFS DEBUG: " f, ## a); \
43
# define dbg_printf(f, a...)
46
#define JOURNAL_CHECK_TRANS_MAGIC(x) \
48
if ((x)->magic != J_TRANS_MAGIC) \
49
return EXT2_ET_INVALID_ARGUMENT; \
52
#define J_TRANS_MAGIC 0xD15EA5ED
53
#define J_TRANS_OPEN 1
54
#define J_TRANS_COMMITTED 2
55
struct journal_transaction_s {
65
typedef struct journal_transaction_s journal_transaction_t;
67
static journal_t *current_journal = NULL;
69
static void journal_dump_trans(journal_transaction_t *trans, const char *tag)
71
dbg_printf("TRANS %p(%s): tid=%d start=%llu block=%llu end=%llu "
72
"flags=0x%x\n", trans, tag, trans->tid, trans->start,
73
trans->block, trans->end, trans->flags);
76
static errcode_t journal_commit_trans(journal_transaction_t *trans)
78
struct buffer_head *bh, *cbh = NULL;
79
struct commit_header *commit;
80
#ifdef HAVE_SYS_TIME_H
85
JOURNAL_CHECK_TRANS_MAGIC(trans);
87
if ((trans->flags & J_TRANS_COMMITTED) ||
88
!(trans->flags & J_TRANS_OPEN))
89
return EXT2_ET_INVALID_ARGUMENT;
91
bh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize);
95
/* write the descriptor block header */
96
commit = (struct commit_header *)bh->b_data;
97
commit->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
98
commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK);
99
commit->h_sequence = ext2fs_cpu_to_be32(trans->tid);
100
if (JFS_HAS_COMPAT_FEATURE(trans->journal,
101
JFS_FEATURE_COMPAT_CHECKSUM)) {
105
cbh = getblk(trans->journal->j_dev, 0,
106
trans->journal->j_blocksize);
112
for (cblk = trans->start; cblk < trans->block; cblk++) {
113
err = journal_bmap(trans->journal, cblk,
117
mark_buffer_uptodate(cbh, 0);
118
ll_rw_block(READ, 1, &cbh);
122
csum_v1 = ext2fs_crc32_be(csum_v1,
123
(unsigned char const *)cbh->b_data,
127
commit->h_chksum_type = JFS_CRC32_CHKSUM;
128
commit->h_chksum_size = JFS_CRC32_CHKSUM_SIZE;
129
commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1);
131
commit->h_chksum_type = 0;
132
commit->h_chksum_size = 0;
133
commit->h_chksum[0] = 0;
135
#ifdef HAVE_SYS_TIME_H
136
gettimeofday(&tv, NULL);
137
commit->h_commit_sec = ext2fs_cpu_to_be32(tv.tv_sec);
138
commit->h_commit_nsec = ext2fs_cpu_to_be32(tv.tv_usec * 1000);
140
commit->h_commit_sec = 0;
141
commit->h_commit_nsec = 0;
145
jbd2_commit_block_csum_set(trans->journal, bh);
146
err = journal_bmap(trans->journal, trans->block, &bh->b_blocknr);
150
dbg_printf("Writing commit block at %llu:%llu\n", trans->block,
152
mark_buffer_dirty(bh);
153
ll_rw_block(WRITE, 1, &bh);
157
trans->flags |= J_TRANS_COMMITTED;
158
trans->flags &= ~J_TRANS_OPEN;
161
trans->fs->super->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
162
ext2fs_mark_super_dirty(trans->fs);
170
static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
171
blk64_t *revoke_list,
174
journal_revoke_header_t *jrb;
179
struct buffer_head *bh;
182
JOURNAL_CHECK_TRANS_MAGIC(trans);
184
if ((trans->flags & J_TRANS_COMMITTED) ||
185
!(trans->flags & J_TRANS_OPEN))
186
return EXT2_ET_INVALID_ARGUMENT;
191
/* Do we need to leave space at the end for a checksum? */
192
if (journal_has_csum_v2or3(trans->journal))
193
csum_size = sizeof(struct journal_revoke_tail);
195
curr_blk = trans->block;
197
bh = getblk(trans->journal->j_dev, curr_blk,
198
trans->journal->j_blocksize);
201
jrb = buf = bh->b_data;
202
jrb->r_header.h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
203
jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK);
204
jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
205
offset = sizeof(*jrb);
207
for (i = 0; i < revoke_len; i++) {
208
/* Block full, write to journal */
209
if (offset > trans->journal->j_blocksize - csum_size) {
210
jrb->r_count = ext2fs_cpu_to_be32(offset);
211
jbd2_revoke_csum_set(trans->journal, bh);
213
err = journal_bmap(trans->journal, curr_blk,
217
dbg_printf("Writing revoke block at %llu:%llu\n",
218
curr_blk, bh->b_blocknr);
219
mark_buffer_dirty(bh);
220
ll_rw_block(WRITE, 1, &bh);
225
offset = sizeof(*jrb);
229
if (revoke_list[i] >=
230
ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
231
err = EXT2_ET_BAD_BLOCK_NUM;
235
if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
236
JFS_FEATURE_INCOMPAT_64BIT)) {
237
*((__u64 *)(&((char *)buf)[offset])) =
238
ext2fs_cpu_to_be64(revoke_list[i]);
242
*((__u32 *)(&((char *)buf)[offset])) =
243
ext2fs_cpu_to_be32(revoke_list[i]);
249
jrb->r_count = ext2fs_cpu_to_be32(offset);
250
jbd2_revoke_csum_set(trans->journal, bh);
252
err = journal_bmap(trans->journal, curr_blk, &bh->b_blocknr);
255
dbg_printf("Writing revoke block at %llu:%llu\n",
256
curr_blk, bh->b_blocknr);
257
mark_buffer_dirty(bh);
258
ll_rw_block(WRITE, 1, &bh);
266
trans->block = curr_blk;
271
static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
272
blk64_t *block_list, size_t block_len,
275
blk64_t curr_blk, jdb_blk;
278
journal_header_t *jdb;
279
journal_block_tag_t *jdbt;
281
void *buf = NULL, *jdb_buf = NULL;
282
struct buffer_head *bh = NULL, *data_bh;
285
JOURNAL_CHECK_TRANS_MAGIC(trans);
287
if ((trans->flags & J_TRANS_COMMITTED) ||
288
!(trans->flags & J_TRANS_OPEN))
289
return EXT2_ET_INVALID_ARGUMENT;
294
/* Do we need to leave space at the end for a checksum? */
295
if (journal_has_csum_v2or3(trans->journal))
296
csum_size = sizeof(struct journal_block_tail);
298
curr_blk = jdb_blk = trans->block;
300
data_bh = getblk(trans->journal->j_dev, curr_blk,
301
trans->journal->j_blocksize);
304
buf = data_bh->b_data;
306
/* write the descriptor block header */
307
bh = getblk(trans->journal->j_dev, curr_blk,
308
trans->journal->j_blocksize);
313
jdb = jdb_buf = bh->b_data;
314
jdb->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
315
jdb->h_blocktype = ext2fs_cpu_to_be32(JFS_DESCRIPTOR_BLOCK);
316
jdb->h_sequence = ext2fs_cpu_to_be32(trans->tid);
317
jdbt = (journal_block_tag_t *)(jdb + 1);
320
for (i = 0; i < block_len; i++) {
321
j = fread(data_bh->b_data, trans->journal->j_blocksize, 1, fp);
327
tag_bytes = journal_tag_bytes(trans->journal);
329
/* No space left in descriptor block, write it out */
330
if ((char *)jdbt + tag_bytes >
331
(char *)jdb_buf + trans->journal->j_blocksize - csum_size) {
332
jbd2_descr_block_csum_set(trans->journal, bh);
333
err = journal_bmap(trans->journal, jdb_blk,
337
dbg_printf("Writing descriptor block at %llu:%llu\n",
338
jdb_blk, bh->b_blocknr);
339
mark_buffer_dirty(bh);
340
ll_rw_block(WRITE, 1, &bh);
345
jdbt = (journal_block_tag_t *)(jdb + 1);
351
ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
352
err = EXT2_ET_BAD_BLOCK_NUM;
356
/* Fill out the block tag */
357
jdbt->t_blocknr = ext2fs_cpu_to_be32(block_list[i] & 0xFFFFFFFF);
359
if (jdbt != (journal_block_tag_t *)(jdb + 1))
360
jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID);
362
memcpy(jdbt + tag_bytes,
363
trans->journal->j_superblock->s_uuid,
364
sizeof(trans->journal->j_superblock->s_uuid));
367
if (i == block_len - 1)
368
jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG);
369
if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
371
jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE);
373
if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
374
JFS_FEATURE_INCOMPAT_64BIT))
375
jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32);
376
jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh,
379
/* Write the data block */
380
err = journal_bmap(trans->journal, curr_blk,
381
&data_bh->b_blocknr);
384
dbg_printf("Writing data block %llu at %llu:%llu tag %d\n",
385
block_list[i], curr_blk, data_bh->b_blocknr,
387
mark_buffer_dirty(data_bh);
388
ll_rw_block(WRITE, 1, &data_bh);
389
err = data_bh->b_err;
394
jdbt = (journal_block_tag_t *)(((char *)jdbt) + tag_bytes);
397
/* Write out the last descriptor block */
398
if (jdbt != (journal_block_tag_t *)(jdb + 1)) {
399
jbd2_descr_block_csum_set(trans->journal, bh);
400
err = journal_bmap(trans->journal, jdb_blk, &bh->b_blocknr);
403
dbg_printf("Writing descriptor block at %llu:%llu\n",
404
jdb_blk, bh->b_blocknr);
405
mark_buffer_dirty(bh);
406
ll_rw_block(WRITE, 1, &bh);
413
trans->block = curr_blk;
420
static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
421
blk64_t revoke_blocks)
426
/* Estimate # of revoke blocks */
427
bs = journal->j_blocksize;
428
if (journal_has_csum_v2or3(journal))
429
bs -= sizeof(struct journal_revoke_tail);
430
sz = JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) ?
431
sizeof(__u64) : sizeof(__u32);
432
ret += revoke_blocks * sz / bs;
434
/* Estimate # of data blocks */
435
bs = journal->j_blocksize - 16;
436
if (journal_has_csum_v2or3(journal))
437
bs -= sizeof(struct journal_block_tail);
438
sz = journal_tag_bytes(journal);
439
ret += data_blocks * sz / bs;
446
static errcode_t journal_open_trans(journal_t *journal,
447
journal_transaction_t *trans,
450
trans->fs = journal->j_fs_dev->k_fs;
451
trans->journal = journal;
452
trans->flags = J_TRANS_OPEN;
454
if (journal->j_tail == 0) {
455
/* Clean journal, start at the tail */
456
trans->tid = journal->j_tail_sequence;
457
trans->start = journal->j_first;
459
/* Put new transaction at the head of the list */
460
trans->tid = journal->j_transaction_sequence;
461
trans->start = journal->j_head;
464
trans->block = trans->start;
465
if (trans->start + blocks > journal->j_last)
467
trans->end = trans->block + blocks;
468
journal_dump_trans(trans, "new transaction");
470
trans->magic = J_TRANS_MAGIC;
474
static errcode_t journal_close_trans(journal_transaction_t *trans)
478
JOURNAL_CHECK_TRANS_MAGIC(trans);
480
if (!(trans->flags & J_TRANS_COMMITTED))
483
journal = trans->journal;
484
if (journal->j_tail == 0) {
485
/* Update the tail */
486
journal->j_tail_sequence = trans->tid;
487
journal->j_tail = trans->start;
488
journal->j_superblock->s_start = ext2fs_cpu_to_be32(trans->start);
491
/* Update the head */
492
journal->j_head = trans->end + 1;
493
journal->j_transaction_sequence = trans->tid + 1;
497
/* Mark ourselves as needing recovery */
498
if (!(EXT2_HAS_INCOMPAT_FEATURE(trans->fs->super,
499
EXT3_FEATURE_INCOMPAT_RECOVER))) {
500
trans->fs->super->s_feature_incompat |=
501
EXT3_FEATURE_INCOMPAT_RECOVER;
502
ext2fs_mark_super_dirty(trans->fs);
508
#define JOURNAL_WRITE_NO_COMMIT 1
509
static errcode_t journal_write(journal_t *journal,
510
int flags, blk64_t *block_list,
511
size_t block_len, blk64_t *revoke_list,
512
size_t revoke_len, FILE *fp)
515
journal_transaction_t trans;
518
if (revoke_len > 0) {
519
journal->j_superblock->s_feature_incompat |=
520
ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_REVOKE);
521
mark_buffer_dirty(journal->j_sb_buffer);
524
blocks = journal_guess_blocks(journal, block_len, revoke_len);
525
err = journal_open_trans(journal, &trans, blocks);
529
err = journal_add_blocks_to_trans(&trans, block_list, block_len, fp);
533
err = journal_add_revoke_to_trans(&trans, revoke_list, revoke_len);
537
if (!(flags & JOURNAL_WRITE_NO_COMMIT)) {
538
err = journal_commit_trans(&trans);
543
err = journal_close_trans(&trans);
550
void do_journal_write(int argc, char *argv[])
552
blk64_t *blist = NULL, *rlist = NULL;
553
size_t bn = 0, rn = 0;
559
if (current_journal == NULL) {
560
printf("Journal not open.\n");
565
while ((opt = getopt(argc, argv, "b:r:c")) != -1) {
568
err = read_list(optarg, &blist, &bn);
570
com_err(argv[0], err,
571
"while reading block list");
574
err = read_list(optarg, &rlist, &rn);
576
com_err(argv[0], err,
577
"while reading revoke list");
580
flags |= JOURNAL_WRITE_NO_COMMIT;
583
printf("%s [-b blocks] [-r revoke] [-c] file\n",
585
printf("-b: Write these blocks into transaction.\n");
586
printf("-c: Do not commit transaction.\n");
587
printf("-r: Revoke these blocks from transaction.\n");
593
if (bn > 0 && optind != argc - 1) {
594
printf("Need a file to read blocks from.\n");
599
fp = fopen(argv[optind], "r");
601
com_err(argv[0], errno,
602
"while opening journal data file");
607
err = journal_write(current_journal, flags, blist, bn,
610
com_err("journal_write", err, "while writing journal");
621
/* Make sure we wrap around the log correctly! */
622
#define wrap(journal, var) \
624
if (var >= (journal)->j_last) \
625
var -= ((journal)->j_last - (journal)->j_first); \
629
* Count the number of in-use tags in a journal descriptor block.
632
static int count_tags(journal_t *journal, char *buf)
635
journal_block_tag_t *tag;
636
int nr = 0, size = journal->j_blocksize;
637
int tag_bytes = journal_tag_bytes(journal);
639
if (journal_has_csum_v2or3(journal))
640
size -= sizeof(struct journal_block_tail);
642
tagp = buf + sizeof(journal_header_t);
644
while ((tagp - buf + tag_bytes) <= size) {
645
tag = (journal_block_tag_t *) tagp;
649
if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID)))
652
if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG))
659
errcode_t journal_find_head(journal_t *journal)
661
unsigned int next_commit_ID;
662
blk64_t next_log_block, head_block;
664
journal_superblock_t *sb;
665
journal_header_t *tmp;
666
struct buffer_head *bh;
667
unsigned int sequence;
671
* First thing is to establish what we expect to find in the log
672
* (in terms of transaction IDs), and where (in terms of log
673
* block offsets): query the superblock.
676
sb = journal->j_superblock;
677
next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
678
next_log_block = ext2fs_be32_to_cpu(sb->s_start);
679
head_block = next_log_block;
681
if (next_log_block == 0)
684
bh = getblk(journal->j_dev, 0, journal->j_blocksize);
689
* Now we walk through the log, transaction by transaction,
690
* making sure that each transaction has a commit block in the
691
* expected place. Each complete transaction gets replayed back
692
* into the main filesystem.
695
dbg_printf("Scanning for sequence ID %u at %lu/%lu\n",
696
next_commit_ID, (unsigned long)next_log_block,
699
/* Skip over each chunk of the transaction looking
700
* either the next descriptor block or the final commit
702
err = journal_bmap(journal, next_log_block, &bh->b_blocknr);
705
mark_buffer_uptodate(bh, 0);
706
ll_rw_block(READ, 1, &bh);
712
wrap(journal, next_log_block);
714
/* What kind of buffer is it?
716
* If it is a descriptor block, check that it has the
717
* expected sequence number. Otherwise, we're all done
720
tmp = (journal_header_t *)bh->b_data;
722
if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
723
dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic);
727
blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
728
sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
729
dbg_printf("Found magic %d, sequence %d\n",
730
blocktype, sequence);
732
if (sequence != next_commit_ID) {
733
dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n",
734
sequence, next_commit_ID);
738
/* OK, we have a valid descriptor block which matches
739
* all of the sequence number checks. What are we going
740
* to do with it? That depends on the pass... */
743
case JFS_DESCRIPTOR_BLOCK:
744
next_log_block += count_tags(journal, bh->b_data);
745
wrap(journal, next_log_block);
748
case JFS_COMMIT_BLOCK:
749
head_block = next_log_block;
753
case JFS_REVOKE_BLOCK:
757
dbg_printf("Unrecognised magic %d, end of scan.\n",
766
dbg_printf("head seq=%d blk=%llu\n", next_commit_ID,
768
journal->j_transaction_sequence = next_commit_ID;
769
journal->j_head = head_block;
775
static void update_journal_csum(journal_t *journal, int ver)
777
journal_superblock_t *jsb;
779
if (journal->j_format_version < 2)
782
if (journal->j_tail != 0 ||
783
EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
784
EXT3_FEATURE_INCOMPAT_RECOVER)) {
785
printf("Journal needs recovery, will not add csums.\n");
789
/* metadata_csum implies journal csum v3 */
790
jsb = journal->j_superblock;
791
if (EXT2_HAS_RO_COMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
792
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
793
printf("Setting csum v%d\n", ver);
796
journal->j_superblock->s_feature_incompat &=
797
ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V3);
798
journal->j_superblock->s_feature_incompat |=
799
ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2);
800
journal->j_superblock->s_feature_compat &=
801
ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
804
journal->j_superblock->s_feature_incompat &=
805
ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V2);
806
journal->j_superblock->s_feature_incompat |=
807
ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3);
808
journal->j_superblock->s_feature_compat &=
809
ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
812
printf("Unknown checksum v%d\n", ver);
815
journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM;
816
journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
817
sizeof(jsb->s_uuid));
819
journal->j_superblock->s_feature_compat |=
820
ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM);
821
journal->j_superblock->s_feature_incompat &=
822
ext2fs_cpu_to_be32(~(JFS_FEATURE_INCOMPAT_CSUM_V2 |
823
JFS_FEATURE_INCOMPAT_CSUM_V3));
827
static void update_uuid(journal_t *journal)
832
if (journal->j_format_version < 2)
835
for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++)
836
if (journal->j_superblock->s_uuid[z])
841
fs = journal->j_fs_dev->k_fs;
842
if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
843
EXT4_FEATURE_INCOMPAT_64BIT))
846
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
847
EXT2_HAS_INCOMPAT_FEATURE(fs->super,
848
EXT4_FEATURE_INCOMPAT_64BIT))
851
if (journal->j_tail != 0 ||
852
EXT2_HAS_INCOMPAT_FEATURE(fs->super,
853
EXT3_FEATURE_INCOMPAT_RECOVER)) {
854
printf("Journal needs recovery, will not set 64bit.\n");
858
memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid,
859
sizeof(fs->super->s_uuid));
862
static void update_64bit_flag(journal_t *journal)
864
if (journal->j_format_version < 2)
867
if (!EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
868
EXT4_FEATURE_INCOMPAT_64BIT))
871
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
872
EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
873
EXT4_FEATURE_INCOMPAT_64BIT))
876
if (journal->j_tail != 0 ||
877
EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
878
EXT3_FEATURE_INCOMPAT_RECOVER)) {
879
printf("Journal needs recovery, will not set 64bit.\n");
883
journal->j_superblock->s_feature_incompat |=
884
ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_64BIT);
887
void do_journal_open(int argc, char *argv[])
889
int opt, enable_csum = 0, csum_ver = 3;
893
if (check_fs_open(argv[0]))
895
if (check_fs_read_write(argv[0]))
897
if (check_fs_bitmaps(argv[0]))
899
if (current_journal) {
900
printf("Journal is already open.\n");
903
if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
904
EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
905
printf("Journalling is not enabled on this filesystem.\n");
910
while ((opt = getopt(argc, argv, "cv:f:")) != -1) {
916
if (current_fs->journal_name)
917
free(current_fs->journal_name);
918
current_fs->journal_name = strdup(optarg);
921
csum_ver = atoi(optarg);
922
if (csum_ver != 2 && csum_ver != 3) {
923
printf("Unknown journal csum v%d\n", csum_ver);
928
printf("%s: [-c] [-v ver]\n", argv[0]);
929
printf("-c: Enable journal checksumming.\n");
930
printf("-v: Use this version checksum format.\n");
934
err = ext2fs_open_journal(current_fs, ¤t_journal);
936
com_err(argv[0], err, "while opening journal");
939
journal = current_journal;
941
dbg_printf("JOURNAL: seq=%d tailseq=%d start=%lu first=%lu "
942
"maxlen=%lu\n", journal->j_tail_sequence,
943
journal->j_transaction_sequence, journal->j_tail,
944
journal->j_first, journal->j_last);
946
update_uuid(journal);
947
update_64bit_flag(journal);
949
update_journal_csum(journal, csum_ver);
951
err = journal_find_head(journal);
953
com_err(argv[0], err, "while examining journal");
956
void do_journal_close(int argc, char *argv[])
958
if (current_journal == NULL) {
959
printf("Journal not open.\n");
963
ext2fs_close_journal(current_fs, ¤t_journal);
966
void do_journal_run(int argc, char *argv[])
970
if (check_fs_open(argv[0]))
972
if (check_fs_read_write(argv[0]))
974
if (check_fs_bitmaps(argv[0]))
976
if (current_journal) {
977
printf("Please close the journal before recovering it.\n");
981
err = ext2fs_run_ext3_journal(¤t_fs);
983
com_err("journal_run", err, "while recovering journal");
985
current_fs->super->s_feature_incompat &=
986
~EXT3_FEATURE_INCOMPAT_RECOVER;
987
ext2fs_mark_super_dirty(current_fs);