]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - quota/state.c
xfs_quota: allow users to truncate group and project quota files
[thirdparty/xfsprogs-dev.git] / quota / state.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
5aead01d 2/*
da23017d
NS
3 * Copyright (c) 2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5aead01d 5 */
29647c8d 6#include <stdbool.h>
6b803e5a 7#include "command.h"
5aead01d
NS
8#include "init.h"
9#include "quota.h"
10
11static cmdinfo_t off_cmd;
12static cmdinfo_t state_cmd;
13static cmdinfo_t enable_cmd;
14static cmdinfo_t disable_cmd;
15static cmdinfo_t remove_cmd;
16
17static void
18off_help(void)
19{
20 printf(_(
21"\n"
22" turn filesystem quota off, both accounting and enforcement\n"
23"\n"
24" Example:\n"
25" 'off -uv' (switch off user quota on the current filesystem)\n"
26" This command is the equivalent of the traditional quotaoff command,\n"
27" which disables quota completely on a mounted filesystem.\n"
28" Note that there is no 'on' command - for XFS filesystems (with the\n"
29" exception of the root filesystem on IRIX) quota can only be enabled\n"
30" at mount time, through the use of one of the quota mount options.\n"
31"\n"
32" The state command is useful for displaying the current state. Using\n"
33" the -v (verbose) option with the 'off' command will display the quota\n"
34" state for the affected filesystem once the operation is complete.\n"
35" The affected quota type is -g (groups), -p (projects) or -u (users)\n"
36" and defaults to user quota (multiple types can be specified).\n"
37"\n"));
38}
39
40static void
41state_help(void)
42{
43 printf(_(
44"\n"
45" query the state of quota on the current filesystem\n"
46"\n"
47" This is a verbose status command, reporting whether or not accounting\n"
48" and/or enforcement are enabled for a filesystem, which inodes are in\n"
49" use as the quota state inodes, and how many extents and blocks are\n"
50" presently being used to hold that information.\n"
51" The quota type is specified via -g (groups), -p (projects) or -u (users)\n"
52" and defaults to user quota (multiple types can be specified).\n"
53"\n"));
54}
55
56static void
57enable_help(void)
58{
59 printf(_(
60"\n"
61" enable quota enforcement on a filesystem\n"
62"\n"
63" If a filesystem is mounted and has quota accounting enabled, but not\n"
64" quota enforcement, enforcement can be enabled with this command.\n"
65" With the -v (verbose) option, the status of the filesystem will be\n"
66" reported after the operation is complete.\n"
67" The affected quota type is -g (groups), -p (projects) or -u (users)\n"
68" and defaults to user quota (multiple types can be specified).\n"
69"\n"));
70}
71
72static void
73disable_help(void)
74{
75 printf(_(
76"\n"
77" disable quota enforcement on a filesystem\n"
78"\n"
79" If a filesystem is mounted and is currently enforcing quota, this\n"
80" provides a mechanism to switch off the enforcement, but continue to\n"
81" perform used space (and used inodes) accounting.\n"
82" The affected quota type is -g (groups), -p (projects) or -u (users).\n"
83"\n"));
84}
85
86static void
87remove_help(void)
88{
89 printf(_(
90"\n"
91" remove any space being used by the quota subsystem\n"
92"\n"
93" Once quota has been switched 'off' on a filesystem, the space that\n"
94" was allocated to holding quota metadata can be freed via this command.\n"
95" The affected quota type is -g (groups), -p (projects) or -u (users)\n"
96" and defaults to user quota (multiple types can be specified).\n"
97"\n"));
98}
99
100static void
101state_qfilestat(
bb92709f
ES
102 FILE *fp,
103 struct fs_path *mount,
104 uint type,
105 struct fs_qfilestatv *qfs,
106 int accounting,
107 int enforcing)
5aead01d
NS
108{
109 fprintf(fp, _("%s quota state on %s (%s)\n"), type_to_string(type),
110 mount->fs_dir, mount->fs_name);
111 fprintf(fp, _(" Accounting: %s\n"), accounting ? _("ON") : _("OFF"));
112 fprintf(fp, _(" Enforcement: %s\n"), enforcing ? _("ON") : _("OFF"));
06065b12
AE
113 if (qfs->qfs_ino != (__u64) -1)
114 fprintf(fp, _(" Inode: #%llu (%llu blocks, %lu extents)\n"),
115 (unsigned long long)qfs->qfs_ino,
116 (unsigned long long)qfs->qfs_nblks,
117 (unsigned long)qfs->qfs_nextents);
118 else
119 fprintf(fp, _(" Inode: N/A\n"));
5aead01d
NS
120}
121
122static void
123state_timelimit(
124 FILE *fp,
125 uint form,
14f8b681 126 uint32_t timelimit)
5aead01d
NS
127{
128 fprintf(fp, _("%s grace time: %s\n"),
129 form_to_string(form),
130 time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG));
131}
132
387a96e1
DW
133static void
134state_warnlimit(
135 FILE *fp,
136 uint form,
137 uint16_t warnlimit)
138{
139 fprintf(fp, _("%s max warnings: %u\n"),
140 form_to_string(form), warnlimit);
141}
142
bb92709f
ES
143/*
144 * fs_quota_stat holds a subset of fs_quota_statv; this copies
145 * the smaller into the larger, leaving any not-present fields
146 * empty. This is so the same reporting function can be used
147 * for both XFS_GETQSTAT and XFS_GETQSTATV results.
148 */
149static void
150state_stat_to_statv(
151 struct fs_quota_stat *s,
152 struct fs_quota_statv *sv)
153{
154 memset(sv, 0, sizeof(struct fs_quota_statv));
155
156 /* shared information */
157 sv->qs_version = s->qs_version;
158 sv->qs_flags = s->qs_flags;
159 sv->qs_incoredqs = s->qs_incoredqs;
160 sv->qs_btimelimit = s->qs_btimelimit;
161 sv->qs_itimelimit = s->qs_itimelimit;
162 sv->qs_rtbtimelimit = s->qs_rtbtimelimit;
163 sv->qs_bwarnlimit = s->qs_bwarnlimit;
164 sv->qs_iwarnlimit = s->qs_iwarnlimit;
165
166 /* Always room for uquota */
167 sv->qs_uquota.qfs_ino = s->qs_uquota.qfs_ino;
168 sv->qs_uquota.qfs_nblks = s->qs_uquota.qfs_nblks;
169 sv->qs_uquota.qfs_nextents = s->qs_uquota.qfs_nextents;
170
171 /*
172 * If we are here, XFS_GETQSTATV failed and XFS_GETQSTAT passed;
173 * that is a very strong hint that we're on a kernel which predates
174 * the on-disk pquota inode; both were added in v3.12. So, we do
175 * some tricksy determination here.
176 * gs_gquota may hold either group quota inode info, or project
177 * quota if that is used instead; which one it actually holds depends
178 * on the quota flags. (If neither is set, neither is used)
179 */
180 if (s->qs_flags & XFS_QUOTA_GDQ_ACCT) {
181 /* gs_gquota holds group quota info */
182 sv->qs_gquota.qfs_ino = s->qs_gquota.qfs_ino;
183 sv->qs_gquota.qfs_nblks = s->qs_gquota.qfs_nblks;
184 sv->qs_gquota.qfs_nextents = s->qs_gquota.qfs_nextents;
185 } else if (s->qs_flags & XFS_QUOTA_PDQ_ACCT) {
186 /* gs_gquota actually holds project quota info */
187 sv->qs_pquota.qfs_ino = s->qs_gquota.qfs_ino;
188 sv->qs_pquota.qfs_nblks = s->qs_gquota.qfs_nblks;
189 sv->qs_pquota.qfs_nextents = s->qs_gquota.qfs_nextents;
190 }
191}
192
5aead01d 193static void
d8a94546 194state_quotafile_stat(
bb92709f
ES
195 FILE *fp,
196 uint type,
d8a94546
BD
197 struct fs_path *mount,
198 struct fs_quota_statv *sv,
199 struct fs_quota_stat *s,
bb92709f 200 uint flags)
5aead01d 201{
d8a94546
BD
202 bool accounting, enforcing;
203 struct fs_qfilestatv *qsv;
bb92709f
ES
204 char *dev = mount->fs_name;
205
d8a94546
BD
206 if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)sv) < 0) {
207 if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)s) < 0) {
bb92709f
ES
208 if (flags & VERBOSE_FLAG)
209 fprintf(fp,
210 _("%s quota are not enabled on %s\n"),
211 type_to_string(type), dev);
212 return;
213 }
d8a94546
BD
214 state_stat_to_statv(s, sv);
215 }
216
217 switch(type) {
218 case XFS_USER_QUOTA:
219 qsv = &sv->qs_uquota;
220 accounting = sv->qs_flags & XFS_QUOTA_UDQ_ACCT;
221 enforcing = sv->qs_flags & XFS_QUOTA_UDQ_ENFD;
222 break;
223 case XFS_GROUP_QUOTA:
224 qsv = &sv->qs_gquota;
225 accounting = sv->qs_flags & XFS_QUOTA_GDQ_ACCT;
226 enforcing = sv->qs_flags & XFS_QUOTA_GDQ_ENFD;
227 break;
228 case XFS_PROJ_QUOTA:
229 qsv = &sv->qs_pquota;
230 accounting = sv->qs_flags & XFS_QUOTA_PDQ_ACCT;
231 enforcing = sv->qs_flags & XFS_QUOTA_PDQ_ENFD;
232 break;
233 default:
234 return;
235 }
236
237
238 state_qfilestat(fp, mount, type, qsv, accounting, enforcing);
239
240 state_timelimit(fp, XFS_BLOCK_QUOTA, sv->qs_btimelimit);
241 state_warnlimit(fp, XFS_BLOCK_QUOTA, sv->qs_bwarnlimit);
242
243 state_timelimit(fp, XFS_INODE_QUOTA, sv->qs_itimelimit);
244 state_warnlimit(fp, XFS_INODE_QUOTA, sv->qs_iwarnlimit);
245
246 state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv->qs_rtbtimelimit);
247}
248
249static void
250state_quotafile_mount(
251 FILE *fp,
252 uint type,
253 struct fs_path *mount,
254 uint flags)
255{
256 struct fs_quota_stat s;
257 struct fs_quota_statv sv;
258
259 sv.qs_version = FS_QSTATV_VERSION1;
260
261 if (type & XFS_USER_QUOTA) {
262 state_quotafile_stat(fp, XFS_USER_QUOTA, mount,
263 &sv, &s, flags);
264 }
265
266 if (type & XFS_GROUP_QUOTA) {
267 state_quotafile_stat(fp, XFS_GROUP_QUOTA, mount,
268 &sv, &s, flags);
5aead01d
NS
269 }
270
d8a94546
BD
271 if (type & XFS_PROJ_QUOTA) {
272 state_quotafile_stat(fp, XFS_PROJ_QUOTA, mount,
273 &sv, &s, flags);
274 }
5aead01d
NS
275}
276
277static void
278state_quotafile(
279 FILE *fp,
280 uint type,
281 char *dir,
282 uint flags)
283{
284 fs_cursor_t cursor;
285 fs_path_t *mount;
286
287 fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor);
288 while ((mount = fs_cursor_next_entry(&cursor)))
289 state_quotafile_mount(fp, type, mount, flags);
290}
291
292static int
293state_f(
294 int argc,
295 char **argv)
296{
297 FILE *fp = NULL;
298 char *fname = NULL;
299 int c, flags = 0, type = 0;
300
301 while ((c = getopt(argc, argv, "af:gpuv")) != EOF) {
302 switch (c) {
303 case 'a':
304 flags |= ALL_MOUNTS_FLAG;
305 break;
306 case 'f':
307 fname = optarg;
308 break;
309 case 'g':
310 type |= XFS_GROUP_QUOTA;
311 break;
312 case 'p':
313 type |= XFS_PROJ_QUOTA;
314 break;
315 case 'u':
316 type |= XFS_USER_QUOTA;
317 break;
318 case 'v':
319 flags |= VERBOSE_FLAG;
320 break;
321 default:
322 return command_usage(&state_cmd);
323 }
324 }
325
326 if (argc != optind)
327 return command_usage(&state_cmd);
328
329 if ((fp = fopen_write_secure(fname)) == NULL)
330 return 0;
331
332 if (!type)
333 type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA;
334
fa13a00f
NS
335 if (flags & ALL_MOUNTS_FLAG)
336 state_quotafile(fp, type, NULL, flags);
04418c59 337 else if (fs_path && fs_path->fs_flags & FS_MOUNT_POINT)
fa13a00f 338 state_quotafile(fp, type, fs_path->fs_dir, flags);
5aead01d
NS
339
340 if (fname)
341 fclose(fp);
342 return 0;
343}
344
345static void
346enable_enforcement(
347 char *dir,
348 uint type,
349 uint qflags,
350 uint flags)
351{
352 fs_path_t *mount;
5aead01d
NS
353
354 mount = fs_table_lookup(dir, FS_MOUNT_POINT);
355 if (!mount) {
e3210fd8 356 exitcode = 1;
5aead01d
NS
357 fprintf(stderr, "%s: unknown mount point %s\n", progname, dir);
358 return;
359 }
360 dir = mount->fs_name;
ca42fa70
BD
361 if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) {
362 if (errno == EEXIST)
363 fprintf(stderr,
364 _("Quota enforcement already enabled.\n"));
365 else if (errno == EINVAL || errno == ENOSYS)
366 fprintf(stderr,
367 _("Can't enable enforcement when quota off.\n"));
368 else
369 perror("XFS_QUOTAON");
370 }
5aead01d
NS
371 else if (flags & VERBOSE_FLAG)
372 state_quotafile_mount(stdout, type, mount, flags);
373}
374
375static void
376disable_enforcement(
377 char *dir,
378 uint type,
379 uint qflags,
380 uint flags)
381{
382 fs_path_t *mount;
5aead01d
NS
383
384 mount = fs_table_lookup(dir, FS_MOUNT_POINT);
385 if (!mount) {
e3210fd8 386 exitcode = 1;
5aead01d
NS
387 fprintf(stderr, "%s: unknown mount point %s\n", progname, dir);
388 return;
389 }
390 dir = mount->fs_name;
ca42fa70
BD
391 if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) {
392 if (errno == EEXIST)
393 fprintf(stderr,
394 _("Quota enforcement already disabled.\n"));
395 else if (errno == EINVAL || errno == ENOSYS)
396 fprintf(stderr,
397 _("Can't disable enforcement when quota off.\n"));
398 else
399 perror("XFS_QUOTAOFF");
400 }
5aead01d
NS
401 else if (flags & VERBOSE_FLAG)
402 state_quotafile_mount(stdout, type, mount, flags);
403}
404
405static void
406quotaoff(
407 char *dir,
408 uint type,
409 uint qflags,
410 uint flags)
411{
412 fs_path_t *mount;
5aead01d
NS
413
414 mount = fs_table_lookup(dir, FS_MOUNT_POINT);
415 if (!mount) {
e3210fd8 416 exitcode = 1;
5aead01d
NS
417 fprintf(stderr, "%s: unknown mount point %s\n", progname, dir);
418 return;
419 }
420 dir = mount->fs_name;
ca42fa70
BD
421 if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) {
422 if (errno == EEXIST || errno == ENOSYS)
423 fprintf(stderr, _("Quota already off.\n"));
424 else
425 perror("XFS_QUOTAOFF");
426 }
5aead01d
NS
427 else if (flags & VERBOSE_FLAG)
428 state_quotafile_mount(stdout, type, mount, flags);
429}
430
79ac1ae4
DD
431static int
432remove_qtype_extents(
433 char *dir,
434 uint type)
435{
436 int error = 0;
437
438 if ((error = xfsquotactl(XFS_QUOTARM, dir, type, 0, (void *)&type)) < 0)
439 perror("XFS_QUOTARM");
440 return error;
441}
442
5aead01d
NS
443static void
444remove_extents(
445 char *dir,
446 uint type,
5aead01d
NS
447 uint flags)
448{
449 fs_path_t *mount;
5aead01d
NS
450
451 mount = fs_table_lookup(dir, FS_MOUNT_POINT);
452 if (!mount) {
e3210fd8 453 exitcode = 1;
5aead01d
NS
454 fprintf(stderr, "%s: unknown mount point %s\n", progname, dir);
455 return;
456 }
457 dir = mount->fs_name;
79ac1ae4 458 if (type & XFS_USER_QUOTA) {
f8149110 459 if (remove_qtype_extents(dir, XFS_USER_QUOTA) < 0)
79ac1ae4
DD
460 return;
461 }
462 if (type & XFS_GROUP_QUOTA) {
f8149110 463 if (remove_qtype_extents(dir, XFS_GROUP_QUOTA) < 0)
79ac1ae4 464 return;
610ec295
DW
465 }
466 if (type & XFS_PROJ_QUOTA) {
f8149110 467 if (remove_qtype_extents(dir, XFS_PROJ_QUOTA) < 0)
79ac1ae4
DD
468 return;
469 }
470 if (flags & VERBOSE_FLAG)
5aead01d
NS
471 state_quotafile_mount(stdout, type, mount, flags);
472}
473
474static int
475enable_f(
476 int argc,
477 char **argv)
478{
479 int c, flags = 0, qflags = 0, type = 0;
480
481 while ((c = getopt(argc, argv, "gpuv")) != EOF) {
482 switch (c) {
483 case 'g':
484 type |= XFS_GROUP_QUOTA;
485 qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD;
486 break;
487 case 'p':
488 type |= XFS_PROJ_QUOTA;
489 qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD;
490 break;
491 case 'u':
492 type |= XFS_USER_QUOTA;
493 qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD;
494 break;
495 case 'v':
496 flags |= VERBOSE_FLAG;
497 break;
498 default:
499 return command_usage(&enable_cmd);
500 }
501 }
502
503 if (argc != optind)
504 return command_usage(&enable_cmd);
505
79ac1ae4 506 if (!type) {
5aead01d
NS
507 type |= XFS_USER_QUOTA;
508 qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD;
509 }
510
fa13a00f
NS
511 if (fs_path->fs_flags & FS_MOUNT_POINT)
512 enable_enforcement(fs_path->fs_dir, type, qflags, flags);
5aead01d
NS
513 return 0;
514}
515
516static int
517disable_f(
518 int argc,
519 char **argv)
520{
521 int c, flags = 0, qflags = 0, type = 0;
522
523 while ((c = getopt(argc, argv, "gpuv")) != EOF) {
524 switch (c) {
525 case 'g':
526 type |= XFS_GROUP_QUOTA;
79ac1ae4 527 qflags |= XFS_QUOTA_GDQ_ENFD;
5aead01d
NS
528 break;
529 case 'p':
530 type |= XFS_PROJ_QUOTA;
79ac1ae4 531 qflags |= XFS_QUOTA_PDQ_ENFD;
5aead01d
NS
532 break;
533 case 'u':
534 type |= XFS_USER_QUOTA;
79ac1ae4 535 qflags |= XFS_QUOTA_UDQ_ENFD;
5aead01d
NS
536 break;
537 case 'v':
538 flags |= VERBOSE_FLAG;
539 break;
540 default:
541 return command_usage(&disable_cmd);
542 }
543 }
544
545 if (argc != optind)
546 return command_usage(&disable_cmd);
547
79ac1ae4 548 if (!type) {
5aead01d 549 type |= XFS_USER_QUOTA;
79ac1ae4 550 qflags |= XFS_QUOTA_UDQ_ENFD;
5aead01d
NS
551 }
552
fa13a00f
NS
553 if (fs_path->fs_flags & FS_MOUNT_POINT)
554 disable_enforcement(fs_path->fs_dir, type, qflags, flags);
5aead01d
NS
555 return 0;
556}
557
558static int
559off_f(
560 int argc,
561 char **argv)
562{
563 int c, flags = 0, qflags = 0, type = 0;
564
565 while ((c = getopt(argc, argv, "gpuv")) != EOF) {
566 switch (c) {
567 case 'g':
568 type |= XFS_GROUP_QUOTA;
569 qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD;
570 break;
571 case 'p':
572 type |= XFS_PROJ_QUOTA;
573 qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD;
574 break;
575 case 'u':
576 type |= XFS_USER_QUOTA;
577 qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD;
578 break;
579 case 'v':
580 flags |= VERBOSE_FLAG;
581 break;
582 default:
583 return command_usage(&off_cmd);
584 }
585 }
586
587 if (argc != optind)
588 return command_usage(&off_cmd);
589
79ac1ae4 590 if (!type) {
5aead01d
NS
591 type |= XFS_USER_QUOTA;
592 qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD;
593 }
594
fa13a00f
NS
595 if (fs_path->fs_flags & FS_MOUNT_POINT)
596 quotaoff(fs_path->fs_dir, type, qflags, flags);
5aead01d
NS
597 return 0;
598}
599
600static int
601remove_f(
602 int argc,
603 char **argv)
604{
79ac1ae4 605 int c, flags = 0, type = 0;
5aead01d
NS
606
607 while ((c = getopt(argc, argv, "gpuv")) != EOF) {
608 switch (c) {
609 case 'g':
610 type |= XFS_GROUP_QUOTA;
5aead01d
NS
611 break;
612 case 'p':
613 type |= XFS_PROJ_QUOTA;
5aead01d
NS
614 break;
615 case 'u':
616 type |= XFS_USER_QUOTA;
5aead01d
NS
617 break;
618 case 'v':
619 flags |= VERBOSE_FLAG;
620 break;
621 default:
622 return command_usage(&remove_cmd);
623 }
624 }
625
626 if (argc != optind)
627 return command_usage(&remove_cmd);
628
79ac1ae4 629 if (!type) {
5aead01d 630 type |= XFS_USER_QUOTA;
5aead01d
NS
631 }
632
fa13a00f 633 if (fs_path->fs_flags & FS_MOUNT_POINT)
79ac1ae4 634 remove_extents(fs_path->fs_dir, type, flags);
5aead01d
NS
635 return 0;
636}
637
638void
639state_init(void)
640{
ad765595 641 off_cmd.name = "off";
5aead01d
NS
642 off_cmd.cfunc = off_f;
643 off_cmd.argmin = 0;
644 off_cmd.argmax = -1;
645 off_cmd.args = _("[-gpu] [-v]");
646 off_cmd.oneline = _("permanently switch quota off for a path");
647 off_cmd.help = off_help;
648
ad765595 649 state_cmd.name = "state";
5aead01d
NS
650 state_cmd.cfunc = state_f;
651 state_cmd.argmin = 0;
652 state_cmd.argmax = -1;
62790d19 653 state_cmd.args = _("[-gpu] [-a] [-v] [-f file]");
5aead01d
NS
654 state_cmd.oneline = _("get overall quota state information");
655 state_cmd.help = state_help;
29647c8d 656 state_cmd.flags = CMD_FLAG_FOREIGN_OK;
5aead01d 657
ad765595 658 enable_cmd.name = "enable";
5aead01d
NS
659 enable_cmd.cfunc = enable_f;
660 enable_cmd.argmin = 0;
661 enable_cmd.argmax = -1;
662 enable_cmd.args = _("[-gpu] [-v]");
663 enable_cmd.oneline = _("enable quota enforcement");
664 enable_cmd.help = enable_help;
665
ad765595 666 disable_cmd.name = "disable";
5aead01d
NS
667 disable_cmd.cfunc = disable_f;
668 disable_cmd.argmin = 0;
669 disable_cmd.argmax = -1;
670 disable_cmd.args = _("[-gpu] [-v]");
671 disable_cmd.oneline = _("disable quota enforcement");
672 disable_cmd.help = disable_help;
673
ad765595 674 remove_cmd.name = "remove";
5aead01d
NS
675 remove_cmd.cfunc = remove_f;
676 remove_cmd.argmin = 0;
677 remove_cmd.argmax = -1;
678 remove_cmd.args = _("[-gpu] [-v]");
679 remove_cmd.oneline = _("remove quota extents from a filesystem");
680 remove_cmd.help = remove_help;
681
682 if (expert) {
683 add_command(&off_cmd);
684 add_command(&state_cmd);
685 add_command(&enable_cmd);
686 add_command(&disable_cmd);
687 add_command(&remove_cmd);
688 }
689}