Esempio n. 1
0
static int walk_chain_func(ocfs2_filesys *fs,
			   uint64_t gd_blkno,
			   int chain_num,
			   void *priv_data)
{
	struct walk_it *wi = priv_data;
	struct ocfs2_group_desc *gd;
	errcode_t ret;

	if (wi->last_chain != chain_num) {
		fprintf(stdout, "CHAIN[%02d]: %d/%d\n", chain_num,
			wi->di->id2.i_chain.cl_recs[chain_num].c_free,
			wi->di->id2.i_chain.cl_recs[chain_num].c_total);
		wi->last_chain = chain_num;
		wi->count_free = wi->count_total = 0;
	}

	ret = ocfs2_read_group_desc(fs, gd_blkno, wi->gd_buf);
	if (ret)
		return OCFS2_CHAIN_ERROR;

	gd = (struct ocfs2_group_desc *)wi->gd_buf;
	wi->count_free += gd->bg_free_bits_count;
	wi->count_total += gd->bg_bits;
	fprintf(stdout, "     %16"PRIu64": %05d/%05d = %05d/%05d\n",
		gd->bg_blkno,
		gd->bg_free_bits_count, gd->bg_bits,
		wi->count_free, wi->count_total);

	return 0;
}
Esempio n. 2
0
static int chain_iterate_gd(struct ocfs2_chain_rec *c_rec,
			    int chain_num,
			    struct chain_context *ctxt)
{
	int iret = 0;
	uint64_t blkno;
	struct ocfs2_group_desc *gd;

	blkno = c_rec->c_blkno;

	while (blkno) {
		iret = (*ctxt->func)(ctxt->fs, blkno, chain_num,
				     ctxt->priv_data);
		if (iret & OCFS2_CHAIN_ABORT)
			break;

		ctxt->errcode = ocfs2_read_group_desc(ctxt->fs, blkno,
						      ctxt->gd_buf);
		if (ctxt->errcode) {
			iret |= OCFS2_CHAIN_ERROR;
			break;
		}
		gd = (struct ocfs2_group_desc *)ctxt->gd_buf;

		if ((gd->bg_blkno != blkno) ||
		    (gd->bg_chain != chain_num)) {
			ctxt->errcode = OCFS2_ET_CORRUPT_GROUP_DESC;
			iret |= OCFS2_CHAIN_ERROR;
			break;
		}

		blkno = gd->bg_next_group;
	}

	return iret;
}
/*
 * This function will iterate the chain_rec and do the following modifications:
 * 1. record all the groups in the chains.
 * 2. for every group, do:
 *    1) modify  Sub Alloc Slot in extent block/inodes accordingly.
 *    2) change the GROUP_PARENT according to its future owner.
 *    3) link the group to the new slot files.
 */
static errcode_t move_chain_rec(ocfs2_filesys *fs, struct relink_ctxt *ctxt)
{
	errcode_t ret = 0;
	int i, start, end = 1;
	uint64_t blkno, gd_blkno = ctxt->cr->c_blkno;
	struct ocfs2_group_desc *gd = NULL;
	struct moved_group *group = NULL, *group_head = NULL;

	if (gd_blkno == 0)
		goto bail;

	/* Record the group in the relink_ctxt.
	 *
	 * We record the group in a reverse order, so the first group
	 * will be at the end of the group list. This is useful for
	 * fsck.ocfs2 when any error happens during the move of groups
	 * and we can safely move the group also.
	 */
	while (gd_blkno) {
		ret = ocfs2_malloc0(sizeof(struct moved_group), &group);
		if (ret)
			goto bail;
		memset(group, 0, sizeof(struct moved_group));

		/* We insert the group first in case of any further error
		 * will not cause memory leak.
		 */
		group->next = group_head;
		group_head = group;

		ret = ocfs2_malloc_block(fs->fs_io, &group->gd_buf);
		if (ret)
			goto bail;

		ret = ocfs2_read_group_desc(fs, gd_blkno, group->gd_buf);
		if (ret)
			goto bail;

		group->blkno = gd_blkno;
		gd = (struct ocfs2_group_desc *)group->gd_buf;
		gd_blkno = gd->bg_next_group;
	}

	group = group_head;
	while (group) {
		gd = (struct ocfs2_group_desc *)group->gd_buf;

		end = 1;
		/* Modify the "Sub Alloc Slot" in the extent block/inodes. */
		while (end < gd->bg_bits) {
			start = ocfs2_find_next_bit_set(gd->bg_bitmap,
							gd->bg_bits, end);
			if (start >= gd->bg_bits)
				break;

			end = ocfs2_find_next_bit_clear(gd->bg_bitmap,
							gd->bg_bits, start);

			for (i = start; i < end; i++) {
				blkno = group->blkno + i;

				ret = change_sub_alloc_slot(fs, blkno, ctxt);
				if (ret)
					goto bail;

			}
		}

		/* move the group to the new slots. */
		ret = move_group(fs, ctxt, group);
		if (ret)
			goto bail;

		group = group->next;
	}

bail:
	group = group_head;
	while (group) {
		group_head = group->next;
		if (group->gd_buf)
			ocfs2_free(&group->gd_buf);
		ocfs2_free(&group);
		group = group_head;
	}
	return ret;
}
Esempio n. 4
0
static void mess_up_sys_file(ocfs2_filesys *fs, uint64_t blkno,
				enum fsck_type type)
{
	errcode_t ret;
	char *buf = NULL, *bufgroup = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_chain_list *cl;
	struct ocfs2_chain_rec *cr;
	uint64_t oldblkno;
	struct ocfs2_group_desc *bg = NULL;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_BITMAP_FL))
		FSWRK_COM_FATAL(progname, ret);

	if (!(di->i_flags & OCFS2_CHAIN_FL))
		FSWRK_COM_FATAL(progname, ret);

	cl = &(di->id2.i_chain);

	/* for CHAIN_EMPTY, CHAIN_HEAD_LINK_RANGE, CHAIN_LINK_RANGE,
	 * CHAIN_BITS, CHAIN_LINK_GEN, CHAIN_LINK_MAGIC,
	 * we need to corrupt some chain rec, so check it first.
	 */
	if (type == CHAIN_EMPTY || type == CHAIN_HEAD_LINK_RANGE ||
		type == CHAIN_LINK_RANGE || type == CHAIN_BITS 	||
		type == CHAIN_LINK_GEN	 || type == CHAIN_LINK_MAGIC)
		if (!cl->cl_next_free_rec) {
			FSWRK_WARN("No chain record found at block#%"PRIu64
				",so can't corrupt it for type[%d].\n",
				 blkno, type);
			goto bail;
		}

	switch (type) {
	case CHAIN_COUNT:
		fprintf(stdout, "Corrupt CHAIN_COUNT: "
			"Modified cl_count "
			"in block#%"PRIu64" from %u to %u\n",  blkno,
			cl->cl_count, (cl->cl_count + 100));
		cl->cl_count += 100;
		break;
	case CHAIN_NEXT_FREE:
		fprintf(stdout, "Corrupt CHAIN_NEXT_FREE:"
			" Modified cl_next_free_rec "
			"in block#%"PRIu64" from %u to %u\n", blkno,
			cl->cl_next_free_rec, (cl->cl_count + 10));
		cl->cl_next_free_rec = cl->cl_count + 10;
		break;
	case CHAIN_EMPTY:
		cr = cl->cl_recs;
		fprintf(stdout, "Corrupt CHAIN_EMPTY:"
			" Modified e_blkno "
			"in block#%"PRIu64" from %"PRIu64" to 0\n",
			 blkno,	(uint64_t)cr->c_blkno);
		cr->c_blkno = 0;
		break;
	case CHAIN_I_CLUSTERS:
		fprintf(stdout, "Corrupt CHAIN_I_CLUSTERS:"
			"change i_clusters in block#%"PRIu64" from %u to %u\n",
			 blkno, di->i_clusters, (di->i_clusters + 10));
		di->i_clusters += 10;
		break;
	case CHAIN_I_SIZE:
		fprintf(stdout, "Corrupt CHAIN_I_SIZE:"
			"change i_size "
			"in block#%"PRIu64" from %"PRIu64" to %"PRIu64"\n",
			 blkno, (uint64_t)di->i_size, ((uint64_t)di->i_size + 10));
		di->i_size += 10;
		break;
	case CHAIN_GROUP_BITS:
		fprintf(stdout, "Corrupt CHAIN_GROUP_BITS:"
			"change i_used of bitmap "
			"in block#%"PRIu64" from %u to %u\n", blkno, 
			di->id1.bitmap1.i_used, (di->id1.bitmap1.i_used + 10));
		di->id1.bitmap1.i_used += 10;
		break;
	case CHAIN_HEAD_LINK_RANGE:
		cr = cl->cl_recs;
		oldblkno = cr->c_blkno;
		cr->c_blkno = 
			ocfs2_clusters_to_blocks(fs, fs->fs_clusters) + 10;
		fprintf(stdout, "Corrupt CHAIN_HEAD_LINK_RANGE:"
			"change  "
			"in block#%"PRIu64" from %"PRIu64" to %"PRIu64"\n",
			 blkno, oldblkno, (uint64_t)cr->c_blkno);
		break;
	case CHAIN_LINK_GEN:
	case CHAIN_LINK_MAGIC:
	case CHAIN_LINK_RANGE:
		ret = ocfs2_malloc_block(fs->fs_io, &bufgroup);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
		
		bg = (struct ocfs2_group_desc *)bufgroup;
		cr = cl->cl_recs;

		ret = ocfs2_read_group_desc(fs, cr->c_blkno, (char *)bg);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		if (type == CHAIN_LINK_GEN) {
			fprintf(stdout, "Corrupt CHAIN_LINK_GEN: "
				"change generation num from %u to 0x1234\n",
				bg->bg_generation);
			bg->bg_generation = 0x1234;
		} else if (type == CHAIN_LINK_MAGIC) {
			fprintf(stdout, "Corrupt CHAIN_LINK_MAGIC: "
				"change signature to '1234'\n");
			sprintf((char *)bg->bg_signature,"1234");
		} else {
			oldblkno = bg->bg_next_group;
			bg->bg_next_group = 
			    ocfs2_clusters_to_blocks(fs, fs->fs_clusters) + 10;
			fprintf(stdout, "Corrupt CHAIN_LINK_RANGE: "
				"change next group from %"PRIu64" to %"PRIu64
				" \n", oldblkno, (uint64_t)bg->bg_next_group);
		}
		
		ret = ocfs2_write_group_desc(fs, cr->c_blkno, (char *)bg);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
		break;	
	case CHAIN_BITS:
		cr = cl->cl_recs;
		fprintf(stdout, "Corrupt CHAIN_BITS:"
			"change inode#%"PRIu64" c_total from %u to %u\n",
			 blkno, cr->c_total, (cr->c_total + 10));
		cr->c_total += 10; 
		break;
	case CHAIN_CPG:
		fprintf(stdout, "Corrupt CHAIN_CPG: "
			"change cl_cpg of global_bitmap from %u to %u.\n",
			cl->cl_cpg, (cl->cl_cpg + 16));
		cl->cl_cpg += 16;
		cl->cl_next_free_rec = 1;
		break;
	default:
		FSWRK_FATAL("Unknown fsck_type[%d]\n", type);
	}

	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

bail:
	if (bufgroup)
		ocfs2_free(&bufgroup);
	if (buf)
		ocfs2_free(&buf);

	return ;
}