Пример #1
0
static errcode_t walk_journal(ocfs2_filesys *fs, int slot, 
			      struct journal_info *ji, char *buf, int recover)
{
	errcode_t err, ret = 0;
	uint32_t next_seq;
	uint64_t next_block, nr;
	journal_superblock_t *jsb = ji->ji_jsb;
	journal_header_t jh;

	next_seq = jsb->s_sequence;
	next_block = jsb->s_start;

	/* s_start == 0 when we have nothing to do */
	if (next_block == 0)
		return 0;

	/* ret is set when bad tags are seen in the first scan and when there
	 * are io errors in the recovery scan.  Only stop walking the journal
	 * when bad tags are seen in the first scan. */
	while(recover || !ret) {
		verbosef("next_seq %"PRIu32" final_seq %"PRIu32" next_block "
			 "%"PRIu64"\n", next_seq, ji->ji_final_seq,
			 next_block);

		if (recover && seq_geq(next_seq, ji->ji_final_seq))
			break;

		/* only mark the blocks used on the first pass */
		err = read_journal_block(fs, ji, next_block, buf, !recover);
		if (err) {
			ret = err;
			break;
		}

		next_block = jwrap(jsb, next_block + 1);

		memcpy(&jh, buf, sizeof(jh));
		jh.h_magic = be32_to_cpu(jh.h_magic);
		jh.h_blocktype = be32_to_cpu(jh.h_blocktype);
		jh.h_sequence = be32_to_cpu(jh.h_sequence);

		verbosef("jh magic %x\n", jh.h_magic);

		if (jh.h_magic != JBD2_MAGIC_NUMBER)
			break;

		verbosef("jh block %x\n", jh.h_blocktype);
		verbosef("jh seq %"PRIu32"\n", jh.h_sequence);

		if (jh.h_sequence != next_seq)
			break;

		switch(jh.h_blocktype) {
		case JBD2_DESCRIPTOR_BLOCK:
			verbosef("found a desc type %x\n", jh.h_blocktype);
			/* replay the blocks described in the desc block */
			if (recover) {
				err = replay_blocks(fs, ji, buf, next_seq, 
						    &next_block);
				if (err)
					ret = err;
				continue;
			}

			/* just record the blocks as used and carry on */ 
			err = count_tags(fs, jsb, buf, &nr);
			if (err)
				ret = err;
			else
				next_block = jwrap(jsb, next_block + nr);
			break;

		case JBD2_COMMIT_BLOCK:
			verbosef("found a commit type %x\n", jh.h_blocktype);
			next_seq++;
			break;

		case JBD2_REVOKE_BLOCK:
			verbosef("found a revoke type %x\n", jh.h_blocktype);
			add_revoke_records(ji, buf, jsb->s_blocksize,
					   next_seq);
			break;

		default:
			verbosef("unknown type %x\n", jh.h_blocktype);
			break;
		}
	}

	verbosef("done scanning with seq %"PRIu32"\n", next_seq);

	if (!recover) {
		ji->ji_set_final_seq = 1;
		ji->ji_final_seq = next_seq;
	} else if (ji->ji_final_seq != next_seq) {
		printf("Replaying slot %d's journal stopped at seq %"PRIu32" "
		       "but an initial scan indicated that it should have "
		       "stopped at seq %"PRIu32"\n", ji->ji_slot, next_seq,
		       ji->ji_final_seq);
		if (ret == 0)
			err = OCFS2_ET_IO;
	}

	return ret;
}
Пример #2
0
static void dump_journal(char *cmdname, FILE *out_file, 
			 struct journal_source *source)
{
	struct ext2_super_block *sb;
	char			jsb_buffer[1024];
	char			buf[8192];
	journal_superblock_t	*jsb;
	unsigned int		blocksize = 1024;
	unsigned int		got;
	int			retval;
	__u32			magic, sequence, blocktype;
	journal_header_t	*header;
	
	tid_t			transaction;
	unsigned int		blocknr = 0;
	
	/* First, check to see if there's an ext2 superblock header */
	retval = read_journal_block(cmdname, source, 0, 
				    buf, 2048, &got);
	if (retval)
		return;

	jsb = (journal_superblock_t *) buf;
	sb = (struct ext2_super_block *) (buf+1024);
#ifdef ENABLE_SWAPFS
	if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) 
		ext2fs_swap_super(sb);
#endif
	
	if ((be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) &&
	    (sb->s_magic == EXT2_SUPER_MAGIC) &&
	    (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
		blocksize = EXT2_BLOCK_SIZE(sb);
		blocknr = (blocksize == 1024) ? 2 : 1;
		uuid_unparse(sb->s_uuid, jsb_buffer);
		fprintf(out_file, "Ext2 superblock header found.\n");
		if (dump_all) {
			fprintf(out_file, "\tuuid=%s\n", jsb_buffer);
			fprintf(out_file, "\tblocksize=%d\n", blocksize);
			fprintf(out_file, "\tjournal data size %ld\n",
				(long) sb->s_blocks_count);
		}
	}
	
	/* Next, read the journal superblock */

	retval = read_journal_block(cmdname, source, blocknr*blocksize, 
				    jsb_buffer, 1024, &got);
	if (retval)
		return;

	jsb = (journal_superblock_t *) jsb_buffer;
	if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) {
		fprintf(out_file,
			"Journal superblock magic number invalid!\n");
		return;
	}
	blocksize = be32_to_cpu(jsb->s_blocksize);
	transaction = be32_to_cpu(jsb->s_sequence);
	blocknr = be32_to_cpu(jsb->s_start);

	fprintf(out_file, "Journal starts at block %u, transaction %u\n",
		blocknr, transaction);

	if (!blocknr)
		/* Empty journal, nothing to do. */
		return;
		
	while (1) {
		retval = read_journal_block(cmdname, source, 
					    blocknr*blocksize, buf,
					    blocksize, &got);
		if (retval || got != blocksize)
			return;
	
		header = (journal_header_t *) buf;

		magic = be32_to_cpu(header->h_magic);
		sequence = be32_to_cpu(header->h_sequence);
		blocktype = be32_to_cpu(header->h_blocktype);
		
		if (magic != JFS_MAGIC_NUMBER) {
			fprintf (out_file, "No magic number at block %u: "
				 "end of journal.\n", blocknr);
			return;
		}
		
		if (sequence != transaction) {
			fprintf (out_file, "Found sequence %u (not %u) at "
				 "block %u: end of journal.\n", 
				 sequence, transaction, blocknr);
			return;
		}

		if (dump_descriptors) {
			fprintf (out_file, "Found expected sequence %u, "
				 "type %u (%s) at block %u\n",
				 sequence, blocktype, 
				 type_to_name(blocktype), blocknr);
		}
		
		switch (blocktype) {
		case JFS_DESCRIPTOR_BLOCK:
			dump_descriptor_block(out_file, source, buf, jsb, 
					      &blocknr, blocksize,
					      transaction);
			continue;

		case JFS_COMMIT_BLOCK:
			transaction++;
			blocknr++;
			WRAP(jsb, blocknr);
			continue;
			
		case JFS_REVOKE_BLOCK:
			dump_revoke_block(out_file, buf, jsb,
					  blocknr, blocksize, 
					  transaction);
			blocknr++;
			WRAP(jsb, blocknr);
			continue;

		default:
			fprintf (out_file, "Unexpected block type %u at "
				 "block %u.\n", blocktype, blocknr);
			return;
		}
	}
}
Пример #3
0
static errcode_t replay_blocks(ocfs2_filesys *fs, struct journal_info *ji,
			       char *buf, uint64_t seq, uint64_t *next_block)
{
	char *tagp;
	journal_block_tag_t *tag;
	size_t i, num;
	char *io_buf = NULL;
	errcode_t err, ret = 0;
	int tag_bytes = ocfs2_journal_tag_bytes(ji->ji_jsb);
	uint32_t t_flags;
	uint64_t block64;
		
	tagp = buf + sizeof(journal_header_t);
	num = (ji->ji_jsb->s_blocksize - sizeof(journal_header_t)) / 
		tag_bytes;

	ret = ocfs2_malloc_blocks(fs->fs_io, 1, &io_buf);
	if (ret) {
		com_err(whoami, ret, "while allocating a block buffer");
		goto out;
	}

	for(i = 0; i < num; i++, tagp += tag_bytes, (*next_block)++) {
		tag = (journal_block_tag_t *)tagp;
		t_flags = be32_to_cpu(tag->t_flags);
		block64 = ocfs2_journal_tag_block(tag, tag_bytes);

		*next_block = jwrap(ji->ji_jsb, *next_block);

		verbosef("recovering journal block %"PRIu64" to disk block "
			 "%"PRIu64"\n", *next_block, block64);

		if (revoke_this_block(&ji->ji_revoke, block64, seq))
			goto skip_io;

		err = read_journal_block(fs, ji, *next_block, io_buf, 1);
		if (err) {
			ret = err;
			goto skip_io;
		}

		if (t_flags & JBD2_FLAG_ESCAPE) {
			uint32_t magic = cpu_to_be32(JBD2_MAGIC_NUMBER);
			memcpy(io_buf, &magic, sizeof(magic));
		}

		err = io_write_block(fs->fs_io, block64, 1, io_buf);
		if (err)
			ret = err;

	skip_io:
		if (t_flags & JBD2_FLAG_LAST_TAG)
			i = num; /* be sure to increment next_block */
		if (!(t_flags & JBD2_FLAG_SAME_UUID))
			tagp += 16;
	}
	
out:
	if (io_buf)
		ocfs2_free(&io_buf);
	return ret;
}