mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-21 09:59:50 +08:00
Filesystem: Wait for unmount() to finish
This commit is contained in:
@@ -1459,6 +1459,13 @@ struct rtems_filesystem_mount_table_entry_tt {
|
||||
* string.
|
||||
*/
|
||||
char *dev;
|
||||
|
||||
/**
|
||||
* The task that initiated the unmount process. After unmount process
|
||||
* completion this task will be notified via the
|
||||
* @ref RTEMS_FILESYSTEM_UNMOUNT_EVENT.
|
||||
*/
|
||||
rtems_id unmount_task;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1513,9 +1520,18 @@ int rtems_filesystem_unregister(
|
||||
/**
|
||||
* @brief Unmounts the file system at @a mount_path.
|
||||
*
|
||||
* @todo Due to file system implementation shortcomings it is possible to
|
||||
* unmount file systems in use. This likely leads to heap corruption. Unmount
|
||||
* only file systems which are not in use by the application.
|
||||
* The function waits for the unmount process completion. In case the calling
|
||||
* thread uses resources of the unmounted file system the function may never
|
||||
* return. In case the calling thread has its root or current directory in the
|
||||
* unmounted file system the function returns with an error status and errno is
|
||||
* set to EBUSY.
|
||||
*
|
||||
* The unmount process completion notification uses the RTEMS classic API
|
||||
* event @ref RTEMS_FILESYSTEM_UNMOUNT_EVENT. It is a fatal error to terminate
|
||||
* the calling thread while waiting for this event.
|
||||
*
|
||||
* A concurrent unmount request for the same file system instance has
|
||||
* unpredictable effects.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -1 An error occured. The @c errno indicates the error.
|
||||
|
||||
@@ -38,6 +38,16 @@ extern "C" {
|
||||
#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
|
||||
#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
|
||||
|
||||
/**
|
||||
* @brief Event to signal an unmount process completion.
|
||||
*
|
||||
* This event should equal the RTEMS_BDBUF_TRANSFER_SYNC event to avoid too
|
||||
* many events reserved for the file system.
|
||||
*
|
||||
* @see rtems_filesystem_do_unmount() and unmount().
|
||||
*/
|
||||
#define RTEMS_FILESYSTEM_UNMOUNT_EVENT RTEMS_EVENT_1
|
||||
|
||||
extern rtems_id rtems_libio_semaphore;
|
||||
|
||||
/*
|
||||
|
||||
@@ -213,5 +213,14 @@ void rtems_filesystem_do_unmount(
|
||||
rtems_filesystem_mt_unlock();
|
||||
rtems_filesystem_global_location_release(mt_entry->mt_point_node);
|
||||
(*mt_entry->ops->fsunmount_me_h)(mt_entry);
|
||||
|
||||
if (mt_entry->unmount_task != 0) {
|
||||
rtems_status_code sc =
|
||||
rtems_event_send(mt_entry->unmount_task, RTEMS_FILESYSTEM_UNMOUNT_EVENT);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
rtems_fatal_error_occurred(0xdeadbeef);
|
||||
}
|
||||
}
|
||||
|
||||
free(mt_entry);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
|
||||
#include <rtems/libio_.h>
|
||||
|
||||
static bool contains_root_or_current_directory(
|
||||
const rtems_filesystem_mount_table_entry_t *mt_entry
|
||||
)
|
||||
{
|
||||
const rtems_filesystem_location_info_t *root =
|
||||
&rtems_filesystem_root->location;
|
||||
const rtems_filesystem_location_info_t *current =
|
||||
&rtems_filesystem_current->location;
|
||||
|
||||
return mt_entry == root->mt_entry || mt_entry == current->mt_entry;
|
||||
}
|
||||
|
||||
int unmount( const char *path )
|
||||
{
|
||||
int rv = 0;
|
||||
@@ -32,16 +44,23 @@ int unmount( const char *path )
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry;
|
||||
|
||||
if ( rtems_filesystem_location_is_root( currentloc ) ) {
|
||||
const rtems_filesystem_operations_table *mt_point_ops =
|
||||
mt_entry->mt_point_node->location.mt_entry->ops;
|
||||
if ( !contains_root_or_current_directory( mt_entry ) ) {
|
||||
const rtems_filesystem_operations_table *mt_point_ops =
|
||||
mt_entry->mt_point_node->location.mt_entry->ops;
|
||||
|
||||
rv = (*mt_point_ops->unmount_h)( mt_entry );
|
||||
if ( rv == 0 ) {
|
||||
rtems_filesystem_mt_entry_declare_lock_context( lock_context );
|
||||
rv = (*mt_point_ops->unmount_h)( mt_entry );
|
||||
if ( rv == 0 ) {
|
||||
rtems_id self_task_id = rtems_task_self();
|
||||
rtems_filesystem_mt_entry_declare_lock_context( lock_context );
|
||||
|
||||
rtems_filesystem_mt_entry_lock( lock_context );
|
||||
mt_entry->mounted = false;
|
||||
rtems_filesystem_mt_entry_unlock( lock_context );
|
||||
rtems_filesystem_mt_entry_lock( lock_context );
|
||||
mt_entry->unmount_task = self_task_id;
|
||||
mt_entry->mounted = false;
|
||||
rtems_filesystem_mt_entry_unlock( lock_context );
|
||||
}
|
||||
} else {
|
||||
errno = EBUSY;
|
||||
rv = -1;
|
||||
}
|
||||
} else {
|
||||
errno = EACCES;
|
||||
@@ -50,5 +69,19 @@ int unmount( const char *path )
|
||||
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
if ( rv == 0 ) {
|
||||
rtems_event_set out;
|
||||
rtems_status_code sc = rtems_event_receive(
|
||||
RTEMS_FILESYSTEM_UNMOUNT_EVENT,
|
||||
RTEMS_EVENT_ALL | RTEMS_WAIT,
|
||||
RTEMS_NO_TIMEOUT,
|
||||
&out
|
||||
);
|
||||
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
rtems_fatal_error_occurred( 0xdeadbeef );
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -256,13 +256,17 @@ truncate_test03 (void)
|
||||
rtems_test_assert (fd >= 0);
|
||||
n = write (fd, databuf, len);
|
||||
rtems_test_assert (n == len);
|
||||
status = close (fd);
|
||||
rtems_test_assert (status == 0);
|
||||
|
||||
/*
|
||||
* Truncate it to the half size
|
||||
*/
|
||||
|
||||
status = truncate (name01, len / 2);
|
||||
rtems_test_assert (status == 0);
|
||||
status = truncate (name01, len);
|
||||
rtems_test_assert (status == 0);
|
||||
|
||||
/*
|
||||
* verify the data
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
*** MOUNT/UNMOUNT TEST ***
|
||||
|
||||
chdir to the root directory
|
||||
@@ -25,30 +23,30 @@ create /b/my_file
|
||||
Verify /b/my_file
|
||||
create c/y/my_mount_point/my_dir/d
|
||||
Verify c/y/my_mount_point/my_dir/d
|
||||
Attempting to mount IMFS file system at /c/z/my_mount_point
|
||||
2nd file system successfully mounted at /c/z/my_mount_point
|
||||
Attempting to mount IMFS file system at /c/z/my_mount_point
|
||||
2nd file system successfully mounted at /c/z/my_mount_point
|
||||
|
||||
chdir to /c/z/my_mount_point.
|
||||
chdir() status : 0
|
||||
|
||||
|
||||
Creating a series of directories under /c/z/my_mount_point
|
||||
Creating: a 0 2 Success
|
||||
Creating: b 0 2 Success
|
||||
Creating: c 0 2 Success
|
||||
Creating: d 0 2 Success
|
||||
Creating: e 0 2 Success
|
||||
Creating: f 0 2 Success
|
||||
Creating: c/y 0 2 Success
|
||||
Creating: c/z 0 2 Success
|
||||
Creating: c/x 0 2 Success
|
||||
Creating: c/y/a3333 0 2 Success
|
||||
Creating: c/y/j123 0 2 Success
|
||||
Creating: c/y/my_mount_point 0 2 Success
|
||||
Creating: c/y/my_mount_point/my_dir 0 2 Success
|
||||
Creating: c/y/my_mount_point/my_dir/d 0 2 Success
|
||||
Creating: c/z/my_mount_point 0 2 Success
|
||||
Creating: /c/z/my_mount_point/a/../../my_mount_point/a/g 0 2 Success
|
||||
Creating: a 0 0 Success
|
||||
Creating: b 0 0 Success
|
||||
Creating: c 0 0 Success
|
||||
Creating: d 0 0 Success
|
||||
Creating: e 0 0 Success
|
||||
Creating: f 0 0 Success
|
||||
Creating: c/y 0 0 Success
|
||||
Creating: c/z 0 0 Success
|
||||
Creating: c/x 0 0 Success
|
||||
Creating: c/y/a3333 0 0 Success
|
||||
Creating: c/y/j123 0 0 Success
|
||||
Creating: c/y/my_mount_point 0 0 Success
|
||||
Creating: c/y/my_mount_point/my_dir 0 0 Success
|
||||
Creating: c/y/my_mount_point/my_dir/d 0 0 Success
|
||||
Creating: c/z/my_mount_point 0 0 Success
|
||||
Creating: /c/z/my_mount_point/a/../../my_mount_point/a/g 0 0 Success
|
||||
|
||||
chdir to /
|
||||
chdir() status : 0
|
||||
@@ -56,31 +54,38 @@ chdir() status : 0
|
||||
Unmount status: 0
|
||||
Mount a NULL file system and verify EINVAL
|
||||
mount with option of -62 should fail with EINVAL
|
||||
Mount a Read Only filesystem at /c/y/my_mount_point
|
||||
Read only file system successfully mounted at /c/y/my_mount_point
|
||||
create c/y/my_mount_point/../../y/my_mount_point/new_dir
|
||||
Mount a Read Only filesystem at /c/y/my_mount_point
|
||||
Read only file system successfully mounted at /c/y/my_mount_point
|
||||
create c/y/my_mount_point/../../y/new_dir
|
||||
Verify a mount point returns EROFS for another mount
|
||||
Unmount /c/y/my_mount_point
|
||||
Mount a read-write file system at /c/y/my_mount_point
|
||||
Verify a mount point returns EBUSY for another mount
|
||||
Mount on a file should fail with ENOTDIR
|
||||
Create and chdir to /c/y/my_mount_point/mydir
|
||||
unmount of /c/y/my_mount_point should fail with EBUSY
|
||||
chdir to / and verify we can unmount /c/y/my_mount_point
|
||||
unmount /c/y/my_mount_point
|
||||
chroot to /c/y/my_mount_point
|
||||
unmount of . should fail with EBUSY
|
||||
chroot to / and verify we can unmount /c/y/my_mount_point
|
||||
unmount of /c/y/my_mount_point
|
||||
chdir to /c/y/my_mount_point/my_dir should fail with ENOENT
|
||||
unmount /b/mount_point should fail with EINVAL
|
||||
Mount /c/y/my_mount_point
|
||||
Create and open /c/y/my_mount_point/my_file
|
||||
|
||||
mkdir /c/y/my_mount_point/my_dir
|
||||
Open /c/y/my_mount_point/my_dir
|
||||
Unmount /c/y/my_mount_point should fail with EBUSY
|
||||
Close /c/y/my_mount_point/my_dir
|
||||
mkdir /c/y/my_mount_point/my_sub_fs_dir
|
||||
open /c/y/my_mount_point/my_sub_fs_dir
|
||||
close /c/y/my_mount_point/my_sub_fs_dir
|
||||
mkdir /c/y/my_mount_point/my_sub_fs_dir should fail with EEXIST
|
||||
unmount /c/y/my_mount_point
|
||||
mkdir /c/y/my_mount_point/my_sub_fs_dir
|
||||
rmdir /c/y/my_mount_point/my_sub_fs_dir
|
||||
Unmount /c/y/my_mount_point/my_dir should fail with EACCES
|
||||
Mount a file system at /c/y/my_mount_point/my_dir
|
||||
unmount /c/y/my_mount_point should fail with EBUSY
|
||||
Mount a file system at /c/y/my_mount_point
|
||||
Verify a hard link across filesystems fails with EXDEV
|
||||
Verify a symbolic link across file systems works
|
||||
unmount /c/y/my_mount_point/my_dir
|
||||
Verify the symbolic link now fails
|
||||
unmount /c/y/my_mount_point
|
||||
Verify the symbolic link now fails
|
||||
|
||||
|
||||
*** END OF MOUNT/UNMOUNT TEST ***
|
||||
|
||||
@@ -314,21 +314,33 @@ int main(
|
||||
status = chdir( "/c/y/my_mount_point/mydir" );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("unmount of /c/y/my_mount_point\n");
|
||||
printf("unmount of /c/y/my_mount_point should fail with EBUSY\n");
|
||||
status = unmount( "/c/y/my_mount_point" );
|
||||
rtems_test_assert( status == -1 );
|
||||
rtems_test_assert( errno == EBUSY );
|
||||
|
||||
status = chdir( "/" );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("chdir to .. should fail with ENXIO\n");
|
||||
status = chdir( ".." );
|
||||
printf("chroot to /c/y/my_mount_point\n");
|
||||
status = chroot( "/c/y/my_mount_point" );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("unmount of . should fail with EBUSY\n");
|
||||
status = unmount( "." );
|
||||
rtems_test_assert( status == -1 );
|
||||
rtems_test_assert( errno == ENXIO );
|
||||
rtems_test_assert( errno == EBUSY );
|
||||
|
||||
/*
|
||||
* Chdir to root and verify we unmounted the file system now.
|
||||
*/
|
||||
|
||||
printf("chdir to / and verify we can unmount /c/y/my_mount_point\n");
|
||||
status = chdir( "/" );
|
||||
printf("chroot to / and verify we can unmount /c/y/my_mount_point\n");
|
||||
status = chroot( "/" );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("unmount of /c/y/my_mount_point\n");
|
||||
status = unmount( "/c/y/my_mount_point" );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("chdir to /c/y/my_mount_point/my_dir should fail with ENOENT\n");
|
||||
@@ -376,6 +388,10 @@ int main(
|
||||
directory = opendir( my_sub_fs_dir );
|
||||
rtems_test_assert( directory );
|
||||
|
||||
printf("close %s\n", my_sub_fs_dir );
|
||||
status = closedir( directory );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("mkdir %s should fail with EEXIST\n", my_sub_fs_dir );
|
||||
status = mkdir( my_sub_fs_dir, S_IRWXU );
|
||||
rtems_test_assert( status == -1 );
|
||||
@@ -385,10 +401,6 @@ int main(
|
||||
status = unmount( mount_point );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("close %s\n", my_sub_fs_dir );
|
||||
status = closedir( directory );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
printf("mkdir %s\n", my_sub_fs_dir );
|
||||
status = mkdir( my_sub_fs_dir, S_IRWXU );
|
||||
rtems_test_assert( status == 0 );
|
||||
|
||||
Reference in New Issue
Block a user