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
23 #include "ext2fs/kernel-jbd.h"
29 # define dbg_printf(f, a...) do {printf("JFS DEBUG: " f, ## a); \
33 # define dbg_printf(f, a...)
36 #define JOURNAL_CHECK_TRANS_MAGIC(x) \
38 if ((x)->magic != J_TRANS_MAGIC) \
39 return EXT2_ET_INVALID_ARGUMENT; \
42 #define J_TRANS_MAGIC 0xD15EA5ED
43 #define J_TRANS_OPEN 1
44 #define J_TRANS_COMMITTED 2
45 struct journal_transaction_s
{
55 typedef struct journal_transaction_s journal_transaction_t
;
57 static journal_t
*current_journal
= NULL
;
59 static void journal_dump_trans(journal_transaction_t
*trans
EXT2FS_ATTR((unused
)),
60 const char *tag
EXT2FS_ATTR((unused
)))
62 dbg_printf("TRANS %p(%s): tid=%u start=%llu block=%llu end=%llu "
63 "flags=0x%x\n", trans
, tag
, trans
->tid
, trans
->start
,
64 trans
->block
, trans
->end
, trans
->flags
);
67 static errcode_t
journal_commit_trans(journal_transaction_t
*trans
)
69 struct buffer_head
*bh
, *cbh
= NULL
;
70 struct commit_header
*commit
;
71 #ifdef HAVE_SYS_TIME_H
76 JOURNAL_CHECK_TRANS_MAGIC(trans
);
78 if ((trans
->flags
& J_TRANS_COMMITTED
) ||
79 !(trans
->flags
& J_TRANS_OPEN
))
80 return EXT2_ET_INVALID_ARGUMENT
;
82 bh
= getblk(trans
->journal
->j_dev
, 0, trans
->journal
->j_blocksize
);
86 /* write the descriptor block header */
87 commit
= (struct commit_header
*)bh
->b_data
;
88 commit
->h_magic
= ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER
);
89 commit
->h_blocktype
= ext2fs_cpu_to_be32(JBD2_COMMIT_BLOCK
);
90 commit
->h_sequence
= ext2fs_cpu_to_be32(trans
->tid
);
91 if (jbd2_has_feature_checksum(trans
->journal
)) {
95 cbh
= getblk(trans
->journal
->j_dev
, 0,
96 trans
->journal
->j_blocksize
);
102 for (cblk
= trans
->start
; cblk
< trans
->block
; cblk
++) {
103 err
= jbd2_journal_bmap(trans
->journal
, cblk
,
107 mark_buffer_uptodate(cbh
, 0);
108 ll_rw_block(REQ_OP_READ
, 0, 1, &cbh
);
112 csum_v1
= ext2fs_crc32_be(csum_v1
,
113 (unsigned char const *)cbh
->b_data
,
117 commit
->h_chksum_type
= JBD2_CRC32_CHKSUM
;
118 commit
->h_chksum_size
= JBD2_CRC32_CHKSUM_SIZE
;
119 commit
->h_chksum
[0] = ext2fs_cpu_to_be32(csum_v1
);
121 commit
->h_chksum_type
= 0;
122 commit
->h_chksum_size
= 0;
123 commit
->h_chksum
[0] = 0;
125 #ifdef HAVE_SYS_TIME_H
126 gettimeofday(&tv
, NULL
);
127 commit
->h_commit_sec
= ext2fs_cpu_to_be32(tv
.tv_sec
);
128 commit
->h_commit_nsec
= ext2fs_cpu_to_be32(tv
.tv_usec
* 1000);
130 commit
->h_commit_sec
= 0;
131 commit
->h_commit_nsec
= 0;
135 jbd2_commit_block_csum_set(trans
->journal
, bh
);
136 err
= jbd2_journal_bmap(trans
->journal
, trans
->block
, &bh
->b_blocknr
);
140 dbg_printf("Writing commit block at %llu:%llu\n", trans
->block
,
142 mark_buffer_dirty(bh
);
143 ll_rw_block(REQ_OP_WRITE
, 0, 1, &bh
);
147 trans
->flags
|= J_TRANS_COMMITTED
;
148 trans
->flags
&= ~J_TRANS_OPEN
;
151 ext2fs_set_feature_journal_needs_recovery(trans
->fs
->super
);
152 ext2fs_mark_super_dirty(trans
->fs
);
160 static errcode_t
journal_add_revoke_to_trans(journal_transaction_t
*trans
,
161 blk64_t
*revoke_list
,
164 jbd2_journal_revoke_header_t
*jrb
;
169 unsigned csum_size
= 0;
170 struct buffer_head
*bh
;
173 JOURNAL_CHECK_TRANS_MAGIC(trans
);
175 if ((trans
->flags
& J_TRANS_COMMITTED
) ||
176 !(trans
->flags
& J_TRANS_OPEN
))
177 return EXT2_ET_INVALID_ARGUMENT
;
182 /* Do we need to leave space at the end for a checksum? */
183 if (jbd2_journal_has_csum_v2or3(trans
->journal
))
184 csum_size
= sizeof(struct jbd2_journal_block_tail
);
186 curr_blk
= trans
->block
;
188 bh
= getblk(trans
->journal
->j_dev
, curr_blk
,
189 trans
->journal
->j_blocksize
);
192 jrb
= buf
= bh
->b_data
;
193 jrb
->r_header
.h_magic
= ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER
);
194 jrb
->r_header
.h_blocktype
= ext2fs_cpu_to_be32(JBD2_REVOKE_BLOCK
);
195 jrb
->r_header
.h_sequence
= ext2fs_cpu_to_be32(trans
->tid
);
196 offset
= sizeof(*jrb
);
198 if (jbd2_has_feature_64bit(trans
->journal
))
203 for (i
= 0; i
< revoke_len
; i
++) {
204 /* Block full, write to journal */
205 if (offset
+ sz
> trans
->journal
->j_blocksize
- csum_size
) {
206 jrb
->r_count
= ext2fs_cpu_to_be32(offset
);
207 jbd2_revoke_csum_set(trans
->journal
, bh
);
209 err
= jbd2_journal_bmap(trans
->journal
, curr_blk
,
213 dbg_printf("Writing revoke block at %llu:%llu\n",
214 curr_blk
, bh
->b_blocknr
);
215 mark_buffer_dirty(bh
);
216 ll_rw_block(REQ_OP_WRITE
, 0, 1, &bh
);
221 offset
= sizeof(*jrb
);
225 if (revoke_list
[i
] >=
226 ext2fs_blocks_count(trans
->journal
->j_fs_dev
->k_fs
->super
)) {
227 err
= EXT2_ET_BAD_BLOCK_NUM
;
231 if (jbd2_has_feature_64bit(trans
->journal
))
232 *((__u64
*)(&((char *)buf
)[offset
])) =
233 ext2fs_cpu_to_be64(revoke_list
[i
]);
235 *((__u32
*)(&((char *)buf
)[offset
])) =
236 ext2fs_cpu_to_be32(revoke_list
[i
]);
241 jrb
->r_count
= ext2fs_cpu_to_be32(offset
);
242 jbd2_revoke_csum_set(trans
->journal
, bh
);
244 err
= jbd2_journal_bmap(trans
->journal
, curr_blk
,
248 dbg_printf("Writing revoke block at %llu:%llu\n",
249 curr_blk
, bh
->b_blocknr
);
250 mark_buffer_dirty(bh
);
251 ll_rw_block(REQ_OP_WRITE
, 0, 1, &bh
);
259 trans
->block
= curr_blk
;
264 static errcode_t
journal_add_blocks_to_trans(journal_transaction_t
*trans
,
265 blk64_t
*block_list
, size_t block_len
,
268 blk64_t curr_blk
, jdb_blk
;
271 journal_header_t
*jdb
;
272 journal_block_tag_t
*jdbt
;
274 void *buf
= NULL
, *jdb_buf
= NULL
;
275 struct buffer_head
*bh
= NULL
, *data_bh
;
278 JOURNAL_CHECK_TRANS_MAGIC(trans
);
280 if ((trans
->flags
& J_TRANS_COMMITTED
) ||
281 !(trans
->flags
& J_TRANS_OPEN
))
282 return EXT2_ET_INVALID_ARGUMENT
;
287 /* Do we need to leave space at the end for a checksum? */
288 if (jbd2_journal_has_csum_v2or3(trans
->journal
))
289 csum_size
= sizeof(struct jbd2_journal_block_tail
);
291 curr_blk
= jdb_blk
= trans
->block
;
293 data_bh
= getblk(trans
->journal
->j_dev
, curr_blk
,
294 trans
->journal
->j_blocksize
);
297 buf
= data_bh
->b_data
;
299 /* write the descriptor block header */
300 bh
= getblk(trans
->journal
->j_dev
, curr_blk
,
301 trans
->journal
->j_blocksize
);
306 jdb
= jdb_buf
= bh
->b_data
;
307 jdb
->h_magic
= ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER
);
308 jdb
->h_blocktype
= ext2fs_cpu_to_be32(JBD2_DESCRIPTOR_BLOCK
);
309 jdb
->h_sequence
= ext2fs_cpu_to_be32(trans
->tid
);
310 jdbt
= (journal_block_tag_t
*)(jdb
+ 1);
313 for (i
= 0; i
< block_len
; i
++) {
314 j
= fread(data_bh
->b_data
, trans
->journal
->j_blocksize
, 1, fp
);
320 tag_bytes
= journal_tag_bytes(trans
->journal
);
322 /* No space left in descriptor block, write it out */
323 if ((char *)jdbt
+ tag_bytes
>
324 (char *)jdb_buf
+ trans
->journal
->j_blocksize
- csum_size
) {
325 jbd2_descr_block_csum_set(trans
->journal
, bh
);
326 err
= jbd2_journal_bmap(trans
->journal
, jdb_blk
,
330 dbg_printf("Writing descriptor block at %llu:%llu\n",
331 jdb_blk
, bh
->b_blocknr
);
332 mark_buffer_dirty(bh
);
333 ll_rw_block(REQ_OP_WRITE
, 0, 1, &bh
);
338 jdbt
= (journal_block_tag_t
*)(jdb
+ 1);
344 ext2fs_blocks_count(trans
->journal
->j_fs_dev
->k_fs
->super
)) {
345 err
= EXT2_ET_BAD_BLOCK_NUM
;
349 /* Fill out the block tag */
350 jdbt
->t_blocknr
= ext2fs_cpu_to_be32(block_list
[i
] & 0xFFFFFFFF);
352 if (jdbt
!= (journal_block_tag_t
*)(jdb
+ 1))
353 jdbt
->t_flags
|= ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID
);
355 memcpy(jdbt
+ tag_bytes
,
356 trans
->journal
->j_superblock
->s_uuid
,
357 sizeof(trans
->journal
->j_superblock
->s_uuid
));
360 if (i
== block_len
- 1)
361 jdbt
->t_flags
|= ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG
);
362 if (*((__u32
*)buf
) == ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER
)) {
364 jdbt
->t_flags
|= ext2fs_cpu_to_be16(JBD2_FLAG_ESCAPE
);
366 if (jbd2_has_feature_64bit(trans
->journal
))
367 jdbt
->t_blocknr_high
= ext2fs_cpu_to_be32(block_list
[i
] >> 32);
368 jbd2_block_tag_csum_set(trans
->journal
, jdbt
, data_bh
,
371 /* Write the data block */
372 err
= jbd2_journal_bmap(trans
->journal
, curr_blk
,
373 &data_bh
->b_blocknr
);
376 dbg_printf("Writing data block %llu at %llu:%llu tag %d\n",
377 block_list
[i
], curr_blk
, data_bh
->b_blocknr
,
379 mark_buffer_dirty(data_bh
);
380 ll_rw_block(REQ_OP_WRITE
, 0, 1, &data_bh
);
381 err
= data_bh
->b_err
;
386 jdbt
= (journal_block_tag_t
*)(((char *)jdbt
) + tag_bytes
);
389 /* Write out the last descriptor block */
390 if (jdbt
!= (journal_block_tag_t
*)(jdb
+ 1)) {
391 jbd2_descr_block_csum_set(trans
->journal
, bh
);
392 err
= jbd2_journal_bmap(trans
->journal
, jdb_blk
,
396 dbg_printf("Writing descriptor block at %llu:%llu\n",
397 jdb_blk
, bh
->b_blocknr
);
398 mark_buffer_dirty(bh
);
399 ll_rw_block(REQ_OP_WRITE
, 0, 1, &bh
);
406 trans
->block
= curr_blk
;
413 static blk64_t
journal_guess_blocks(journal_t
*journal
, blk64_t data_blocks
,
414 blk64_t revoke_blocks
)
419 /* Estimate # of revoke blocks */
420 bs
= journal
->j_blocksize
;
421 if (jbd2_journal_has_csum_v2or3(journal
))
422 bs
-= sizeof(struct jbd2_journal_block_tail
);
423 sz
= jbd2_has_feature_64bit(journal
) ? sizeof(__u64
) : sizeof(__u32
);
424 ret
+= revoke_blocks
* sz
/ bs
;
426 /* Estimate # of data blocks */
427 bs
= journal
->j_blocksize
- 16;
428 if (jbd2_journal_has_csum_v2or3(journal
))
429 bs
-= sizeof(struct jbd2_journal_block_tail
);
430 sz
= journal_tag_bytes(journal
);
431 ret
+= data_blocks
* sz
/ bs
;
438 static errcode_t
journal_open_trans(journal_t
*journal
,
439 journal_transaction_t
*trans
,
442 trans
->fs
= journal
->j_fs_dev
->k_fs
;
443 trans
->journal
= journal
;
444 trans
->flags
= J_TRANS_OPEN
;
446 if (journal
->j_tail
== 0) {
447 /* Clean journal, start at the tail */
448 trans
->tid
= journal
->j_tail_sequence
;
449 trans
->start
= journal
->j_first
;
451 /* Put new transaction at the head of the list */
452 trans
->tid
= journal
->j_transaction_sequence
;
453 trans
->start
= journal
->j_head
;
456 trans
->block
= trans
->start
;
457 if (trans
->start
+ blocks
> journal
->j_last
)
459 trans
->end
= trans
->block
+ blocks
;
460 journal_dump_trans(trans
, "new transaction");
462 trans
->magic
= J_TRANS_MAGIC
;
466 static errcode_t
journal_close_trans(journal_transaction_t
*trans
)
470 JOURNAL_CHECK_TRANS_MAGIC(trans
);
472 if (!(trans
->flags
& J_TRANS_COMMITTED
))
475 journal
= trans
->journal
;
476 if (journal
->j_tail
== 0) {
477 /* Update the tail */
478 journal
->j_tail_sequence
= trans
->tid
;
479 journal
->j_tail
= trans
->start
;
480 journal
->j_superblock
->s_start
= ext2fs_cpu_to_be32(trans
->start
);
483 /* Update the head */
484 journal
->j_head
= trans
->end
+ 1;
485 journal
->j_transaction_sequence
= trans
->tid
+ 1;
489 /* Mark ourselves as needing recovery */
490 if (!ext2fs_has_feature_journal_needs_recovery(trans
->fs
->super
)) {
491 ext2fs_set_feature_journal_needs_recovery(trans
->fs
->super
);
492 ext2fs_mark_super_dirty(trans
->fs
);
498 #define JOURNAL_WRITE_NO_COMMIT 1
499 static errcode_t
journal_write(journal_t
*journal
,
500 int flags
, blk64_t
*block_list
,
501 size_t block_len
, blk64_t
*revoke_list
,
502 size_t revoke_len
, FILE *fp
)
505 journal_transaction_t trans
;
508 if (revoke_len
> 0) {
509 jbd2_set_feature_revoke(journal
);
510 mark_buffer_dirty(journal
->j_sb_buffer
);
513 blocks
= journal_guess_blocks(journal
, block_len
, revoke_len
);
514 err
= journal_open_trans(journal
, &trans
, blocks
);
518 err
= journal_add_blocks_to_trans(&trans
, block_list
, block_len
, fp
);
522 err
= journal_add_revoke_to_trans(&trans
, revoke_list
, revoke_len
);
526 if (!(flags
& JOURNAL_WRITE_NO_COMMIT
)) {
527 err
= journal_commit_trans(&trans
);
532 err
= journal_close_trans(&trans
);
537 void do_journal_write(int argc
, char *argv
[], int sci_idx
EXT2FS_ATTR((unused
)),
538 void *infop
EXT2FS_ATTR((unused
)))
540 blk64_t
*blist
= NULL
, *rlist
= NULL
;
541 size_t bn
= 0, rn
= 0;
547 if (current_journal
== NULL
) {
548 printf("Journal not open.\n");
553 while ((opt
= getopt(argc
, argv
, "b:r:c")) != -1) {
556 err
= read_list(optarg
, &blist
, &bn
);
558 com_err(argv
[0], err
,
559 "while reading block list");
564 err
= read_list(optarg
, &rlist
, &rn
);
566 com_err(argv
[0], err
,
567 "while reading revoke list");
572 flags
|= JOURNAL_WRITE_NO_COMMIT
;
575 printf("%s [-b blocks] [-r revoke] [-c] file\n",
577 printf("-b: Write these blocks into transaction.\n");
578 printf("-c: Do not commit transaction.\n");
579 printf("-r: Revoke these blocks from transaction.\n");
585 if (bn
> 0 && optind
!= argc
- 1) {
586 printf("Need a file to read blocks from.\n");
591 fp
= fopen(argv
[optind
], "r");
593 com_err(argv
[0], errno
,
594 "while opening journal data file");
599 err
= journal_write(current_journal
, flags
, blist
, bn
,
602 com_err("journal_write", err
, "while writing journal");
613 /* Make sure we wrap around the log correctly! */
614 #define wrap(journal, var) \
616 if (var >= (journal)->j_last) \
617 var -= ((journal)->j_last - (journal)->j_first); \
621 * Count the number of in-use tags in a journal descriptor block.
624 static int count_tags(journal_t
*journal
, char *buf
)
627 journal_block_tag_t
*tag
;
628 int nr
= 0, size
= journal
->j_blocksize
;
629 int tag_bytes
= journal_tag_bytes(journal
);
631 if (jbd2_journal_has_csum_v2or3(journal
))
632 size
-= sizeof(struct jbd2_journal_block_tail
);
634 tagp
= buf
+ sizeof(journal_header_t
);
636 while ((tagp
- buf
+ tag_bytes
) <= size
) {
637 tag
= (journal_block_tag_t
*) tagp
;
641 if (!(tag
->t_flags
& ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID
)))
644 if (tag
->t_flags
& ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG
))
651 static errcode_t
journal_find_head(journal_t
*journal
)
653 unsigned int next_commit_ID
;
654 blk64_t next_log_block
, head_block
;
656 journal_superblock_t
*sb
;
657 journal_header_t
*tmp
;
658 struct buffer_head
*bh
;
659 unsigned int sequence
;
663 * First thing is to establish what we expect to find in the log
664 * (in terms of transaction IDs), and where (in terms of log
665 * block offsets): query the superblock.
668 sb
= journal
->j_superblock
;
669 next_commit_ID
= ext2fs_be32_to_cpu(sb
->s_sequence
);
670 next_log_block
= ext2fs_be32_to_cpu(sb
->s_start
);
671 head_block
= next_log_block
;
673 if (next_log_block
== 0)
676 bh
= getblk(journal
->j_dev
, 0, journal
->j_blocksize
);
681 * Now we walk through the log, transaction by transaction,
682 * making sure that each transaction has a commit block in the
683 * expected place. Each complete transaction gets replayed back
684 * into the main filesystem.
687 dbg_printf("Scanning for sequence ID %u at %lu/%lu\n",
688 next_commit_ID
, (unsigned long)next_log_block
,
691 /* Skip over each chunk of the transaction looking
692 * either the next descriptor block or the final commit
694 err
= jbd2_journal_bmap(journal
, next_log_block
,
698 mark_buffer_uptodate(bh
, 0);
699 ll_rw_block(REQ_OP_READ
, 0, 1, &bh
);
705 wrap(journal
, next_log_block
);
707 /* What kind of buffer is it?
709 * If it is a descriptor block, check that it has the
710 * expected sequence number. Otherwise, we're all done
713 tmp
= (journal_header_t
*)bh
->b_data
;
715 if (tmp
->h_magic
!= ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER
)) {
716 dbg_printf("JBD2: wrong magic 0x%x\n", tmp
->h_magic
);
720 blocktype
= ext2fs_be32_to_cpu(tmp
->h_blocktype
);
721 sequence
= ext2fs_be32_to_cpu(tmp
->h_sequence
);
722 dbg_printf("Found magic %d, sequence %d\n",
723 blocktype
, sequence
);
725 if (sequence
!= next_commit_ID
) {
726 dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n",
727 sequence
, next_commit_ID
);
731 /* OK, we have a valid descriptor block which matches
732 * all of the sequence number checks. What are we going
733 * to do with it? That depends on the pass... */
736 case JBD2_DESCRIPTOR_BLOCK
:
737 next_log_block
+= count_tags(journal
, bh
->b_data
);
738 wrap(journal
, next_log_block
);
741 case JBD2_COMMIT_BLOCK
:
742 head_block
= next_log_block
;
746 case JBD2_REVOKE_BLOCK
:
750 dbg_printf("Unrecognised magic %d, end of scan.\n",
759 dbg_printf("head seq=%d blk=%llu\n", next_commit_ID
,
761 journal
->j_transaction_sequence
= next_commit_ID
;
762 journal
->j_head
= head_block
;
768 static void update_journal_csum(journal_t
*journal
, int ver
)
770 journal_superblock_t
*jsb
;
772 if (journal
->j_format_version
< 2)
775 if (journal
->j_tail
!= 0 ||
776 ext2fs_has_feature_journal_needs_recovery(
777 journal
->j_fs_dev
->k_fs
->super
)) {
778 printf("Journal needs recovery, will not add csums.\n");
782 /* metadata_csum implies journal csum v3 */
783 jsb
= journal
->j_superblock
;
784 if (ext2fs_has_feature_metadata_csum(journal
->j_fs_dev
->k_fs
->super
)) {
785 printf("Setting csum v%d\n", ver
);
788 jbd2_clear_feature_csum3(journal
);
789 jbd2_set_feature_csum2(journal
);
790 jbd2_clear_feature_checksum(journal
);
793 jbd2_set_feature_csum3(journal
);
794 jbd2_clear_feature_csum2(journal
);
795 jbd2_clear_feature_checksum(journal
);
798 printf("Unknown checksum v%d\n", ver
);
801 journal
->j_superblock
->s_checksum_type
= JBD2_CRC32C_CHKSUM
;
802 journal
->j_csum_seed
= jbd2_chksum(journal
, ~0, jsb
->s_uuid
,
803 sizeof(jsb
->s_uuid
));
805 jbd2_clear_feature_csum3(journal
);
806 jbd2_clear_feature_csum2(journal
);
807 jbd2_set_feature_checksum(journal
);
811 static void update_uuid(journal_t
*journal
)
816 if (journal
->j_format_version
< 2)
819 for (z
= 0; z
< sizeof(journal
->j_superblock
->s_uuid
); z
++)
820 if (journal
->j_superblock
->s_uuid
[z
])
825 fs
= journal
->j_fs_dev
->k_fs
;
826 if (!ext2fs_has_feature_64bit(fs
->super
))
829 if (jbd2_has_feature_64bit(journal
) &&
830 ext2fs_has_feature_64bit(fs
->super
))
833 if (journal
->j_tail
!= 0 ||
834 ext2fs_has_feature_journal_needs_recovery(fs
->super
)) {
835 printf("Journal needs recovery, will not set 64bit.\n");
839 memcpy(journal
->j_superblock
->s_uuid
, fs
->super
->s_uuid
,
840 sizeof(fs
->super
->s_uuid
));
843 static void update_64bit_flag(journal_t
*journal
)
845 if (journal
->j_format_version
< 2)
848 if (!ext2fs_has_feature_64bit(journal
->j_fs_dev
->k_fs
->super
))
851 if (jbd2_has_feature_64bit(journal
) &&
852 ext2fs_has_feature_64bit(journal
->j_fs_dev
->k_fs
->super
))
855 if (journal
->j_tail
!= 0 ||
856 ext2fs_has_feature_journal_needs_recovery(
857 journal
->j_fs_dev
->k_fs
->super
)) {
858 printf("Journal needs recovery, will not set 64bit.\n");
862 jbd2_set_feature_64bit(journal
);
865 void do_journal_open(int argc
, char *argv
[], int sci_idx
EXT2FS_ATTR((unused
)),
866 void *infop
EXT2FS_ATTR((unused
)))
868 int opt
, enable_csum
= 0, csum_ver
= 3;
872 if (check_fs_open(argv
[0]))
874 if (check_fs_read_write(argv
[0]))
876 if (check_fs_bitmaps(argv
[0]))
878 if (current_journal
) {
879 printf("Journal is already open.\n");
882 if (!ext2fs_has_feature_journal(current_fs
->super
)) {
883 printf("Journalling is not enabled on this filesystem.\n");
888 while ((opt
= getopt(argc
, argv
, "cv:f:")) != -1) {
894 if (current_fs
->journal_name
)
895 free(current_fs
->journal_name
);
896 current_fs
->journal_name
= strdup(optarg
);
899 csum_ver
= atoi(optarg
);
900 if (csum_ver
!= 2 && csum_ver
!= 3) {
901 printf("Unknown journal csum v%d\n", csum_ver
);
906 printf("%s: [-c] [-v ver] [-f ext_jnl]\n", argv
[0]);
907 printf("-c: Enable journal checksumming.\n");
908 printf("-v: Use this version checksum format.\n");
909 printf("-f: Load this external journal.\n");
913 err
= ext2fs_open_journal(current_fs
, ¤t_journal
);
915 com_err(argv
[0], err
, "while opening journal");
918 journal
= current_journal
;
920 dbg_printf("JOURNAL: seq=%u tailseq=%u start=%lu first=%lu "
921 "maxlen=%lu\n", journal
->j_tail_sequence
,
922 journal
->j_transaction_sequence
, journal
->j_tail
,
923 journal
->j_first
, journal
->j_last
);
925 update_uuid(journal
);
926 update_64bit_flag(journal
);
928 update_journal_csum(journal
, csum_ver
);
930 err
= journal_find_head(journal
);
932 com_err(argv
[0], err
, "while examining journal");
935 void do_journal_close(int argc
EXT2FS_ATTR((unused
)),
936 char *argv
[] EXT2FS_ATTR((unused
)),
937 int sci_idx
EXT2FS_ATTR((unused
)),
938 void *infop
EXT2FS_ATTR((unused
)))
940 if (current_journal
== NULL
) {
941 printf("Journal not open.\n");
945 ext2fs_close_journal(current_fs
, ¤t_journal
);
948 void do_journal_run(int argc
EXT2FS_ATTR((unused
)), char *argv
[],
949 int sci_idx
EXT2FS_ATTR((unused
)),
950 void *infop
EXT2FS_ATTR((unused
)))
954 if (check_fs_open(argv
[0]))
956 if (check_fs_read_write(argv
[0]))
958 if (check_fs_bitmaps(argv
[0]))
960 if (current_journal
) {
961 printf("Please close the journal before recovering it.\n");
965 err
= ext2fs_run_ext3_journal(¤t_fs
);
967 com_err("journal_run", err
, "while recovering journal");
969 ext2fs_clear_feature_journal_needs_recovery(current_fs
->super
);
970 ext2fs_mark_super_dirty(current_fs
);