#include "commands.h"
#include "utils.h"
+#include "help.h"
static const char * const quota_cmd_group_usage[] = {
"btrfs quota <command> [options] <path>",
NULL
};
-int quota_ctl(int cmd, int argc, char **argv)
+static int quota_ctl(int cmd, int argc, char **argv)
{
int ret = 0;
int fd;
int e;
char *path = argv[1];
struct btrfs_ioctl_quota_ctl_args args;
+ DIR *dirstream = NULL;
if (check_argc_exact(argc, 2))
return -1;
memset(&args, 0, sizeof(args));
args.cmd = cmd;
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access '%s'\n", path);
- return 12;
- }
+ fd = btrfs_open_dir(path, &dirstream, 1);
+ if (fd < 0)
+ return 1;
ret = ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args);
e = errno;
- close(fd);
+ close_file_or_dir(fd, dirstream);
if (ret < 0) {
- fprintf(stderr, "ERROR: quota command failed: %s\n",
- strerror(e));
- return 30;
+ error("quota command failed: %s", strerror(e));
+ return 1;
}
return 0;
}
static int cmd_quota_enable(int argc, char **argv)
{
- int ret = quota_ctl(BTRFS_QUOTA_CTL_ENABLE, argc, argv);
+ int ret;
+
+ clean_args_no_options(argc, argv, cmd_quota_enable_usage);
+
+ ret = quota_ctl(BTRFS_QUOTA_CTL_ENABLE, argc, argv);
+
if (ret < 0)
usage(cmd_quota_enable_usage);
return ret;
static int cmd_quota_disable(int argc, char **argv)
{
- int ret = quota_ctl(BTRFS_QUOTA_CTL_DISABLE, argc, argv);
+ int ret;
+
+ clean_args_no_options(argc, argv, cmd_quota_disable_usage);
+
+ ret = quota_ctl(BTRFS_QUOTA_CTL_DISABLE, argc, argv);
+
if (ret < 0)
usage(cmd_quota_disable_usage);
return ret;
}
static const char * const cmd_quota_rescan_usage[] = {
- "btrfs quota rescan [-s] <path>",
+ "btrfs quota rescan [-sw] <path>",
"Trash all qgroup numbers and scan the metadata again with the current config.",
"",
"-s show status of a running rescan operation",
+ "-w wait for rescan operation to finish (can be already in progress)",
NULL
};
int e;
char *path = NULL;
struct btrfs_ioctl_quota_rescan_args args;
- int ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
+ unsigned long ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
+ DIR *dirstream = NULL;
+ int wait_for_completion = 0;
- optind = 1;
while (1) {
- int c = getopt(argc, argv, "s");
+ int c = getopt(argc, argv, "sw");
if (c < 0)
break;
switch (c) {
case 's':
ioctlnum = BTRFS_IOC_QUOTA_RESCAN_STATUS;
break;
+ case 'w':
+ wait_for_completion = 1;
+ break;
default:
usage(cmd_quota_rescan_usage);
}
}
+ if (ioctlnum != BTRFS_IOC_QUOTA_RESCAN && wait_for_completion) {
+ error("switch -w cannot be used with -s");
+ return 1;
+ }
+
if (check_argc_exact(argc - optind, 1))
usage(cmd_quota_rescan_usage);
memset(&args, 0, sizeof(args));
path = argv[optind];
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access '%s'\n", path);
- return 12;
- }
+ fd = btrfs_open_dir(path, &dirstream, 1);
+ if (fd < 0)
+ return 1;
ret = ioctl(fd, ioctlnum, &args);
e = errno;
- close(fd);
- if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN) {
+ if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS) {
+ close_file_or_dir(fd, dirstream);
if (ret < 0) {
- fprintf(stderr, "ERROR: quota rescan failed: "
- "%s\n", strerror(e));
- return 30;
- } else {
- printf("quota rescan started\n");
+ error("could not obtain quota rescan status: %s",
+ strerror(e));
+ return 1;
}
- } else {
- if (!args.flags) {
+ if (!args.flags)
printf("no rescan operation in progress\n");
- } else {
+ else
printf("rescan operation running (current key %lld)\n",
args.progress);
+ return 0;
+ }
+
+ if (ret == 0) {
+ printf("quota rescan started\n");
+ fflush(stdout);
+ } else if (ret < 0 && (!wait_for_completion || e != EINPROGRESS)) {
+ error("quota rescan failed: %s", strerror(e));
+ close_file_or_dir(fd, dirstream);
+ return 1;
+ }
+
+ if (wait_for_completion) {
+ ret = ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT, &args);
+ e = errno;
+ if (ret < 0) {
+ error("quota rescan wait failed: %s",
+ strerror(e));
+ close_file_or_dir(fd, dirstream);
+ return 1;
}
}
+ close_file_or_dir(fd, dirstream);
return 0;
}
+static const char quota_cmd_group_info[] =
+"manage filesystem quota settings";
+
const struct cmd_group quota_cmd_group = {
- quota_cmd_group_usage, NULL, {
+ quota_cmd_group_usage, quota_cmd_group_info, {
{ "enable", cmd_quota_enable, cmd_quota_enable_usage, NULL, 0 },
- { "disable", cmd_quota_disable, cmd_quota_disable_usage, 0, 0 },
+ { "disable", cmd_quota_disable, cmd_quota_disable_usage,
+ NULL, 0 },
{ "rescan", cmd_quota_rescan, cmd_quota_rescan_usage, NULL, 0 },
- { 0, 0, 0, 0, 0 }
+ NULL_CMD_STRUCT
}
};