summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2012-06-08 18:32:09 +0000
committerjhb <jhb@FreeBSD.org>2012-06-08 18:32:09 +0000
commit176ddf31c38f565f6eccc0929f28b58bf1c44624 (patch)
tree0b8f87f34ade8316dd1813d458dd36c04d80600e /sys/kern/vfs_syscalls.c
parenta3a73ec277af4f8e132fad81ba45506af9eb90b7 (diff)
downloadFreeBSD-src-176ddf31c38f565f6eccc0929f28b58bf1c44624.zip
FreeBSD-src-176ddf31c38f565f6eccc0929f28b58bf1c44624.tar.gz
Split the second half of vn_open_cred() (after a vnode has been found via
a lookup or created via VOP_CREATE()) into a new vn_open_vnode() function and use this function in fhopen() instead of duplicating code from vn_open_cred() directly. Tested by: pho Reviewed by: kib MFC after: 2 weeks
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c165
1 files changed, 39 insertions, 126 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 79206a0..072ea96 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -4484,17 +4484,12 @@ sys_fhopen(td, uap)
int flags;
} */ *uap;
{
- struct proc *p = td->td_proc;
struct mount *mp;
struct vnode *vp;
struct fhandle fhp;
- struct vattr vat;
- struct vattr *vap = &vat;
struct flock lf;
struct file *fp;
- register struct filedesc *fdp = p->p_fd;
int fmode, error, type;
- accmode_t accmode;
struct file *nfp;
int vfslocked;
int indx;
@@ -4502,6 +4497,7 @@ sys_fhopen(td, uap)
error = priv_check(td, PRIV_VFS_FHOPEN);
if (error)
return (error);
+ indx = -1;
fmode = FFLAGS(uap->flags);
/* why not allow a non-read/write open for our lockd? */
if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
@@ -4517,109 +4513,40 @@ sys_fhopen(td, uap)
/* now give me my vnode, it gets returned to me locked */
error = VFS_FHTOVP(mp, &fhp.fh_fid, LK_EXCLUSIVE, &vp);
vfs_unbusy(mp);
- if (error)
- goto out;
- /*
- * from now on we have to make sure not
- * to forget about the vnode
- * any error that causes an abort must vput(vp)
- * just set error = err and 'goto bad;'.
- */
-
- /*
- * from vn_open
- */
- if (vp->v_type == VLNK) {
- error = EMLINK;
- goto bad;
- }
- if (vp->v_type == VSOCK) {
- error = EOPNOTSUPP;
- goto bad;
- }
- if (vp->v_type != VDIR && fmode & O_DIRECTORY) {
- error = ENOTDIR;
- goto bad;
- }
- accmode = 0;
- if (fmode & (FWRITE | O_TRUNC)) {
- if (vp->v_type == VDIR) {
- error = EISDIR;
- goto bad;
- }
- error = vn_writechk(vp);
- if (error)
- goto bad;
- accmode |= VWRITE;
- }
- if (fmode & FREAD)
- accmode |= VREAD;
- if ((fmode & O_APPEND) && (fmode & FWRITE))
- accmode |= VAPPEND;
-#ifdef MAC
- error = mac_vnode_check_open(td->td_ucred, vp, accmode);
- if (error)
- goto bad;
-#endif
- if (accmode) {
- error = VOP_ACCESS(vp, accmode, td->td_ucred, td);
- if (error)
- goto bad;
- }
- if (fmode & O_TRUNC) {
- vfs_ref(mp);
- VOP_UNLOCK(vp, 0); /* XXX */
- if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
- vrele(vp);
- vfs_rel(mp);
- goto out;
- }
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
- vfs_rel(mp);
-#ifdef MAC
- /*
- * We don't yet have fp->f_cred, so use td->td_ucred, which
- * should be right.
- */
- error = mac_vnode_check_write(td->td_ucred, td->td_ucred, vp);
- if (error == 0) {
-#endif
- VATTR_NULL(vap);
- vap->va_size = 0;
- error = VOP_SETATTR(vp, vap, td->td_ucred);
-#ifdef MAC
- }
-#endif
- vn_finished_write(mp);
- if (error)
- goto bad;
+ if (error) {
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
}
- error = VOP_OPEN(vp, fmode, td->td_ucred, td, NULL);
- if (error)
- goto bad;
- if (fmode & FWRITE) {
- vp->v_writecount++;
- CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",
- __func__, vp, vp->v_writecount);
- }
+ error = falloc_noinstall(td, &nfp);
+ if (error) {
+ vput(vp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
+ }
- /*
- * end of vn_open code
- */
+ /* An extra reference on `nfp' has been held for us by falloc(). */
+ fp = nfp;
+#ifdef INVARIANTS
+ td->td_dupfd = -1;
+#endif
+ error = vn_open_vnode(vp, fmode, td->td_ucred, td, fp);
+ if (error) {
+ KASSERT(fp->f_ops == &badfileops,
+ ("VOP_OPEN in fhopen() set f_ops"));
+ KASSERT(td->td_dupfd < 0,
+ ("fhopen() encountered fdopen()"));
- if ((error = falloc(td, &nfp, &indx, fmode)) != 0) {
- if (fmode & FWRITE) {
- vp->v_writecount--;
- CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d",
- __func__, vp, vp->v_writecount);
- }
+ vput(vp);
goto bad;
}
- /* An extra reference on `nfp' has been held for us by falloc(). */
- fp = nfp;
- nfp->f_vnode = vp;
- finit(nfp, fmode & FMASK, DTYPE_VNODE, vp, &vnops);
+#ifdef INVARIANTS
+ td->td_dupfd = 0;
+#endif
+ fp->f_vnode = vp;
+ fp->f_seqcount = 1;
+ finit(fp, fmode & FMASK, DTYPE_VNODE, vp, &vnops);
+ VOP_UNLOCK(vp, 0);
if (fmode & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -4631,36 +4558,22 @@ sys_fhopen(td, uap)
type = F_FLOCK;
if ((fmode & FNONBLOCK) == 0)
type |= F_WAIT;
- VOP_UNLOCK(vp, 0);
if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
- type)) != 0) {
- /*
- * The lock request failed. Normally close the
- * descriptor but handle the case where someone might
- * have dup()d or close()d it when we weren't looking.
- */
- fdclose(fdp, fp, indx, td);
-
- /*
- * release our private reference
- */
- fdrop(fp, td);
- goto out;
- }
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ type)) != 0)
+ goto bad;
atomic_set_int(&fp->f_flag, FHASLOCK);
}
+ if (fmode & O_TRUNC) {
+ error = fo_truncate(fp, 0, td->td_ucred, td);
+ if (error)
+ goto bad;
+ }
- VOP_UNLOCK(vp, 0);
- fdrop(fp, td);
- VFS_UNLOCK_GIANT(vfslocked);
- td->td_retval[0] = indx;
- return (0);
-
+ error = finstall(td, fp, &indx, fmode);
bad:
- vput(vp);
-out:
VFS_UNLOCK_GIANT(vfslocked);
+ fdrop(fp, td);
+ td->td_retval[0] = indx;
return (error);
}
OpenPOWER on IntegriCloud