return STATUS_SUCCESS;
}
-static NTSTATUS add_ext_holes(LIST_ENTRY* exts, UINT64 size) {
+static NTSTATUS add_ext_holes(device_extension* Vcb, LIST_ENTRY* exts, UINT64 size) {
UINT64 lastoff = 0;
LIST_ENTRY* le;
ext2->offset = lastoff;
ext2->datalen = offsetof(EXTENT_DATA, data) + sizeof(EXTENT_DATA2);
- ext2->data.decoded_size = ed2->num_bytes = size - lastoff;
+ ext2->data.decoded_size = ed2->num_bytes = sector_align(size - lastoff, Vcb->superblock.sector_size);
ext2->data.type = EXTENT_TYPE_REGULAR;
ed2->address = ed2->size = ed2->offset = 0;
return STATUS_SUCCESS;
if (context->parent) {
- Status = add_ext_holes(&context->lastinode.exts, context->lastinode.size);
+ Status = add_ext_holes(context->Vcb, &context->lastinode.exts, context->lastinode.size);
if (!NT_SUCCESS(Status)) {
ERR("add_ext_holes returned %08x\n", Status);
return Status;
}
- Status = add_ext_holes(&context->lastinode.oldexts, context->lastinode.size);
+ Status = add_ext_holes(context->Vcb, &context->lastinode.oldexts, context->lastinode.size);
if (!NT_SUCCESS(Status)) {
ERR("add_ext_holes returned %08x\n", Status);
return Status;
if (se->data.compression == BTRFS_COMPRESSION_NONE)
send_add_tlv(context, BTRFS_SEND_TLV_DATA, se->data.data, (UINT16)se->data.decoded_size);
- else if (se->data.compression == BTRFS_COMPRESSION_ZLIB || se->data.compression == BTRFS_COMPRESSION_LZO) {
+ else if (se->data.compression == BTRFS_COMPRESSION_ZLIB || se->data.compression == BTRFS_COMPRESSION_LZO || se->data.compression == BTRFS_COMPRESSION_ZSTD) {
ULONG inlen = se->datalen - (ULONG)offsetof(EXTENT_DATA, data[0]);
send_add_tlv(context, BTRFS_SEND_TLV_DATA, NULL, (UINT16)se->data.decoded_size);
if (se2) ExFreePool(se2);
return Status;
}
+ } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
+ Status = zstd_decompress(se->data.data, inlen, &context->data[context->datalen - se->data.decoded_size], (UINT32)se->data.decoded_size);
+ if (!NT_SUCCESS(Status)) {
+ ERR("zlib_decompress returned %08x\n", Status);
+ ExFreePool(se);
+ if (se2) ExFreePool(se2);
+ return Status;
+ }
}
} else {
ERR("unhandled compression type %x\n", se->data.compression);
offset = se->offset + off;
send_add_tlv(context, BTRFS_SEND_TLV_OFFSET, &offset, sizeof(UINT64));
- length = min((UINT16)(context->lastinode.size - se->offset - off), length);
+ length = (UINT16)min(context->lastinode.size - se->offset - off, length);
send_add_tlv(context, BTRFS_SEND_TLV_DATA, buf + skip_start, length);
send_command_finish(context, pos);
if (se2) ExFreePool(se2);
return Status;
}
+ } else if (se->data.compression == BTRFS_COMPRESSION_ZSTD) {
+ Status = zstd_decompress(compbuf, (UINT32)ed2->size, buf, (UINT32)se->data.decoded_size);
+ if (!NT_SUCCESS(Status)) {
+ ERR("zstd_decompress returned %08x\n", Status);
+ ExFreePool(compbuf);
+ ExFreePool(buf);
+ ExFreePool(se);
+ if (se2) ExFreePool(se2);
+ return Status;
+ }
}
ExFreePool(compbuf);
offset = se->offset + off;
send_add_tlv(context, BTRFS_SEND_TLV_OFFSET, &offset, sizeof(UINT64));
- length = min((UINT16)(context->lastinode.size - se->offset - off), length);
+ length = (UINT16)min(context->lastinode.size - se->offset - off, length);
send_add_tlv(context, BTRFS_SEND_TLV_DATA, &buf[off], length);
send_command_finish(context, pos);
return STATUS_INTERNAL_ERROR;
}
- if (ed->compression != BTRFS_COMPRESSION_NONE && ed->compression != BTRFS_COMPRESSION_ZLIB && ed->compression != BTRFS_COMPRESSION_LZO) {
+ if (ed->compression != BTRFS_COMPRESSION_NONE && ed->compression != BTRFS_COMPRESSION_ZLIB &&
+ ed->compression != BTRFS_COMPRESSION_LZO && ed->compression != BTRFS_COMPRESSION_ZSTD) {
ERR("unknown compression type %u\n", ed->compression);
return STATUS_INTERNAL_ERROR;
}
return STATUS_INTERNAL_ERROR;
}
- if (ed->compression != BTRFS_COMPRESSION_NONE && ed->compression != BTRFS_COMPRESSION_ZLIB && ed->compression != BTRFS_COMPRESSION_LZO) {
+ if (ed->compression != BTRFS_COMPRESSION_NONE && ed->compression != BTRFS_COMPRESSION_ZLIB &&
+ ed->compression != BTRFS_COMPRESSION_LZO && ed->compression != BTRFS_COMPRESSION_ZSTD) {
ERR("unknown compression type %u\n", ed->compression);
return STATUS_INTERNAL_ERROR;
}
context = ExAllocatePoolWithTag(NonPagedPool, sizeof(send_context), ALLOC_TAG);
if (!context) {
ERR("out of memory\n");
+
+ if (clones)
+ ExFreePool(clones);
+
ExReleaseResourceLite(&Vcb->send_load_lock);
return STATUS_INSUFFICIENT_RESOURCES;
}
ERR("out of memory\n");
ExFreePool(context->data);
ExFreePool(context);
+
+ if (clones)
+ ExFreePool(clones);
+
ExReleaseResourceLite(&Vcb->send_load_lock);
return STATUS_INSUFFICIENT_RESOURCES;
}
ExFreePool(send);
ExFreePool(context->data);
ExFreePool(context);
+
+ if (clones)
+ ExFreePool(clones);
+
ExReleaseResourceLite(&Vcb->send_load_lock);
return Status;
}