/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=4:tabstop=4: * * Copyright (C) 2002 Cluster File Systems, Inc. * Author: Matt Wu * * This file is part of Lustre, http://www.lustre.org. * * Lustre is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * Lustre 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 for more details. * * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DEBUG_SUBSYSTEM S_LNET /* * Included Headers */ #include /* 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); /* pingcli module init/exit routines */ DECLARE_INIT(pingcli_init); DECLARE_EXIT(pingcli_cleanup); /* pingsrv module init/exit routines */ DECLARE_INIT(pingsrv_init); DECLARE_EXIT(pingsrv_cleanup); /* * structure definitions */ #define LUSTRE_PING_VERSION 0x00010000 /* ping srv/cli version: 0001.0000 */ #define LUSTRE_PING_DEVICE L"\\Device\\LNET" /* device object name */ #define LUSTRE_PING_SYMLNK L"\\DosDevices\\LNET" /* user-visible name for the device*/ typedef struct _DEVICE_EXTENSION { BOOLEAN bProcFS; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; /* * global definitions */ PDEVICE_OBJECT PingObject = NULL; /* ping device object */ PDEVICE_OBJECT ProcObject = NULL; /* procfs emulator device */ /* * common routines */ // // complete Irp request ... // NTSTATUS UTCompleteIrp( 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 UTCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { KdPrint(("UTCreate: DeviceCreate ...\n")); return UTCompleteIrp(Irp,STATUS_SUCCESS,0); } // // Close Devcie ... // NTSTATUS UTClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KdPrint(("UTClose: Device Closed.\n")); return UTCompleteIrp(Irp, STATUS_SUCCESS, 0); UNREFERENCED_PARAMETER(DeviceObject); } NTSTATUS UTShutdown( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { KdPrint(("UTShutdown: shuting TdiSock ...\n")); return UTCompleteIrp(Irp, STATUS_SUCCESS, 0); UNREFERENCED_PARAMETER(DeviceObject); } // // driver frame Routines ... // NTSTATUS UTDeviceControl( 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; KdPrint(("UTDeviceControl: Device Ioctl ...\n")); 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)(LUSTRE_PING_VERSION); Irp->IoStatus.Information = sizeof(ULONG); Status = STATUS_SUCCESS; break; default: break; } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); KdPrint(("UTDeviceControl: Device Ioctl returned.\n")); 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; KdPrint(("ProcCreate: Proc device is being opened ...\n")); 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 UTCompleteIrp(Irp, Status, 0); } // // Close Devcie ... // NTSTATUS ProcClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; cfs_file_t * fp; KdPrint(("ProcClose: Proc device object is to be closed.\n")); 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 UTCompleteIrp(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; KdPrint(("ProcDeviceControl: Proc device ioctling ...\n")); 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)(LUSTRE_PING_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)); } if (rc == 0) { Irp->IoStatus.Information = InputLength; Status = STATUS_SUCCESS; } } } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); KdPrint(("ProcDeviceControl: Proc device ioctl returned with status = %xh.\n", Status)); 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 UTCompleteIrp(Irp, Status, rc); } // // common dispatch routines // NTSTATUS UTDispatchRequest( 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 == PingObject) { Status = UTCreate(DeviceObject, Irp); } else if (DeviceObject == ProcObject) { Status = ProcCreate(DeviceObject, Irp); } break; case IRP_MJ_CLOSE: if (DeviceObject == PingObject) { Status = UTClose(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 == PingObject) { Status = UTDeviceControl(DeviceObject, Irp); } else if (DeviceObject == ProcObject) { Status = ProcDeviceControl(DeviceObject, Irp); } break; case IRP_MJ_SHUTDOWN: Status = UTShutdown(DeviceObject, Irp); break; default: KdPrint(("UTDispatchRequest: Major Function: %xh is not supported.\n", IrpSp->MajorFunction)); UTCompleteIrp(Irp, Status, 0); break; } } __finally { } return Status; } // // create a device object and a dosdevice symbol link // PDEVICE_OBJECT CreateDevice( 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->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return DeviceObject; } // // DriverEntry // NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { KdPrint(("Lustre ping test: Build Time: " __DATE__ " " __TIME__ "\n")); KdPrint(("Lustre ping test: DriverEntry ... \n")); /* initialize libcfs module */ if (module_init_libcfs_module() != 0) { KdPrint(("ping: error initialize module: libcfs ...\n")); goto errorout; } /* initialize lnet module */ if (module_init_lnet() != 0) { module_exit_libcfs_module(); KdPrint(("ping: error initialize module: lnet ...\n")); goto errorout; } /* initialize tdinal module */ if (module_ksocknal_module_init() != 0) { module_fini_lnet(); module_exit_libcfs_module(); KdPrint(("ping: error initialize module: tdilnd ...\n")); goto errorout; } #if defined(LUSTRE_PING_CLI) /* initialize pingcli module */ if (module_pingcli_init() != 0) { module_ksocknal_module_fini(); module_fini_lnet(); module_exit_libcfs_module(); KdPrint(("ping: error initialize module: pingcli ...\n")); goto errorout; } #endif #if defined(LUSTRE_PING_SRV) /* initialize pingsrv module */ if (module_pingsrv_init() != 0) { module_ksocknal_module_fini(); module_fini_lnet(); module_exit_libcfs_module(); KdPrint(("ping: error initialize module: pingsrv ...\n")); goto errorout; } #endif /* create the ping device object */ PingObject = CreateDevice( DriverObject, LUSTRE_PING_DEVICE, LUSTRE_PING_SYMLNK, FALSE ); if (!PingObject) { #if defined(LUSTRE_PING_CLI) module_pingcli_cleanup(); #endif #if defined(LUSTRE_PING_SRV) module_pingsrv_cleanup(); #endif module_ksocknal_module_fini(); module_fini_lnet(); module_exit_libcfs_module(); return STATUS_INSUFFICIENT_RESOURCES; } /* create the libcfs proc fs emultor device object */ ProcObject = CreateDevice( DriverObject, LUSTRE_PROC_DEVICE, LUSTRE_PROC_SYMLNK, TRUE ); if (!ProcObject) { IoDeleteDevice(PingObject); #if defined(LUSTRE_PING_CLI) module_pingcli_cleanup(); #endif #if defined(LUSTRE_PING_SRV) module_pingsrv_cleanup(); #endif 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] = UTDispatchRequest; DriverObject->MajorFunction[IRP_MJ_CLOSE] = UTDispatchRequest; DriverObject->MajorFunction[IRP_MJ_READ] = UTDispatchRequest; DriverObject->MajorFunction[IRP_MJ_WRITE] = UTDispatchRequest; DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = UTDispatchRequest; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UTDispatchRequest; return STATUS_SUCCESS; errorout: cfs_enter_debugger(); return STATUS_UNSUCCESSFUL; }