コード例 #1
0
ファイル: journal.c プロジェクト: djs55/ocfs2-tools
static errcode_t check_journals_func(o2fsck_state *ost,
				     ocfs2_cached_inode *ci,
				     struct journal_check_context *jc)
{
	errcode_t err, ret;
	ocfs2_filesys *fs = ost->ost_fs;
	uint64_t contig;
	uint64_t blkno;
	char *buf = NULL;
	journal_superblock_t *jsb;
	struct journal_check_info *ji = &(jc->jc_info[jc->jc_this_slot]);

	ret = ocfs2_malloc_blocks(fs->fs_io, 1, &buf);
	if (ret)
		goto out;

	err = ocfs2_extent_map_get_blocks(ci, 0, 1, &blkno, &contig, NULL);
	if (err) {
		ji->i_error = err;
		goto out;
	}

	ji->i_clusters = ci->ci_inode->i_clusters;

	err = ocfs2_read_journal_superblock(fs, blkno, buf);
	if (err) {
		ji->i_error = err;
		goto out;
	}

	jsb = (journal_superblock_t *)buf;
	ji->i_features.opt_compat = jsb->s_feature_compat;
	ji->i_features.opt_ro_compat = jsb->s_feature_ro_compat;
	ji->i_features.opt_incompat = jsb->s_feature_incompat;

	if (!ji->i_clusters) {
		ji->i_error = OCFS2_ET_JOURNAL_TOO_SMALL;
		goto out;
	}

	jc->jc_max_clusters = ocfs2_max(jc->jc_max_clusters,
					ci->ci_inode->i_clusters);
	jc->jc_max_features.opt_compat |= jsb->s_feature_compat;
	jc->jc_max_features.opt_ro_compat |= jsb->s_feature_ro_compat;
	jc->jc_max_features.opt_incompat |= jsb->s_feature_incompat;
	ji->i_error = 0;

out:
	if (buf)
		ocfs2_free(&buf);

	return ret;
}
コード例 #2
0
ファイル: journal.c プロジェクト: djs55/ocfs2-tools
static errcode_t prep_journal_info(ocfs2_filesys *fs, int slot,
			           struct journal_info *ji)
{
	errcode_t err;


	err = ocfs2_malloc_blocks(fs->fs_io, 1, &ji->ji_jsb);
	if (err)
		com_err(whoami, err, "while allocating space for slot %d's "
			    "journal superblock", slot);

	err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE,
					slot, &ji->ji_ino);
	if (err) {
		com_err(whoami, err, "while looking up the journal inode for "
			"slot %d", slot);
		goto out;
	}

	err = ocfs2_read_cached_inode(fs, ji->ji_ino, &ji->ji_cinode);
	if (err) {
		com_err(whoami, err, "while reading cached inode %"PRIu64" "
			"for slot %d's journal", ji->ji_ino, slot);
		goto out;
	}

	if (!(ji->ji_cinode->ci_inode->id1.journal1.ij_flags &
	      OCFS2_JOURNAL_DIRTY_FL))
		goto out;

	err = lookup_journal_block(fs, ji, 0, &ji->ji_jsb_block, 1);
	if (err)
		goto out;

	/* XXX be smarter about reading in the whole super block if it
	 * spans multiple blocks */
	err = ocfs2_read_journal_superblock(fs, ji->ji_jsb_block, 
					    (char *)ji->ji_jsb);
	if (err) {
		com_err(whoami, err, "while reading block %"PRIu64" as slot "
			"%d's journal super block", ji->ji_jsb_block,
			ji->ji_slot);
		goto out;
	}

	ji->ji_replay = 1;

	verbosef("slot: %d jsb start %u maxlen %u\n", slot,
		 ji->ji_jsb->s_start, ji->ji_jsb->s_maxlen);
out:
	return err;
}
コード例 #3
0
ファイル: backup_super.c プロジェクト: djs55/ocfs2-tools
errcode_t ocfs2_set_backup_super_list(ocfs2_filesys *fs,
				      uint64_t *blocks, size_t len)
{
	size_t i;
	errcode_t ret = 0;
	char *buf = NULL;
	uint64_t *blkno = blocks;
	uint32_t cluster, bpc = fs->fs_clustersize / fs->fs_blocksize;

	if (!len || !blocks || !*blocks)
		goto bail;
	len = ocfs2_min(len,(size_t)OCFS2_MAX_BACKUP_SUPERBLOCKS);

	if (!OCFS2_HAS_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super),
				      OCFS2_FEATURE_COMPAT_BACKUP_SB)) {
		/* check all the blkno to see whether it is used. */
		for (i = 0; i < len; i++, blkno++) {
			ret = check_cluster(fs,
					    ocfs2_blocks_to_clusters(fs, *blkno));
			if (ret)
				goto bail;
		}
	}

	ret = ocfs2_malloc_blocks(fs->fs_io, bpc, &buf);
	if (ret)
		goto bail;
	memset(buf, 0, fs->fs_clustersize);

	/* zero all the clusters at first */
	blkno = blocks;
	for (i = 0; i < len; i++, blkno++) {
		cluster = ocfs2_blocks_to_clusters(fs, *blkno);
		ret = io_write_block(fs->fs_io, cluster*bpc, bpc, buf);
		if (ret)
			goto bail;
	}

	ret = ocfs2_refresh_backup_super_list(fs, blocks, len);
	if (ret)
		goto bail;

	/* We just tested the clusters, so the allocation can't fail */
	blkno = blocks;
	for (i = 0; i < len; i++, blkno++)
		ocfs2_new_specific_cluster(fs, ocfs2_blocks_to_clusters(fs, *blkno));

bail:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
コード例 #4
0
ファイル: dump.c プロジェクト: abligh/ocfs2-tools
static errcode_t dump_xattr_buckets(FILE *out,
                                    ocfs2_filesys *fs,
                                    uint64_t blkno,
                                    uint32_t clusters,
                                    uint64_t *xattrs_bucket,
                                    int verbose)
{
    int i;
    errcode_t ret = 0;
    char *bucket = NULL;
    struct ocfs2_xattr_header *xh;
    int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
    uint32_t bpc = ocfs2_xattr_buckets_per_cluster(fs);
    uint32_t num_buckets = clusters * bpc;

    ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
    if (ret)
        goto out;

    fprintf(out, "\tExtended Attributes extent record start at #%"PRIu64
            "  Has clusters: %u", blkno, clusters);
    for (i = 0; i < num_buckets; i++, blkno += blk_per_bucket) {
        ret = ocfs2_read_xattr_bucket(fs, blkno, bucket);
        if (ret)
            goto out;

        xh = (struct ocfs2_xattr_header *)bucket;
        /*
         * The real bucket num in this series of blocks is stored
         * in the 1st bucket.
         */
        if (i == 0) {
            num_buckets = xh->xh_num_buckets;
            fprintf(out, "  Has buckets: %d\n", num_buckets);
        }
        fprintf(out, "\t\tExtended Attributes in bucket #%d: %u\n",
                i, xh->xh_count);
        if (verbose)
            dump_xattr(out, xh);
        *xattrs_bucket += xh->xh_count;
    }

out:
    if (bucket)
        ocfs2_free(&bucket);

    return ret;
}
コード例 #5
0
ファイル: unix_io.c プロジェクト: djs55/ocfs2-tools
errcode_t io_init_cache(io_channel *channel, size_t nr_blocks)
{
	int i;
	struct io_cache *ic;
	char *dbuf;
	struct io_cache_block *icb_list;
	errcode_t ret;

	ret = ocfs2_malloc0(sizeof(struct io_cache), &ic);
	if (ret)
		goto out;

	ic->ic_nr_blocks = nr_blocks;
	ic->ic_lookup = RB_ROOT;
	INIT_LIST_HEAD(&ic->ic_lru);

	ret = ocfs2_malloc_blocks(channel, nr_blocks, &ic->ic_data_buffer);
	if (ret)
		goto out;
	ic->ic_data_buffer_len = (unsigned long)nr_blocks * channel->io_blksize;

	ret = ocfs2_malloc0(sizeof(struct io_cache_block) * nr_blocks,
			    &ic->ic_metadata_buffer);
	if (ret)
		goto out;
	ic->ic_metadata_buffer_len =
		(unsigned long)nr_blocks * sizeof(struct io_cache_block);

	icb_list = ic->ic_metadata_buffer;
	dbuf = ic->ic_data_buffer;
	for (i = 0; i < nr_blocks; i++) {
		icb_list[i].icb_blkno = UINT64_MAX;
		icb_list[i].icb_buf = dbuf;
		dbuf += channel->io_blksize;
		list_add_tail(&icb_list[i].icb_list, &ic->ic_lru);
	}

	ic->ic_use_count = 1;
	channel->io_cache = ic;

out:
	if (ret)
		io_free_cache(ic);

	return ret;
}
コード例 #6
0
ファイル: dirblocks.c プロジェクト: ystk/debian-ocfs2-tools
void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
			      void *priv_data)
{
	o2fsck_dirblocks *db = &ost->ost_dirblocks;
	ocfs2_filesys *fs = ost->ost_fs;
	o2fsck_dirblock_entry *dbe;
	struct rb_node *node;
	unsigned ret;
	errcode_t err;
	char *pre_cache_buf = NULL;
	int pre_cache_blocks = ocfs2_blocks_in_bytes(fs, 1024 * 1024);
	int cached_blocks = 0;

	o2fsck_reset_blocks_cached();
	if (o2fsck_worth_caching(1)) {
		err = ocfs2_malloc_blocks(fs->fs_io, pre_cache_blocks,
					  &pre_cache_buf);
		if (err)
			verbosef("Unable to allocate dirblock pre-cache "
				 "buffer, %s\n",
				 "ignoring");
	}

	for (node = rb_first(&db->db_root); node; node = rb_next(node)) {
		if (!cached_blocks && pre_cache_buf)
			cached_blocks = try_to_cache(fs, node, pre_cache_buf,
						     pre_cache_blocks);

		dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
		ret = func(dbe, priv_data);
		if (ret & OCFS2_DIRENT_ABORT)
			break;

		if (cached_blocks)
			cached_blocks--;
	}

	if (pre_cache_buf)
		ocfs2_free(&pre_cache_buf);
}
コード例 #7
0
ファイル: truncate.c プロジェクト: pepe5/ocfs2-tools
/*
 * Zero the area past i_size but still within an allocated
 * cluster. This avoids exposing nonzero data on subsequent file
 * extends.
 */
static errcode_t ocfs2_zero_tail_for_truncate(ocfs2_cached_inode *ci,
					      uint64_t new_size)
{
	errcode_t ret;
	char *buf = NULL;
	ocfs2_filesys *fs = ci->ci_fs;
	uint64_t start_blk, p_blkno, contig_blocks, start_off;
	int count, byte_counts, bpc = fs->fs_clustersize /fs->fs_blocksize;
	uint16_t ext_flags;

	if (new_size == 0)
		return 0;

	start_blk = new_size / fs->fs_blocksize;

	ret = ocfs2_extent_map_get_blocks(ci, start_blk, 1,
					  &p_blkno, &contig_blocks, &ext_flags);
	if (ret)
		goto out;

	/* Tail is a hole. */
	if (!p_blkno)
		goto out;

	if (ext_flags & OCFS2_EXT_REFCOUNTED) {
		uint32_t cpos = ocfs2_blocks_to_clusters(fs, start_blk);
		ret = ocfs2_refcount_cow(ci, cpos, 1, cpos + 1);
		if (ret)
			goto out;

		ret = ocfs2_extent_map_get_blocks(ci, start_blk, 1,
						  &p_blkno, &contig_blocks,
						  &ext_flags);
		if (ret)
			goto out;

		assert(!(ext_flags & OCFS2_EXT_REFCOUNTED) && p_blkno);

	}

	/* calculate the total blocks we need to empty. */
	count = bpc - (p_blkno & (bpc - 1));
	ret = ocfs2_malloc_blocks(fs->fs_io, count, &buf);
	if (ret)
		goto out;

	ret = ocfs2_read_blocks(fs, p_blkno, count, buf);
	if (ret)
		goto out;

	/* empty the content after the new_size and within the same cluster. */
	start_off = new_size % fs->fs_blocksize;
	byte_counts = count * fs->fs_blocksize - start_off;
	memset(buf + start_off, 0, byte_counts);

	ret = io_write_block(fs->fs_io, p_blkno, count, buf);

out:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
コード例 #8
0
ファイル: chain.c プロジェクト: djs55/ocfs2-tools
errcode_t ocfs2_cache_chain_allocator_blocks(ocfs2_filesys *fs,
					     struct ocfs2_dinode *di)
{
	struct io_vec_unit *ivus = NULL;
	char *buf = NULL;
	errcode_t ret = 0;
	int i, j, count;
	struct ocfs2_chain_list *cl;
	struct ocfs2_chain_rec *cr;
	struct ocfs2_group_desc *gd;
	io_channel *channel = fs->fs_io;
	int blocksize = fs->fs_blocksize;
	int64_t group_size;

	if (!(di->i_flags & OCFS2_CHAIN_FL)) {
		ret = OCFS2_ET_INODE_NOT_VALID;
		goto out;
	}

	if (!channel)
		goto out;

	if (!di->i_clusters)
		goto out;

	group_size = (int64_t)di->i_clusters / di->id2.i_chain.cl_cpg;
	group_size *= blocksize;

	if (group_size > io_get_cache_size(channel))
		goto out;

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

	ret = ocfs2_malloc_blocks(channel, count, &buf);
	if (ret)
		goto out;
	memset(buf, 0, count * blocksize);

	ret = ocfs2_malloc(sizeof(struct io_vec_unit) * count, &ivus);
	if (ret)
		goto out;

	for (i = 0; i < count; ++i) {
		cr = &(cl->cl_recs[i]);
		ivus[i].ivu_blkno = cr->c_blkno;
		ivus[i].ivu_buf = buf + (i * blocksize);
		ivus[i].ivu_buflen = blocksize;
	}

	while (count) {
		ret = io_vec_read_blocks(channel, ivus, count);
		if (ret)
			goto out;

		for (i = 0, j = 0; i < count; ++i) {
			gd = (struct ocfs2_group_desc *)ivus[i].ivu_buf;

			ret = ocfs2_validate_meta_ecc(fs, ivus[i].ivu_buf,
						      &gd->bg_check);
			if (ret)
				goto out;

			if (memcmp(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
				   strlen(OCFS2_GROUP_DESC_SIGNATURE))) {
				ret = OCFS2_ET_BAD_GROUP_DESC_MAGIC;
				goto out;
			}
			ocfs2_swap_group_desc_to_cpu(fs, gd);

			if ((gd->bg_next_group > OCFS2_SUPER_BLOCK_BLKNO) &&
			    (gd->bg_next_group < fs->fs_blocks)) {
				ivus[j].ivu_blkno = gd->bg_next_group;
				memset(ivus[j].ivu_buf, 0, blocksize);
				ivus[j].ivu_buflen = blocksize;
				j++;
			}
		}

		count = j;
	}

out:
	ocfs2_free(&ivus);
	ocfs2_free(&buf);
	return ret;
}
コード例 #9
0
ファイル: journal.c プロジェクト: djs55/ocfs2-tools
/* Try and replay the slots journals if they're dirty.  This only returns
 * a non-zero error if the caller should not continue. */
errcode_t o2fsck_replay_journals(ocfs2_filesys *fs, int *replayed)
{
	errcode_t err = 0, ret = 0;
	struct journal_info *jis = NULL, *ji;
	journal_superblock_t *jsb;
	char *buf = NULL;
	int journal_trouble = 0;
	uint16_t i, max_slots;
	ocfs2_bitmap *used_blocks = NULL;

	max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;

	ret = ocfs2_block_bitmap_new(fs, "journal blocks",
				     &used_blocks);
	if (ret) {
		com_err(whoami, ret, "while allocating journal block bitmap"); 
		goto out;
	}

	ret = ocfs2_malloc_blocks(fs->fs_io, 1, &buf);
	if (ret) {
		com_err(whoami, ret, "while allocating room to read journal "
			    "blocks");
		goto out;
	}

	ret = ocfs2_malloc0(sizeof(struct journal_info) * max_slots, &jis);
	if (ret) {
		com_err(whoami, ret, "while allocating an array of block "
			 "numbers for journal replay");
		goto out;
	}

	printf("Checking each slot's journal.\n");

	for (i = 0, ji = jis; i < max_slots; i++, ji++) {
		ji->ji_used_blocks = used_blocks;
		ji->ji_revoke = RB_ROOT;
		ji->ji_slot = i;

		/* sets ji->ji_replay */
		err = prep_journal_info(fs, i, ji);
		if (err) {
			printf("Slot %d seems to have a corrupt journal.\n",
			       i);
			journal_trouble = 1;
			continue;
		}

		if (!ji->ji_replay) {
			verbosef("slot %d is clean\n", i);
			continue;
		}

		err = walk_journal(fs, i, ji, buf, 0);
		if (err) {
			printf("Slot %d's journal can not be replayed.\n", i);
			journal_trouble = 1;
		}
	}

	for (i = 0, ji = jis; i < max_slots; i++, ji++) {
		if (!ji->ji_replay)
			continue;

		printf("Replaying slot %d's journal.\n", i);

		err = walk_journal(fs, i, ji, buf, 1);
		if (err) {
			journal_trouble = 1;
			continue;
		} 

		jsb = ji->ji_jsb;
		/* reset the journal */
		jsb->s_start = 0;

		if (ji->ji_set_final_seq)
			jsb->s_sequence = ji->ji_final_seq + 1;

		/* we don't write back a clean 'mounted' bit here.  That would
		 * have to also include having recovered the orphan dir.  we
		 * updated s_start, though, so we won't replay the journal
		 * again. */
		err = ocfs2_write_journal_superblock(fs,
						     ji->ji_jsb_block,
						     (char *)ji->ji_jsb);
		if (err) {
			com_err(whoami, err, "while writing slot %d's journal "
				"super block", i);
			journal_trouble = 1;
		} else {
			printf("Slot %d's journal replayed successfully.\n",
			       i);
			*replayed = 1;
		}
	}

	/* this is awkward, but we want fsck -n to tell us as much as it
	 * can so we don't want to ask to proceed here.  */
	if (journal_trouble)
		printf("*** There were problems replaying journals.  Be "
		       "careful in telling fsck to make repairs to this "
		       "filesystem.\n");

	ret = 0;

out:
	if (jis) {
		for (i = 0, ji = jis; i < max_slots; i++, ji++) {
			if (ji->ji_jsb)
				ocfs2_free(&ji->ji_jsb);
			if (ji->ji_cinode)
				ocfs2_free_cached_inode(fs, 
							ji->ji_cinode);
			revoke_free_all(&ji->ji_revoke);
		}
		ocfs2_free(&jis);
	}

	if (buf)
		ocfs2_free(&buf);
	if (used_blocks)
		ocfs2_bitmap_free(used_blocks);

	return ret;
}
コード例 #10
0
ファイル: journal.c プロジェクト: ystk/debian-ocfs2-tools
errcode_t read_journal(ocfs2_filesys *fs, uint64_t blkno, FILE *out)
{
	char *buf = NULL;
	char *jsb_buf = NULL;
	char *p;
	uint64_t blocknum;
	uint64_t len;
	uint64_t offset;
	uint32_t got;
	uint64_t last_unknown = 0;
	uint32_t buflen = 1024 * 1024;
	int buflenbits;
	ocfs2_cached_inode *ci = NULL;
	errcode_t ret;
	journal_superblock_t *jsb;

	ret = ocfs2_read_cached_inode(fs, blkno, &ci);
	if (ret) {
		com_err(gbls.cmd, ret, "while reading inode %"PRIu64, blkno);
		goto bail;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &jsb_buf);
	if (ret) {
		com_err(gbls.cmd, ret,
			"while allocating journal superblock buffer");
		goto bail;
	}

	buflenbits = buflen >>
			OCFS2_RAW_SB(gbls.fs->fs_super)->s_blocksize_bits;
	ret = ocfs2_malloc_blocks(fs->fs_io, buflenbits, &buf);
	if (ret) {
		com_err(gbls.cmd, ret, "while allocating %u bytes", buflen);
		goto bail;
	}

	offset = 0;
	blocknum = 0;
	jsb = (journal_superblock_t *)jsb_buf;
	while (1) {
		ret = ocfs2_file_read(ci, buf, buflen, offset, &got);
		if (ret) {
			com_err(gbls.cmd, ret, "while reading journal");
			goto bail;
		};

		if (got == 0)
			break;

		p = buf;
		len = got;

		if (offset == 0) {
			memcpy(jsb_buf, buf, fs->fs_blocksize);
			dump_jbd_superblock(out, jsb);
			ocfs2_swap_journal_superblock(jsb);
			blocknum++;
			p += fs->fs_blocksize;
			len -= fs->fs_blocksize;
		}

		scan_journal(out, jsb, p, len, &blocknum, &last_unknown);

		if (got < buflen)
			break;
		offset += got;
	}

	if (last_unknown) {
		dump_jbd_unknown(out, last_unknown, blocknum);
		last_unknown = 0;
	}

bail:
	if (jsb_buf)
		ocfs2_free(&jsb_buf);
	if (buf)
		ocfs2_free(&buf);
	if (ci)
		ocfs2_free_cached_inode(fs, ci);

	return ret;
}
コード例 #11
0
ファイル: fileio.c プロジェクト: ystk/debian-ocfs2-tools
errcode_t ocfs2_read_whole_file(ocfs2_filesys *fs,
				uint64_t blkno,
				char **buf,
				int *len)
{
	struct read_whole_context	ctx;
	errcode_t			retval;
	char *inode_buf;
	struct ocfs2_dinode *di;

	/* So the caller can see nothing was read */
	*len = 0;
	*buf = NULL;

	retval = ocfs2_malloc_block(fs->fs_io, &inode_buf);
	if (retval)
		return retval;

	retval = ocfs2_read_inode(fs, blkno, inode_buf);
	if (retval)
		goto out_free;

	di = (struct ocfs2_dinode *)inode_buf;

	/* Arbitrary limit for our malloc */
	retval = OCFS2_ET_INVALID_ARGUMENT;
	if (di->i_size > INT_MAX) 
		goto out_free;

	retval = ocfs2_malloc_blocks(fs->fs_io,
				     ocfs2_blocks_in_bytes(fs, di->i_size),
				     buf);
	if (retval)
		goto out_free;

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
		return ocfs2_inline_data_read(di, *buf, di->i_size, 0,
					      (uint32_t *)len);

	ctx.buf = *buf;
	ctx.ptr = *buf;
	ctx.size = di->i_size;
	ctx.offset = 0;
	ctx.errcode = 0;
	retval = ocfs2_block_iterate(fs, blkno, 0,
				     read_whole_func, &ctx);

	*len = ctx.size;
	if (ctx.offset < ctx.size)
		*len = ctx.offset;

out_free:
	ocfs2_free(&inode_buf);

	if (!(*len)) {
		ocfs2_free(buf);
		*buf = NULL;
	}

	if (retval)
		return retval;
	return ctx.errcode;
}
コード例 #12
0
ファイル: memory.c プロジェクト: pepe5/ocfs2-tools
errcode_t ocfs2_malloc_block(io_channel *channel, void *ptr)
{
	return ocfs2_malloc_blocks(channel, 1, ptr);
}
コード例 #13
0
ファイル: image.c プロジェクト: pepe5/ocfs2-tools
/*
 * allocate ocfs2_image_bitmap_arr and ocfs2 image bitmap blocks. o2image bitmap
 * block is of size OCFS2_IMAGE_BITMAP_BLOCKSIZE and ocfs2_image_bitmap_arr
 * tracks the bitmap blocks
 */
errcode_t ocfs2_image_alloc_bitmap(ocfs2_filesys *ofs)
{
	uint64_t blks, allocsize, leftsize;
	struct ocfs2_image_state *ost = ofs->ost;
	int indx, i, n;
	errcode_t ret;
	char *buf;

	ost->ost_bmpblks =
		((ost->ost_fsblkcnt - 1) / (OCFS2_IMAGE_BITS_IN_BLOCK)) + 1;
	ost->ost_bmpblksz = OCFS2_IMAGE_BITMAP_BLOCKSIZE;
	blks = ost->ost_bmpblks;

	/* allocate memory for an array to track bitmap blocks */
	ret = ocfs2_malloc0((blks * sizeof(ocfs2_image_bitmap_arr)),
			    &ost->ost_bmparr);
	if (ret)
		return ret;

	allocsize = blks * OCFS2_IMAGE_BITMAP_BLOCKSIZE;
	leftsize = allocsize;
	indx = 0;

	/* allocate bitmap blocks and assign blocks to above array */
	while (leftsize) {
		ret = ocfs2_malloc_blocks(ofs->fs_io,
					  allocsize/io_get_blksize(ofs->fs_io),
					  &buf);
		if (ret && (ret != -ENOMEM))
			goto out;

		if (ret == -ENOMEM) {
			if (allocsize == OCFS2_IMAGE_BITMAP_BLOCKSIZE)
				goto out;
			allocsize >>= 1;
			if (allocsize % OCFS2_IMAGE_BITMAP_BLOCKSIZE) {
				allocsize /= OCFS2_IMAGE_BITMAP_BLOCKSIZE;
				allocsize *= OCFS2_IMAGE_BITMAP_BLOCKSIZE;
			}
			continue;
		}

		n = allocsize / OCFS2_IMAGE_BITMAP_BLOCKSIZE;
		for (i = 0; i < n; i++) {
			ost->ost_bmparr[indx].arr_set_bit_cnt = 0;
			ost->ost_bmparr[indx].arr_map =
				((char *)buf + (i *
						OCFS2_IMAGE_BITMAP_BLOCKSIZE));

			/* remember buf address to free it later */
			if (!i)
				ost->ost_bmparr[indx].arr_self = buf;
			indx++;
		}
		leftsize -= allocsize;
		if (leftsize <= allocsize)
			allocsize = leftsize;
	}
out:
	/* If allocation failed free and return error */
	if (leftsize) {
		for (i = 0; i < indx; i++)
			if (ost->ost_bmparr[i].arr_self)
				ocfs2_free(&ost->ost_bmparr[i].arr_self);
		ocfs2_free(&ost->ost_bmparr);
	}

	return ret;
}
コード例 #14
0
ファイル: unix_io.c プロジェクト: ystk/debian-ocfs2-tools
int main(int argc, char *argv[])
{
	errcode_t ret;
	int c;
	int64_t blkno, count, blksize;
	char *filename;
	io_channel *channel;
	char *blks;

	/* Some simple defaults */
	blksize = 512;
	blkno = 0;
	count = 1;

	initialize_ocfs_error_table();

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

			case 'c':
				count = read_number(optarg);
				if (!count) {
					fprintf(stderr, 
						"Invalid count: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			case 'B':
				blksize = read_number(optarg);
				if (!blksize) {
					fprintf(stderr, 
						"Invalid blksize: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

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

	if (blksize % OCFS2_MIN_BLOCKSIZE) {
		fprintf(stderr, "Invalid blocksize: %"PRId64"\n", blksize);
		print_usage();
		return 1;
	}
	if (count < 0) {
		if (-count > (int64_t)INT_MAX) {
			fprintf(stderr, "Count is too large: %"PRId64"\n",
				count);
			print_usage();
			return 1;
		}
		count = -count / blksize;
	} else  {
		if ((count * blksize) > INT_MAX) {
			fprintf(stderr, "Count is too large: %"PRId64"\n",
				count);
			print_usage();
			return 1;
		}
	}

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

	filename = argv[optind];

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

	ret = ocfs2_malloc_blocks(channel, (int)count, &blks);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating %"PRId64" blocks", count);
		goto out_channel;
	}

	ret = io_read_block(channel, blkno, (int)count, blks);
	if (ret) {
		com_err(argv[0], ret,
			"while reading %"PRId64" blocks at block %"PRId64" (%s)",
			count, blkno,
			strerror(io_get_error(channel)));
		goto out_blocks;
	}

	for (c = 0; c < count; c++)
		dump_block(blkno + c, blksize, blks + (c * blksize));

out_blocks:
	ocfs2_free(&blks);

out_channel:
	ret = io_close(channel);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
コード例 #15
0
ファイル: journal.c プロジェクト: djs55/ocfs2-tools
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;
}
コード例 #16
0
ファイル: inode.c プロジェクト: renzhengeek/automake-project
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);
}
コード例 #17
0
ファイル: extents.c プロジェクト: ystk/debian-ocfs2-tools
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno;
	int c;
	int walk_blocks = 0, walk_extents = 0;
	char *filename, *buf, *eb_buf = NULL;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_it wi;
	struct walk_block wb;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "bei:")) != EOF) {
		switch (c) {
			case 'b':
				walk_blocks = 1;
				break;

			case 'e':
				walk_extents = 1;
				break;

			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];

	if (!(walk_blocks + walk_extents)) {
		fprintf(stderr,
			"No operation specified\n");
		print_usage();
		return 1;
	}

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

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


	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;

	fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\" has depth %"PRId16"\n",
		blkno, filename, di->id2.i_list.l_tree_depth);

	if (walk_extents) {
		if (di->id2.i_list.l_tree_depth) {
			ret = ocfs2_malloc_blocks(fs->fs_io,
						  di->id2.i_list.l_tree_depth,
						  &eb_buf);
			if (ret) {
				com_err(argv[0], ret,
					"while allocating eb buffer");
				goto out_free;
			}
		}

		wi.di = di;
		ret = ocfs2_extent_iterate(fs, blkno, 0,
					   eb_buf,
					   walk_extents_func,
					   &wi);
		if (ret) {
			com_err(argv[0], ret,
				"while walking extents");
			goto out_free;
		}
	}

	if (walk_blocks) {
		wb.di = di;
		wb.run_first_blkno = wb.run_first_bcount =
			wb.run_prev_blkno = 0;
		wb.last_block = (wb.di->i_size +
				 (fs->fs_blocksize - 1)) /
			fs->fs_blocksize;
		ret = ocfs2_block_iterate(fs, blkno, 0,
					  walk_blocks_func,
					  &wb);
		if (ret) {
			com_err(argv[0], ret,
				"while walking blocks");
			goto out_free;
		}
	}

out_free:
	if (eb_buf)
		ocfs2_free(&eb_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;
}