diff options
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/libcsupport/src/unmount.c | 204 |
1 files changed, 116 insertions, 88 deletions
diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c index 81e097c818..fa5e71077d 100644 --- a/cpukit/libcsupport/src/unmount.c +++ b/cpukit/libcsupport/src/unmount.c @@ -42,12 +42,51 @@ int search_mt_for_mount_point( rtems_filesystem_location_info_t *location_of_mount_point ); +rtems_boolean rtems_filesystem_nodes_equal( + const rtems_filesystem_location_info_t *loc1, + const rtems_filesystem_location_info_t *loc2 +){ + return ( loc1->node_access == loc2->node_access ); +} + + +/* + * file_systems_below_this_mountpoint + * + * This routine will run through the entries that currently exist in the + * mount table chain. For each entry in the mount table chain it will + * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the + * mount table file system root nodes matches the new file system root node + * this indicates that we are trying to mount a file system that has already + * been mounted. This is not a permitted operation. temp_loc is set to + * the root node of the file system being unmounted. + */ -int file_systems_below_this_mountpoint( +rtems_boolean file_systems_below_this_mountpoint( const char *path, - rtems_filesystem_location_info_t *temp_loc, - rtems_filesystem_mount_table_entry_t *temp_mt_entry -); + rtems_filesystem_location_info_t *fs_root_loc, + rtems_filesystem_mount_table_entry_t *fs_to_unmount +) +{ + Chain_Node *the_node; + rtems_filesystem_mount_table_entry_t *the_mount_entry; + + /* + * Search the mount table for any mount entries referencing this + * mount entry. + */ + + for ( the_node = rtems_filesystem_mount_table_control.first; + !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node ); + the_node = the_node->next ) { + the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node; + if (the_mount_entry->mt_point_node.mt_entry == fs_root_loc->mt_entry ) { + return TRUE; + } + } + + return FALSE; +} /* * unmount @@ -61,132 +100,121 @@ int unmount( const char *path ) { - int status; - rtems_filesystem_location_info_t fs_root_loc; - rtems_filesystem_mount_table_entry_t temp_mt_entry; + rtems_filesystem_location_info_t loc; + rtems_filesystem_location_info_t *fs_root_loc; + rtems_filesystem_location_info_t *fs_mount_loc; + rtems_filesystem_mount_table_entry_t *mt_entry; /* - * Are there any file systems below the path specified + * Get + * The root node of the mounted filesytem. + * The node for the directory that the fileystem is mounted on. + * The mount entry that is being refered to. */ - status = file_systems_below_this_mountpoint( - path, - &fs_root_loc, - &temp_mt_entry - ); - - if ( status != 0 ) + if ( rtems_filesystem_evaluate_path( path, 0x0, &loc, TRUE ) ) return -1; + mt_entry = loc.mt_entry; + fs_mount_loc = &mt_entry->mt_point_node; + fs_root_loc = &mt_entry->mt_fs_root; + /* - * Is the current node reference pointing to a node in the file system - * we are attempting to unmount ? + * Verify this is the root node for the file system to be unmounted. */ - if ( rtems_filesystem_current.mt_entry == fs_root_loc.mt_entry ) { - rtems_filesystem_freenode( &fs_root_loc ); - set_errno_and_return_minus_one( EBUSY ); + if ( !rtems_filesystem_nodes_equal( fs_root_loc, &loc) ){ + rtems_filesystem_freenode( &loc ); + set_errno_and_return_minus_one( EACCES ); } /* - * Run the file descriptor table to determine if there are any file - * descriptors that are currently active and reference nodes in the - * file system that we are trying to unmount + * Free the loc node and just use the nodes from the mt_entry . */ - if ( rtems_libio_is_open_files_in_fs( fs_root_loc.mt_entry ) == 1 ) { - rtems_filesystem_freenode( &fs_root_loc ); - set_errno_and_return_minus_one( EBUSY ); - } - + rtems_filesystem_freenode( &loc ); + /* - * Allow the file system being unmounted on to do its cleanup. + * Verify Unmount is supported by both filesystems. */ - if ((temp_mt_entry.mt_point_node.ops->unmount_h )( fs_root_loc.mt_entry ) != 0 ) { - rtems_filesystem_freenode( &fs_root_loc ); - return -1; - } + if ( !fs_mount_loc->ops->unmount_h ) + set_errno_and_return_minus_one( ENOTSUP ); - /* - * Run the unmount function for the subordinate file system. - */ + if ( !fs_root_loc->ops->fsunmount_me_h ) + set_errno_and_return_minus_one( ENOTSUP ); - if ((temp_mt_entry.mt_fs_root.ops->fsunmount_me_h )( fs_root_loc.mt_entry ) != 0){ - rtems_filesystem_freenode( &fs_root_loc ); - return -1; - } /* - * Extract the mount table entry from the chain + * Verify the current node is not in this filesystem. + * XXX - Joel I have a question here wasn't code added + * that made the current node thread based instead + * of system based? I thought it was but it doesn't + * look like it in this version. */ - Chain_Extract( ( Chain_Node * ) fs_root_loc.mt_entry ); + if ( rtems_filesystem_current.mt_entry == mt_entry ) + set_errno_and_return_minus_one( EBUSY ); /* - * Free the memory associated with the extracted mount table entry. + * Verify there are no file systems below the path specified */ - rtems_filesystem_freenode( &fs_root_loc.mt_entry->mt_point_node ); - free( fs_root_loc.mt_entry ); - rtems_filesystem_freenode( &fs_root_loc ); - - return 0; -} + if ( file_systems_below_this_mountpoint( path, fs_root_loc, mt_entry ) != 0 ) + set_errno_and_return_minus_one( EBUSY ); + /* + * Run the file descriptor table to determine if there are any file + * descriptors that are currently active and reference nodes in the + * file system that we are trying to unmount + */ -/* - * file_systems_below_this_mountpoint - * - * This routine will run through the entries that currently exist in the - * mount table chain. For each entry in the mount table chain it will - * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the - * mount table file system root nodes matches the new file system root node - * this indicates that we are trying to mount a file system that has already - * been mounted. This is not a permitted operation. temp_loc is set to - * the root node of the file system being unmounted. - */ + if ( rtems_libio_is_open_files_in_fs( mt_entry ) == 1 ) + set_errno_and_return_minus_one( EBUSY ); + + /* + * Allow the file system being unmounted on to do its cleanup. + * If it fails it will set the errno to the approprate value + * and the fileystem will not be modified. + */ -int file_systems_below_this_mountpoint( - const char *path, - rtems_filesystem_location_info_t *fs_root_loc, - rtems_filesystem_mount_table_entry_t *fs_to_unmount -) -{ - Chain_Node *the_node; - rtems_filesystem_mount_table_entry_t *the_mount_entry; + if (( fs_mount_loc->ops->unmount_h )( mt_entry ) != 0 ) + return -1; /* - * Is the path even a valid node name in the existing tree? + * Allow the mounted filesystem to unmark the use of the root node. + * + * Run the unmount function for the subordinate file system. + * + * If we fail to unmount the filesystem remount it on the base filesystems + * directory node. + * + * NOTE: Fatal error is called in a case which should never happen + * This was response was questionable but the best we could + * come up with. */ - if ( rtems_filesystem_evaluate_path( path, 0x0, fs_root_loc, TRUE ) ) + if ((fs_root_loc->ops->fsunmount_me_h )( mt_entry ) != 0){ + if (( fs_mount_loc->ops->mount_h )( mt_entry ) != 0 ) + rtems_fatal_error_occurred( 0 ); return -1; - + } + /* - * Verify this is the root node for the file system to be unmounted. + * Extract the mount table entry from the chain */ - *fs_to_unmount = *fs_root_loc->mt_entry; - if ( fs_to_unmount->mt_fs_root.node_access != fs_root_loc->node_access ){ - rtems_filesystem_freenode(fs_root_loc); - set_errno_and_return_minus_one( EACCES ); - } + Chain_Extract( ( Chain_Node * ) mt_entry ); /* - * Search the mount table for any mount entries referencing this - * mount entry. + * Free the memory node that was allocated in mount + * Free the memory associated with the extracted mount table entry. */ - for ( the_node = rtems_filesystem_mount_table_control.first; - !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node ); - the_node = the_node->next ) { - the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node; - if (the_mount_entry->mt_point_node.mt_entry == fs_root_loc->mt_entry ) { - rtems_filesystem_freenode(fs_root_loc); - set_errno_and_return_minus_one( EBUSY ); - } - } + rtems_filesystem_freenode( fs_mount_loc ); + free( mt_entry ); return 0; } + + |