Exemplo n.º 1
0
/* ARGSUSED */
int
sys_flock(struct lwp *l, const struct sys_flock_args *uap, register_t *retval)
{
	/* {
		syscallarg(int)	fd;
		syscallarg(int)	how;
	} */
	int fd, how, error;
	file_t *fp;
	vnode_t	*vp;
	struct flock lf;

	fd = SCARG(uap, fd);
	how = SCARG(uap, how);
	error = 0;

	if ((fp = fd_getfile(fd)) == NULL) {
		return EBADF;
	}
	if (fp->f_type != DTYPE_VNODE) {
		fd_putfile(fd);
		return EOPNOTSUPP;
	}

	vp = fp->f_vnode;
	lf.l_whence = SEEK_SET;
	lf.l_start = 0;
	lf.l_len = 0;

	switch (how & ~LOCK_NB) {
	case LOCK_UN:
		lf.l_type = F_UNLCK;
		atomic_and_uint(&fp->f_flag, ~FHASLOCK);
		error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
		fd_putfile(fd);
		return error;
	case LOCK_EX:
		lf.l_type = F_WRLCK;
		break;
	case LOCK_SH:
		lf.l_type = F_RDLCK;
		break;
	default:
		fd_putfile(fd);
		return EINVAL;
	}

	atomic_or_uint(&fp->f_flag, FHASLOCK);
	if (how & LOCK_NB) {
		error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK);
	} else {
		error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
	}
	fd_putfile(fd);
	return error;
}
Exemplo n.º 2
0
static int
unionfs_advlock(void *v)
{
	struct vop_advlock_args *ap = v;
	int error;
	struct unionfs_node *unp;
	struct unionfs_node_status *unsp;
	struct vnode   *vp;
	struct vnode   *uvp;
	kauth_cred_t	cred;

	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n");

	vp = ap->a_vp;
	cred = kauth_cred_get();

	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);

	unp = VTOUNIONFS(ap->a_vp);
	uvp = unp->un_uppervp;

	if (uvp == NULLVP) {
		error = unionfs_copyfile(unp, 1, cred);
		if (error != 0)
			goto unionfs_advlock_abort;
		uvp = unp->un_uppervp;

		unionfs_get_node_status(unp, &unsp);
		if (unsp->uns_lower_opencnt > 0) {
			/* try reopen the vnode */
			error = VOP_OPEN(uvp, unsp->uns_lower_openmode, cred);
			if (error)
				goto unionfs_advlock_abort;
			unsp->uns_upper_opencnt++;
			VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, cred);
			unsp->uns_lower_opencnt--;
		} else
			unionfs_tryrem_node_status(unp, unsp);
	}

	VOP_UNLOCK(vp);

	error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags);

	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);

	return error;

unionfs_advlock_abort:
	VOP_UNLOCK(vp);

	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);

	return error;
}
Exemplo n.º 3
0
int
RUMP_VOP_ADVLOCK(struct vnode *vp,
    void *id,
    int op,
    struct flock *fl,
    int flags)
{
	int error;

	rump_schedule();
	error = VOP_ADVLOCK(vp, id, op, fl, flags);
	rump_unschedule();

	return error;
}
Exemplo n.º 4
0
/*
 * File table vnode close routine.
 */
int
vn_closefile(struct file *fp, struct proc *p)
{
	struct vnode *vp = fp->f_data;
	struct flock lf;
	
	if ((fp->f_iflags & FIF_HASLOCK)) {
		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));
}
Exemplo n.º 5
0
int
do_fcntl_lock(int fd, int cmd, struct flock *fl)
{
	file_t *fp;
	vnode_t *vp;
	proc_t *p;
	int error, flg;

	if ((fp = fd_getfile(fd)) == NULL)
		return EBADF;
	if (fp->f_type != DTYPE_VNODE) {
		fd_putfile(fd);
		return EINVAL;
	}
	vp = fp->f_vnode;
	if (fl->l_whence == SEEK_CUR)
		fl->l_start += fp->f_offset;

	flg = F_POSIX;
	p = curproc;

	switch (cmd) {
	case F_SETLKW:
		flg |= F_WAIT;
		/* Fall into F_SETLK */

	case F_SETLK:
		switch (fl->l_type) {
		case F_RDLCK:
			if ((fp->f_flag & FREAD) == 0) {
				error = EBADF;
				break;
			}
			if ((p->p_flag & PK_ADVLOCK) == 0) {
				mutex_enter(p->p_lock);
				p->p_flag |= PK_ADVLOCK;
				mutex_exit(p->p_lock);
			}
			error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
			break;

		case F_WRLCK:
			if ((fp->f_flag & FWRITE) == 0) {
				error = EBADF;
				break;
			}
			if ((p->p_flag & PK_ADVLOCK) == 0) {
				mutex_enter(p->p_lock);
				p->p_flag |= PK_ADVLOCK;
				mutex_exit(p->p_lock);
			}
			error = VOP_ADVLOCK(vp, p, F_SETLK, fl, flg);
			break;

		case F_UNLCK:
			error = VOP_ADVLOCK(vp, p, F_UNLCK, fl, F_POSIX);
			break;

		default:
			error = EINVAL;
			break;
		}
		break;

	case F_GETLK:
		if (fl->l_type != F_RDLCK &&
		    fl->l_type != F_WRLCK &&
		    fl->l_type != F_UNLCK) {
			error = EINVAL;
			break;
		}
		error = VOP_ADVLOCK(vp, p, F_GETLK, fl, F_POSIX);
		break;

	default:
		error = EINVAL;
		break;
	}

	fd_putfile(fd);
	return error;
}