FreeBSD/sys/kern/vfs_vnops.c
/*
 * Package up an I/O request on a vnode into a uio and do it.
 */
Package up an I/O request on a vnode into a uio and do it.
Package up an I / O request on a vnode into a uio and do it .
int
vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset,
    enum uio_seg segflg, int ioflg, struct ucred *active_cred,
    struct ucred *file_cred, ssize_t *aresid, struct thread *td)
{
	struct uio auio;
	struct iovec aiov;
	struct mount *mp;
	struct ucred *cred;
	void *rl_cookie;
	struct vn_io_fault_args args;
	int error, lock_flags;
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	aiov.iov_base = base;
	aiov.iov_len = len;
	auio.uio_resid = len;
	auio.uio_offset = offset;
	auio.uio_segflg = segflg;
	auio.uio_rw = rw;
	auio.uio_td = td;
	error = 0;
	if ((ioflg & IO_NODELOCKED) == 0) {
		if ((ioflg & IO_RANGELOCKED) == 0) {
			if (rw == UIO_READ) {
				rl_cookie = vn_rangelock_rlock(vp, offset,
				    offset + len);
			} else {
				rl_cookie = vn_rangelock_wlock(vp, offset,
				    offset + len);
			}
		} else
			rl_cookie = NULL;
		mp = NULL;
		if (rw == UIO_WRITE) { 
			if (vp->v_type != VCHR &&
			    (error = vn_start_write(vp, &mp, V_WAIT | PCATCH))
			    != 0)
				goto out;
			if (MNT_SHARED_WRITES(mp) ||
			    ((mp == NULL) && MNT_SHARED_WRITES(vp->v_mount)))
				lock_flags = LK_SHARED;
			else
				lock_flags = LK_EXCLUSIVE;
		} else
			lock_flags = LK_SHARED;
		vn_lock(vp, lock_flags | LK_RETRY);
	} else
		rl_cookie = NULL;
	ASSERT_VOP_LOCKED(vp, "IO_NODELOCKED with no vp lock held");
#ifdef MAC
	if ((ioflg & IO_NOMACCHECK) == 0) {
		if (rw == UIO_READ)
			error = mac_vnode_check_read(active_cred, file_cred,
			    vp);
		else
			error = mac_vnode_check_write(active_cred, file_cred,
			    vp);
	}
#endif
	if (error == 0) {
		if (file_cred != NULL)
			cred = file_cred;
		else
			cred = active_cred;
		if (do_vn_io_fault(vp, &auio)) {
			args.kind = VN_IO_FAULT_VOP;
			args.cred = cred;
			args.flags = ioflg;
			args.args.vop_args.vp = vp;
			error = vn_io_fault1(vp, &auio, &args, td);
		} else if (rw == UIO_READ) {
			error = VOP_READ(vp, &auio, ioflg, cred);
		} else  {
			error = VOP_WRITE(vp, &auio, ioflg, cred);
		}
	}
	if (aresid)
		*aresid = auio.uio_resid;
	else
		if (auio.uio_resid && error == 0)
			error = EIO;
	if ((ioflg & IO_NODELOCKED) == 0) {
		VOP_UNLOCK(vp, 0);
		if (mp != NULL)
			vn_finished_write(mp);
	}
 out:
	if (rl_cookie != NULL)
		vn_rangelock_unlock(vp, rl_cookie);
	return (error);
}
int vn_rdwr ( enum uio_rw rw , struct vnode * vp , void * base , int len , off_t offset , enum uio_seg segflg , int ioflg , struct ucred * active_cred , struct ucred * file_cred , ssize_t * aresid , struct thread * td ) { struct uio auio ; struct iovec aiov ; struct mount * mp ; struct ucred * cred ; void * rl_cookie ; struct vn_io_fault_args args ; int error , lock_flags ; auio . uio_iov = & aiov ; auio . uio_iovcnt = 1 ; aiov . iov_base = base ; aiov . iov_len = len ; auio . uio_resid = len ; auio . uio_offset = offset ; auio . uio_segflg = segflg ; auio . uio_rw = rw ; auio . uio_td = td ; error = 0 ; if ( ( ioflg & IO_NODELOCKED ) == 0 ) { if ( ( ioflg & IO_RANGELOCKED ) == 0 ) { if ( rw == UIO_READ ) { rl_cookie = vn_rangelock_rlock ( vp , offset , offset + len ) ; } else { rl_cookie = vn_rangelock_wlock ( vp , offset , offset + len ) ; } } else rl_cookie = NULL ; mp = NULL ; if ( rw == UIO_WRITE ) { if ( vp -> v_type != VCHR && ( error = vn_start_write ( vp , & mp , V_WAIT | PCATCH ) ) != 0 ) goto out ; if ( MNT_SHARED_WRITES ( mp ) || ( ( mp == NULL ) && MNT_SHARED_WRITES ( vp -> v_mount ) ) ) lock_flags = LK_SHARED ; else lock_flags = LK_EXCLUSIVE ; } else lock_flags = LK_SHARED ; vn_lock ( vp , lock_flags | LK_RETRY ) ; } else rl_cookie = NULL ; ASSERT_VOP_LOCKED ( vp , " " ) ; #ifdef MAC if ( ( ioflg & IO_NOMACCHECK ) == 0 ) { if ( rw == UIO_READ ) error = mac_vnode_check_read ( active_cred , file_cred , vp ) ; else error = mac_vnode_check_write ( active_cred , file_cred , vp ) ; } #endif if ( error == 0 ) { if ( file_cred != NULL ) cred = file_cred ; else cred = active_cred ; if ( do_vn_io_fault ( vp , & auio ) ) { args . kind = VN_IO_FAULT_VOP ; args . cred = cred ; args . flags = ioflg ; args . args . vop_args . vp = vp ; error = vn_io_fault1 ( vp , & auio , & args , td ) ; } else if ( rw == UIO_READ ) { error = VOP_READ ( vp , & auio , ioflg , cred ) ; } else { error = VOP_WRITE ( vp , & auio , ioflg , cred ) ; } } if ( aresid ) * aresid = auio . uio_resid ; else if ( auio . uio_resid && error == 0 ) error = EIO ; if ( ( ioflg & IO_NODELOCKED ) == 0 ) { VOP_UNLOCK ( vp , 0 ) ; if ( mp != NULL ) vn_finished_write ( mp ) ; } out : if ( rl_cookie != NULL ) vn_rangelock_unlock ( vp , rl_cookie ) ; return ( error ) ; }
Package up an I/O request on a vnode into a uio and do it.
Package up an I / O request on a vnode into a uio and do it .
/* if (rw == UIO_WRITE) */