[rtems commit] IMFS: Reference counting for nodes

Sebastian Huber sebh at rtems.org
Tue Mar 13 11:31:31 UTC 2012


Module:    rtems
Branch:    master
Commit:    1bdff036acddbbc63aa849741abba6581549f7b6
Changeset: http://git.rtems.org/rtems/commit/?id=1bdff036acddbbc63aa849741abba6581549f7b6

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Feb 23 17:57:27 2012 +0100

IMFS: Reference counting for nodes

The introduction of reference counting of nodes avoids the removal of
open nodes and potential usage of freed memory.

---

 cpukit/libfs/src/imfs/deviceio.c                |    2 -
 cpukit/libfs/src/imfs/fifoimfs_init.c           |    4 +-
 cpukit/libfs/src/imfs/imfs.h                    |   45 +++++++++--------------
 cpukit/libfs/src/imfs/imfs_creat.c              |    1 +
 cpukit/libfs/src/imfs/imfs_directory.c          |   24 ------------
 cpukit/libfs/src/imfs/imfs_eval.c               |    2 +
 cpukit/libfs/src/imfs/imfs_fifo.c               |    3 --
 cpukit/libfs/src/imfs/imfs_fsunmount.c          |    5 ++-
 cpukit/libfs/src/imfs/imfs_handlers_directory.c |    2 +-
 cpukit/libfs/src/imfs/imfs_handlers_memfile.c   |    2 +-
 cpukit/libfs/src/imfs/imfs_init.c               |    4 +-
 cpukit/libfs/src/imfs/imfs_initsupp.c           |   38 +++++++++++++++++++
 cpukit/libfs/src/imfs/imfs_link.c               |   12 ++++--
 cpukit/libfs/src/imfs/imfs_rmnod.c              |   40 +++-----------------
 cpukit/libfs/src/imfs/memfile.c                 |   22 -----------
 cpukit/libfs/src/imfs/miniimfs_init.c           |    4 +-
 16 files changed, 84 insertions(+), 126 deletions(-)

diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
index 69f409e..c4e7a92 100644
--- a/cpukit/libfs/src/imfs/deviceio.c
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -80,8 +80,6 @@ int device_close(
     (void *) &args
   );
 
-  IMFS_check_node_remove( the_jnode );
-
   return rtems_deviceio_errno( status );
 }
 
diff --git a/cpukit/libfs/src/imfs/fifoimfs_init.c b/cpukit/libfs/src/imfs/fifoimfs_init.c
index d2af7af..966e9e1 100644
--- a/cpukit/libfs/src/imfs/fifoimfs_init.c
+++ b/cpukit/libfs/src/imfs/fifoimfs_init.c
@@ -36,8 +36,8 @@ const rtems_filesystem_operations_table fifoIMFS_ops = {
   .rmnod_h = IMFS_rmnod,
   .fchmod_h = IMFS_fchmod,
   .chown_h = IMFS_chown,
-  .clonenod_h = rtems_filesystem_default_clonenode,
-  .freenod_h = rtems_filesystem_default_freenode,
+  .clonenod_h = IMFS_node_clone,
+  .freenod_h = IMFS_node_free,
   .mount_h = IMFS_mount,
   .fsmount_me_h = fifoIMFS_initialize,
   .unmount_h = IMFS_unmount,
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index c2d95f0..e9be053 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -166,6 +166,7 @@ struct IMFS_jnode_tt {
   IMFS_jnode_t       *Parent;                /* Parent node */
   char                name[IMFS_NAME_MAX+1]; /* "basename" */
   mode_t              st_mode;               /* File mode */
+  unsigned short      reference_count;
   nlink_t             st_nlink;              /* Link count */
   ino_t               st_ino;                /* inode */
 
@@ -274,6 +275,11 @@ extern void IMFS_dump( void );
  */
 extern int IMFS_memfile_maximum_size( void );
 
+extern void IMFS_node_destroy( IMFS_jnode_t *node );
+
+extern int IMFS_node_clone( rtems_filesystem_location_info_t *loc );
+
+extern void IMFS_node_free( const rtems_filesystem_location_info_t *loc );
 
 extern rtems_filesystem_node_types_t IMFS_node_type(
   const rtems_filesystem_location_info_t *loc
@@ -353,10 +359,6 @@ extern int imfs_dir_open(
   mode_t         mode             /* IN  */
 );
 
-extern int imfs_dir_close(
-  rtems_libio_t *iop             /* IN  */
-);
-
 extern ssize_t imfs_dir_read(
   rtems_libio_t *iop,              /* IN  */
   void          *buffer,           /* IN  */
@@ -376,10 +378,6 @@ extern int memfile_open(
   mode_t         mode             /* IN  */
 );
 
-extern int memfile_close(
-  rtems_libio_t *iop             /* IN  */
-);
-
 extern ssize_t memfile_read(
   rtems_libio_t *iop,             /* IN  */
   void          *buffer,          /* IN  */
@@ -476,19 +474,22 @@ extern int IMFS_rename(
   size_t namelen
 );
 
-extern void IMFS_create_orphan(
-  IMFS_jnode_t *jnode
-);
-
-extern void IMFS_check_node_remove(
-  IMFS_jnode_t *jnode
-);
-
 extern int IMFS_rmnod(
   const rtems_filesystem_location_info_t *parentloc,
   const rtems_filesystem_location_info_t *loc
 );
 
+/*
+ *  Turn on IMFS assertions when RTEMS_DEBUG is defined.
+ */
+#ifdef RTEMS_DEBUG
+  #include <assert.h>
+
+  #define IMFS_assert(_x) assert(_x)
+#else
+  #define IMFS_assert(_x)
+#endif
+
 static inline void IMFS_add_to_directory(
   IMFS_jnode_t *dir,
   IMFS_jnode_t *node
@@ -500,21 +501,11 @@ static inline void IMFS_add_to_directory(
 
 static inline void IMFS_remove_from_directory( IMFS_jnode_t *node )
 {
+  IMFS_assert( node->Parent != NULL );
   node->Parent = NULL;
   rtems_chain_extract_unprotected( &node->Node );
 }
 
-/*
- *  Turn on IMFS assertions when RTEMS_DEBUG is defined.
- */
-#ifdef RTEMS_DEBUG
-  #include <assert.h>
-
-  #define IMFS_assert(_x) assert(_x)
-#else
-  #define IMFS_assert(_x)
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
index caf82be..2fe3c7d 100644
--- a/cpukit/libfs/src/imfs/imfs_creat.c
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -123,6 +123,7 @@ IMFS_jnode_t *IMFS_allocate_node(
   /*
    *  Fill in the basic information
    */
+  node->reference_count = 1;
   node->st_nlink = 1;
   node->type     = type;
   memcpy( node->name, name, namelen );
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
index fc687e4..3bbbec2 100644
--- a/cpukit/libfs/src/imfs/imfs_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -127,30 +127,6 @@ ssize_t imfs_dir_read(
    return bytes_transferred;
 }
 
-
-
-/*
- *  imfs_dir_close
- *
- *  This routine will be called by the generic close routine to cleanup any
- *  resources that have been allocated for the management of the file
- */
-
-int imfs_dir_close(
-  rtems_libio_t  *iop
-)
-{
-  /*
-   *  The generic close routine handles the deallocation of the file control
-   *  and associated memory. At present the imfs_dir_close simply
-   *  returns a successful completion status.
-   */
-
-  return 0;
-}
-
-
-
 /*
  *  imfs_dir_lseek
  *
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
index 33e7e36..5b1ccfb 100644
--- a/cpukit/libfs/src/imfs/imfs_eval.c
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -154,6 +154,8 @@ static rtems_filesystem_eval_path_generic_status IMFS_eval_token(
           IMFS_is_mount_point( entry );
 
         if ( fs_root_ptr == NULL ) {
+          --dir->reference_count;
+          ++entry->reference_count;
           currentloc->node_access = entry;
           IMFS_Set_handlers( currentloc );
 
diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c
index 9852750..dc62362 100644
--- a/cpukit/libfs/src/imfs/imfs_fifo.c
+++ b/cpukit/libfs/src/imfs/imfs_fifo.c
@@ -50,9 +50,6 @@ static int IMFS_fifo_close(
 
   pipe_release(&JNODE2PIPE(jnode), iop);
 
-  iop->flags &= ~LIBIO_FLAGS_OPEN;
-  IMFS_check_node_remove(jnode);
-
   IMFS_FIFO_RETURN(err);
 }
 
diff --git a/cpukit/libfs/src/imfs/imfs_fsunmount.c b/cpukit/libfs/src/imfs/imfs_fsunmount.c
index 49ade1b..6f9388e 100644
--- a/cpukit/libfs/src/imfs/imfs_fsunmount.c
+++ b/cpukit/libfs/src/imfs/imfs_fsunmount.c
@@ -63,8 +63,9 @@ void IMFS_fsunmount(
 
      if ( jnode->type != IMFS_DIRECTORY || jnode_has_no_children( jnode ) ) {
         result = IMFS_rmnod( NULL, &loc );
-        if (result != 0)
-	  rtems_fatal_error_occurred(0xdeadbeef);
+        if ( result != 0 )
+	  rtems_fatal_error_occurred( 0xdeadbeef );
+        IMFS_node_destroy( jnode );
         jnode = next;
      }
      if ( jnode != NULL ) {
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
index dfda4fc..b18f2ab 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
@@ -23,7 +23,7 @@
 
 const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
   imfs_dir_open,
-  imfs_dir_close,
+  rtems_filesystem_default_close,
   imfs_dir_read,
   rtems_filesystem_default_write,
   rtems_filesystem_default_ioctl,
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
index e179eab..10cba94 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
@@ -23,7 +23,7 @@
 
 const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
   memfile_open,
-  memfile_close,
+  rtems_filesystem_default_close,
   memfile_read,
   memfile_write,
   memfile_ioctl,
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
index 2a7d890..8b4db45 100644
--- a/cpukit/libfs/src/imfs/imfs_init.c
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -34,8 +34,8 @@ const rtems_filesystem_operations_table IMFS_ops = {
   .rmnod_h = IMFS_rmnod,
   .fchmod_h = IMFS_fchmod,
   .chown_h = IMFS_chown,
-  .clonenod_h = rtems_filesystem_default_clonenode,
-  .freenod_h = rtems_filesystem_default_freenode,
+  .clonenod_h = IMFS_node_clone,
+  .freenod_h = IMFS_node_free,
   .mount_h = IMFS_mount,
   .fsmount_me_h = IMFS_initialize,
   .unmount_h = IMFS_unmount,
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
index 61ad6a7..042995b 100644
--- a/cpukit/libfs/src/imfs/imfs_initsupp.c
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -106,3 +106,41 @@ int IMFS_initialize_support(
 
   return 0;
 }
+
+int IMFS_node_clone( rtems_filesystem_location_info_t *loc )
+{
+  IMFS_jnode_t *node = loc->node_access;
+
+  ++node->reference_count;
+
+  return 0;
+}
+
+void IMFS_node_destroy( IMFS_jnode_t *node )
+{
+  IMFS_assert( node->reference_count == 0 );
+
+  switch ( node->type ) {
+    case IMFS_MEMORY_FILE:
+      IMFS_memfile_remove( node );
+      break;
+    case IMFS_SYM_LINK:
+      free( node->info.sym_link.name );
+      break;
+    default:
+      break;
+  }
+
+  free( node );
+}
+
+void IMFS_node_free( const rtems_filesystem_location_info_t *loc )
+{
+  IMFS_jnode_t *node = loc->node_access;
+
+  if ( node->reference_count == 1 ) {
+    IMFS_node_destroy( node );
+  } else {
+    --node->reference_count;
+  }
+}
diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c
index 130c529..2684dbe 100644
--- a/cpukit/libfs/src/imfs/imfs_link.c
+++ b/cpukit/libfs/src/imfs/imfs_link.c
@@ -30,12 +30,15 @@ int IMFS_link(
 {
   IMFS_types_union   info;
   IMFS_jnode_t      *new_node;
+  IMFS_jnode_t      *target;
+
+  target = targetloc->node_access;
+  info.hard_link.link_node = target;
 
   /*
    *  Verify this node can be linked to.
    */
-  info.hard_link.link_node = targetloc->node_access;
-  if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+  if ( target->st_nlink >= LINK_MAX )
     rtems_set_errno_and_return_minus_one( EMLINK );
 
   /*
@@ -56,8 +59,9 @@ int IMFS_link(
   /*
    * Increment the link count of the node being pointed to.
    */
-  info.hard_link.link_node->st_nlink++;
-  IMFS_update_ctime( info.hard_link.link_node );
+  target->reference_count++;
+  target->st_nlink++;
+  IMFS_update_ctime( target );
 
   return 0;
 }
diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c
index ae4d8fb..748a6f7 100644
--- a/cpukit/libfs/src/imfs/imfs_rmnod.c
+++ b/cpukit/libfs/src/imfs/imfs_rmnod.c
@@ -23,44 +23,13 @@
 
 #include "imfs.h"
 
-#include <stdlib.h>
-
-void IMFS_create_orphan( IMFS_jnode_t *jnode )
-{
-  if ( jnode->Parent != NULL ) {
-    IMFS_remove_from_directory( jnode );
-  }
-
-  --jnode->st_nlink;
-
-  IMFS_update_ctime( jnode );
-}
-
-void IMFS_check_node_remove( IMFS_jnode_t *jnode )
-{
-  if ( jnode->st_nlink < 1 ) {
-    switch ( jnode->type ) {
-      case IMFS_MEMORY_FILE:
-        IMFS_memfile_remove( jnode );
-        break;
-      case IMFS_SYM_LINK:
-        free( jnode->info.sym_link.name );
-        break;
-      default:
-        break;
-    }
-
-    free( jnode );
-  }
-}
-
 static int IMFS_rmnod_directory(
   const rtems_filesystem_location_info_t *parentloc,
   const rtems_filesystem_location_info_t *loc
 )
 {
-  IMFS_jnode_t *node = loc->node_access;
   int rv = 0;
+  IMFS_jnode_t *node = loc->node_access;
 
   if ( !rtems_chain_is_empty( &node->info.directory.Entries ) ) {
     errno = ENOTEMPTY;
@@ -120,8 +89,11 @@ int IMFS_rmnod(
   }
 
   if ( rv == 0 ) {
-    IMFS_create_orphan( node );
-    IMFS_check_node_remove( node );
+    --node->reference_count;
+    --node->st_nlink;
+    if ( node->Parent != NULL ) {
+      IMFS_remove_from_directory( node );
+    }
   }
 
   return rv;
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index 65810c0..fed8914 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -114,28 +114,6 @@ int memfile_open(
 }
 
 /*
- *  memfile_close
- *
- *  This routine processes the close() system call.  Note that there is
- *  nothing to flush or memory to free at this point.
- */
-int memfile_close(
-  rtems_libio_t *iop
-)
-{
-  IMFS_jnode_t   *the_jnode;
-
-  the_jnode = iop->pathinfo.node_access;
-
-  if (iop->flags & LIBIO_FLAGS_APPEND)
-    iop->offset = the_jnode->info.file.size;
-
-  IMFS_check_node_remove( the_jnode );
-
-  return 0;
-}
-
-/*
  *  memfile_read
  *
  *  This routine processes the read() system call.
diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c
index a4db968..af791f5 100644
--- a/cpukit/libfs/src/imfs/miniimfs_init.c
+++ b/cpukit/libfs/src/imfs/miniimfs_init.c
@@ -34,8 +34,8 @@ static const rtems_filesystem_operations_table miniIMFS_ops = {
   .rmnod_h = IMFS_rmnod,
   .fchmod_h = rtems_filesystem_default_fchmod,
   .chown_h = rtems_filesystem_default_chown,
-  .clonenod_h = rtems_filesystem_default_clonenode,
-  .freenod_h = rtems_filesystem_default_freenode,
+  .clonenod_h = IMFS_node_clone,
+  .freenod_h = IMFS_node_free,
   .mount_h = IMFS_mount,
   .fsmount_me_h = miniIMFS_initialize,
   .unmount_h = rtems_filesystem_default_unmount,




More information about the vc mailing list