]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - e2fsck/journal.c
Minor bug fixes in the blkid library.
[thirdparty/e2fsprogs.git] / e2fsck / journal.c
CommitLineData
17390c04
TT
1/*
2 * journal.c --- code for handling the "ext3" journal
3b5386dc
TT
3 *
4 * Copyright (C) 2000 Andreas Dilger
5 * Copyright (C) 2000 Theodore Ts'o
6 *
7 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
8 * Copyright (C) 1999 Red Hat Software
9 *
10 * This file may be redistributed under the terms of the
11 * GNU General Public License version 2 or at your discretion
12 * any later version.
17390c04
TT
13 */
14
3b5386dc
TT
15#ifdef HAVE_SYS_MOUNT_H
16#include <sys/mount.h>
17#define MNT_FL (MS_MGC_VAL | MS_RDONLY)
18#endif
19#ifdef HAVE_SYS_STAT_H
20#include <sys/stat.h>
21#endif
17390c04 22
53ef44c4 23#define E2FSCK_INCLUDE_INLINE_FUNCS
0e8a9560 24#include "jfs_user.h"
3b5386dc
TT
25#include "problem.h"
26#include "uuid/uuid.h"
17390c04 27
8cf93332 28#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */
3b5386dc 29static int bh_count = 0;
3b5386dc
TT
30#endif
31
d1a2182a
TT
32/*
33 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
34 * This creates a larger static binary, and a smaller binary using
35 * shared libraries. It's also probably slightly less CPU-efficient,
36 * which is why it's not on by default. But, it's a good way of
37 * testing the functions in inode_io.c and fileio.c.
38 */
39#undef USE_INODE_IO
40
b2f93192
TT
41/* Kernel compatibility functions for handling the journal. These allow us
42 * to use the recovery.c file virtually unchanged from the kernel, so we
43 * don't have to do much to keep kernel and user recovery in sync.
44 */
8cf93332 45int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
3b5386dc 46{
d1a2182a
TT
47#ifdef USE_INODE_IO
48 *phys = block;
49 return 0;
50#else
8cf93332
TT
51 struct inode *inode = journal->j_inode;
52 errcode_t retval;
53 blk_t pblk;
3b5386dc 54
8cf93332
TT
55 if (!inode) {
56 *phys = block;
57 return 0;
58 }
3b5386dc 59
8cf93332
TT
60 retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
61 &inode->i_ext2, NULL, 0, block, &pblk);
62 *phys = pblk;
63 return (retval);
d1a2182a 64#endif
3b5386dc
TT
65}
66
8cf93332 67struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
3b5386dc
TT
68{
69 struct buffer_head *bh;
70
8cf93332 71 bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
3b5386dc
TT
72 if (!bh)
73 return NULL;
74
75 jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
53ef44c4 76 (unsigned long) blocknr, blocksize, ++bh_count);
3b5386dc 77
8cf93332
TT
78 bh->b_ctx = kdev->k_ctx;
79 if (kdev->k_dev == K_DEV_FS)
80 bh->b_io = kdev->k_ctx->fs->io;
81 else
82 bh->b_io = kdev->k_ctx->journal_io;
3b5386dc
TT
83 bh->b_size = blocksize;
84 bh->b_blocknr = blocknr;
85
86 return bh;
87}
88
0e8a9560 89void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
3b5386dc
TT
90{
91 int retval;
0e8a9560 92 struct buffer_head *bh;
3b5386dc 93
0e8a9560
TT
94 for (; nr > 0; --nr) {
95 bh = *bhp++;
96 if (rw == READ && !bh->b_uptodate) {
97 jfs_debug(3, "reading block %lu/%p\n",
53ef44c4 98 (unsigned long) bh->b_blocknr, (void *) bh);
8cf93332 99 retval = io_channel_read_blk(bh->b_io,
0e8a9560
TT
100 bh->b_blocknr,
101 1, bh->b_data);
102 if (retval) {
103 com_err(bh->b_ctx->device_name, retval,
104 "while reading block %ld\n",
105 bh->b_blocknr);
106 bh->b_err = retval;
107 continue;
108 }
109 bh->b_uptodate = 1;
110 } else if (rw == WRITE && bh->b_dirty) {
111 jfs_debug(3, "writing block %lu/%p\n",
53ef44c4 112 (unsigned long) bh->b_blocknr, (void *) bh);
8cf93332 113 retval = io_channel_write_blk(bh->b_io,
0e8a9560
TT
114 bh->b_blocknr,
115 1, bh->b_data);
116 if (retval) {
117 com_err(bh->b_ctx->device_name, retval,
118 "while writing block %ld\n",
119 bh->b_blocknr);
120 bh->b_err = retval;
121 continue;
122 }
123 bh->b_dirty = 0;
124 bh->b_uptodate = 1;
125 } else
126 jfs_debug(3, "no-op %s for block %lu\n",
127 rw == READ ? "read" : "write",
53ef44c4 128 (unsigned long) bh->b_blocknr);
0e8a9560 129 }
3b5386dc
TT
130}
131
8cf93332 132void mark_buffer_dirty(struct buffer_head *bh)
3b5386dc 133{
8cf93332 134 bh->b_dirty = 1;
3b5386dc
TT
135}
136
6a6d3d44
TT
137static void mark_buffer_clean(struct buffer_head * bh)
138{
139 bh->b_dirty = 0;
140}
141
3b5386dc
TT
142void brelse(struct buffer_head *bh)
143{
144 if (bh->b_dirty)
0e8a9560 145 ll_rw_block(WRITE, 1, &bh);
3b5386dc 146 jfs_debug(3, "freeing block %lu/%p (total %d)\n",
53ef44c4 147 (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
3b5386dc
TT
148 ext2fs_free_mem((void **) &bh);
149}
150
151int buffer_uptodate(struct buffer_head *bh)
152{
153 return bh->b_uptodate;
154}
155
15986f79
TT
156void mark_buffer_uptodate(struct buffer_head *bh, int val)
157{
158 bh->b_uptodate = val;
159}
160
3b5386dc
TT
161void wait_on_buffer(struct buffer_head *bh)
162{
163 if (!bh->b_uptodate)
0e8a9560 164 ll_rw_block(READ, 1, &bh);
3b5386dc
TT
165}
166
80bfaa3e 167
3b5386dc
TT
168static void e2fsck_clear_recover(e2fsck_t ctx, int error)
169{
5dd8f963 170 ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
3b5386dc
TT
171
172 /* if we had an error doing journal recovery, we need a full fsck */
173 if (error)
5dd8f963 174 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
3b5386dc
TT
175 ext2fs_mark_super_dirty(ctx->fs);
176}
177
d1a2182a 178static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
3b5386dc 179{
d1a2182a
TT
180 struct ext2_super_block *sb = ctx->fs->super;
181 struct ext2_super_block jsuper;
182 struct problem_context pctx;
183 struct buffer_head *bh;
184 struct inode *j_inode = NULL;
185 struct kdev_s *dev_fs = NULL, *dev_journal;
3e699064 186 const char *journal_name = 0;
d1a2182a 187 journal_t *journal = NULL;
3e699064
TT
188 errcode_t retval = 0;
189 io_manager io_ptr = 0;
d1a2182a
TT
190 unsigned long start = 0;
191 int free_journal_name = 0;
192 int ext_journal = 0;
193
194 clear_problem_context(&pctx);
195
196 journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
197 if (!journal) {
3b5386dc
TT
198 return EXT2_ET_NO_MEMORY;
199 }
200
8cf93332
TT
201 dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
202 if (!dev_fs) {
203 retval = EXT2_ET_NO_MEMORY;
204 goto errout;
205 }
206 dev_journal = dev_fs+1;
207
8cf93332
TT
208 dev_fs->k_ctx = dev_journal->k_ctx = ctx;
209 dev_fs->k_dev = K_DEV_FS;
210 dev_journal->k_dev = K_DEV_JOURNAL;
211
d1a2182a
TT
212 journal->j_dev = dev_journal;
213 journal->j_fs_dev = dev_fs;
214 journal->j_inode = NULL;
215 journal->j_blocksize = ctx->fs->blocksize;
3b5386dc 216
d1a2182a
TT
217 if (uuid_is_null(sb->s_journal_uuid)) {
218 if (!sb->s_journal_inum)
219 return EXT2_ET_BAD_INODE_NUM;
220 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
221 "journal inode");
222 if (!j_inode) {
223 retval = EXT2_ET_NO_MEMORY;
224 goto errout;
225 }
3b5386dc 226
d1a2182a
TT
227 j_inode->i_ctx = ctx;
228 j_inode->i_ino = sb->s_journal_inum;
229
230 if ((retval = ext2fs_read_inode(ctx->fs,
231 sb->s_journal_inum,
232 &j_inode->i_ext2)))
233 goto errout;
234 if (!j_inode->i_ext2.i_links_count ||
235 !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
236 retval = EXT2_ET_NO_JOURNAL;
237 goto errout;
238 }
239 if (j_inode->i_ext2.i_size / journal->j_blocksize <
240 JFS_MIN_JOURNAL_BLOCKS) {
241 retval = EXT2_ET_JOURNAL_TOO_SMALL;
242 goto errout;
243 }
3b5386dc 244
d1a2182a 245 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
3b5386dc 246
d1a2182a
TT
247#ifdef USE_INODE_IO
248 retval = ext2fs_inode_io_intern(ctx->fs, sb->s_journal_inum,
249 &journal_name);
250 if (retval)
251 goto errout;
3b5386dc 252
d1a2182a
TT
253 io_ptr = inode_io_manager;
254#else
255 journal->j_inode = j_inode;
256 ctx->journal_io = ctx->fs->io;
257 if ((retval = journal_bmap(journal, 0, &start)) != 0)
258 goto errout;
259#endif
260 } else {
261 ext_journal = 1;
262 journal_name = ctx->journal_name;
263 if (!journal_name) {
264 journal_name = ext2fs_find_block_device(sb->s_journal_dev);
265 free_journal_name = 1;
266 }
267
268 if (!journal_name) {
269 fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
270 return EXT2_ET_LOAD_EXT_JOURNAL;
271 }
272
273 jfs_debug(1, "Using journal file %s\n", journal_name);
274 io_ptr = unix_io_manager;
3b5386dc
TT
275 }
276
d1a2182a
TT
277#if 0
278 test_io_backing_manager = io_ptr;
adee8d75 279 io_ptr = test_io_manager;
adee8d75 280#endif
d1a2182a
TT
281#ifndef USE_INODE_IO
282 if (ext_journal)
283#endif
284 retval = io_ptr->open(journal_name, IO_FLAG_RW,
285 &ctx->journal_io);
286 if (free_journal_name)
6d222f32
TT
287 free((void *) journal_name);
288 if (retval)
d1a2182a 289 goto errout;
adee8d75 290
d1a2182a
TT
291 io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
292
293 if (ext_journal) {
294 if (ctx->fs->blocksize == 1024)
295 start = 1;
296 bh = getblk(dev_journal, start, ctx->fs->blocksize);
297 if (!bh) {
298 retval = EXT2_ET_NO_MEMORY;
299 goto errout;
300 }
301 ll_rw_block(READ, 1, &bh);
302 if ((retval = bh->b_err) != 0)
303 goto errout;
304 memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024,
305 sizeof(jsuper));
306 brelse(bh);
adee8d75 307#ifdef EXT2FS_ENABLE_SWAPFS
d1a2182a
TT
308 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
309 ext2fs_swap_super(&jsuper);
adee8d75 310#endif
d1a2182a
TT
311 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
312 !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
313 fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
314 retval = EXT2_ET_LOAD_EXT_JOURNAL;
315 goto errout;
316 }
317 /* Make sure the journal UUID is correct */
318 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
319 sizeof(jsuper.s_uuid))) {
320 fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
321 retval = EXT2_ET_LOAD_EXT_JOURNAL;
322 goto errout;
323 }
adee8d75 324
d1a2182a
TT
325 journal->j_maxlen = jsuper.s_blocks_count;
326 start++;
3b5386dc
TT
327 }
328
d1a2182a 329 if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
adee8d75
TT
330 retval = EXT2_ET_NO_MEMORY;
331 goto errout;
332 }
adee8d75 333
d1a2182a
TT
334 journal->j_sb_buffer = bh;
335 journal->j_superblock = (journal_superblock_t *)bh->b_data;
336
337#ifdef USE_INODE_IO
338 if (j_inode)
339 ext2fs_free_mem((void **)&j_inode);
340#endif
341
342 *ret_journal = journal;
adee8d75
TT
343 return 0;
344
345errout:
d1a2182a
TT
346 if (dev_fs)
347 ext2fs_free_mem((void **)&dev_fs);
348 if (j_inode)
349 ext2fs_free_mem((void **)&j_inode);
350 if (journal)
351 ext2fs_free_mem((void **)&journal);
adee8d75 352 return retval;
d1a2182a 353
3b5386dc
TT
354}
355
6a6d3d44
TT
356static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
357 struct problem_context *pctx)
3b5386dc 358{
5dd8f963
TT
359 struct ext2_super_block *sb = ctx->fs->super;
360 int recover = ctx->fs->super->s_feature_incompat &
361 EXT3_FEATURE_INCOMPAT_RECOVER;
362 int has_journal = ctx->fs->super->s_feature_compat &
363 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3b5386dc 364
5dd8f963 365 if (has_journal || sb->s_journal_inum) {
3b5386dc 366 /* The journal inode is bogus, remove and force full fsck */
7e92dfae 367 pctx->ino = sb->s_journal_inum;
3b5386dc 368 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
5dd8f963 369 if (has_journal && sb->s_journal_inum)
3b5386dc
TT
370 printf("*** ext3 journal has been deleted - "
371 "filesystem is now ext2 only ***\n\n");
5dd8f963
TT
372 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
373 sb->s_journal_inum = 0;
424cd2be 374 ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3b5386dc
TT
375 e2fsck_clear_recover(ctx, 1);
376 return 0;
377 }
378 return EXT2_ET_BAD_INODE_NUM;
379 } else if (recover) {
380 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
381 e2fsck_clear_recover(ctx, 1);
382 return 0;
383 }
384 return EXT2_ET_UNSUPP_FEATURE;
385 }
386 return 0;
387}
388
62e3e7fe
TT
389#define V1_SB_SIZE 0x0024
390static void clear_v2_journal_fields(journal_t *journal)
391{
8cf93332 392 e2fsck_t ctx = journal->j_dev->k_ctx;
62e3e7fe
TT
393 struct problem_context pctx;
394
395 clear_problem_context(&pctx);
396
397 if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
398 return;
399
400 memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
401 ctx->fs->blocksize-V1_SB_SIZE);
8cf93332 402 mark_buffer_dirty(journal->j_sb_buffer);
62e3e7fe
TT
403}
404
405
6a6d3d44 406static errcode_t e2fsck_journal_load(journal_t *journal)
3b5386dc 407{
8cf93332 408 e2fsck_t ctx = journal->j_dev->k_ctx;
3b5386dc
TT
409 journal_superblock_t *jsb;
410 struct buffer_head *jbh = journal->j_sb_buffer;
411 struct problem_context pctx;
412
413 clear_problem_context(&pctx);
414
0e8a9560 415 ll_rw_block(READ, 1, &jbh);
3b5386dc
TT
416 if (jbh->b_err) {
417 com_err(ctx->device_name, jbh->b_err,
418 _("reading journal superblock\n"));
419 return jbh->b_err;
420 }
421
422 jsb = journal->j_superblock;
423 /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
424 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
425 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
426
0e8a9560
TT
427 switch (ntohl(jsb->s_header.h_blocktype)) {
428 case JFS_SUPERBLOCK_V1:
429 journal->j_format_version = 1;
62e3e7fe
TT
430 if (jsb->s_feature_compat ||
431 jsb->s_feature_incompat ||
432 jsb->s_feature_ro_compat ||
433 jsb->s_nr_users)
434 clear_v2_journal_fields(journal);
0e8a9560
TT
435 break;
436
437 case JFS_SUPERBLOCK_V2:
438 journal->j_format_version = 2;
b3b3d465 439 if (ntohl(jsb->s_nr_users) > 1 &&
62e3e7fe
TT
440 (ctx->fs->io == ctx->journal_io))
441 clear_v2_journal_fields(journal);
adee8d75
TT
442 if (ntohl(jsb->s_nr_users) > 1) {
443 fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
444 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
445 }
0e8a9560 446 break;
c7f23364
TT
447
448 /*
449 * These should never appear in a journal super block, so if
450 * they do, the journal is badly corrupted.
451 */
452 case JFS_DESCRIPTOR_BLOCK:
453 case JFS_COMMIT_BLOCK:
454 case JFS_REVOKE_BLOCK:
455 return EXT2_ET_CORRUPT_SUPERBLOCK;
0e8a9560
TT
456
457 /* If we don't understand the superblock major type, but there
458 * is a magic number, then it is likely to be a new format we
459 * just don't understand, so leave it alone. */
460 default:
c7f23364 461 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
0e8a9560
TT
462 }
463
2f686ace
TT
464 if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
465 return EXT2_ET_UNSUPP_FEATURE;
424cd2be 466
2f686ace
TT
467 if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
468 return EXT2_ET_RO_UNSUPP_FEATURE;
3b5386dc 469
0e8a9560
TT
470 /* We have now checked whether we know enough about the journal
471 * format to be able to proceed safely, so any other checks that
472 * fail we should attempt to recover from. */
473 if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
474 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
475 _("%s: no valid journal superblock found\n"),
476 ctx->device_name);
477 return EXT2_ET_CORRUPT_SUPERBLOCK;
3b5386dc
TT
478 }
479
480 if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
481 journal->j_maxlen = ntohl(jsb->s_maxlen);
482 else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
0e8a9560
TT
483 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
484 _("%s: journal too short\n"),
485 ctx->device_name);
3b5386dc
TT
486 return EXT2_ET_CORRUPT_SUPERBLOCK;
487 }
488
489 journal->j_tail_sequence = ntohl(jsb->s_sequence);
ecf1b776 490 journal->j_transaction_sequence = journal->j_tail_sequence;
3b5386dc
TT
491 journal->j_tail = ntohl(jsb->s_start);
492 journal->j_first = ntohl(jsb->s_first);
493 journal->j_last = ntohl(jsb->s_maxlen);
494
495 return 0;
496}
497
53ef44c4 498static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
6a6d3d44 499 journal_t *journal)
3b5386dc 500{
0e8a9560 501 char *p;
424cd2be
TT
502 union {
503 uuid_t uuid;
504 __u32 val[4];
505 } u;
506 __u32 new_seq = 0;
507 int i;
508
0e8a9560
TT
509 /* Leave a valid existing V1 superblock signature alone.
510 * Anything unrecognisable we overwrite with a new V2
511 * signature. */
512
513 if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
514 jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
515 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
516 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
517 }
518
519 /* Zero out everything else beyond the superblock header */
520
521 p = ((char *) jsb) + sizeof(journal_header_t);
522 memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
523
3b5386dc 524 jsb->s_blocksize = htonl(ctx->fs->blocksize);
0e8a9560
TT
525 jsb->s_maxlen = htonl(journal->j_maxlen);
526 jsb->s_first = htonl(1);
0e8a9560 527
424cd2be
TT
528 /* Initialize the journal sequence number so that there is "no"
529 * chance we will find old "valid" transactions in the journal.
530 * This avoids the need to zero the whole journal (slow to do,
531 * and risky when we are just recovering the filesystem).
532 */
533 uuid_generate(u.uuid);
534 for (i = 0; i < 4; i ++)
535 new_seq ^= u.val[i];
536 jsb->s_sequence = htonl(new_seq);
0e8a9560 537
8cf93332 538 mark_buffer_dirty(journal->j_sb_buffer);
0e8a9560 539 ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3b5386dc
TT
540}
541
6a6d3d44
TT
542static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
543 journal_t *journal,
544 struct problem_context *pctx)
3b5386dc 545{
5dd8f963
TT
546 struct ext2_super_block *sb = ctx->fs->super;
547 int recover = ctx->fs->super->s_feature_incompat &
548 EXT3_FEATURE_INCOMPAT_RECOVER;
3b5386dc 549
5dd8f963 550 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3b5386dc 551 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
b2f93192
TT
552 e2fsck_journal_reset_super(ctx, journal->j_superblock,
553 journal);
3b5386dc
TT
554 journal->j_transaction_sequence = 1;
555 e2fsck_clear_recover(ctx, recover);
556 return 0;
557 }
558 return EXT2_ET_CORRUPT_SUPERBLOCK;
559 } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
560 return EXT2_ET_CORRUPT_SUPERBLOCK;
561
562 return 0;
563}
564
6a6d3d44
TT
565static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
566 int reset, int drop)
3b5386dc
TT
567{
568 journal_superblock_t *jsb;
569
6a6d3d44
TT
570 if (drop)
571 mark_buffer_clean(journal->j_sb_buffer);
572 else if (!(ctx->options & E2F_OPT_READONLY)) {
3b5386dc
TT
573 jsb = journal->j_superblock;
574 jsb->s_sequence = htonl(journal->j_transaction_sequence);
575 if (reset)
576 jsb->s_start = 0; /* this marks the journal as empty */
8cf93332 577 mark_buffer_dirty(journal->j_sb_buffer);
3b5386dc
TT
578 }
579 brelse(journal->j_sb_buffer);
580
6d222f32
TT
581 if (ctx->journal_io) {
582 if (ctx->fs && ctx->fs->io != ctx->journal_io)
583 io_channel_close(ctx->journal_io);
584 ctx->journal_io = 0;
585 }
586
d1a2182a 587#ifndef USE_INODE_IO
3b5386dc 588 if (journal->j_inode)
6a6d3d44 589 ext2fs_free_mem((void **)&journal->j_inode);
d1a2182a
TT
590#endif
591 if (journal->j_fs_dev)
592 ext2fs_free_mem((void **)&journal->j_fs_dev);
3b5386dc
TT
593 ext2fs_free_mem((void **)&journal);
594}
595
9b565759
TT
596/*
597 * This function makes sure that the superblock fields regarding the
598 * journal are consistent.
599 */
3b5386dc
TT
600int e2fsck_check_ext3_journal(e2fsck_t ctx)
601{
5dd8f963 602 struct ext2_super_block *sb = ctx->fs->super;
3b5386dc 603 journal_t *journal;
5dd8f963
TT
604 int recover = ctx->fs->super->s_feature_incompat &
605 EXT3_FEATURE_INCOMPAT_RECOVER;
3b5386dc 606 struct problem_context pctx;
d37066a9 607 problem_t problem;
d3f35b64 608 int reset = 0, force_fsck = 0;
3b5386dc
TT
609 int retval;
610
611 /* If we don't have any journal features, don't do anything more */
5dd8f963
TT
612 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
613 !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
614 uuid_is_null(sb->s_journal_uuid))
9b565759 615 return 0;
3b5386dc
TT
616
617 clear_problem_context(&pctx);
5dd8f963 618 pctx.num = sb->s_journal_inum;
3b5386dc
TT
619
620 retval = e2fsck_get_journal(ctx, &journal);
621 if (retval) {
f2d5c937
TT
622 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
623 (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
624 (retval == EXT2_ET_NO_JOURNAL))
3b5386dc
TT
625 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
626 return retval;
627 }
628
629 retval = e2fsck_journal_load(journal);
630 if (retval) {
c7f23364 631 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2f686ace
TT
632 ((retval == EXT2_ET_UNSUPP_FEATURE) &&
633 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
634 &pctx))) ||
635 ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
636 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
637 &pctx))) ||
c7f23364
TT
638 ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
639 (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
6a6d3d44
TT
640 retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
641 &pctx);
642 e2fsck_journal_release(ctx, journal, 0, 1);
3b5386dc
TT
643 return retval;
644 }
645
646 /*
647 * We want to make the flags consistent here. We will not leave with
648 * needs_recovery set but has_journal clear. We can't get in a loop
649 * with -y, -n, or -p, only if a user isn't making up their mind.
650 */
651no_has_journal:
5dd8f963
TT
652 if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
653 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3b5386dc
TT
654 pctx.str = "inode";
655 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
656 if (recover &&
657 !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
658 goto no_has_journal;
d3f35b64
TT
659 /*
660 * Need a full fsck if we are releasing a
8c2dc521 661 * journal stored on a reserved inode.
d3f35b64
TT
662 */
663 force_fsck = recover ||
664 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
665 /* Clear all of the journal fields */
5dd8f963 666 sb->s_journal_inum = 0;
d3f35b64
TT
667 sb->s_journal_dev = 0;
668 memset(sb->s_journal_uuid, 0,
669 sizeof(sb->s_journal_uuid));
670 e2fsck_clear_recover(ctx, force_fsck);
3b5386dc 671 } else if (!(ctx->options & E2F_OPT_READONLY)) {
5dd8f963 672 sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3b5386dc
TT
673 ext2fs_mark_super_dirty(ctx->fs);
674 }
675 }
676
5dd8f963
TT
677 if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
678 !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3b5386dc 679 journal->j_superblock->s_start != 0) {
d37066a9
TT
680 /* Print status information */
681 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
682 if (ctx->superblock)
683 problem = PR_0_JOURNAL_RUN_DEFAULT;
684 else
685 problem = PR_0_JOURNAL_RUN;
686 if (fix_problem(ctx, problem, &pctx)) {
687 ctx->options |= E2F_OPT_FORCE;
688 sb->s_feature_incompat |=
689 EXT3_FEATURE_INCOMPAT_RECOVER;
690 ext2fs_mark_super_dirty(ctx->fs);
691 } else if (fix_problem(ctx,
692 PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3b5386dc 693 reset = 1;
d3f35b64
TT
694 sb->s_state &= ~EXT2_VALID_FS;
695 ext2fs_mark_super_dirty(ctx->fs);
696 }
697 /*
698 * If the user answers no to the above question, we
699 * ignore the fact that journal apparently has data;
700 * accidentally replaying over valid data would be far
701 * worse than skipping a questionable recovery.
702 *
703 * XXX should we abort with a fatal error here? What
704 * will the ext3 kernel code do if a filesystem with
705 * !NEEDS_RECOVERY but with a non-zero
706 * journal->j_superblock->s_start is mounted?
707 */
3b5386dc
TT
708 }
709
6a6d3d44 710 e2fsck_journal_release(ctx, journal, reset, 0);
3b5386dc
TT
711 return retval;
712}
713
6a6d3d44 714static errcode_t recover_ext3_journal(e2fsck_t ctx)
3b5386dc 715{
3b5386dc
TT
716 journal_t *journal;
717 int retval;
718
8cf93332 719 journal_init_revoke_caches();
3b5386dc
TT
720 retval = e2fsck_get_journal(ctx, &journal);
721 if (retval)
ecf1b776
TT
722 return retval;
723
3b5386dc
TT
724 retval = e2fsck_journal_load(journal);
725 if (retval)
6a6d3d44 726 goto errout;
3b5386dc 727
0e8a9560
TT
728 retval = journal_init_revoke(journal, 1024);
729 if (retval)
6a6d3d44 730 goto errout;
0e8a9560 731
3b5386dc 732 retval = -journal_recover(journal);
c0a083fa
TT
733 if (retval)
734 goto errout;
735
736 if (journal->j_superblock->s_errno) {
737 ctx->fs->super->s_state |= EXT2_ERROR_FS;
738 ext2fs_mark_super_dirty(ctx->fs);
739 journal->j_superblock->s_errno = 0;
8cf93332 740 mark_buffer_dirty(journal->j_sb_buffer);
c0a083fa
TT
741 }
742
6a6d3d44 743errout:
d1a2182a 744 journal_destroy_revoke(journal);
8cf93332 745 journal_destroy_revoke_caches();
6a6d3d44 746 e2fsck_journal_release(ctx, journal, 1, 0);
3b5386dc
TT
747 return retval;
748}
749
80bfaa3e
TT
750int e2fsck_run_ext3_journal(e2fsck_t ctx)
751{
752 io_manager io_ptr = ctx->fs->io->manager;
753 int blocksize = ctx->fs->blocksize;
ecf1b776 754 errcode_t retval, recover_retval;
8394902e
TT
755
756 printf(_("%s: recovering journal\n"), ctx->device_name);
ecf1b776 757 if (ctx->options & E2F_OPT_READONLY) {
8394902e 758 printf(_("%s: won't do journal recovery while read-only\n"),
ecf1b776
TT
759 ctx->device_name);
760 return EXT2_ET_FILE_RO;
761 }
762
0f2cfe25 763 if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3c6b8977 764 ext2fs_flush(ctx->fs); /* Force out any modifications */
d0515212 765
ecf1b776 766 recover_retval = recover_ext3_journal(ctx);
80bfaa3e
TT
767
768 /*
769 * Reload the filesystem context to get up-to-date data from disk
770 * because journal recovery will change the filesystem under us.
771 */
772 ext2fs_close(ctx->fs);
ecf1b776 773 retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
80bfaa3e
TT
774 ctx->superblock, blocksize, io_ptr,
775 &ctx->fs);
776
777 if (retval) {
778 com_err(ctx->program_name, retval,
779 _("while trying to re-open %s"),
780 ctx->device_name);
99a2cc96 781 fatal_error(ctx, 0);
80bfaa3e
TT
782 }
783 ctx->fs->priv_data = ctx;
17390c04 784
ecf1b776
TT
785 /* Set the superblock flags */
786 e2fsck_clear_recover(ctx, recover_retval);
787 return recover_retval;
17390c04 788}
773fd8a1
TT
789
790/*
791 * This function will move the journal inode from a visible file in
792 * the filesystem directory hierarchy to the reserved inode if necessary.
793 */
546a1ff1 794static const char * const journal_names[] = {
773fd8a1
TT
795 ".journal", "journal", ".journal.dat", "journal.dat", 0 };
796
797void e2fsck_move_ext3_journal(e2fsck_t ctx)
798{
799 struct ext2_super_block *sb = ctx->fs->super;
800 struct problem_context pctx;
801 struct ext2_inode inode;
802 ext2_filsys fs = ctx->fs;
803 ext2_ino_t ino;
804 errcode_t retval;
805 const char * const * cpp;
806 int group, mount_flags;
807
808 /*
809 * If the filesystem is opened read-only, or there is no
810 * journal, or the journal is already in the hidden inode,
811 * then do nothing.
812 */
813 if ((ctx->options & E2F_OPT_READONLY) ||
814 (sb->s_journal_inum == 0) ||
815 (sb->s_journal_inum == EXT2_JOURNAL_INO) ||
816 !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
817 return;
818
819 /*
820 * If the filesystem is mounted, or we can't tell whether
821 * or not it's mounted, do nothing.
822 */
823 retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
824 if (retval || (mount_flags & EXT2_MF_MOUNTED))
825 return;
826
827 /*
828 * If we can't find the name of the journal inode, then do
829 * nothing.
830 */
831 for (cpp = journal_names; *cpp; cpp++) {
832 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
833 strlen(*cpp), 0, &ino);
834 if ((retval == 0) && (ino == sb->s_journal_inum))
835 break;
836 }
837 if (*cpp == 0)
838 return;
839
840 /*
841 * The inode had better have only one link and not be readable.
842 */
843 if (ext2fs_read_inode(fs, ino, &inode) != 0)
844 return;
845 if (inode.i_links_count != 1)
846 return;
847
848 /* We need the inode bitmap to be loaded */
849 retval = ext2fs_read_bitmaps(fs);
850 if (retval)
851 return;
852
853 clear_problem_context(&pctx);
854 pctx.str = *cpp;
855 if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
856 return;
857
858 /*
859 * OK, we've done all the checks, let's actually move the
860 * journal inode. Errors at this point mean we need to force
861 * an ext2 filesystem check.
862 */
863 if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
864 goto err_out;
865 if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
866 goto err_out;
867 sb->s_journal_inum = EXT2_JOURNAL_INO;
868 ext2fs_mark_super_dirty(fs);
869 inode.i_links_count = 0;
870 inode.i_dtime = time(0);
871 if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
872 goto err_out;
873
874 group = ext2fs_group_of_ino(fs, ino);
875 ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
876 ext2fs_mark_ib_dirty(fs);
877 fs->group_desc[group].bg_free_inodes_count++;
878 fs->super->s_free_inodes_count++;
879 return;
880
881err_out:
882 pctx.errcode = retval;
883 fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
884 fs->super->s_state &= ~EXT2_VALID_FS;
885 ext2fs_mark_super_dirty(fs);
886 return;
887}
888