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
This commit is contained in:
parent
5478ba7358
commit
d5ff273563
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user