+++ /dev/null
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=4:tabstop=4:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * 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
-
-#include <libcfs/libcfs.h>
-
-const CHAR *dos_file_prefix = "\\??\\";
-
-/*
- * cfs_filp_open
- * To open or create a file in kernel mode
- *
- * Arguments:
- * name: name of the file to be opened or created, no dos path prefix
- * flags: open/creation attribute options
- * mode: access mode/permission to open or create
- * err: error code
- *
- * Return Value:
- * the pointer to the cfs_file_t or NULL if it fails
- *
- * Notes:
- * N/A
- */
-
-cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
-{
- cfs_file_t * fp = NULL;
-
- NTSTATUS Status;
-
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE FileHandle;
- IO_STATUS_BLOCK IoStatus;
- ACCESS_MASK DesiredAccess;
- ULONG CreateDisposition;
- ULONG ShareAccess;
- ULONG CreateOptions;
-
- USHORT NameLength = 0;
- USHORT PrefixLength = 0;
-
- UNICODE_STRING UnicodeName;
- PWCHAR UnicodeString = NULL;
-
- ANSI_STRING AnsiName;
- PUCHAR AnsiString = NULL;
-
- /* Analyze the flags settings */
-
- if (cfs_is_flag_set(flags, O_WRONLY)) {
- DesiredAccess = (GENERIC_WRITE | SYNCHRONIZE);
- ShareAccess = 0;
- } else if (cfs_is_flag_set(flags, O_RDWR)) {
- DesiredAccess = (GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE);
- ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
- } else {
- DesiredAccess = (GENERIC_READ | SYNCHRONIZE);
- ShareAccess = FILE_SHARE_READ;
- }
-
- if (cfs_is_flag_set(flags, O_CREAT)) {
- if (cfs_is_flag_set(flags, O_EXCL)) {
- CreateDisposition = FILE_CREATE;
- } else {
- CreateDisposition = FILE_OPEN_IF;
- }
- } else {
- CreateDisposition = FILE_OPEN;
- }
-
- if (cfs_is_flag_set(flags, O_TRUNC)) {
- if (cfs_is_flag_set(flags, O_EXCL)) {
- CreateDisposition = FILE_OVERWRITE;
- } else {
- CreateDisposition = FILE_OVERWRITE_IF;
- }
- }
-
- CreateOptions = 0;
-
- if (cfs_is_flag_set(flags, O_DIRECTORY)) {
- cfs_set_flag(CreateOptions, FILE_DIRECTORY_FILE);
- }
-
- if (cfs_is_flag_set(flags, O_SYNC)) {
- cfs_set_flag(CreateOptions, FILE_WRITE_THROUGH);
- }
-
- if (cfs_is_flag_set(flags, O_DIRECT)) {
- cfs_set_flag(CreateOptions, FILE_NO_INTERMEDIATE_BUFFERING);
- }
-
- /* Initialize the unicode path name for the specified file */
-
- NameLength = (USHORT)strlen(name);
-
- if (name[0] != '\\') {
- PrefixLength = (USHORT)strlen(dos_file_prefix);
- }
-
- AnsiString = cfs_alloc( sizeof(CHAR) * (NameLength + PrefixLength + 1),
- CFS_ALLOC_ZERO);
- if (NULL == AnsiString) {
- if (err) *err = -ENOMEM;
- return NULL;
- }
-
- UnicodeString = cfs_alloc( sizeof(WCHAR) * (NameLength + PrefixLength + 1),
- CFS_ALLOC_ZERO);
-
- if (NULL == UnicodeString) {
- if (err) *err = -ENOMEM;
- cfs_free(AnsiString);
- return NULL;
- }
-
- if (PrefixLength) {
- RtlCopyMemory(&AnsiString[0], dos_file_prefix , PrefixLength);
- }
-
- RtlCopyMemory(&AnsiString[PrefixLength], name, NameLength);
- NameLength += PrefixLength;
-
- AnsiName.MaximumLength = NameLength + 1;
- AnsiName.Length = NameLength;
- AnsiName.Buffer = AnsiString;
-
- UnicodeName.MaximumLength = (NameLength + 1) * sizeof(WCHAR);
- UnicodeName.Length = 0;
- UnicodeName.Buffer = (PWSTR)UnicodeString;
-
- RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, FALSE);
-
- /* Setup the object attributes structure for the file. */
-
- InitializeObjectAttributes(
- &ObjectAttributes,
- &UnicodeName,
- OBJ_CASE_INSENSITIVE |
- OBJ_KERNEL_HANDLE,
- NULL,
- NULL );
-
- /* Now to open or create the file now */
-
- Status = ZwCreateFile(
- &FileHandle,
- DesiredAccess,
- &ObjectAttributes,
- &IoStatus,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- ShareAccess,
- CreateDisposition,
- CreateOptions,
- NULL,
- 0 );
-
- /* Check the returned status of IoStatus... */
-
- if (!NT_SUCCESS(IoStatus.Status)) {
- *err = cfs_error_code(IoStatus.Status);
- cfs_free(UnicodeString);
- cfs_free(AnsiString);
- return NULL;
- }
-
- /* Allocate the cfs_file_t: libcfs file object */
-
- fp = cfs_alloc(sizeof(cfs_file_t) + NameLength, CFS_ALLOC_ZERO);
-
- if (NULL == fp) {
- Status = ZwClose(FileHandle);
- ASSERT(NT_SUCCESS(Status));
- *err = -ENOMEM;
- cfs_free(UnicodeString);
- cfs_free(AnsiString);
- return NULL;
- }
-
- fp->f_handle = FileHandle;
- strcpy(fp->f_name, name);
- fp->f_flags = flags;
- fp->f_mode = (mode_t)mode;
- fp->f_count = 1;
- *err = 0;
-
- /* free the memory of temporary name strings */
- cfs_free(UnicodeString);
- cfs_free(AnsiString);
-
- return fp;
-}
-
-
-/*
- * cfs_filp_close
- * To close the opened file and release the filp structure
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- *
- * Return Value:
- * ZERO: on success
- * Non-Zero: on failure
- *
- * Notes:
- * N/A
- */
-
-int cfs_filp_close(cfs_file_t *fp)
-{
- NTSTATUS Status;
-
- ASSERT(fp != NULL);
- ASSERT(fp->f_handle != NULL);
-
- /* release the file handle */
- Status = ZwClose(fp->f_handle);
- ASSERT(NT_SUCCESS(Status));
-
- /* free the file flip structure */
- cfs_free(fp);
- return 0;
-}
-
-
-/*
- * cfs_filp_read
- * To read data from the opened file
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- * buf: pointer to the buffer to contain the data
- * nbytes: size in bytes to be read from the file
- * pos: offset in file where reading starts, if pos
- * NULL, then read from current file offset
- *
- * Return Value:
- * Actual size read into the buffer in success case
- * Error code in failure case
- *
- * Notes:
- * N/A
- */
-
-int cfs_filp_read(cfs_file_t *fp, void *buf, size_t nbytes, loff_t *pos)
-{
- LARGE_INTEGER address;
- NTSTATUS Status;
- IO_STATUS_BLOCK IoStatus;
-
- int rc = 0;
-
- /* Read data from the file into the specified buffer */
-
- if (pos != NULL) {
- address.QuadPart = *pos;
- } else {
- address.QuadPart = fp->f_pos;
- }
-
- Status = ZwReadFile( fp->f_handle,
- 0,
- NULL,
- NULL,
- &IoStatus,
- buf,
- nbytes,
- &address,
- NULL );
-
- if (!NT_SUCCESS(IoStatus.Status)) {
- rc = cfs_error_code(IoStatus.Status);
- } else {
- rc = (int)IoStatus.Information;
- fp->f_pos = address.QuadPart + rc;
-
- if (pos != NULL) {
- *pos = fp->f_pos;
- }
- }
-
- return rc;
-}
-
-
-/*
- * cfs_filp_wrtie
- * To write specified data to the opened file
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- * buf: pointer to the buffer containing the data
- * nbytes: size in bytes to be written to the file
- * pos: offset in file where writing starts, if pos
- * NULL, then write to current file offset
- *
- * Return Value:
- * Actual size written into the buffer in success case
- * Error code in failure case
- *
- * Notes:
- * N/A
- */
-
-int cfs_filp_write(cfs_file_t *fp, void *buf, size_t nbytes, loff_t *pos)
-{
- LARGE_INTEGER address;
- NTSTATUS Status;
- IO_STATUS_BLOCK IoStatus;
- int rc = 0;
-
- /* Write user specified data into the file */
-
- if (pos != NULL) {
- address.QuadPart = *pos;
- } else {
- address.QuadPart = fp->f_pos;
- }
-
- Status = ZwWriteFile( fp->f_handle,
- 0,
- NULL,
- NULL,
- &IoStatus,
- buf,
- nbytes,
- &address,
- NULL );
-
- if (!NT_SUCCESS(Status)) {
- rc = cfs_error_code(Status);
- } else {
- rc = (int)IoStatus.Information;
- fp->f_pos = address.QuadPart + rc;
-
- if (pos != NULL) {
- *pos = fp->f_pos;
- }
- }
-
- return rc;
-}
-
-
-NTSTATUS
-CompletionRoutine(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PVOID Context)
-{
- /* copy the IoStatus result */
- *Irp->UserIosb = Irp->IoStatus;
-
- /* singal the event we set */
- KeSetEvent(Irp->UserEvent, 0, FALSE);
-
- /* free the Irp we allocated */
- IoFreeIrp(Irp);
-
- return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-
-/*
- * cfs_filp_fsync
- * To sync the dirty data of the file to disk
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- *
- * Return Value:
- * Zero: in success case
- * Error code: in failure case
- *
- * Notes:
- * Nt kernel doesn't export such a routine to flush a file,
- * we must allocate our own Irp and issue it to the file
- * system driver.
- */
-
-int cfs_filp_fsync(cfs_file_t *fp)
-{
-
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
-
- NTSTATUS Status;
- PIRP Irp;
- KEVENT Event;
- IO_STATUS_BLOCK IoSb;
- PIO_STACK_LOCATION IrpSp;
-
- /* get the FileObject and the DeviceObject */
-
- Status = ObReferenceObjectByHandle(
- fp->f_handle,
- FILE_WRITE_DATA,
- NULL,
- KernelMode,
- (PVOID*)&FileObject,
- NULL );
-
- if (!NT_SUCCESS(Status)) {
- return cfs_error_code(Status);
- }
-
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
- /* allocate a new Irp */
-
- Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
-
- if (!Irp) {
-
- ObDereferenceObject(FileObject);
- return -ENOMEM;
- }
-
- /* intialize the event */
- KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-
- /* setup the Irp */
- Irp->UserEvent = &Event;
- Irp->UserIosb = &IoSb;
- Irp->RequestorMode = KernelMode;
-
- Irp->Tail.Overlay.Thread = PsGetCurrentThread();
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
- /* setup the Irp stack location */
- IrpSp = IoGetNextIrpStackLocation(Irp);
-
- IrpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
- IrpSp->DeviceObject = DeviceObject;
- IrpSp->FileObject = FileObject;
-
- IoSetCompletionRoutine(Irp, CompletionRoutine, 0, TRUE, TRUE, TRUE);
-
-
- /* issue the Irp to the underlying file system driver */
- IoCallDriver(DeviceObject, Irp);
-
- /* wait until it is finished */
- KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0);
-
- /* cleanup our reference on it */
- ObDereferenceObject(FileObject);
-
- Status = IoSb.Status;
-
- return cfs_error_code(Status);
-}
-
-/*
- * cfs_get_file
- * To increase the reference of the file object
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- *
- * Return Value:
- * Zero: in success case
- * Non-Zero: in failure case
- *
- * Notes:
- * N/A
- */
-
-int cfs_get_file(cfs_file_t *fp)
-{
- InterlockedIncrement(&(fp->f_count));
- return 0;
-}
-
-
-/*
- * cfs_put_file
- * To decrease the reference of the file object
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- *
- * Return Value:
- * Zero: in success case
- * Non-Zero: in failure case
- *
- * Notes:
- * N/A
- */
-
-int cfs_put_file(cfs_file_t *fp)
-{
- if (InterlockedDecrement(&(fp->f_count)) == 0) {
- cfs_filp_close(fp);
- }
-
- return 0;
-}
-
-
-/*
- * cfs_file_count
- * To query the reference count of the file object
- *
- * Arguments:
- * fp: the pointer of the cfs_file_t strcture
- *
- * Return Value:
- * the reference count of the file object
- *
- * Notes:
- * N/A
- */
-
-int cfs_file_count(cfs_file_t *fp)
-{
- return (int)(fp->f_count);
-}