Whamcloud - gitweb
LU-1346 libcfs: cleanup libcfs atomic primitives
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-fs.c
index 128781b..4465acd 100644 (file)
@@ -1,33 +1,47 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=4:tabstop=4:
+/*
+ * GPL HEADER START
  *
- *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *   This file is part of Lustre, http://www.lustre.org.
+ * 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.
  *
- *   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.
+ * 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).
  *
- *   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
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
  *
- *   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.
+ * 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 (c) 2008, 2010, Oracle and/or its affiliates. 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.
  */
 
 # define DEBUG_SUBSYSTEM S_LNET
 
 #include <libcfs/libcfs.h>
 
-const CHAR *dos_file_prefix = "\\??\\";
+const CHAR *dos_file_prefix[] = {
+            "\\??\\", "\\DosDevices\\",
+            "\\SystemRoot\\", NULL};
 
 /*
- * cfs_filp_open
+ * filp_open
  *     To open or create a file in kernel mode
  *
  * Arguments:
@@ -37,15 +51,18 @@ const CHAR *dos_file_prefix = "\\??\\";
  *   err:   error code
  *
  * Return Value:
- *   the pointer to the cfs_file_t or NULL if it fails
+ *   the pointer to the struct file or NULL if it fails
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
-cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
+#define is_drv_letter_valid(x) (((x) >= 0 && (x) <= 9) || \
+                ( ((x)|0x20) <= 'z' && ((x)|0x20) >= 'a'))
+
+struct file *filp_open(const char *name, int flags, int mode, int *err)
 {
-    cfs_file_t *        fp = NULL;
+       struct file *fp = NULL;
 
     NTSTATUS            Status;
 
@@ -67,7 +84,6 @@ cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
     PUCHAR              AnsiString = NULL;
 
     /* Analyze the flags settings */
-
     if (cfs_is_flag_set(flags, O_WRONLY)) {
         DesiredAccess = (GENERIC_WRITE | SYNCHRONIZE);
         ShareAccess = 0;
@@ -112,31 +128,43 @@ cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
     }
 
     /* 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;
-    }
+       /* Check file & path name */
+       if (name[0] != '\\') {
+               if (NameLength < 1 || name[1] != ':' ||
+                   !is_drv_letter_valid(name[0])) {
+                       /* invalid file path name */
+                       return ERR_PTR(-EINVAL);
+               }
+               PrefixLength = (USHORT)strlen(dos_file_prefix[0]);
+       } else {
+               int i, j;
+               for (i = 0; i < 3 && dos_file_prefix[i] != NULL; i++) {
+                       j = strlen(dos_file_prefix[i]);
+                       if (NameLength > j &&
+                           _strnicmp(dos_file_prefix[i], name, j) == 0)
+                               break;
+               }
+               if (i >= 3)
+                       return ERR_PTR(-EINVAL);
+       }
+
+       AnsiString = kmalloc(sizeof(CHAR) * (NameLength + PrefixLength + 1),
+                               __GFP_ZERO);
+       if (NULL == AnsiString)
+               return ERR_PTR(-ENOMEM);
+
+       UnicodeString =
+               kmalloc(sizeof(WCHAR) * (NameLength + PrefixLength + 1),
+                         __GFP_ZERO);
+       if (NULL == UnicodeString) {
+               kfree(AnsiString);
+               return ERR_PTR(-ENOMEM);
+       }
 
     if (PrefixLength) {
-        RtlCopyMemory(&AnsiString[0], dos_file_prefix , PrefixLength);
+        RtlCopyMemory(&AnsiString[0], dos_file_prefix[0], PrefixLength);
     }
 
     RtlCopyMemory(&AnsiString[PrefixLength], name, NameLength);
@@ -153,7 +181,6 @@ cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
     RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, FALSE);
 
     /* Setup the object attributes structure for the file. */
-
     InitializeObjectAttributes(
             &ObjectAttributes,
             &UnicodeName,
@@ -163,7 +190,6 @@ cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
             NULL );
 
     /* Now to open or create the file now */
-
     Status = ZwCreateFile(
             &FileHandle,
             DesiredAccess,
@@ -177,59 +203,54 @@ cfs_file_t *cfs_filp_open(const char *name, int flags, int mode, int *err)
             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 */
+       /* Check the returned status of IoStatus... */
+       if (!NT_SUCCESS(IoStatus.Status)) {
+               kfree(UnicodeString);
+               kfree(AnsiString);
+               return ERR_PTR(cfs_error_code(IoStatus.Status));
+       }
 
-    fp = cfs_alloc(sizeof(cfs_file_t) + NameLength, CFS_ALLOC_ZERO);
+       /* Allocate the file_t: libcfs file object */
+       fp = kmalloc(sizeof(*fp) + NameLength, __GFP_ZERO);
 
-    if (NULL == fp) {
-        Status = ZwClose(FileHandle);
-        ASSERT(NT_SUCCESS(Status));
-        *err = -ENOMEM;
-        cfs_free(UnicodeString);
-        cfs_free(AnsiString);
-        return NULL;
-    }
+       if (NULL == fp) {
+               Status = ZwClose(FileHandle);
+               ASSERT(NT_SUCCESS(Status));
+               kfree(UnicodeString);
+               kfree(AnsiString);
+               return ERR_PTR(-ENOMEM);
+       }
 
     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);
+       /* free the memory of temporary name strings */
+       kfree(UnicodeString);
+       kfree(AnsiString);
 
-    return fp;
+       return fp;
 }
 
 
 /*
- * cfs_filp_close
+ * filp_close
  *     To close the opened file and release the filp structure
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file structure
  *
  * Return Value:
  *   ZERO: on success
  *   Non-Zero: on failure
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
-int cfs_filp_close(cfs_file_t *fp)
+int filp_close(file_t *fp, void *id)
 {
     NTSTATUS    Status;
 
@@ -240,18 +261,176 @@ int cfs_filp_close(cfs_file_t *fp)
     Status = ZwClose(fp->f_handle);
     ASSERT(NT_SUCCESS(Status));
 
-    /* free the file flip structure */
-    cfs_free(fp);
-    return 0;
+       /* free the file flip structure */
+       kfree(fp);
+       return 0;
+}
+
+
+NTSTATUS CompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
+{
+    /* copy the IoStatus result */
+    if (Irp->UserIosb)
+        *Irp->UserIosb = Irp->IoStatus;
+    
+    /* singal the event we set */
+    KeSetEvent((PKEVENT) Context, 0, FALSE);
+   
+    /* free the Irp we allocated */
+    IoFreeIrp(Irp);
+    
+    return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
 
+NTSTATUS cfs_nt_filp_io(HANDLE Handle, BOOLEAN Writing, PLARGE_INTEGER Offset,
+                        ULONG Length,  PUCHAR Buffer,   PULONG Bytes)
+{
+    NTSTATUS                status;
+    IO_STATUS_BLOCK         iosb;
+
+    PIRP                    irp = NULL;
+    PIO_STACK_LOCATION      irpSp = NULL;
+
+    PFILE_OBJECT            fileObject = NULL;
+    PDEVICE_OBJECT          deviceObject;
+
+    KEVENT                  event;
+
+    KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+
+    status = ObReferenceObjectByHandle( Handle,
+                                        Writing ? FILE_WRITE_DATA : 
+                                                  FILE_READ_DATA,
+                                        *IoFileObjectType,
+                                        KernelMode,
+                                        (PVOID *) &fileObject,
+                                        NULL );
+    if (!NT_SUCCESS(status)) {
+        goto errorout;
+    }
+
+    /* query the DeviceObject in case no input */
+    deviceObject = IoGetBaseFileSystemDeviceObject(fileObject);
+
+
+    /* allocate our own irp */
+    irp = IoAllocateIrp(deviceObject->StackSize, FALSE);
+    if (NULL == irp) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
+
+    irp->Tail.Overlay.OriginalFileObject = fileObject;
+    irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL;
+    irp->PendingReturned = FALSE;
+    irp->Cancel = FALSE;
+    irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
+    irp->RequestorMode = KernelMode;
+    irp->UserIosb = &iosb;
+
+    /* set up the next I/O stack location. */
+    irpSp = (PIO_STACK_LOCATION)IoGetNextIrpStackLocation(irp);
+    irpSp->MajorFunction = Writing ? IRP_MJ_WRITE : IRP_MJ_READ;
+    irpSp->FileObject = fileObject;
+    irpSp->DeviceObject = deviceObject;
+
+    if (deviceObject->Flags & DO_BUFFERED_IO) {
+        irp->AssociatedIrp.SystemBuffer = Buffer;
+        irp->UserBuffer = Buffer;
+        irp->Flags |= (ULONG) (IRP_BUFFERED_IO |
+                               IRP_INPUT_OPERATION);
+    } else if (deviceObject->Flags & DO_DIRECT_IO) {
+
+        PMDL mdl = NULL;
+
+        mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, irp);
+        if (mdl == NULL) {
+            KsPrint((0, "cfs_nt_filp_io: failed to allocate MDL for %wZ .\n",
+                        &fileObject->FileName));
+            status = STATUS_INSUFFICIENT_RESOURCES;
+            goto errorout;
+        }
+
+        __try {
+            MmProbeAndLockPages(mdl, KernelMode, Writing ? IoReadAccess : IoWriteAccess );
+        } __except(EXCEPTION_EXECUTE_HANDLER) {
+            KsPrint((0, "cfs_nt_filp_io: failed to lock buffer %p for %wZ .\n",
+                        Buffer, &fileObject->FileName));
+            IoFreeMdl(irp->MdlAddress);
+            irp->MdlAddress = NULL;
+            status = STATUS_INSUFFICIENT_RESOURCES;
+        }
+    } else {
+        irp->UserBuffer = Buffer;
+        irp->Flags = 0;
+    }
+
+    if (Writing) {
+        irp->Flags |= IRP_WRITE_OPERATION | IRP_DEFER_IO_COMPLETION;
+        irpSp->Parameters.Write.Length = Length;
+        irpSp->Parameters.Write.ByteOffset = *Offset;
+    } else {
+        irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
+        irpSp->Parameters.Read.Length = Length;
+        irpSp->Parameters.Read.ByteOffset = *Offset;
+    }
+
+    /* set the Irp completion routine */
+    IoSetCompletionRoutine( irp, CompletionRoutine, 
+                            &event, TRUE, TRUE, TRUE);
+
+
+    /* issue the irp to the lower layer device */
+    status = IoCallDriver(deviceObject, irp);
+
+    /* Irp is to be cleaned up in the compleiton routine */
+    irp = NULL;
+
+    if (status == STATUS_PENDING) {
+
+        /* we need wait until operation is completed, then we can
+           get the returned status and information length */
+
+        status = KeWaitForSingleObject(
+                    &event,
+                    Executive,
+                    KernelMode,
+                    FALSE,
+                    NULL
+                    );
+        if (NT_SUCCESS(status)) {
+            status = iosb.Status;
+        }
+    }
+
+    if (NT_SUCCESS(status)) {
+        *Bytes = (ULONG)iosb.Information;
+    } else {
+        *Bytes = 0;
+    }
+
+errorout:
+
+    if (fileObject) {
+        ObDereferenceObject(fileObject);
+    }
+
+    /* free the Irp in error case */
+    if (irp) {
+        IoFreeIrp(irp);
+    }
+
+    return status;
+}
+
 /*
- * cfs_filp_read
+ * filp_read
  *     To read data from the opened file
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file 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
@@ -264,54 +443,41 @@ int cfs_filp_close(cfs_file_t *fp)
  * Notes: 
  *   N/A
  */
-
-int cfs_filp_read(cfs_file_t *fp, void *buf, size_t nbytes, loff_t *pos)
+int filp_read(struct file *fp, void *buf, size_t nbytes, loff_t *pos)
 {
-    LARGE_INTEGER   address;
-    NTSTATUS        Status;
-    IO_STATUS_BLOCK IoStatus;
-
+    LARGE_INTEGER   offset;
+    NTSTATUS        status;
     int             rc = 0;
 
     /* Read data from the file into the specified buffer */
-
     if (pos != NULL) {
-        address.QuadPart = *pos;
+        offset.QuadPart = *pos;
     } else {
-        address.QuadPart = fp->f_pos;
+        offset.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) {
+    status = cfs_nt_filp_io(fp->f_handle, 0, &offset,
+                            nbytes, buf, &rc);
+
+    if (!NT_SUCCESS(status)) {
+        rc = cfs_error_code(status);
+    }
+
+    if (rc > 0) {
+        fp->f_pos = offset.QuadPart + rc;
+        if (pos != NULL)
             *pos = fp->f_pos;
-        }   
     }
 
-    return rc;     
+    return rc;
 }
 
-
 /*
  * cfs_filp_wrtie
  *     To write specified data to the opened file
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file 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
@@ -325,71 +491,41 @@ int cfs_filp_read(cfs_file_t *fp, void *buf, size_t nbytes, loff_t *pos)
  *   N/A
  */
 
-int cfs_filp_write(cfs_file_t *fp, void *buf, size_t nbytes, loff_t *pos)
+int filp_write(struct file *fp, void *buf, size_t nbytes, loff_t *pos)
 {
-    LARGE_INTEGER   address;
-    NTSTATUS        Status;
-    IO_STATUS_BLOCK IoStatus;
+    LARGE_INTEGER   offset;
+    NTSTATUS        status;
     int             rc = 0;
 
-    /* Write user specified data into the file */
-
+    /* Read data from the file into the specified buffer */
     if (pos != NULL) {
-        address.QuadPart = *pos;
+        offset.QuadPart = *pos;
     } else {
-        address.QuadPart = fp->f_pos;
+        offset.QuadPart = fp->f_pos;
     }
 
-    Status = ZwWriteFile( fp->f_handle,
-                         0,
-                         NULL,
-                         NULL,
-                         &IoStatus,
-                         buf,
-                         nbytes,
-                         &address,
-                         NULL );
+    status = cfs_nt_filp_io(fp->f_handle, 1, &offset,
+                            nbytes, buf, &rc);
 
-    if (!NT_SUCCESS(Status)) {
-        rc =  cfs_error_code(Status);
-    } else {
-        rc = (int)IoStatus.Information;
-        fp->f_pos = address.QuadPart + rc;
-        if (pos != NULL) {
+    if (!NT_SUCCESS(status)) {
+        rc = cfs_error_code(status);
+    }
+
+    if (rc > 0) {
+        fp->f_pos = offset.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
+ * filp_fsync
  *     To sync the dirty data of the file to disk
  *
  * Arguments:
- *   fp: the pointer of the cfs_file_t strcture
+ *   fp: the pointer of the file strcture
  *
  * Return Value:
  *   Zero:  in success case
@@ -400,10 +536,8 @@ CompletionRoutine(
  *   we must allocate our own Irp and issue it to the file
  *   system driver.
  */
-
-int cfs_filp_fsync(cfs_file_t *fp)
+int filp_fsync(struct file *fp)
 {
-
     PFILE_OBJECT            FileObject;
     PDEVICE_OBJECT          DeviceObject;
 
@@ -414,7 +548,6 @@ int cfs_filp_fsync(cfs_file_t *fp)
     PIO_STACK_LOCATION      IrpSp;
 
     /* get the FileObject and the DeviceObject */
-
     Status = ObReferenceObjectByHandle(
                 fp->f_handle,
                 FILE_WRITE_DATA,
@@ -430,11 +563,8 @@ int cfs_filp_fsync(cfs_file_t *fp)
     DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
     /* allocate a new Irp */
-
     Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
-
     if (!Irp) {
-
         ObDereferenceObject(FileObject);
         return -ENOMEM;
     }
@@ -443,7 +573,6 @@ int cfs_filp_fsync(cfs_file_t *fp)
     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
 
     /* setup the Irp */
-    Irp->UserEvent = &Event;
     Irp->UserIosb = &IoSb;
     Irp->RequestorMode = KernelMode;
 
@@ -457,7 +586,8 @@ int cfs_filp_fsync(cfs_file_t *fp)
     IrpSp->DeviceObject = DeviceObject;
     IrpSp->FileObject = FileObject;
 
-    IoSetCompletionRoutine(Irp, CompletionRoutine, 0, TRUE, TRUE, TRUE);
+    IoSetCompletionRoutine( Irp, CompletionRoutine,
+                            &Event, TRUE, TRUE, TRUE);
 
 
     /* issue the Irp to the underlying file system driver */
@@ -475,11 +605,11 @@ int cfs_filp_fsync(cfs_file_t *fp)
 }
 
 /*
- * cfs_get_file
+ * get_file
  *     To increase the reference of the file object
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file strcture
  *
  * Return Value:
  *   Zero:  in success case
@@ -489,7 +619,7 @@ int cfs_filp_fsync(cfs_file_t *fp)
  *   N/A
  */
 
-int cfs_get_file(cfs_file_t *fp)
+int get_file(struct file *fp)
 {
     InterlockedIncrement(&(fp->f_count));
     return 0;
@@ -497,36 +627,35 @@ int cfs_get_file(cfs_file_t *fp)
 
 
 /*
- * cfs_put_file
+ * fput
  *     To decrease the reference of the file object
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file strcture
  *
  * Return Value:
  *   Zero:  in success case
  *   Non-Zero: in failure case
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
-int cfs_put_file(cfs_file_t *fp)
+int fput(struct file *fp)
 {
-    if (InterlockedDecrement(&(fp->f_count)) == 0) {
-        cfs_filp_close(fp);
-    }
+       if (InterlockedDecrement(&(fp->f_count)) == 0)
+               filp_close(fp, NULL);
 
-    return 0;
+       return 0;
 }
 
 
 /*
- * cfs_file_count
+ * file_count
  *   To query the reference count of the file object
  *
  * Arguments:
- *   fp:   the pointer of the cfs_file_t strcture
+ *   fp:   the pointer of the file strcture
  *
  * Return Value:
  *   the reference count of the file object
@@ -535,7 +664,25 @@ int cfs_put_file(cfs_file_t *fp)
  *   N/A
  */
 
-int cfs_file_count(cfs_file_t *fp)
+int file_count(struct file *fp)
 {
-    return (int)(fp->f_count);
+       return (int)(fp->f_count);
+}
+
+struct dentry *dget(struct dentry *de)
+{
+       if (de) {
+               atomic_inc(&de->d_count);
+       }
+       return de;
+}
+
+void dput(struct dentry *de)
+{
+    if (!de || atomic_read(&de->d_count) == 0) {
+        return;
+    }
+    if (atomic_dec_and_test(&de->d_count)) {
+       kfree(de);
+    }
 }