From 1bdff036acddbbc63aa849741abba6581549f7b6 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 23 Feb 2012 17:57:27 +0100 Subject: 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(-) (limited to 'cpukit/libfs') diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c index 69f409e472..c4e7a921ff 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 d2af7af8e5..966e9e1dde 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 c2d95f0f8e..e9be053c20 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 + + #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 - - #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 caf82be250..2fe3c7dba1 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 fc687e4331..3bbbec22fb 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 33e7e36520..5b1ccfb989 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 985275049a..dc623629b6 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 49ade1bab9..6f9388ea86 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 dfda4fc2cb..b18f2ab6b9 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 e179eabf44..10cba9477b 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 2a7d890a09..8b4db45019 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 61ad6a70f2..042995b878 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 130c529d75..2684dbe64f 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 ae4d8fb92b..748a6f7365 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 - -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 65810c0bca..fed8914235 100644 --- a/cpukit/libfs/src/imfs/memfile.c +++ b/cpukit/libfs/src/imfs/memfile.c @@ -113,28 +113,6 @@ int memfile_open( return 0; } -/* - * 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 * diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c index a4db968e3c..af791f5a31 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, -- cgit v1.2.3