Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_syscalls.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/uma.h> | #include <vm/uma.h> | ||||
#include <fs/devfs/devfs.h> | #include <fs/devfs/devfs.h> | ||||
#include <ufs/ufs/quota.h> | |||||
MALLOC_DEFINE(M_FADVISE, "fadvise", "posix_fadvise(2) information"); | MALLOC_DEFINE(M_FADVISE, "fadvise", "posix_fadvise(2) information"); | ||||
static int kern_chflagsat(struct thread *td, int fd, const char *path, | static int kern_chflagsat(struct thread *td, int fd, const char *path, | ||||
enum uio_seg pathseg, u_long flags, int atflag); | enum uio_seg pathseg, u_long flags, int atflag); | ||||
static int setfflags(struct thread *td, struct vnode *, u_long); | static int setfflags(struct thread *td, struct vnode *, u_long); | ||||
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); | static int getutimes(const struct timeval *, enum uio_seg, struct timespec *); | ||||
static int getutimens(const struct timespec *, enum uio_seg, | static int getutimens(const struct timespec *, enum uio_seg, | ||||
struct timespec *, int *); | struct timespec *, int *); | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sys_quotactl(struct thread *td, struct quotactl_args *uap) | sys_quotactl(struct thread *td, struct quotactl_args *uap) | ||||
{ | { | ||||
struct mount *mp; | struct mount *mp; | ||||
struct nameidata nd; | struct nameidata nd; | ||||
int error; | int error; | ||||
bool mp_busy; | |||||
AUDIT_ARG_CMD(uap->cmd); | AUDIT_ARG_CMD(uap->cmd); | ||||
AUDIT_ARG_UID(uap->uid); | AUDIT_ARG_UID(uap->uid); | ||||
if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS)) | if (!prison_allow(td->td_ucred, PR_ALLOW_QUOTAS)) | ||||
return (EPERM); | return (EPERM); | ||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, | NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, | ||||
uap->path, td); | uap->path, td); | ||||
if ((error = namei(&nd)) != 0) | if ((error = namei(&nd)) != 0) | ||||
return (error); | return (error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
mp = nd.ni_vp->v_mount; | mp = nd.ni_vp->v_mount; | ||||
vfs_ref(mp); | vfs_ref(mp); | ||||
vput(nd.ni_vp); | vput(nd.ni_vp); | ||||
error = vfs_busy(mp, 0); | error = vfs_busy(mp, 0); | ||||
if (error != 0) { | if (error != 0) { | ||||
vfs_rel(mp); | vfs_rel(mp); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg); | mp_busy = true; | ||||
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, &mp_busy); | |||||
/* | /* | ||||
* Since quota on operation typically needs to open quota | * Since quota on/off operations typically need to open quota | ||||
* file, the Q_QUOTAON handler needs to unbusy the mount point | * files, the implementation may need to unbusy the mount point | ||||
* before calling into namei. Otherwise, unmount might be | * before calling into namei. Otherwise, unmount might be | ||||
* started between two vfs_busy() invocations (first is our, | * started between two vfs_busy() invocations (first is ours, | ||||
* second is from mount point cross-walk code in lookup()), | * second is from mount point cross-walk code in lookup()), | ||||
* causing deadlock. | * causing deadlock. | ||||
* | * | ||||
* Require that Q_QUOTAON handles the vfs_busy() reference on | * Avoid unbusying mp if the implementation indicates it has | ||||
* its own, always returning with ubusied mount point. | * already done so. | ||||
*/ | */ | ||||
if ((uap->cmd >> SUBCMDSHIFT) != Q_QUOTAON && | if (mp_busy) | ||||
(uap->cmd >> SUBCMDSHIFT) != Q_QUOTAOFF) | |||||
vfs_unbusy(mp); | vfs_unbusy(mp); | ||||
vfs_rel(mp); | vfs_rel(mp); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Used by statfs conversion routines to scale the block size up if | * Used by statfs conversion routines to scale the block size up if | ||||
* necessary so that all of the block counts are <= 'max_size'. Note | * necessary so that all of the block counts are <= 'max_size'. Note | ||||
▲ Show 20 Lines • Show All 4,749 Lines • Show Last 20 Lines |