[rtems commit] IMFS: Add and use node control

Joel Sherrill joel at rtems.org
Thu Mar 29 14:14:29 UTC 2012


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Feb 24 17:08:06 2012 +0100

IMFS: Add and use node control

Add and use structure IMFS_node_control with support functions.  This
helps to make high level functions independent of the node type and
reduces the number of branches in the code.

---

 cpukit/libfs/src/imfs/fifoimfs_init.c           |   14 ++-
 cpukit/libfs/src/imfs/imfs.h                    |  138 +++++++++++++++++------
 cpukit/libfs/src/imfs/imfs_creat.c              |  138 +++++++----------------
 cpukit/libfs/src/imfs/imfs_eval.c               |   32 -----
 cpukit/libfs/src/imfs/imfs_fifo.c               |   14 ++-
 cpukit/libfs/src/imfs/imfs_handlers_device.c    |   25 ++++-
 cpukit/libfs/src/imfs/imfs_handlers_directory.c |   45 +++++++-
 cpukit/libfs/src/imfs/imfs_handlers_link.c      |   69 +++++++++++-
 cpukit/libfs/src/imfs/imfs_handlers_memfile.c   |   22 +++-
 cpukit/libfs/src/imfs/imfs_init.c               |   14 ++-
 cpukit/libfs/src/imfs/imfs_initsupp.c           |  136 +++++++++++++----------
 cpukit/libfs/src/imfs/imfs_rmnod.c              |   65 +----------
 cpukit/libfs/src/imfs/memfile.c                 |    6 +-
 cpukit/libfs/src/imfs/miniimfs_init.c           |   16 ++-
 14 files changed, 419 insertions(+), 315 deletions(-)

diff --git a/cpukit/libfs/src/imfs/fifoimfs_init.c b/cpukit/libfs/src/imfs/fifoimfs_init.c
index 966e9e1..8ebdca3 100644
--- a/cpukit/libfs/src/imfs/fifoimfs_init.c
+++ b/cpukit/libfs/src/imfs/fifoimfs_init.c
@@ -49,6 +49,17 @@ const rtems_filesystem_operations_table fifoIMFS_ops = {
   .statvfs_h = rtems_filesystem_default_statvfs
 };
 
+static const IMFS_node_control *const
+  IMFS_fifo_node_controls [IMFS_TYPE_COUNT] = {
+  [IMFS_DIRECTORY] = &IMFS_node_control_directory,
+  [IMFS_DEVICE] = &IMFS_node_control_device,
+  [IMFS_HARD_LINK] = &IMFS_node_control_hard_link,
+  [IMFS_SYM_LINK] = &IMFS_node_control_sym_link,
+  [IMFS_MEMORY_FILE] = &IMFS_node_control_memfile,
+  [IMFS_LINEAR_FILE] = &IMFS_node_control_linfile,
+  [IMFS_FIFO] = &IMFS_node_control_fifo
+};
+
 int fifoIMFS_initialize(
   rtems_filesystem_mount_table_entry_t *mt_entry,
   const void *data
@@ -57,7 +68,6 @@ int fifoIMFS_initialize(
   return IMFS_initialize_support(
     mt_entry,
     &fifoIMFS_ops,
-    &IMFS_link_handlers,
-    &IMFS_fifo_handlers
+    IMFS_fifo_node_controls
   );
 }
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
index 7c926a8..ae247c5 100644
--- a/cpukit/libfs/src/imfs/imfs.h
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -132,9 +132,12 @@ typedef enum {
   IMFS_SYM_LINK =  RTEMS_FILESYSTEM_SYM_LINK,
   IMFS_MEMORY_FILE = RTEMS_FILESYSTEM_MEMORY_FILE,
   IMFS_LINEAR_FILE,
-  IMFS_FIFO
+  IMFS_FIFO,
+  IMFS_INVALID_NODE
 } IMFS_jnode_types_t;
 
+#define IMFS_TYPE_COUNT (IMFS_FIFO + 1)
+
 typedef union {
   IMFS_directory_t   directory;
   IMFS_device_t      device;
@@ -145,6 +148,38 @@ typedef union {
   IMFS_fifo_t        fifo;
 } IMFS_types_union;
 
+typedef IMFS_jnode_t *(*IMFS_node_control_initialize)(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+);
+
+IMFS_jnode_t *IMFS_node_initialize_default(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+);
+
+typedef IMFS_jnode_t *(*IMFS_node_control_remove)(
+  IMFS_jnode_t *node,
+  const IMFS_jnode_t *root_node
+);
+
+IMFS_jnode_t *IMFS_node_remove_default(
+  IMFS_jnode_t *node,
+  const IMFS_jnode_t *root_node
+);
+
+typedef IMFS_jnode_t *(*IMFS_node_control_destroy)( IMFS_jnode_t *node );
+
+IMFS_jnode_t *IMFS_node_destroy_default( IMFS_jnode_t *node );
+
+typedef struct {
+  IMFS_jnode_types_t imfs_type;
+  const rtems_filesystem_file_handlers_r *handlers;
+  IMFS_node_control_initialize node_initialize;
+  IMFS_node_control_remove node_remove;
+  IMFS_node_control_destroy node_destroy;
+} IMFS_node_control;
+
 /*
  * Major device number for the IMFS. This is not a real device number because
  * the IMFS is just a file system and does not have a driver.
@@ -176,7 +211,7 @@ struct IMFS_jnode_tt {
   time_t              stat_atime;            /* Time of last access */
   time_t              stat_mtime;            /* Time of last modification */
   time_t              stat_ctime;            /* Time of last status change */
-  IMFS_jnode_types_t  type;                  /* Type of this entry */
+  const IMFS_node_control *control;
   IMFS_types_union    info;
 };
 
@@ -210,25 +245,28 @@ struct IMFS_jnode_tt {
   } while (0)
 
 typedef struct {
-  int                                     instance;
-  ino_t                                   ino_count;
-  const rtems_filesystem_file_handlers_r *memfile_handlers;
-  const rtems_filesystem_file_handlers_r *directory_handlers;
-  const rtems_filesystem_file_handlers_r *link_handlers;
-  const rtems_filesystem_file_handlers_r *fifo_handlers;
+  int instance;
+  ino_t ino_count;
+  const IMFS_node_control *node_controls [IMFS_TYPE_COUNT];
 } IMFS_fs_info_t;
 
 /*
  *  Shared Data
  */
 
-extern const rtems_filesystem_file_handlers_r       IMFS_directory_handlers;
-extern const rtems_filesystem_file_handlers_r       IMFS_device_handlers;
-extern const rtems_filesystem_file_handlers_r       IMFS_link_handlers;
-extern const rtems_filesystem_file_handlers_r       IMFS_memfile_handlers;
-extern const rtems_filesystem_file_handlers_r       IMFS_fifo_handlers;
-extern const rtems_filesystem_operations_table      IMFS_ops;
-extern const rtems_filesystem_operations_table      fifoIMFS_ops;
+extern const IMFS_node_control IMFS_node_control_directory;
+extern const IMFS_node_control IMFS_node_control_device;
+extern const IMFS_node_control IMFS_node_control_hard_link;
+extern const IMFS_node_control IMFS_node_control_sym_link;
+extern const IMFS_node_control IMFS_node_control_memfile;
+extern const IMFS_node_control IMFS_node_control_linfile;
+extern const IMFS_node_control IMFS_node_control_fifo;
+extern const IMFS_node_control IMFS_node_control_default;
+
+extern const rtems_filesystem_operations_table miniIMFS_ops;
+extern const rtems_filesystem_operations_table IMFS_ops;
+extern const rtems_filesystem_operations_table fifoIMFS_ops;
+
 extern const rtems_filesystem_limits_and_options_t  IMFS_LIMITS_AND_OPTIONS;
 
 /*
@@ -251,10 +289,9 @@ extern int miniIMFS_initialize(
 );
 
 extern int IMFS_initialize_support(
-   rtems_filesystem_mount_table_entry_t       *mt_entry,
-   const rtems_filesystem_operations_table    *op_table,
-   const rtems_filesystem_file_handlers_r     *link_handlers,
-   const rtems_filesystem_file_handlers_r     *fifo_handlers
+  rtems_filesystem_mount_table_entry_t *mt_entry,
+  const rtems_filesystem_operations_table *op_table,
+  const IMFS_node_control *const node_controls [IMFS_TYPE_COUNT]
 );
 
 extern void IMFS_fsunmount(
@@ -290,8 +327,6 @@ extern int IMFS_stat(
   struct stat *buf
 );
 
-extern void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc );
-
 extern void IMFS_eval_path(
   rtems_filesystem_eval_path_context_t *ctx
 );
@@ -318,21 +353,21 @@ extern int IMFS_mknod(
 );
 
 extern IMFS_jnode_t *IMFS_allocate_node(
-  IMFS_jnode_types_t                type,         /* IN  */
-  const char                       *name,         /* IN  */
-  size_t                            namelen,      /* IN  */
-  mode_t                            mode          /* IN  */
+  IMFS_fs_info_t *fs_info,
+  const IMFS_node_control *node_control,
+  const char *name,
+  size_t namelen,
+  mode_t mode,
+  const IMFS_types_union *info
 );
 
-extern IMFS_jnode_t *IMFS_create_root_node(void);
-
-extern IMFS_jnode_t *IMFS_create_node(
-  const rtems_filesystem_location_info_t *pathloc, /* IN  */
-  IMFS_jnode_types_t                      type,    /* IN  */
-  const char                             *name,    /* IN  */
-  size_t                                  namelen, /* IN  */
-  mode_t                                  mode,    /* IN  */
-  const IMFS_types_union                 *info     /* IN  */
+extern IMFS_jnode_t *IMFS_create_node_with_control(
+  const rtems_filesystem_location_info_t *parentloc,
+  const IMFS_node_control *node_control,
+  const char *name,
+  size_t namelen,
+  mode_t mode,
+  const IMFS_types_union *info
 );
 
 extern int IMFS_mount(
@@ -343,7 +378,7 @@ extern int IMFS_unmount(
   rtems_filesystem_mount_table_entry_t *mt_entry  /* IN */
 );
 
-extern int IMFS_memfile_remove(
+extern IMFS_jnode_t *IMFS_memfile_remove(
  IMFS_jnode_t  *the_jnode         /* IN/OUT */
 );
 
@@ -483,6 +518,13 @@ extern int IMFS_rmnod(
   #define IMFS_assert(_x)
 #endif
 
+static inline void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc )
+{
+  IMFS_jnode_t *node = (IMFS_jnode_t *) loc->node_access;
+
+  loc->handlers = node->control->handlers;
+}
+
 static inline void IMFS_add_to_directory(
   IMFS_jnode_t *dir,
   IMFS_jnode_t *node
@@ -501,12 +543,34 @@ static inline void IMFS_remove_from_directory( IMFS_jnode_t *node )
 
 static inline IMFS_jnode_types_t IMFS_type( const IMFS_jnode_t *node )
 {
-  return node->type;
+  return node->control->imfs_type;
 }
 
 static inline bool IMFS_is_directory( const IMFS_jnode_t *node )
 {
-  return node->type == IMFS_DIRECTORY;
+  return node->control->imfs_type == IMFS_DIRECTORY;
+}
+
+static inline IMFS_jnode_t *IMFS_create_node(
+  const rtems_filesystem_location_info_t *parentloc,
+  IMFS_jnode_types_t type,
+  const char *name,
+  size_t namelen,
+  mode_t mode,
+  const IMFS_types_union *info
+)
+{
+  const IMFS_fs_info_t *fs_info =
+    (const IMFS_fs_info_t *) parentloc->mt_entry->fs_info;
+
+  return IMFS_create_node_with_control(
+    parentloc,
+    fs_info->node_controls [type],
+    name,
+    namelen,
+    mode,
+    info
+  );
 }
 
 #ifdef __cplusplus
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
index 2fe3c7d..103320f 100644
--- a/cpukit/libfs/src/imfs/imfs_creat.c
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -22,83 +22,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-static void IMFS_initialize_directory( IMFS_jnode_t *dir )
-{
-  rtems_chain_initialize_empty( &dir->info.directory.Entries );
-}
-
-/*
- *  Create an IMFS filesystem node of an arbitrary type that is NOT
- *  the root directory node.
- */
-IMFS_jnode_t *IMFS_create_node(
-  const rtems_filesystem_location_info_t *parent_loc,
-  IMFS_jnode_types_t                      type,
-  const char                             *name,
-  size_t                                  namelen,
-  mode_t                                  mode,
-  const IMFS_types_union                 *info
-)
-{
-  IMFS_jnode_t        *node;
-  IMFS_jnode_t        *parent;
-  IMFS_fs_info_t      *fs_info;
-
-  parent = parent_loc->node_access;
-  fs_info = parent_loc->mt_entry->fs_info;
-
-  /*
-   *  Allocate filesystem node and fill in basic information
-   */
-  node  = IMFS_allocate_node( type, name, namelen, mode );
-  if ( !node )
-    return NULL;
-
-  /*
-   *  Set the type specific information
-   */
-  if ( type == IMFS_DIRECTORY ) {
-    IMFS_initialize_directory( node );
-  } else if ( type == IMFS_HARD_LINK ) {
-    node->info.hard_link.link_node = info->hard_link.link_node;
-  } else if ( type == IMFS_SYM_LINK ) {
-    node->info.sym_link.name = info->sym_link.name;
-  } else if ( type == IMFS_DEVICE ) {
-    node->info.device.major = info->device.major;
-    node->info.device.minor = info->device.minor;
-  } else if ( type == IMFS_LINEAR_FILE ) {
-    node->info.linearfile.size      = 0;
-    node->info.linearfile.direct    = 0;
-  } else if ( type == IMFS_MEMORY_FILE ) {
-      node->info.file.size            = 0;
-      node->info.file.indirect        = 0;
-      node->info.file.doubly_indirect = 0;
-      node->info.file.triply_indirect = 0;
-  } else if ( type == IMFS_FIFO ) {
-    node->info.fifo.pipe = NULL;
-  } else {
-    IMFS_assert(0);
-  }
-
-  /*
-   *  This node MUST have a parent, so put it in that directory list.
-   */
-  IMFS_assert( parent != NULL );
-  IMFS_add_to_directory( parent, node );
-
-  node->st_ino = ++fs_info->ino_count;
-
-  return node;
-}
-
-/*
- *  Allocate filesystem node and fill in basic information
- */
 IMFS_jnode_t *IMFS_allocate_node(
-  IMFS_jnode_types_t                type,
-  const char                       *name,
-  size_t                            namelen,
-  mode_t                            mode
+  IMFS_fs_info_t *fs_info,
+  const IMFS_node_control *node_control,
+  const char *name,
+  size_t namelen,
+  mode_t mode,
+  const IMFS_types_union *info
 )
 {
   IMFS_jnode_t        *node;
@@ -110,6 +40,8 @@ IMFS_jnode_t *IMFS_allocate_node(
     return NULL;
   }
 
+  gettimeofday( &tv, 0 );
+
   /*
    *  Allocate an IMFS jnode
    */
@@ -125,9 +57,9 @@ IMFS_jnode_t *IMFS_allocate_node(
    */
   node->reference_count = 1;
   node->st_nlink = 1;
-  node->type     = type;
   memcpy( node->name, name, namelen );
   node->name [namelen] = '\0';
+  node->control = node_control;
 
   /*
    *  Fill in the mode and permission information for the jnode structure.
@@ -144,32 +76,48 @@ IMFS_jnode_t *IMFS_allocate_node(
   /*
    *  Now set all the times.
    */
-  gettimeofday( &tv, 0 );
 
   node->stat_atime  = (time_t) tv.tv_sec;
   node->stat_mtime  = (time_t) tv.tv_sec;
   node->stat_ctime  = (time_t) tv.tv_sec;
+  node->st_ino = ++fs_info->ino_count;
 
-  return node;
+  return (*node->control->node_initialize)( node, info );
 }
 
-IMFS_jnode_t *IMFS_create_root_node(void)
+/*
+ *  Create an IMFS filesystem node of an arbitrary type that is NOT
+ *  the root directory node.
+ */
+IMFS_jnode_t *IMFS_create_node_with_control(
+  const rtems_filesystem_location_info_t *parentloc,
+  const IMFS_node_control *node_control,
+  const char *name,
+  size_t namelen,
+  mode_t mode,
+  const IMFS_types_union *info
+)
 {
-  IMFS_jnode_t        *node;
-
-  /*
-   *  Allocate filesystem node and fill in basic information
-   */
-  node = IMFS_allocate_node( IMFS_DIRECTORY, "", 0, (S_IFDIR | 0755) );
-  if ( !node )
-    return NULL;
-
-  /*
-   *  Set the type specific information
-   *
-   *  NOTE: Root node is always a directory.
-   */
-  IMFS_initialize_directory( node );
+  IMFS_fs_info_t *fs_info = parentloc->mt_entry->fs_info;
+  IMFS_jnode_t *node = IMFS_allocate_node(
+    fs_info,
+    node_control,
+    name,
+    namelen,
+    mode,
+    info
+  );
+
+  if ( node != NULL ) {
+    IMFS_jnode_t *parent = parentloc->node_access;
+
+    /*
+     *  This node MUST have a parent, so put it in that directory list.
+     */
+    IMFS_assert( parent != NULL );
+    IMFS_add_to_directory( parent, node );
+  }
 
   return node;
 }
+
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
index a65569a..4fcfd67 100644
--- a/cpukit/libfs/src/imfs/imfs_eval.c
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -18,38 +18,6 @@
 
 #include "imfs.h"
 
-void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc )
-{
-  IMFS_jnode_t *node = loc->node_access;
-  IMFS_fs_info_t *fs_info = loc->mt_entry->fs_info;
-  const rtems_filesystem_file_handlers_r *handlers;
-
-  switch ( node->type ) {
-    case IMFS_DIRECTORY:
-      handlers = &IMFS_directory_handlers;
-      break;
-    case IMFS_DEVICE:
-      handlers = &IMFS_device_handlers;
-      break;
-    case IMFS_HARD_LINK:
-    case IMFS_SYM_LINK:
-      handlers = fs_info->link_handlers;
-      break;
-    case IMFS_MEMORY_FILE:
-    case IMFS_LINEAR_FILE:
-      handlers = &IMFS_memfile_handlers;
-      break;
-    case IMFS_FIFO:
-      handlers = fs_info->fifo_handlers;
-      break;
-    default:
-      IMFS_assert( 0 );
-      break;
-  }
-
-  loc->handlers = handlers;
-}
-
 static bool IMFS_eval_is_directory(
   rtems_filesystem_eval_path_context_t *ctx,
   void *arg
diff --git a/cpukit/libfs/src/imfs/imfs_fifo.c b/cpukit/libfs/src/imfs/imfs_fifo.c
index dc62362..6160256 100644
--- a/cpukit/libfs/src/imfs/imfs_fifo.c
+++ b/cpukit/libfs/src/imfs/imfs_fifo.c
@@ -119,11 +119,7 @@ static off_t IMFS_fifo_lseek(
   IMFS_FIFO_RETURN(err);
 }
 
-/*
- *  Handler table for IMFS FIFO nodes
- */
-
-const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
+static const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
   IMFS_fifo_open,
   IMFS_fifo_close,
   IMFS_fifo_read,
@@ -136,3 +132,11 @@ const rtems_filesystem_file_handlers_r IMFS_fifo_handlers = {
   rtems_filesystem_default_fsync_or_fdatasync,
   rtems_filesystem_default_fcntl
 };
+
+const IMFS_node_control IMFS_node_control_fifo = {
+  .imfs_type = IMFS_FIFO,
+  .handlers = &IMFS_fifo_handlers,
+  .node_initialize = IMFS_node_initialize_default,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_node_destroy_default
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c
index df9ea1a..625bc39 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_device.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c
@@ -17,11 +17,7 @@
 
 #include "imfs.h"
 
-/*
- *  Handler table for IMFS device nodes
- */
-
-const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
+static const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
   device_open,
   device_close,
   device_read,
@@ -34,3 +30,22 @@ const rtems_filesystem_file_handlers_r IMFS_device_handlers = {
   rtems_filesystem_default_fsync_or_fdatasync,
   rtems_filesystem_default_fcntl
 };
+
+static IMFS_jnode_t *IMFS_node_initialize_device(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+)
+{
+  node->info.device.major = info->device.major;
+  node->info.device.minor = info->device.minor;
+
+  return node;
+}
+
+const IMFS_node_control IMFS_node_control_device = {
+  .imfs_type = IMFS_DEVICE,
+  .handlers = &IMFS_device_handlers,
+  .node_initialize = IMFS_node_initialize_device,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_node_destroy_default
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
index 842f098..56b1461 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_directory.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
@@ -17,11 +17,7 @@
 
 #include "imfs.h"
 
-/*
- *  Set of operations handlers for operations on directories.
- */
-
-const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
+static const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
   rtems_filesystem_default_open,
   rtems_filesystem_default_close,
   imfs_dir_read,
@@ -34,3 +30,42 @@ const rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
   rtems_filesystem_default_fsync_or_fdatasync_success,
   rtems_filesystem_default_fcntl
 };
+
+static IMFS_jnode_t *IMFS_node_initialize_directory(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+)
+{
+  rtems_chain_initialize_empty( &node->info.directory.Entries );
+
+  return node;
+}
+
+static bool IMFS_is_mount_point( const IMFS_jnode_t *node )
+{
+  return node->info.directory.mt_fs != NULL;
+}
+
+static IMFS_jnode_t *IMFS_node_remove_directory(
+  IMFS_jnode_t *node,
+  const IMFS_jnode_t *root_node
+)
+{
+  if ( !rtems_chain_is_empty( &node->info.directory.Entries ) ) {
+    errno = ENOTEMPTY;
+    node = NULL;
+  } else if ( node == root_node || IMFS_is_mount_point( node ) ) {
+    errno = EBUSY;
+    node = NULL;
+  }
+
+  return node;
+}
+
+const IMFS_node_control IMFS_node_control_directory = {
+  .imfs_type = IMFS_DIRECTORY,
+  .handlers = &IMFS_directory_handlers,
+  .node_initialize = IMFS_node_initialize_directory,
+  .node_remove = IMFS_node_remove_directory,
+  .node_destroy = IMFS_node_destroy_default
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_link.c b/cpukit/libfs/src/imfs/imfs_handlers_link.c
index fd68f77..08dddb7 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_link.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_link.c
@@ -17,11 +17,9 @@
 
 #include "imfs.h"
 
-/*
- *  Handler table for IMFS device nodes
- */
+#include <stdlib.h>
 
-const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
+static const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
   rtems_filesystem_default_open,
   rtems_filesystem_default_close,
   rtems_filesystem_default_read,
@@ -34,3 +32,66 @@ const rtems_filesystem_file_handlers_r IMFS_link_handlers = {
   rtems_filesystem_default_fsync_or_fdatasync,
   rtems_filesystem_default_fcntl
 };
+
+static IMFS_jnode_t *IMFS_node_initialize_hard_link(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+)
+{
+  node->info.hard_link.link_node = info->hard_link.link_node;
+
+  return node;
+}
+
+static IMFS_jnode_t *IMFS_node_remove_hard_link(
+  IMFS_jnode_t *node,
+  const IMFS_jnode_t *root_node
+)
+{
+  IMFS_jnode_t *target = node->info.hard_link.link_node;
+
+  if ( target->st_nlink == 1) {
+    target = (*target->control->node_remove)( target, root_node );
+    if ( target == NULL ) {
+      node = NULL;
+    }
+  } else {
+    --target->st_nlink;
+    IMFS_update_ctime( target );
+  }
+
+  return node;
+}
+
+const IMFS_node_control IMFS_node_control_hard_link = {
+  .imfs_type = IMFS_HARD_LINK,
+  .handlers = &IMFS_link_handlers,
+  .node_initialize = IMFS_node_initialize_hard_link,
+  .node_remove = IMFS_node_remove_hard_link,
+  .node_destroy = IMFS_node_destroy_default
+};
+
+static IMFS_jnode_t *IMFS_node_initialize_sym_link(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+)
+{
+  node->info.sym_link.name = info->sym_link.name;
+
+  return node;
+}
+
+static IMFS_jnode_t *IMFS_node_destroy_sym_link( IMFS_jnode_t *node )
+{
+  free( node->info.sym_link.name );
+
+  return node;
+}
+
+const IMFS_node_control IMFS_node_control_sym_link = {
+  .imfs_type = IMFS_SYM_LINK,
+  .handlers = &IMFS_link_handlers,
+  .node_initialize = IMFS_node_initialize_sym_link,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_node_destroy_sym_link
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
index 10cba94..0e32291 100644
--- a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
+++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
@@ -17,11 +17,7 @@
 
 #include "imfs.h"
 
-/*
- *  Set of operations handlers for operations on memfile entities.
- */
-
-const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
+static const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
   memfile_open,
   rtems_filesystem_default_close,
   memfile_read,
@@ -34,3 +30,19 @@ const rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
   rtems_filesystem_default_fsync_or_fdatasync_success,
   rtems_filesystem_default_fcntl
 };
+
+const IMFS_node_control IMFS_node_control_memfile = {
+  .imfs_type = IMFS_MEMORY_FILE,
+  .handlers = &IMFS_memfile_handlers,
+  .node_initialize = IMFS_node_initialize_default,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_memfile_remove
+};
+
+const IMFS_node_control IMFS_node_control_linfile = {
+  .imfs_type = IMFS_LINEAR_FILE,
+  .handlers = &IMFS_memfile_handlers,
+  .node_initialize = IMFS_node_initialize_default,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_node_destroy_default
+};
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
index 8b4db45..6b2524e 100644
--- a/cpukit/libfs/src/imfs/imfs_init.c
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -47,6 +47,17 @@ const rtems_filesystem_operations_table IMFS_ops = {
   .statvfs_h = rtems_filesystem_default_statvfs
 };
 
+static const IMFS_node_control *const
+  IMFS_node_controls [IMFS_TYPE_COUNT] = {
+  [IMFS_DIRECTORY] = &IMFS_node_control_directory,
+  [IMFS_DEVICE] = &IMFS_node_control_device,
+  [IMFS_HARD_LINK] = &IMFS_node_control_hard_link,
+  [IMFS_SYM_LINK] = &IMFS_node_control_sym_link,
+  [IMFS_MEMORY_FILE] = &IMFS_node_control_memfile,
+  [IMFS_LINEAR_FILE] = &IMFS_node_control_linfile,
+  [IMFS_FIFO] = &IMFS_node_control_default
+};
+
 int IMFS_initialize(
   rtems_filesystem_mount_table_entry_t *mt_entry,
   const void                           *data
@@ -55,7 +66,6 @@ int IMFS_initialize(
   return IMFS_initialize_support(
     mt_entry,
     &IMFS_ops,
-    &IMFS_link_handlers,
-    &rtems_filesystem_handlers_default /* for fifos */
+    IMFS_node_controls
   );
 }
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
index 042995b..d480b13 100644
--- a/cpukit/libfs/src/imfs/imfs_initsupp.c
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -50,61 +50,59 @@ static int IMFS_determine_bytes_per_block(
   return 0;
 }
 
-
-/*
- *  IMFS_initialize
- */
 int IMFS_initialize_support(
-  rtems_filesystem_mount_table_entry_t        *temp_mt_entry,
-   const rtems_filesystem_operations_table    *op_table,
-   const rtems_filesystem_file_handlers_r     *link_handlers,
-   const rtems_filesystem_file_handlers_r     *fifo_handlers
+  rtems_filesystem_mount_table_entry_t *mt_entry,
+  const rtems_filesystem_operations_table *op_table,
+  const IMFS_node_control *const node_controls [IMFS_TYPE_COUNT]
 )
 {
-  static int                             imfs_instance;
-  IMFS_fs_info_t                        *fs_info;
-  IMFS_jnode_t                          *jnode;
-
-  /*
-   * determine/check value for imfs_memfile_bytes_per_block
-   */
-  IMFS_determine_bytes_per_block(&imfs_memfile_bytes_per_block,
-				 imfs_rq_memfile_bytes_per_block,
-				 IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK);
-
-  /*
-   *  Create the root node
-   *
-   *  NOTE: UNIX root is 755 and owned by root/root (0/0).
-   */
-  temp_mt_entry->mt_fs_root->location.node_access = IMFS_create_root_node();
-  temp_mt_entry->mt_fs_root->location.handlers = &IMFS_directory_handlers;
-  temp_mt_entry->mt_fs_root->location.ops = op_table;
-  temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
-
-  /*
-   * Create custom file system data.
-   */
-  fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
-  if ( !fs_info ) {
-    free(temp_mt_entry->mt_fs_root->location.node_access);
-    rtems_set_errno_and_return_minus_one(ENOMEM);
+  static int imfs_instance;
+
+  int rv = 0;
+  IMFS_fs_info_t *fs_info = calloc( 1, sizeof( *fs_info ) );
+
+  if ( fs_info != NULL ) {
+    IMFS_jnode_t *root_node;
+
+    fs_info->instance = imfs_instance++;
+    memcpy(
+      fs_info->node_controls,
+      node_controls,
+      sizeof( fs_info->node_controls )
+    );
+
+    root_node = IMFS_allocate_node(
+      fs_info,
+      fs_info->node_controls [IMFS_DIRECTORY],
+      "",
+      0,
+      (S_IFDIR | 0755),
+      NULL
+    );
+    if ( root_node != NULL ) {
+      mt_entry->fs_info = fs_info;
+      mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+      mt_entry->mt_fs_root->location.node_access = root_node;
+      mt_entry->mt_fs_root->location.ops = op_table;
+      IMFS_Set_handlers( &mt_entry->mt_fs_root->location );
+    } else {
+      errno = ENOMEM;
+      rv = -1;
+    }
+  } else {
+    errno = ENOMEM;
+    rv = -1;
   }
-  temp_mt_entry->fs_info = fs_info;
-
-  /*
-   * Set st_ino for the root to 1.
-   */
-
-  fs_info->instance              = imfs_instance++;
-  fs_info->ino_count             = 1;
-  fs_info->link_handlers         = link_handlers;
-  fs_info->fifo_handlers         = fifo_handlers;
 
-  jnode = temp_mt_entry->mt_fs_root->location.node_access;
-  jnode->st_ino = fs_info->ino_count;
+  if ( rv == 0 ) {
+    IMFS_determine_bytes_per_block(
+      &imfs_memfile_bytes_per_block,
+      imfs_rq_memfile_bytes_per_block,
+      IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK
+    );
+  }
 
-  return 0;
+  return rv;
 }
 
 int IMFS_node_clone( rtems_filesystem_location_info_t *loc )
@@ -120,16 +118,7 @@ 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;
-  }
+  node = (*node->control->node_destroy)( node );
 
   free( node );
 }
@@ -144,3 +133,32 @@ void IMFS_node_free( const rtems_filesystem_location_info_t *loc )
     --node->reference_count;
   }
 }
+
+IMFS_jnode_t *IMFS_node_initialize_default(
+  IMFS_jnode_t *node,
+  const IMFS_types_union *info
+)
+{
+  return node;
+}
+
+IMFS_jnode_t *IMFS_node_remove_default(
+  IMFS_jnode_t *node,
+  const IMFS_jnode_t *root_node
+)
+{
+  return node;
+}
+
+IMFS_jnode_t *IMFS_node_destroy_default( IMFS_jnode_t *node )
+{
+  return node;
+}
+
+const IMFS_node_control IMFS_node_control_default = {
+  .imfs_type = IMFS_INVALID_NODE,
+  .handlers = &rtems_filesystem_handlers_default,
+  .node_initialize = IMFS_node_initialize_default,
+  .node_remove = IMFS_node_remove_default,
+  .node_destroy = IMFS_node_destroy_default
+};
diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c
index 748a6f7..2d7041e 100644
--- a/cpukit/libfs/src/imfs/imfs_rmnod.c
+++ b/cpukit/libfs/src/imfs/imfs_rmnod.c
@@ -23,52 +23,6 @@
 
 #include "imfs.h"
 
-static int IMFS_rmnod_directory(
-  const rtems_filesystem_location_info_t *parentloc,
-  const rtems_filesystem_location_info_t *loc
-)
-{
-  int rv = 0;
-  IMFS_jnode_t *node = loc->node_access;
-
-  if ( !rtems_chain_is_empty( &node->info.directory.Entries ) ) {
-    errno = ENOTEMPTY;
-    rv = -1;
-  } else if (
-    rtems_filesystem_location_is_root( loc )
-      || node->info.directory.mt_fs != NULL
-  ) {
-    errno = EBUSY;
-    rv = -1;
-  }
-
-  return rv;
-}
-
-static int IMFS_rmnod_hard_link(
-  const rtems_filesystem_location_info_t *parentloc,
-  const rtems_filesystem_location_info_t *loc
-)
-{
-  int rv = 0;
-  IMFS_jnode_t *node = loc->node_access;
-  IMFS_jnode_t *target = node->info.hard_link.link_node;
-
-  if ( target->st_nlink == 1) {
-    rtems_filesystem_location_info_t target_loc = *loc;
-
-    target_loc.node_access = target;
-    IMFS_Set_handlers( &target_loc );
-
-    rv = (*target_loc.ops->rmnod_h)( parentloc, &target_loc );
-  } else {
-    --target->st_nlink;
-    IMFS_update_ctime( target );
-  }
-
-  return rv;
-}
-
 int IMFS_rmnod(
   const rtems_filesystem_location_info_t *parentloc,
   const rtems_filesystem_location_info_t *loc
@@ -77,23 +31,18 @@ int IMFS_rmnod(
   int rv = 0;
   IMFS_jnode_t *node = loc->node_access;
 
-  switch ( node->type ) {
-    case IMFS_DIRECTORY:
-      rv = IMFS_rmnod_directory( parentloc, loc );
-      break;
-    case IMFS_HARD_LINK:
-      rv = IMFS_rmnod_hard_link( parentloc, loc );
-      break;
-    default:
-      break;
-  }
-
-  if ( rv == 0 ) {
+  node = (*node->control->node_remove)(
+    node,
+    loc->mt_entry->mt_fs_root->location.node_access
+  );
+  if ( node != NULL ) {
     --node->reference_count;
     --node->st_nlink;
     if ( node->Parent != NULL ) {
       IMFS_remove_from_directory( node );
     }
+  } else {
+    rv = -1;
   }
 
   return rv;
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
index aa3f8a7..d2cff01 100644
--- a/cpukit/libfs/src/imfs/memfile.c
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -97,7 +97,7 @@ int memfile_open(
     uint32_t   count = the_jnode->info.linearfile.size;
     const unsigned char *buffer = the_jnode->info.linearfile.direct;
 
-    the_jnode->type = IMFS_MEMORY_FILE;
+    the_jnode->control = &IMFS_node_control_memfile;
     the_jnode->info.file.size            = 0;
     the_jnode->info.file.indirect        = 0;
     the_jnode->info.file.doubly_indirect = 0;
@@ -420,7 +420,7 @@ static void memfile_free_blocks_in_table(
  *         Regardless until the IMFS implementation is proven, it
  *         is better to stick to simple, easy to understand algorithms.
  */
-int IMFS_memfile_remove(
+IMFS_jnode_t *IMFS_memfile_remove(
  IMFS_jnode_t  *the_jnode
 )
 {
@@ -482,7 +482,7 @@ int IMFS_memfile_remove(
         (block_p **)&info->triply_indirect, to_free );
   }
 
-  return 0;
+  return the_jnode;
 }
 
 /*
diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c
index af791f5..d70f4db 100644
--- a/cpukit/libfs/src/imfs/miniimfs_init.c
+++ b/cpukit/libfs/src/imfs/miniimfs_init.c
@@ -23,7 +23,7 @@
 
 #include "imfs.h"
 
-static const rtems_filesystem_operations_table miniIMFS_ops = {
+const rtems_filesystem_operations_table miniIMFS_ops = {
   .lock_h = rtems_filesystem_default_lock,
   .unlock_h = rtems_filesystem_default_unlock,
   .eval_path_h = IMFS_eval_path,
@@ -47,6 +47,17 @@ static const rtems_filesystem_operations_table miniIMFS_ops = {
   .statvfs_h = rtems_filesystem_default_statvfs
 };
 
+static const IMFS_node_control *const
+  IMFS_mini_node_controls [IMFS_TYPE_COUNT] = {
+  [IMFS_DIRECTORY] = &IMFS_node_control_directory,
+  [IMFS_DEVICE] = &IMFS_node_control_device,
+  [IMFS_HARD_LINK] = &IMFS_node_control_default,
+  [IMFS_SYM_LINK] = &IMFS_node_control_default,
+  [IMFS_MEMORY_FILE] = &IMFS_node_control_memfile,
+  [IMFS_LINEAR_FILE] = &IMFS_node_control_linfile,
+  [IMFS_FIFO] = &IMFS_node_control_default
+};
+
 int miniIMFS_initialize(
   rtems_filesystem_mount_table_entry_t *mt_entry,
   const void                           *data
@@ -55,7 +66,6 @@ int miniIMFS_initialize(
   return IMFS_initialize_support(
     mt_entry,
     &miniIMFS_ops,
-    &rtems_filesystem_handlers_default, /* for links */
-    &rtems_filesystem_handlers_default  /* for fifos */
+    IMFS_mini_node_controls
   );
 }




More information about the vc mailing list