MFC: quotacheck.c 1.27 - 1.29
Quota system cleanup.
This commit is contained in:
parent
33c1d45249
commit
1843e9e481
@ -115,10 +115,9 @@ int gflag; /* check group quotas */
|
||||
int uflag; /* check user quotas */
|
||||
int vflag; /* verbose */
|
||||
int fi; /* open disk file descriptor */
|
||||
u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
|
||||
|
||||
struct fileusage *
|
||||
addid(u_long, int, char *);
|
||||
addid(u_long, int, char *, char *);
|
||||
char *blockcheck(char *);
|
||||
void bread(ufs2_daddr_t, char *, long);
|
||||
extern int checkfstab(int, int, void * (*)(struct fstab *),
|
||||
@ -133,6 +132,7 @@ struct fileusage *
|
||||
lookup(u_long, int);
|
||||
void *needchk(struct fstab *);
|
||||
int oneof(char *, char*[], int);
|
||||
void printchanges(char *, int, struct dqblk *, struct fileusage *, u_long);
|
||||
void setinodebuf(ino_t);
|
||||
int update(char *, char *, int);
|
||||
void usage(void);
|
||||
@ -183,13 +183,15 @@ main(argc, argv)
|
||||
if (gflag) {
|
||||
setgrent();
|
||||
while ((gr = getgrent()) != NULL)
|
||||
(void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
|
||||
(void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name,
|
||||
NULL);
|
||||
endgrent();
|
||||
}
|
||||
if (uflag) {
|
||||
setpwent();
|
||||
while ((pw = getpwent()) != NULL)
|
||||
(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
|
||||
(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name,
|
||||
NULL);
|
||||
endpwent();
|
||||
}
|
||||
/*
|
||||
@ -271,8 +273,9 @@ chkquota(fsname, mntpt, qnp)
|
||||
struct fileusage *fup;
|
||||
union dinode *dp;
|
||||
int cg, i, mode, errs = 0;
|
||||
ino_t ino, inosused;
|
||||
ino_t ino, inosused, userino = 0, groupino = 0;
|
||||
char *cp;
|
||||
struct stat sb;
|
||||
|
||||
if ((fi = open(fsname, O_RDONLY, 0)) < 0) {
|
||||
warn("%s", fsname);
|
||||
@ -287,6 +290,14 @@ chkquota(fsname, mntpt, qnp)
|
||||
(void)printf("%s", qfextension[GRPQUOTA]);
|
||||
(void)printf(" quotas for %s (%s)\n", fsname, mntpt);
|
||||
}
|
||||
if (qnp->flags & HASUSR) {
|
||||
if (stat(qnp->usrqfname, &sb) == 0)
|
||||
userino = sb.st_ino;
|
||||
}
|
||||
if (qnp->flags & HASGRP) {
|
||||
if (stat(qnp->grpqfname, &sb) == 0)
|
||||
groupino = sb.st_ino;
|
||||
}
|
||||
sync();
|
||||
dev_bsize = 1;
|
||||
for (i = 0; sblock_try[i] != -1; i++) {
|
||||
@ -341,9 +352,37 @@ chkquota(fsname, mntpt, qnp)
|
||||
if ((dp = getnextinode(ino)) == NULL || ino < ROOTINO ||
|
||||
(mode = DIP(dp, di_mode) & IFMT) == 0)
|
||||
continue;
|
||||
/*
|
||||
* XXX: Do not account for UIDs or GIDs that appear
|
||||
* to be negative to prevent generating 100GB+
|
||||
* quota files.
|
||||
*/
|
||||
if ((int)DIP(dp, di_uid) < 0 ||
|
||||
(int)DIP(dp, di_gid) < 0) {
|
||||
if (vflag) {
|
||||
if (aflag)
|
||||
(void)printf("%s: ", mntpt);
|
||||
(void)printf("out of range UID/GID (%u/%u) ino=%u\n",
|
||||
DIP(dp, di_uid), DIP(dp,di_gid),
|
||||
ino);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not account for file system snapshot files
|
||||
* or the actual quota data files to be consistent
|
||||
* with how they are handled inside the kernel.
|
||||
*/
|
||||
#ifdef SF_SNAPSHOT
|
||||
if (DIP(dp, di_flags) & SF_SNAPSHOT)
|
||||
continue;
|
||||
#endif
|
||||
if (ino == userino || ino == groupino)
|
||||
continue;
|
||||
if (qnp->flags & HASGRP) {
|
||||
fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA,
|
||||
(char *)0);
|
||||
(char *)0, mntpt);
|
||||
fup->fu_curinodes++;
|
||||
if (mode == IFREG || mode == IFDIR ||
|
||||
mode == IFLNK)
|
||||
@ -351,7 +390,7 @@ chkquota(fsname, mntpt, qnp)
|
||||
}
|
||||
if (qnp->flags & HASUSR) {
|
||||
fup = addid((u_long)DIP(dp, di_uid), USRQUOTA,
|
||||
(char *)0);
|
||||
(char *)0, mntpt);
|
||||
fup->fu_curinodes++;
|
||||
if (mode == IFREG || mode == IFDIR ||
|
||||
mode == IFLNK)
|
||||
@ -378,9 +417,11 @@ update(fsname, quotafile, type)
|
||||
{
|
||||
struct fileusage *fup;
|
||||
FILE *qfi, *qfo;
|
||||
u_long id, lastid;
|
||||
u_long id, lastid, highid = 0;
|
||||
off_t offset;
|
||||
int i;
|
||||
struct dqblk dqbuf;
|
||||
struct stat sb;
|
||||
static int warned = 0;
|
||||
static struct dqblk zerodqbuf;
|
||||
static struct fileusage zerofileusage;
|
||||
@ -409,32 +450,40 @@ update(fsname, quotafile, type)
|
||||
(void)printf("*** Warning: %s\n",
|
||||
"Quotas are not compiled into this kernel");
|
||||
}
|
||||
for (lastid = highid[type], id = 0, offset = 0; id <= lastid;
|
||||
if (fstat(fileno(qfi), &sb) < 0) {
|
||||
warn("Cannot fstat quota file %s\n", quotafile);
|
||||
(void) fclose(qfo);
|
||||
(void) fclose(qfi);
|
||||
return (1);
|
||||
}
|
||||
if ((sb.st_size % sizeof(struct dqblk)) != 0)
|
||||
warn("%s size is not a multiple of dqblk\n", quotafile);
|
||||
|
||||
/*
|
||||
* Scan the on-disk quota file and record any usage changes.
|
||||
*/
|
||||
|
||||
if (sb.st_size != 0)
|
||||
lastid = (sb.st_size / sizeof(struct dqblk)) - 1;
|
||||
else
|
||||
lastid = 0;
|
||||
for (id = 0, offset = 0; id <= lastid;
|
||||
id++, offset += sizeof(struct dqblk)) {
|
||||
if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0)
|
||||
dqbuf = zerodqbuf;
|
||||
if ((fup = lookup(id, type)) == 0)
|
||||
if ((fup = lookup(id, type)) == NULL)
|
||||
fup = &zerofileusage;
|
||||
if (fup->fu_curinodes || fup->fu_curblocks ||
|
||||
dqbuf.dqb_bsoftlimit || dqbuf.dqb_bhardlimit ||
|
||||
dqbuf.dqb_isoftlimit || dqbuf.dqb_ihardlimit)
|
||||
highid = id;
|
||||
if (dqbuf.dqb_curinodes == fup->fu_curinodes &&
|
||||
dqbuf.dqb_curblocks == fup->fu_curblocks) {
|
||||
fup->fu_curinodes = 0;
|
||||
fup->fu_curblocks = 0;
|
||||
continue;
|
||||
}
|
||||
if (vflag) {
|
||||
if (aflag)
|
||||
printf("%s: ", fsname);
|
||||
printf("%-8s fixed:", fup->fu_name);
|
||||
if (dqbuf.dqb_curinodes != fup->fu_curinodes)
|
||||
(void)printf("\tinodes %lu -> %lu",
|
||||
(u_long)dqbuf.dqb_curinodes,
|
||||
(u_long)fup->fu_curinodes);
|
||||
if (dqbuf.dqb_curblocks != fup->fu_curblocks)
|
||||
(void)printf("\tblocks %lu -> %lu",
|
||||
(u_long)dqbuf.dqb_curblocks,
|
||||
(u_long)fup->fu_curblocks);
|
||||
(void)printf("\n");
|
||||
}
|
||||
printchanges(fsname, type, &dqbuf, fup, id);
|
||||
/*
|
||||
* Reset time limit if have a soft limit and were
|
||||
* previously under it, but are now over it.
|
||||
@ -449,7 +498,7 @@ update(fsname, quotafile, type)
|
||||
dqbuf.dqb_itime = 0;
|
||||
dqbuf.dqb_curinodes = fup->fu_curinodes;
|
||||
dqbuf.dqb_curblocks = fup->fu_curblocks;
|
||||
if (fseek(qfo, offset, SEEK_SET) < 0) {
|
||||
if (fseeko(qfo, offset, SEEK_SET) < 0) {
|
||||
warn("%s: seek failed", quotafile);
|
||||
return(1);
|
||||
}
|
||||
@ -459,10 +508,41 @@ update(fsname, quotafile, type)
|
||||
fup->fu_curinodes = 0;
|
||||
fup->fu_curblocks = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the hash table looking for ids with non-zero usage
|
||||
* that are not currently recorded in the quota file. E.g.
|
||||
* ids that are past the end of the current file.
|
||||
*/
|
||||
|
||||
for (i = 0; i < FUHASH; i++) {
|
||||
for (fup = fuhead[type][i]; fup != NULL; fup = fup->fu_next) {
|
||||
if (fup->fu_id <= lastid)
|
||||
continue;
|
||||
if (fup->fu_curinodes == 0 && fup->fu_curblocks == 0)
|
||||
continue;
|
||||
bzero(&dqbuf, sizeof(struct dqblk));
|
||||
if (fup->fu_id > highid)
|
||||
highid = fup->fu_id;
|
||||
printchanges(fsname, type, &dqbuf, fup, id);
|
||||
dqbuf.dqb_curinodes = fup->fu_curinodes;
|
||||
dqbuf.dqb_curblocks = fup->fu_curblocks;
|
||||
offset = (off_t)fup->fu_id * sizeof(struct dqblk);
|
||||
if (fseeko(qfo, offset, SEEK_SET) < 0) {
|
||||
warn("%s: seek failed", quotafile);
|
||||
return(1);
|
||||
}
|
||||
fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo);
|
||||
(void) quotactl(fsname, QCMD(Q_SETUSE, type), id,
|
||||
(caddr_t)&dqbuf);
|
||||
fup->fu_curinodes = 0;
|
||||
fup->fu_curblocks = 0;
|
||||
}
|
||||
}
|
||||
fclose(qfi);
|
||||
fflush(qfo);
|
||||
ftruncate(fileno(qfo),
|
||||
(((off_t)highid[type] + 1) * sizeof(struct dqblk)));
|
||||
(((off_t)highid + 1) * sizeof(struct dqblk)));
|
||||
fclose(qfo);
|
||||
return (0);
|
||||
}
|
||||
@ -560,10 +640,11 @@ lookup(id, type)
|
||||
* Add a new file usage id if it does not already exist.
|
||||
*/
|
||||
struct fileusage *
|
||||
addid(id, type, name)
|
||||
addid(id, type, name, fsname)
|
||||
u_long id;
|
||||
int type;
|
||||
char *name;
|
||||
char *fsname;
|
||||
{
|
||||
struct fileusage *fup, **fhp;
|
||||
int len;
|
||||
@ -573,22 +654,23 @@ addid(id, type, name)
|
||||
if (name)
|
||||
len = strlen(name);
|
||||
else
|
||||
len = 10;
|
||||
len = 0;
|
||||
if ((fup = calloc(1, sizeof(*fup) + len)) == NULL)
|
||||
errx(1, "calloc failed");
|
||||
fhp = &fuhead[type][id & (FUHASH - 1)];
|
||||
fup->fu_next = *fhp;
|
||||
*fhp = fup;
|
||||
fup->fu_id = id;
|
||||
if (id > highid[type])
|
||||
highid[type] = id;
|
||||
if (name)
|
||||
bcopy(name, fup->fu_name, len + 1);
|
||||
else {
|
||||
(void)sprintf(fup->fu_name, "%lu", id);
|
||||
if (vflag)
|
||||
if (vflag) {
|
||||
if (aflag && fsname != NULL)
|
||||
(void)printf("%s: ", fsname);
|
||||
printf("unknown %cid: %lu\n",
|
||||
type == USRQUOTA ? 'u' : 'g', id);
|
||||
}
|
||||
}
|
||||
return (fup);
|
||||
}
|
||||
@ -695,3 +777,46 @@ bread(bno, buf, cnt)
|
||||
read(fi, buf, cnt) != cnt)
|
||||
errx(1, "bread failed on block %ld", (long)bno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display updated block and i-node counts.
|
||||
*/
|
||||
void
|
||||
printchanges(fsname, type, dp, fup, id)
|
||||
char *fsname;
|
||||
int type;
|
||||
struct dqblk *dp;
|
||||
struct fileusage *fup;
|
||||
u_long id;
|
||||
{
|
||||
if (!vflag)
|
||||
return;
|
||||
if (aflag)
|
||||
(void)printf("%s: ", fsname);
|
||||
if (fup->fu_name[0] == '\0')
|
||||
(void)printf("%-8lu fixed ", id);
|
||||
else
|
||||
(void)printf("%-8s fixed ", fup->fu_name);
|
||||
switch (type) {
|
||||
|
||||
case GRPQUOTA:
|
||||
(void)printf("(group):");
|
||||
break;
|
||||
|
||||
case USRQUOTA:
|
||||
(void)printf("(user): ");
|
||||
break;
|
||||
|
||||
default:
|
||||
(void)printf("(unknown quota type %d)", type);
|
||||
break;
|
||||
}
|
||||
if (dp->dqb_curinodes != fup->fu_curinodes)
|
||||
(void)printf("\tinodes %lu -> %lu", (u_long)dp->dqb_curinodes,
|
||||
(u_long)fup->fu_curinodes);
|
||||
if (dp->dqb_curblocks != fup->fu_curblocks)
|
||||
(void)printf("\tblocks %lu -> %lu",
|
||||
(u_long)dp->dqb_curblocks,
|
||||
(u_long)fup->fu_curblocks);
|
||||
(void)printf("\n");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user