X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/bd504ef0e0b883cdd7917b73b3574eb9ce669905..bb59bff194111743b33cc36712410b5656329d3c:/bsd/kern/kern_symfile.c diff --git a/bsd/kern/kern_symfile.c b/bsd/kern/kern_symfile.c index 2e1965dfd..0e9d6c9c6 100644 --- a/bsd/kern/kern_symfile.c +++ b/bsd/kern/kern_symfile.c @@ -133,7 +133,8 @@ kern_ioctl_file_extents(struct kern_direct_file_io_ref_t * ref, u_long theIoctl, filechunk = 1*1024*1024*1024; if (filechunk > (size_t)(end - offset)) filechunk = (size_t)(end - offset); - error = VNOP_BLOCKMAP(ref->vp, offset, filechunk, &blkno, &filechunk, NULL, 0, NULL); + error = VNOP_BLOCKMAP(ref->vp, offset, filechunk, &blkno, + &filechunk, NULL, VNODE_WRITE, NULL); if (error) break; fileblk = blkno * ref->blksize; } @@ -156,7 +157,7 @@ kern_ioctl_file_extents(struct kern_direct_file_io_ref_t * ref, u_long theIoctl, { pin.cp_extent.offset = fileblk; pin.cp_extent.length = filechunk; - pin.cp_flags = _DKIOCSPINDISCARDDATA; + pin.cp_flags = _DKIOCCSPINFORHIBERNATION; error = do_ioctl(p1, p2, theIoctl, (caddr_t)&pin); if (error && (ENOTTY != error)) { @@ -172,11 +173,10 @@ kern_ioctl_file_extents(struct kern_direct_file_io_ref_t * ref, u_long theIoctl, return (error); } -int -kern_write_file(struct kern_direct_file_io_ref_t * ref, off_t offset, caddr_t addr, vm_size_t len); struct kern_direct_file_io_ref_t * kern_open_file_for_direct_io(const char * name, + boolean_t create_file, kern_get_file_extents_callback_t callback, void * callback_ref, off_t set_file_size, @@ -223,12 +223,20 @@ kern_open_file_for_direct_io(const char * name, p = kernproc; ref->ctx = vfs_context_create(vfs_context_current()); - if ((error = vnode_open(name, (O_CREAT | FWRITE), (0), 0, &ref->vp, ref->ctx))) + if ((error = vnode_open(name, (create_file) ? (O_CREAT | FWRITE) : FWRITE, + (0), 0, &ref->vp, ref->ctx))) goto out; + if (ref->vp->v_type == VREG) + { + vnode_lock_spin(ref->vp); + SET(ref->vp->v_flag, VSWAP); + vnode_unlock(ref->vp); + } + if (write_file_addr && write_file_len) { - if ((error = kern_write_file(ref, write_file_offset, write_file_addr, write_file_len))) + if ((error = kern_write_file(ref, write_file_offset, write_file_addr, write_file_len, 0))) goto out; } @@ -236,6 +244,7 @@ kern_open_file_for_direct_io(const char * name, VATTR_WANTED(&va, va_rdev); VATTR_WANTED(&va, va_fsid); VATTR_WANTED(&va, va_data_size); + VATTR_WANTED(&va, va_data_alloc); VATTR_WANTED(&va, va_nlink); error = EFAULT; if (vnode_getattr(ref->vp, &va, ref->ctx)) @@ -243,13 +252,13 @@ kern_open_file_for_direct_io(const char * name, kprintf("vp va_rdev major %d minor %d\n", major(va.va_rdev), minor(va.va_rdev)); kprintf("vp va_fsid major %d minor %d\n", major(va.va_fsid), minor(va.va_fsid)); - kprintf("vp size %qd\n", va.va_data_size); + kprintf("vp size %qd alloc %qd\n", va.va_data_size, va.va_data_alloc); if (ref->vp->v_type == VREG) { - /* Don't dump files with links. */ - if (va.va_nlink != 1) - goto out; + /* Don't dump files with links. */ + if (va.va_nlink != 1) + goto out; device = va.va_fsid; ref->filelength = va.va_data_size; @@ -258,18 +267,14 @@ kern_open_file_for_direct_io(const char * name, p2 = p; do_ioctl = &file_ioctl; - if (set_file_size) - { - off_t bytesallocated = 0; - u_int32_t alloc_flags = PREALLOCATE | ALLOCATEFROMPEOF | ALLOCATEALL; - error = VNOP_ALLOCATE(ref->vp, set_file_size, alloc_flags, - &bytesallocated, 0 /*fst_offset*/, - ref->ctx); - // F_SETSIZE: - if (!error) error = vnode_setsize(ref->vp, set_file_size, IO_NOZEROFILL, ref->ctx); - kprintf("vnode_setsize(%d) %qd\n", error, set_file_size); - ref->filelength = bytesallocated; - } + if (set_file_size) + { + error = vnode_setsize(ref->vp, set_file_size, + IO_NOZEROFILL | IO_NOAUTH, ref->ctx); + if (error) + goto out; + ref->filelength = set_file_size; + } } else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR)) { @@ -323,7 +328,8 @@ kern_open_file_for_direct_io(const char * name, filechunk = 1*1024*1024*1024; daddr64_t blkno; - error = VNOP_BLOCKMAP(ref->vp, f_offset, filechunk, &blkno, &filechunk, NULL, 0, NULL); + error = VNOP_BLOCKMAP(ref->vp, f_offset, filechunk, &blkno, + &filechunk, NULL, VNODE_WRITE, NULL); if (error) goto out; @@ -355,7 +361,15 @@ kern_open_file_for_direct_io(const char * name, error = ENOTSUP; goto out; } +#if HIBFRAGMENT + uint64_t rev; + for (rev = 4096; rev <= getphysreq.length; rev += 4096) + { + callback(callback_ref, getphysreq.offset + getphysreq.length - rev, 4096); + } +#else callback(callback_ref, getphysreq.offset, getphysreq.length); +#endif physoffset += getphysreq.length; } f_offset += filechunk; @@ -367,9 +381,12 @@ kern_open_file_for_direct_io(const char * name, // get partition base - error = do_ioctl(p1, p2, DKIOCGETBASE, (caddr_t) partitionbase_result); - if (error) - goto out; + if (partitionbase_result) + { + error = do_ioctl(p1, p2, DKIOCGETBASE, (caddr_t) partitionbase_result); + if (error) + goto out; + } // get block size & constraints @@ -435,7 +452,7 @@ kern_open_file_for_direct_io(const char * name, *partition_device_result = device; if (image_device_result) *image_device_result = target; - if (flags) + if (oflags) *oflags = flags; out: @@ -449,6 +466,15 @@ out: if (error && ref) { + if (ref->pinned) + { + _dk_cs_pin_t pin; + bzero(&pin, sizeof(pin)); + + pin.cp_flags = _DKIOCCSPINDISCARDBLACKLIST; + p1 = &device; + (void) do_ioctl(p1, p2, _DKIOCCSUNPINEXTENT, (caddr_t)&pin); + } if (ref->vp) { vnode_close(ref->vp, FWRITE, ref->ctx); @@ -463,11 +489,11 @@ out: } int -kern_write_file(struct kern_direct_file_io_ref_t * ref, off_t offset, caddr_t addr, vm_size_t len) +kern_write_file(struct kern_direct_file_io_ref_t * ref, off_t offset, caddr_t addr, vm_size_t len, int ioflag) { return (vn_rdwr(UIO_WRITE, ref->vp, addr, len, offset, - UIO_SYSSPACE, IO_SYNC|IO_NODELOCKED|IO_UNIT, + UIO_SYSSPACE, ioflag|IO_SYNC|IO_NODELOCKED|IO_UNIT, vfs_context_ucred(ref->ctx), (int *) 0, vfs_context_proc(ref->ctx))); } @@ -479,6 +505,7 @@ kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref, off_t discard_offset, off_t discard_end) { int error; + _dk_cs_pin_t pin; kprintf("kern_close_file_for_direct_io\n"); if (!ref) return; @@ -503,15 +530,23 @@ kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref, do_ioctl = &device_ioctl; } (void) do_ioctl(p1, p2, DKIOCUNLOCKPHYSICALEXTENTS, NULL); - - if (addr && write_length) + + if (ref->pinned) { - (void) kern_write_file(ref, write_offset, addr, write_length); + bzero(&pin, sizeof(pin)); + pin.cp_flags = _DKIOCCSPINDISCARDBLACKLIST; + (void) do_ioctl(p1, p2, _DKIOCCSUNPINEXTENT, (caddr_t)&pin); } + + if (discard_offset && discard_end && !ref->pinned) { (void) kern_ioctl_file_extents(ref, DKIOCUNMAP, discard_offset, discard_end); } + if (addr && write_length) + { + (void) kern_write_file(ref, write_offset, addr, write_length, 0); + } error = vnode_close(ref->vp, FWRITE, ref->ctx); @@ -522,4 +557,3 @@ kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref, ref->ctx = NULL; kfree(ref, sizeof(struct kern_direct_file_io_ref_t)); } -