summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/compat/hpux/hpux_file.c16
-rw-r--r--sys/kern/kern_descrip.c103
-rw-r--r--sys/kern/vfs_lockf.c8
-rw-r--r--sys/kern/vfs_vnops.c17
-rw-r--r--sys/sys/filedesc.h9
-rw-r--r--sys/sys/lockf.h3
-rw-r--r--sys/sys/proc.h3
7 files changed, 93 insertions, 66 deletions
diff --git a/sys/compat/hpux/hpux_file.c b/sys/compat/hpux/hpux_file.c
index cad38f912b3..a3596136e40 100644
--- a/sys/compat/hpux/hpux_file.c
+++ b/sys/compat/hpux/hpux_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hpux_file.c,v 1.18 2007/03/15 10:22:30 art Exp $ */
+/* $OpenBSD: hpux_file.c,v 1.19 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: hpux_file.c,v 1.5 1997/04/27 21:40:48 thorpej Exp $ */
/*
@@ -282,8 +282,8 @@ hpux_sys_fcntl(p, v, retval)
goto out;
}
- atomic_setbits_int(&p->p_flag, P_ADVLOCK);
- error = VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg);
+ atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK);
+ error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg);
goto out;
case F_WRLCK:
@@ -291,13 +291,12 @@ hpux_sys_fcntl(p, v, retval)
error = EBADF;
goto out;
}
- atomic_setbits_int(&p->p_flag, P_ADVLOCK);
- error = VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg);
+ atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK);
+ error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg);
goto out;
case F_UNLCK:
- error = VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
- F_POSIX);
+ error = VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX);
goto out;
default:
@@ -328,8 +327,7 @@ hpux_sys_fcntl(p, v, retval)
if (fl.l_whence == SEEK_CUR)
fl.l_start += fp->f_offset;
- if ((error =
- VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)))
+ if ((error = VOP_ADVLOCK(vp, fdp, F_GETLK, &fl, F_POSIX)))
goto out;
hfl.hl_start = fl.l_start;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 772d0006ed9..8097d04710e 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_descrip.c,v 1.79 2008/06/12 18:10:06 thib Exp $ */
+/* $OpenBSD: kern_descrip.c,v 1.80 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */
/*
@@ -430,22 +430,21 @@ restart:
error = EBADF;
goto out;
}
- atomic_setbits_int(&p->p_flag, P_ADVLOCK);
- error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
- goto out;
+ atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK);
+ error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg);
+ break;
case F_WRLCK:
if ((fp->f_flag & FWRITE) == 0) {
error = EBADF;
goto out;
}
- atomic_setbits_int(&p->p_flag, P_ADVLOCK);
- error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
- goto out;
+ atomic_setbits_int(&fdp->fd_flags, FD_ADVLOCK);
+ error = VOP_ADVLOCK(vp, fdp, F_SETLK, &fl, flg);
+ break;
case F_UNLCK:
- error = (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
- F_POSIX));
+ error = VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX);
goto out;
default:
@@ -453,6 +452,21 @@ restart:
goto out;
}
+ if (fp != fd_getfile(fdp, fd)) {
+ /*
+ * We have lost the race with close() or dup2()
+ * unlock, pretend that we'd won the race and that
+ * lock had been removed by close()
+ */
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+ VOP_ADVLOCK(vp, fdp, F_UNLCK, &fl, F_POSIX);
+ fl.l_type = F_UNLCK;
+ }
+ goto out;
+
+
case F_GETLK:
if (fp->f_type != DTYPE_VNODE) {
error = EBADF;
@@ -479,7 +493,7 @@ restart:
error = EINVAL;
break;
}
- error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
+ error = VOP_ADVLOCK(vp, fdp, F_GETLK, &fl, F_POSIX);
if (error)
break;
error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
@@ -1013,14 +1027,36 @@ fdfree(struct proc *p)
int
closef(struct file *fp, struct proc *p)
{
- struct vnode *vp;
- struct flock lf;
+ struct filedesc *fdp;
+ int references_left;
int error;
if (fp == NULL)
return (0);
/*
+ * Some files passed to this function could be accessed
+ * without a FILE_IS_USABLE check (and in some cases it's perfectly
+ * legal), we must beware of files where someone already won the
+ * race to FIF_WANTCLOSE.
+ */
+ if ((fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+ --fp->f_count > 0) {
+ references_left = 1;
+ } else {
+ references_left = 0;
+#ifdef DIAGNOSTIC
+ if (fp->f_count < 0)
+ panic("closef: count < 0");
+#endif
+
+ /* Wait for the last usecount to drain. */
+ fp->f_iflags |= FIF_WANTCLOSE;
+ while (fp->f_usecount > 1)
+ tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
+ }
+
+ /*
* POSIX record locking dictates that any close releases ALL
* locks owned by this process. This is handled by setting
* a flag in the unlock to free ONLY locks obeying POSIX
@@ -1028,49 +1064,24 @@ closef(struct file *fp, struct proc *p)
* If the descriptor was in a message, POSIX-style locks
* aren't passed with the descriptor.
*/
- if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
+ if (p && ((fdp = p->p_fd) != NULL) &&
+ (fdp->fd_flags & FD_ADVLOCK) &&
+ fp->f_type == DTYPE_VNODE) {
+ struct vnode *vp = fp->f_data;
+ struct flock lf;
+
lf.l_whence = SEEK_SET;
lf.l_start = 0;
lf.l_len = 0;
lf.l_type = F_UNLCK;
- vp = (struct vnode *)fp->f_data;
- (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
- }
-
- /*
- * Some files passed to this function could be accessed
- * without a FILE_IS_USABLE check (and in some cases it's perfectly
- * legal), we must beware of files where someone already won the
- * race to FIF_WANTCLOSE.
- */
- if ((fp->f_iflags & FIF_WANTCLOSE) != 0) {
- FRELE(fp);
- return (0);
+ (void) VOP_ADVLOCK(vp, fdp, F_UNLCK, &lf, F_POSIX);
}
- if (--fp->f_count > 0) {
+ if (references_left) {
FRELE(fp);
return (0);
}
-#ifdef DIAGNOSTIC
- if (fp->f_count < 0)
- panic("closef: count < 0");
-#endif
-
- /* Wait for the last usecount to drain. */
- fp->f_iflags |= FIF_WANTCLOSE;
- while (fp->f_usecount > 1)
- tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
-
- if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
- lf.l_whence = SEEK_SET;
- lf.l_start = 0;
- lf.l_len = 0;
- lf.l_type = F_UNLCK;
- vp = (struct vnode *)fp->f_data;
- (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
- }
if (fp->f_ops)
error = (*fp->f_ops->fo_close)(fp, p);
else
@@ -1115,6 +1126,7 @@ sys_flock(struct proc *p, void *v, register_t *retval)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (EOPNOTSUPP);
+ FREF(fp);
vp = (struct vnode *)fp->f_data;
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -1139,6 +1151,7 @@ sys_flock(struct proc *p, void *v, register_t *retval)
else
error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
out:
+ FRELE(fp);
return (error);
}
diff --git a/sys/kern/vfs_lockf.c b/sys/kern/vfs_lockf.c
index f628c6a1608..9afa0c0a367 100644
--- a/sys/kern/vfs_lockf.c
+++ b/sys/kern/vfs_lockf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_lockf.c,v 1.12 2005/11/20 21:55:15 pedro Exp $ */
+/* $OpenBSD: vfs_lockf.c,v 1.13 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: vfs_lockf.c,v 1.7 1996/02/04 02:18:21 christos Exp $ */
/*
@@ -192,6 +192,7 @@ lf_advlock(struct lockf **head, off_t size, caddr_t id, int op,
lock->lf_next = NULL;
TAILQ_INIT(&lock->lf_blkhd);
lock->lf_flags = flags;
+ lock->lf_pid = (flags & F_POSIX) ? curproc->p_pid : -1;
/*
* Do the requested operation.
*/
@@ -544,10 +545,7 @@ lf_getlock(struct lockf *lock, struct flock *fl)
fl->l_len = 0;
else
fl->l_len = block->lf_end - block->lf_start + 1;
- if (block->lf_flags & F_POSIX)
- fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
- else
- fl->l_pid = -1;
+ fl->l_pid = block->lf_pid;
} else {
fl->l_type = F_UNLCK;
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index f7782056ea7..c8f33a561e1 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.59 2008/04/08 14:46:45 thib Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.60 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -52,6 +52,7 @@
#include <sys/tty.h>
#include <sys/cdio.h>
#include <sys/poll.h>
+#include <sys/filedesc.h>
#include <uvm/uvm_extern.h>
#include <miscfs/specfs/specdev.h>
@@ -482,8 +483,18 @@ vn_lock(struct vnode *vp, int flags, struct proc *p)
int
vn_closefile(struct file *fp, struct proc *p)
{
- return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
- fp->f_cred, p));
+ struct vnode *vp = fp->f_data;
+ struct flock lf;
+
+ if ((fp->f_flag & FHASLOCK)) {
+ lf.l_whence = SEEK_SET;
+ lf.l_start = 0;
+ lf.l_len = 0;
+ lf.l_type = F_UNLCK;
+ (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
+ }
+
+ return (vn_close(vp, fp->f_flag, fp->f_cred, p));
}
int
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 121429a6bce..792129b1cb8 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: filedesc.h,v 1.19 2004/07/22 06:11:10 tedu Exp $ */
+/* $OpenBSD: filedesc.h,v 1.20 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $ */
/*
@@ -74,6 +74,8 @@ struct filedesc {
struct klist *fd_knlist; /* list of attached knotes */
u_long fd_knhashmask; /* size of knhash */
struct klist *fd_knhash; /* hash table for attached knotes */
+
+ int fd_flags; /* flags on the file descriptor table */
};
/*
@@ -102,6 +104,11 @@ struct filedesc0 {
#define UF_EXCLOSE 0x01 /* auto-close on exec */
/*
+ * Flags on the file descriptor table.
+ */
+#define FD_ADVLOCK 0x01 /* May hold a POSIX adv. lock. */
+
+/*
* Storage required per open file descriptor.
*/
#define OFILESIZE (sizeof(struct file *) + sizeof(char))
diff --git a/sys/sys/lockf.h b/sys/sys/lockf.h
index 1b17d451522..c6b96256d16 100644
--- a/sys/sys/lockf.h
+++ b/sys/sys/lockf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lockf.h,v 1.7 2005/03/10 17:26:10 tedu Exp $ */
+/* $OpenBSD: lockf.h,v 1.8 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: lockf.h,v 1.5 1994/06/29 06:44:33 cgd Exp $ */
/*
@@ -54,6 +54,7 @@ struct lockf {
struct locklist lf_blkhd; /* The list of blocked locks */
TAILQ_ENTRY(lockf) lf_block; /* A request waiting for a lock */
uid_t lf_uid; /* User ID responsible */
+ pid_t lf_pid; /* POSIX - owner pid */
};
/* Maximum length of sleep chains to traverse to try and detect deadlock. */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index ba1ae9e9975..fe13e39a683 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.103 2008/05/05 15:37:41 thib Exp $ */
+/* $OpenBSD: proc.h,v 1.104 2008/09/19 12:24:55 art Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -269,7 +269,6 @@ struct proc {
#define P_ZOMBIE(p) ((p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
/* These flags are kept in p_flag. */
-#define P_ADVLOCK 0x000001 /* Proc may hold a POSIX adv. lock. */
#define P_CONTROLT 0x000002 /* Has a controlling terminal. */
#define P_INMEM 0x000004 /* Loaded into memory. UNUSED */
#define P_NOCLDSTOP 0x000008 /* No SIGCHLD when children stop. */