btrfs-progs: Remove deprecated btrfs-show-super
[platform/upstream/btrfs-progs.git] / cmds-quota.c
1 /*
2  * Copyright (C) 2012 STRATO.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18
19 #include <sys/ioctl.h>
20 #include <unistd.h>
21
22 #include "ctree.h"
23 #include "ioctl.h"
24
25 #include "commands.h"
26 #include "utils.h"
27 #include "help.h"
28
29 static const char * const quota_cmd_group_usage[] = {
30         "btrfs quota <command> [options] <path>",
31         NULL
32 };
33
34 static int quota_ctl(int cmd, int argc, char **argv)
35 {
36         int ret = 0;
37         int fd;
38         char *path = argv[1];
39         struct btrfs_ioctl_quota_ctl_args args;
40         DIR *dirstream = NULL;
41
42         if (check_argc_exact(argc, 2))
43                 return -1;
44
45         memset(&args, 0, sizeof(args));
46         args.cmd = cmd;
47
48         fd = btrfs_open_dir(path, &dirstream, 1);
49         if (fd < 0)
50                 return 1;
51
52         ret = ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args);
53         close_file_or_dir(fd, dirstream);
54         if (ret < 0) {
55                 error("quota command failed: %m");
56                 return 1;
57         }
58         return 0;
59 }
60
61 static const char * const cmd_quota_enable_usage[] = {
62         "btrfs quota enable <path>",
63         "Enable subvolume quota support for a filesystem.",
64         "Any data already present on the filesystem will not count towards",
65         "the space usage numbers. It is recommended to enable quota for a",
66         "filesystem before writing any data to it.",
67         NULL
68 };
69
70 static int cmd_quota_enable(int argc, char **argv)
71 {
72         int ret;
73
74         clean_args_no_options(argc, argv, cmd_quota_enable_usage);
75
76         ret = quota_ctl(BTRFS_QUOTA_CTL_ENABLE, argc, argv);
77
78         if (ret < 0)
79                 usage(cmd_quota_enable_usage);
80         return ret;
81 }
82
83 static const char * const cmd_quota_disable_usage[] = {
84         "btrfs quota disable <path>",
85         "Disable subvolume quota support for a filesystem.",
86         NULL
87 };
88
89 static int cmd_quota_disable(int argc, char **argv)
90 {
91         int ret;
92
93         clean_args_no_options(argc, argv, cmd_quota_disable_usage);
94
95         ret = quota_ctl(BTRFS_QUOTA_CTL_DISABLE, argc, argv);
96
97         if (ret < 0)
98                 usage(cmd_quota_disable_usage);
99         return ret;
100 }
101
102 static const char * const cmd_quota_rescan_usage[] = {
103         "btrfs quota rescan [-sw] <path>",
104         "Trash all qgroup numbers and scan the metadata again with the current config.",
105         "",
106         "-s   show status of a running rescan operation",
107         "-w   wait for rescan operation to finish (can be already in progress)",
108         NULL
109 };
110
111 static int cmd_quota_rescan(int argc, char **argv)
112 {
113         int ret = 0;
114         int fd;
115         int e;
116         char *path = NULL;
117         struct btrfs_ioctl_quota_rescan_args args;
118         unsigned long ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
119         DIR *dirstream = NULL;
120         int wait_for_completion = 0;
121
122         while (1) {
123                 int c = getopt(argc, argv, "sw");
124                 if (c < 0)
125                         break;
126                 switch (c) {
127                 case 's':
128                         ioctlnum = BTRFS_IOC_QUOTA_RESCAN_STATUS;
129                         break;
130                 case 'w':
131                         wait_for_completion = 1;
132                         break;
133                 default:
134                         usage(cmd_quota_rescan_usage);
135                 }
136         }
137
138         if (ioctlnum != BTRFS_IOC_QUOTA_RESCAN && wait_for_completion) {
139                 error("switch -w cannot be used with -s");
140                 return 1;
141         }
142
143         if (check_argc_exact(argc - optind, 1))
144                 usage(cmd_quota_rescan_usage);
145
146         memset(&args, 0, sizeof(args));
147
148         path = argv[optind];
149         fd = btrfs_open_dir(path, &dirstream, 1);
150         if (fd < 0)
151                 return 1;
152
153         ret = ioctl(fd, ioctlnum, &args);
154         e = errno;
155
156         if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS) {
157                 close_file_or_dir(fd, dirstream);
158                 if (ret < 0) {
159                         error("could not obtain quota rescan status: %m");
160                         return 1;
161                 }
162                 if (!args.flags)
163                         printf("no rescan operation in progress\n");
164                 else
165                         printf("rescan operation running (current key %lld)\n",
166                                 args.progress);
167                 return 0;
168         }
169
170         if (ret == 0) {
171                 printf("quota rescan started\n");
172                 fflush(stdout);
173         } else if (ret < 0 && (!wait_for_completion || e != EINPROGRESS)) {
174                 error("quota rescan failed: %m");
175                 close_file_or_dir(fd, dirstream);
176                 return 1;
177         }
178
179         if (wait_for_completion) {
180                 ret = ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT, &args);
181                 e = errno;
182                 if (ret < 0) {
183                         error("quota rescan wait failed: %m");
184                         close_file_or_dir(fd, dirstream);
185                         return 1;
186                 }
187         }
188
189         close_file_or_dir(fd, dirstream);
190         return 0;
191 }
192
193 static const char quota_cmd_group_info[] =
194 "manage filesystem quota settings";
195
196 const struct cmd_group quota_cmd_group = {
197         quota_cmd_group_usage, quota_cmd_group_info, {
198                 { "enable", cmd_quota_enable, cmd_quota_enable_usage, NULL, 0 },
199                 { "disable", cmd_quota_disable, cmd_quota_disable_usage,
200                    NULL, 0 },
201                 { "rescan", cmd_quota_rescan, cmd_quota_rescan_usage, NULL, 0 },
202                 NULL_CMD_STRUCT
203         }
204 };
205
206 int cmd_quota(int argc, char **argv)
207 {
208         return handle_command_group(&quota_cmd_group, argc, argv);
209 }