diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ufs/ufs/quota.h | 44 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 394 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vfsops.c | 16 | ||||
-rw-r--r-- | sys/ufs/ufs/ufsmount.h | 1 |
4 files changed, 417 insertions, 38 deletions
diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h index 28f4e92..ca0dcce 100644 --- a/sys/ufs/ufs/quota.h +++ b/sys/ufs/ufs/quota.h @@ -81,10 +81,14 @@ #define Q_QUOTAON 0x0100 /* enable quotas */ #define Q_QUOTAOFF 0x0200 /* disable quotas */ -#define Q_GETQUOTA 0x0300 /* get limits and usage */ -#define Q_SETQUOTA 0x0400 /* set limits and usage */ -#define Q_SETUSE 0x0500 /* set usage */ +#define Q_GETQUOTA32 0x0300 /* get limits and usage (32-bit version) */ +#define Q_SETQUOTA32 0x0400 /* set limits and usage (32-bit version) */ +#define Q_SETUSE32 0x0500 /* set usage (32-bit version) */ #define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ +#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 @@ -93,7 +97,7 @@ * the vnode for each quota file (a pointer is retained in the ufsmount * structure). */ -struct dqblk { +struct dqblk32 { u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ u_int32_t dqb_curblocks; /* current block count */ @@ -104,6 +108,30 @@ struct dqblk { int32_t dqb_itime; /* time limit for excessive files */ }; +struct dqblk64 { + u_int64_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int64_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int64_t dqb_curblocks; /* current block count */ + u_int64_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */ + u_int64_t dqb_isoftlimit; /* preferred inode limit */ + u_int64_t dqb_curinodes; /* current # allocated inodes */ + int64_t dqb_btime; /* time limit for excessive disk use */ + int64_t dqb_itime; /* time limit for excessive files */ +}; + +#define dqblk dqblk64 + +#define Q_DQHDR64_MAGIC "QUOTA64" +#define Q_DQHDR64_VERSION 0x20081104 + +struct dqhdr64 { + char dqh_magic[8]; /* Q_DQHDR64_MAGIC */ + uint32_t dqh_version; /* Q_DQHDR64_VERSION */ + uint32_t dqh_hdrlen; /* header length */ + uint32_t dqh_reclen; /* record length */ + char dqh_unused[44]; /* reserved for future extension */ +}; + #ifdef _KERNEL #include <sys/queue.h> @@ -125,7 +153,7 @@ struct dquot { u_int32_t dq_id; /* identifier this applies to */ struct ufsmount *dq_ump; /* (h) filesystem that this is taken from */ - struct dqblk dq_dqb; /* actual usage & quotas */ + struct dqblk64 dq_dqb; /* actual usage & quotas */ }; /* * Flag values. @@ -199,12 +227,16 @@ void dqinit(void); void dqrele(struct vnode *, struct dquot *); void dquninit(void); int getinoquota(struct inode *); -int getquota(struct thread *, struct mount *, u_long, int, void *); int qsync(struct mount *mp); int quotaoff(struct thread *td, struct mount *, int); int quotaon(struct thread *td, struct mount *, int, void *); +int getquota32(struct thread *, struct mount *, u_long, int, void *); +int setquota32(struct thread *, struct mount *, u_long, int, void *); +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 */ diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 2db0444..c516189 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/endian.h> #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/lock.h> @@ -59,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> +CTASSERT(sizeof(struct dqblk64) == sizeof(struct dqhdr64)); + static int unprivileged_get_quota = 0; SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_get_quota, CTLFLAG_RW, &unprivileged_get_quota, 0, @@ -73,6 +76,7 @@ static char *quotatypes[] = INITQFNAMES; static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int, int *); static int chkiqchg(struct inode *, int, struct ucred *, int, int *); +static int dqopen(struct vnode *, struct ufsmount *, int); static int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); static int dqsync(struct vnode *, struct dquot *); @@ -80,6 +84,14 @@ static void dqflush(struct vnode *); static int quotaoff1(struct thread *td, struct mount *mp, int type); static int quotaoff_inchange(struct thread *td, struct mount *mp, int type); +/* conversion functions - from_to() */ +static void dqb32_dq(const struct dqblk32 *, struct dquot *); +static void dqb64_dq(const struct dqblk64 *, struct dquot *); +static void dq_dqb32(const struct dquot *, struct dqblk32 *); +static void dq_dqb64(const struct dquot *, struct dqblk64 *); +static void dqb32_dqb64(const struct dqblk32 *, struct dqblk64 *); +static void dqb64_dqb32(const struct dqblk64 *, struct dqblk32 *); + #ifdef DIAGNOSTIC static void dqref(struct dquot *); static void chkdquot(struct inode *); @@ -90,7 +102,7 @@ static void chkdquot(struct inode *); * * This routine completely defines the semantics of quotas. * If other criterion want to be used to establish quotas, the - * MAXQUOTAS value in quotas.h should be increased, and the + * MAXQUOTAS value in quota.h should be increased, and the * additional dquots set up here. */ int @@ -496,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; @@ -522,10 +537,18 @@ 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); + VFS_UNLOCK_GIANT(vfslocked); + return (error); + } MNT_ILOCK(mp); mp->mnt_flag |= MNT_QUOTA; MNT_IUNLOCK(mp); - UFS_UNLOCK(ump); vpp = &ump->um_quotas[type]; if (*vpp != vp) @@ -734,8 +757,9 @@ quotaoff(struct thread *td, struct mount *mp, int type) /* * Q_GETQUOTA - return current values in a dqblk structure. */ -int -getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +static int +_getquota(struct thread *td, struct mount *mp, u_long id, int type, + struct dqblk64 *dqb) { struct dquot *dq; int error; @@ -766,7 +790,7 @@ getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq); if (error) return (error); - error = copyout(&dq->dq_dqb, addr, sizeof (struct dqblk)); + *dqb = dq->dq_dqb; dqrele(NULLVP, dq); return (error); } @@ -774,23 +798,21 @@ getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) /* * Q_SETQUOTA - assign an entire dqblk structure. */ -int -setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +static int +_setquota(struct thread *td, struct mount *mp, u_long id, int type, + struct dqblk64 *dqb) { struct dquot *dq; struct dquot *ndq; struct ufsmount *ump; - struct dqblk newlim; + struct dqblk64 newlim; int error; error = priv_check(td, PRIV_VFS_SETQUOTA); if (error) return (error); - ump = VFSTOUFS(mp); - error = copyin(addr, &newlim, sizeof (struct dqblk)); - if (error) - return (error); + newlim = *dqb; ndq = NODQUOT; ump = VFSTOUFS(mp); @@ -839,23 +861,21 @@ setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) /* * Q_SETUSE - set current inode and block usage. */ -int -setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +static int +_setuse(struct thread *td, struct mount *mp, u_long id, int type, + struct dqblk64 *dqb) { struct dquot *dq; struct ufsmount *ump; struct dquot *ndq; - struct dqblk usage; + struct dqblk64 usage; int error; error = priv_check(td, PRIV_UFS_SETUSE); if (error) return (error); - ump = VFSTOUFS(mp); - error = copyin(addr, &usage, sizeof (struct dqblk)); - if (error) - return (error); + usage = *dqb; ump = VFSTOUFS(mp); ndq = NODQUOT; @@ -888,6 +908,114 @@ setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) return (0); } +int +getquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk32 dqb32; + struct dqblk64 dqb64; + int error; + + error = _getquota(td, mp, id, type, &dqb64); + if (error) + return (error); + dqb64_dqb32(&dqb64, &dqb32); + error = copyout(&dqb32, addr, sizeof(dqb32)); + return (error); +} + +int +setquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk32 dqb32; + struct dqblk64 dqb64; + int error; + + error = copyin(addr, &dqb32, sizeof(dqb32)); + if (error) + return (error); + dqb32_dqb64(&dqb32, &dqb64); + error = _setquota(td, mp, id, type, &dqb64); + return (error); +} + +int +setuse32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk32 dqb32; + struct dqblk64 dqb64; + int error; + + error = copyin(addr, &dqb32, sizeof(dqb32)); + if (error) + return (error); + dqb32_dqb64(&dqb32, &dqb64); + error = _setuse(td, mp, id, type, &dqb64); + return (error); +} + +int +getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk64 dqb64; + int error; + + error = _getquota(td, mp, id, type, &dqb64); + if (error) + return (error); + error = copyout(&dqb64, addr, sizeof(dqb64)); + return (error); +} + +int +setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk64 dqb64; + int error; + + error = copyin(addr, &dqb64, sizeof(dqb64)); + if (error) + return (error); + error = _setquota(td, mp, id, type, &dqb64); + return (error); +} + +int +setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) +{ + struct dqblk64 dqb64; + int error; + + error = copyin(addr, &dqb64, sizeof(dqb64)); + if (error) + return (error); + error = _setuse(td, mp, id, type, &dqb64); + 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. */ @@ -1025,6 +1153,60 @@ dqhashfind(struct dqhash *dqh, u_long id, struct vnode *dqvp) } /* + * Determine the quota file type. + * + * A 32-bit quota file is simply an array of struct dqblk32. + * + * A 64-bit quota file is a struct dqhdr64 followed by an array of struct + * dqblk64. The header contains various magic bits which allow us to be + * reasonably confident that it is indeeda 64-bit quota file and not just + * a 32-bit quota file that just happens to "look right". + * + */ +static int +dqopen(struct vnode *vp, struct ufsmount *ump, int type) +{ + struct dqhdr64 dqh; + struct iovec aiov; + struct uio auio; + int error, vfslocked; + + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = &dqh; + aiov.iov_len = sizeof(dqh); + auio.uio_resid = sizeof(dqh); + auio.uio_offset = 0; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = (struct thread *)0; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + error = VOP_READ(vp, &auio, 0, ump->um_cred[type]); + VFS_UNLOCK_GIANT(vfslocked); + + if (error != 0) + return (error); + if (auio.uio_resid > 0) { + /* assume 32 bits */ + 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)) { + /* XXX: what if the magic matches, but the sizes are wrong? */ + ump->um_qflags[type] |= QTF_64BIT; + } else { + ump->um_qflags[type] &= ~QTF_64BIT; + } + UFS_UNLOCK(ump); + + return (0); +} + +/* * Obtain a dquot structure for the specified identifier and quota file * reading the information from the file if necessary. */ @@ -1032,6 +1214,8 @@ static int dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, struct dquot **dqp) { + uint8_t buf[sizeof(struct dqblk64)]; + off_t base, recsize; struct dquot *dq, *dq1; struct dqhash *dqh; struct vnode *dqvp; @@ -1121,8 +1305,7 @@ hfound: DQI_LOCK(dq); if (numdquot < desireddquot) { numdquot++; DQH_UNLOCK(); - dq1 = (struct dquot *)malloc(sizeof *dq, M_DQUOT, - M_WAITOK | M_ZERO); + dq1 = malloc(sizeof *dq1, M_DQUOT, M_WAITOK | M_ZERO); mtx_init(&dq1->dq_lock, "dqlock", NULL, MTX_DEF); DQH_LOCK(); /* @@ -1169,20 +1352,37 @@ hfound: DQI_LOCK(dq); DQREF(dq); DQH_UNLOCK(); + /* + * Read the requested quota record from the quota file, performing + * any necessary conversions. + */ + if (ump->um_qflags[type] & QTF_64BIT) { + recsize = sizeof(struct dqblk64); + base = sizeof(struct dqhdr64); + } else { + recsize = sizeof(struct dqblk32); + base = 0; + } auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - aiov.iov_base = &dq->dq_dqb; - aiov.iov_len = sizeof (struct dqblk); - auio.uio_resid = sizeof (struct dqblk); - auio.uio_offset = (off_t)id * sizeof (struct dqblk); + aiov.iov_base = buf; + aiov.iov_len = recsize; + auio.uio_resid = recsize; + auio.uio_offset = base + id * recsize; auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_READ; auio.uio_td = (struct thread *)0; vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]); - if (auio.uio_resid == sizeof(struct dqblk) && error == 0) - bzero(&dq->dq_dqb, sizeof(struct dqblk)); + if (auio.uio_resid == recsize && error == 0) { + bzero(&dq->dq_dqb, sizeof(dq->dq_dqb)); + } else { + if (ump->um_qflags[type] & QTF_64BIT) + dqb64_dq((struct dqblk64 *)buf, dq); + else + dqb32_dq((struct dqblk32 *)buf, dq); + } if (dqvplocked) vput(dqvp); else @@ -1293,6 +1493,8 @@ sync: static int dqsync(struct vnode *vp, struct dquot *dq) { + uint8_t buf[sizeof(struct dqblk64)]; + off_t base, recsize; struct vnode *dqvp; struct iovec aiov; struct uio auio; @@ -1339,12 +1541,26 @@ dqsync(struct vnode *vp, struct dquot *dq) dq->dq_flags |= DQ_LOCK; DQI_UNLOCK(dq); + /* + * Write the quota record to the quota file, performing any + * necessary conversions. See dqget() for additional details. + */ + if (ump->um_qflags[dq->dq_type] & QTF_64BIT) { + dq_dqb64(dq, (struct dqblk64 *)buf); + recsize = sizeof(struct dqblk64); + base = sizeof(struct dqhdr64); + } else { + dq_dqb32(dq, (struct dqblk32 *)buf); + recsize = sizeof(struct dqblk32); + base = 0; + } + auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - aiov.iov_base = &dq->dq_dqb; - aiov.iov_len = sizeof (struct dqblk); - auio.uio_resid = sizeof (struct dqblk); - auio.uio_offset = (off_t)dq->dq_id * sizeof (struct dqblk); + aiov.iov_base = buf; + aiov.iov_len = recsize; + auio.uio_resid = recsize; + auio.uio_offset = base + dq->dq_id * recsize; auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_td = (struct thread *)0; @@ -1357,7 +1573,8 @@ dqsync(struct vnode *vp, struct dquot *dq) DQI_LOCK(dq); DQI_WAKEUP(dq); dq->dq_flags &= ~DQ_MOD; -out: DQI_UNLOCK(dq); +out: + DQI_UNLOCK(dq); vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); if (vp != dqvp) vput(dqvp); @@ -1396,3 +1613,116 @@ dqflush(struct vnode *vp) } DQH_UNLOCK(); } + +/* + * 32-bit / 64-bit conversion functions. + * + * 32-bit quota records are stored in native byte order. Attention must + * be paid to overflow issues. + * + * 64-bit quota records are stored in network byte order. + */ + +#define CLIP32(u64) (u64 > UINT32_MAX ? UINT32_MAX : (uint32_t)u64) + +/* + * Convert 32-bit host-order structure to dquot. + */ +static void +dqb32_dq(const struct dqblk32 *dqb32, struct dquot *dq) +{ + + dq->dq_bhardlimit = dqb32->dqb_bhardlimit; + dq->dq_bsoftlimit = dqb32->dqb_bsoftlimit; + dq->dq_curblocks = dqb32->dqb_curblocks; + dq->dq_ihardlimit = dqb32->dqb_ihardlimit; + dq->dq_isoftlimit = dqb32->dqb_isoftlimit; + dq->dq_curinodes = dqb32->dqb_curinodes; + dq->dq_btime = dqb32->dqb_btime; + dq->dq_itime = dqb32->dqb_itime; +} + +/* + * Convert 64-bit network-order structure to dquot. + */ +static void +dqb64_dq(const struct dqblk64 *dqb64, struct dquot *dq) +{ + + dq->dq_bhardlimit = be64toh(dqb64->dqb_bhardlimit); + dq->dq_bsoftlimit = be64toh(dqb64->dqb_bsoftlimit); + dq->dq_curblocks = be64toh(dqb64->dqb_curblocks); + dq->dq_ihardlimit = be64toh(dqb64->dqb_ihardlimit); + dq->dq_isoftlimit = be64toh(dqb64->dqb_isoftlimit); + dq->dq_curinodes = be64toh(dqb64->dqb_curinodes); + dq->dq_btime = be64toh(dqb64->dqb_btime); + dq->dq_itime = be64toh(dqb64->dqb_itime); +} + +/* + * Convert dquot to 32-bit host-order structure. + */ +static void +dq_dqb32(const struct dquot *dq, struct dqblk32 *dqb32) +{ + + dqb32->dqb_bhardlimit = CLIP32(dq->dq_bhardlimit); + dqb32->dqb_bsoftlimit = CLIP32(dq->dq_bsoftlimit); + dqb32->dqb_curblocks = CLIP32(dq->dq_curblocks); + dqb32->dqb_ihardlimit = CLIP32(dq->dq_ihardlimit); + dqb32->dqb_isoftlimit = CLIP32(dq->dq_isoftlimit); + dqb32->dqb_curinodes = CLIP32(dq->dq_curinodes); + dqb32->dqb_btime = CLIP32(dq->dq_btime); + dqb32->dqb_itime = CLIP32(dq->dq_itime); +} + +/* + * Convert dquot to 64-bit network-order structure. + */ +static void +dq_dqb64(const struct dquot *dq, struct dqblk64 *dqb64) +{ + + dqb64->dqb_bhardlimit = htobe64(dq->dq_bhardlimit); + dqb64->dqb_bsoftlimit = htobe64(dq->dq_bsoftlimit); + dqb64->dqb_curblocks = htobe64(dq->dq_curblocks); + dqb64->dqb_ihardlimit = htobe64(dq->dq_ihardlimit); + dqb64->dqb_isoftlimit = htobe64(dq->dq_isoftlimit); + dqb64->dqb_curinodes = htobe64(dq->dq_curinodes); + dqb64->dqb_btime = htobe64(dq->dq_btime); + dqb64->dqb_itime = htobe64(dq->dq_itime); +} + +/* + * Convert 64-bit host-order structure to 32-bit host-order structure. + */ +static void +dqb64_dqb32(const struct dqblk64 *dqb64, struct dqblk32 *dqb32) +{ + + dqb32->dqb_bhardlimit = CLIP32(dqb64->dqb_bhardlimit); + dqb32->dqb_bsoftlimit = CLIP32(dqb64->dqb_bsoftlimit); + dqb32->dqb_curblocks = CLIP32(dqb64->dqb_curblocks); + dqb32->dqb_ihardlimit = CLIP32(dqb64->dqb_ihardlimit); + dqb32->dqb_isoftlimit = CLIP32(dqb64->dqb_isoftlimit); + dqb32->dqb_curinodes = CLIP32(dqb64->dqb_curinodes); + dqb32->dqb_btime = CLIP32(dqb64->dqb_btime); + dqb32->dqb_itime = CLIP32(dqb64->dqb_itime); +} + +/* + * Convert 32-bit host-order structure to 64-bit host-order structure. + */ +static void +dqb32_dqb64(const struct dqblk32 *dqb32, struct dqblk64 *dqb64) +{ + + dqb64->dqb_bhardlimit = dqb32->dqb_bhardlimit; + dqb64->dqb_bsoftlimit = dqb32->dqb_bsoftlimit; + dqb64->dqb_curblocks = dqb32->dqb_curblocks; + dqb64->dqb_ihardlimit = dqb32->dqb_ihardlimit; + dqb64->dqb_isoftlimit = dqb32->dqb_isoftlimit; + dqb64->dqb_curinodes = dqb32->dqb_curinodes; + dqb64->dqb_btime = dqb32->dqb_btime; + dqb64->dqb_itime = dqb32->dqb_itime; +} diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index f6b6b1e..0eeb14f 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -127,6 +127,18 @@ ufs_quotactl(mp, cmds, id, arg) error = quotaoff(td, mp, type); break; + case Q_SETQUOTA32: + error = setquota32(td, mp, id, type, arg); + break; + + case Q_SETUSE32: + error = setuse32(td, mp, id, type, arg); + break; + + case Q_GETQUOTA32: + error = getquota32(td, mp, id, type, arg); + break; + case Q_SETQUOTA: error = setquota(td, mp, id, type, arg); break; @@ -139,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; diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h index 3f356b1..d566917 100644 --- a/sys/ufs/ufs/ufsmount.h +++ b/sys/ufs/ufs/ufsmount.h @@ -129,6 +129,7 @@ struct ufsmount { */ #define QTF_OPENING 0x01 /* Q_QUOTAON in progress */ #define QTF_CLOSING 0x02 /* Q_QUOTAOFF in progress */ +#define QTF_64BIT 0x04 /* 64-bit quota file */ /* Convert mount ptr to ufsmount ptr. */ #define VFSTOUFS(mp) ((struct ufsmount *)((mp)->mnt_data)) |