/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2015 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
-#if !HFS_COMPRESSION
-/* we need these symbols even though compression is turned off */
-char register_decmpfs_decompressor;
-char unregister_decmpfs_decompressor;
-#else /* HFS_COMPRESSION */
+#if !FS_COMPRESSION
+
+/* We need these symbols even though compression is turned off */
+
+#define UNUSED_SYMBOL(x) asm(".global _" #x "\n.set _" #x ", 0\n");
+
+UNUSED_SYMBOL(register_decmpfs_decompressor)
+UNUSED_SYMBOL(unregister_decmpfs_decompressor)
+UNUSED_SYMBOL(decmpfs_init)
+UNUSED_SYMBOL(decmpfs_read_compressed)
+UNUSED_SYMBOL(decmpfs_cnode_cmp_type)
+UNUSED_SYMBOL(decmpfs_cnode_get_vnode_state)
+UNUSED_SYMBOL(decmpfs_cnode_get_vnode_cached_size)
+UNUSED_SYMBOL(decmpfs_lock_compressed_data)
+UNUSED_SYMBOL(decmpfs_cnode_free)
+UNUSED_SYMBOL(decmpfs_cnode_alloc)
+UNUSED_SYMBOL(decmpfs_cnode_destroy)
+UNUSED_SYMBOL(decmpfs_decompress_file)
+UNUSED_SYMBOL(decmpfs_unlock_compressed_data)
+UNUSED_SYMBOL(decmpfs_cnode_init)
+UNUSED_SYMBOL(decmpfs_cnode_set_vnode_state)
+UNUSED_SYMBOL(decmpfs_hides_xattr)
+UNUSED_SYMBOL(decmpfs_ctx)
+UNUSED_SYMBOL(decmpfs_file_is_compressed)
+UNUSED_SYMBOL(decmpfs_update_attributes)
+UNUSED_SYMBOL(decmpfs_hides_rsrc)
+UNUSED_SYMBOL(decmpfs_pagein_compressed)
+UNUSED_SYMBOL(decmpfs_validate_compressed_file)
+
+#else /* FS_COMPRESSION */
#include <sys/kernel.h>
#include <sys/vnode_internal.h>
#include <sys/file_internal.h>
return ret;
}
+static char*
+vnpath(vnode_t vp, char *path, int len)
+{
+ int origlen = len;
+ path[0] = 0;
+ vn_getpath(vp, path, &len);
+ path[origlen - 1] = 0;
+ return path;
+}
+
#define ErrorLog(x, args...) printf("%s:%d:%s: " x, baseName(__FILE__), __LINE__, __FUNCTION__, ## args)
+#define ErrorLogWithPath(x, args...) do { char *path; MALLOC(path, char *, PATH_MAX, M_TEMP, M_WAITOK); printf("%s:%d:%s: %s: " x, baseName(__FILE__), __LINE__, __FUNCTION__, vnpath(vp, path, PATH_MAX), ## args); FREE(path, M_TEMP); } while(0)
#if COMPRESSION_DEBUG
#define DebugLog ErrorLog
+#define DebugLogWithPath ErrorLogWithPath
#else
#define DebugLog(x...) do { } while(0)
+#define DebugLogWithPath(x...) do { } while(0)
#endif
#if COMPRESSION_DEBUG_VERBOSE
#define VerboseLog ErrorLog
+#define VerboseLogWithPath ErrorLogWithPath
#else
#define VerboseLog(x...) do { } while(0)
+#define VerboseLogWithPath(x...) do { } while(0)
#endif
#if MALLOC_DEBUG
extern boolean_t IOCatalogueMatchingDriversPresent( const char * property );
static void *
-_decmp_get_func(uint32_t type, uintptr_t offset)
+_decmp_get_func(vnode_t vp, uint32_t type, uintptr_t offset)
{
/*
this function should be called while holding a shared lock to decompressorsLock,
char resourceName[80];
uint64_t delay = 10000000ULL; // 10 milliseconds.
snprintf(resourceName, sizeof(resourceName), "com.apple.AppleFSCompression.Type%u", type);
- printf("waiting for %s\n", resourceName);
+ ErrorLogWithPath("waiting for %s\n", resourceName);
while(decompressors[type] == NULL) {
lck_rw_unlock_shared(decompressorsLock); // we have to unlock to allow the kext to register
if (IOServiceWaitForMatchingResource(resourceName, delay)) {
}
if (!IOCatalogueMatchingDriversPresent(providesName)) {
//
- printf("the kext with %s is no longer present\n", providesName);
+ ErrorLogWithPath("the kext with %s is no longer present\n", providesName);
lck_rw_lock_shared(decompressorsLock);
break;
}
- printf("still waiting for %s\n", resourceName);
+ ErrorLogWithPath("still waiting for %s\n", resourceName);
delay *= 2;
lck_rw_lock_shared(decompressorsLock);
}
// IOKit says the kext is loaded, so it should be registered too!
if (decompressors[type] == NULL) {
- ErrorLog("we found %s, but the type still isn't registered\n", providesName);
+ ErrorLogWithPath("we found %s, but the type still isn't registered\n", providesName);
return NULL;
}
// it's now registered, so let's return the function
}
// the compressor hasn't registered, so it never will unless someone manually kextloads it
- ErrorLog("tried to access a compressed file of unregistered type %d\n", type);
+ ErrorLogWithPath("tried to access a compressed file of unregistered type %d\n", type);
return NULL;
}
-#define decmp_get_func(type, func) ((typeof(((decmpfs_registration*)NULL)->func))_decmp_get_func(type, offsetof_func(func)))
+#define decmp_get_func(vp, type, func) ((typeof(((decmpfs_registration*)NULL)->func))_decmp_get_func(vp, type, offsetof_func(func)))
#pragma mark --- utilities ---
#if COMPRESSION_DEBUG
-static char*
-vnpath(vnode_t vp, char *path, int len)
-{
- int origlen = len;
- path[0] = 0;
- vn_getpath(vp, path, &len);
- path[origlen - 1] = 0;
- return path;
-}
-
static int
vnsize(vnode_t vp, uint64_t *size)
{
VATTR_WANTED(&va, va_data_size);
int error = vnode_getattr(vp, &va, decmpfs_ctx);
if (error != 0) {
- ErrorLog("vnode_getattr err %d\n", error);
+ ErrorLogWithPath("vnode_getattr err %d\n", error);
return error;
}
*size = va.va_data_size;
#pragma mark --- cnode routines ---
+decmpfs_cnode *decmpfs_cnode_alloc(void)
+{
+ decmpfs_cnode *dp;
+ MALLOC_ZONE(dp, decmpfs_cnode *, sizeof(decmpfs_cnode), M_DECMPFS_CNODE, M_WAITOK);
+ return dp;
+}
+
+void decmpfs_cnode_free(decmpfs_cnode *dp)
+{
+ FREE_ZONE(dp, sizeof(*dp), M_DECMPFS_CNODE);
+}
+
void
decmpfs_cnode_init(decmpfs_cnode *cp)
{
lck_rw_destroy(&cp->compressed_data_lock, decmpfs_lockgrp);
}
-boolean_t
+bool
decmpfs_trylock_compressed_data(decmpfs_cnode *cp, int exclusive)
{
void *thread = current_thread();
- boolean_t retval = FALSE;
+ bool retval = false;
if (cp->lockowner == thread) {
/* this thread is already holding an exclusive lock, so bump the count */
cp->lockcount++;
- retval = TRUE;
+ retval = true;
} else if (exclusive) {
if ((retval = lck_rw_try_lock_exclusive(&cp->compressed_data_lock))) {
cp->lockowner = thread;
}
}
+uint32_t decmpfs_cnode_cmp_type(decmpfs_cnode *cp)
+{
+ return cp->cmp_type;
+}
+
#pragma mark --- decmpfs state routines ---
static int
}
if (hdr->compression_magic != DECMPFS_MAGIC) {
- ErrorLog("invalid compression_magic 0x%08x, should be 0x%08x\n", hdr->compression_magic, DECMPFS_MAGIC);
+ ErrorLogWithPath("invalid compression_magic 0x%08x, should be 0x%08x\n", hdr->compression_magic, DECMPFS_MAGIC);
err = EINVAL;
goto out;
}
/* return the header even though the type is out of range */
err = ERANGE;
} else {
- ErrorLog("compression_type %d out of range\n", hdr->compression_type);
+ ErrorLogWithPath("compression_type %d out of range\n", hdr->compression_type);
err = EINVAL;
}
goto out;
out:
if (err && (err != ERANGE)) {
- DebugLog("err %d\n", err);
+ DebugLogWithPath("err %d\n", err);
if (data) FREE(data, M_TEMP);
*hdrOut = NULL;
} else {
}
lck_rw_lock_shared(decompressorsLock);
- decmpfs_validate_compressed_file_func validate = decmp_get_func(hdr->compression_type, validate);
+ decmpfs_validate_compressed_file_func validate = decmp_get_func(vp, hdr->compression_type, validate);
if (validate) { /* make sure this validation function is valid */
/* is the data okay? */
err = validate(vp, decmpfs_ctx, hdr);
- } else if (decmp_get_func(hdr->compression_type, fetch) == NULL) {
+ } else if (decmp_get_func(vp, hdr->compression_type, fetch) == NULL) {
/* the type isn't registered */
err = EIO;
} else {
if (hdr) FREE(hdr, M_TEMP);
#if COMPRESSION_DEBUG
if (err) {
- DebugLog("decmpfs_validate_compressed_file ret %d, vp->v_flag %d\n", err, vp->v_flag);
+ DebugLogWithPath("decmpfs_validate_compressed_file ret %d, vp->v_flag %d\n", err, vp->v_flag);
}
#endif
return err;
break;
default:
/* unknown state, assume file is not compressed */
- ErrorLog("unknown cmp_state %d\n", cmp_state);
+ ErrorLogWithPath("unknown cmp_state %d\n", cmp_state);
return 0;
}
-// if (!vnode_isreg(vp)) {
-// /* only regular files can be compressed */
-// ret = FILE_IS_NOT_COMPRESSED;
-// goto done;
-// }
+ if (!vnode_isreg(vp)) {
+ /* only regular files can be compressed */
+ ret = FILE_IS_NOT_COMPRESSED;
+ goto done;
+ }
mp = vnode_mount(vp);
if (mp == NULL) {
/* update the decompression flags in the decmpfs cnode */
lck_rw_lock_shared(decompressorsLock);
- decmpfs_get_decompression_flags_func get_flags = decmp_get_func(hdr->compression_type, get_flags);
+ decmpfs_get_decompression_flags_func get_flags = decmp_get_func(vp, hdr->compression_type, get_flags);
if (get_flags) {
decompression_flags = get_flags(vp, decmpfs_ctx, hdr);
}
return 1;
default:
/* unknown state, assume file is not compressed */
- ErrorLog("unknown ret %d\n", ret);
+ ErrorLogWithPath("unknown ret %d\n", ret);
return 0;
}
}
if (ctx == decmpfs_ctx)
return 0;
- if (strncmp(xattr, XATTR_RESOURCEFORK_NAME, 22) == 0)
+ if (strncmp(xattr, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME) - 1) == 0)
return decmpfs_hides_rsrc(ctx, cp);
if (!decmpfs_fast_file_is_compressed(cp))
/* file is not compressed, so don't hide this xattr */
return 0;
- if (strncmp(xattr, DECMPFS_XATTR_NAME, 11) == 0)
+ if (strncmp(xattr, DECMPFS_XATTR_NAME, sizeof(DECMPFS_XATTR_NAME) - 1) == 0)
/* it's our xattr, so hide it */
return 1;
/* don't hide this xattr */
}
static int
-compression_type_valid(decmpfs_header *hdr)
+compression_type_valid(vnode_t vp, decmpfs_header *hdr)
{
/* fast pre-check to determine if the given compressor has checked in */
int ret = 0;
/* every compressor must have at least a fetch function */
lck_rw_lock_shared(decompressorsLock);
- if (decmp_get_func(hdr->compression_type, fetch) != NULL) {
+ if (decmp_get_func(vp, hdr->compression_type, fetch) != NULL) {
ret = 1;
}
lck_rw_unlock_shared(decompressorsLock);
}
lck_rw_lock_shared(decompressorsLock);
- decmpfs_fetch_uncompressed_data_func fetch = decmp_get_func(hdr->compression_type, fetch);
+ decmpfs_fetch_uncompressed_data_func fetch = decmp_get_func(vp, hdr->compression_type, fetch);
if (fetch) {
err = fetch(vp, decmpfs_ctx, hdr, offset, size, nvec, vec, bytes_read);
lck_rw_unlock_shared(decompressorsLock);
commit_upl(upl_t upl, upl_offset_t pl_offset, size_t uplSize, int flags, int abort)
{
kern_return_t kr = 0;
+
+#if CONFIG_IOSCHED
+ upl_unmark_decmp(upl);
+#endif /* CONFIG_IOSCHED */
/* commit the upl pages */
if (abort) {
VerboseLog("aborting upl, flags 0x%08x\n", flags);
kr = ubc_upl_abort_range(upl, pl_offset, uplSize, flags);
if (kr != KERN_SUCCESS)
- ErrorLog("ubc_upl_commit_range error %d\n", (int)kr);
+ ErrorLog("ubc_upl_abort_range error %d\n", (int)kr);
} else {
VerboseLog("committing upl, flags 0x%08x\n", flags | UPL_COMMIT_CLEAR_DIRTY);
- kr = ubc_upl_commit_range(upl, pl_offset, uplSize, flags | UPL_COMMIT_CLEAR_DIRTY);
+ kr = ubc_upl_commit_range(upl, pl_offset, uplSize, flags | UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_WRITTEN_BY_KERNEL);
if (kr != KERN_SUCCESS)
ErrorLog("ubc_upl_commit_range error %d\n", (int)kr);
}
return kr;
}
+
errno_t
decmpfs_pagein_compressed(struct vnop_pagein_args *ap, int *is_compressed, decmpfs_cnode *cp)
{
/* handles a page-in request from vfs for a compressed file */
int err = 0;
- struct vnode *vp = ap->a_vp;
+ vnode_t vp = ap->a_vp;
upl_t pl = ap->a_pl;
upl_offset_t pl_offset = ap->a_pl_offset;
off_t f_offset = ap->a_f_offset;
user_ssize_t uplSize = 0;
void *data = NULL;
decmpfs_header *hdr = NULL;
- int abort_pagein = 0;
uint64_t cachedSize = 0;
int cmpdata_locked = 0;
if (flags & ~(UPL_IOSYNC | UPL_NOCOMMIT | UPL_NORDAHEAD)) {
- DebugLog("pagein: unknown flags 0x%08x\n", (flags & ~(UPL_IOSYNC | UPL_NOCOMMIT | UPL_NORDAHEAD)));
+ DebugLogWithPath("pagein: unknown flags 0x%08x\n", (flags & ~(UPL_IOSYNC | UPL_NOCOMMIT | UPL_NORDAHEAD)));
}
err = decmpfs_fetch_compressed_header(vp, cp, &hdr, 0);
cachedSize = hdr->uncompressed_size;
- if (!compression_type_valid(hdr)) {
+ if (!compression_type_valid(vp, hdr)) {
/* compressor not registered */
err = ENOTSUP;
goto out;
}
-
+
+#if CONFIG_IOSCHED
+ /* Mark the UPL as the requesting UPL for decompression */
+ upl_mark_decmp(pl);
+#endif /* CONFIG_IOSCHED */
+
/* map the upl so we can fetch into it */
kern_return_t kr = ubc_upl_map(pl, (vm_offset_t*)&data);
if ((kr != KERN_SUCCESS) || (data == NULL)) {
+ err = ENOSPC;
+ data = NULL;
+#if CONFIG_IOSCHED
+ upl_unmark_decmp(pl);
+#endif /* CONFIG_IOSCHED */
goto out;
}
uplPos = f_offset;
uplSize = size;
-
+
/* clip the size to the size of the file */
if ((uint64_t)uplPos + uplSize > cachedSize) {
/* truncate the read to the size of the file */
uint64_t did_read = 0;
if (decmpfs_fast_get_state(cp) == FILE_IS_CONVERTING) {
- ErrorLog("unexpected pagein during decompress\n");
+ ErrorLogWithPath("unexpected pagein during decompress\n");
/*
if the file is converting, this must be a recursive call to pagein from underneath a call to decmpfs_decompress_file;
pretend that it succeeded but don't do anything since we're just going to write over the pages anyway
err = decmpfs_fetch_uncompressed_data(vp, cp, hdr, uplPos, uplSize, 1, &vec, &did_read);
}
if (err) {
- DebugLog("decmpfs_fetch_uncompressed_data err %d\n", err);
+ DebugLogWithPath("decmpfs_fetch_uncompressed_data err %d\n", err);
int cmp_state = decmpfs_fast_get_state(cp);
if (cmp_state == FILE_IS_CONVERTING) {
- DebugLog("cmp_state == FILE_IS_CONVERTING\n");
+ DebugLogWithPath("cmp_state == FILE_IS_CONVERTING\n");
cmp_state = wait_for_decompress(cp);
if (cmp_state == FILE_IS_COMPRESSED) {
- DebugLog("cmp_state == FILE_IS_COMPRESSED\n");
+ DebugLogWithPath("cmp_state == FILE_IS_COMPRESSED\n");
/* a decompress was attempted but it failed, let's try calling fetch again */
goto decompress;
}
}
if (cmp_state == FILE_IS_NOT_COMPRESSED) {
- DebugLog("cmp_state == FILE_IS_NOT_COMPRESSED\n");
+ DebugLogWithPath("cmp_state == FILE_IS_NOT_COMPRESSED\n");
/* the file was decompressed after we started reading it */
- abort_pagein = 1; /* we're not going to commit our data */
*is_compressed = 0; /* instruct caller to fall back to its normal path */
}
}
if (did_read < total_size) {
memset((char*)vec.buf + did_read, 0, total_size - did_read);
}
-
+
+#if CONFIG_IOSCHED
+ upl_unmark_decmp(pl);
+#endif /* CONFIG_IOSCHED */
+
kr = ubc_upl_unmap(pl); data = NULL; /* make sure to set data to NULL so we don't try to unmap again below */
if (kr != KERN_SUCCESS)
- ErrorLog("ubc_upl_unmap error %d\n", (int)kr);
+ ErrorLogWithPath("ubc_upl_unmap error %d\n", (int)kr);
else {
- if (!abort_pagein) {
+ if (!err) {
/* commit our pages */
kr = commit_upl(pl, pl_offset, total_size, UPL_COMMIT_FREE_ON_EMPTY, 0);
}
if (data) ubc_upl_unmap(pl);
if (hdr) FREE(hdr, M_TEMP);
if (cmpdata_locked) decmpfs_unlock_compressed_data(cp, 0);
- if (err)
- ErrorLog("err %d\n", err);
-
+ if (err) {
+#if 0
+ if (err != ENXIO && err != ENOSPC) {
+ char *path;
+ MALLOC(path, char *, PATH_MAX, M_TEMP, M_WAITOK);
+ panic("%s: decmpfs_pagein_compressed: err %d", vnpath(vp, path, PATH_MAX), err);
+ FREE(path, M_TEMP);
+ }
+#endif /* 0 */
+ ErrorLogWithPath("err %d\n", err);
+ }
return err;
}
uplPos = uio_offset(uio);
uplSize = uio_resid(uio);
- VerboseLog("uplPos %lld uplSize %lld\n", uplPos, uplSize);
+ VerboseLogWithPath("uplPos %lld uplSize %lld\n", uplPos, uplSize);
cachedSize = decmpfs_cnode_get_vnode_cached_size(cp);
if (err != 0) {
goto out;
}
- if (!compression_type_valid(hdr)) {
+ if (!compression_type_valid(vp, hdr)) {
err = ENOTSUP;
goto out;
}
uplPos = uioPos;
uplSize = uioRemaining;
#if COMPRESSION_DEBUG
- char path[PATH_MAX];
- DebugLog("%s: uplPos %lld uplSize %lld\n", vnpath(vp, path, sizeof(path)), (uint64_t)uplPos, (uint64_t)uplSize);
+ DebugLogWithPath("uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
#endif
lck_rw_lock_shared(decompressorsLock);
- decmpfs_adjust_fetch_region_func adjust_fetch = decmp_get_func(hdr->compression_type, adjust_fetch);
+ decmpfs_adjust_fetch_region_func adjust_fetch = decmp_get_func(vp, hdr->compression_type, adjust_fetch);
if (adjust_fetch) {
/* give the compressor a chance to adjust the portion of the file that we read */
adjust_fetch(vp, decmpfs_ctx, hdr, &uplPos, &uplSize);
- VerboseLog("adjusted uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
+ VerboseLogWithPath("adjusted uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
}
lck_rw_unlock_shared(decompressorsLock);
/* round size up to page multiple */
uplSize = (uplSize + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
- VerboseLog("new uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
+ VerboseLogWithPath("new uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
uplRemaining = uplSize;
curUplPos = uplPos;
/* clip to max upl size */
curUplSize = uplRemaining;
- if (curUplSize > MAX_UPL_SIZE * PAGE_SIZE) {
- curUplSize = MAX_UPL_SIZE * PAGE_SIZE;
+ if (curUplSize > MAX_UPL_SIZE_BYTES) {
+ curUplSize = MAX_UPL_SIZE_BYTES;
}
/* create the upl */
kr = ubc_create_upl(vp, curUplPos, curUplSize, &upl, &pli, UPL_SET_LITE);
if (kr != KERN_SUCCESS) {
- ErrorLog("ubc_create_upl error %d\n", (int)kr);
+ ErrorLogWithPath("ubc_create_upl error %d\n", (int)kr);
err = EINVAL;
goto out;
}
- VerboseLog("curUplPos %lld curUplSize %lld\n", (uint64_t)curUplPos, (uint64_t)curUplSize);
-
+ VerboseLogWithPath("curUplPos %lld curUplSize %lld\n", (uint64_t)curUplPos, (uint64_t)curUplSize);
+
+#if CONFIG_IOSCHED
+ /* Mark the UPL as the requesting UPL for decompression */
+ upl_mark_decmp(upl);
+#endif /* CONFIG_IOSCHED */
+
/* map the upl */
kr = ubc_upl_map(upl, (vm_offset_t*)&data);
if (kr != KERN_SUCCESS) {
- ErrorLog("ubc_upl_map error %d\n", (int)kr);
+
+ commit_upl(upl, 0, curUplSize, UPL_ABORT_FREE_ON_EMPTY, 1);
+#if 0
+ char *path;
+ MALLOC(path, char *, PATH_MAX, M_TEMP, M_WAITOK);
+ panic("%s: decmpfs_read_compressed: ubc_upl_map error %d", vnpath(vp, path, PATH_MAX), (int)kr);
+ FREE(path, M_TEMP);
+#else /* 0 */
+ ErrorLogWithPath("ubc_upl_map kr=0x%x\n", (int)kr);
+#endif /* 0 */
err = EINVAL;
goto out;
}
/* make sure the map succeeded */
if (!data) {
- ErrorLog("ubc_upl_map mapped null\n");
+
+ commit_upl(upl, 0, curUplSize, UPL_ABORT_FREE_ON_EMPTY, 1);
+
+ ErrorLogWithPath("ubc_upl_map mapped null\n");
err = EINVAL;
goto out;
}
vec = (decmpfs_vector){ .buf = data, .size = curUplSize };
err = decmpfs_fetch_uncompressed_data(vp, cp, hdr, curUplPos, curUplSize, 1, &vec, &did_read);
if (err) {
- ErrorLog("decmpfs_fetch_uncompressed_data err %d\n", err);
+ ErrorLogWithPath("decmpfs_fetch_uncompressed_data err %d\n", err);
/* maybe the file is converting to decompressed */
int cmp_state = decmpfs_fast_get_state(cp);
if (cmp_state == FILE_IS_CONVERTING) {
- ErrorLog("cmp_state == FILE_IS_CONVERTING\n");
+ ErrorLogWithPath("cmp_state == FILE_IS_CONVERTING\n");
cmp_state = wait_for_decompress(cp);
if (cmp_state == FILE_IS_COMPRESSED) {
- ErrorLog("cmp_state == FILE_IS_COMPRESSED\n");
+ ErrorLogWithPath("cmp_state == FILE_IS_COMPRESSED\n");
/* a decompress was attempted but it failed, let's try fetching again */
goto decompress;
}
}
if (cmp_state == FILE_IS_NOT_COMPRESSED) {
- ErrorLog("cmp_state == FILE_IS_NOT_COMPRESSED\n");
+ ErrorLogWithPath("cmp_state == FILE_IS_NOT_COMPRESSED\n");
/* the file was decompressed after we started reading it */
abort_read = 1; /* we're not going to commit our data */
*is_compressed = 0; /* instruct caller to fall back to its normal path */
if (abort_read) {
kr = commit_upl(upl, 0, curUplSize, UPL_ABORT_FREE_ON_EMPTY, 1);
} else {
- VerboseLog("uioPos %lld uioRemaining %lld\n", (uint64_t)uioPos, (uint64_t)uioRemaining);
+ VerboseLogWithPath("uioPos %lld uioRemaining %lld\n", (uint64_t)uioPos, (uint64_t)uioRemaining);
if (uioRemaining) {
off_t uplOff = uioPos - curUplPos;
if (uplOff < 0) {
- ErrorLog("uplOff %lld should never be negative\n", (int64_t)uplOff);
+ ErrorLogWithPath("uplOff %lld should never be negative\n", (int64_t)uplOff);
err = EINVAL;
} else {
off_t count = curUplPos + curUplSize - uioPos;
int io_resid = count;
err = cluster_copy_upl_data(uio, upl, uplOff, &io_resid);
int copied = count - io_resid;
- VerboseLog("uplOff %lld count %lld copied %lld\n", (uint64_t)uplOff, (uint64_t)count, (uint64_t)copied);
+ VerboseLogWithPath("uplOff %lld count %lld copied %lld\n", (uint64_t)uplOff, (uint64_t)count, (uint64_t)copied);
if (err) {
- ErrorLog("cluster_copy_upl_data err %d\n", err);
+ ErrorLogWithPath("cluster_copy_upl_data err %d\n", err);
}
uioPos += copied;
uioRemaining -= copied;
}
}
} else {
- ErrorLog("ubc_upl_unmap error %d\n", (int)kr);
+ ErrorLogWithPath("ubc_upl_unmap error %d\n", (int)kr);
}
-
+
uplRemaining -= curUplSize;
}
out:
+
if (hdr) FREE(hdr, M_TEMP);
if (cmpdata_locked) decmpfs_unlock_compressed_data(cp, 0);
if (err) {/* something went wrong */
- ErrorLog("err %d\n", err);
+ ErrorLogWithPath("err %d\n", err);
return err;
}
#if COMPRESSION_DEBUG
uplSize = uio_resid(uio);
if (uplSize)
- VerboseLog("still %lld bytes to copy\n", uplSize);
+ VerboseLogWithPath("still %lld bytes to copy\n", uplSize);
#endif
return 0;
}
decmpfs_header *hdr = NULL;
int err = decmpfs_fetch_compressed_header(vp, cp, &hdr, 0);
if (err) {
- ErrorLog("decmpfs_fetch_compressed_header err %d\n", err);
+ ErrorLogWithPath("decmpfs_fetch_compressed_header err %d\n", err);
} else {
lck_rw_lock_shared(decompressorsLock);
- decmpfs_free_compressed_data_func free_data = decmp_get_func(hdr->compression_type, free_data);
+ decmpfs_free_compressed_data_func free_data = decmp_get_func(vp, hdr->compression_type, free_data);
if (free_data) {
err = free_data(vp, decmpfs_ctx, hdr);
} else {
lck_rw_unlock_shared(decompressorsLock);
if (err != 0) {
- ErrorLog("decompressor err %d\n", err);
+ ErrorLogWithPath("decompressor err %d\n", err);
}
}
err = vnode_getattr(vp, &va, decmpfs_ctx);
if (err != 0) {
- ErrorLog("vnode_getattr err %d\n", err);
+ ErrorLogWithPath("vnode_getattr err %d\n", err);
} else {
new_bsdflags = va.va_flags & ~UF_COMPRESSED;
VATTR_SET(&va, va_flags, new_bsdflags);
err = vnode_setattr(vp, &va, decmpfs_ctx);
if (err != 0) {
- ErrorLog("vnode_setattr err %d\n", err);
+ ErrorLogWithPath("vnode_setattr err %d\n", err);
}
}
return err;
decmpfs_vector vec = { .buf = data, .size = MIN(allocSize, remaining) };
err = decmpfs_fetch_uncompressed_data(vp, cp, hdr, offset, vec.size, 1, &vec, &bytes_read);
if (err != 0) {
- ErrorLog("decmpfs_fetch_uncompressed_data err %d\n", err);
+ ErrorLogWithPath("decmpfs_fetch_uncompressed_data err %d\n", err);
goto out;
}
uio_reset(uio_w, offset, UIO_SYSSPACE, UIO_WRITE);
err = uio_addiov(uio_w, CAST_USER_ADDR_T(data), bytes_read);
if (err != 0) {
- ErrorLog("uio_addiov err %d\n", err);
+ ErrorLogWithPath("uio_addiov err %d\n", err);
err = ENOMEM;
goto out;
}
err = VNOP_WRITE(vp, uio_w, 0, decmpfs_ctx);
if (err != 0) {
/* if the write failed, truncate the file to zero bytes */
- ErrorLog("VNOP_WRITE err %d\n", err);
+ ErrorLogWithPath("VNOP_WRITE err %d\n", err);
break;
}
offset += bytes_read;
if (err == 0) {
if (offset != toSize) {
- ErrorLog("file decompressed to %lld instead of %lld\n", offset, toSize);
+ ErrorLogWithPath("file decompressed to %lld instead of %lld\n", offset, toSize);
err = EINVAL;
goto out;
}
/* sync the data and metadata */
err = VNOP_FSYNC(vp, MNT_WAIT, decmpfs_ctx);
if (err != 0) {
- ErrorLog("VNOP_FSYNC err %d\n", err);
+ ErrorLogWithPath("VNOP_FSYNC err %d\n", err);
goto out;
}
}
if (err != 0) {
/* write, setattr, or fsync failed */
- ErrorLog("aborting decompress, err %d\n", err);
+ ErrorLogWithPath("aborting decompress, err %d\n", err);
if (truncate_okay) {
/* truncate anything we might have written */
int error = vnode_setsize(vp, 0, 0, decmpfs_ctx);
- ErrorLog("vnode_setsize err %d\n", error);
+ ErrorLogWithPath("vnode_setsize err %d\n", error);
}
goto out;
}
/* free the compressed data associated with this file */
err = decmpfs_free_compressed_data(vp, cp);
if (err != 0) {
- ErrorLog("decmpfs_free_compressed_data err %d\n", err);
+ ErrorLogWithPath("decmpfs_free_compressed_data err %d\n", err);
}
/*
{
uint64_t filesize = 0;
vnsize(vp, &filesize);
- DebugLog("new file size %lld\n", filesize);
+ DebugLogWithPath("new file size %lld\n", filesize);
}
#endif
#if COMPRESSION_DEBUG
static int dummy = 0; // prevent syslog from coalescing printfs
- char path[PATH_MAX];
- DebugLog("%s: %d memcpy %lld at %lld\n", vnpath(vp, path, sizeof(path)), dummy++, size, (uint64_t)offset);
+ DebugLogWithPath("%d memcpy %lld at %lld\n", dummy++, size, (uint64_t)offset);
#endif
remaining = size;
lck_grp_attr_t *attr = lck_grp_attr_alloc_init();
decmpfs_lockgrp = lck_grp_alloc_init("VFSCOMP", attr);
+ lck_grp_attr_free(attr);
decompressorsLock = lck_rw_alloc_init(decmpfs_lockgrp, NULL);
decompress_channel_mtx = lck_mtx_alloc_init(decmpfs_lockgrp, NULL);
done = 1;
}
-#endif /* HFS_COMPRESSION */
+#endif /* FS_COMPRESSION */