Changeset View
Changeset View
Standalone View
Standalone View
sys/ufs/ufs/ufs_quota.c
Show First 20 Lines • Show All 486 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Code to process quotactl commands. | * Code to process quotactl commands. | ||||
*/ | */ | ||||
/* | /* | ||||
* Q_QUOTAON - set up a quota file for a particular filesystem. | * Q_QUOTAON - set up a quota file for a particular filesystem. | ||||
*/ | */ | ||||
int | int | ||||
quotaon(struct thread *td, struct mount *mp, int type, void *fname) | quotaon(struct thread *td, struct mount *mp, int type, void *fname, | ||||
bool *mp_busy) | |||||
{ | { | ||||
struct ufsmount *ump; | struct ufsmount *ump; | ||||
struct vnode *vp, **vpp; | struct vnode *vp, **vpp; | ||||
struct vnode *mvp; | struct vnode *mvp; | ||||
struct dquot *dq; | struct dquot *dq; | ||||
int error, flags; | int error, flags; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
error = priv_check(td, PRIV_UFS_QUOTAON); | error = priv_check(td, PRIV_UFS_QUOTAON); | ||||
if (error != 0) { | if (error != 0) | ||||
vfs_unbusy(mp); | |||||
return (error); | return (error); | ||||
} | |||||
if ((mp->mnt_flag & MNT_RDONLY) != 0) { | if ((mp->mnt_flag & MNT_RDONLY) != 0) | ||||
vfs_unbusy(mp); | |||||
return (EROFS); | return (EROFS); | ||||
} | |||||
ump = VFSTOUFS(mp); | ump = VFSTOUFS(mp); | ||||
dq = NODQUOT; | dq = NODQUOT; | ||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td); | NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td); | ||||
flags = FREAD | FWRITE; | flags = FREAD | FWRITE; | ||||
vfs_ref(mp); | vfs_ref(mp); | ||||
KASSERT(*mp_busy, ("%s called without busied mount", __func__)); | |||||
vfs_unbusy(mp); | vfs_unbusy(mp); | ||||
*mp_busy = false; | |||||
error = vn_open(&nd, &flags, 0, NULL); | error = vn_open(&nd, &flags, 0, NULL); | ||||
if (error != 0) { | if (error != 0) { | ||||
vfs_rel(mp); | vfs_rel(mp); | ||||
return (error); | return (error); | ||||
} | } | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
vp = nd.ni_vp; | vp = nd.ni_vp; | ||||
error = vfs_busy(mp, MBF_NOWAIT); | error = vfs_busy(mp, MBF_NOWAIT); | ||||
vfs_rel(mp); | vfs_rel(mp); | ||||
if (error == 0) { | if (error == 0) { | ||||
if (vp->v_type != VREG) { | *mp_busy = true; | ||||
if (vp->v_type != VREG) | |||||
error = EACCES; | error = EACCES; | ||||
vfs_unbusy(mp); | |||||
} | } | ||||
} | |||||
if (error != 0) { | if (error != 0) { | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
UFS_LOCK(ump); | UFS_LOCK(ump); | ||||
if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { | if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { | ||||
UFS_UNLOCK(ump); | UFS_UNLOCK(ump); | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | ||||
vfs_unbusy(mp); | |||||
return (EALREADY); | return (EALREADY); | ||||
} | } | ||||
ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING; | ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING; | ||||
UFS_UNLOCK(ump); | UFS_UNLOCK(ump); | ||||
if ((error = dqopen(vp, ump, type)) != 0) { | if ((error = dqopen(vp, ump, type)) != 0) { | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
UFS_LOCK(ump); | UFS_LOCK(ump); | ||||
ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING); | ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING); | ||||
UFS_UNLOCK(ump); | UFS_UNLOCK(ump); | ||||
(void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); | ||||
vfs_unbusy(mp); | |||||
return (error); | return (error); | ||||
} | } | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
MNT_ILOCK(mp); | MNT_ILOCK(mp); | ||||
mp->mnt_flag |= MNT_QUOTA; | mp->mnt_flag |= MNT_QUOTA; | ||||
mp->mnt_stat.f_flags |= MNT_QUOTA; | mp->mnt_stat.f_flags |= MNT_QUOTA; | ||||
MNT_IUNLOCK(mp); | MNT_IUNLOCK(mp); | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | if (error) { | ||||
if (error) | if (error) | ||||
quotaoff_inchange(td, mp, type); | quotaoff_inchange(td, mp, type); | ||||
UFS_LOCK(ump); | UFS_LOCK(ump); | ||||
ump->um_qflags[type] &= ~QTF_OPENING; | ump->um_qflags[type] &= ~QTF_OPENING; | ||||
KASSERT((ump->um_qflags[type] & QTF_CLOSING) == 0, | KASSERT((ump->um_qflags[type] & QTF_CLOSING) == 0, | ||||
("quotaon: leaking flags")); | ("quotaon: leaking flags")); | ||||
UFS_UNLOCK(ump); | UFS_UNLOCK(ump); | ||||
vfs_unbusy(mp); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Main code to turn off disk quotas for a filesystem. Does not change | * Main code to turn off disk quotas for a filesystem. Does not change | ||||
* flags. | * flags. | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 1,236 Lines • Show Last 20 Lines |