win-pvdrivers

annotate xencache/xencache.c @ 1075:5e8aeb18279c

Add export methods to retrieve and set the hypercall stubs for the dump_xenpci driver
author James Harper <james.harper@bendigoit.com.au>
date Mon Dec 09 13:30:14 2013 +1100 (2013-12-09)
parents 2d5fbe07e866
children
rev   line source
james@1055 1 /*
james@1055 2 PV Drivers for Windows Xen HVM Domains
james@1055 3 Copyright (C) 2013 James Harper
james@1055 4
james@1055 5 This program is free software; you can redistribute it and/or
james@1055 6 modify it under the terms of the GNU General Public License
james@1055 7 as published by the Free Software Foundation; either version 2
james@1055 8 of the License, or (at your option) any later version.
james@1055 9
james@1055 10 This program is distributed in the hope that it will be useful,
james@1055 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@1055 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@1055 13 GNU General Public License for more details.
james@1055 14
james@1055 15 You should have received a copy of the GNU General Public License
james@1055 16 along with this program; if not, write to the Free Software
james@1055 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@1055 18 */
james@1055 19
james@1055 20 #include "xencache.h"
james@1055 21
james@1055 22 #define TMEM_CONTROL 0
james@1055 23 #define TMEM_NEW_POOL 1
james@1055 24 #define TMEM_DESTROY_POOL 2
james@1055 25 #define TMEM_NEW_PAGE 3
james@1055 26 #define TMEM_PUT_PAGE 4
james@1055 27 #define TMEM_GET_PAGE 5
james@1055 28 #define TMEM_FLUSH_PAGE 6
james@1055 29 #define TMEM_FLUSH_OBJECT 7
james@1055 30 #define TMEM_READ 8
james@1055 31 #define TMEM_WRITE 9
james@1055 32 #define TMEM_XCHG 10
james@1055 33
james@1055 34 /* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
james@1055 35 #define TMEM_POOL_PERSIST 1
james@1055 36 #define TMEM_POOL_SHARED 2
james@1055 37 #define TMEM_POOL_PAGESIZE_SHIFT 4
james@1055 38 #define TMEM_VERSION_SHIFT 24
james@1055 39
james@1055 40 /* flags for tmem_ops.new_pool */
james@1055 41 #define TMEM_POOL_PERSIST 1
james@1055 42 #define TMEM_POOL_SHARED 2
james@1055 43
james@1055 44 PFLT_FILTER filter_handle;
james@1055 45 global_context_t global_context;
james@1055 46
james@1055 47 DRIVER_INITIALIZE DriverEntry;
james@1055 48
james@1055 49 NTSTATUS XenCache_FilterUnload(FLT_FILTER_UNLOAD_FLAGS flags);
james@1055 50 NTSTATUS XenCache_InstanceSetup(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_SETUP_FLAGS flags, DEVICE_TYPE volume_device_type, FLT_FILESYSTEM_TYPE volume_filesystem_type);
james@1055 51 NTSTATUS XenCache_InstanceQueryTeardown(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS flags);
james@1055 52 VOID XenCache_InstanceTeardownStart(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS reason);
james@1055 53 VOID XenCache_InstanceTeardownComplete(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS reason);
james@1055 54
james@1055 55 FLT_PREOP_CALLBACK_STATUS XenCache_Pre_CLOSE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context);
james@1055 56 FLT_POSTOP_CALLBACK_STATUS XenCache_Pst_CLOSE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID completion_context, FLT_POST_OPERATION_FLAGS flags);
james@1055 57 FLT_PREOP_CALLBACK_STATUS XenCache_Pre_CLEANUP(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context);
james@1055 58 FLT_POSTOP_CALLBACK_STATUS XenCache_Pst_CLEANUP(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID completion_context, FLT_POST_OPERATION_FLAGS flags);
james@1055 59 FLT_PREOP_CALLBACK_STATUS XenCache_Pre_READ(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context);
james@1055 60 FLT_PREOP_CALLBACK_STATUS XenCache_Pre_WRITE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context);
james@1055 61
james@1055 62 FLT_OPERATION_REGISTRATION filter_callbacks[] = {
james@1055 63 { IRP_MJ_CLOSE, 0, XenCache_Pre_CLOSE, XenCache_Pst_CLOSE },
james@1055 64 { IRP_MJ_CLEANUP, 0, XenCache_Pre_CLEANUP, XenCache_Pst_CLEANUP },
james@1055 65 { IRP_MJ_READ, 0, XenCache_Pre_READ, NULL },
james@1055 66 { IRP_MJ_WRITE, 0, XenCache_Pre_WRITE, NULL },
james@1055 67 { IRP_MJ_OPERATION_END }
james@1055 68 };
james@1055 69
james@1055 70 FLT_REGISTRATION filter_registration = {
james@1055 71 sizeof(FLT_REGISTRATION),
james@1055 72 FLT_REGISTRATION_VERSION,
james@1055 73 0, // flags
james@1055 74 NULL, // context_callbacks,
james@1055 75 filter_callbacks,
james@1055 76 XenCache_FilterUnload,
james@1055 77 XenCache_InstanceSetup,
james@1055 78 XenCache_InstanceQueryTeardown,
james@1055 79 XenCache_InstanceTeardownStart,
james@1055 80 XenCache_InstanceTeardownComplete,
james@1055 81 NULL, // XenCache_GenerateFileName,
james@1055 82 NULL, // XenCache_NormalizeNameComponentn,
james@1055 83 NULL, // XenCache_NormalizeContextCleanup,
james@1055 84 #if FLT_MGR_LONGHORN
james@1055 85 NULL, // XenCache_TransactionNotification,
james@1055 86 NULL, // XenCache_NormalizeNameComponentEx,
james@1055 87 #endif
james@1055 88 };
james@1055 89
james@1055 90 NTSTATUS
james@1055 91 DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path) {
james@1055 92 NTSTATUS status;
james@1055 93
james@1055 94 UNREFERENCED_PARAMETER(registry_path);
james@1055 95
james@1055 96 FUNCTION_ENTER();
james@1055 97
james@1055 98 RtlZeroMemory(&global_context, sizeof(global_context_t));
james@1055 99 KeInitializeSpinLock(&global_context.lock);
james@1055 100
james@1055 101 status = FltRegisterFilter(driver_object, &filter_registration, &filter_handle);
james@1055 102 FUNCTION_MSG("FltRegisterFilter = %08x\n", status);
james@1055 103
james@1055 104 if (!NT_SUCCESS(status)) {
james@1055 105 FUNCTION_EXIT();
james@1055 106 return status;
james@1055 107 }
james@1055 108 status = FltStartFiltering(filter_handle);
james@1055 109 FUNCTION_MSG("FltStartFiltering = %08x\n", status);
james@1055 110 if (!NT_SUCCESS(status)) {
james@1055 111 FltUnregisterFilter(filter_handle);
james@1055 112 }
james@1055 113
james@1055 114 FUNCTION_EXIT();
james@1055 115
james@1055 116 return status;
james@1055 117 }
james@1055 118
james@1055 119 NTSTATUS
james@1055 120 XenCache_FilterUnload(FLT_FILTER_UNLOAD_FLAGS flags) {
james@1055 121 UNREFERENCED_PARAMETER(flags);
james@1055 122 FUNCTION_ENTER();
james@1055 123 FltUnregisterFilter(filter_handle);
james@1055 124 RtlZeroMemory(&global_context, sizeof(global_context_t));
james@1055 125 FUNCTION_EXIT();
james@1055 126 return STATUS_SUCCESS;
james@1055 127 }
james@1055 128
james@1055 129 NTSTATUS
james@1055 130 XenCache_InstanceSetup(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_SETUP_FLAGS flags, DEVICE_TYPE volume_device_type, FLT_FILESYSTEM_TYPE volume_filesystem_type) {
james@1055 131 FUNCTION_ENTER();
james@1055 132 if (volume_device_type != FILE_DEVICE_DISK_FILE_SYSTEM) {
james@1055 133 FUNCTION_MSG("is not disk\n");
james@1055 134 FUNCTION_EXIT();
james@1055 135 return STATUS_FLT_DO_NOT_ATTACH;
james@1055 136 }
james@1055 137 if (volume_filesystem_type != FLT_FSTYPE_NTFS) {
james@1055 138 FUNCTION_MSG("is not NTFS\n");
james@1055 139 FUNCTION_EXIT();
james@1055 140 return STATUS_FLT_DO_NOT_ATTACH;
james@1055 141 }
james@1055 142 FUNCTION_MSG("flt_objects = %p\n", flt_objects);
james@1055 143 FUNCTION_MSG("flags = %08x\n", flags);
james@1055 144 FUNCTION_MSG("volume_device_type = %08x\n", volume_device_type);
james@1055 145 FUNCTION_MSG("volume_filesystem_type = %08x\n", volume_filesystem_type);
james@1055 146 FUNCTION_EXIT();
james@1055 147 return STATUS_SUCCESS;
james@1055 148 }
james@1055 149
james@1055 150 NTSTATUS
james@1055 151 XenCache_InstanceQueryTeardown(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS flags) {
james@1055 152 FUNCTION_ENTER();
james@1055 153 FUNCTION_MSG("flt_objects = %p\n", flt_objects);
james@1055 154 FUNCTION_MSG("flags = %08x\n", flags);
james@1055 155 FUNCTION_EXIT();
james@1055 156 return STATUS_SUCCESS;
james@1055 157 }
james@1055 158
james@1055 159 VOID
james@1055 160 XenCache_InstanceTeardownStart(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS reason) {
james@1055 161 FUNCTION_ENTER();
james@1055 162 FUNCTION_MSG("flt_objects = %p\n", flt_objects);
james@1055 163 FUNCTION_MSG("reason = %08x\n", reason);
james@1055 164 FUNCTION_EXIT();
james@1055 165 }
james@1055 166
james@1055 167 VOID
james@1055 168 XenCache_InstanceTeardownComplete(PCFLT_RELATED_OBJECTS flt_objects, FLT_INSTANCE_QUERY_TEARDOWN_FLAGS reason) {
james@1055 169 FUNCTION_ENTER();
james@1055 170 FUNCTION_MSG("flt_objects = %p\n", flt_objects);
james@1055 171 FUNCTION_MSG("reason = %08x\n", reason);
james@1055 172 FUNCTION_EXIT();
james@1055 173 }
james@1055 174
james@1055 175 FLT_PREOP_CALLBACK_STATUS
james@1055 176 XenCache_Pre_CLOSE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context) {
james@1055 177 UNREFERENCED_PARAMETER(data);
james@1055 178 UNREFERENCED_PARAMETER(flt_objects);
james@1055 179 UNREFERENCED_PARAMETER(completion_context);
james@1055 180 if (FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 181 FUNCTION_ENTER();
james@1055 182 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 183 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 184 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 185 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 186 FUNCTION_EXIT();
james@1055 187 }
james@1055 188 #if 0
james@1055 189 FUNCTION_ENTER();
james@1055 190 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 191 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 192 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 193 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 194 FUNCTION_EXIT();
james@1055 195 #endif
james@1055 196 return FLT_PREOP_SUCCESS_WITH_CALLBACK;
james@1055 197 }
james@1055 198
james@1055 199 FLT_POSTOP_CALLBACK_STATUS
james@1055 200 XenCache_Pst_CLOSE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID completion_context, FLT_POST_OPERATION_FLAGS flags) {
james@1055 201 UNREFERENCED_PARAMETER(data);
james@1055 202 UNREFERENCED_PARAMETER(flt_objects);
james@1055 203 UNREFERENCED_PARAMETER(completion_context);
james@1055 204 UNREFERENCED_PARAMETER(flags);
james@1055 205 if (FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 206 FUNCTION_ENTER();
james@1055 207 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 208 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 209 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 210 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 211 FUNCTION_EXIT();
james@1055 212 }
james@1055 213 #if 0
james@1055 214 FUNCTION_ENTER();
james@1055 215 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 216 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 217 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 218 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 219 FUNCTION_EXIT();
james@1055 220 #endif
james@1055 221 return FLT_POSTOP_FINISHED_PROCESSING;
james@1055 222 }
james@1055 223
james@1055 224 FLT_PREOP_CALLBACK_STATUS
james@1055 225 XenCache_Pre_CLEANUP(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context) {
james@1055 226 UNREFERENCED_PARAMETER(data);
james@1055 227 UNREFERENCED_PARAMETER(flt_objects);
james@1055 228 UNREFERENCED_PARAMETER(completion_context);
james@1055 229 if (FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 230 FUNCTION_ENTER();
james@1055 231 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 232 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 233 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 234 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 235 FUNCTION_EXIT();
james@1055 236 }
james@1055 237 #if 0
james@1055 238 FUNCTION_ENTER();
james@1055 239 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 240 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 241 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 242 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 243 FUNCTION_EXIT();
james@1055 244 #endif
james@1055 245 return FLT_PREOP_SUCCESS_WITH_CALLBACK;
james@1055 246 }
james@1055 247
james@1055 248 FLT_POSTOP_CALLBACK_STATUS
james@1055 249 XenCache_Pst_CLEANUP(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID completion_context, FLT_POST_OPERATION_FLAGS flags) {
james@1055 250 UNREFERENCED_PARAMETER(data);
james@1055 251 UNREFERENCED_PARAMETER(flt_objects);
james@1055 252 UNREFERENCED_PARAMETER(completion_context);
james@1055 253 UNREFERENCED_PARAMETER(flags);
james@1055 254 if (FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 255 FUNCTION_ENTER();
james@1055 256 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
james@1055 257 FUNCTION_MSG("FileObject = %p\n", flt_objects->FileObject);
james@1055 258 FUNCTION_MSG("FileName = %S\n", flt_objects->FileObject->FileName.Buffer);
james@1055 259 FUNCTION_MSG("IsPagingFile = %d\n", FsRtlIsPagingFile(flt_objects->FileObject));
james@1055 260 FUNCTION_EXIT();
james@1055 261 }
james@1055 262 return FLT_POSTOP_FINISHED_PROCESSING;
james@1055 263 }
james@1055 264
james@1055 265 FLT_PREOP_CALLBACK_STATUS
james@1055 266 XenCache_Pre_WRITE(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context) {
james@1055 267 pagefile_context_t *context;
james@1055 268 int i;
james@1055 269 KIRQL old_irql;
james@1057 270 LONG rc;
james@1055 271 struct tmem_op tmem_op;
james@1055 272
james@1055 273 UNREFERENCED_PARAMETER(data);
james@1055 274 UNREFERENCED_PARAMETER(flt_objects);
james@1055 275 UNREFERENCED_PARAMETER(completion_context);
james@1055 276
james@1057 277 if (global_context.error_count) {
james@1057 278 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1057 279 }
james@1055 280 if (!FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 281 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 282 }
james@1055 283
james@1057 284 if (!(data->Flags & FLTFL_CALLBACK_DATA_IRP_OPERATION)) {
james@1057 285 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1057 286 }
james@1057 287
james@1055 288 KeAcquireSpinLock(&global_context.lock, &old_irql);
james@1055 289 for (context = global_context.pagefile_head; context; context = context->next) {
james@1055 290 if (context->file_object == flt_objects->FileObject)
james@1055 291 break;
james@1055 292 }
james@1055 293 if (!context) {
james@1055 294 context = ExAllocatePoolWithTag(NonPagedPool, sizeof(pagefile_context_t), XENCACHE_POOL_TAG);
james@1055 295 if (!context) {
james@1055 296 FUNCTION_MSG("Failed to allocate context\n");
james@1055 297 /* should probably detach this instance here */
james@1055 298 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1055 299 FUNCTION_EXIT();
james@1055 300 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 301 }
james@1055 302 RtlZeroMemory(context, sizeof(pagefile_context_t));
james@1055 303 context->file_object = flt_objects->FileObject;
james@1055 304 context->next = global_context.pagefile_head;
james@1055 305 tmem_op.cmd = TMEM_NEW_POOL;
james@1055 306 tmem_op.pool_id = 0; /* this doesn't actually get used for private */
james@1055 307 tmem_op.u.new.flags = (TMEM_SPEC_VERSION << TMEM_VERSION_SHIFT); /* private, not shared */
james@1055 308 context->pool_id = XnTmemOp(&tmem_op);
james@1055 309 FUNCTION_MSG("pool_id = %d\n", context->pool_id);
james@1057 310 if (context->pool_id < 0) {
james@1057 311 ExFreePoolWithTag(context, XENCACHE_POOL_TAG);
james@1057 312 global_context.error_count++;
james@1057 313 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1057 314 /* should actually unload here */
james@1057 315 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1057 316 }
james@1055 317 global_context.pagefile_head = context;
james@1055 318 }
james@1055 319
james@1055 320 for (i = 0; i < (int)data->Iopb->Parameters.Write.Length >> PAGE_SHIFT; i++) {
james@1055 321 ULONG page = (ULONG)(data->Iopb->Parameters.Write.ByteOffset.QuadPart >> PAGE_SHIFT) + i;
james@1055 322
james@1055 323 tmem_op.cmd = TMEM_PUT_PAGE;
james@1055 324 tmem_op.pool_id = context->pool_id;
james@1055 325 tmem_op.u.gen.oid[0] = 0;
james@1055 326 tmem_op.u.gen.oid[1] = 0;
james@1055 327 tmem_op.u.gen.oid[2] = 0;
james@1055 328 tmem_op.u.gen.index = page;
james@1055 329 tmem_op.u.gen.tmem_offset = 0;
james@1055 330 tmem_op.u.gen.pfn_offset = 0;
james@1055 331 tmem_op.u.gen.len = 0;
james@1055 332 set_xen_guest_handle(tmem_op.u.gen.gmfn, (void *)MmGetMdlPfnArray(data->Iopb->Parameters.Write.MdlAddress)[i]);
james@1055 333 rc = XnTmemOp(&tmem_op);
james@1055 334 if (rc == 1) {
james@1055 335 context->put_success_count++;
james@1055 336 } else if (rc == 0) {
james@1055 337 context->put_fail_count++;
james@1055 338 } else {
james@1055 339 FUNCTION_MSG("TMEM_PUT_PAGE = %d\n", rc);
james@1057 340 context->put_fail_count++;
james@1057 341 context->error_count++;
james@1055 342 }
james@1055 343 }
james@1055 344 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1055 345 if (((context->put_success_count + context->put_fail_count + context->get_success_count + context->get_fail_count) & 0xff) == 0) {
james@1055 346 FUNCTION_MSG(" put_success_count = %I64d\n", context->put_success_count);
james@1055 347 FUNCTION_MSG(" put_fail_count = %I64d\n", context->put_fail_count);
james@1055 348 FUNCTION_MSG(" get_success_count = %I64d\n", context->get_success_count);
james@1055 349 FUNCTION_MSG(" get_fail_count = %I64d\n", context->get_fail_count);
james@1057 350 FUNCTION_MSG(" error_count = %I64d\n", context->error_count);
james@1055 351 }
james@1055 352 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 353 }
james@1055 354
james@1055 355 FLT_PREOP_CALLBACK_STATUS
james@1055 356 XenCache_Pre_READ(PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS flt_objects, PVOID *completion_context) {
james@1055 357 NTSTATUS status;
james@1055 358 pagefile_context_t *context;
james@1055 359 KIRQL old_irql;
james@1055 360 int i;
james@1057 361 LONG rc;
james@1055 362 struct tmem_op tmem_op;
james@1055 363
james@1055 364 UNREFERENCED_PARAMETER(data);
james@1055 365 UNREFERENCED_PARAMETER(flt_objects);
james@1055 366 UNREFERENCED_PARAMETER(completion_context);
james@1055 367
james@1055 368 if (!FsRtlIsPagingFile(flt_objects->FileObject)) {
james@1055 369 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 370 }
james@1055 371 KeAcquireSpinLock(&global_context.lock, &old_irql);
james@1055 372 for (context = global_context.pagefile_head; context; context = context->next) {
james@1055 373 if (context->file_object == flt_objects->FileObject)
james@1055 374 break;
james@1055 375 }
james@1055 376 if (!context) {
james@1055 377 /* no need to create context if op is a READ - either something is wrong or we were just loaded */
james@1055 378 //FUNCTION_MSG("Failed to find context\n");
james@1055 379 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1055 380 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 381 }
james@1055 382 if (!(data->Flags & FLTFL_CALLBACK_DATA_IRP_OPERATION)) {
james@1055 383 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1055 384 return FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 385 }
james@1055 386
james@1055 387 status = FLT_PREOP_COMPLETE;
james@1055 388 for (i = 0; i < (int)data->Iopb->Parameters.Read.Length / 4096; i++) {
james@1055 389 ULONG page = (ULONG)(data->Iopb->Parameters.Read.ByteOffset.QuadPart >> PAGE_SHIFT) + i;
james@1055 390
james@1055 391 tmem_op.cmd = TMEM_GET_PAGE;
james@1055 392 tmem_op.pool_id = context->pool_id;
james@1055 393 tmem_op.u.gen.oid[0] = 0;
james@1055 394 tmem_op.u.gen.oid[1] = 0;
james@1055 395 tmem_op.u.gen.oid[2] = 0;
james@1055 396 tmem_op.u.gen.index = page;
james@1055 397 tmem_op.u.gen.tmem_offset = 0;
james@1055 398 tmem_op.u.gen.pfn_offset = 0;
james@1055 399 tmem_op.u.gen.len = 0;
james@1055 400 set_xen_guest_handle(tmem_op.u.gen.gmfn, (void *)MmGetMdlPfnArray(data->Iopb->Parameters.Read.MdlAddress)[i]);
james@1055 401 rc = XnTmemOp(&tmem_op);
james@1055 402 if (rc == 1) {
james@1055 403 context->get_success_count++;
james@1055 404 } else if (rc == 0) {
james@1055 405 status = FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 406 context->get_fail_count++;
james@1055 407 } else {
james@1055 408 FUNCTION_MSG("TMEM_GET_PAGE = %d\n", rc);
james@1055 409 status = FLT_PREOP_SUCCESS_NO_CALLBACK;
james@1055 410 context->get_fail_count++;
james@1057 411 context->error_count++;
james@1055 412 }
james@1055 413 }
james@1055 414
james@1055 415 if (((context->put_success_count + context->put_fail_count + context->get_success_count + context->get_fail_count) & 0xff) == 0) {
james@1055 416 FUNCTION_MSG(" put_success_count = %I64d\n", context->put_success_count);
james@1055 417 FUNCTION_MSG(" put_fail_count = %I64d\n", context->put_fail_count);
james@1055 418 FUNCTION_MSG(" get_success_count = %I64d\n", context->get_success_count);
james@1055 419 FUNCTION_MSG(" get_fail_count = %I64d\n", context->get_fail_count);
james@1057 420 FUNCTION_MSG(" error_count = %I64d\n", context->error_count);
james@1055 421 }
james@1055 422 KeReleaseSpinLock(&global_context.lock, old_irql);
james@1055 423
james@1055 424 if (status == FLT_PREOP_COMPLETE) {
james@1055 425 data->IoStatus.Status = STATUS_SUCCESS;
james@1055 426 data->IoStatus.Information = data->Iopb->Parameters.Read.Length;
james@1055 427 }
james@1055 428 return status;
james@1055 429 }