示例#1
0
文件: spl-vnode.c 项目: rottegift/spl
int zfs_vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, ssize_t len,
                offset_t offset, enum uio_seg seg, int ioflag, rlim64_t ulimit,
                cred_t *cr, ssize_t *residp)
{
    uio_t *auio;
    int spacetype;
    int error=0;
    vfs_context_t vctx;

    spacetype = UIO_SEG_IS_USER_SPACE(seg) ? UIO_USERSPACE32 : UIO_SYSSPACE;

    vctx = vfs_context_create((vfs_context_t)0);
    auio = uio_create(1, 0, spacetype, rw);
    uio_reset(auio, offset, spacetype, rw);
    uio_addiov(auio, (uint64_t)(uintptr_t)base, len);

    if (rw == UIO_READ) {
        error = VNOP_READ(vp, auio, ioflag, vctx);
    } else {
        error = VNOP_WRITE(vp, auio, ioflag, vctx);
    }

    if (residp) {
        *residp = uio_resid(auio);
    } else {
        if (uio_resid(auio) && error == 0)
            error = EIO;
    }

    uio_free(auio);
    vfs_context_rele(vctx);

    return (error);
}
示例#2
0
int
cttywrite(__unused dev_t dev, struct uio *uio, int flag)
{
	vnode_t ttyvp = cttyvp(current_proc());
	struct vfs_context context;
	int error;

	if (ttyvp == NULL)
		return (EIO);

	context.vc_thread = current_thread();
	context.vc_ucred = NOCRED;

	error = VNOP_WRITE(ttyvp, uio, flag, &context);
	vnode_put(ttyvp);

	return (error);
}
示例#3
0
/* Generic write interface */
int
afs_osi_Write(struct osi_file *afile, afs_int32 offset, void *aptr,
	      afs_int32 asize)
{
    afs_ucred_t *oldCred;
    afs_size_t resid;
    afs_int32 code;
#ifdef AFS_DARWIN80_ENV
    uio_t uio;
#endif
    AFS_STATCNT(osi_Write);
    if (!afile)
	osi_Panic("afs_osi_Write called with null param");
    if (offset != -1)
	afile->offset = offset;
    {
	AFS_GUNLOCK();
#ifdef AFS_DARWIN80_ENV
        uio=uio_create(1, afile->offset, AFS_UIOSYS, UIO_WRITE);
        uio_addiov(uio, CAST_USER_ADDR_T(aptr), asize);
        code = VNOP_WRITE(afile->vnode, uio, IO_UNIT, afs_osi_ctxtp);
        resid = AFS_UIO_RESID(uio);
        uio_free(uio);
#else
	code =
	    gop_rdwr(UIO_WRITE, afile->vnode, (caddr_t) aptr, asize,
		     afile->offset, AFS_UIOSYS, IO_UNIT, &afs_osi_cred,
		     &resid);
#endif
	AFS_GLOCK();
    }
    if (code == 0) {
	code = asize - resid;
	afile->offset += code;
    } else {
	if (code > 0) {
	    code *= -1;
	}
    }
    if (afile->proc) {
	(*afile->proc) (afile, code);
    }
    return code;
}
示例#4
0
static int
file_io(struct vnode * vp, vfs_context_t ctx, 
	enum uio_rw op, char * base, off_t offset, user_ssize_t count,
	user_ssize_t * resid)
{
	uio_t 		auio;
	int		error;
	char		uio_buf[UIO_SIZEOF(1)];
	
	auio = uio_createwithbuffer(1, offset, UIO_SYSSPACE, op, 
				    &uio_buf[0], sizeof(uio_buf));
	uio_addiov(auio, CAST_USER_ADDR_T(base), count);
	if (op == UIO_READ)
		error = VNOP_READ(vp, auio, IO_SYNC, ctx);
	else
		error = VNOP_WRITE(vp, auio, IO_SYNC, ctx);

	if (resid != NULL) {
		*resid = uio_resid(auio);
	}
	return (error);
}
示例#5
0
static int 
vnwrite(dev_t dev, struct uio *uio, int ioflag)
{
	struct vfs_context  	context;
	int 			error;
	off_t			offset;
	proc_t			p;
	user_ssize_t		resid;
	struct vn_softc *	vn;
	int 			unit;

	unit = vnunit(dev);
	if (vnunit(dev) >= NVNDEVICE) {
		return (ENXIO);
	}
	p = current_proc();
	vn = vn_table + unit;
	if ((vn->sc_flags & VNF_INITED) == 0) {
		error = ENXIO;
		goto done;
	}
	if (vn->sc_flags & VNF_READONLY) {
		error = EROFS;
		goto done;
	}

	context.vc_thread = current_thread();
	context.vc_ucred = vn->sc_cred;

	error = vnode_getwithvid(vn->sc_vp, vn->sc_vid);
	if (error != 0) {
		/* the vnode is no longer available, abort */
		error = ENXIO;
		vnclear(vn, &context);
		goto done;
	}
	resid = uio_resid(uio);
	offset = uio_offset(uio);

	/*
	 * If out of bounds return an error.  If at the EOF point,
	 * simply write less.
	 */
	if (offset >= (off_t)vn->sc_fsize) {
		if (offset > (off_t)vn->sc_fsize) {
			error = EINVAL;
		}
		goto done;
	}
	/*
	 * If the request crosses EOF, truncate the request.
	 */
	if ((offset + resid) > (off_t)vn->sc_fsize) {
		resid = (off_t)vn->sc_fsize - offset;
		uio_setresid(uio, resid);
	}

	if (vn->sc_shadow_vp != NULL) {
		error = vnode_getwithvid(vn->sc_shadow_vp,
					 vn->sc_shadow_vid);
		if (error != 0) {
			/* the vnode is no longer available, abort */
			error = ENXIO;
			vnode_put(vn->sc_vp);
			vnclear(vn, &context);
			goto done;
		}
		error = vnwrite_shadow(vn, uio, ioflag, &context);
		vnode_put(vn->sc_shadow_vp);
	} else {
		error = VNOP_WRITE(vn->sc_vp, uio, ioflag, &context);
	}
	vnode_put(vn->sc_vp);
 done:
	return (error);
}
示例#6
0
static int
vnwrite_shadow(struct vn_softc * vn, struct uio *uio, int ioflag, 
	       vfs_context_t ctx)
{
	u_int32_t		blocksize = vn->sc_secsize;
	int 		error = 0;
	user_ssize_t	resid;
	off_t		offset;

	resid = uio_resid(uio);
	offset = uio_offset(uio);

	while (resid > 0) {
		int		flags = 0;
		u_int32_t		offset_block_number;
		u_int32_t		remainder;
		u_int32_t		resid_block_count;
		u_int32_t		shadow_block_count;
		u_int32_t		shadow_block_number;
		user_ssize_t	this_resid;

		/* figure out which blocks to write */
		offset_block_number = block_truncate(offset, blocksize);
		remainder = block_remainder(offset, blocksize);
		resid_block_count = block_round(resid + remainder, blocksize);
		/* figure out if the first or last blocks are partial writes */
		if (remainder > 0
		    && !shadow_map_is_written(vn->sc_shadow_map,
					      offset_block_number)) {
			/* the first block is a partial write */
			flags |= FLAGS_FIRST_BLOCK_PARTIAL;
		}
		if (resid_block_count > 1
		    && !shadow_map_is_written(vn->sc_shadow_map,
					      offset_block_number
					      + resid_block_count - 1)
		    && block_remainder(offset + resid, blocksize) > 0) {
			/* the last block is a partial write */
			flags |= FLAGS_LAST_BLOCK_PARTIAL;
		}
		if (shadow_map_write(vn->sc_shadow_map,
				     offset_block_number, resid_block_count,
				     &shadow_block_number, 
				     &shadow_block_count)) {
			/* shadow file is growing */
#if 0
			/* truncate the file to its new length before write */
			off_t	size;
			size = (off_t)shadow_map_shadow_size(vn->sc_shadow_map) 
				* vn->sc_secsize;
			vnode_setsize(vn->sc_shadow_vp, size, IO_SYNC, ctx);
#endif
		}
		/* write the blocks (or parts thereof) */
		uio_setoffset(uio, (off_t)
			      shadow_block_number * blocksize + remainder);
		this_resid = (off_t)shadow_block_count * blocksize - remainder;
		if (this_resid >= resid) {
			this_resid = resid;
			if ((flags & FLAGS_LAST_BLOCK_PARTIAL) != 0) {
				/* copy the last block to the shadow */
				u_int32_t 	d;
				u_int32_t	s;

				s = offset_block_number 
					+ resid_block_count - 1;
				d = shadow_block_number 
					+ shadow_block_count - 1;
				error = vncopy_block_to_shadow(vn, ctx, s, d);
				if (error) {
					printf("vnwrite_shadow: failed to copy"
					       " block %u to shadow block %u\n",
					       s, d);
					break;
				}
			}
		}
		uio_setresid(uio, this_resid);
		if ((flags & FLAGS_FIRST_BLOCK_PARTIAL) != 0) {
			/* copy the first block to the shadow */
			error = vncopy_block_to_shadow(vn, ctx,
						       offset_block_number,
						       shadow_block_number);
			if (error) {
				printf("vnwrite_shadow: failed to"
				       " copy block %u to shadow block %u\n", 
				       offset_block_number, 
				       shadow_block_number);
				break;
			}
		}
		error = VNOP_WRITE(vn->sc_shadow_vp, uio, ioflag, ctx);
		if (error) {
			break;
		}
		/* figure out how much we actually wrote */
		this_resid -= uio_resid(uio);
		if (this_resid == 0) {
			printf("vn device: vnwrite_shadow zero length write\n");
			break;
		}
		resid -= this_resid;
		offset += this_resid;
	}
	uio_setresid(uio, resid);
	uio_setoffset(uio, offset);
	return (error);
}
示例#7
0
int
vn_rdwr_64FromKernelCode(
    enum uio_rw rw,
    struct vnode *vp,
    uint64_t base,
    int64_t len,
    off_t offset,
    enum uio_seg segflg,
    int ioflg,
    int *aresid,
    proc_t p)
{
    uio_t auio;
    //int spacetype;
    vfs_context_t context;
    int error=0;
    //char uio_buf[ UIO_SIZEOF(1) ];

    //context.vc_thread = current_thread();
    //context.vc_ucred = cred;

//	if (UIO_SEG_IS_USER_SPACE(segflg)) {
//		spacetype = proc_is64bit(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
//	}
//	else {
//		spacetype = UIO_SYSSPACE;
//	}
    auio = uio_create(1, offset, UIO_SYSSPACE, rw);
    uio_addiov(auio, base, len);

//#if CONFIG_MACF
//	/* XXXMAC
//	 * 	IO_NOAUTH should be re-examined.
// 	 *	Likely that mediation should be performed in caller.
//	 */
//	if ((ioflg & IO_NOAUTH) == 0) {
//		/* passed cred is fp->f_cred */
//		if (rw == UIO_READ)
//			error = mac_vnode_check_read(&context, cred, vp);
//		else
//			error = mac_vnode_check_write(&context, cred, vp);
//	}
//#endif


    if (rw == UIO_READ)
    {
        error = VNOP_READ(vp, auio, ioflg, context);
    }
    else
    {
        error = VNOP_WRITE(vp, auio, ioflg, context);
    }

    if (aresid)
        // LP64todo - fix this
        *aresid = uio_resid(auio);
    else if (uio_resid(auio) && error == 0)
        error = EIO;
    return (error);
}