1*33de042dSApple OSS Distributions /*
2*33de042dSApple OSS Distributions * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
3*33de042dSApple OSS Distributions *
4*33de042dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*33de042dSApple OSS Distributions *
6*33de042dSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*33de042dSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*33de042dSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*33de042dSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*33de042dSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*33de042dSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*33de042dSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*33de042dSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*33de042dSApple OSS Distributions *
15*33de042dSApple OSS Distributions * Please obtain a copy of the License at
16*33de042dSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*33de042dSApple OSS Distributions *
18*33de042dSApple OSS Distributions * The Original Code and all software distributed under the License are
19*33de042dSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*33de042dSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*33de042dSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*33de042dSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*33de042dSApple OSS Distributions * Please see the License for the specific language governing rights and
24*33de042dSApple OSS Distributions * limitations under the License.
25*33de042dSApple OSS Distributions *
26*33de042dSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*33de042dSApple OSS Distributions */
28*33de042dSApple OSS Distributions
29*33de042dSApple OSS Distributions #include <stdint.h>
30*33de042dSApple OSS Distributions #include <sys/fcntl.h>
31*33de042dSApple OSS Distributions #include <sys/vnode_internal.h>
32*33de042dSApple OSS Distributions #include <sys/vnode.h>
33*33de042dSApple OSS Distributions #include <sys/kauth.h>
34*33de042dSApple OSS Distributions #include <sys/mount_internal.h>
35*33de042dSApple OSS Distributions #include <sys/buf_internal.h>
36*33de042dSApple OSS Distributions #include <kern/debug.h>
37*33de042dSApple OSS Distributions #include <kern/kalloc.h>
38*33de042dSApple OSS Distributions #include <sys/cprotect.h>
39*33de042dSApple OSS Distributions #include <sys/disk.h>
40*33de042dSApple OSS Distributions #include <vm/vm_protos_internal.h>
41*33de042dSApple OSS Distributions #include <vm/vm_pageout_xnu.h>
42*33de042dSApple OSS Distributions #include <sys/content_protection.h>
43*33de042dSApple OSS Distributions #include <vm/vm_ubc.h>
44*33de042dSApple OSS Distributions #include <vm/vm_compressor_backing_store_internal.h>
45*33de042dSApple OSS Distributions
46*33de042dSApple OSS Distributions void
vm_swapfile_open(const char * path,vnode_t * vp)47*33de042dSApple OSS Distributions vm_swapfile_open(const char *path, vnode_t *vp)
48*33de042dSApple OSS Distributions {
49*33de042dSApple OSS Distributions int error = 0;
50*33de042dSApple OSS Distributions vfs_context_t ctx = vfs_context_kernel();
51*33de042dSApple OSS Distributions
52*33de042dSApple OSS Distributions if ((error = vnode_open(path, (O_CREAT | O_TRUNC | FREAD | FWRITE), S_IRUSR | S_IWUSR, 0, vp, ctx))) {
53*33de042dSApple OSS Distributions printf("Failed to open swap file %d\n", error);
54*33de042dSApple OSS Distributions *vp = NULL;
55*33de042dSApple OSS Distributions return;
56*33de042dSApple OSS Distributions }
57*33de042dSApple OSS Distributions
58*33de042dSApple OSS Distributions /*
59*33de042dSApple OSS Distributions * If MNT_IOFLAGS_NOSWAP is set, opening the swap file should fail.
60*33de042dSApple OSS Distributions * To avoid a race on the mount we only make this check after creating the
61*33de042dSApple OSS Distributions * vnode.
62*33de042dSApple OSS Distributions */
63*33de042dSApple OSS Distributions if ((*vp)->v_mount->mnt_kern_flag & MNTK_NOSWAP) {
64*33de042dSApple OSS Distributions vnode_put(*vp);
65*33de042dSApple OSS Distributions vm_swapfile_close((uint64_t)path, *vp);
66*33de042dSApple OSS Distributions *vp = NULL;
67*33de042dSApple OSS Distributions return;
68*33de042dSApple OSS Distributions }
69*33de042dSApple OSS Distributions
70*33de042dSApple OSS Distributions vnode_put(*vp);
71*33de042dSApple OSS Distributions }
72*33de042dSApple OSS Distributions
73*33de042dSApple OSS Distributions uint64_t
vm_swapfile_get_blksize(vnode_t vp)74*33de042dSApple OSS Distributions vm_swapfile_get_blksize(vnode_t vp)
75*33de042dSApple OSS Distributions {
76*33de042dSApple OSS Distributions return (uint64_t)vfs_devblocksize(vnode_mount(vp));
77*33de042dSApple OSS Distributions }
78*33de042dSApple OSS Distributions
79*33de042dSApple OSS Distributions uint64_t
vm_swapfile_get_transfer_size(vnode_t vp)80*33de042dSApple OSS Distributions vm_swapfile_get_transfer_size(vnode_t vp)
81*33de042dSApple OSS Distributions {
82*33de042dSApple OSS Distributions return (uint64_t)vp->v_mount->mnt_vfsstat.f_iosize;
83*33de042dSApple OSS Distributions }
84*33de042dSApple OSS Distributions
85*33de042dSApple OSS Distributions int unlink1(vfs_context_t, vnode_t, user_addr_t, enum uio_seg, int);
86*33de042dSApple OSS Distributions
87*33de042dSApple OSS Distributions void
vm_swapfile_close(uint64_t path_addr,vnode_t vp)88*33de042dSApple OSS Distributions vm_swapfile_close(uint64_t path_addr, vnode_t vp)
89*33de042dSApple OSS Distributions {
90*33de042dSApple OSS Distributions vfs_context_t context = vfs_context_kernel();
91*33de042dSApple OSS Distributions int error;
92*33de042dSApple OSS Distributions
93*33de042dSApple OSS Distributions vnode_getwithref(vp);
94*33de042dSApple OSS Distributions vnode_close(vp, 0, context);
95*33de042dSApple OSS Distributions
96*33de042dSApple OSS Distributions error = unlink1(context, NULLVP, CAST_USER_ADDR_T(path_addr),
97*33de042dSApple OSS Distributions UIO_SYSSPACE, 0);
98*33de042dSApple OSS Distributions
99*33de042dSApple OSS Distributions #if DEVELOPMENT || DEBUG
100*33de042dSApple OSS Distributions if (error) {
101*33de042dSApple OSS Distributions printf("%s : unlink of %s failed with error %d", __FUNCTION__,
102*33de042dSApple OSS Distributions (char *)path_addr, error);
103*33de042dSApple OSS Distributions }
104*33de042dSApple OSS Distributions #endif
105*33de042dSApple OSS Distributions }
106*33de042dSApple OSS Distributions
107*33de042dSApple OSS Distributions int
vm_swapfile_preallocate(vnode_t vp,uint64_t * size,boolean_t * pin)108*33de042dSApple OSS Distributions vm_swapfile_preallocate(vnode_t vp, uint64_t *size, boolean_t *pin)
109*33de042dSApple OSS Distributions {
110*33de042dSApple OSS Distributions int error = 0;
111*33de042dSApple OSS Distributions uint64_t file_size = 0;
112*33de042dSApple OSS Distributions vfs_context_t ctx = NULL;
113*33de042dSApple OSS Distributions #if CONFIG_FREEZE
114*33de042dSApple OSS Distributions struct vnode_attr va;
115*33de042dSApple OSS Distributions #endif /* CONFIG_FREEZE */
116*33de042dSApple OSS Distributions
117*33de042dSApple OSS Distributions ctx = vfs_context_kernel();
118*33de042dSApple OSS Distributions
119*33de042dSApple OSS Distributions error = vnode_setsize(vp, *size, IO_NOZEROFILL, ctx);
120*33de042dSApple OSS Distributions
121*33de042dSApple OSS Distributions if (error) {
122*33de042dSApple OSS Distributions printf("vnode_setsize for swap files failed: %d\n", error);
123*33de042dSApple OSS Distributions goto done;
124*33de042dSApple OSS Distributions }
125*33de042dSApple OSS Distributions
126*33de042dSApple OSS Distributions error = vnode_size(vp, (off_t*) &file_size, ctx);
127*33de042dSApple OSS Distributions
128*33de042dSApple OSS Distributions if (error) {
129*33de042dSApple OSS Distributions printf("vnode_size (new file) for swap file failed: %d\n", error);
130*33de042dSApple OSS Distributions goto done;
131*33de042dSApple OSS Distributions }
132*33de042dSApple OSS Distributions assert(file_size == *size);
133*33de042dSApple OSS Distributions
134*33de042dSApple OSS Distributions if (pin != NULL && *pin != FALSE) {
135*33de042dSApple OSS Distributions error = VNOP_IOCTL(vp, FIOPINSWAP, NULL, 0, ctx);
136*33de042dSApple OSS Distributions
137*33de042dSApple OSS Distributions if (error) {
138*33de042dSApple OSS Distributions printf("pin for swap files failed: %d, file_size = %lld\n", error, file_size);
139*33de042dSApple OSS Distributions /* this is not fatal, carry on with files wherever they landed */
140*33de042dSApple OSS Distributions *pin = FALSE;
141*33de042dSApple OSS Distributions error = 0;
142*33de042dSApple OSS Distributions }
143*33de042dSApple OSS Distributions }
144*33de042dSApple OSS Distributions
145*33de042dSApple OSS Distributions vnode_lock_spin(vp);
146*33de042dSApple OSS Distributions SET(vp->v_flag, VSWAP);
147*33de042dSApple OSS Distributions vnode_unlock(vp);
148*33de042dSApple OSS Distributions
149*33de042dSApple OSS Distributions #if CONFIG_FREEZE
150*33de042dSApple OSS Distributions VATTR_INIT(&va);
151*33de042dSApple OSS Distributions VATTR_SET(&va, va_dataprotect_class, PROTECTION_CLASS_C);
152*33de042dSApple OSS Distributions error = VNOP_SETATTR(vp, &va, ctx);
153*33de042dSApple OSS Distributions
154*33de042dSApple OSS Distributions if (error) {
155*33de042dSApple OSS Distributions printf("setattr PROTECTION_CLASS_C for swap file failed: %d\n", error);
156*33de042dSApple OSS Distributions goto done;
157*33de042dSApple OSS Distributions }
158*33de042dSApple OSS Distributions #endif /* CONFIG_FREEZE */
159*33de042dSApple OSS Distributions
160*33de042dSApple OSS Distributions done:
161*33de042dSApple OSS Distributions return error;
162*33de042dSApple OSS Distributions }
163*33de042dSApple OSS Distributions
164*33de042dSApple OSS Distributions
165*33de042dSApple OSS Distributions int
vm_record_file_write(vnode_t vp,uint64_t offset,char * buf,int size)166*33de042dSApple OSS Distributions vm_record_file_write(vnode_t vp, uint64_t offset, char *buf, int size)
167*33de042dSApple OSS Distributions {
168*33de042dSApple OSS Distributions int error = 0;
169*33de042dSApple OSS Distributions vfs_context_t ctx;
170*33de042dSApple OSS Distributions
171*33de042dSApple OSS Distributions ctx = vfs_context_kernel();
172*33de042dSApple OSS Distributions
173*33de042dSApple OSS Distributions error = vn_rdwr(UIO_WRITE, vp, (caddr_t)buf, size, offset,
174*33de042dSApple OSS Distributions UIO_SYSSPACE, IO_NODELOCKED, vfs_context_ucred(ctx), (int *) 0, vfs_context_proc(ctx));
175*33de042dSApple OSS Distributions
176*33de042dSApple OSS Distributions return error;
177*33de042dSApple OSS Distributions }
178*33de042dSApple OSS Distributions
179*33de042dSApple OSS Distributions
180*33de042dSApple OSS Distributions
181*33de042dSApple OSS Distributions int
vm_swapfile_io(vnode_t vp,uint64_t offset,uint64_t start,int npages,int flags,void * upl_iodone)182*33de042dSApple OSS Distributions vm_swapfile_io(vnode_t vp, uint64_t offset, uint64_t start, int npages, int flags, void *upl_iodone)
183*33de042dSApple OSS Distributions {
184*33de042dSApple OSS Distributions int error = 0;
185*33de042dSApple OSS Distributions upl_size_t io_size = (upl_size_t) (npages * PAGE_SIZE_64);
186*33de042dSApple OSS Distributions #if 1
187*33de042dSApple OSS Distributions kern_return_t kr = KERN_SUCCESS;
188*33de042dSApple OSS Distributions upl_t upl = NULL;
189*33de042dSApple OSS Distributions unsigned int count = 0;
190*33de042dSApple OSS Distributions upl_control_flags_t upl_create_flags = 0;
191*33de042dSApple OSS Distributions int upl_control_flags = 0;
192*33de042dSApple OSS Distributions upl_size_t upl_size = 0;
193*33de042dSApple OSS Distributions
194*33de042dSApple OSS Distributions upl_create_flags = UPL_SET_INTERNAL | UPL_SET_LITE;
195*33de042dSApple OSS Distributions
196*33de042dSApple OSS Distributions if (upl_iodone == NULL) {
197*33de042dSApple OSS Distributions upl_control_flags = UPL_IOSYNC;
198*33de042dSApple OSS Distributions }
199*33de042dSApple OSS Distributions
200*33de042dSApple OSS Distributions #if ENCRYPTED_SWAP
201*33de042dSApple OSS Distributions upl_control_flags |= UPL_PAGING_ENCRYPTED;
202*33de042dSApple OSS Distributions #endif
203*33de042dSApple OSS Distributions
204*33de042dSApple OSS Distributions if ((flags & SWAP_READ) == FALSE) {
205*33de042dSApple OSS Distributions upl_create_flags |= UPL_COPYOUT_FROM;
206*33de042dSApple OSS Distributions }
207*33de042dSApple OSS Distributions
208*33de042dSApple OSS Distributions upl_size = io_size;
209*33de042dSApple OSS Distributions kr = vm_map_create_upl( kernel_map,
210*33de042dSApple OSS Distributions start,
211*33de042dSApple OSS Distributions &upl_size,
212*33de042dSApple OSS Distributions &upl,
213*33de042dSApple OSS Distributions NULL,
214*33de042dSApple OSS Distributions &count,
215*33de042dSApple OSS Distributions &upl_create_flags,
216*33de042dSApple OSS Distributions VM_KERN_MEMORY_OSFMK);
217*33de042dSApple OSS Distributions
218*33de042dSApple OSS Distributions if (kr != KERN_SUCCESS || (upl_size != io_size)) {
219*33de042dSApple OSS Distributions panic("vm_map_create_upl failed with %d", kr);
220*33de042dSApple OSS Distributions }
221*33de042dSApple OSS Distributions
222*33de042dSApple OSS Distributions if (flags & SWAP_READ) {
223*33de042dSApple OSS Distributions vnode_pagein(vp,
224*33de042dSApple OSS Distributions upl,
225*33de042dSApple OSS Distributions 0,
226*33de042dSApple OSS Distributions offset,
227*33de042dSApple OSS Distributions io_size,
228*33de042dSApple OSS Distributions upl_control_flags | UPL_IGNORE_VALID_PAGE_CHECK,
229*33de042dSApple OSS Distributions &error);
230*33de042dSApple OSS Distributions if (error) {
231*33de042dSApple OSS Distributions #if DEBUG
232*33de042dSApple OSS Distributions printf("vm_swapfile_io: vnode_pagein failed with %d (vp: %p, offset: 0x%llx, size:%u)\n", error, vp, offset, io_size);
233*33de042dSApple OSS Distributions #else /* DEBUG */
234*33de042dSApple OSS Distributions printf("vm_swapfile_io: vnode_pagein failed with %d.\n", error);
235*33de042dSApple OSS Distributions #endif /* DEBUG */
236*33de042dSApple OSS Distributions }
237*33de042dSApple OSS Distributions } else {
238*33de042dSApple OSS Distributions upl_set_iodone(upl, upl_iodone);
239*33de042dSApple OSS Distributions
240*33de042dSApple OSS Distributions vnode_pageout(vp,
241*33de042dSApple OSS Distributions upl,
242*33de042dSApple OSS Distributions 0,
243*33de042dSApple OSS Distributions offset,
244*33de042dSApple OSS Distributions io_size,
245*33de042dSApple OSS Distributions upl_control_flags,
246*33de042dSApple OSS Distributions &error);
247*33de042dSApple OSS Distributions if (error) {
248*33de042dSApple OSS Distributions #if DEBUG
249*33de042dSApple OSS Distributions printf("vm_swapfile_io: vnode_pageout failed with %d (vp: %p, offset: 0x%llx, size:%u)\n", error, vp, offset, io_size);
250*33de042dSApple OSS Distributions #else /* DEBUG */
251*33de042dSApple OSS Distributions printf("vm_swapfile_io: vnode_pageout failed with %d.\n", error);
252*33de042dSApple OSS Distributions #endif /* DEBUG */
253*33de042dSApple OSS Distributions }
254*33de042dSApple OSS Distributions }
255*33de042dSApple OSS Distributions
256*33de042dSApple OSS Distributions return error;
257*33de042dSApple OSS Distributions
258*33de042dSApple OSS Distributions #else /* 1 */
259*33de042dSApple OSS Distributions vfs_context_t ctx;
260*33de042dSApple OSS Distributions ctx = vfs_context_kernel();
261*33de042dSApple OSS Distributions
262*33de042dSApple OSS Distributions error = vn_rdwr((flags & SWAP_READ) ? UIO_READ : UIO_WRITE, vp, (caddr_t)start, io_size, offset,
263*33de042dSApple OSS Distributions UIO_SYSSPACE, IO_SYNC | IO_NODELOCKED | IO_UNIT | IO_NOCACHE | IO_SWAP_DISPATCH, vfs_context_ucred(ctx), (int *) 0, vfs_context_proc(ctx));
264*33de042dSApple OSS Distributions
265*33de042dSApple OSS Distributions if (error) {
266*33de042dSApple OSS Distributions printf("vn_rdwr: Swap I/O failed with %d\n", error);
267*33de042dSApple OSS Distributions }
268*33de042dSApple OSS Distributions return error;
269*33de042dSApple OSS Distributions #endif /* 1 */
270*33de042dSApple OSS Distributions }
271*33de042dSApple OSS Distributions
272*33de042dSApple OSS Distributions
273*33de042dSApple OSS Distributions #define MAX_BATCH_TO_TRIM 256
274*33de042dSApple OSS Distributions
275*33de042dSApple OSS Distributions #define ROUTE_ONLY 0x10 /* if corestorage is present, tell it to just pass */
276*33de042dSApple OSS Distributions /* the DKIOUNMAP command through w/o acting on it */
277*33de042dSApple OSS Distributions /* this is used by the compressed swap system to reclaim empty space */
278*33de042dSApple OSS Distributions
279*33de042dSApple OSS Distributions
280*33de042dSApple OSS Distributions u_int32_t
vnode_trim_list(vnode_t vp,struct trim_list * tl,boolean_t route_only)281*33de042dSApple OSS Distributions vnode_trim_list(vnode_t vp, struct trim_list *tl, boolean_t route_only)
282*33de042dSApple OSS Distributions {
283*33de042dSApple OSS Distributions int error = 0;
284*33de042dSApple OSS Distributions int trim_index = 0;
285*33de042dSApple OSS Distributions u_int32_t blocksize = 0;
286*33de042dSApple OSS Distributions struct vnode *devvp;
287*33de042dSApple OSS Distributions dk_extent_t *extents;
288*33de042dSApple OSS Distributions dk_unmap_t unmap;
289*33de042dSApple OSS Distributions _dk_cs_unmap_t cs_unmap;
290*33de042dSApple OSS Distributions
291*33de042dSApple OSS Distributions if (!(vp->v_mount->mnt_ioflags & MNT_IOFLAGS_UNMAP_SUPPORTED)) {
292*33de042dSApple OSS Distributions return ENOTSUP;
293*33de042dSApple OSS Distributions }
294*33de042dSApple OSS Distributions
295*33de042dSApple OSS Distributions if (tl == NULL) {
296*33de042dSApple OSS Distributions return 0;
297*33de042dSApple OSS Distributions }
298*33de042dSApple OSS Distributions
299*33de042dSApple OSS Distributions /*
300*33de042dSApple OSS Distributions * Get the underlying device vnode and physical block size
301*33de042dSApple OSS Distributions */
302*33de042dSApple OSS Distributions devvp = vp->v_mount->mnt_devvp;
303*33de042dSApple OSS Distributions blocksize = vp->v_mount->mnt_devblocksize;
304*33de042dSApple OSS Distributions
305*33de042dSApple OSS Distributions extents = kalloc_data(sizeof(dk_extent_t) * MAX_BATCH_TO_TRIM, Z_WAITOK);
306*33de042dSApple OSS Distributions
307*33de042dSApple OSS Distributions if (vp->v_mount->mnt_ioflags & MNT_IOFLAGS_CSUNMAP_SUPPORTED) {
308*33de042dSApple OSS Distributions memset(&cs_unmap, 0, sizeof(_dk_cs_unmap_t));
309*33de042dSApple OSS Distributions cs_unmap.extents = extents;
310*33de042dSApple OSS Distributions
311*33de042dSApple OSS Distributions if (route_only == TRUE) {
312*33de042dSApple OSS Distributions cs_unmap.options = ROUTE_ONLY;
313*33de042dSApple OSS Distributions }
314*33de042dSApple OSS Distributions } else {
315*33de042dSApple OSS Distributions memset(&unmap, 0, sizeof(dk_unmap_t));
316*33de042dSApple OSS Distributions unmap.extents = extents;
317*33de042dSApple OSS Distributions }
318*33de042dSApple OSS Distributions
319*33de042dSApple OSS Distributions while (tl) {
320*33de042dSApple OSS Distributions daddr64_t io_blockno; /* Block number corresponding to the start of the extent */
321*33de042dSApple OSS Distributions size_t io_bytecount; /* Number of bytes in current extent for the specified range */
322*33de042dSApple OSS Distributions size_t trimmed;
323*33de042dSApple OSS Distributions size_t remaining_length;
324*33de042dSApple OSS Distributions off_t current_offset;
325*33de042dSApple OSS Distributions
326*33de042dSApple OSS Distributions current_offset = tl->tl_offset;
327*33de042dSApple OSS Distributions remaining_length = tl->tl_length;
328*33de042dSApple OSS Distributions trimmed = 0;
329*33de042dSApple OSS Distributions
330*33de042dSApple OSS Distributions /*
331*33de042dSApple OSS Distributions * We may not get the entire range from tl_offset -> tl_offset+tl_length in a single
332*33de042dSApple OSS Distributions * extent from the blockmap call. Keep looping/going until we are sure we've hit
333*33de042dSApple OSS Distributions * the whole range or if we encounter an error.
334*33de042dSApple OSS Distributions */
335*33de042dSApple OSS Distributions while (trimmed < tl->tl_length) {
336*33de042dSApple OSS Distributions /*
337*33de042dSApple OSS Distributions * VNOP_BLOCKMAP will tell us the logical to physical block number mapping for the
338*33de042dSApple OSS Distributions * specified offset. It returns blocks in contiguous chunks, so if the logical range is
339*33de042dSApple OSS Distributions * broken into multiple extents, it must be called multiple times, increasing the offset
340*33de042dSApple OSS Distributions * in each call to ensure that the entire range is covered.
341*33de042dSApple OSS Distributions */
342*33de042dSApple OSS Distributions error = VNOP_BLOCKMAP(vp, current_offset, remaining_length,
343*33de042dSApple OSS Distributions &io_blockno, &io_bytecount, NULL, VNODE_READ | VNODE_BLOCKMAP_NO_TRACK, NULL);
344*33de042dSApple OSS Distributions
345*33de042dSApple OSS Distributions if (error) {
346*33de042dSApple OSS Distributions goto trim_exit;
347*33de042dSApple OSS Distributions }
348*33de042dSApple OSS Distributions if (io_blockno != -1) {
349*33de042dSApple OSS Distributions extents[trim_index].offset = (uint64_t) io_blockno * (u_int64_t) blocksize;
350*33de042dSApple OSS Distributions extents[trim_index].length = io_bytecount;
351*33de042dSApple OSS Distributions
352*33de042dSApple OSS Distributions trim_index++;
353*33de042dSApple OSS Distributions }
354*33de042dSApple OSS Distributions if (trim_index == MAX_BATCH_TO_TRIM) {
355*33de042dSApple OSS Distributions if (vp->v_mount->mnt_ioflags & MNT_IOFLAGS_CSUNMAP_SUPPORTED) {
356*33de042dSApple OSS Distributions cs_unmap.extentsCount = trim_index;
357*33de042dSApple OSS Distributions error = VNOP_IOCTL(devvp, _DKIOCCSUNMAP, (caddr_t)&cs_unmap, 0, vfs_context_kernel());
358*33de042dSApple OSS Distributions } else {
359*33de042dSApple OSS Distributions unmap.extentsCount = trim_index;
360*33de042dSApple OSS Distributions error = VNOP_IOCTL(devvp, DKIOCUNMAP, (caddr_t)&unmap, 0, vfs_context_kernel());
361*33de042dSApple OSS Distributions }
362*33de042dSApple OSS Distributions if (error) {
363*33de042dSApple OSS Distributions goto trim_exit;
364*33de042dSApple OSS Distributions }
365*33de042dSApple OSS Distributions trim_index = 0;
366*33de042dSApple OSS Distributions }
367*33de042dSApple OSS Distributions trimmed += io_bytecount;
368*33de042dSApple OSS Distributions current_offset += io_bytecount;
369*33de042dSApple OSS Distributions remaining_length -= io_bytecount;
370*33de042dSApple OSS Distributions }
371*33de042dSApple OSS Distributions tl = tl->tl_next;
372*33de042dSApple OSS Distributions }
373*33de042dSApple OSS Distributions if (trim_index) {
374*33de042dSApple OSS Distributions if (vp->v_mount->mnt_ioflags & MNT_IOFLAGS_CSUNMAP_SUPPORTED) {
375*33de042dSApple OSS Distributions cs_unmap.extentsCount = trim_index;
376*33de042dSApple OSS Distributions error = VNOP_IOCTL(devvp, _DKIOCCSUNMAP, (caddr_t)&cs_unmap, 0, vfs_context_kernel());
377*33de042dSApple OSS Distributions } else {
378*33de042dSApple OSS Distributions unmap.extentsCount = trim_index;
379*33de042dSApple OSS Distributions error = VNOP_IOCTL(devvp, DKIOCUNMAP, (caddr_t)&unmap, 0, vfs_context_kernel());
380*33de042dSApple OSS Distributions }
381*33de042dSApple OSS Distributions }
382*33de042dSApple OSS Distributions trim_exit:
383*33de042dSApple OSS Distributions kfree_data(extents, sizeof(dk_extent_t) * MAX_BATCH_TO_TRIM);
384*33de042dSApple OSS Distributions
385*33de042dSApple OSS Distributions return error;
386*33de042dSApple OSS Distributions }
387*33de042dSApple OSS Distributions
388*33de042dSApple OSS Distributions #if CONFIG_FREEZE
389*33de042dSApple OSS Distributions int
vm_swap_vol_get_budget(vnode_t vp,uint64_t * freeze_daily_budget)390*33de042dSApple OSS Distributions vm_swap_vol_get_budget(vnode_t vp, uint64_t *freeze_daily_budget)
391*33de042dSApple OSS Distributions {
392*33de042dSApple OSS Distributions vnode_t devvp = NULL;
393*33de042dSApple OSS Distributions vfs_context_t ctx = vfs_context_kernel();
394*33de042dSApple OSS Distributions errno_t err = 0;
395*33de042dSApple OSS Distributions
396*33de042dSApple OSS Distributions err = vnode_getwithref(vp);
397*33de042dSApple OSS Distributions if (err == 0) {
398*33de042dSApple OSS Distributions if (vp->v_mount && vp->v_mount->mnt_devvp) {
399*33de042dSApple OSS Distributions devvp = vp->v_mount->mnt_devvp;
400*33de042dSApple OSS Distributions err = VNOP_IOCTL(devvp, DKIOCGETMAXSWAPWRITE, (caddr_t)freeze_daily_budget, 0, ctx);
401*33de042dSApple OSS Distributions } else {
402*33de042dSApple OSS Distributions err = ENODEV;
403*33de042dSApple OSS Distributions }
404*33de042dSApple OSS Distributions vnode_put(vp);
405*33de042dSApple OSS Distributions }
406*33de042dSApple OSS Distributions
407*33de042dSApple OSS Distributions return err;
408*33de042dSApple OSS Distributions }
409*33de042dSApple OSS Distributions #endif /* CONFIG_FREEZE */
410*33de042dSApple OSS Distributions
411*33de042dSApple OSS Distributions int
vm_swap_vol_get_capacity(const char * volume_name,uint64_t * capacity)412*33de042dSApple OSS Distributions vm_swap_vol_get_capacity(const char *volume_name, uint64_t *capacity)
413*33de042dSApple OSS Distributions {
414*33de042dSApple OSS Distributions vfs_context_t ctx = vfs_context_kernel();
415*33de042dSApple OSS Distributions vnode_t vp = NULL, devvp = NULL;
416*33de042dSApple OSS Distributions uint64_t block_size = 0;
417*33de042dSApple OSS Distributions uint64_t block_count = 0;
418*33de042dSApple OSS Distributions int error = 0;
419*33de042dSApple OSS Distributions *capacity = 0;
420*33de042dSApple OSS Distributions
421*33de042dSApple OSS Distributions if ((error = vnode_open(volume_name, FREAD, 0, 0, &vp, ctx))) {
422*33de042dSApple OSS Distributions printf("Unable to open swap volume\n");
423*33de042dSApple OSS Distributions return error;
424*33de042dSApple OSS Distributions }
425*33de042dSApple OSS Distributions
426*33de042dSApple OSS Distributions devvp = vp->v_mount->mnt_devvp;
427*33de042dSApple OSS Distributions if ((error = VNOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, (caddr_t)&block_size, 0, ctx))) {
428*33de042dSApple OSS Distributions printf("Unable to get swap volume block size\n");
429*33de042dSApple OSS Distributions goto out;
430*33de042dSApple OSS Distributions }
431*33de042dSApple OSS Distributions if ((error = VNOP_IOCTL(devvp, DKIOCGETBLOCKCOUNT, (caddr_t)&block_count, 0, ctx))) {
432*33de042dSApple OSS Distributions printf("Unable to get swap volume block count\n");
433*33de042dSApple OSS Distributions goto out;
434*33de042dSApple OSS Distributions }
435*33de042dSApple OSS Distributions
436*33de042dSApple OSS Distributions *capacity = block_count * block_size;
437*33de042dSApple OSS Distributions out:
438*33de042dSApple OSS Distributions error = vnode_close(vp, 0, ctx);
439*33de042dSApple OSS Distributions return error;
440*33de042dSApple OSS Distributions }
441