Whamcloud - gitweb
LU-1961 build: fix 'dereference before null check' errors
[fs/lustre-release.git] / lnet / selftest / winnt / selftest-winnt.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * winnt selftest driver framework
35  *
36  */
37
38 #define DEBUG_SUBSYSTEM S_LNET
39
40 /*
41  *  Included Headers 
42  */
43
44
45 #include <libcfs/libcfs.h>
46
47
48 /* libcfs module init/exit routines */
49 DECLARE_INIT(init_libcfs_module);
50 DECLARE_EXIT(exit_libcfs_module);
51
52 /* portal module init/exit routines */
53 DECLARE_INIT(init_lnet);
54 DECLARE_EXIT(fini_lnet);
55
56 /* tdinal module init/exit routines */
57 DECLARE_INIT(ksocknal_module_init);
58 DECLARE_EXIT(ksocknal_module_fini);
59
60 /* selftest module init/exit routines */
61 DECLARE_INIT(lnet_selftest_init);
62 DECLARE_EXIT(lnet_selftest_fini);
63
64 /*
65  * module info
66  */
67
68 cfs_module_t libcfs_global_module =  {"selftest"};
69
70 /*
71  * structure definitions
72  */
73
74 #define LNET_SELFTEST_VERSION   0x00010001                  /* LNET selftest module version */
75
76 #define LNET_SELFTEST_DEVICE    L"\\Device\\Selftest"       /* device object name */
77 #define LNET_SELFTEST_SYMLNK    L"\\DosDevices\\Selftest"   /* user-visible name for the device*/
78
79 typedef struct _DEVICE_EXTENSION {
80     BOOLEAN    bProcFS;
81 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
82
83 /*
84  *  global definitions
85  */
86
87 PDEVICE_OBJECT  SelfObject = NULL;  /* lnet selftest object */
88 PDEVICE_OBJECT  ProcObject = NULL;  /* procfs emulator device */
89
90
91 /*
92  *  common routines
93  */
94
95
96 //
97 // complete Irp request ...
98 //
99
100 NTSTATUS
101 LstCompleteIrp(
102     PIRP        Irp,
103     NTSTATUS    Status,
104     ULONG       Info
105     )
106 {
107     Irp->IoStatus.Status = Status;
108     Irp->IoStatus.Information = Info;
109     IoCompleteRequest(Irp,IO_NO_INCREMENT);
110
111     return Status;
112 }
113
114 //
115 //  Open/Create Device ...
116 //
117
118 NTSTATUS
119 LstCreate(
120     IN PDEVICE_OBJECT   DeviceObject,
121     IN PIRP             Irp
122     )
123 {
124     KdPrint(("LstCreate: DeviceCreate ...\n"));
125
126     return LstCompleteIrp(Irp,STATUS_SUCCESS,0);
127 }
128
129 //
130 // Close Devcie ...
131 //
132
133 NTSTATUS
134 LstClose(
135     IN PDEVICE_OBJECT   DeviceObject,
136     IN PIRP             Irp)
137 {
138     KdPrint(("LstClose: Device Closed.\n"));
139
140     return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
141
142     UNREFERENCED_PARAMETER(DeviceObject);
143 }
144
145
146 //
147 // computer is being shut down
148 //
149
150 NTSTATUS
151 LstShutdown(
152     IN PDEVICE_OBJECT   DeviceObject,
153     IN PIRP             Irp
154     )
155 {
156     KdPrint(("LstShutdown:  ...\n"));
157
158     return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
159
160     UNREFERENCED_PARAMETER(DeviceObject);
161 }
162
163 //
164 // device io control
165 //
166
167
168 NTSTATUS
169 LstDeviceControl(
170     IN PDEVICE_OBJECT   DeviceObject,
171     IN PIRP             Irp
172     )
173 {
174     NTSTATUS            Status = STATUS_INVALID_DEVICE_REQUEST;
175     PIO_STACK_LOCATION  IrpSp;
176
177     ULONG               ControlCode;
178     ULONG               InputLength;
179     ULONG               OutputLength;
180
181     PVOID               lpvInBuffer;
182
183     Irp->IoStatus.Information = 0;
184     IrpSp = IoGetCurrentIrpStackLocation(Irp);
185
186     ControlCode  = IrpSp->Parameters.DeviceIoControl.IoControlCode;
187     InputLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
188     OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
189     lpvInBuffer  = Irp->AssociatedIrp.SystemBuffer;
190
191     ASSERT (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
192
193     switch (ControlCode)
194     {
195         case IOCTL_LIBCFS_VERSION:
196
197             *((ULONG *)lpvInBuffer) = (ULONG)(LNET_SELFTEST_VERSION);
198             Irp->IoStatus.Information = sizeof(ULONG);
199             Status = STATUS_SUCCESS;
200             break;
201
202         default:
203             break;
204     }
205
206     Irp->IoStatus.Status = Status;
207     IoCompleteRequest(Irp, IO_NO_INCREMENT);
208
209     return Status;
210 }
211
212 NTSTATUS
213 ProcCreate(
214     IN PDEVICE_OBJECT   DeviceObject,
215     IN PIRP             Irp
216     )
217 {
218     NTSTATUS                    Status;
219     PIO_STACK_LOCATION          IrpSp;
220
221     FILE_FULL_EA_INFORMATION *  ea;
222     cfs_file_t *                fp;
223
224     IrpSp = IoGetCurrentIrpStackLocation(Irp);
225     ea = (PFILE_FULL_EA_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
226
227     if (!ea) {
228         Status = STATUS_INVALID_PARAMETER;
229     } else {
230         fp = lustre_open_file(&ea->EaName[0]);
231         if (!fp) {
232             Status = STATUS_OBJECT_NAME_NOT_FOUND;
233         } else {
234             IrpSp->FileObject->FsContext = fp;
235             IrpSp->FileObject->FsContext2 = fp->private_data;
236             Status = STATUS_SUCCESS;
237         }
238     }
239
240     return LstCompleteIrp(Irp, Status, 0);
241 }
242
243 //
244 // Close Devcie ...
245 //
246
247 NTSTATUS
248 ProcClose(
249     IN PDEVICE_OBJECT   DeviceObject,
250     IN PIRP             Irp)
251 {
252     PIO_STACK_LOCATION          IrpSp;
253
254     cfs_file_t *                fp;
255
256     IrpSp = IoGetCurrentIrpStackLocation(Irp);
257     fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
258     ASSERT(fp != NULL);
259     ASSERT(IrpSp->FileObject->FsContext2 == fp->private_data);
260
261     lustre_close_file(fp);
262
263     return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
264
265     UNREFERENCED_PARAMETER(DeviceObject);
266 }
267
268 /*
269  * proc frame routines
270  */
271
272 NTSTATUS
273 ProcDeviceControl(
274     IN PDEVICE_OBJECT   DeviceObject,
275     IN PIRP             Irp
276     )
277 {
278     NTSTATUS            Status = STATUS_INVALID_DEVICE_REQUEST;
279     PIO_STACK_LOCATION  IrpSp;
280
281     ULONG               ControlCode;
282     ULONG               InputLength;
283     ULONG               OutputLength;
284
285     PVOID               lpvInBuffer;
286
287     Irp->IoStatus.Information = 0;
288     IrpSp = IoGetCurrentIrpStackLocation(Irp);
289
290     ControlCode  = IrpSp->Parameters.DeviceIoControl.IoControlCode;
291     InputLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
292     OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
293     lpvInBuffer  = Irp->AssociatedIrp.SystemBuffer;
294
295     ASSERT (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
296
297     switch (ControlCode)
298     {
299         case IOCTL_LIBCFS_VERSION:
300
301             *((ULONG *)lpvInBuffer) = (ULONG)(LNET_SELFTEST_VERSION);
302             Irp->IoStatus.Information = sizeof(ULONG);
303
304             Status = STATUS_SUCCESS;
305
306             break;
307
308         case IOCTL_LIBCFS_ENTRY:
309         {
310             int rc = 0;
311             cfs_file_t * fp;
312
313             fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
314
315             if (!fp) {
316                 rc = -EINVAL;
317             } else {
318                 rc = lustre_ioctl_file(fp, (PCFS_PROC_IOCTL) lpvInBuffer);
319             }
320
321             ((PCFS_PROC_IOCTL) lpvInBuffer)->rc = rc;
322             Irp->IoStatus.Information = InputLength;
323             Status = STATUS_SUCCESS;
324         }    
325     }
326
327     Irp->IoStatus.Status = Status;
328     IoCompleteRequest(Irp, IO_NO_INCREMENT);
329
330     return Status;
331 }
332
333
334 NTSTATUS
335 ProcReadWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
336 {
337     PIO_STACK_LOCATION  IrpSp;
338     NTSTATUS            Status;
339
340     cfs_file_t *        fp;
341     int                 rc;
342     PCHAR               buf;
343
344     IrpSp = IoGetCurrentIrpStackLocation(Irp);
345     if (Irp->MdlAddress) {
346         buf = MmGetSystemAddressForMdlSafe(
347                         Irp->MdlAddress,
348                         NormalPagePriority);
349     } else {
350         buf = Irp->AssociatedIrp.SystemBuffer;
351     }
352
353     if (buf == NULL) {
354         Status = STATUS_SUCCESS;
355         rc = 0;
356     } else {
357         fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
358
359         if (!fp) {
360             Status = STATUS_INVALID_PARAMETER;
361             goto errorout;
362         }
363
364         if (IrpSp->MajorFunction == IRP_MJ_READ) {
365             rc = lustre_read_file(
366                     fp, IrpSp->Parameters.Read.ByteOffset.LowPart,
367                     IrpSp->Parameters.Read.Length, buf);
368         } else {
369             rc = lustre_write_file(
370                     fp, IrpSp->Parameters.Write.ByteOffset.LowPart,
371                     IrpSp->Parameters.Write.Length, buf);
372         }
373         if (rc < 0) {
374             cfs_enter_debugger();
375             Status = STATUS_UNSUCCESSFUL;
376         } else {
377             Status = STATUS_SUCCESS;
378         }
379     }
380
381  
382 errorout:
383     return LstCompleteIrp(Irp, Status, rc);
384 }
385
386
387 //
388 //  common dispatch routines
389 //
390
391 NTSTATUS
392 LstDispatchRequest(
393     IN PDEVICE_OBJECT DeviceObject,
394     IN PIRP           Irp
395     )
396 {
397     NTSTATUS            Status;
398     PIO_STACK_LOCATION  IrpSp;
399
400     Status = STATUS_INVALID_DEVICE_REQUEST;
401
402     __try {
403
404         IrpSp = IoGetCurrentIrpStackLocation(Irp);
405
406         switch (IrpSp->MajorFunction) {
407
408             case IRP_MJ_CREATE:
409                 if (DeviceObject == SelfObject) {
410                     Status = LstCreate(DeviceObject, Irp);
411                 } else if (DeviceObject == ProcObject) {
412                     Status = ProcCreate(DeviceObject, Irp);
413                 }
414                 break;
415         
416             case IRP_MJ_CLOSE:
417                 if (DeviceObject == SelfObject) {
418                     Status = LstClose(DeviceObject, Irp);
419                 } else if (DeviceObject == ProcObject) {
420                     Status = ProcClose(DeviceObject, Irp);
421                 }
422                 break;
423
424             case IRP_MJ_READ:
425             case IRP_MJ_WRITE:
426                 if (DeviceObject == ProcObject) {
427                     Status = ProcReadWrite(DeviceObject, Irp);
428                 }
429                 break;
430         
431             case IRP_MJ_DEVICE_CONTROL:
432                 if (DeviceObject == SelfObject) {
433                     Status = LstDeviceControl(DeviceObject, Irp);
434                 } else if (DeviceObject == ProcObject) {
435                     Status = ProcDeviceControl(DeviceObject, Irp);
436                 }
437                 break;
438
439             case IRP_MJ_SHUTDOWN:
440                 Status = LstShutdown(DeviceObject, Irp);
441                 break;
442
443             default:
444
445                 KdPrint(("LstDispatchRequest: Major Function: %xh is not supported.\n",
446                            IrpSp->MajorFunction));
447                 LstCompleteIrp(Irp, Status, 0);
448                 break;
449         }
450     }
451
452     __finally {
453     }
454
455     return Status;
456 }
457
458 //
459 // create a device object and a dosdevice symbol link
460 //
461
462 PDEVICE_OBJECT
463 LstCreateDevice(
464     IN PDRIVER_OBJECT   DriverObject,
465     IN PWCHAR           DeviceName,
466     IN PWCHAR           SymlnkName,
467     IN BOOLEAN          bProcFS
468     )
469 {
470     NTSTATUS            Status;
471
472     UNICODE_STRING      NtDevName;
473     UNICODE_STRING      Win32DevName;
474
475     PDEVICE_EXTENSION   DeviceExtension;
476     PDEVICE_OBJECT      DeviceObject;
477
478     /* create the device object with the specified name */
479
480     RtlInitUnicodeString(&NtDevName, DeviceName);
481     
482     Status = IoCreateDevice(
483                     DriverObject,
484                     sizeof(DEVICE_EXTENSION),
485                     &NtDevName,
486                     FILE_DEVICE_UNKNOWN,
487                     0,
488                     FALSE,
489                     &DeviceObject );
490         
491     if (!NT_SUCCESS(Status)) {
492
493         cfs_enter_debugger();
494         return NULL;
495     }
496
497     /* create the symlink to make the device visible to user */
498
499     RtlInitUnicodeString(&Win32DevName, SymlnkName);
500     Status = IoCreateSymbolicLink(&Win32DevName, &NtDevName);
501
502     if (!NT_SUCCESS(Status)) {
503
504         IoDeleteDevice(DeviceObject);
505         return NULL;
506     }
507
508     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceObjectExtension;
509     DeviceExtension->bProcFS = bProcFS;
510
511     DeviceObject->AlignmentRequirement = 0;
512     DeviceObject->SectorSize = 0;
513     DeviceObject->Flags |= DO_BUFFERED_IO;
514     DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
515
516     return DeviceObject;
517 }
518
519 //
520 // DriverEntry
521 //
522
523 NTSTATUS DriverEntry(
524     IN PDRIVER_OBJECT  DriverObject,
525     IN PUNICODE_STRING RegistryPath 
526     )
527 {
528     KdPrint(("LNet selftest: Build Time: " __DATE__ " " __TIME__ "\n"));
529     KdPrint(("LNet selftest: DriverEntry ... \n"));
530
531     /* initialize libcfs module */
532     if (module_init_libcfs_module() != 0) {
533         KdPrint(("selftest: failed to initialize module: libcfs ...\n"));
534         goto errorout;
535     }
536
537     /* initialize portals module */
538     if (module_init_lnet() != 0) {
539         KdPrint(("selftest: failed to initialize module: lnet ...\n"));
540         module_exit_libcfs_module();
541         goto errorout;
542     }
543
544     /* initialize tdinal module */
545     if (module_ksocknal_module_init() != 0) {
546         KdPrint(("selftest: failed to initialize module: socklnd ...\n"));
547         module_fini_lnet();
548         module_exit_libcfs_module();
549         goto errorout;
550     }
551
552     /* initialize lnet selttest module */
553     if (module_lnet_selftest_init() != 0) {
554         KdPrint(("selftest: failed to initialize module: selftest ...\n"));
555         module_ksocknal_module_fini();
556         module_fini_lnet();
557         module_exit_libcfs_module();
558         goto errorout;
559     }
560
561     /* create lnet selftest device object */
562     SelfObject = LstCreateDevice(
563                         DriverObject,
564                         LNET_SELFTEST_DEVICE,
565                         LNET_SELFTEST_SYMLNK,
566                         FALSE );
567     if (!SelfObject) {
568         KdPrint(("selftest: failed to allocate DeviceObject ...\n"));
569         module_lnet_selftest_fini();
570         module_ksocknal_module_fini();
571         module_fini_lnet();
572         module_exit_libcfs_module();
573
574         return STATUS_INSUFFICIENT_RESOURCES;
575     }
576
577     /* create the libcfs proc fs emultor device object */
578     ProcObject  = LstCreateDevice(
579                         DriverObject,
580                         LUSTRE_PROC_DEVICE,
581                         LUSTRE_PROC_SYMLNK,
582                         TRUE );
583     if (!ProcObject) {
584
585         KdPrint(("selftest: failed to allocate proc DeviceObject ...\n"));
586         /* remove Selftest DeviceObject */
587         IoDeleteDevice(SelfObject);
588         module_lnet_selftest_fini();
589         module_ksocknal_module_fini();
590         module_fini_lnet();
591         module_exit_libcfs_module();
592         return STATUS_INSUFFICIENT_RESOURCES;
593     }
594
595     /* initialize the driver callback routines */
596
597     DriverObject->MajorFunction[IRP_MJ_CREATE]          = LstDispatchRequest;
598     DriverObject->MajorFunction[IRP_MJ_CLOSE]           = LstDispatchRequest;
599     DriverObject->MajorFunction[IRP_MJ_READ]            = LstDispatchRequest;
600     DriverObject->MajorFunction[IRP_MJ_WRITE]           = LstDispatchRequest;
601     DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        = LstDispatchRequest;
602     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = LstDispatchRequest;
603
604     return STATUS_SUCCESS;
605
606 errorout:
607
608     cfs_enter_debugger();
609
610     return STATUS_UNSUCCESSFUL;
611 }