int btrfs_main(int argc, char **argv)
{
	const struct cmd_struct *cmd;
	const char *bname;

	if ((bname = strrchr(argv[0], '/')) != NULL)
		bname++;
	else
		bname = argv[0];

	if (!strcmp(bname, "btrfsck")) {
		argv[0] = "check";
	} else {
		argc--;
		argv++;
		handle_options(&argc, &argv);
		if (argc > 0) {
			if (!prefixcmp(argv[0], "--"))
				argv[0] += 2;
		} else {
			usage_command_group(&btrfs_cmd_group, 0, 0);
			exit(1);
		}
	}

	cmd = parse_command_token(argv[0], &btrfs_cmd_group);

	handle_help_options_next_level(cmd, argc, argv);

	crc32c_optimization_init();

	fixup_argv0(argv, cmd->token);
	exit(cmd->fn(argc, argv));
}
Exemple #2
0
/**
 * Intialise and write the data blocks for a new journal as a contiguous
 * extent. The indirect blocks pointing to these data blocks should have been
 * written separately using lgfs2_write_filemeta() and the extent should have
 * been allocated using lgfs2_file_alloc().
 * ip: The journal's inode
 * Returns 0 on success or -1 with errno set on error.
 */
int lgfs2_write_journal_data(struct gfs2_inode *ip)
{
	struct gfs2_log_header lh = {
		.lh_header.mh_magic = GFS2_MAGIC,
		.lh_header.mh_type = GFS2_METATYPE_LH,
		.lh_header.mh_format = GFS2_FORMAT_LH,
		.lh_tail = 0,
		.lh_blkno = 0,
		.lh_hash = 0,
#ifdef GFS2_HAS_LH_V2
		.lh_flags = GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_USERSPACE,
		.lh_crc = 0,
		.lh_nsec = 0,
		.lh_sec = 0,
		.lh_jinode = ip->i_di.di_num.no_addr,
		.lh_statfs_addr = 0,
		.lh_quota_addr = 0,
		.lh_local_total = 0,
		.lh_local_free = 0,
		.lh_local_dinodes = 0,
#else
		.lh_flags = GFS2_LOG_HEAD_UNMOUNT,
#endif
	};
	struct gfs2_buffer_head *bh;
	struct gfs2_sbd *sdp = ip->i_sbd;
	unsigned blocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize;
	uint64_t jext0 = ip->i_di.di_num.no_addr + ip->i_di.di_blocks - blocks;
	uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0)));

	bh = bget(sdp, jext0);
	if (bh == NULL)
		return -1;

	crc32c_optimization_init();
	do {
		struct gfs2_log_header *buflh = (struct gfs2_log_header *)bh->b_data;

		lh.lh_sequence = seq;
		lh.lh_blkno = bh->b_blocknr - jext0;
		gfs2_log_header_out(&lh, bh->b_data);

		buflh->lh_hash = cpu_to_be32(lgfs2_log_header_hash(bh->b_data));
#ifdef GFS2_HAS_LH_V2
		buflh->lh_addr = cpu_to_be64(bh->b_blocknr);
		buflh->lh_crc = cpu_to_be32(lgfs2_log_header_crc(bh->b_data, sdp->bsize));
#endif

		if (bwrite(bh)) {
			free(bh);
			return -1;
		}

		if (++seq == blocks)
			seq = 0;

	} while (++bh->b_blocknr < jext0 + blocks);

	free(bh);
	return 0;
}

int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks)
{
	struct gfs2_log_header lh;
	unsigned int x;
	uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0)));
	uint32_t hash;
	unsigned int height;

	/* Build the height up so our journal blocks will be contiguous and */
	/* not broken up by indirect block pages.                           */
	height = calc_tree_height(jnl, (blocks + 1) * bsize);
	build_height(jnl, height);

	memset(&lh, 0, sizeof(struct gfs2_log_header));
	lh.lh_header.mh_magic = GFS2_MAGIC;
	lh.lh_header.mh_type = GFS2_METATYPE_LH;
	lh.lh_header.mh_format = GFS2_FORMAT_LH;
	lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
#ifdef GFS2_HAS_LH_V2
	lh.lh_flags |= GFS2_LOG_HEAD_USERSPACE;
	lh.lh_jinode = jnl->i_di.di_num.no_addr;
#endif
	for (x = 0; x < blocks; x++) {
		struct gfs2_buffer_head *bh = get_file_buf(jnl, x, TRUE);
		if (!bh)
			return -1;
		bmodified(bh);
		brelse(bh);
	}
	crc32c_optimization_init();
	for (x = 0; x < blocks; x++) {
		struct gfs2_buffer_head *bh = get_file_buf(jnl, x, FALSE);
		if (!bh)
			return -1;

		memset(bh->b_data, 0, bsize);
		lh.lh_sequence = seq;
		lh.lh_blkno = x;
		gfs2_log_header_out(&lh, bh->b_data);
		hash = lgfs2_log_header_hash(bh->b_data);
		((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash);
#ifdef GFS2_HAS_LH_V2
		((struct gfs2_log_header *)bh->b_data)->lh_addr = cpu_to_be64(bh->b_blocknr);
		hash = lgfs2_log_header_crc(bh->b_data, bsize);
		((struct gfs2_log_header *)bh->b_data)->lh_crc = cpu_to_be32(hash);
#endif
		bmodified(bh);
		brelse(bh);

		if (++seq == blocks)
			seq = 0;
	}

	return 0;
}

int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex)
{
	char name[256];
	int ret;

	sprintf(name, "journal%u", j);
	sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600,
				     GFS2_DIF_SYSTEM);
	if (sdp->md.journal[j] == NULL) {
		return errno;
	}
	ret = write_journal(sdp->md.journal[j], sdp->bsize,
			    sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift);
	return ret;
}