[PATCH] Filesystem: Wait for unmount() finish

sebastian.huber at embedded-brains.de sebastian.huber at embedded-brains.de
Wed May 23 10:12:25 UTC 2012


From: Sebastian Huber <sebastian.huber at embedded-brains.de>

---
 cpukit/libcsupport/include/rtems/libio.h  |   16 +++++++++++++---
 cpukit/libcsupport/include/rtems/libio_.h |   10 ++++++++++
 cpukit/libcsupport/src/sup_fs_location.c  |    9 +++++++++
 cpukit/libcsupport/src/unmount.c          |   16 ++++++++++++++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
index b59ec0f..23a9049 100644
--- a/cpukit/libcsupport/include/rtems/libio.h
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -1459,6 +1459,13 @@ struct rtems_filesystem_mount_table_entry_tt {
    *  string.
    */
   char                                  *dev;
+
+  /**
+   * The task that initiated the unmount process.  After unmount process
+   * completition this task will be notified via the
+   * @ref RTEMS_FILESYSTEM_UNMOUNT_EVENT.
+   */
+  rtems_id                               unmount_task;
 };
 
 /**
@@ -1513,9 +1520,12 @@ 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 completition.  In case the
+ * calling thread has its root or current directory in the unmounted file
+ * system a dead lock will occur and the function never returns.
+ *
+ * The unmount process completition notification uses the RTEMS classic API
+ * event @ref RTEMS_FILESYSTEM_UNMOUNT_EVENT.
  *
  * @retval 0 Successful operation.
  * @retval -1 An error occured.  The @c errno indicates the error.
diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h
index 418f4a3..aa93a74 100644
--- a/cpukit/libcsupport/include/rtems/libio_.h
+++ b/cpukit/libcsupport/include/rtems/libio_.h
@@ -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 completition.
+ *
+ * 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;
 
 /*
diff --git a/cpukit/libcsupport/src/sup_fs_location.c b/cpukit/libcsupport/src/sup_fs_location.c
index 4ebf5f0..f991024 100644
--- a/cpukit/libcsupport/src/sup_fs_location.c
+++ b/cpukit/libcsupport/src/sup_fs_location.c
@@ -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);
 }
diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c
index b58955d..3b16945 100644
--- a/cpukit/libcsupport/src/unmount.c
+++ b/cpukit/libcsupport/src/unmount.c
@@ -37,9 +37,11 @@ int unmount( const char *path )
 
     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->unmount_task = self_task_id;
       mt_entry->mounted = false;
       rtems_filesystem_mt_entry_unlock( lock_context );
     }
@@ -50,5 +52,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;
 }
-- 
1.7.1




More information about the devel mailing list