diff options
author | kib <kib@FreeBSD.org> | 2010-04-13 08:52:20 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-04-13 08:52:20 +0000 |
commit | bf84540647fc1be184bf41e391a3ef7d015f2397 (patch) | |
tree | d1bc352b19f5d267fa971fec890107ea62f73a1e /sys | |
parent | d5f342f2daa0632a7ce5dc14cc5bc84bea1b8a16 (diff) | |
download | FreeBSD-src-bf84540647fc1be184bf41e391a3ef7d015f2397.zip FreeBSD-src-bf84540647fc1be184bf41e391a3ef7d015f2397.tar.gz |
Handle a case in kern_openat() when vn_open() change file type from
DTYPE_VNODE.
Only acquire locks for O_EXLOCK/O_SHLOCK if file type is still vnode,
since we allow for fcntl(2) to process with advisory locks for
DTYPE_VNODE only. Another reason is that all fo_close() routines need to
check and release locks otherwise.
For O_TRUNC, call fo_truncate() instead of truncating the vnode.
Discussed with: rwatson
MFC after: 2 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 17 |
1 files changed, 2 insertions, 15 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index f266688..ab0627d 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1047,8 +1047,6 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; - struct vattr vat; - struct mount *mp; int cmode; struct file *nfp; int type, indx, error; @@ -1141,7 +1139,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, } VOP_UNLOCK(vp, 0); - if (flags & (O_EXLOCK | O_SHLOCK)) { + if (fp->f_type == DTYPE_VNODE && (flags & (O_EXLOCK | O_SHLOCK)) != 0) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; @@ -1158,18 +1156,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg, atomic_set_int(&fp->f_flag, FHASLOCK); } if (flags & O_TRUNC) { - if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) - goto bad; - VATTR_NULL(&vat); - vat.va_size = 0; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); -#ifdef MAC - error = mac_vnode_check_write(td->td_ucred, fp->f_cred, vp); - if (error == 0) -#endif - error = VOP_SETATTR(vp, &vat, td->td_ucred); - VOP_UNLOCK(vp, 0); - vn_finished_write(mp); + error = fo_truncate(fp, 0, td->td_ucred, td); if (error) goto bad; } |