Debugging nits found while testing the new 64-bit quota code.

This commit is contained in:
Kirk McKusick 2010-03-16 06:12:30 +00:00
parent 1a0fda2b54
commit 516ad57b74
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/quota64/; revision=205207
7 changed files with 80 additions and 24 deletions

View File

@ -84,7 +84,7 @@ and group identifiers (GRPQUOTA).
The
.Dq ufs
specific commands are:
.Bl -tag -width Q_QUOTAOFFxx
.Bl -tag -width Q_GETQUOTASIZEx
.It Dv Q_QUOTAON
Enable disk quotas for the file system specified by
.Fa path .
@ -110,6 +110,17 @@ and
.Fa id
arguments are unused.
Only the super-user may turn quotas off.
.It Dv Q_GETQUOTASIZE
Get the wordsize used to represent the quotas for the user or group
(as determined by the command type).
Possible values are 32 for the old-style quota file
and 64 for the new-style quota file.
The
.Fa addr
argument is a pointer to an integer into which the size is stored.
The identifier
.Fa id
is not used.
.It Dv Q_GETQUOTA
Get disk quota limits and current usage for the user or group
(as determined by the command type) with identifier
@ -177,9 +188,11 @@ The
argument
or the command type is invalid.
In
.Dv Q_GETQUOTA
and
.Dv Q_GETQUOTASIZE ,
.Dv Q_GETQUOTA ,
.Dv Q_SETQUOTA ,
and
.Dv Q_SETUSE ,
quotas are not currently enabled for this file system.
.Pp
The
@ -208,7 +221,8 @@ Too many symbolic links were encountered in translating a pathname.
.It Bq Er EROFS
In
.Dv Q_QUOTAON ,
the quota file resides on a read-only file system.
either the file system on which quotas are to be enabled is mounted read-only
or the quota file resides on a read-only file system.
.It Bq Er EIO
An
.Tn I/O

View File

@ -129,11 +129,9 @@ quota_open(struct fstab *fs, int quotatype, int openflags)
goto error;
qf->dev = st.st_dev;
serrno = hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname));
qcmd = QCMD(Q_GETQUOTA, quotatype);
if (quotactl(fs->fs_file, qcmd, 0, &dqh) == 0) {
qf->wordsize = 64;
qcmd = QCMD(Q_GETQUOTASIZE, quotatype);
if (quotactl(qf->fsname, qcmd, 0, &qf->wordsize) == 0)
return (qf);
}
if (serrno == 0) {
errno = EOPNOTSUPP;
goto error;
@ -250,18 +248,22 @@ int
quota_maxid(struct quotafile *qf)
{
struct stat st;
int maxid;
if (stat(qf->qfname, &st) < 0)
return (0);
switch (qf->wordsize) {
case 32:
return (st.st_size / sizeof(struct dqblk32) - 1);
maxid = st.st_size / sizeof(struct dqblk32) - 1;
break;
case 64:
return (st.st_size / sizeof(struct dqblk64) - 2);
maxid = st.st_size / sizeof(struct dqblk64) - 2;
break;
default:
return (0);
maxid = 0;
break;
}
/* not reached */
return (maxid > 0 ? maxid : 0);
}
static int
@ -395,10 +397,6 @@ quota_write_usage(struct quotafile *qf, struct dqblk *dqb, int id)
struct dqblk dqbuf;
int qcmd;
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (qf->fd == -1) {
qcmd = QCMD(Q_SETUSE, qf->quotatype);
return (quotactl(qf->fsname, qcmd, id, dqb));
@ -406,6 +404,10 @@ quota_write_usage(struct quotafile *qf, struct dqblk *dqb, int id)
/*
* Have to do read-modify-write of quota in file.
*/
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (quota_read(qf, &dqbuf, id) != 0)
return (-1);
/*
@ -443,10 +445,6 @@ quota_write_limits(struct quotafile *qf, struct dqblk *dqb, int id)
struct dqblk dqbuf;
int qcmd;
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (qf->fd == -1) {
qcmd = QCMD(Q_SETQUOTA, qf->quotatype);
return (quotactl(qf->fsname, qcmd, id, dqb));
@ -454,6 +452,10 @@ quota_write_limits(struct quotafile *qf, struct dqblk *dqb, int id)
/*
* Have to do read-modify-write of quota in file.
*/
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (quota_read(qf, &dqbuf, id) != 0)
return (-1);
/*

View File

@ -88,6 +88,7 @@
#define Q_GETQUOTA 0x0700 /* get limits and usage (64-bit version) */
#define Q_SETQUOTA 0x0800 /* set limits and usage (64-bit version) */
#define Q_SETUSE 0x0900 /* set usage (64-bit version) */
#define Q_GETQUOTASIZE 0x0A00 /* get bit-size of quota file fields */
/*
* The following structure defines the format of the disk quota file
@ -235,6 +236,7 @@ int setuse32(struct thread *, struct mount *, u_long, int, void *);
int getquota(struct thread *, struct mount *, u_long, int, void *);
int setquota(struct thread *, struct mount *, u_long, int, void *);
int setuse(struct thread *, struct mount *, u_long, int, void *);
int getquotasize(struct thread *, struct mount *, u_long, int, void *);
vfs_quotactl_t ufs_quotactl;
#else /* !_KERNEL */

View File

@ -508,6 +508,9 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname)
if (error)
return (error);
if (mp->mnt_flag & MNT_RDONLY)
return (EROFS);
ump = VFSTOUFS(mp);
dq = NODQUOT;
@ -534,7 +537,9 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname)
return (EALREADY);
}
ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING;
UFS_UNLOCK(ump);
if ((error = dqopen(vp, ump, type)) != 0) {
UFS_LOCK(ump);
ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING);
UFS_UNLOCK(ump);
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
@ -544,7 +549,6 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname)
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_QUOTA;
MNT_IUNLOCK(mp);
UFS_UNLOCK(ump);
vpp = &ump->um_quotas[type];
if (*vpp != vp)
@ -988,6 +992,30 @@ setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
return (error);
}
/*
* Q_GETQUOTASIZE - get bit-size of quota file fields
*/
int
getquotasize(struct thread *td, struct mount *mp, u_long id, int type,
void *sizep)
{
struct ufsmount *ump = VFSTOUFS(mp);
int bitsize;
UFS_LOCK(ump);
if (ump->um_quotas[type] == NULLVP ||
(ump->um_qflags[type] & QTF_CLOSING)) {
UFS_UNLOCK(ump);
return (EINVAL);
}
if ((ump->um_qflags[type] & QTF_64BIT) != 0)
bitsize = 64;
else
bitsize = 32;
UFS_UNLOCK(ump);
return (copyout(&bitsize, sizep, sizeof(int)));
}
/*
* Q_SYNC - sync quota files to disk.
*/
@ -1163,12 +1191,17 @@ dqopen(struct vnode *vp, struct ufsmount *ump, int type)
return (0);
}
UFS_LOCK(ump);
if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) == 0 &&
be32toh(dqh.dqh_version) == Q_DQHDR64_VERSION &&
be32toh(dqh.dqh_hdrlen) == (uint32_t)sizeof(struct dqhdr64) &&
be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64))
be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) {
/* XXX: what if the magic matches, but the sizes are wrong? */
ump->um_qflags[type] |= QTF_64BIT;
/* XXX: what if the magic matches, but the sizes are wrong? */
} else {
ump->um_qflags[type] &= ~QTF_64BIT;
}
UFS_UNLOCK(ump);
return (0);
}

View File

@ -151,6 +151,10 @@ ufs_quotactl(mp, cmds, id, arg)
error = getquota(td, mp, id, type, arg);
break;
case Q_GETQUOTASIZE:
error = getquotasize(td, mp, id, type, arg);
break;
case Q_SYNC:
error = qsync(mp);
break;

View File

@ -3,6 +3,7 @@
PROG= quota
BINOWN= root
BINMODE=4555
DPADD= ${LIBRPCSVC} ${LIBUTIL}
LDADD= -lrpcsvc -lutil

View File

@ -224,7 +224,7 @@ repquota(struct fstab *fs, int type)
printf("User%*s used soft hard grace used soft hard grace\n",
max(MAXLOGNAME - 1, 10), " ");
maxid = quota_maxid(qf);
for (id = 0; id < maxid; id++) {
for (id = 0; id <= maxid; id++) {
if (quota_read(qf, &dqbuf, id) != 0)
break;
if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)