diff options
author | Nathan Scott <nathans@sgi.com> | 2005-06-03 06:10:38 +0000 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2005-06-03 06:10:38 +0000 |
commit | 1774874a458e604ba87e110b902111835c56ff87 (patch) | |
tree | 2b002a0d2eacee8a2a1e0e392b62d629f8cb02a6 /quota | |
parent | a1465f3f78fa906667aebccfb5c5155ffb63cf42 (diff) | |
download | xfsprogs-dev-1774874a458e604ba87e110b902111835c56ff87.tar.gz |
Fix xfs_quota bugs found by QA tests, and add some options to assist testing.
Merge of master-melb:xfs-cmds:22798a by kenmcd.
Diffstat (limited to 'quota')
-rw-r--r-- | quota/edit.c | 127 | ||||
-rw-r--r-- | quota/free.c | 6 | ||||
-rw-r--r-- | quota/quot.c | 11 | ||||
-rw-r--r-- | quota/quota.c | 31 | ||||
-rw-r--r-- | quota/quota.h | 1 | ||||
-rw-r--r-- | quota/report.c | 180 |
6 files changed, 208 insertions, 148 deletions
diff --git a/quota/edit.c b/quota/edit.c index 5c52e354d8..d2bc6019c2 100644 --- a/quota/edit.c +++ b/quota/edit.c @@ -71,14 +71,15 @@ timer_help(void) { printf(_( "\n" -" modify quota enforcement timeout for the specified user\n" +" modify quota enforcement timeout for the current filesystem\n" "\n" " Example:\n" -" 'timer -i 3days sam'\n" -" (soft inode limit timer for user 'sam' is changed to 3 days)\n" +" 'timer -i 3days'\n" +" (soft inode limit timer is changed to 3 days)\n" "\n" " Changes the timeout value associated with the block limits, inode limits\n" -" and/or realtime block limits for the specified user, group, or project.\n" +" and/or realtime block limits for all users, groups, or projects on the\n" +" current filesystem.\n" " As soon as a user consumes the amount of space or number of inodes set as\n" " the soft limit, a timer is started. If the timer expires and the user is\n" " still over the soft limit, the soft limit is enforced as the hard limit.\n" @@ -94,7 +95,6 @@ timer_help(void) " However, a suffix may be used to alternatively specify minutes (m),\n" " hours (h), days (d), or weeks (w) - either the full word or the first\n" " letter of the word can be used.\n" -" The user/group/project can be specified either by name or by number.\n" "\n")); } @@ -225,8 +225,9 @@ set_project_limits( bsoft, bhard, isoft, ihard, rtbsoft, rtbhard); } +/* extract number of blocks from an ascii string */ static int -extract( +extractb( char *string, const char *prefix, int length, @@ -246,6 +247,24 @@ extract( return 0; } +/* extract number of inodes from an ascii string */ +static int +extracti( + char *string, + const char *prefix, + int length, + __uint64_t *value) +{ + char *sp, *s = string; + + if (strncmp(string, prefix, length) == 0) { + s = string + length + 1; + *value = strtoll(s, &sp, 0); + return 1; + } + return 0; +} + static int limit_f( int argc, @@ -297,17 +316,17 @@ limit_f( */ while (argc > optind + endoptions - 1) { char *s = argv[optind++]; - if (extract(s, "bsoft=", 5, bsize, ssize, &bsoft)) + if (extractb(s, "bsoft=", 5, bsize, ssize, &bsoft)) mask |= FS_DQ_BSOFT; - else if (extract(s, "bhard=", 5, bsize, ssize, &bhard)) + else if (extractb(s, "bhard=", 5, bsize, ssize, &bhard)) mask |= FS_DQ_BHARD; - else if (extract(s, "isoft=", 5, bsize, ssize, &isoft)) + else if (extracti(s, "isoft=", 5, &isoft)) mask |= FS_DQ_ISOFT; - else if (extract(s, "ihard=", 5, bsize, ssize, &ihard)) + else if (extracti(s, "ihard=", 5, &ihard)) mask |= FS_DQ_IHARD; - else if (extract(s, "rtbsoft=", 7, bsize, ssize, &rtbsoft)) + else if (extractb(s, "rtbsoft=", 7, bsize, ssize, &rtbsoft)) mask |= FS_DQ_RTBSOFT; - else if (extract(s, "rtbhard=", 7, bsize, ssize, &rtbhard)) + else if (extractb(s, "rtbhard=", 7, bsize, ssize, &rtbhard)) mask |= FS_DQ_RTBHARD; else { fprintf(stderr, _("%s: unrecognised argument %s\n"), @@ -435,7 +454,6 @@ restore_f( static void set_timer( - __uint32_t id, uint type, uint mask, char *dev, @@ -445,80 +463,27 @@ set_timer( memset(&d, 0, sizeof(d)); d.d_version = FS_DQUOT_VERSION; - d.d_id = id; d.d_flags = type; d.d_fieldmask = mask; d.d_itimer = value; d.d_btimer = value; d.d_rtbtimer = value; - if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) + if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) fprintf(stderr, _("%s: cannot set timer: %s\n"), progname, strerror(errno)); } -static void -set_user_timer( - char *name, - uint type, - uint mask, - uint value) -{ - uid_t uid = uid_from_string(name); - - if (uid == -1) - fprintf(stderr, _("%s: invalid user name: %s\n"), - progname, name); - else - set_timer(uid, type, mask, fs_path->fs_name, value); -} - -static void -set_group_timer( - char *name, - uint type, - uint mask, - uint value) -{ - gid_t gid = gid_from_string(name); - - if (gid == -1) - fprintf(stderr, _("%s: invalid group name: %s\n"), - progname, name); - else - set_timer(gid, type, mask, fs_path->fs_name, value); -} - -static void -set_project_timer( - char *name, - uint type, - uint mask, - uint value) -{ - prid_t prid = prid_from_string(name); - - if (prid == -1) - fprintf(stderr, _("%s: invalid project name: %s\n"), - progname, name); - else - set_timer(prid, type, mask, fs_path->fs_name, value); -} - static int timer_f( int argc, char **argv) { - char *name; uint value; - int c, flags = 0, type = 0, mask = 0; + int c, type = 0, mask = 0; - while ((c = getopt(argc, argv, "bdgipru")) != EOF) { + while ((c = getopt(argc, argv, "bgipru")) != EOF) { switch (c) { - case 'd': - flags |= DEFAULTS_FLAG; - break; case 'b': mask |= FS_DQ_BTIMER; break; @@ -542,20 +507,10 @@ timer_f( } } - /* - * In the usual case, we need at least 2 more arguments - - * one (or more) value and a user name/id. - * For setting defaults (-d) we don't want a user name/id. - */ - if (flags & DEFAULTS_FLAG) { - if (argc != optind + 1) - return command_usage(&timer_cmd); - } else if (argc != optind + 2) { + if (argc != optind + 1) return command_usage(&timer_cmd); - } value = cvttime(argv[optind++]); - name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++]; if (!mask) mask = FS_DQ_TIMER_MASK; @@ -563,17 +518,7 @@ timer_f( if (!type) type = XFS_USER_QUOTA; - switch (type) { - case XFS_USER_QUOTA: - set_user_timer(name, type, mask, value); - break; - case XFS_GROUP_QUOTA: - set_group_timer(name, type, mask, value); - break; - case XFS_PROJ_QUOTA: - set_project_timer(name, type, mask, value); - break; - } + set_timer(type, mask, fs_path->fs_name, value); return 0; } diff --git a/quota/free.c b/quota/free.c index 63b1fb4b16..717bffc7bb 100644 --- a/quota/free.c +++ b/quota/free.c @@ -51,7 +51,7 @@ free_help(void) " -i -- report the inode count values\n" " -r -- report the realtime block count values\n" " -h -- report in a human-readable format\n" -" -n -- suppress the header from the output\n" +" -N -- suppress the header from the output\n" "\n")); } @@ -318,7 +318,7 @@ free_f( char *fname = NULL; int c, flags = 0, form = 0, type = 0; - while ((c = getopt(argc, argv, "bf:hnir")) != EOF) { + while ((c = getopt(argc, argv, "bf:hNir")) != EOF) { switch (c) { case 'f': fname = optarg; @@ -335,7 +335,7 @@ free_f( case 'h': flags |= HUMAN_FLAG; break; - case 'n': + case 'N': flags |= NO_HEADER_FLAG; break; default: diff --git a/quota/quot.c b/quota/quot.c index 068c409707..751cb286b2 100644 --- a/quota/quot.c +++ b/quota/quot.c @@ -82,7 +82,8 @@ quot_help(void) " -b -- display number of blocks used\n" " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" -" -n -- suppress the initial header\n" +" -n -- skip identifier-to-name translations, just report IDs\n" +" -N -- suppress the initial header\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" " number (i.e. uid/gid/projid).\n" @@ -240,7 +241,8 @@ quot_report_mount_any_type( if (form & XFS_INODE_QUOTA) fprintf(fp, "%8llu ", (unsigned long long) dp->nfiles); - if ((cp = (names)(dp->id)) != NULL) + if (!(flags & NO_LOOKUP_FLAG) && + ((cp = (names)(dp->id)) != NULL)) fprintf(fp, "%-8.8s", cp); else fprintf(fp, "#%-7d", dp->id); @@ -357,7 +359,7 @@ quot_f( char *fname = NULL; int c, flags = 0, type = 0, form = 0; - while ((c = getopt(argc, argv, "abcf:hgipruv")) != EOF) { + while ((c = getopt(argc, argv, "abcf:ghinpruv")) != EOF) { switch (c) { case 'f': fname = optarg; @@ -386,6 +388,9 @@ quot_f( case 'c': flags |= HISTOGRAM_FLAG; break; + case 'n': + flags |= NO_LOOKUP_FLAG; + break; case 'v': flags |= VERBOSE_FLAG; break; diff --git a/quota/quota.c b/quota/quota.c index 8af5facc9a..8da04def59 100644 --- a/quota/quota.c +++ b/quota/quota.c @@ -53,7 +53,8 @@ quota_help(void) " -i -- display number of inodes used\n" " -r -- display number of realtime blocks used\n" " -h -- report in a human-readable format\n" -" -n -- suppress the initial header\n" +" -n -- skip identifier-to-name translations, just report IDs\n" +" -N -- suppress the initial header\n" " -v -- increase verbosity in reporting (also dumps zero values)\n" " -f -- send output to a file\n" " The (optional) user/group/project can be specified either by name or by\n" @@ -210,12 +211,13 @@ quota( static char * getusername( - uid_t uid) + uid_t uid, + int numeric) { static char buffer[32]; struct passwd *u; - if ((u = getpwuid(uid))) + if (!numeric && (u = getpwuid(uid))) return u->pw_name; snprintf(buffer, sizeof(buffer), "#%u", uid); return &buffer[0]; @@ -235,7 +237,7 @@ quota_user_type( if (name) { if (isdigit(name[0])) { id = atoi(name); - name = getusername(id); + name = getusername(id, flags & NO_LOOKUP_FLAG); } else if ((u = getpwnam(name))) { id = u->pw_uid; name = u->pw_name; @@ -246,7 +248,7 @@ quota_user_type( } } else { id = getuid(); - name = getusername(id); + name = getusername(id, flags & NO_LOOKUP_FLAG); } quota(fp, id, name, form, type, flags); @@ -254,12 +256,13 @@ quota_user_type( static char * getgroupname( - gid_t gid) + gid_t gid, + int numeric) { static char buffer[32]; struct group *g; - if ((g = getgrgid(gid))) + if (!numeric && (g = getgrgid(gid))) return g->gr_name; snprintf(buffer, sizeof(buffer), "#%u", gid); return &buffer[0]; @@ -280,7 +283,7 @@ quota_group_type( if (name) { if (isdigit(name[0])) { gid = atoi(name); - name = getgroupname(gid); + name = getgroupname(gid, flags & NO_LOOKUP_FLAG); } else { if ((g = getgrnam(name))) { gid = g->gr_gid; @@ -306,7 +309,7 @@ quota_group_type( for (i = 0; i < ngroups; i++, name = NULL) { if (!name) - name = getgroupname(gids[i]); + name = getgroupname(gids[i], flags & NO_LOOKUP_FLAG); quota(fp, gids[i], name, form, type, flags); } @@ -316,7 +319,8 @@ quota_group_type( static char * getprojectname( - prid_t prid) + prid_t prid, + int numeric) { static char buffer[32]; fs_project_t *p; @@ -346,7 +350,7 @@ quota_proj_type( if (isdigit(name[0])) { id = atoi(name); - name = getprojectname(id); + name = getprojectname(id, flags & NO_LOOKUP_FLAG); } else if ((p = getprnam(name))) { id = p->pr_prid; name = p->pr_name; @@ -389,7 +393,7 @@ quota_f( char *fname = NULL; int c, flags = 0, type = 0, form = 0; - while ((c = getopt(argc, argv, "bf:hgnipruv")) != EOF) { + while ((c = getopt(argc, argv, "bf:ghnNipruv")) != EOF) { switch (c) { case 'f': fname = optarg; @@ -416,6 +420,9 @@ quota_f( flags |= HUMAN_FLAG; break; case 'n': + flags |= NO_LOOKUP_FLAG; + break; + case 'N': flags |= NO_HEADER_FLAG; break; case 'v': diff --git a/quota/quota.h b/quota/quota.h index 818427e353..f84f116a69 100644 --- a/quota/quota.h +++ b/quota/quota.h @@ -83,6 +83,7 @@ enum { HISTOGRAM_FLAG = 0x0080, /* histogram format output */ DEFAULTS_FLAG = 0x0100, /* use value as a default */ ABSOLUTE_FLAG = 0x0200, /* absolute time, not related to now */ + NO_LOOKUP_FLAG = 0x0400, /* skip name lookups, just report ID */ }; /* diff --git a/quota/report.c b/quota/report.c index 0d297e9ee6..a32e016d71 100644 --- a/quota/report.c +++ b/quota/report.c @@ -70,7 +70,8 @@ report_help(void) " or all filesystems.\n" " -a -- report for all mounted filesystems with quota enabled\n" " -h -- report in a human-readable format\n" -" -n -- suppress the header from the output\n" +" -n -- skip identifier-to-name translations, just report IDs\n" +" -N -- suppress the header from the output\n" " -t -- terse output format, hides rows which are all zero\n" " -g -- report group usage and quota information\n" " -p -- report project usage and quota information\n" @@ -92,23 +93,38 @@ dump_file( if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) return; + if (!d.d_blk_softlimit && !d.d_blk_hardlimit && + !d.d_ino_softlimit && !d.d_ino_hardlimit && + !d.d_rtb_softlimit && !d.d_rtb_hardlimit) + return; fprintf(fp, "fs = %s\n", dev); - fprintf(fp, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n", id, - (unsigned long long)d.d_blk_softlimit, - (unsigned long long)d.d_blk_hardlimit, - (unsigned long long)d.d_ino_softlimit, - (unsigned long long)d.d_ino_hardlimit, - (unsigned long long)d.d_rtb_softlimit, - (unsigned long long)d.d_rtb_hardlimit); + /* this branch is for backward compatibility reasons */ + if (d.d_rtb_softlimit || d.d_rtb_hardlimit) + fprintf(fp, "%-10d %7llu %7llu %7llu %7llu %7llu %7llu\n", id, + (unsigned long long)d.d_blk_softlimit, + (unsigned long long)d.d_blk_hardlimit, + (unsigned long long)d.d_ino_softlimit, + (unsigned long long)d.d_ino_hardlimit, + (unsigned long long)d.d_rtb_softlimit, + (unsigned long long)d.d_rtb_hardlimit); + else + fprintf(fp, "%-10d %7llu %7llu %7llu %7llu\n", id, + (unsigned long long)d.d_blk_softlimit, + (unsigned long long)d.d_blk_hardlimit, + (unsigned long long)d.d_ino_softlimit, + (unsigned long long)d.d_ino_hardlimit); } static void dump_limits_any_type( FILE *fp, uint type, - char *dir) + char *dir, + uint lower, + uint upper) { fs_path_t *mount; + uint id; if ((mount = fs_table_lookup(dir, FS_MOUNT_POINT)) == NULL) { fprintf(stderr, "%s: cannot find mount point %s\n", @@ -116,6 +132,12 @@ dump_limits_any_type( return; } + if (upper) { + for (id = lower; id < upper; id++) + dump_file(fp, id, type, mount->fs_name); + return; + } + switch (type) { case XFS_GROUP_QUOTA: { struct group *g; @@ -151,9 +173,10 @@ dump_f( { FILE *fp; char *fname = NULL; + uint lower = 0, upper = 0; int c, type = XFS_USER_QUOTA; - while ((c = getopt(argc, argv, "f:gpu")) != EOF) { + while ((c = getopt(argc, argv, "f:gpuL:U:")) != EOF) { switch(c) { case 'f': fname = optarg; @@ -167,6 +190,12 @@ dump_f( case 'u': type = XFS_USER_QUOTA; break; + case 'L': + lower = (uint)atoi(optarg); + break; + case 'U': + upper = (uint)atoi(optarg); + break; default: return command_usage(&dump_cmd); } @@ -178,7 +207,7 @@ dump_f( if ((fp = fopen_write_secure(fname)) == NULL) return 0; - dump_limits_any_type(fp, type, fs_path->fs_dir); + dump_limits_any_type(fp, type, fs_path->fs_dir, lower, upper); if (fname) fclose(fp); @@ -369,18 +398,37 @@ report_user_mount( FILE *fp, uint form, fs_path_t *mount, + uint lower, + uint upper, uint flags) { - struct passwd *u; + struct passwd *u; + char n[MAXNAMELEN]; + uint id; + + if (upper) { /* identifier range specified */ + for (id = lower; id < upper; id++) { + snprintf(n, sizeof(n)-1, "#%u", id); + if (report_mount(fp, id, n, + form, XFS_USER_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + } else { + setpwent(); + while ((u = getpwent()) != NULL) { + if (flags & NO_LOOKUP_FLAG) + snprintf(n, sizeof(n)-1, "#%u", u->pw_uid); + else + strncpy(n, u->pw_name, sizeof(n)-1); + if (report_mount(fp, u->pw_uid, n, + form, XFS_USER_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + endpwent(); + } - setpwent(); - while ((u = getpwent()) != NULL) - if (report_mount(fp, u->pw_uid, u->pw_name, - form, XFS_USER_QUOTA, mount, flags)) - flags |= NO_HEADER_FLAG; if (flags & NO_HEADER_FLAG) fputc('\n', fp); - endpwent(); } static void @@ -388,15 +436,33 @@ report_group_mount( FILE *fp, uint form, fs_path_t *mount, + uint lower, + uint upper, uint flags) { - struct group *g; - - setgrent(); - while ((g = getgrent()) != NULL) - if (report_mount(fp, g->gr_gid, g->gr_name, - form, XFS_GROUP_QUOTA, mount, flags)) - flags |= NO_HEADER_FLAG; + struct group *g; + char n[MAXNAMELEN]; + uint id; + + if (upper) { /* identifier range specified */ + for (id = lower; id < upper; id++) { + snprintf(n, sizeof(n)-1, "#%u", id); + if (report_mount(fp, id, n, + form, XFS_GROUP_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + } else { + setgrent(); + while ((g = getgrent()) != NULL) { + if (flags & NO_LOOKUP_FLAG) + snprintf(n, sizeof(n)-1, "#%u", g->gr_gid); + else + strncpy(n, g->gr_name, sizeof(n)-1); + if (report_mount(fp, g->gr_gid, n, + form, XFS_GROUP_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + } if (flags & NO_HEADER_FLAG) fputc('\n', fp); endgrent(); @@ -407,18 +473,37 @@ report_project_mount( FILE *fp, uint form, fs_path_t *mount, + uint lower, + uint upper, uint flags) { fs_project_t *p; + char n[MAXNAMELEN]; + uint id; + + if (upper) { /* identifier range specified */ + for (id = lower; id < upper; id++) { + snprintf(n, sizeof(n)-1, "#%u", id); + if (report_mount(fp, id, n, + form, XFS_PROJ_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + } else { + setprent(); + while ((p = getprent()) != NULL) { + if (flags & NO_LOOKUP_FLAG) + snprintf(n, sizeof(n)-1, "#%u", p->pr_prid); + else + strncpy(n, p->pr_name, sizeof(n)-1); + if (report_mount(fp, p->pr_prid, n, + form, XFS_PROJ_QUOTA, mount, flags)) + flags |= NO_HEADER_FLAG; + } + endprent(); + } - setprent(); - while ((p = getprent()) != NULL) - if (report_mount(fp, p->pr_prid, p->pr_name, - form, XFS_PROJ_QUOTA, mount, flags)) - flags |= NO_HEADER_FLAG; if (flags & NO_HEADER_FLAG) fputc('\n', fp); - endprent(); } static void @@ -427,6 +512,8 @@ report_any_type( uint form, uint type, char *dir, + uint lower, + uint upper, uint flags) { fs_cursor_t cursor; @@ -435,17 +522,20 @@ report_any_type( if (type & XFS_USER_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) - report_user_mount(fp, form, mount, flags); + report_user_mount(fp, form, mount, + lower, upper, flags); } if (type & XFS_GROUP_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) - report_group_mount(fp, form, mount, flags); + report_group_mount(fp, form, mount, + lower, upper, flags); } if (type & XFS_PROJ_QUOTA) { fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); while ((mount = fs_cursor_next_entry(&cursor))) - report_project_mount(fp, form, mount, flags); + report_project_mount(fp, form, mount, + lower, upper, flags); } } @@ -455,10 +545,11 @@ report_f( char **argv) { FILE *fp = NULL; - char *fname = NULL; + char *dir, *fname = NULL; + uint lower = 0, upper = 0; int c, flags = 0, type = 0, form = 0; - while ((c = getopt(argc, argv, "abf:hgniprtu")) != EOF) { + while ((c = getopt(argc, argv, "abf:ghiL:NnprtuU:")) != EOF) { switch (c) { case 'f': fname = optarg; @@ -488,11 +579,20 @@ report_f( flags |= HUMAN_FLAG; break; case 'n': + flags |= NO_LOOKUP_FLAG; + break; + case 'N': flags |= NO_HEADER_FLAG; break; case 't': flags |= TERSE_FLAG; break; + case 'L': + lower = (uint)atoi(optarg); + break; + case 'U': + upper = (uint)atoi(optarg); + break; default: return command_usage(&report_cmd); } @@ -509,9 +609,11 @@ report_f( if (argc == optind) report_any_type(fp, form, type, (flags & ALL_MOUNTS_FLAG) ? - NULL : fs_path->fs_dir, flags); - else while (argc > optind) - report_any_type(fp, form, type, argv[optind++], flags); + NULL : fs_path->fs_dir, lower, upper, flags); + else while (argc > optind) { + dir = argv[optind++]; + report_any_type(fp, form, type, dir, lower, upper, flags); + } if (fname) fclose(fp); |