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); }
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); }
/* 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; }
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); }
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); }
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); }
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); }