示例#1
0
static int cmd_device_usage(int argc, char **argv)
{
	unsigned unit_mode;
	int ret = 0;
	int i;

	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);

	clean_args_no_options(argc, argv, cmd_device_usage_usage);

	if (check_argc_min(argc - optind, 1))
		usage(cmd_device_usage_usage);

	for (i = optind; i < argc; i++) {
		int fd;
		DIR *dirstream = NULL;

		if (i > 1)
			printf("\n");

		fd = btrfs_open_dir(argv[i], &dirstream, 1);
		if (fd < 0) {
			ret = 1;
			break;
		}

		ret = _cmd_device_usage(fd, argv[i], unit_mode);
		close_file_or_dir(fd, dirstream);

		if (ret)
			break;
	}

	return !!ret;
}
示例#2
0
int main(int argc, char **argv)
{
	char *path;
	int fd;
	int ret;
	u64 flags = 0;
	char *dir = "html";
	DIR *dirstream = NULL;

	while (1) {
		int c = getopt(argc, argv, "cmso:h");
		if (c < 0)
			break;
		switch (c) {
		case 'c':
			use_color = 1;
			break;
		case 'd':
			flags |= BTRFS_BLOCK_GROUP_DATA;
			break;
		case 'm':
			flags |= BTRFS_BLOCK_GROUP_METADATA;
			break;
		case 's':
			flags |= BTRFS_BLOCK_GROUP_SYSTEM;
			break;
		case 'o':
			dir = optarg;
			break;
		case 'h':
		default:
			fragments_usage();
		}
	}

	set_argv0(argv);
	if (check_argc_min(argc - optind, 1))
		fragments_usage();

	path = argv[optind++];

	fd = btrfs_open_dir(path, &dirstream, 1);
	if (fd < 0)
		exit(1);

	if (flags == 0)
		flags = BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA;

	ret = list_fragments(fd, flags, dir);
	close_file_or_dir(fd, dirstream);
	if (ret)
		exit(1);

	exit(0);
}
示例#3
0
int main(int argc, char **argv)
{
	int c;
	unsigned long checksum = 0;
	char *str;
	char *buf;
	int length = 10;
	int seed = getpid() ^ getppid();
	int loop = 0;
	int i;

	while ((c = getopt(argc, argv, "l:c:s:h")) != -1) {
		switch (c) {
		case 'l':
			length = atol(optarg);
			break;
		case 'c':
			sscanf(optarg, "%li", &checksum);
			loop = 1;
			break;
		case 's':
			seed = atol(optarg);
			break;
		case 'h':
			usage();
		case '?':
			return 255;
		}
	}

	set_argv0(argv);
	str = argv[optind];

	if (!loop) {
		if (check_argc_min(argc - optind, 1))
			return 255;

		printf("%12u - %s\n", crc32c(~1, str, strlen(str)), str);
		return 0;
	}

	buf = malloc(length);
	if (!buf)
		return -ENOMEM;
	srand(seed);

	while (1) {
		for (i = 0; i < length; i++)
			buf[i] = rand() % 94 + 33;
		if (crc32c(~1, buf, length) == checksum)
			printf("%12lu - %.*s\n", checksum, length, buf);
	}

	return 0;
}
示例#4
0
int main(int argc, char **argv)
{
	struct btrfs_root *root;
	int dev_fd;
	int opt;
	int ret;

	while ((opt = getopt(argc, argv, "l:o:g:")) != -1) {
		switch(opt) {
			case 'o':
				search_objectid = arg_strtou64(optarg);
				break;
			case 'g':
				search_generation = arg_strtou64(optarg);
				break;
			case 'l':
				search_level = arg_strtou64(optarg);
				break;
			default:
				usage();
				exit(1);
		}
	}

	set_argv0(argv);
	argc = argc - optind;
	if (check_argc_min(argc, 1)) {
		usage();
		exit(1);
	}

	dev_fd = open(argv[optind], O_RDONLY);
	if (dev_fd < 0) {
		fprintf(stderr, "Failed to open device %s\n", argv[optind]);
		exit(1);
	}

	root = open_ctree_broken(dev_fd, argv[optind]);
	close(dev_fd);

	if (!root) {
		fprintf(stderr, "Open ctree failed\n");
		exit(1);
	}

	if (search_generation == 0)
		search_generation = btrfs_super_generation(root->fs_info->super_copy);

	csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	ret = find_root(root);
	close_ctree(root);
	return ret;
}
示例#5
0
static int cmd_rm_dev(int argc, char **argv)
{
	char	*mntpnt;
	int	i, fdmnt, ret=0, e;
	DIR	*dirstream = NULL;

	if (check_argc_min(argc, 3))
		usage(cmd_rm_dev_usage);

	mntpnt = argv[argc - 1];

	fdmnt = open_file_or_dir(mntpnt, &dirstream);
	if (fdmnt < 0) {
		fprintf(stderr, "ERROR: can't access '%s'\n", mntpnt);
		return 1;
	}

	for(i=1 ; i < argc - 1; i++ ){
		struct	btrfs_ioctl_vol_args arg;
		int	res;

		if (!is_block_device(argv[i])) {
			fprintf(stderr,
				"ERROR: %s is not a block device\n", argv[i]);
			ret++;
			continue;
		}
		memset(&arg, 0, sizeof(arg));
		strncpy_null(arg.name, argv[i]);
		res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
		e = errno;
		if (res) {
			const char *msg;

			if (res > 0)
				msg = btrfs_err_str(res);
			else
				msg = strerror(e);
			fprintf(stderr,
				"ERROR: error removing the device '%s' - %s\n",
				argv[i], msg);
			ret++;
		}
	}

	close_file_or_dir(fdmnt, dirstream);
	return !!ret;
}
示例#6
0
static int cmd_ready_dev(int argc, char **argv)
{
	struct	btrfs_ioctl_vol_args args;
	int	fd;
	int	ret;
	char	*path;

	if (check_argc_min(argc, 2))
		usage(cmd_ready_dev_usage);

	fd = open("/dev/btrfs-control", O_RDWR);
	if (fd < 0) {
		perror("failed to open /dev/btrfs-control");
		return 1;
	}

	path = canonicalize_path(argv[argc - 1]);
	if (!path) {
		fprintf(stderr,
			"ERROR: Could not canonicalize pathname '%s': %s\n",
			argv[argc - 1], strerror(errno));
		ret = 1;
		goto out;
	}

	if (!is_block_device(path)) {
		fprintf(stderr,
			"ERROR: %s is not a block device\n", path);
		ret = 1;
		goto out;
	}

	memset(&args, 0, sizeof(args));
	strncpy_null(args.name, path);
	ret = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args);
	if (ret < 0) {
		fprintf(stderr, "ERROR: unable to determine if the device '%s'"
			" is ready for mounting - %s\n", path,
			strerror(errno));
		ret = 1;
	}

out:
	free(path);
	close(fd);
	return ret;
}
示例#7
0
static int cmd_list(int argc, char **argv)
{
	int ret;
	char *object = NULL;
	int types = 0;

	if (check_argc_min(argc, 2) || check_argc_max(argc, 3))
		usage(cmd_list_usage);

	parse_args(argc, argv, cmd_list_usage, &types, &object, NULL, NULL);
	if (!object) {
		fprintf(stderr, "ERROR: invalid arguments.\n");
		usage(cmd_set_usage);
	}

	ret = dump_props(types, object, 1);

	return ret;
}
示例#8
0
static int cmd_set(int argc, char **argv)
{
	int ret;
	char *object;
	char *name;
	char *value;
	int types = 0;

	if (check_argc_min(argc, 4) || check_argc_max(argc, 5))
		usage(cmd_set_usage);

	parse_args(argc, argv, cmd_set_usage, &types, &object, &name, &value);
	if (!object || !name || !value) {
		fprintf(stderr, "ERROR: invalid arguments.\n");
		usage(cmd_set_usage);
	}

	ret = setget_prop(types, object, name, value);

	return ret;
}
示例#9
0
static int cmd_get(int argc, char **argv)
{
	int ret;
	char *object;
	char *name = NULL;
	int types = 0;

	if (check_argc_min(argc, 2) || check_argc_max(argc, 4))
		usage(cmd_get_usage);

	parse_args(argc, argv, cmd_get_usage, &types, &object, &name, NULL);
	if (!object) {
		fprintf(stderr, "ERROR: invalid arguments.\n");
		usage(cmd_set_usage);
	}

	if (name)
		ret = setget_prop(types, object, name, NULL);
	else
		ret = dump_props(types, object, 0);

	return ret;
}
static int cmd_rm_dev(int argc, char **argv)
{
	char	*mntpnt;
	int	i, fdmnt, ret=0, e;

	if (check_argc_min(argc, 3))
		usage(cmd_rm_dev_usage);

	mntpnt = argv[argc - 1];

	fdmnt = open_file_or_dir(mntpnt);
	if (fdmnt < 0) {
		fprintf(stderr, "ERROR: can't access to '%s'\n", mntpnt);
		return 12;
	}

	for(i=1 ; i < argc - 1; i++ ){
		struct	btrfs_ioctl_vol_args arg;
		int	res;

		strncpy(arg.name, argv[i], BTRFS_PATH_NAME_MAX);
		arg.name[BTRFS_PATH_NAME_MAX-1] = 0;
		res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
		e = errno;
		if(res<0){
			fprintf(stderr, "ERROR: error removing the device '%s' - %s\n",
				argv[i], strerror(e));
			ret++;
		}
	}

	close(fdmnt);
	if( ret)
		return ret+20;
	else
		return 0;
}
static int cmd_add_dev(int argc, char **argv)
{
	char	*mntpnt;
	int	i, fdmnt, ret=0, e;

	if (check_argc_min(argc, 3))
		usage(cmd_add_dev_usage);

	mntpnt = argv[argc - 1];

	fdmnt = open_file_or_dir(mntpnt);
	if (fdmnt < 0) {
		fprintf(stderr, "ERROR: can't access to '%s'\n", mntpnt);
		return 12;
	}

	for (i = 1; i < argc - 1; i++ ){
		struct btrfs_ioctl_vol_args ioctl_args;
		int	devfd, res;
		u64 dev_block_count = 0;
		struct stat st;
		int mixed = 0;

		res = check_mounted(argv[i]);
		if (res < 0) {
			fprintf(stderr, "error checking %s mount status\n",
				argv[i]);
			ret++;
			continue;
		}
		if (res == 1) {
			fprintf(stderr, "%s is mounted\n", argv[i]);
			ret++;
			continue;
		}

		devfd = open(argv[i], O_RDWR);
		if (!devfd) {
			fprintf(stderr, "ERROR: Unable to open device '%s'\n", argv[i]);
			close(devfd);
			ret++;
			continue;
		}
		res = fstat(devfd, &st);
		if (res) {
			fprintf(stderr, "ERROR: Unable to stat '%s'\n", argv[i]);
			close(devfd);
			ret++;
			continue;
		}
		if (!S_ISBLK(st.st_mode)) {
			fprintf(stderr, "ERROR: '%s' is not a block device\n", argv[i]);
			close(devfd);
			ret++;
			continue;
		}

		res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count,
					   0, &mixed, 0);
		if (res) {
			fprintf(stderr, "ERROR: Unable to init '%s'\n", argv[i]);
			close(devfd);
			ret++;
			continue;
		}
		close(devfd);

		strncpy(ioctl_args.name, argv[i], BTRFS_PATH_NAME_MAX);
		ioctl_args.name[BTRFS_PATH_NAME_MAX-1] = 0;
		res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
		e = errno;
		if(res<0){
			fprintf(stderr, "ERROR: error adding the device '%s' - %s\n",
				argv[i], strerror(e));
			ret++;
		}

	}

	close(fdmnt);
	if (ret)
		return ret+20;
	else
		return 0;
}
示例#12
0
int cmd_filesystem_usage(int argc, char **argv)
{
	int ret = 0;
	unsigned unit_mode;
	int i;
	int more_than_one = 0;
	int tabular = 0;

	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);

	optind = 1;
	while (1) {
		int c;

		c = getopt(argc, argv, "T");
		if (c < 0)
			break;

		switch (c) {
		case 'T':
			tabular = 1;
			break;
		default:
			usage(cmd_filesystem_usage_usage);
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_filesystem_usage_usage);

	for (i = optind; i < argc; i++) {
		int fd;
		DIR *dirstream = NULL;
		struct chunk_info *chunkinfo = NULL;
		struct device_info *devinfo = NULL;
		int chunkcount = 0;
		int devcount = 0;

		fd = open_file_or_dir(argv[i], &dirstream);
		if (fd < 0) {
			fprintf(stderr, "ERROR: can't access '%s'\n",
				argv[i]);
			ret = 1;
			goto out;
		}
		if (more_than_one)
			printf("\n");

		ret = load_chunk_and_device_info(fd, &chunkinfo, &chunkcount,
				&devinfo, &devcount);
		if (ret)
			goto cleanup;

		ret = print_filesystem_usage_overall(fd, chunkinfo, chunkcount,
				devinfo, devcount, argv[i], unit_mode);
		if (ret)
			goto cleanup;
		printf("\n");
		ret = print_filesystem_usage_by_chunk(fd, chunkinfo, chunkcount,
				devinfo, devcount, argv[i], unit_mode, tabular);
cleanup:
		close_file_or_dir(fd, dirstream);
		free(chunkinfo);
		free(devinfo);

		if (ret)
			goto out;
		more_than_one = 1;
	}

out:
	return !!ret;
}
static void parse_args(int argc, char **argv,
		       const char * const *usage_str,
		       int *types, char **object,
		       char **name, char **value, int min_nonopt_args)
{
	int ret;
	char *type_str = NULL;
	int max_nonopt_args = 1;

	optind = 1;
	while (1) {
		int c = getopt(argc, argv, "t:");
		if (c < 0)
			break;

		switch (c) {
		case 't':
			type_str = optarg;
			break;
		default:
			usage(usage_str);
		}
	}

	if (name)
		max_nonopt_args++;
	if (value)
		max_nonopt_args++;

	if (check_argc_min(argc - optind, min_nonopt_args) ||
	    check_argc_max(argc - optind, max_nonopt_args))
		usage(usage_str);

	*types = 0;
	if (type_str) {
		if (!strcmp(type_str, "s") || !strcmp(type_str, "subvol")) {
			*types = prop_object_subvol;
		} else if (!strcmp(type_str, "f") ||
			   !strcmp(type_str, "filesystem")) {
			*types = prop_object_root;
		} else if (!strcmp(type_str, "i") ||
			   !strcmp(type_str, "inode")) {
			*types = prop_object_inode;
		} else if (!strcmp(type_str, "d") ||
			   !strcmp(type_str, "device")) {
			*types = prop_object_dev;
		} else {
			error("invalid object type: %s", type_str);
			usage(usage_str);
		}
	}

	*object = argv[optind++];
	if (optind < argc)
		*name = argv[optind++];
	if (optind < argc)
		*value = argv[optind++];

	if (!*types) {
		ret = autodetect_object_types(*object, types);
		if (ret < 0) {
			error("failed to detect object type: %s",
				strerror(-ret));
			usage(usage_str);
		}
		if (!*types) {
			error("object is not a btrfs object: %s", *object);
			usage(usage_str);
		}
	}
}
示例#14
0
static int cmd_subvol_sync(int argc, char **argv)
{
	int fd = -1;
	int i;
	int ret = 1;
	DIR *dirstream = NULL;
	u64 *ids = NULL;
	int id_count;
	int sleep_interval = 1;

	optind = 1;
	while (1) {
		int c = getopt(argc, argv, "s:");

		if (c < 0)
			break;

		switch (c) {
		case 's':
			sleep_interval = atoi(argv[optind]);
			if (sleep_interval < 1) {
				fprintf(stderr,
					"ERROR: invalid sleep interval %s\n",
					argv[optind]);
				ret = 1;
				goto out;
			}
			break;
		default:
			usage(cmd_subvol_sync_usage);
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_subvol_sync_usage);

	fd = open_file_or_dir(argv[optind], &dirstream);
	if (fd < 0) {
		fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind]);
		ret = 1;
		goto out;
	}
	optind++;

	id_count = argc - optind;
	if (!id_count) {
		id_count = SUBVOL_ID_BATCH;
		ids = (u64*)malloc(id_count * sizeof(u64));
		if (!ids) {
			fprintf(stderr, "ERROR: not enough memory\n");
			ret = 1;
			goto out;
		}
		id_count = enumerate_dead_subvols(fd, id_count, &ids);
		if (id_count < 0) {
			fprintf(stderr, "ERROR: can't enumerate dead subvolumes: %s\n",
					strerror(-id_count));
			ret = 1;
			goto out;
		}
		if (id_count == 0) {
			ret = 0;
			goto out;
		}
	} else {
		ids = (u64*)malloc(id_count * sizeof(u64));
		if (!ids) {
			fprintf(stderr, "ERROR: not enough memory\n");
			ret = 1;
			goto out;
		}

		for (i = 0; i < id_count; i++) {
			u64 id;
			const char *arg;

			arg = argv[optind + i];
			errno = 0;
			id = strtoull(arg, NULL, 10);
			if (errno < 0) {
				fprintf(stderr,
					"ERROR: unrecognized subvolume id %s\n",
					arg);
				ret = 1;
				goto out;
			}
			if (id < BTRFS_FIRST_FREE_OBJECTID
					|| id > BTRFS_LAST_FREE_OBJECTID) {
				fprintf(stderr,
					"ERROR: subvolume id %s out of range\n",
					arg);
				ret = 1;
				goto out;
			}
			ids[i] = id;
		}
	}

	ret = wait_for_subvolume_cleaning(fd, id_count, ids, sleep_interval);

out:
	free(ids);
	close_file_or_dir(fd, dirstream);

	return !!ret;
}
static int cmd_qgroup_limit(int argc, char **argv)
{
	int ret = 0;
	int fd;
	int e;
	char *path = NULL;
	struct btrfs_ioctl_qgroup_limit_args args;
	unsigned long long size;
	int compressed = 0;
	int exclusive = 0;
	DIR *dirstream = NULL;

	optind = 1;
	while (1) {
		int c = getopt(argc, argv, "ce");
		if (c < 0)
			break;
		switch (c) {
		case 'c':
			compressed = 1;
			break;
		case 'e':
			exclusive = 1;
			break;
		default:
			usage(cmd_qgroup_limit_usage);
		}
	}

	if (check_argc_min(argc - optind, 2))
		usage(cmd_qgroup_limit_usage);

	if (!parse_limit(argv[optind], &size)) {
		error("invalid size argument: %s", argv[optind]);
		return 1;
	}

	memset(&args, 0, sizeof(args));
	if (compressed)
		args.lim.flags |= BTRFS_QGROUP_LIMIT_RFER_CMPR |
				  BTRFS_QGROUP_LIMIT_EXCL_CMPR;
	if (exclusive) {
		args.lim.flags |= BTRFS_QGROUP_LIMIT_MAX_EXCL;
		args.lim.max_exclusive = size;
	} else {
		args.lim.flags |= BTRFS_QGROUP_LIMIT_MAX_RFER;
		args.lim.max_referenced = size;
	}

	if (argc - optind == 2) {
		args.qgroupid = 0;
		path = argv[optind + 1];
		ret = test_issubvolume(path);
		if (ret < 0) {
			error("cannot access '%s': %s", path, strerror(-ret));
			return 1;
		}
		if (!ret) {
			error("'%s' is not a subvolume", path);
			return 1;
		}
		/*
		 * keep qgroupid at 0, this indicates that the subvolume the
		 * fd refers to is to be limited
		 */
	} else if (argc - optind == 3) {
		args.qgroupid = parse_qgroupid(argv[optind + 1]);
		path = argv[optind + 2];
	} else
		usage(cmd_qgroup_limit_usage);

	fd = btrfs_open_dir(path, &dirstream, 1);
	if (fd < 0)
		return 1;

	ret = ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args);
	e = errno;
	close_file_or_dir(fd, dirstream);
	if (ret < 0) {
		error("unable to limit requested quota group: %s", strerror(e));
		return 1;
	}
	return 0;
}
示例#16
0
static int cmd_add_dev(int argc, char **argv)
{
	char	*mntpnt;
	int	i, fdmnt, ret=0, e;
	DIR	*dirstream = NULL;
	int discard = 1;
	int force = 0;

	while (1) {
		int c;
		static const struct option long_options[] = {
			{ "nodiscard", optional_argument, NULL, 'K'},
			{ "force", no_argument, NULL, 'f'},
			{ NULL, 0, NULL, 0}
		};

		c = getopt_long(argc, argv, "Kf", long_options, NULL);
		if (c < 0)
			break;
		switch (c) {
		case 'K':
			discard = 0;
			break;
		case 'f':
			force = 1;
			break;
		default:
			usage(cmd_add_dev_usage);
		}
	}

	argc = argc - optind;

	if (check_argc_min(argc, 2))
		usage(cmd_add_dev_usage);

	mntpnt = argv[optind + argc - 1];

	fdmnt = open_file_or_dir(mntpnt, &dirstream);
	if (fdmnt < 0) {
		fprintf(stderr, "ERROR: can't access '%s'\n", mntpnt);
		return 1;
	}

	for (i = optind; i < optind + argc - 1; i++){
		struct btrfs_ioctl_vol_args ioctl_args;
		int	devfd, res;
		u64 dev_block_count = 0;
		int mixed = 0;
		char *path;

		res = test_dev_for_mkfs(argv[i], force);
		if (res) {
			ret++;
			continue;
		}

		devfd = open(argv[i], O_RDWR);
		if (devfd < 0) {
			fprintf(stderr, "ERROR: Unable to open device '%s'\n", argv[i]);
			ret++;
			continue;
		}

		res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count,
					   0, &mixed, discard);
		close(devfd);
		if (res) {
			ret++;
			goto error_out;
		}

		path = canonicalize_path(argv[i]);
		if (!path) {
			fprintf(stderr,
				"ERROR: Could not canonicalize pathname '%s': %s\n",
				argv[i], strerror(errno));
			ret++;
			goto error_out;
		}

		memset(&ioctl_args, 0, sizeof(ioctl_args));
		strncpy_null(ioctl_args.name, path);
		res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
		e = errno;
		if (res < 0) {
			fprintf(stderr, "ERROR: error adding the device '%s' - %s\n",
				path, strerror(e));
			ret++;
		}
		free(path);
	}

error_out:
	close_file_or_dir(fdmnt, dirstream);
	return !!ret;
}
示例#17
0
int cmd_send(int argc, char **argv)
{
	char *subvol = NULL;
	int ret;
	char outname[PATH_MAX];
	struct btrfs_send send;
	u32 i;
	char *mount_root = NULL;
	char *snapshot_parent = NULL;
	u64 root_id = 0;
	u64 parent_root_id = 0;
	int full_send = 1;
	int new_end_cmd_semantic = 0;
	u64 send_flags = 0;

	memset(&send, 0, sizeof(send));
	send.dump_fd = fileno(stdout);
	outname[0] = 0;

	while (1) {
		enum { GETOPT_VAL_SEND_NO_DATA = 256 };
		static const struct option long_options[] = {
			{ "verbose", no_argument, NULL, 'v' },
			{ "quiet", no_argument, NULL, 'q' },
			{ "no-data", no_argument, NULL, GETOPT_VAL_SEND_NO_DATA }
		};
		int c = getopt_long(argc, argv, "vqec:f:i:p:", long_options, NULL);

		if (c < 0)
			break;

		switch (c) {
		case 'v':
			g_verbose++;
			break;
		case 'q':
			g_verbose = 0;
			break;
		case 'e':
			new_end_cmd_semantic = 1;
			break;
		case 'c':
			subvol = realpath(optarg, NULL);
			if (!subvol) {
				ret = -errno;
				error("realpath %s failed: %s\n", optarg, strerror(-ret));
				goto out;
			}

			ret = set_root_info(&send, subvol, &root_id);
			if (ret < 0)
				goto out;

			ret = is_subvol_ro(&send, subvol);
			if (ret < 0)
				goto out;
			if (!ret) {
				ret = -EINVAL;
				error("cloned subvolume %s is not read-only", subvol);
				goto out;
			}

			ret = add_clone_source(&send, root_id);
			if (ret < 0) {
				error("cannot add clone source: %s", strerror(-ret));
				goto out;
			}
			free(subvol);
			subvol = NULL;
			free_send_info(&send);
			full_send = 0;
			break;
		case 'f':
			if (arg_copy_path(outname, optarg, sizeof(outname))) {
				error("output file path too long (%zu)", strlen(optarg));
				ret = 1;
				goto out;
			}
			break;
		case 'p':
			if (snapshot_parent) {
				error("you cannot have more than one parent (-p)");
				ret = 1;
				goto out;
			}
			snapshot_parent = realpath(optarg, NULL);
			if (!snapshot_parent) {
				ret = -errno;
				error("realpath %s failed: %s", optarg, strerror(-ret));
				goto out;
			}

			ret = is_subvol_ro(&send, snapshot_parent);
			if (ret < 0)
				goto out;
			if (!ret) {
				ret = -EINVAL;
				error("parent subvolume %s is not read-only",
					snapshot_parent);
				goto out;
			}

			full_send = 0;
			break;
		case 'i':
			error("option -i was removed, use -c instead");
			ret = 1;
			goto out;
		case GETOPT_VAL_SEND_NO_DATA:
			send_flags |= BTRFS_SEND_FLAG_NO_FILE_DATA;
			break;
		case '?':
		default:
			error("send arguments invalid");
			ret = 1;
			goto out;
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_send_usage);

	if (outname[0]) {
		int tmpfd;

		/*
		 * Try to use an existing file first. Even if send runs as
		 * root, it might not have permissions to create file (eg. on a
		 * NFS) but it should still be able to use a pre-created file.
		 */
		tmpfd = open(outname, O_WRONLY | O_TRUNC);
		if (tmpfd < 0) {
			if (errno == ENOENT)
				tmpfd = open(outname,
					O_CREAT | O_WRONLY | O_TRUNC, 0600);
		}
		send.dump_fd = tmpfd;
		if (send.dump_fd == -1) {
			ret = -errno;
			error("cannot create '%s': %s", outname, strerror(-ret));
			goto out;
		}
	}

	if (isatty(send.dump_fd)) {
		error(
	    "not dumping send stream into a terminal, redirect it into a file");
		ret = 1;
		goto out;
	}

	/* use first send subvol to determine mount_root */
	subvol = realpath(argv[optind], NULL);
	if (!subvol) {
		ret = -errno;
		error("unable to resolve %s", argv[optind]);
		goto out;
	}

	ret = init_root_path(&send, subvol);
	if (ret < 0)
		goto out;

	if (snapshot_parent != NULL) {
		ret = get_root_id(&send,
			subvol_strip_mountpoint(send.root_path, snapshot_parent),
			&parent_root_id);
		if (ret < 0) {
			error("could not resolve rootid for %s", snapshot_parent);
			goto out;
		}

		ret = add_clone_source(&send, parent_root_id);
		if (ret < 0) {
			error("cannot add clone source: %s", strerror(-ret));
			goto out;
		}
	}

	for (i = optind; i < argc; i++) {
		free(subvol);
		subvol = realpath(argv[i], NULL);
		if (!subvol) {
			ret = -errno;
			error("unable to resolve %s", argv[i]);
			goto out;
		}

		ret = find_mount_root(subvol, &mount_root);
		if (ret < 0) {
			error("find_mount_root failed on %s: %s", subvol,
				strerror(-ret));
			goto out;
		}
		if (ret > 0) {
			error("%s does not belong to btrfs mount point",
				subvol);
			ret = -EINVAL;
			goto out;
		}
		if (strcmp(send.root_path, mount_root) != 0) {
			ret = -EINVAL;
			error("all subvolumes must be from the same filesystem");
			goto out;
		}
		free(mount_root);

		ret = is_subvol_ro(&send, subvol);
		if (ret < 0)
			goto out;
		if (!ret) {
			ret = -EINVAL;
			error("subvolume %s is not read-only", subvol);
			goto out;
		}
	}

	if ((send_flags & BTRFS_SEND_FLAG_NO_FILE_DATA) && g_verbose > 1)
		if (g_verbose > 1)
			fprintf(stderr, "Mode NO_FILE_DATA enabled\n");

	for (i = optind; i < argc; i++) {
		int is_first_subvol;
		int is_last_subvol;

		free(subvol);
		subvol = argv[i];

		if (g_verbose > 0)
			fprintf(stderr, "At subvol %s\n", subvol);

		subvol = realpath(subvol, NULL);
		if (!subvol) {
			ret = -errno;
			error("realpath %s failed: %s", argv[i], strerror(-ret));
			goto out;
		}

		if (!full_send && !snapshot_parent) {
			ret = set_root_info(&send, subvol, &root_id);
			if (ret < 0)
				goto out;

			ret = find_good_parent(&send, root_id, &parent_root_id);
			if (ret < 0) {
				error("parent determination failed for %lld",
					root_id);
				goto out;
			}
		}

		if (new_end_cmd_semantic) {
			/* require new kernel */
			is_first_subvol = (i == optind);
			is_last_subvol = (i == argc - 1);
		} else {
			/* be compatible to old and new kernel */
			is_first_subvol = 1;
			is_last_subvol = 1;
		}
		ret = do_send(&send, parent_root_id, is_first_subvol,
			      is_last_subvol, subvol, send_flags);
		if (ret < 0)
			goto out;

		if (!full_send && !snapshot_parent) {
			/* done with this subvol, so add it to the clone sources */
			ret = add_clone_source(&send, root_id);
			if (ret < 0) {
				error("cannot add clone source: %s", strerror(-ret));
				goto out;
			}
			free_send_info(&send);
		}
	}

	ret = 0;

out:
	free(subvol);
	free(snapshot_parent);
	free(send.clone_sources);
	free_send_info(&send);
	return !!ret;
}
示例#18
0
int main(int ac, char **av)
{
	struct cache_tree root_cache;
	struct btrfs_root *root;
	char *dev;
	char *output_file = NULL;
	u64 copy = 0;
	u64 logical = 0;
	u64 bytes = 0;
	u64 cur_logical = 0;
	u64 cur_len = 0;
	int out_fd = -1;
	int found = 0;
	int ret = 0;

	while(1) {
		int c;
		static const struct option long_options[] = {
			/* { "byte-count", 1, NULL, 'b' }, */
			{ "logical", required_argument, NULL, 'l' },
			{ "copy", required_argument, NULL, 'c' },
			{ "output", required_argument, NULL, 'o' },
			{ "bytes", required_argument, NULL, 'b' },
			{ NULL, 0, NULL, 0}
		};

		c = getopt_long(ac, av, "l:c:o:b:", long_options, NULL);
		if (c < 0)
			break;
		switch(c) {
			case 'l':
				logical = arg_strtou64(optarg);
				break;
			case 'c':
				copy = arg_strtou64(optarg);
				break;
			case 'b':
				bytes = arg_strtou64(optarg);
				break;
			case 'o':
				output_file = strdup(optarg);
				break;
			default:
				print_usage();
		}
	}
	set_argv0(av);
	ac = ac - optind;
	if (check_argc_min(ac, 1))
		print_usage();
	if (logical == 0)
		print_usage();

	dev = av[optind];

	radix_tree_init();
	cache_tree_init(&root_cache);

	root = open_ctree(dev, 0, 0);
	if (!root) {
		fprintf(stderr, "Open ctree failed\n");
		exit(1);
	}

	info_file = stdout;
	if (output_file) {
		if (strcmp(output_file, "-") == 0) {
			out_fd = 1;
			info_file = stderr;
		} else {
			out_fd = open(output_file, O_RDWR | O_CREAT, 0600);
			if (out_fd < 0)
				goto close;
			ret = ftruncate(out_fd, 0);
			if (ret) {
				ret = 1;
				close(out_fd);
				goto close;
			}
			info_file = stdout;
		}
	}

	if (bytes == 0)
		bytes = root->nodesize;
	cur_logical = logical;
	cur_len = bytes;

	/* First find the nearest extent */
	ret = map_one_extent(root->fs_info, &cur_logical, &cur_len, 0);
	if (ret < 0) {
		fprintf(stderr, "Failed to find extent at [%llu,%llu): %s\n",
			cur_logical, cur_logical + cur_len, strerror(-ret));
		goto out_close_fd;
	}
	/*
	 * Normally, search backward should be OK, but for special case like
	 * given logical is quite small where no extents are before it,
	 * we need to search forward.
	 */
	if (ret > 0) {
		ret = map_one_extent(root->fs_info, &cur_logical, &cur_len, 1);
		if (ret < 0) {
			fprintf(stderr,
				"Failed to find extent at [%llu,%llu): %s\n",
				cur_logical, cur_logical + cur_len,
				strerror(-ret));
			goto out_close_fd;
		}
		if (ret > 0) {
			fprintf(stderr,
				"Failed to find any extent at [%llu,%llu)\n",
				cur_logical, cur_logical + cur_len);
			goto out_close_fd;
		}
	}

	while (cur_logical + cur_len >= logical && cur_logical < logical +
	       bytes) {
		u64 real_logical;
		u64 real_len;

		found = 1;
		ret = map_one_extent(root->fs_info, &cur_logical, &cur_len, 1);
		if (ret < 0)
			goto out_close_fd;
		if (ret > 0)
			break;
		real_logical = max(logical, cur_logical);
		real_len = min(logical + bytes, cur_logical + cur_len) -
			   real_logical;

		ret = print_mapping_info(root->fs_info, real_logical, real_len);
		if (ret < 0)
			goto out_close_fd;
		if (output_file && out_fd != -1) {
			ret = write_extent_content(root->fs_info, out_fd,
					real_logical, real_len, copy);
			if (ret < 0)
				goto out_close_fd;
		}

		cur_logical += cur_len;
	}

	if (!found) {
		fprintf(stderr, "No extent found at range [%llu,%llu)\n",
			logical, logical + bytes);
	}
out_close_fd:
	if (output_file && out_fd != 1)
		close(out_fd);
close:
	close_ctree(root);
	if (ret < 0)
		ret = 1;
	return ret;
}
示例#19
0
int cmd_inspect_dump_super(int argc, char **argv)
{
	int all = 0;
	int full = 0;
	int force = 0;
	char *filename;
	int fd = -1;
	int i;
	int ret = 0;
	u64 arg;
	u64 sb_bytenr = btrfs_sb_offset(0);

	while (1) {
		int c;
		enum { GETOPT_VAL_BYTENR = 257 };
		static const struct option long_options[] = {
			{"all", no_argument, NULL, 'a'},
			{"bytenr", required_argument, NULL, GETOPT_VAL_BYTENR },
			{"full", no_argument, NULL, 'f'},
			{"force", no_argument, NULL, 'F'},
			{"super", required_argument, NULL, 's' },
			{NULL, 0, NULL, 0}
		};

		c = getopt_long(argc, argv, "fFai:s:", long_options, NULL);
		if (c < 0)
			break;

		switch (c) {
		case 'i':
			warning(
			    "option -i is deprecated, please use -s or --super");
			arg = arg_strtou64(optarg);
			if (arg >= BTRFS_SUPER_MIRROR_MAX) {
				error("super mirror too big: %llu >= %d",
					arg, BTRFS_SUPER_MIRROR_MAX);
				return 1;
			}
			sb_bytenr = btrfs_sb_offset(arg);
			break;

		case 'a':
			all = 1;
			break;
		case 'f':
			full = 1;
			break;
		case 'F':
			force = 1;
			break;
		case 's':
			arg = arg_strtou64(optarg);
			if (BTRFS_SUPER_MIRROR_MAX <= arg) {
				warning(
		"deprecated use of -s <bytenr> with %llu, assuming --bytenr",
						(unsigned long long)arg);
				sb_bytenr = arg;
			} else {
				sb_bytenr = btrfs_sb_offset(arg);
			}
			all = 0;
			break;
		case GETOPT_VAL_BYTENR:
			arg = arg_strtou64(optarg);
			sb_bytenr = arg;
			all = 0;
			break;
		default:
			usage_unknown_option(cmd_inspect_dump_super_usage, argv);
		}
	}

	if (check_argc_min(argc - optind, 1))
		return 1;

	for (i = optind; i < argc; i++) {
		filename = argv[i];
		fd = open(filename, O_RDONLY);
		if (fd < 0) {
			error("cannot open %s: %m", filename);
			ret = 1;
			goto out;
		}

		if (all) {
			int idx;

			for (idx = 0; idx < BTRFS_SUPER_MIRROR_MAX; idx++) {
				sb_bytenr = btrfs_sb_offset(idx);
				if (load_and_dump_sb(filename, fd,
						sb_bytenr, full, force)) {
					close(fd);
					ret = 1;
					goto out;
				}

				putchar('\n');
			}
		} else {
			load_and_dump_sb(filename, fd, sb_bytenr, full, force);
			putchar('\n');
		}
		close(fd);
	}

out:
	return ret;
}
示例#20
0
int cmd_device_usage(int argc, char **argv)
{
	unsigned unit_mode = UNITS_DEFAULT;
	int ret = 0;
	int	i, more_than_one = 0;

	optind = 1;
	while (1) {
		int c;
		static const struct option long_options[] = {
			{ "raw", no_argument, NULL, 'b'},
			{ "kbytes", no_argument, NULL, 'k'},
			{ "mbytes", no_argument, NULL, 'm'},
			{ "gbytes", no_argument, NULL, 'g'},
			{ "tbytes", no_argument, NULL, 't'},
			{ "si", no_argument, NULL, GETOPT_VAL_SI},
			{ "iec", no_argument, NULL, GETOPT_VAL_IEC},
			{ "human-readable", no_argument, NULL,
				GETOPT_VAL_HUMAN_READABLE},
			{ NULL, 0, NULL, 0 }
		};

		c = getopt_long(argc, argv, "bhHkmgt", long_options, NULL);
		if (c < 0)
			break;
		switch (c) {
		case 'b':
			unit_mode = UNITS_RAW;
			break;
		case 'k':
			units_set_base(&unit_mode, UNITS_KBYTES);
			break;
		case 'm':
			units_set_base(&unit_mode, UNITS_MBYTES);
			break;
		case 'g':
			units_set_base(&unit_mode, UNITS_GBYTES);
			break;
		case 't':
			units_set_base(&unit_mode, UNITS_TBYTES);
			break;
		case GETOPT_VAL_HUMAN_READABLE:
		case 'h':
			unit_mode = UNITS_HUMAN_BINARY;
			break;
		case 'H':
			unit_mode = UNITS_HUMAN_DECIMAL;
			break;
		case GETOPT_VAL_SI:
			units_set_mode(&unit_mode, UNITS_DECIMAL);
			break;
		case GETOPT_VAL_IEC:
			units_set_mode(&unit_mode, UNITS_BINARY);
			break;
		default:
			usage(cmd_device_usage_usage);
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_device_usage_usage);

	for (i = optind; i < argc ; i++) {
		int fd;
		DIR	*dirstream = NULL;
		if (more_than_one)
			printf("\n");

		fd = open_file_or_dir(argv[i], &dirstream);
		if (fd < 0) {
			fprintf(stderr, "ERROR: can't access '%s'\n",
				argv[1]);
			ret = 1;
			goto out;
		}

		ret = _cmd_device_usage(fd, argv[i], unit_mode);
		close_file_or_dir(fd, dirstream);

		if (ret)
			goto out;
		more_than_one = 1;
	}
out:
	return !!ret;
}
示例#21
0
static int cmd_subvol_sync(int argc, char **argv)
{
	int fd = -1;
	int i;
	int ret = 1;
	DIR *dirstream = NULL;
	u64 *ids = NULL;
	int id_count;
	int remaining;
	int sleep_interval = 1;

	optind = 1;
	while (1) {
		int c = getopt(argc, argv, "s:");

		if (c < 0)
			break;

		switch (c) {
		case 's':
			sleep_interval = atoi(argv[optind]);
			if (sleep_interval < 1) {
				fprintf(stderr,
					"ERROR: invalid sleep interval %s\n",
					argv[optind]);
				ret = 1;
				goto out;
			}
			break;
		default:
			usage(cmd_subvol_sync_usage);
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_subvol_sync_usage);

	fd = open_file_or_dir(argv[optind], &dirstream);
	if (fd < 0) {
		fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind]);
		ret = 1;
		goto out;
	}
	optind++;

	id_count = argc - optind;

	/*
	 * Wait for all
	 */
	if (!id_count) {
		while (1) {
			ret = fs_has_dead_subvolumes(fd);
			if (ret < 0) {
				fprintf(stderr, "ERROR: can't perform the search - %s\n",
						strerror(-ret));
				ret = 1;
				goto out;
			}
			if (!ret)
				goto out;
			sleep(sleep_interval);
		}
	}

	/*
	 * Wait only for the requested ones
	 */
	ids = (u64*)malloc(sizeof(u64) * id_count);

	if (!ids) {
		fprintf(stderr, "ERROR: not enough memory\n");
		ret = 1;
		goto out;
	}

	for (i = 0; i < id_count; i++) {
		u64 id;
		const char *arg;

		arg = argv[optind + i];
		errno = 0;
		id = strtoull(arg, NULL, 10);
		if (errno < 0) {
			fprintf(stderr, "ERROR: unrecognized subvolume id %s\n",
				arg);
			ret = 1;
			goto out;
		}
		if (id < BTRFS_FIRST_FREE_OBJECTID || id > BTRFS_LAST_FREE_OBJECTID) {
			fprintf(stderr, "ERROR: subvolume id %s out of range\n",
				arg);
			ret = 1;
			goto out;
		}
		ids[i] = id;
	}

	remaining = id_count;
	while (1) {
		for (i = 0; i < id_count; i++) {
			if (!ids[i])
				continue;
			ret = is_subvolume_cleaned(fd, ids[i]);
			if (ret < 0) {
				fprintf(stderr, "ERROR: can't perform the search - %s\n",
						strerror(-ret));
				goto out;
			}
			if (ret) {
				printf("Subvolume id %llu is gone\n", ids[i]);
				ids[i] = 0;
				remaining--;
			}
		}
		if (!remaining)
			break;
		sleep(sleep_interval);
	}

out:
	free(ids);
	close_file_or_dir(fd, dirstream);

	return !!ret;
}
示例#22
0
static int _cmd_device_remove(int argc, char **argv,
		const char * const *usagestr)
{
	char	*mntpnt;
	int i, fdmnt, ret = 0;
	DIR	*dirstream = NULL;

	clean_args_no_options(argc, argv, usagestr);

	if (check_argc_min(argc - optind, 2))
		usage(usagestr);

	mntpnt = argv[argc - 1];

	fdmnt = btrfs_open_dir(mntpnt, &dirstream, 1);
	if (fdmnt < 0)
		return 1;

	for(i = optind; i < argc - 1; i++) {
		struct	btrfs_ioctl_vol_args arg;
		struct btrfs_ioctl_vol_args_v2 argv2 = {0};
		int is_devid = 0;
		int	res;

		if (string_is_numerical(argv[i])) {
			argv2.devid = arg_strtou64(argv[i]);
			argv2.flags = BTRFS_DEVICE_SPEC_BY_ID;
			is_devid = 1;
		} else if (is_block_device(argv[i]) == 1 ||
				strcmp(argv[i], "missing") == 0) {
			strncpy_null(argv2.name, argv[i]);
		} else {
			error("not a block device: %s", argv[i]);
			ret++;
			continue;
		}

		/*
		 * Positive values are from BTRFS_ERROR_DEV_*,
		 * otherwise it's a generic error, one of errnos
		 */
		res = ioctl(fdmnt, BTRFS_IOC_RM_DEV_V2, &argv2);

		/*
		 * If BTRFS_IOC_RM_DEV_V2 is not supported we get ENOTTY and if
		 * argv2.flags includes a flag which kernel doesn't understand then
		 * we shall get EOPNOTSUPP
		 */
		if (res < 0 && (errno == ENOTTY || errno == EOPNOTSUPP)) {
			if (is_devid) {
				error("device delete by id failed: %m");
				ret++;
				continue;
			}
			memset(&arg, 0, sizeof(arg));
			strncpy_null(arg.name, argv[i]);
			res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
		}

		if (res) {
			const char *msg;

			if (res > 0)
				msg = btrfs_err_str(res);
			else
				msg = strerror(errno);
			if (is_devid) {
				error("error removing devid %llu: %s",
					(unsigned long long)argv2.devid, msg);
			} else {
				error("error removing device '%s': %s",
					argv[i], msg);
			}
			ret++;
		}
	}

	close_file_or_dir(fdmnt, dirstream);
	return !!ret;
}
示例#23
0
static int cmd_subvol_delete(int argc, char **argv)
{
	int	res, e, ret = 0;
	int cnt;
	int fd = -1;
	struct btrfs_ioctl_vol_args	args;
	char	*dname, *vname, *cpath;
	char	*dupdname = NULL;
	char	*dupvname = NULL;
	char	*path;
	DIR	*dirstream = NULL;
	int verbose = 0;
	int commit_mode = 0;

	optind = 1;
	while (1) {
		int c;
		static const struct option long_options[] = {
			{"commit-after", no_argument, NULL, 'c'},  /* commit mode 1 */
			{"commit-each", no_argument, NULL, 'C'},  /* commit mode 2 */
			{NULL, 0, NULL, 0}
		};

		c = getopt_long(argc, argv, "cC", long_options, NULL);
		if (c < 0)
			break;

		switch(c) {
		case 'c':
			commit_mode = 1;
			break;
		case 'C':
			commit_mode = 2;
			break;
		case 'v':
			verbose++;
			break;
		default:
			usage(cmd_subvol_delete_usage);
		}
	}

	if (check_argc_min(argc - optind, 1))
		usage(cmd_subvol_delete_usage);

	if (verbose > 0) {
		printf("Transaction commit: %s\n",
			!commit_mode ? "none (default)" :
			commit_mode == 1 ? "at the end" : "after each");
	}

	cnt = optind;

again:
	path = argv[cnt];

	res = test_issubvolume(path);
	if (res < 0) {
		fprintf(stderr, "ERROR: error accessing '%s'\n", path);
		ret = 1;
		goto out;
	}
	if (!res) {
		fprintf(stderr, "ERROR: '%s' is not a subvolume\n", path);
		ret = 1;
		goto out;
	}

	cpath = realpath(path, NULL);
	if (!cpath) {
		ret = errno;
		fprintf(stderr, "ERROR: finding real path for '%s': %s\n",
			path, strerror(errno));
		goto out;
	}
	dupdname = strdup(cpath);
	dname = dirname(dupdname);
	dupvname = strdup(cpath);
	vname = basename(dupvname);
	free(cpath);

	fd = open_file_or_dir(dname, &dirstream);
	if (fd < 0) {
		fprintf(stderr, "ERROR: can't access '%s'\n", dname);
		ret = 1;
		goto out;
	}

	printf("Delete subvolume (%s): '%s/%s'\n",
		commit_mode == 2 || (commit_mode == 1 && cnt + 1 == argc)
		? "commit" : "no-commit", dname, vname);
	memset(&args, 0, sizeof(args));
	strncpy_null(args.name, vname);
	res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);
	e = errno;

	if(res < 0 ){
		fprintf( stderr, "ERROR: cannot delete '%s/%s' - %s\n",
			dname, vname, strerror(e));
		ret = 1;
		goto out;
	}

	if (commit_mode == 1) {
		res = wait_for_commit(fd);
		if (res < 0) {
			fprintf(stderr,
				"ERROR: unable to wait for commit after '%s': %s\n",
				path, strerror(errno));
			ret = 1;
		}
	}

out:
	free(dupdname);
	free(dupvname);
	dupdname = NULL;
	dupvname = NULL;
	cnt++;
	if (cnt < argc) {
		close_file_or_dir(fd, dirstream);
		/* avoid double free */
		fd = -1;
		dirstream = NULL;
		goto again;
	}

	if (commit_mode == 2 && fd != -1) {
		res = wait_for_commit(fd);
		if (res < 0) {
			fprintf(stderr,
				"ERROR: unable to do final sync: %s\n",
				strerror(errno));
			ret = 1;
		}
	}
	close_file_or_dir(fd, dirstream);

	return ret;
}
示例#24
0
static int cmd_device_add(int argc, char **argv)
{
	char	*mntpnt;
	int i, fdmnt, ret = 0;
	DIR	*dirstream = NULL;
	int discard = 1;
	int force = 0;
	int last_dev;

	optind = 0;
	while (1) {
		int c;
		static const struct option long_options[] = {
			{ "nodiscard", optional_argument, NULL, 'K'},
			{ "force", no_argument, NULL, 'f'},
			{ NULL, 0, NULL, 0}
		};

		c = getopt_long(argc, argv, "Kf", long_options, NULL);
		if (c < 0)
			break;
		switch (c) {
		case 'K':
			discard = 0;
			break;
		case 'f':
			force = 1;
			break;
		default:
			usage(cmd_device_add_usage);
		}
	}

	if (check_argc_min(argc - optind, 2))
		usage(cmd_device_add_usage);

	last_dev = argc - 1;
	mntpnt = argv[last_dev];

	fdmnt = btrfs_open_dir(mntpnt, &dirstream, 1);
	if (fdmnt < 0)
		return 1;

	for (i = optind; i < last_dev; i++){
		struct btrfs_ioctl_vol_args ioctl_args;
		int	devfd, res;
		u64 dev_block_count = 0;
		char *path;

		res = test_dev_for_mkfs(argv[i], force);
		if (res) {
			ret++;
			continue;
		}

		devfd = open(argv[i], O_RDWR);
		if (devfd < 0) {
			error("unable to open device '%s'", argv[i]);
			ret++;
			continue;
		}

		res = btrfs_prepare_device(devfd, argv[i], &dev_block_count, 0,
				PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE |
				(discard ? PREP_DEVICE_DISCARD : 0));
		close(devfd);
		if (res) {
			ret++;
			goto error_out;
		}

		path = canonicalize_path(argv[i]);
		if (!path) {
			error("could not canonicalize pathname '%s': %m",
				argv[i]);
			ret++;
			goto error_out;
		}

		memset(&ioctl_args, 0, sizeof(ioctl_args));
		strncpy_null(ioctl_args.name, path);
		res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
		if (res < 0) {
			error("error adding device '%s': %m", path);
			ret++;
		}
		free(path);
	}

error_out:
	close_file_or_dir(fdmnt, dirstream);
	return !!ret;
}
示例#25
0
int main(int argc, char **argv)
{
	int opt;
	int all = 0;
	int full = 0;
	int force = 0;
	char *filename;
	int fd = -1;
	int i;
	u64 arg;
	u64 sb_bytenr = btrfs_sb_offset(0);

	while ((opt = getopt(argc, argv, "fFai:s:")) != -1) {
		switch (opt) {
		case 'i':
			arg = arg_strtou64(optarg);
			if (arg >= BTRFS_SUPER_MIRROR_MAX) {
				fprintf(stderr,
					"Illegal super_mirror %llu\n",
					arg);
				print_usage();
				exit(1);
			}
			sb_bytenr = btrfs_sb_offset(arg);
			break;

		case 'a':
			all = 1;
			break;
		case 'f':
			full = 1;
			break;
		case 'F':
			force = 1;
			break;
		case 's':
			sb_bytenr = arg_strtou64(optarg);
			all = 0;
			break;
		default:
			print_usage();
			exit(1);
		}
	}

	set_argv0(argv);
	if (check_argc_min(argc - optind, 1)) {
		print_usage();
		exit(1);
	}

	for (i = optind; i < argc; i++) {
		filename = argv[i];
		fd = open(filename, O_RDONLY, 0666);
		if (fd < 0) {
			fprintf(stderr, "Could not open %s\n", filename);
			exit(1);
		}

		if (all) {
			int idx;
			for (idx = 0; idx < BTRFS_SUPER_MIRROR_MAX; idx++) {
				sb_bytenr = btrfs_sb_offset(idx);
				if (load_and_dump_sb(filename, fd,
						sb_bytenr, full, force)) {
					close(fd);
					exit(1);
				}

				putchar('\n');
			}
		} else {
			load_and_dump_sb(filename, fd, sb_bytenr, full, force);
			putchar('\n');
		}
		close(fd);
	}

	exit(0);
}
示例#26
0
int main(int argc, char **argv)
{
	struct btrfs_fs_info *fs_info;
	struct btrfs_find_root_filter filter = {0};
	struct cache_tree result;
	struct cache_extent *found;
	int ret;

	/* Default to search root tree */
	filter.objectid = BTRFS_ROOT_TREE_OBJECTID;
	filter.match_gen = (u64)-1;
	filter.match_level = (u8)-1;
	while (1) {
		static const struct option long_options[] = {
			{ "help", no_argument, NULL, GETOPT_VAL_HELP},
			{ NULL, 0, NULL, 0 }
		};
		int c = getopt_long(argc, argv, "al:o:g:", long_options, NULL);

		if (c < 0)
			break;

		switch (c) {
		case 'a':
			filter.search_all = 1;
			break;
		case 'o':
			filter.objectid = arg_strtou64(optarg);
			break;
		case 'g':
			filter.generation = arg_strtou64(optarg);
			break;
		case 'l':
			filter.level = arg_strtou64(optarg);
			break;
		case GETOPT_VAL_HELP:
		default:
			find_root_usage();
			exit(c != GETOPT_VAL_HELP);
		}
	}

	set_argv0(argv);
	if (check_argc_min(argc - optind, 1)) {
		find_root_usage();
		exit(1);
	}

	fs_info = open_ctree_fs_info(argv[optind], 0, 0, 0,
			OPEN_CTREE_CHUNK_ROOT_ONLY |
			OPEN_CTREE_IGNORE_CHUNK_TREE_ERROR);
	if (!fs_info) {
		error("open ctree failed");
		exit(1);
	}
	cache_tree_init(&result);

	get_root_gen_and_level(filter.objectid, fs_info,
			       &filter.match_gen, &filter.match_level);
	ret = btrfs_find_root_search(fs_info, &filter, &result, &found);
	if (ret < 0) {
		fprintf(stderr, "Fail to search the tree root: %s\n",
			strerror(-ret));
		goto out;
	}
	if (ret > 0) {
		printf("Found tree root at %llu gen %llu level %u\n",
		       found->start, filter.match_gen, filter.match_level);
		ret = 0;
	}
	print_find_root_result(&result, &filter);
out:
	btrfs_find_root_free(&result);
	close_ctree_fs_info(fs_info);
	btrfs_close_all_devices();
	return ret;
}