Whamcloud - gitweb
b=16150
[fs/lustre-release.git] / lnet / selftest / winnt / selftest-winnt.c
diff --git a/lnet/selftest/winnt/selftest-winnt.c b/lnet/selftest/winnt/selftest-winnt.c
new file mode 100755 (executable)
index 0000000..5b3dee2
--- /dev/null
@@ -0,0 +1,613 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=4:tabstop=4:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * winnt selftest driver framework
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_LNET
+
+/*
+ *  Included Headers 
+ */
+
+
+#include <libcfs/libcfs.h>
+
+
+/* libcfs module init/exit routines */
+DECLARE_INIT(init_libcfs_module);
+DECLARE_EXIT(exit_libcfs_module);
+
+/* portal module init/exit routines */
+DECLARE_INIT(init_lnet);
+DECLARE_EXIT(fini_lnet);
+
+/* tdinal module init/exit routines */
+DECLARE_INIT(ksocknal_module_init);
+DECLARE_EXIT(ksocknal_module_fini);
+
+/* selftest module init/exit routines */
+DECLARE_INIT(lnet_selftest_init);
+DECLARE_EXIT(lnet_selftest_fini);
+
+/*
+ * module info
+ */
+
+struct module libcfs_global_module =  {"selftest"};
+
+/*
+ * structure definitions
+ */
+
+#define LNET_SELFTEST_VERSION   0x00010001                  /* LNET selftest module version */
+
+#define LNET_SELFTEST_DEVICE    L"\\Device\\Selftest"       /* device object name */
+#define LNET_SELFTEST_SYMLNK    L"\\DosDevices\\Selftest"   /* user-visible name for the device*/
+
+typedef struct _DEVICE_EXTENSION {
+    BOOLEAN    bProcFS;
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*
+ *  global definitions
+ */
+
+PDEVICE_OBJECT  SelfObject = NULL;  /* lnet selftest object */
+PDEVICE_OBJECT  ProcObject = NULL;  /* procfs emulator device */
+
+
+/*
+ *  common routines
+ */
+
+
+//
+// complete Irp request ...
+//
+
+NTSTATUS
+LstCompleteIrp(
+    PIRP        Irp,
+    NTSTATUS    Status,
+    ULONG       Info
+    )
+{
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = Info;
+    IoCompleteRequest(Irp,IO_NO_INCREMENT);
+
+    return Status;
+}
+
+//
+//  Open/Create Device ...
+//
+
+NTSTATUS
+LstCreate(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    KdPrint(("LstCreate: DeviceCreate ...\n"));
+
+    return LstCompleteIrp(Irp,STATUS_SUCCESS,0);
+}
+
+//
+// Close Devcie ...
+//
+
+NTSTATUS
+LstClose(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp)
+{
+    KdPrint(("LstClose: Device Closed.\n"));
+
+    return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+}
+
+
+//
+// computer is being shut down
+//
+
+NTSTATUS
+LstShutdown(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    KdPrint(("LstShutdown:  ...\n"));
+
+    return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+}
+
+//
+// device io control
+//
+
+
+NTSTATUS
+LstDeviceControl(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    NTSTATUS            Status = STATUS_INVALID_DEVICE_REQUEST;
+    PIO_STACK_LOCATION  IrpSp;
+
+    ULONG               ControlCode;
+    ULONG               InputLength;
+    ULONG               OutputLength;
+
+    PVOID               lpvInBuffer;
+
+    Irp->IoStatus.Information = 0;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    ControlCode  = IrpSp->Parameters.DeviceIoControl.IoControlCode;
+    InputLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
+    OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
+    lpvInBuffer  = Irp->AssociatedIrp.SystemBuffer;
+
+    ASSERT (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
+
+    switch (ControlCode)
+    {
+        case IOCTL_LIBCFS_VERSION:
+
+            *((ULONG *)lpvInBuffer) = (ULONG)(LNET_SELFTEST_VERSION);
+            Irp->IoStatus.Information = sizeof(ULONG);
+            Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+NTSTATUS
+ProcCreate(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    NTSTATUS                    Status;
+    PIO_STACK_LOCATION          IrpSp;
+
+    FILE_FULL_EA_INFORMATION *  ea;
+    cfs_file_t *                fp;
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    ea = (PFILE_FULL_EA_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
+
+    if (!ea) {
+        Status = STATUS_INVALID_PARAMETER;
+    } else {
+        fp = lustre_open_file(&ea->EaName[0]);
+        if (!fp) {
+            Status = STATUS_OBJECT_NAME_NOT_FOUND;
+        } else {
+            IrpSp->FileObject->FsContext = fp;
+            IrpSp->FileObject->FsContext2 = fp->private_data;
+            Status = STATUS_SUCCESS;
+        }
+    }
+
+    return LstCompleteIrp(Irp, Status, 0);
+}
+
+//
+// Close Devcie ...
+//
+
+NTSTATUS
+ProcClose(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp)
+{
+    PIO_STACK_LOCATION          IrpSp;
+
+    cfs_file_t *                fp;
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
+    ASSERT(fp != NULL);
+    ASSERT(IrpSp->FileObject->FsContext2 == fp->private_data);
+
+    lustre_close_file(fp);
+
+    return LstCompleteIrp(Irp, STATUS_SUCCESS, 0);
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+}
+
+/*
+ * proc frame routines
+ */
+
+NTSTATUS
+ProcDeviceControl(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    NTSTATUS            Status = STATUS_INVALID_DEVICE_REQUEST;
+    PIO_STACK_LOCATION  IrpSp;
+
+    ULONG               ControlCode;
+    ULONG               InputLength;
+    ULONG               OutputLength;
+
+    PVOID               lpvInBuffer;
+
+    Irp->IoStatus.Information = 0;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    ControlCode  = IrpSp->Parameters.DeviceIoControl.IoControlCode;
+    InputLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
+    OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
+    lpvInBuffer  = Irp->AssociatedIrp.SystemBuffer;
+
+    ASSERT (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
+
+    switch (ControlCode)
+    {
+        case IOCTL_LIBCFS_VERSION:
+
+            *((ULONG *)lpvInBuffer) = (ULONG)(LNET_SELFTEST_VERSION);
+            Irp->IoStatus.Information = sizeof(ULONG);
+
+            Status = STATUS_SUCCESS;
+
+            break;
+
+        case IOCTL_LIBCFS_ENTRY:
+        {
+            int rc = 0;
+            cfs_file_t * fp;
+
+            fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
+
+            if (!fp) {
+                rc = -EINVAL;
+            } else {
+                rc = lustre_ioctl_file(fp, (PCFS_PROC_IOCTL) lpvInBuffer);
+            }
+
+            ((PCFS_PROC_IOCTL) lpvInBuffer)->rc = rc;
+            Irp->IoStatus.Information = InputLength;
+            Status = STATUS_SUCCESS;
+        }    
+    }
+
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}
+
+
+NTSTATUS
+ProcReadWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+    PIO_STACK_LOCATION  IrpSp;
+    NTSTATUS            Status;
+
+    cfs_file_t *        fp;
+    int                 rc;
+    PCHAR               buf;
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    if (Irp->MdlAddress) {
+        buf = MmGetSystemAddressForMdlSafe(
+                        Irp->MdlAddress,
+                        NormalPagePriority);
+    } else {
+        buf = Irp->AssociatedIrp.SystemBuffer;
+    }
+
+    if (buf == NULL) {
+        Status = STATUS_SUCCESS;
+        rc = 0;
+    } else {
+        fp = (cfs_file_t *) IrpSp->FileObject->FsContext;
+
+        if (!fp) {
+            Status = STATUS_INVALID_PARAMETER;
+            goto errorout;
+        }
+
+        if (IrpSp->MajorFunction == IRP_MJ_READ) {
+            rc = lustre_read_file(
+                    fp, IrpSp->Parameters.Read.ByteOffset.LowPart,
+                    IrpSp->Parameters.Read.Length, buf);
+        } else {
+            rc = lustre_write_file(
+                    fp, IrpSp->Parameters.Write.ByteOffset.LowPart,
+                    IrpSp->Parameters.Write.Length, buf);
+        }
+        if (rc < 0) {
+            cfs_enter_debugger();
+            Status = STATUS_UNSUCCESSFUL;
+        } else {
+            Status = STATUS_SUCCESS;
+        }
+    }
+
+errorout:
+    return LstCompleteIrp(Irp, Status, rc);
+}
+
+
+//
+//  common dispatch routines
+//
+
+NTSTATUS
+LstDispatchRequest(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP           Irp
+    )
+{
+    NTSTATUS            Status;
+    PIO_STACK_LOCATION  IrpSp;
+
+    Status = STATUS_INVALID_DEVICE_REQUEST;
+
+    __try {
+
+        IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+        switch (IrpSp->MajorFunction) {
+
+            case IRP_MJ_CREATE:
+                if (DeviceObject == SelfObject) {
+                    Status = LstCreate(DeviceObject, Irp);
+                } else if (DeviceObject == ProcObject) {
+                    Status = ProcCreate(DeviceObject, Irp);
+                }
+                break;
+        
+            case IRP_MJ_CLOSE:
+                if (DeviceObject == SelfObject) {
+                    Status = LstClose(DeviceObject, Irp);
+                } else if (DeviceObject == ProcObject) {
+                    Status = ProcClose(DeviceObject, Irp);
+                }
+                break;
+
+            case IRP_MJ_READ:
+            case IRP_MJ_WRITE:
+                if (DeviceObject == ProcObject) {
+                    Status = ProcReadWrite(DeviceObject, Irp);
+                }
+                break;
+        
+            case IRP_MJ_DEVICE_CONTROL:
+                if (DeviceObject == SelfObject) {
+                    Status = LstDeviceControl(DeviceObject, Irp);
+                } else if (DeviceObject == ProcObject) {
+                    Status = ProcDeviceControl(DeviceObject, Irp);
+                }
+                break;
+
+            case IRP_MJ_SHUTDOWN:
+                Status = LstShutdown(DeviceObject, Irp);
+                break;
+
+            default:
+
+                KdPrint(("LstDispatchRequest: Major Function: %xh is not supported.\n",
+                           IrpSp->MajorFunction));
+                LstCompleteIrp(Irp, Status, 0);
+                break;
+        }
+    }
+
+    __finally {
+    }
+
+    return Status;
+}
+
+//
+// create a device object and a dosdevice symbol link
+//
+
+PDEVICE_OBJECT
+LstCreateDevice(
+    IN PDRIVER_OBJECT   DriverObject,
+    IN PWCHAR           DeviceName,
+    IN PWCHAR           SymlnkName,
+    IN BOOLEAN          bProcFS
+    )
+{
+    NTSTATUS            Status;
+
+    UNICODE_STRING      NtDevName;
+    UNICODE_STRING      Win32DevName;
+
+    PDEVICE_EXTENSION   DeviceExtension;
+    PDEVICE_OBJECT      DeviceObject;
+
+    /* create the device object with the specified name */
+
+    RtlInitUnicodeString(&NtDevName, DeviceName);
+    
+    Status = IoCreateDevice(
+                    DriverObject,
+                    sizeof(DEVICE_EXTENSION),
+                    &NtDevName,
+                    FILE_DEVICE_UNKNOWN,
+                    0,
+                    FALSE,
+                    &DeviceObject );
+        
+    if (!NT_SUCCESS(Status)) {
+
+        cfs_enter_debugger();
+        return NULL;
+    }
+
+    /* create the symlink to make the device visible to user */
+
+    RtlInitUnicodeString(&Win32DevName, SymlnkName);
+    Status = IoCreateSymbolicLink(&Win32DevName, &NtDevName);
+
+    if (!NT_SUCCESS(Status)) {
+
+        IoDeleteDevice(DeviceObject);
+        return NULL;
+    }
+
+    DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceObjectExtension;
+    DeviceExtension->bProcFS = bProcFS;
+
+    DeviceObject->AlignmentRequirement = 0;
+    DeviceObject->SectorSize = 0;
+    DeviceObject->Flags |= DO_BUFFERED_IO;
+    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    return DeviceObject;
+}
+
+//
+// DriverEntry
+//
+
+NTSTATUS DriverEntry(
+    IN PDRIVER_OBJECT  DriverObject,
+    IN PUNICODE_STRING RegistryPath 
+    )
+{
+    KdPrint(("LNet selftest: Build Time: " __DATE__ " " __TIME__ "\n"));
+    KdPrint(("LNet selftest: DriverEntry ... \n"));
+
+    /* initialize libcfs module */
+    if (module_init_libcfs_module() != 0) {
+        KdPrint(("selftest: failed to initialize module: libcfs ...\n"));
+        goto errorout;
+    }
+
+    /* initialize portals module */
+    if (module_init_lnet() != 0) {
+        KdPrint(("selftest: failed to initialize module: lnet ...\n"));
+        module_exit_libcfs_module();
+        goto errorout;
+    }
+
+    /* initialize tdinal module */
+    if (module_ksocknal_module_init() != 0) {
+        KdPrint(("selftest: failed to initialize module: socklnd ...\n"));
+        module_fini_lnet();
+        module_exit_libcfs_module();
+        goto errorout;
+    }
+
+    /* initialize lnet selttest module */
+    if (module_lnet_selftest_init() != 0) {
+        KdPrint(("selftest: failed to initialize module: selftest ...\n"));
+        module_ksocknal_module_fini();
+        module_fini_lnet();
+        module_exit_libcfs_module();
+        goto errorout;
+    }
+
+    /* create lnet selftest device object */
+    SelfObject = LstCreateDevice(
+                        DriverObject,
+                        LNET_SELFTEST_DEVICE,
+                        LNET_SELFTEST_SYMLNK,
+                        FALSE );
+    if (!SelfObject) {
+        KdPrint(("selftest: failed to allocate DeviceObject ...\n"));
+        module_lnet_selftest_fini();
+        module_ksocknal_module_fini();
+        module_fini_lnet();
+        module_exit_libcfs_module();
+
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* create the libcfs proc fs emultor device object */
+    ProcObject  = LstCreateDevice(
+                        DriverObject,
+                        LUSTRE_PROC_DEVICE,
+                        LUSTRE_PROC_SYMLNK,
+                        TRUE );
+    if (!ProcObject) {
+
+        KdPrint(("selftest: failed to allocate proc DeviceObject ...\n"));
+        /* remove Selftest DeviceObject */
+        IoDeleteDevice(SelfObject);
+        module_lnet_selftest_fini();
+        module_ksocknal_module_fini();
+        module_fini_lnet();
+        module_exit_libcfs_module();
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* initialize the driver callback routines */
+
+    DriverObject->MajorFunction[IRP_MJ_CREATE]          = LstDispatchRequest;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]           = LstDispatchRequest;
+    DriverObject->MajorFunction[IRP_MJ_READ]            = LstDispatchRequest;
+    DriverObject->MajorFunction[IRP_MJ_WRITE]           = LstDispatchRequest;
+    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]        = LstDispatchRequest;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = LstDispatchRequest;
+
+    return STATUS_SUCCESS;
+
+errorout:
+
+    cfs_enter_debugger();
+
+    return STATUS_UNSUCCESSFUL;
+}