/*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
void vm_swapfile_open(const char *path, vnode_t *vp);
void vm_swapfile_close(uint64_t path, vnode_t vp);
-int vm_swapfile_preallocate(vnode_t vp, uint64_t *size);
+int vm_swapfile_preallocate(vnode_t vp, uint64_t *size, boolean_t *pin);
uint64_t vm_swapfile_get_blksize(vnode_t vp);
uint64_t vm_swapfile_get_transfer_size(vnode_t vp);
int vm_swapfile_io(vnode_t vp, uint64_t offset, uint64_t start, int npages, int flags);
+int vm_record_file_write(struct vnode *vp, uint64_t offset, char *buf, int size);
+
void
vm_swapfile_open(const char *path, vnode_t *vp)
{
int error = 0;
- vfs_context_t ctx = vfs_context_current();
+ vfs_context_t ctx = vfs_context_kernel();
if ((error = vnode_open(path, (O_CREAT | O_TRUNC | FREAD | FWRITE), S_IRUSR | S_IWUSR, 0, vp, ctx))) {
printf("Failed to open swap file %d\n", error);
return;
}
+ /*
+ * If MNT_IOFLAGS_NOSWAP is set, opening the swap file should fail.
+ * To avoid a race on the mount we only make this check after creating the
+ * vnode.
+ */
+ if ((*vp)->v_mount->mnt_kern_flag & MNTK_NOSWAP) {
+ vnode_put(*vp);
+ vm_swapfile_close((uint64_t)path, *vp);
+ *vp = NULL;
+ return;
+ }
+
vnode_put(*vp);
}
void
vm_swapfile_close(uint64_t path_addr, vnode_t vp)
{
- vfs_context_t context = vfs_context_current();
+ vfs_context_t context = vfs_context_kernel();
int error;
vnode_getwithref(vp);
}
int
-vm_swapfile_preallocate(vnode_t vp, uint64_t *size)
+vm_swapfile_preallocate(vnode_t vp, uint64_t *size, boolean_t *pin)
{
int error = 0;
uint64_t file_size = 0;
vfs_context_t ctx = NULL;
- ctx = vfs_context_current();
-
-#if CONFIG_PROTECT
- {
-#if 0 // <rdar://11771612>
-
- if ((error = cp_vnode_setclass(vp, PROTECTION_CLASS_F))) {
- if(config_protect_bug) {
- printf("swap protection class set failed with %d\n", error);
- } else {
- panic("swap protection class set failed with %d\n", error);
- }
- }
-#endif
- /* initialize content protection keys manually */
- if ((error = cp_handle_vnop(vp, CP_WRITE_ACCESS, 0)) != 0) {
- printf("Content Protection key failure on swap: %d\n", error);
- vnode_put(vp);
- vp = NULL;
- goto done;
- }
- }
-#endif
+ ctx = vfs_context_kernel();
error = vnode_setsize(vp, *size, IO_NOZEROFILL, ctx);
if (error) {
printf("vnode_size (new file) for swap file failed: %d\n", error);
+ goto done;
}
-
assert(file_size == *size);
+ if (pin != NULL && *pin != FALSE) {
+ error = VNOP_IOCTL(vp, FIOPINSWAP, NULL, 0, ctx);
+
+ if (error) {
+ printf("pin for swap files failed: %d, file_size = %lld\n", error, file_size);
+ /* this is not fatal, carry on with files wherever they landed */
+ *pin = FALSE;
+ error = 0;
+ }
+ }
+
vnode_lock_spin(vp);
SET(vp->v_flag, VSWAP);
vnode_unlock(vp);
return error;
}
+
+int
+vm_record_file_write(vnode_t vp, uint64_t offset, char *buf, int size)
+{
+ int error = 0;
+ vfs_context_t ctx;
+
+ ctx = vfs_context_kernel();
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)buf, size, offset,
+ UIO_SYSSPACE, IO_NODELOCKED, vfs_context_ucred(ctx), (int *) 0, vfs_context_proc(ctx));
+
+ return (error);
+}
+
+
+
int
vm_swapfile_io(vnode_t vp, uint64_t offset, uint64_t start, int npages, int flags)
{
kern_return_t kr = KERN_SUCCESS;
upl_t upl = NULL;
unsigned int count = 0;
- int upl_create_flags = 0, upl_control_flags = 0;
+ upl_control_flags_t upl_create_flags = 0;
+ int upl_control_flags = 0;
upl_size_t upl_size = 0;
- upl_create_flags = UPL_SET_INTERNAL | UPL_SET_LITE;
+ upl_create_flags = UPL_SET_INTERNAL | UPL_SET_LITE
+ | UPL_MEMORY_TAG_MAKE(VM_KERN_MEMORY_OSFMK);
#if ENCRYPTED_SWAP
upl_control_flags = UPL_IOSYNC | UPL_PAGING_ENCRYPTED;