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