Esempio n. 1
0
void mess_up_inode_alloc(ocfs2_filesys *fs, enum fsck_type type,
			 uint16_t slotnum)
{
	errcode_t ret;
	uint64_t tmpblkno;
	char *buf = NULL;
	struct ocfs2_dinode *di;

	ret = ocfs2_new_inode(fs, &tmpblkno, S_IFREG | 0755);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

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

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

	di = (struct ocfs2_dinode *)buf;

	di->i_flags &= ~OCFS2_VALID_FL;

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

	fprintf(stdout, "INODE_ALLOC_REPAIR: "
		"Create an inode#%"PRIu64" and invalidate it.\n", tmpblkno);

	if (buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 2
0
errcode_t ocfs2_write_primary_super(ocfs2_filesys *fs)
{
	errcode_t ret;
	char *blk;
	struct ocfs2_dinode *di;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;

	blk = (char *)fs->fs_super;
	di = (struct ocfs2_dinode *)blk;

	ret = OCFS2_ET_BAD_MAGIC;
	if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
		   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)))
		goto out_blk;

	ret = ocfs2_write_inode(fs, OCFS2_SUPER_BLOCK_BLKNO, blk);
	if (ret)
		goto out_blk;

	return 0;

out_blk:
	return ret;
}
Esempio n. 3
0
errcode_t ocfs2_extend_file(ocfs2_filesys *fs, uint64_t ino, uint64_t new_size)
{
	errcode_t ret = 0;
	char *buf = NULL;
	struct ocfs2_dinode* di = NULL;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;
	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, ino, buf);
	if (ret)
		goto out_free_buf;

	di = (struct ocfs2_dinode *)buf;
	if (di->i_size >= new_size) {
		ret = EINVAL;
		goto out_free_buf;
	}

	di->i_size = new_size;

	ret = ocfs2_write_inode(fs, ino, buf);

out_free_buf:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 4
0
errcode_t ocfs2_write_backup_super(ocfs2_filesys *fs, uint64_t blkno)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto out_blk;

	memcpy(buf, (char *)fs->fs_super, fs->fs_blocksize);
	di = (struct ocfs2_dinode *)buf;

	ret = OCFS2_ET_BAD_MAGIC;
	if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
		   strlen(OCFS2_SUPER_BLOCK_SIGNATURE)))
		goto out_blk;

	di->i_blkno = blkno;
	OCFS2_SET_COMPAT_FEATURE(OCFS2_RAW_SB(di),
				 OCFS2_FEATURE_COMPAT_BACKUP_SB);
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		goto out_blk;

	ret = 0;

out_blk:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 5
0
static errcode_t create_local_alloc(ocfs2_filesys *fs, uint16_t slot)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;
	uint32_t la_size, found;
	uint64_t la_off, blkno;

	ret = ocfs2_lookup_system_inode(fs, LOCAL_ALLOC_SYSTEM_INODE,
					slot, &blkno);
	if (ret)
		goto bail;

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

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		goto bail;

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		goto bail;

	if (di->id1.bitmap1.i_total > 0) {
		fprintf(stderr, "local alloc#%"PRIu64" file not empty."
			"Can't create a new one.\n", blkno);
		goto bail;
	}

	la_size = get_local_alloc_window_bits();

	ret = ocfs2_new_clusters(fs, 1, la_size, &la_off, &found);
	if (ret)
		goto bail;

	if(la_size != found)
		goto bail;

	la = &(di->id2.i_lab);

	la->la_bm_off = ocfs2_blocks_to_clusters(fs, la_off);
	di->id1.bitmap1.i_total = la_size;
	di->id1.bitmap1.i_used = 0;
	memset(la->la_bitmap, 0, la->la_size);
	
	ret = ocfs2_write_inode(fs, blkno, buf);

bail:
	if(buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 6
0
static void create_local_alloc(ocfs2_filesys *fs, uint64_t blkno)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;
	uint32_t la_size, found;
	uint64_t la_off;

	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_VALID_FL))
		FSWRK_FATAL("not a file");

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		FSWRK_FATAL("not a local alloc file");

	if (di->id1.bitmap1.i_total > 0) {
		FSWRK_WARN("local alloc#%"PRIu64" file not empty."
				"Can't create a new one.\n", blkno);
		goto bail;
	}

	la_size = get_local_alloc_window_bits();

	ret = ocfs2_new_clusters(fs, 1, la_size, &la_off, &found);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
	if(la_size != found)
		FSWRK_FATAL("can't allocate enough clusters for local alloc");

	la = &(di->id2.i_lab);

	la->la_bm_off = la_off;
	di->id1.bitmap1.i_total = la_size;
	di->id1.bitmap1.i_used = 0;
	memset(la->la_bitmap, 0, la->la_size);
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

bail:
	if(buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 7
0
void mess_up_inode_field(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{
	errcode_t ret;
	uint64_t tmpblkno;
	uint32_t clusters = 10;

	char *buf = NULL;
	struct ocfs2_dinode *di;

	create_file(fs, blkno, &tmpblkno);

	if ((type == INODE_SPARSE_SIZE) || (type == INODE_SPARSE_CLUSTERS)) {

		if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super)))
			FSWRK_FATAL("should specfiy a sparse file supported "
				    "volume to do this corruption\n");

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

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

		di = (struct ocfs2_dinode *)buf;

		di->i_size = fs->fs_clustersize * 2;

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

		if (buf)
			ocfs2_free(&buf);
	}

	if ((type == INODE_CLUSTERS) || (type == INODE_SPARSE_CLUSTERS) ||
	    (type == INODE_SPARSE_SIZE)) {
		ret = ocfs2_extend_allocation(fs, tmpblkno, clusters);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
	}

	if (type == REFCOUNT_FLAG_INVALID &&
	    ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)))
		FSWRK_FATAL("should specfiy a norefcount volume\n");
	if (type == REFCOUNT_LOC_INVALID &&
	    !ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)))
		FSWRK_FATAL("Should specify a refcount supported volume\n");

	damage_inode(fs, tmpblkno, type);
	return;
}
Esempio n. 8
0
void mess_up_inline_flag(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{

	int i;
	errcode_t ret;
	char *buf = NULL, file_type[20];
	uint64_t inline_blkno;
	struct ocfs2_dinode *di;
	struct ocfs2_super_block *osb;

	osb = OCFS2_RAW_SB(fs->fs_super);
	if (ocfs2_support_inline_data(osb))
		FSWRK_FATAL("should specfiy a noinline-data supported "
			    "volume to do this corruption\n");

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

	for (i = 0; i < 2; i++) {
		if (i == 0) {
			create_file(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Regular file");
		} else {
			create_directory(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Diectory");
		}

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

		di = (struct ocfs2_dinode *)buf;
		if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
			di->i_dyn_features |= OCFS2_INLINE_DATA_FL;
			ret = ocfs2_write_inode(fs, inline_blkno, buf);
			if (ret)
				FSWRK_COM_FATAL(progname, ret);
		}

		fprintf(stdout, "INLINE_DATA_FLAG_INVALID: "
			"Create an inlined inode#%"PRIu64"(%s) "
			"on a noinline-data supported volume\n",
			inline_blkno, file_type);
	}

	if (buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 9
0
/*
 * NOTE: ocfs2_truncate_inline() also handles fast symlink,
 * since truncating for inline file and fasy symlink are
 * almost the same thing per se.
 */
errcode_t ocfs2_truncate_inline(ocfs2_filesys *fs, uint64_t ino,
				uint64_t new_i_size)
{
	errcode_t ret = 0;
	char *buf = NULL;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_inline_data *idata = NULL;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;

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

	ret = ocfs2_read_inode(fs, ino, buf);
	if (ret)
		goto out_free_buf;

	di = (struct ocfs2_dinode *)buf;
	if (di->i_size < new_i_size) {
		ret = EINVAL;
		goto out_free_buf;
	}

	idata = &di->id2.i_data;

	if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL) &&
	    !(S_ISLNK(di->i_mode) && !di->i_clusters)) {
		ret = EINVAL;
		goto out_free_buf;
	}

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
		memset(idata->id_data + new_i_size, 0, di->i_size - new_i_size);
	else
		memset(di->id2.i_symlink + new_i_size, 0,
		       di->i_size - new_i_size);

	di->i_size = new_i_size;

	ret = ocfs2_write_inode(fs, ino, buf);

out_free_buf:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 10
0
static errcode_t remove_slot_entry(ocfs2_filesys *fs, uint16_t removed_slot)
{
	struct remove_slot_ctxt ctxt = {
		.fs = fs,
		.removed_slot = removed_slot,
		.errcode = 0
	};

	ocfs2_dir_iterate(fs, fs->fs_sysdir_blkno,
			  OCFS2_DIRENT_FLAG_EXCLUDE_DOTS, NULL,
			  remove_slot_iterate, &ctxt);

	return ctxt.errcode;
}

static errcode_t decrease_link_count(ocfs2_filesys *fs, uint16_t blkno)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di  = NULL;

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

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (di->i_links_count > 0)
		di->i_links_count--;
	else {
		ret = OCFS2_ET_INODE_NOT_VALID;
		goto bail;
	}

	ret = ocfs2_write_inode(fs, blkno, buf);
bail:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 11
0
void o2fsck_write_inode(o2fsck_state *ost, uint64_t blkno,
                        struct ocfs2_dinode *di)
{
    errcode_t ret;
    const char *whoami = __FUNCTION__;

    if (blkno != di->i_blkno) {
        com_err(whoami, OCFS2_ET_INTERNAL_FAILURE, "when asked to "
                "write an inode with an i_blkno of %"PRIu64" to block "
                "%"PRIu64, (uint64_t)di->i_blkno, blkno);
        return;
    }

    ret = ocfs2_write_inode(ost->ost_fs, blkno, (char *)di);
    if (ret) {
        com_err(whoami, ret, "while writing inode %"PRIu64,
                (uint64_t)di->i_blkno);
        ost->ost_saw_error = 1;
    }
}
Esempio n. 12
0
static errcode_t change_sub_alloc_slot(ocfs2_filesys *fs,
				       uint64_t blkno,
				       struct relink_ctxt *ctxt)
{
	errcode_t ret;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_extent_block *eb = NULL;

	if (ctxt->inode_type == EXTENT_ALLOC_SYSTEM_INODE) {
		/* change sub alloc bit in the extent block. */
		ret = ocfs2_read_extent_block(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;

		eb = (struct ocfs2_extent_block *)ctxt->ex_buf;
		eb->h_suballoc_slot = ctxt->new_slot;

		ret = ocfs2_write_extent_block(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;
	} else {
		/* change sub alloc bit in the inode. */
		ret = ocfs2_read_inode(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;

		di = (struct ocfs2_dinode *)ctxt->ex_buf;
		di->i_suballoc_slot = ctxt->new_slot;

		ret = ocfs2_write_inode(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;
	}
bail:
	return ret;
}
Esempio n. 13
0
static errcode_t create_truncate_log(ocfs2_filesys *fs, uint16_t slot)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	uint16_t i, used = 10;
	uint32_t found, clusters = 10;
	uint64_t begin, blkno;

	ret = ocfs2_lookup_system_inode(fs, TRUNCATE_LOG_SYSTEM_INODE,
					slot, &blkno);
	if (ret)
		goto bail;
	
	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto bail;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL)) {
		fprintf(stderr,"not a valid file\n");
		goto bail;
	}

	if (!(di->i_flags & OCFS2_DEALLOC_FL)) {
		fprintf(stderr,"not a valid truncate log\n");
		goto bail;
	}
	
	tl = &di->id2.i_dealloc;

	if (le16_to_cpu(tl->tl_used) > 0) {
		fprintf(stderr,"truncate log#%"PRIu64" file not empty."
			"Can't create a new one.\n", blkno);
		goto bail;
	}

	tl->tl_used = used;

	for (i = 0; i < tl->tl_used; i++) {
		ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found);
		if (ret)
			goto bail;
		
		tl->tl_recs[i].t_start = 
			ocfs2_blocks_to_clusters(fs, begin);
		tl->tl_recs[i].t_clusters = found;
	}

	ret = ocfs2_write_inode(fs, blkno, buf);

bail:
	if(buf)
		ocfs2_free(&buf);
	return ret;
}
Esempio n. 14
0
static void damage_inode(ocfs2_filesys *fs, uint64_t blkno,
				enum fsck_type type)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;

	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_VALID_FL))
		FSWRK_FATAL("not a file");

	switch (type) {
	case INODE_GEN:
		fprintf(stdout, "INODE_GEN: "
			"Corrupt inode#%"PRIu64", change generation "
			" from %u to 0x1234\n", blkno, di->i_fs_generation);
		di->i_fs_generation = 0x1234;
		break;
	case INODE_GEN_FIX:
		fprintf(stdout, "INODE_GEN_FIX: "
			"Corrupt inode#%"PRIu64", change generation "
			" from %u to 0x1234, please answer 'n' when "
			"INODE_GEN error shows in fsck.ocfs2\n",
			blkno, di->i_fs_generation);
		di->i_fs_generation = 0x1234;
		break;
	case INODE_BLKNO:
		fprintf(stdout, "INODE_BLKNO: "
			"Corrupt inode#%"PRIu64", change i_blkno from %"PRIu64
			" to %"PRIu64"\n",
			blkno, di->i_blkno, (di->i_blkno + 100));
		di->i_blkno += 100;
		break;
	case INODE_NZ_DTIME:
		fprintf(stdout, "INODE_NZ_DTIME: "
			"Corrupt inode#%"PRIu64", change i_dtime from %"PRIu64
			" to 100\n", blkno, di->i_dtime);
		di->i_dtime = 100;
		break;
	case INODE_SUBALLOC:
		fprintf(stdout, "INODE_SUBALLOC: "
			"Corrupt inode#%"PRIu64", change i_suballoc_slot"
			" from %u to %u\n", blkno, di->i_suballoc_slot,
			(di->i_suballoc_slot + 10));
		di->i_suballoc_slot += 10;
		break;
	case INODE_SIZE:
		fprintf(stdout, "INODE_SIZE: "
			"Corrupt inode#%"PRIu64", change i_size"
			" from %"PRIu64" to %"PRIu64"\n",
			 blkno, di->i_size, (di->i_size + 100));
		di->i_size += 100;
		break;
	case INODE_SPARSE_SIZE:
		fprintf(stdout, "INODE_SPARSE_SIZE: "
			"Corrupt inode#%"PRIu64", change i_size "
			"from %"PRIu64" to %u\n",
			 blkno, di->i_size, fs->fs_clustersize);
		di->i_size = fs->fs_clustersize;
		break;
	case INODE_CLUSTERS:
		fprintf(stdout, "INODE_CLUSTERS: "
			"Corrupt inode#%"PRIu64", change i_clusters"
			" from %u to 0\n", blkno, di->i_clusters);
		di->i_clusters = 0;
		break;
	case INODE_SPARSE_CLUSTERS:
		fprintf(stdout, "INODE_SPARSE_CLUSTERS: "
			"Corrupt inode#%"PRIu64", change i_clusters"
			" from %u to 0\n", blkno, di->i_clusters);
		di->i_clusters = 0;
		break;
	case INODE_COUNT:
		di->i_links_count = 0;
		fprintf(stdout, "INODE_COUNT: "
			"Corrupte inode#%"PRIu64", set link count to 0\n",
			blkno);
		break;
	case INODE_BLOCK_ECC:
		fprintf(stdout, "INODE_BLOCK_ECC: "
			"Corrupte inode#%"PRIu64", set both i_check.bc_crc32e"
			"=%"PRIu64" and i_check.bc_ecc=%"PRIu64" to 0x1234\n",
			blkno, di->i_check.bc_crc32e, di->i_check.bc_ecc);
		di->i_check.bc_crc32e = 0x1234;
		di->i_check.bc_ecc = 0x1234;
		break;
	case INODE_VALID_FLAG:
		fprintf(stdout, "INODE_VALID_FLAG: "
			"Corrupt inode#%"PRIu64", clear inode valid flag\n",
			blkno);
		di->i_flags &= ~OCFS2_VALID_FL;
		break;
	case REFCOUNT_FLAG_INVALID:
		di->i_dyn_features |= OCFS2_HAS_REFCOUNT_FL;
		fprintf(stdout, "REFCOUNT_FLAG_INVALD: "
			"Corrupt inode#%"PRIu64", add refcount feature\n",
			blkno);
		break;
	case REFCOUNT_LOC_INVALID:
		di->i_refcount_loc = 100;
		fprintf(stdout, "REFCOUNT_LOC_INVALID: "
			"Create an inode#%"PRIu64","
			"whose i_refcount_loc has been messed up.\n",
			blkno);
		break;
	default:
		FSWRK_FATAL("Invalid type[%d]\n", type);
	}

	if (type != INODE_BLOCK_ECC)
		ret = ocfs2_write_inode(fs, blkno, buf);
	else
		ret = ocfs2_write_inode_without_meta_ecc(fs, blkno, buf);

	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	if (buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 15
0
void mess_up_dup_clusters(ocfs2_filesys *fs, enum fsck_type type,
			  uint64_t blkno)
{
	errcode_t err;
	char *buf = NULL;
	uint64_t inode1_blkno, inode2_blkno;
	struct ocfs2_dinode *di1, *di2;
	struct ocfs2_extent_list *el1, *el2;

	err = ocfs2_malloc_blocks(fs->fs_io, 2, &buf);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	create_file(fs, blkno, &inode1_blkno);

	di1 = (struct ocfs2_dinode *)buf;
	err = ocfs2_read_inode(fs, inode1_blkno, (char *)di1);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
		if (di1->i_dyn_features & OCFS2_INLINE_DATA_FL) {
			di1->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
			err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1);
			if (err)
				FSWRK_COM_FATAL(progname, err);
		}
	}

	if (type != DUP_CLUSTERS_SYSFILE_CLONE) {

		create_file(fs, blkno, &inode2_blkno);
		di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize);
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
			if (di2->i_dyn_features & OCFS2_INLINE_DATA_FL) {
				di2->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
				err = ocfs2_write_inode(fs, inode2_blkno,
							(char *)di2);
				if (err)
					FSWRK_COM_FATAL(progname, err);
			}
		}

		err = ocfs2_extend_allocation(fs, inode2_blkno, 1);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		/* Re-read the inode with the allocation */
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		/* Set i_size to non-zero so that the allocation is valid */
		di2->i_size = fs->fs_clustersize;
		err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (type == DUP_CLUSTERS_CLONE)
			fprintf(stdout, "DUP_CLUSTERS_CLONE: "
				"Create two inodes #%"PRIu64" and #%"PRIu64
				" by allocating same cluster to them.\n",
				inode1_blkno, inode2_blkno);
		else
			fprintf(stdout, "DUP_CLUSTERS_DELETE: "
				"Create two inodes #%"PRIu64" and #%"PRIu64
				" by allocating same cluster to them.\n",
				inode1_blkno, inode2_blkno);
	} else {
		/* Here use journal file*/
		err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE, 0,
						&inode2_blkno);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize);
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (di2->id2.i_list.l_tree_depth)
			FSWRK_FATAL("Journal inode has non-zero tree "
				    "depth.  fswreck can't use it for "
				    "DUP_CLUSTERS_SYSFILE_CLONE\n");

		fprintf(stdout, "DUP_CLUSTERS_SYSFILE_CLONE: "
			"Allocate same cluster to journal file "
			"#%"PRIu64" and regular file #%"PRIu64".\n",
			inode1_blkno, inode2_blkno);
	}

	el1 = &(di1->id2.i_list);
	el2 = &(di2->id2.i_list);


	el1->l_next_free_rec = 1;
	el1->l_recs[0] = el2->l_recs[0];

	di1->i_size =
		ocfs2_clusters_to_bytes(fs, el1->l_recs[0].e_leaf_clusters);
	di1->i_clusters = di2->i_clusters;

	err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	ocfs2_free(&buf);
}
Esempio n. 16
0
void mess_up_inline_inode(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{
	int i;
	errcode_t ret;
	char *buf = NULL, file_type[20];
	uint64_t inline_blkno;
	struct ocfs2_dinode *di;
	uint16_t max_inline_sz;
	struct ocfs2_super_block *osb;

	osb = OCFS2_RAW_SB(fs->fs_super);
	if (!ocfs2_support_inline_data(osb))
		FSWRK_FATAL("Should specify a inline-data supported "
			    "volume to do this corruption\n");

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

	for (i = 0; i < 2; i++) {
		if (i == 0) {
			create_file(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Regular file");
		} else {
			create_directory(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Diectroy");
		}

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

		di = (struct ocfs2_dinode *)buf;
		max_inline_sz =
			ocfs2_max_inline_data_with_xattr(fs->fs_blocksize, di);

		if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
			di->i_dyn_features |= OCFS2_INLINE_DATA_FL;

		switch (type) {
		case INLINE_DATA_COUNT_INVALID:
			di->id2.i_data.id_count = 0;
			fprintf(stdout, "INLINE_DATA_COUNT_INVALID: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose id_count has been messed up.\n",
				inline_blkno, file_type);
			break;
		case INODE_INLINE_SIZE:
			di->i_size = max_inline_sz + 1;
			fprintf(stdout, "INODE_INLINE_SIZE: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose i_size has been messed up.\n",
				inline_blkno, file_type);
			break;
		case INODE_INLINE_CLUSTERS:
			di->i_clusters = 1;
			fprintf(stdout, "INODE_INLINE_CLUSTERS: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose i_clusters has been messed up.\n",
				inline_blkno, file_type);
			break;

		default:
			FSWRK_FATAL("Invalid type[%d]\n", type);
		}

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

	if (buf)
		ocfs2_free(&buf);

	return;
}
Esempio n. 17
0
/* this could certainly be more clever to issue reads in groups */
static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, 
					void *priv_data) 
{
	struct dirblock_data *dd = priv_data;
	struct ocfs2_dir_entry *dirent, *prev = NULL;
	unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize;
	unsigned int write_off, saved_reclen;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; 
	errcode_t ret = 0;

	if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) {
		printf("Directory block %"PRIu64" belongs to directory inode "
		       "%"PRIu64" which isn't allocated.  Ignoring this "
		       "block.", dbe->e_blkno, dbe->e_ino);
		goto out;
	}

	if (dbe->e_ino != dd->last_ino) {
		o2fsck_strings_free(&dd->strings);
		dd->last_ino = dbe->e_ino;

		ret = ocfs2_read_inode(dd->ost->ost_fs, dbe->e_ino,
				       dd->inoblock_buf);
		if (ret == OCFS2_ET_BAD_CRC32) {
			if (prompt(dd->ost, PY, PR_BAD_CRC32, 
						"Directory inode %"PRIu64" "
						"has bad CRC32. Recalculate CRC32 "
						"and write inode block?", dbe->e_ino)) {
				ocfs2_write_inode(dd->ost->ost_fs, dbe->e_ino,
						dd->inoblock_buf);
			}
		} else if (ret) {
			com_err(whoami, ret, "while reading dir inode %"PRIu64,
				dbe->e_ino);
			ret_flags |= OCFS2_DIRENT_ABORT;
			goto out;
		}

		verbosef("dir inode %"PRIu64" i_size %"PRIu64"\n",
			 dbe->e_ino, (uint64_t)di->i_size);

		/* Set the flag for index rebuilding */
		if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super))
			&& !(di->i_dyn_features & OCFS2_INLINE_DATA_FL)
			&& !(di->i_dyn_features & OCFS2_INDEXED_DIR_FL) 
			&& prompt(dd->ost, PY, PR_DX_TREE_MISSING, 
				  "Directory %"PRIu64" is missing index. "
				  "Rebuild?", dbe->e_ino))
				ret_flags |= OCFS2_DIRENT_CHANGED;

	}

	verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n",
		 dbe->e_blkno, dbe->e_blkcount);

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
		if (dbe->e_ino != dbe->e_blkno)
			goto out;

		memcpy(dd->dirblock_buf, dd->inoblock_buf,
		       dd->fs->fs_blocksize);
		offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
	} else {
		if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
Esempio n. 18
0
static errcode_t move_group(ocfs2_filesys *fs,
			    struct relink_ctxt *ctxt,
			    struct moved_group *group)
{
	errcode_t ret = 0;
	uint16_t cr_pos;
	struct ocfs2_group_desc *gd = NULL;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_chain_list *cl = NULL;
	struct ocfs2_chain_rec *cr = NULL;

	if (!group || !group->blkno || !group->gd_buf)
		goto bail;

	di = (struct ocfs2_dinode *)ctxt->dst_inode;
	cl = &di->id2.i_chain;

	/* calculate the insert position. */
	if (cl->cl_next_free_rec < cl->cl_count)
		cr_pos = cl->cl_next_free_rec;
	else {
		/* Now we have all the chain record filled with some groups.
		 * so we figure out all the groups we have and then calculate
		 * the proper place for our insert.
		 */
		cr_pos = di->id1.bitmap1.i_total / (cl->cl_cpg * cl->cl_bpc);
		cr_pos %= cl->cl_count;
	}

	cr = &cl->cl_recs[cr_pos];

	gd = (struct ocfs2_group_desc *)group->gd_buf;
	gd->bg_chain = cr_pos;
	gd->bg_parent_dinode = ctxt->dst_blkno;

	/* we can safely set the bg_next_group here since all the group
	 * below it in the moving chain is already moved to the new
	 * position and we don't need to worry about any "lost" groups.
	 *
	 * Please see how we build up the group list in move_chain_rec.
	 */
	gd->bg_next_group = cr->c_blkno;

	ret = ocfs2_write_group_desc(fs, group->blkno, group->gd_buf);
	if (ret)
		goto bail;

	/* modify the chain record and the new files simultaneously. */
	cr->c_blkno = gd->bg_blkno;
	cr->c_total += gd->bg_bits;
	cr->c_free += gd->bg_free_bits_count;

	/* If the chain isn't full, increase the free_rec. */
	if (cl->cl_next_free_rec != cl->cl_count)
		cl->cl_next_free_rec++;

	di->id1.bitmap1.i_total += gd->bg_bits;
	di->id1.bitmap1.i_used += gd->bg_bits;
	di->id1.bitmap1.i_used -= gd->bg_free_bits_count;
	di->i_clusters += cl->cl_cpg;
	di->i_size += cl->cl_cpg * fs->fs_clustersize;

	ret = ocfs2_write_inode(fs, ctxt->dst_blkno, ctxt->dst_inode);

bail:
	return ret;
}
Esempio n. 19
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno, sys_blkno;
	int c;
	char *filename, *buf;
	const char *bitmap_name = ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_block wb;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}
	filename = argv[optind];

	ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
		sys_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno;

		ret = ocfs2_lookup(fs, sys_blkno, bitmap_name, 
				   strlen(bitmap_name), NULL, &blkno);
		if (ret) {
			com_err(argv[0], ret,
				"while looking up \"%s\"", bitmap_name);
			goto out;
		}
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	memset(&wb, 0, sizeof(wb));

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	wb.di = di;
	ret = ocfs2_malloc_block(fs->fs_io, &wb.buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating block buffer");
		goto out_free;
	}

	ret = ocfs2_block_iterate(fs, blkno, 0,
				  walk_blocks_func,
				  &wb);
	if (ret) {
		com_err(argv[0], ret,
			"while walking blocks");
		goto out_free;
	}

	di->id1.bitmap1.i_used = wb.used;

	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

out_free:
	if (wb.buf)
		ocfs2_free(&wb.buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
Esempio n. 20
0
static errcode_t relink_system_alloc(ocfs2_filesys *fs,
				     uint16_t removed_slot,
				     uint16_t new_slots,
				     int inode_type)
{
	errcode_t ret;
	int16_t i;
	uint64_t blkno;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_chain_list *cl = NULL;
	struct relink_ctxt ctxt;
	char fname[OCFS2_MAX_FILENAME_LEN];

	memset(&ctxt, 0, sizeof(ctxt));

	ocfs2_sprintf_system_inode_name(fname, OCFS2_MAX_FILENAME_LEN,
					inode_type, removed_slot);
	verbosef(VL_APP, "Relinking system allocator \"%s\"\n", fname);

	ret = ocfs2_lookup_system_inode(fs, inode_type,
					removed_slot, &blkno);
	if (ret) {
		verbosef(VL_APP, "%s while looking up the allocator\n",
			 error_message(ret));
		goto bail;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &ctxt.src_inode);
	if (ret) {
		verbosef(VL_APP,
			 "%s while allocating the inode buffer\n",
			 error_message(ret));
		goto bail;
	}

	ret = ocfs2_read_inode(fs, blkno, ctxt.src_inode);
	if (ret) {
		verbosef(VL_APP,
			 "%s while reading allocator inode %"PRIu64"\n",
			 error_message(ret), blkno);
		goto bail;
	}

	di = (struct ocfs2_dinode *)ctxt.src_inode;

	if (!(di->i_flags & OCFS2_VALID_FL) ||
	    !(di->i_flags & OCFS2_BITMAP_FL) ||
	    !(di->i_flags & OCFS2_CHAIN_FL)) {
		verbosef(VL_APP, "Allocator inode %"PRIu64" is corrupt.\n",
			 blkno);
		goto bail;
	}

	if (di->id1.bitmap1.i_total == 0)
		goto bail;

	/* Iterate all the groups and modify the group descriptors accordingly. */
	ret = ocfs2_malloc_block(fs->fs_io, &ctxt.ex_buf);
	if (ret) {
		verbosef(VL_APP,
			 "%s while allocating an extent block buffer\n",
			 error_message(ret));
		goto bail;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &ctxt.dst_inode);
	if (ret) {
		verbosef(VL_APP,
			 "%s while allocating the destination inode buffer\n",
			 error_message(ret));
		goto bail;
	}

	cl = &di->id2.i_chain;
	ctxt.inode_type = inode_type;

	/*iterate all the chain record and move them to the new slots. */
	for (i = cl->cl_next_free_rec - 1; i >= 0; i--) {
		ctxt.new_slot = i % new_slots;
		ret = ocfs2_lookup_system_inode(fs, inode_type,
						ctxt.new_slot,
						&ctxt.dst_blkno);
		if (ret) {
			verbosef(VL_APP,
				 "%s while finding the target allocator "
				 "for slot %d\n",
				 error_message(ret), ctxt.new_slot);
			goto bail;
		}

		ret = ocfs2_read_inode(fs, ctxt.dst_blkno, ctxt.dst_inode);
		if (ret) {
			verbosef(VL_APP,
				 "%s while reading target allocator inode "
				 "%"PRIu64"\n",
				 error_message(ret), ctxt.dst_blkno);
			goto bail;
		}

		ctxt.cr = &cl->cl_recs[i];

		ret = move_chain_rec(fs, &ctxt);
		if (ret) {
			verbosef(VL_APP,
				"%s while trying to move a chain record "
				"to the allocator in slot %d\n",
				error_message(ret), ctxt.new_slot);
			goto bail;
		}
	}


	/* emtpy the original alloc files. */
	di->id1.bitmap1.i_used = 0;
	di->id1.bitmap1.i_total = 0;
	di->i_clusters = 0;
	di->i_size = 0;

	cl = &di->id2.i_chain;
	cl->cl_next_free_rec = 0;
	memset(cl->cl_recs, 0, sizeof(struct ocfs2_chain_rec) * cl->cl_count);

	ret = ocfs2_write_inode(fs, blkno, ctxt.src_inode);
	if (ret)
		verbosef(VL_APP,
			 "%s while writing out the empty allocator inode\n",
			 error_message(ret));

bail:
	if (ctxt.ex_buf)
		ocfs2_free(&ctxt.ex_buf);
	if (ctxt.dst_inode)
		ocfs2_free(&ctxt.dst_inode);
	if (ctxt.src_inode)
		ocfs2_free(&ctxt.src_inode);

	if (!ret)
		verbosef(VL_APP, "Successfully relinked allocator \"%s\"\n",
			 fname);
	return ret;
}
Esempio n. 21
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 ;
}
Esempio n. 22
0
static void create_truncate_log(ocfs2_filesys *fs, uint64_t blkno,
				uint16_t used, uint32_t clusters)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	uint16_t i, max;
	uint32_t found;
	uint64_t begin;

	max = ocfs2_truncate_recs_per_inode(fs->fs_blocksize);
	if (used > max)
		FSWRK_FATAL("recnum exceeds the limit of truncate log");

	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_VALID_FL))
		FSWRK_FATAL("not a valid file");

	if (!(di->i_flags & OCFS2_DEALLOC_FL))
		FSWRK_FATAL("not a valid truncate log");
	
	tl = &di->id2.i_dealloc;

	if (tl->tl_used > 0) {
		FSWRK_WARN("truncate log#%"PRIu64" file not empty."
				"Can't create a new one.\n", blkno);
		goto bail;
	}

	used = min(used, tl->tl_count);
	tl->tl_used = used;

	for (i = 0; i < tl->tl_used; i++) {
		ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
		
		tl->tl_recs[i].t_start = 
			cpu_to_le32(ocfs2_blocks_to_clusters(fs, begin));
		tl->tl_recs[i].t_clusters = cpu_to_le32(found);
	}

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

bail:
	if(buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 23
0
static void damage_local_alloc(ocfs2_filesys *fs,
				uint64_t blkno, enum fsck_type type)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;

	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_VALID_FL))
		FSWRK_FATAL("not a file");

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		FSWRK_FATAL("not a local alloc file");
	
	la = &(di->id2.i_lab);

	/* For LALLOC_BM_OVERRUN, LALLOC_BM_STRADDLE,LALLOC_BM_SIZE,
	 * LALLOC_USED_OVERRUN, LALLOC_CLEAR, i_total must be greater than 0.
	 * So check it first.
	 */
	if (type == LALLOC_BM_OVERRUN || type == LALLOC_BM_STRADDLE ||
		type == LALLOC_BM_SIZE || type == LALLOC_USED_OVERRUN)
		if (di->id1.bitmap1.i_total == 0) {
			FSWRK_WARN("local inode#%"PRIu64" is empty, so can't"
					"corrupt it for type[%d]\n",
					blkno, type);
			goto bail;
		}
	
	switch (type) {
	case LALLOC_SIZE:
	case LALLOC_CLEAR:
		if (type == LALLOC_SIZE)
			fprintf(stdout, "LALLOC_SIZE: ");
		else
			fprintf(stdout, "LALLOC_CLEAR: ");
		fprintf(stdout,	"Corrupt local alloc inode#%"PRIu64
			", change size from %u to %u\n", blkno, la->la_size,
			(ocfs2_local_alloc_size(fs->fs_blocksize) + 10));
		la->la_size = ocfs2_local_alloc_size(fs->fs_blocksize) + 10;
		break;
	case LALLOC_NZ_USED:
		di->id1.bitmap1.i_total = 0;
		di->id1.bitmap1.i_used = 10;
		fprintf(stdout, "LALLOC_NZ_USED: "
			"Corrupt local alloc inode#%"PRIu64", total = %d "
			" used =  %d\n",blkno,  di->id1.bitmap1.i_total,
			di->id1.bitmap1.i_used);
		break;
	case LALLOC_NZ_BM:
		di->id1.bitmap1.i_total = 0;
		la->la_bm_off = 100;
		fprintf(stdout, "LALLOC_NZ_BM: "
			"Corrupt local alloc inode#%"PRIu64", total = %d "
			" la_bm_off =  %d\n",blkno,  di->id1.bitmap1.i_total,
			la->la_bm_off);
		break;
	case LALLOC_BM_OVERRUN:
	case LALLOC_BM_STRADDLE:
		la->la_bm_off = fs->fs_clusters + 10;
		if (type == LALLOC_BM_OVERRUN)
			fprintf(stdout, "LALLOC_BM_OVERRUN: ");
		else
			fprintf(stdout, "LALLOC_BM_STRADDLE: ");
		fprintf(stdout, "Corrupt local alloc inode#%"PRIu64
			", la_bm_off =%u\n", blkno,  la->la_bm_off);
		break;
	case LALLOC_BM_SIZE:
		fprintf(stdout, "LALLOC_SIZE: "
			"Corrupt local alloc inode#%"PRIu64", change i_total"
			" from %u to %u\n", blkno, di->id1.bitmap1.i_total,
			(la->la_size * 8 + 10));
		di->id1.bitmap1.i_total = la->la_size * 8 + 10;
		break;
	case LALLOC_USED_OVERRUN:
		fprintf(stdout, "LALLOC_USED_OVERRUN: "
			"Corrupt local alloc inode#%"PRIu64", change i_used"
			" from %u to %u\n", blkno, di->id1.bitmap1.i_used,
			(di->id1.bitmap1.i_total + 10));
		di->id1.bitmap1.i_used = di->id1.bitmap1.i_total + 10;
		break;
	default:
		FSWRK_FATAL("Unknown type = %d", type);
	}
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
bail:
	if (buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 24
0
errcode_t o2fsck_check_journals(o2fsck_state *ost)
{
	errcode_t ret;
	int i;
	ocfs2_filesys *fs = ost->ost_fs;
	int have_one_good_journal = 0, problem_is_consistent = 1;
	errcode_t known_problem = 0;
	struct journal_check_context jc = {
		.jc_max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots,
	};
	struct journal_check_info *ji;

	ret = ocfs2_malloc0(sizeof(struct journal_check_info) *
			    jc.jc_max_slots,
			    &jc.jc_info);
	if (ret) {
		com_err(whoami, ret, "while checking journals");
		goto out;
	}

	ret = check_journal_walk(ost, check_journals_func, &jc);
	if (ret) {
		com_err(whoami, ret, "while checking journals");
		goto out;
	}

	/*
	 * We now know the state of all our journals.  If we have at least
	 * one good journal, we have a sane state to fix the others from.
	 * We require all our journals to have identical configuration.
	 * Any inconsistencies (invalid size, bad feature flags) are
	 * probably corruption or a failed tunefs.
	 *
	 * If we don't have a good journal, but all the journals have the
	 * exact same problem, we may be able to handle it as well.  We
	 * currently know how to handle these problems:
	 *
	 * JOURNAL_TOO_SMALL
	 *
	 * We simply allocate a default journal size.
	 *
	 * UNSUPP_FEATURE & RO_UNSUPP_FEATURE
	 *
	 * If one journal has an unsupported feature bit set, it's probably
	 * corruption.  If all the journals have the exact same feature
	 * bit set, it's certainly a feature we don't understand, and we
	 * want the user to upgrade their fsck.
	 */
	for (i = 0; i < jc.jc_max_slots; i++) {
		ji = &jc.jc_info[i];

		if (!ji->i_error) {
			have_one_good_journal = 1;
			continue;
		}

		if ((ji->i_error != OCFS2_ET_JOURNAL_TOO_SMALL) &&
		    (ji->i_error != OCFS2_ET_UNSUPP_FEATURE) &&
		    (ji->i_error != OCFS2_ET_RO_UNSUPP_FEATURE)) {
			problem_is_consistent = 0;
			continue;
		}

		if (known_problem) {
			if (known_problem != ji->i_error)
				problem_is_consistent = 0;
			continue;
		}

		known_problem = ji->i_error;
	}

	if (!have_one_good_journal) {
		if (!problem_is_consistent || !known_problem) {
			ret = jc.jc_info[0].i_error;
			com_err(whoami, ret, "while checking journals");
			goto out;
		}
		if ((known_problem == OCFS2_ET_UNSUPP_FEATURE) ||
		    (known_problem == OCFS2_ET_RO_UNSUPP_FEATURE)) {
			com_err(whoami, known_problem,
				"on all journals.  Please upgrade to the "
				"latest version of fsck.ocfs2");
			ret = known_problem;
			goto out;
		}

		if (known_problem != OCFS2_ET_JOURNAL_TOO_SMALL) {
			ret = known_problem;
			com_err(whoami, ret, "for all journals");
			goto out;
		}

		/* Force a valid cluster count for the journals */
		jc.jc_max_clusters =
			ocfs2_clusters_in_bytes(fs,
						OCFS2_MIN_JOURNAL_SIZE);
	}

	ret = check_journal_walk(ost, fix_journals_func, &jc);

out:
	if (jc.jc_info)
		ocfs2_free(&jc.jc_info);

	return ret;
}

static errcode_t ocfs2_clear_journal_flag(ocfs2_filesys *fs,
					  struct ocfs2_dinode *di,
					  int slot)
{
	errcode_t ret = 0;

	if (!(di->i_flags & OCFS2_VALID_FL) ||
	    !(di->i_flags & OCFS2_SYSTEM_FL) ||
	    !(di->i_flags & OCFS2_JOURNAL_FL))
		return OCFS2_ET_INVALID_ARGUMENT;

	if (!(di->id1.journal1.ij_flags & OCFS2_JOURNAL_DIRTY_FL))
		goto bail;

	di->id1.journal1.ij_flags &= ~OCFS2_JOURNAL_DIRTY_FL;

	ret = ocfs2_write_inode(fs, di->i_blkno, (char *)di);
	if (!ret)
		printf("Slot %d's journal dirty flag removed\n", slot);

bail:
	return ret;
}
Esempio n. 25
0
static void damage_truncate_log(ocfs2_filesys *fs,
				uint64_t blkno, enum fsck_type type, int recnum)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	struct ocfs2_truncate_rec *tr;

	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_VALID_FL))
		FSWRK_FATAL("not a valid file");

	if (!(di->i_flags & OCFS2_DEALLOC_FL))
		FSWRK_FATAL("not a valid truncate log");
	
	tl = &di->id2.i_dealloc;

	/* For TRUNCATE_REC_START_RANGE, TRUNCATE_REC_WRAP, TRUNCATE_REC_RANGE,
	 * tl_used must be greater than 0 and recnum must be less than tl_used.
	 * So check it first.
	 */
	if (type == TRUNCATE_REC_START_RANGE || type == TRUNCATE_REC_WRAP ||
		type == TRUNCATE_REC_RANGE) {
		if (tl->tl_used == 0) {
			FSWRK_WARN("truncate log#%"PRIu64" is empty, so can't"
					"corrupt it for type[%d]\n",
					blkno, type);
			goto bail;
		}
		
		if(tl->tl_used <= recnum) {
			FSWRK_WARN("truncate log#%"PRIu64" can't corrupt "
					"item[%d] corrupt it for type[%d]\n",
					blkno, recnum, type);
			goto bail;
		}
	}
	
	switch (type) {
	case DEALLOC_COUNT:
		fprintf(stdout, "DEALLOC_COUNT: "
			"Corrupt truncate log inode#%"PRIu64", change tl_count"
			" from %u to %u\n",
			blkno, tl->tl_count, (tl->tl_count + 10));
		tl->tl_count += 10;
		break;
	case DEALLOC_USED:
		fprintf(stdout, "DEALLOC_USED: "
			"Corrupt truncate log inode#%"PRIu64", change tl_used"
			" from %u to %u\n",
			blkno, tl->tl_used, (tl->tl_count + 10));
		tl->tl_used = tl->tl_count + 10;
		break;
	case TRUNCATE_REC_START_RANGE:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_START_RANGE: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_start from %u to %u\n",
			blkno, recnum, tr->t_start, (fs->fs_clusters + 10));
		tr->t_start = fs->fs_clusters + 10;
		break;
	case TRUNCATE_REC_WRAP:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_WRAP: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_start from %u to 10000\n,"
			"change t_clusters from %u to %u\n",
			blkno, recnum,
			tr->t_start,tr->t_clusters, (UINT32_MAX - 10));
		tr->t_start = 10000;
		tr->t_clusters = UINT32_MAX - 10;
		break;
	case TRUNCATE_REC_RANGE:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_RANGE: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_clusters from %u to %u\n",
			blkno, recnum, tr->t_clusters, (fs->fs_clusters + 10));
		tr->t_clusters = fs->fs_clusters + 10;
		break;
	default:
		FSWRK_FATAL("Unknown type = %d", type);
	}
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
bail:
	if (buf)
		ocfs2_free(&buf);
	return;
}
Esempio n. 26
0
errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
				     struct ocfs2_dinode *inode,
				     int flags,
				     char *block_buf,
				     int (*func)(ocfs2_filesys *fs,
					         struct ocfs2_extent_rec *rec,
					         int tree_depth,
					         uint32_t ccount,
					         uint64_t ref_blkno,
					         int ref_recno,
					         void *priv_data),
					         void *priv_data)
{
	int i;
	int iret = 0;
	struct ocfs2_extent_list *el;
	errcode_t ret;
	struct extent_context ctxt;

	ret = OCFS2_ET_INODE_NOT_VALID;
	if (!(inode->i_flags & OCFS2_VALID_FL))
		goto out;

	ret = OCFS2_ET_INODE_CANNOT_BE_ITERATED;
	if (inode->i_flags & (OCFS2_SUPER_BLOCK_FL |
			      OCFS2_LOCAL_ALLOC_FL |
			      OCFS2_CHAIN_FL))
		goto out;

	el = &inode->id2.i_list;
	if (el->l_tree_depth) {
		ret = ocfs2_malloc0(sizeof(char *) * el->l_tree_depth,
				    &ctxt.eb_bufs);
		if (ret)
			goto out;

		if (block_buf) {
			ctxt.eb_bufs[0] = block_buf;
		} else {
			ret = ocfs2_malloc0(fs->fs_blocksize *
					    el->l_tree_depth,
					    &ctxt.eb_bufs[0]);
			if (ret)
				goto out_eb_bufs;
		}

		for (i = 1; i < el->l_tree_depth; i++) {
			ctxt.eb_bufs[i] = ctxt.eb_bufs[0] +
				i * fs->fs_blocksize;
		}
	}
	else
		ctxt.eb_bufs = NULL;

	ctxt.fs = fs;
	ctxt.func = func;
	ctxt.priv_data = priv_data;
	ctxt.flags = flags;
	ctxt.ccount = 0;
	ctxt.last_eb_blkno = 0;
	ctxt.last_eb_cpos = 0;

	ret = 0;
	iret |= extent_iterate_el(el, 0, &ctxt);
	if (iret & OCFS2_EXTENT_ERROR)
		ret = ctxt.errcode;

	if (iret & OCFS2_EXTENT_ABORT)
		goto out_abort;

	/* we can only trust ctxt.last_eb_blkno if we walked the whole tree */
	if (inode->i_last_eb_blk != ctxt.last_eb_blkno) {
		inode->i_last_eb_blk = ctxt.last_eb_blkno;
		iret |= OCFS2_EXTENT_CHANGED;
	}

out_abort:
	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
		ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);

out_eb_bufs:
	if (ctxt.eb_bufs) {
		if (!block_buf && ctxt.eb_bufs[0])
			ocfs2_free(&ctxt.eb_bufs[0]);
		ocfs2_free(&ctxt.eb_bufs);
	}

out:
	return ret;
}