Esempio n. 1
0
errcode_t ocfs2_bitmap_alloc_region(ocfs2_bitmap *bitmap,
				    uint64_t start_bit,
				    int bitmap_start,
				    int total_bits,
				    struct ocfs2_bitmap_region **ret_br)
{
	errcode_t ret;
	struct ocfs2_bitmap_region *br;

	if (total_bits < 0)
		return OCFS2_ET_INVALID_BIT;

	ret = ocfs2_malloc0(sizeof(struct ocfs2_bitmap_region), &br);
	if (ret)
		return ret;


	br->br_start_bit = start_bit;
	br->br_bitmap_start = bitmap_start;
	br->br_valid_bits = total_bits;
	br->br_total_bits = total_bits + bitmap_start;
	br->br_bytes = ocfs2_align_total(br->br_total_bits);

	ret = ocfs2_malloc0(br->br_bytes, &br->br_bitmap);
	if (ret)
		ocfs2_free(&br);
	else
		*ret_br = br;

	return ret;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
errcode_t ocfs2_chain_iterate(ocfs2_filesys *fs,
			      uint64_t blkno,
			      int (*func)(ocfs2_filesys *fs,
					  uint64_t gd_blkno,
					  int chain_num,
					  void *priv_data),
			       void *priv_data)
{
	int iret = 0;
	char *buf;
	struct ocfs2_dinode *inode;
	errcode_t ret;
	struct chain_context ctxt;

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

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

	inode = (struct ocfs2_dinode *)buf;

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

	ret = OCFS2_ET_INODE_CANNOT_BE_ITERATED;
	if (!(inode->i_flags & OCFS2_CHAIN_FL))
		goto out_buf;

	ret = ocfs2_malloc0(fs->fs_blocksize, &ctxt.gd_buf);
	if (ret)
		goto out_gd_buf;

	ctxt.fs = fs;
	ctxt.func = func;
	ctxt.priv_data = priv_data;

	ret = 0;
	iret |= chain_iterate_cl(&inode->id2.i_chain, &ctxt);
	if (iret & OCFS2_EXTENT_ERROR)
		ret = ctxt.errcode;

	if (iret & OCFS2_EXTENT_CHANGED) {
		/* Do something */
	}

out_gd_buf:
	if (ctxt.gd_buf)
		ocfs2_free(&ctxt.gd_buf);

out_buf:
	ocfs2_free(&buf);

	return ret;
}
Esempio n. 4
0
/*
 * This function is private to the library.  Bitmap subtypes will
 * use this to allocate their structure, but their b_ops will
 * determine how they work.
 */
errcode_t ocfs2_bitmap_new(ocfs2_filesys *fs,
			   uint64_t total_bits,
			   const char *description,
			   struct ocfs2_bitmap_operations *ops,
			   void *private_data,
			   ocfs2_bitmap **ret_bitmap)
{
	errcode_t ret;
	ocfs2_bitmap *bitmap;

	if (!ops->set_bit || !ops->clear_bit || !ops->test_bit)
		return OCFS2_ET_INVALID_ARGUMENT;

	ret = ocfs2_malloc0(sizeof(struct _ocfs2_bitmap), &bitmap);
	if (ret)
		return ret;

	bitmap->b_fs = fs;
	bitmap->b_total_bits = total_bits;
	bitmap->b_ops = ops;
	bitmap->b_regions = RB_ROOT;
	bitmap->b_private = private_data;
	if (description) {
		ret = ocfs2_malloc0(sizeof(char) *
				    (strlen(description) + 1),
				    &bitmap->b_description);
		if (ret)
			goto out_free;

		strcpy(bitmap->b_description, description);
	}

	*ret_bitmap = bitmap;
	return 0;

out_free:
	ocfs2_free(&bitmap);

	return ret;
}
Esempio n. 5
0
static int features_parse_option(struct tunefs_operation *op, char *arg)
{
    int rc = 1;
    errcode_t err;
    struct feature_op_state *state = NULL;
    struct check_supported_context ctxt = {
        .sc_string = arg,
    };

    if (!arg) {
        errorf("No features specified\n");
        goto out;
    }

    err = ocfs2_malloc0(sizeof(struct feature_op_state), &state);
    if (err) {
        tcom_err(err, "while processing feature options");
        goto out;
    }

    state->fo_op = op;
    err = ocfs2_parse_feature(arg, &state->fo_feature_set,
                              &state->fo_reverse_set);
    if (err) {
        tcom_err(err, "while parsing feature options \"%s\"", arg);
        goto out;
    }

    ctxt.sc_state = state;
    ctxt.sc_action = FEATURE_ENABLE;
    ocfs2_feature_foreach(&state->fo_feature_set, check_supported_func,
                          &ctxt);
    if (ctxt.sc_error)
        goto out;

    ctxt.sc_action = FEATURE_DISABLE;
    ocfs2_feature_reverse_foreach(&state->fo_reverse_set,
                                  check_supported_func,
                                  &ctxt);
    if (ctxt.sc_error)
        goto out;

    rc = 0;

out:
    if (!rc)
        op->to_private = state;
    else if (state)
        ocfs2_free(&state);

    return rc;
}
Esempio n. 6
0
/*
 * \a=0x07, \b=0x08, \t=0x09, \n=0x0a, \v=0x0b, \f=0x0c, \r=0x0d
 */
static char * process_escapes(char *queryfmt)
{
	char *fmt;
	int i, j;
	int len;

	len = strlen(queryfmt);

	if (ocfs2_malloc0(len + 1, &fmt))
		return NULL;

	for(i = 0, j = 0; i < len; ) {
		if (queryfmt[i] != '\\')
			fmt[j++] = queryfmt[i++];
		else {
			switch(queryfmt[i + 1]) {
			case 'a':
				fmt[j++] = 0x07;
				break;
			case 'b':
				fmt[j++] = 0x08;
				break;
			case 't':
				fmt[j++] = 0x09;
				break;
			case 'n':
				fmt[j++] = 0x0A;
				break;
			case 'v':
				fmt[j++] = 0x0B;
				break;
			case 'f':
				fmt[j++] = 0x0C;
				break;
			case 'r':
				fmt[j++] = 0x0D;
				break;
			default:
				fmt[j++] = queryfmt[i];
				fmt[j++] = queryfmt[i + 1];
				break;
			}
			i += 2;
		}
	}

	return fmt;
}
Esempio n. 7
0
errcode_t ocfs2_lookup_system_inode(ocfs2_filesys *fs, int type,
				    int slot_num, uint64_t *blkno)
{
	errcode_t ret;
	char *buf;

	ret = ocfs2_malloc0(sizeof(char) * (OCFS2_MAX_FILENAME_LEN + 1), &buf);
	if (ret)
		return ret;

	ocfs2_sprintf_system_inode_name(buf, OCFS2_MAX_FILENAME_LEN, 
					type, slot_num);

	ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, buf,
			   strlen(buf), NULL, blkno);

	ocfs2_free(&buf);

	return ret;
}
Esempio n. 8
0
/*
 * ocfs2_partition_list()
 *
 */
static errcode_t ocfs2_partition_list (struct list_head *dev_list)
{
	errcode_t ret = 0;
	FILE *proc;
	char line[256];
	char name[256];
	char major[256];
	char minor[256];
	ocfs2_devices *dev;

	proc = fopen ("/proc/partitions", "r");
	if (proc == NULL) {
		ret = OCFS2_ET_IO;
		goto bail;
	}

	while (fgets (line, sizeof(line), proc) != NULL) {
		*major = *minor = *name = '\0';
		if (sscanf(line, "%*[ ]%[0-9]%*[ ]%[0-9] %*d %99[^ \t\n]",
			   major, minor, name) != 3)
			continue;

		ret = ocfs2_malloc0(sizeof(ocfs2_devices), &dev);
		if (ret)
			goto bail;

		snprintf(dev->dev_name, sizeof(dev->dev_name), "/dev/%s", name);
		dev->maj_num = strtoul(major, NULL, 0);
		dev->min_num = strtoul(minor, NULL, 0);
		list_add_tail(&(dev->list), dev_list);
	}

bail:
	if (proc)
		fclose(proc);

	return ret;
}
Esempio n. 9
0
errcode_t io_open(const char *name, int flags, io_channel **channel)
{
	errcode_t ret;
	io_channel *chan = NULL;
#ifdef __linux__
	struct stat stat_buf;
	struct utsname ut;
#endif

	if (!name || !*name)
		return OCFS2_ET_BAD_DEVICE_NAME;

	ret = ocfs2_malloc0(sizeof(struct _io_channel), &chan);
	if (ret)
		return ret;

	ret = ocfs2_malloc(strlen(name)+1, &chan->io_name);
	if (ret)
		goto out_chan;
	strcpy(chan->io_name, name);
	chan->io_blksize = OCFS2_MIN_BLOCKSIZE;
	chan->io_flags = (flags & OCFS2_FLAG_RW) ? O_RDWR : O_RDONLY;
	chan->io_nocache = false;
	if (!(flags & OCFS2_FLAG_BUFFERED))
		chan->io_flags |= O_DIRECT;
	chan->io_error = 0;

	chan->io_fd = open64(name, chan->io_flags);
	if (chan->io_fd < 0) {
		/* chan will be freed, don't bother with chan->io_error */
		if (errno == ENOENT)
			ret = OCFS2_ET_NAMED_DEVICE_NOT_FOUND;
		else
			ret = OCFS2_ET_IO;
		goto out_name;
	}

	if (!(flags & OCFS2_FLAG_BUFFERED)) {
		ret = io_validate_o_direct(chan);
		if (ret)
			goto out_close;  /* FIXME: bindraw here */
	}

	/* Workaround from e2fsprogs */
#ifdef __linux__
#undef RLIM_INFINITY
#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4)))
#define RLIM_INFINITY	((unsigned long)(~0UL>>1))
#else
#define RLIM_INFINITY  (~0UL)
#endif
	/*
	 * Work around a bug in 2.4.10-2.4.18 kernels where writes to
	 * block devices are wrongly getting hit by the filesize
	 * limit.  This workaround isn't perfect, since it won't work
	 * if glibc wasn't built against 2.2 header files.  (Sigh.)
	 * 
	 */
	if ((flags & OCFS2_FLAG_RW) &&
	    (uname(&ut) == 0) &&
	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
	     (ut.release[2] == '4') && (ut.release[3] == '.') &&
	     (ut.release[4] == '1') && (ut.release[5] >= '0') &&
	     (ut.release[5] < '8')) &&
	    (fstat(chan->io_fd, &stat_buf) == 0) &&
	    (S_ISBLK(stat_buf.st_mode))) {
		struct rlimit	rlim;
		
		rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY;
		setrlimit(RLIMIT_FSIZE, &rlim);
		getrlimit(RLIMIT_FSIZE, &rlim);
		if (((unsigned long) rlim.rlim_cur) <
		    ((unsigned long) rlim.rlim_max)) {
			rlim.rlim_cur = rlim.rlim_max;
			setrlimit(RLIMIT_FSIZE, &rlim);
		}
	}
#endif

	*channel = chan;
	return 0;

out_close:
	/* Ignore the return, leave the original error */
	close(chan->io_fd);

out_name:
	ocfs2_free(&chan->io_name);

out_chan:
	ocfs2_free(&chan);

	*channel = NULL;
	return ret;
}
Esempio n. 10
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. 11
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;
}
Esempio n. 12
0
/*
 * 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. 13
0
/*
 * 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;
}
Esempio n. 14
0
/*
 * This routine loads bitmap blocks from an o2image image file into memory.
 * This process happens during file open. bitmap blocks reside towards
 * the end of the imagefile.
 */
errcode_t ocfs2_image_load_bitmap(ocfs2_filesys *ofs)
{
	struct ocfs2_image_state *ost;
	struct ocfs2_image_hdr *hdr;
	uint64_t blk_off, bits_set;
	int i, j, fd;
	ssize_t count;
	errcode_t ret;
	char *blk;

	ret = ocfs2_malloc0(sizeof(struct ocfs2_image_state), &ofs->ost);
	if (ret)
		return ret;

	ost = ofs->ost;
	ret = ocfs2_malloc_block(ofs->fs_io, &blk);
	if (ret)
		return ret;

	/* read ocfs2 image header */
	ret = io_read_block(ofs->fs_io, 0, 1, blk);
	if (ret)
		goto out;

	hdr = (struct ocfs2_image_hdr *)blk;
	ocfs2_image_swap_header(hdr);

	ret = OCFS2_ET_BAD_MAGIC;
	if (hdr->hdr_magic != OCFS2_IMAGE_MAGIC)
		goto out;

	if (memcmp(hdr->hdr_magic_desc, OCFS2_IMAGE_DESC,
		   sizeof(OCFS2_IMAGE_DESC)))
		goto out;

	ret = OCFS2_ET_OCFS_REV;
	if (hdr->hdr_version > OCFS2_IMAGE_VERSION)
		goto out;

	ost->ost_fsblkcnt 	= hdr->hdr_fsblkcnt;
	ost->ost_fsblksz 	= hdr->hdr_fsblksz;
	ost->ost_imgblkcnt 	= hdr->hdr_imgblkcnt;
	ost->ost_bmpblksz 	= hdr->hdr_bmpblksz;

	ret = ocfs2_image_alloc_bitmap(ofs);
	if (ret)
		return ret;

	/* load bitmap blocks ocfs2 image state */
	bits_set = 0;
	fd 	= io_get_fd(ofs->fs_io);
	blk_off = (ost->ost_imgblkcnt + 1) * ost->ost_fsblksz;

	for (i = 0; i < ost->ost_bmpblks; i++) {
		ost->ost_bmparr[i].arr_set_bit_cnt = bits_set;
		/*
		 * we don't use io_read_block as ocfs2 image bitmap block size
		 * could be different from filesystem block size
		 */
		count = pread64(fd, ost->ost_bmparr[i].arr_map,
				ost->ost_bmpblksz, blk_off);
		if (count < 0) {
			ret = OCFS2_ET_IO;
			goto out;
		}

		/* add bits set in this bitmap */
		for (j = 0; j < (ost->ost_bmpblksz * 8); j++)
			if (ocfs2_test_bit(j, ost->ost_bmparr[i].arr_map))
				bits_set++;

		blk_off += ost->ost_bmpblksz;
	}

out:
	if (blk)
		ocfs2_free(&blk);
	return ret;
}
Esempio n. 15
0
static int walk_tree_func(struct ocfs2_dir_entry *dentry,
			  int offset,
			  int blocksize,
			  char *buf,
			  void *priv_data)
{
	errcode_t ret;
	int len, oldval;
	int reti = 0;
	char *old_path, *path;
	struct walk_path *wp = priv_data;

	if (!strncmp(dentry->name, ".", dentry->name_len) ||
	    !strncmp(dentry->name, "..", dentry->name_len))
		return 0;

	len = strlen(wp->path);

	if (len + dentry->name_len > 4095) {
		fprintf(stderr, "name is too long in %s\n", wp->path);
		return OCFS2_DIRENT_ABORT;
	}

	ret = ocfs2_malloc0(4096, &path);
	if (ret) {
		com_err(wp->argv0, ret,
			"while allocating path memory in %s\n",
			wp->path);
		return OCFS2_DIRENT_ABORT;
	}
	
	memcpy(path, wp->path, len);
	memcpy(path + len, dentry->name, dentry->name_len);
	if (dentry->file_type == OCFS2_FT_DIR)
		path[len + dentry->name_len] = '/';

	if (wp->check_dups) {
		ret = ocfs2_bitmap_test(wp->dup_map, dentry->inode,
					&oldval);
		if (oldval) {
			fprintf(stdout, "Dup! %20"PRIu64" %s\n",
				(uint64_t)dentry->inode, path);
		}
		goto out;
	}

	oldval = 0;
	ret = ocfs2_bitmap_set(wp->inode_map, dentry->inode, &oldval);
	if (ret) {
		com_err(wp->argv0, ret,
			"while setting bitmap bit %"PRIu64"\n",
			(uint64_t)dentry->inode);
		reti = OCFS2_DIRENT_ABORT;
		goto out;
	}

	if (oldval) {
		wp->has_dups = 1;
		ret = ocfs2_bitmap_set(wp->dup_map, dentry->inode,
				       NULL);
		if (ret) {
			com_err(wp->argv0, ret,
				"while setting dup bit %"PRIu64"\n",
				(uint64_t)dentry->inode);
			reti = OCFS2_DIRENT_ABORT;
			goto out;
		}
	}

	if (!wp->quiet)
		fprintf(stdout, "%20"PRIu64" %s\n",
			(uint64_t)dentry->inode, path);

	if (dentry->file_type == OCFS2_FT_DIR) {
		old_path = wp->path;
		wp->path = path;
		ret = ocfs2_dir_iterate(wp->fs, dentry->inode, 0, NULL,
					walk_tree_func, wp);
		if (ret) {
			com_err(wp->argv0, ret,
				"while walking %s", wp->path);
			reti = OCFS2_DIRENT_ABORT;
		}
		wp->path = old_path;
	}

out:
	ocfs2_free(&path);

	return reti;
}
Esempio n. 16
0
/* 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;
}
Esempio n. 17
0
errcode_t ocfs2_open(const char *name, int flags,
		     unsigned int superblock, unsigned int block_size,
		     ocfs2_filesys **ret_fs)
{
	ocfs2_filesys *fs;
	errcode_t ret;
	int i, len;
	char *ptr;
	unsigned char *raw_uuid;

	ret = ocfs2_malloc0(sizeof(ocfs2_filesys), &fs);
	if (ret)
		return ret;

	fs->fs_flags = flags;
	fs->fs_umask = 022;

	ret = io_open(name, (flags & (OCFS2_FLAG_RO | OCFS2_FLAG_RW |
				      OCFS2_FLAG_BUFFERED)),
		      &fs->fs_io);
	if (ret)
		goto out;

	ret = ocfs2_malloc(strlen(name)+1, &fs->fs_devname);
	if (ret)
		goto out;
	strcpy(fs->fs_devname, name);

	/*
	 * If OCFS2_FLAG_IMAGE_FILE is specified, it needs to be handled
	 * differently
	 */
	if (flags & OCFS2_FLAG_IMAGE_FILE) {
		ret = ocfs2_image_load_bitmap(fs);
		if (ret)
			goto out;
		if (!superblock)
			superblock = fs->ost->ost_superblocks[0];
		if (!block_size)
			block_size = fs->ost->ost_fsblksz;
	}

	/* image file is not a device */
	if (!(flags & OCFS2_FLAG_IMAGE_FILE)) {
		if (io_is_device_readonly(fs->fs_io))
			fs->fs_flags |= OCFS2_FLAG_HARD_RO;
	}

	/*
	 * If OCFS2_FLAG_NO_REV_CHECK is specified, fsck (or someone
	 * like it) is asking to ignore the OCFS vol_header at
	 * block 0.
	 */
	if (!(flags & OCFS2_FLAG_NO_REV_CHECK)) {
		ret = ocfs2_validate_ocfs1_header(fs);
		if (ret)
			goto out;
	}

	if (superblock) {
		ret = OCFS2_ET_INVALID_ARGUMENT;
		if (!block_size)
			goto out;
		io_set_blksize(fs->fs_io, block_size);
		ret = ocfs2_read_super(fs, (uint64_t)superblock, NULL);
	} else {
		superblock = OCFS2_SUPER_BLOCK_BLKNO;
		if (block_size) {
			io_set_blksize(fs->fs_io, block_size);
			ret = ocfs2_read_super(fs, (uint64_t)superblock, NULL);
		} else {
			for (block_size = io_get_blksize(fs->fs_io);
			     block_size <= OCFS2_MAX_BLOCKSIZE;
			     block_size <<= 1) {
				io_set_blksize(fs->fs_io, block_size);
				ret = ocfs2_read_super(fs, (uint64_t)superblock,
						       NULL);
				if ((ret == OCFS2_ET_BAD_MAGIC) ||
				    (ret == OCFS2_ET_IO))
					continue;
				break;
			}
		}
	}
	if (ret)
		goto out;

	fs->fs_blocksize = block_size;
	if (superblock == OCFS2_SUPER_BLOCK_BLKNO) {
		ret = ocfs2_malloc_block(fs->fs_io, &fs->fs_orig_super);
		if (ret)
			goto out;
		memcpy((char *)fs->fs_orig_super,
		       (char *)fs->fs_super, fs->fs_blocksize);
	}

#if 0
	ret = OCFS2_ET_REV_TOO_HIGH;
	if (fs->fs_super->id2.i_super.s_major_rev_level >
	    OCFS2_LIB_CURRENT_REV)
		goto out;
#endif

	if (flags & OCFS2_FLAG_STRICT_COMPAT_CHECK) {
		ret = OCFS2_ET_UNSUPP_FEATURE;
		if (OCFS2_RAW_SB(fs->fs_super)->s_feature_compat &
		    ~OCFS2_LIB_FEATURE_COMPAT_SUPP)
			    goto out;

		/* We need to check s_tunefs_flag also to make sure
		 * fsck.ocfs2 won't try to clean up an aborted tunefs
		 * that it doesn't know.
		 */
		if (OCFS2_HAS_INCOMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super),
					OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG) &&
		    (OCFS2_RAW_SB(fs->fs_super)->s_tunefs_flag &
		     ~OCFS2_LIB_ABORTED_TUNEFS_SUPP))
			goto out;
	}

	ret = OCFS2_ET_UNSUPP_FEATURE;
	if (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat &
	    ~OCFS2_LIB_FEATURE_INCOMPAT_SUPP)
		goto out;

	ret = OCFS2_ET_RO_UNSUPP_FEATURE;
	if ((flags & OCFS2_FLAG_RW) &&
	    (OCFS2_RAW_SB(fs->fs_super)->s_feature_ro_compat &
	     ~OCFS2_LIB_FEATURE_RO_COMPAT_SUPP))
		goto out;

	ret = OCFS2_ET_UNSUPP_FEATURE;
	if (!(flags & OCFS2_FLAG_HEARTBEAT_DEV_OK) &&
	    (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat &
	     OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV))
		goto out;

	ret = OCFS2_ET_CORRUPT_SUPERBLOCK;
	if (!OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits)
		goto out;
	if (fs->fs_super->i_blkno != superblock)
		goto out;
	if ((OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits < 12) ||
	    (OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits > 20))
		goto out;
	if (!OCFS2_RAW_SB(fs->fs_super)->s_root_blkno ||
	    !OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno)
		goto out;
	if (OCFS2_RAW_SB(fs->fs_super)->s_max_slots > OCFS2_MAX_SLOTS)
		goto out;

	ret = ocfs2_malloc0(OCFS2_RAW_SB(fs->fs_super)->s_max_slots *
			    sizeof(ocfs2_cached_inode *), 
			    &fs->fs_inode_allocs);
	if (ret)
		goto out;

	ret = ocfs2_malloc0(OCFS2_RAW_SB(fs->fs_super)->s_max_slots *
			    sizeof(ocfs2_cached_inode *), 
			    &fs->fs_eb_allocs);
	if (ret)
		goto out;

	ret = OCFS2_ET_UNEXPECTED_BLOCK_SIZE;
	if (block_size !=
	    (1U << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits))
		goto out;

	fs->fs_clustersize =
		1 << OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;

	/* FIXME: Read the system dir */
	
	fs->fs_root_blkno =
		OCFS2_RAW_SB(fs->fs_super)->s_root_blkno;
	fs->fs_sysdir_blkno =
		OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno;

	fs->fs_clusters = fs->fs_super->i_clusters;
	fs->fs_blocks = ocfs2_clusters_to_blocks(fs, fs->fs_clusters);
	fs->fs_first_cg_blkno = 
		OCFS2_RAW_SB(fs->fs_super)->s_first_cluster_group;

	raw_uuid = OCFS2_RAW_SB(fs->fs_super)->s_uuid;
	for (i = 0, ptr = fs->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) {
		/* print with null */
		len = snprintf(ptr, 3, "%02X", raw_uuid[i]);
		if (len != 2) {
			ret = OCFS2_ET_INTERNAL_FAILURE;
			goto out;
		}
		/* then only advace past the last char */
		ptr += 2;
	}

	*ret_fs = fs;
	return 0;

out:
	if (fs->fs_inode_allocs)
		ocfs2_free(&fs->fs_inode_allocs);

	ocfs2_freefs(fs);

	return ret;
}
Esempio n. 18
0
errcode_t ocfs2_extent_iterate_xattr(ocfs2_filesys *fs,
				     struct ocfs2_extent_list *el,
				     uint64_t last_eb_blk,
				     int flags,
				     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 *changed)
{
	int i;
	int iret = 0;
	errcode_t ret;
	struct extent_context ctxt;

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

		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;

	if (last_eb_blk != ctxt.last_eb_blkno) {
		last_eb_blk = ctxt.last_eb_blkno;
		iret |= OCFS2_EXTENT_CHANGED;
	}

out_abort:
	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
		*changed = 1;
out_eb_bufs:
	if (ctxt.eb_bufs) {
		if (ctxt.eb_bufs[0])
			ocfs2_free(&ctxt.eb_bufs[0]);
		ocfs2_free(&ctxt.eb_bufs);
	}
out:
	return ret;
}