[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