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=%d 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(JFS_MAGIC_NUMBER);
89 commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK);
90 commit->h_sequence = ext2fs_cpu_to_be32(trans->tid);
91 if (jfs_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 = journal_bmap(trans->journal, cblk,
107 mark_buffer_uptodate(cbh, 0);
108 ll_rw_block(READ, 1, &cbh);
112 csum_v1 = ext2fs_crc32_be(csum_v1,
113 (unsigned char const *)cbh->b_data,
117 commit->h_chksum_type = JFS_CRC32_CHKSUM;
118 commit->h_chksum_size = JFS_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 = 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(WRITE, 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 journal_revoke_header_t *jrb;
168 int sz, csum_size = 0;
169 struct buffer_head *bh;
172 JOURNAL_CHECK_TRANS_MAGIC(trans);
174 if ((trans->flags & J_TRANS_COMMITTED) ||
175 !(trans->flags & J_TRANS_OPEN))
176 return EXT2_ET_INVALID_ARGUMENT;
181 /* Do we need to leave space at the end for a checksum? */
182 if (journal_has_csum_v2or3(trans->journal))
183 csum_size = sizeof(struct journal_revoke_tail);
185 curr_blk = trans->block;
187 bh = getblk(trans->journal->j_dev, curr_blk,
188 trans->journal->j_blocksize);
191 jrb = buf = bh->b_data;
192 jrb->r_header.h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
193 jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK);
194 jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
195 offset = sizeof(*jrb);
197 if (jfs_has_feature_64bit(trans->journal))
202 for (i = 0; i < revoke_len; i++) {
203 /* Block full, write to journal */
204 if (offset + sz > trans->journal->j_blocksize - csum_size) {
205 jrb->r_count = ext2fs_cpu_to_be32(offset);
206 jbd2_revoke_csum_set(trans->journal, bh);
208 err = journal_bmap(trans->journal, curr_blk,
212 dbg_printf("Writing revoke block at %llu:%llu\n",
213 curr_blk, bh->b_blocknr);
214 mark_buffer_dirty(bh);
215 ll_rw_block(WRITE, 1, &bh);
220 offset = sizeof(*jrb);
224 if (revoke_list[i] >=
225 ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
226 err = EXT2_ET_BAD_BLOCK_NUM;
230 if (jfs_has_feature_64bit(trans->journal))
231 *((__u64 *)(&((char *)buf)[offset])) =
232 ext2fs_cpu_to_be64(revoke_list[i]);
234 *((__u32 *)(&((char *)buf)[offset])) =
235 ext2fs_cpu_to_be32(revoke_list[i]);
240 jrb->r_count = ext2fs_cpu_to_be32(offset);
241 jbd2_revoke_csum_set(trans->journal, bh);
243 err = journal_bmap(trans->journal, curr_blk, &bh->b_blocknr);
246 dbg_printf("Writing revoke block at %llu:%llu\n",
247 curr_blk, bh->b_blocknr);
248 mark_buffer_dirty(bh);
249 ll_rw_block(WRITE, 1, &bh);
257 trans->block = curr_blk;
262 static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
263 blk64_t *block_list, size_t block_len,
266 blk64_t curr_blk, jdb_blk;
269 journal_header_t *jdb;
270 journal_block_tag_t *jdbt;
272 void *buf = NULL, *jdb_buf = NULL;
273 struct buffer_head *bh = NULL, *data_bh;
276 JOURNAL_CHECK_TRANS_MAGIC(trans);
278 if ((trans->flags & J_TRANS_COMMITTED) ||
279 !(trans->flags & J_TRANS_OPEN))
280 return EXT2_ET_INVALID_ARGUMENT;
285 /* Do we need to leave space at the end for a checksum? */
286 if (journal_has_csum_v2or3(trans->journal))
287 csum_size = sizeof(struct journal_block_tail);
289 curr_blk = jdb_blk = trans->block;
291 data_bh = getblk(trans->journal->j_dev, curr_blk,
292 trans->journal->j_blocksize);
295 buf = data_bh->b_data;
297 /* write the descriptor block header */
298 bh = getblk(trans->journal->j_dev, curr_blk,
299 trans->journal->j_blocksize);
304 jdb = jdb_buf = bh->b_data;
305 jdb->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
306 jdb->h_blocktype = ext2fs_cpu_to_be32(JFS_DESCRIPTOR_BLOCK);
307 jdb->h_sequence = ext2fs_cpu_to_be32(trans->tid);
308 jdbt = (journal_block_tag_t *)(jdb + 1);
311 for (i = 0; i < block_len; i++) {
312 j = fread(data_bh->b_data, trans->journal->j_blocksize, 1, fp);
318 tag_bytes = journal_tag_bytes(trans->journal);
320 /* No space left in descriptor block, write it out */
321 if ((char *)jdbt + tag_bytes >
322 (char *)jdb_buf + trans->journal->j_blocksize - csum_size) {
323 jbd2_descr_block_csum_set(trans->journal, bh);
324 err = journal_bmap(trans->journal, jdb_blk,
328 dbg_printf("Writing descriptor block at %llu:%llu\n",
329 jdb_blk, bh->b_blocknr);
330 mark_buffer_dirty(bh);
331 ll_rw_block(WRITE, 1, &bh);
336 jdbt = (journal_block_tag_t *)(jdb + 1);
342 ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
343 err = EXT2_ET_BAD_BLOCK_NUM;
347 /* Fill out the block tag */
348 jdbt->t_blocknr = ext2fs_cpu_to_be32(block_list[i] & 0xFFFFFFFF);
350 if (jdbt != (journal_block_tag_t *)(jdb + 1))
351 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID);
353 memcpy(jdbt + tag_bytes,
354 trans->journal->j_superblock->s_uuid,
355 sizeof(trans->journal->j_superblock->s_uuid));
358 if (i == block_len - 1)
359 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG);
360 if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
362 jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE);
364 if (jfs_has_feature_64bit(trans->journal))
365 jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32);
366 jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh,
369 /* Write the data block */
370 err = journal_bmap(trans->journal, curr_blk,
371 &data_bh->b_blocknr);
374 dbg_printf("Writing data block %llu at %llu:%llu tag %d\n",
375 block_list[i], curr_blk, data_bh->b_blocknr,
377 mark_buffer_dirty(data_bh);
378 ll_rw_block(WRITE, 1, &data_bh);
379 err = data_bh->b_err;
384 jdbt = (journal_block_tag_t *)(((char *)jdbt) + tag_bytes);
387 /* Write out the last descriptor block */
388 if (jdbt != (journal_block_tag_t *)(jdb + 1)) {
389 jbd2_descr_block_csum_set(trans->journal, bh);
390 err = journal_bmap(trans->journal, jdb_blk, &bh->b_blocknr);
393 dbg_printf("Writing descriptor block at %llu:%llu\n",
394 jdb_blk, bh->b_blocknr);
395 mark_buffer_dirty(bh);
396 ll_rw_block(WRITE, 1, &bh);
403 trans->block = curr_blk;
410 static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
411 blk64_t revoke_blocks)
416 /* Estimate # of revoke blocks */
417 bs = journal->j_blocksize;
418 if (journal_has_csum_v2or3(journal))
419 bs -= sizeof(struct journal_revoke_tail);
420 sz = jfs_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32);
421 ret += revoke_blocks * sz / bs;
423 /* Estimate # of data blocks */
424 bs = journal->j_blocksize - 16;
425 if (journal_has_csum_v2or3(journal))
426 bs -= sizeof(struct journal_block_tail);
427 sz = journal_tag_bytes(journal);
428 ret += data_blocks * sz / bs;
435 static errcode_t journal_open_trans(journal_t *journal,
436 journal_transaction_t *trans,
439 trans->fs = journal->j_fs_dev->k_fs;
440 trans->journal = journal;
441 trans->flags = J_TRANS_OPEN;
443 if (journal->j_tail == 0) {
444 /* Clean journal, start at the tail */
445 trans->tid = journal->j_tail_sequence;
446 trans->start = journal->j_first;
448 /* Put new transaction at the head of the list */
449 trans->tid = journal->j_transaction_sequence;
450 trans->start = journal->j_head;
453 trans->block = trans->start;
454 if (trans->start + blocks > journal->j_last)
456 trans->end = trans->block + blocks;
457 journal_dump_trans(trans, "new transaction");
459 trans->magic = J_TRANS_MAGIC;
463 static errcode_t journal_close_trans(journal_transaction_t *trans)
467 JOURNAL_CHECK_TRANS_MAGIC(trans);
469 if (!(trans->flags & J_TRANS_COMMITTED))
472 journal = trans->journal;
473 if (journal->j_tail == 0) {
474 /* Update the tail */
475 journal->j_tail_sequence = trans->tid;
476 journal->j_tail = trans->start;
477 journal->j_superblock->s_start = ext2fs_cpu_to_be32(trans->start);
480 /* Update the head */
481 journal->j_head = trans->end + 1;
482 journal->j_transaction_sequence = trans->tid + 1;
486 /* Mark ourselves as needing recovery */
487 if (!ext2fs_has_feature_journal_needs_recovery(trans->fs->super)) {
488 ext2fs_set_feature_journal_needs_recovery(trans->fs->super);
489 ext2fs_mark_super_dirty(trans->fs);
495 #define JOURNAL_WRITE_NO_COMMIT 1
496 static errcode_t journal_write(journal_t *journal,
497 int flags, blk64_t *block_list,
498 size_t block_len, blk64_t *revoke_list,
499 size_t revoke_len, FILE *fp)
502 journal_transaction_t trans;
505 if (revoke_len > 0) {
506 jfs_set_feature_revoke(journal);
507 mark_buffer_dirty(journal->j_sb_buffer);
510 blocks = journal_guess_blocks(journal, block_len, revoke_len);
511 err = journal_open_trans(journal, &trans, blocks);
515 err = journal_add_blocks_to_trans(&trans, block_list, block_len, fp);
519 err = journal_add_revoke_to_trans(&trans, revoke_list, revoke_len);
523 if (!(flags & JOURNAL_WRITE_NO_COMMIT)) {
524 err = journal_commit_trans(&trans);
529 err = journal_close_trans(&trans);
536 void do_journal_write(int argc, char *argv[])
538 blk64_t *blist = NULL, *rlist = NULL;
539 size_t bn = 0, rn = 0;
545 if (current_journal == NULL) {
546 printf("Journal not open.\n");
551 while ((opt = getopt(argc, argv, "b:r:c")) != -1) {
554 err = read_list(optarg, &blist, &bn);
556 com_err(argv[0], err,
557 "while reading block list");
560 err = read_list(optarg, &rlist, &rn);
562 com_err(argv[0], err,
563 "while reading revoke list");
566 flags |= JOURNAL_WRITE_NO_COMMIT;
569 printf("%s [-b blocks] [-r revoke] [-c] file\n",
571 printf("-b: Write these blocks into transaction.\n");
572 printf("-c: Do not commit transaction.\n");
573 printf("-r: Revoke these blocks from transaction.\n");
579 if (bn > 0 && optind != argc - 1) {
580 printf("Need a file to read blocks from.\n");
585 fp = fopen(argv[optind], "r");
587 com_err(argv[0], errno,
588 "while opening journal data file");
593 err = journal_write(current_journal, flags, blist, bn,
596 com_err("journal_write", err, "while writing journal");
607 /* Make sure we wrap around the log correctly! */
608 #define wrap(journal, var) \
610 if (var >= (journal)->j_last) \
611 var -= ((journal)->j_last - (journal)->j_first); \
615 * Count the number of in-use tags in a journal descriptor block.
618 static int count_tags(journal_t *journal, char *buf)
621 journal_block_tag_t *tag;
622 int nr = 0, size = journal->j_blocksize;
623 int tag_bytes = journal_tag_bytes(journal);
625 if (journal_has_csum_v2or3(journal))
626 size -= sizeof(struct journal_block_tail);
628 tagp = buf + sizeof(journal_header_t);
630 while ((tagp - buf + tag_bytes) <= size) {
631 tag = (journal_block_tag_t *) tagp;
635 if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID)))
638 if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG))
645 static errcode_t journal_find_head(journal_t *journal)
647 unsigned int next_commit_ID;
648 blk64_t next_log_block, head_block;
650 journal_superblock_t *sb;
651 journal_header_t *tmp;
652 struct buffer_head *bh;
653 unsigned int sequence;
657 * First thing is to establish what we expect to find in the log
658 * (in terms of transaction IDs), and where (in terms of log
659 * block offsets): query the superblock.
662 sb = journal->j_superblock;
663 next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
664 next_log_block = ext2fs_be32_to_cpu(sb->s_start);
665 head_block = next_log_block;
667 if (next_log_block == 0)
670 bh = getblk(journal->j_dev, 0, journal->j_blocksize);
675 * Now we walk through the log, transaction by transaction,
676 * making sure that each transaction has a commit block in the
677 * expected place. Each complete transaction gets replayed back
678 * into the main filesystem.
681 dbg_printf("Scanning for sequence ID %u at %lu/%lu\n",
682 next_commit_ID, (unsigned long)next_log_block,
685 /* Skip over each chunk of the transaction looking
686 * either the next descriptor block or the final commit
688 err = journal_bmap(journal, next_log_block, &bh->b_blocknr);
691 mark_buffer_uptodate(bh, 0);
692 ll_rw_block(READ, 1, &bh);
698 wrap(journal, next_log_block);
700 /* What kind of buffer is it?
702 * If it is a descriptor block, check that it has the
703 * expected sequence number. Otherwise, we're all done
706 tmp = (journal_header_t *)bh->b_data;
708 if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
709 dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic);
713 blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
714 sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
715 dbg_printf("Found magic %d, sequence %d\n",
716 blocktype, sequence);
718 if (sequence != next_commit_ID) {
719 dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n",
720 sequence, next_commit_ID);
724 /* OK, we have a valid descriptor block which matches
725 * all of the sequence number checks. What are we going
726 * to do with it? That depends on the pass... */
729 case JFS_DESCRIPTOR_BLOCK:
730 next_log_block += count_tags(journal, bh->b_data);
731 wrap(journal, next_log_block);
734 case JFS_COMMIT_BLOCK:
735 head_block = next_log_block;
739 case JFS_REVOKE_BLOCK:
743 dbg_printf("Unrecognised magic %d, end of scan.\n",
752 dbg_printf("head seq=%d blk=%llu\n", next_commit_ID,
754 journal->j_transaction_sequence = next_commit_ID;
755 journal->j_head = head_block;
761 static void update_journal_csum(journal_t *journal, int ver)
763 journal_superblock_t *jsb;
765 if (journal->j_format_version < 2)
768 if (journal->j_tail != 0 ||
769 ext2fs_has_feature_journal_needs_recovery(
770 journal->j_fs_dev->k_fs->super)) {
771 printf("Journal needs recovery, will not add csums.\n");
775 /* metadata_csum implies journal csum v3 */
776 jsb = journal->j_superblock;
777 if (ext2fs_has_feature_metadata_csum(journal->j_fs_dev->k_fs->super)) {
778 printf("Setting csum v%d\n", ver);
781 jfs_clear_feature_csum3(journal);
782 jfs_set_feature_csum2(journal);
783 jfs_clear_feature_checksum(journal);
786 jfs_set_feature_csum3(journal);
787 jfs_clear_feature_csum2(journal);
788 jfs_clear_feature_checksum(journal);
791 printf("Unknown checksum v%d\n", ver);
794 journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM;
795 journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
796 sizeof(jsb->s_uuid));
798 jfs_clear_feature_csum3(journal);
799 jfs_clear_feature_csum2(journal);
800 jfs_set_feature_checksum(journal);
804 static void update_uuid(journal_t *journal)
809 if (journal->j_format_version < 2)
812 for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++)
813 if (journal->j_superblock->s_uuid[z])
818 fs = journal->j_fs_dev->k_fs;
819 if (!ext2fs_has_feature_64bit(fs->super))
822 if (jfs_has_feature_64bit(journal) &&
823 ext2fs_has_feature_64bit(fs->super))
826 if (journal->j_tail != 0 ||
827 ext2fs_has_feature_journal_needs_recovery(fs->super)) {
828 printf("Journal needs recovery, will not set 64bit.\n");
832 memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid,
833 sizeof(fs->super->s_uuid));
836 static void update_64bit_flag(journal_t *journal)
838 if (journal->j_format_version < 2)
841 if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
844 if (jfs_has_feature_64bit(journal) &&
845 ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
848 if (journal->j_tail != 0 ||
849 ext2fs_has_feature_journal_needs_recovery(
850 journal->j_fs_dev->k_fs->super)) {
851 printf("Journal needs recovery, will not set 64bit.\n");
855 jfs_set_feature_64bit(journal);
858 void do_journal_open(int argc, char *argv[])
860 int opt, enable_csum = 0, csum_ver = 3;
864 if (check_fs_open(argv[0]))
866 if (check_fs_read_write(argv[0]))
868 if (check_fs_bitmaps(argv[0]))
870 if (current_journal) {
871 printf("Journal is already open.\n");
874 if (!ext2fs_has_feature_journal(current_fs->super)) {
875 printf("Journalling is not enabled on this filesystem.\n");
880 while ((opt = getopt(argc, argv, "cv:f:")) != -1) {
886 if (current_fs->journal_name)
887 free(current_fs->journal_name);
888 current_fs->journal_name = strdup(optarg);
891 csum_ver = atoi(optarg);
892 if (csum_ver != 2 && csum_ver != 3) {
893 printf("Unknown journal csum v%d\n", csum_ver);
898 printf("%s: [-c] [-v ver] [-f ext_jnl]\n", argv[0]);
899 printf("-c: Enable journal checksumming.\n");
900 printf("-v: Use this version checksum format.\n");
901 printf("-j: Load this external journal.\n");
905 err = ext2fs_open_journal(current_fs, ¤t_journal);
907 com_err(argv[0], err, "while opening journal");
910 journal = current_journal;
912 dbg_printf("JOURNAL: seq=%d tailseq=%d start=%lu first=%lu "
913 "maxlen=%lu\n", journal->j_tail_sequence,
914 journal->j_transaction_sequence, journal->j_tail,
915 journal->j_first, journal->j_last);
917 update_uuid(journal);
918 update_64bit_flag(journal);
920 update_journal_csum(journal, csum_ver);
922 err = journal_find_head(journal);
924 com_err(argv[0], err, "while examining journal");
927 void do_journal_close(int argc EXT2FS_ATTR((unused)),
928 char *argv[] EXT2FS_ATTR((unused)))
930 if (current_journal == NULL) {
931 printf("Journal not open.\n");
935 ext2fs_close_journal(current_fs, ¤t_journal);
938 void do_journal_run(int argc EXT2FS_ATTR((unused)), char *argv[])
942 if (check_fs_open(argv[0]))
944 if (check_fs_read_write(argv[0]))
946 if (check_fs_bitmaps(argv[0]))
948 if (current_journal) {
949 printf("Please close the journal before recovering it.\n");
953 err = ext2fs_run_ext3_journal(¤t_fs);
955 com_err("journal_run", err, "while recovering journal");
957 ext2fs_clear_feature_journal_needs_recovery(current_fs->super);
958 ext2fs_mark_super_dirty(current_fs);