- VerboseLog("adjusted uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
- }
- lck_rw_done(decompressorsLock);
-
- /* clip the adjusted size to the size of the file */
- if ((uint64_t)uplPos + uplSize > cachedSize) {
- /* truncate the read to the size of the file */
- uplSize = cachedSize - uplPos;
- }
-
- if (uplSize <= 0) {
- /* nothing left */
- goto out;
- }
-
- /*
- since we're going to create a upl for the given region of the file,
- make sure we're on page boundaries
- */
-
- if (uplPos & (PAGE_SIZE - 1)) {
- /* round position down to page boundary */
- uplSize += (uplPos & (PAGE_SIZE - 1));
- uplPos &= ~(PAGE_SIZE - 1);
- }
- /* 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);
-
- uplRemaining = uplSize;
- curUplPos = uplPos;
- curUplSize = 0;
-
- while(uplRemaining > 0) {
- /* start after the last upl */
- curUplPos += curUplSize;
-
- /* clip to max upl size */
- curUplSize = uplRemaining;
- if (curUplSize > MAX_UPL_SIZE * PAGE_SIZE) {
- curUplSize = MAX_UPL_SIZE * PAGE_SIZE;
- }
-
- /* 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);
- err = EINVAL;
- goto out;
- }
- VerboseLog("curUplPos %lld curUplSize %lld\n", (uint64_t)curUplPos, (uint64_t)curUplSize);
-
- /* 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);
- err = EINVAL;
- goto out;
- }
-
- /* make sure the map succeeded */
- if (!data) {
- ErrorLog("ubc_upl_map mapped null\n");
- err = EINVAL;
- goto out;
- }
-
- /* fetch uncompressed data into the mapped upl */
- decmpfs_vector vec;
- decompress:
- vec = (decmpfs_vector){ .buf = data, .size = curUplSize };
- err = decmpfs_fetch_uncompressed_data(vp, hdr, curUplPos, curUplSize, 1, &vec, &did_read);
- if (err) {
- ErrorLog("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");
- cmp_state = wait_for_decompress(cp);
- if (cmp_state == FILE_IS_COMPRESSED) {
- ErrorLog("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");
- /* 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 */
- }
- kr = KERN_FAILURE;
- did_read = 0;
- }
- /* zero out the remainder of the last page */
- memset((char*)data + did_read, 0, curUplSize - did_read);
- kr = ubc_upl_unmap(upl);
- if (kr == KERN_SUCCESS) {
- if (abort_read) {
+ VerboseLogWithPath("adjusted uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
+ }
+ lck_rw_unlock_shared(decompressorsLock);
+
+ /* clip the adjusted size to the size of the file */
+ if ((uint64_t)uplPos + uplSize > cachedSize) {
+ /* truncate the read to the size of the file */
+ uplSize = cachedSize - uplPos;
+ }
+
+ if (uplSize <= 0) {
+ /* nothing left */
+ goto out;
+ }
+
+ /*
+ * since we're going to create a upl for the given region of the file,
+ * make sure we're on page boundaries
+ */
+
+ if (uplPos & (PAGE_SIZE - 1)) {
+ /* round position down to page boundary */
+ uplSize += (uplPos & (PAGE_SIZE - 1));
+ uplPos &= ~(PAGE_SIZE - 1);
+ }
+ /* round size up to page multiple */
+ uplSize = (uplSize + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+
+ VerboseLogWithPath("new uplPos %lld uplSize %lld\n", (uint64_t)uplPos, (uint64_t)uplSize);
+
+ uplRemaining = uplSize;
+ curUplPos = uplPos;
+ curUplSize = 0;
+
+ while (uplRemaining > 0) {
+ /* start after the last upl */
+ curUplPos += curUplSize;
+
+ /* clip to max upl size */
+ curUplSize = uplRemaining;
+ if (curUplSize > MAX_UPL_SIZE_BYTES) {
+ curUplSize = MAX_UPL_SIZE_BYTES;
+ }
+
+ /* create the upl */
+ kr = ubc_create_upl_kernel(vp, curUplPos, curUplSize, &upl, &pli, UPL_SET_LITE, VM_KERN_MEMORY_FILE);
+ if (kr != KERN_SUCCESS) {
+ ErrorLogWithPath("ubc_create_upl error %d\n", (int)kr);
+ err = EINVAL;
+ goto out;
+ }
+ 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) {
+ 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) {
+ commit_upl(upl, 0, curUplSize, UPL_ABORT_FREE_ON_EMPTY, 1);
+
+ ErrorLogWithPath("ubc_upl_map mapped null\n");
+ err = EINVAL;
+ goto out;
+ }
+
+ /* fetch uncompressed data into the mapped upl */
+ decmpfs_vector vec;
+decompress:
+ vec = (decmpfs_vector){ .buf = data, .size = curUplSize };
+ err = decmpfs_fetch_uncompressed_data(vp, cp, hdr, curUplPos, curUplSize, 1, &vec, &did_read);
+ if (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) {
+ ErrorLogWithPath("cmp_state == FILE_IS_CONVERTING\n");
+ cmp_state = wait_for_decompress(cp);
+ if (cmp_state == FILE_IS_COMPRESSED) {
+ 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) {
+ 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 */
+ }
+ kr = KERN_FAILURE;
+ did_read = 0;
+ }
+ /* zero out the remainder of the last page */
+ memset((char*)data + did_read, 0, curUplSize - did_read);
+ kr = ubc_upl_unmap(upl);
+ if (kr == KERN_SUCCESS) {
+ if (abort_read) {