summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-09-29 15:48:52 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-09-29 15:48:52 -0600
commite66fe204e0f9eed047fccdbd7b7fd31f264a2bc7 (patch)
treef7b007c79502fd72466690bd1a67de0e42b6df20
parent43b185f9cb9da1bde9caa42ad9daede6d7c10b4d (diff)
downloadnuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.tar.gz
nuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.tar.bz2
nuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.zip
Completes the re-implementation of mq_unlink()
-rw-r--r--nuttx/fs/mqueue/mq_close.c84
-rw-r--r--nuttx/fs/mqueue/mq_open.c7
-rw-r--r--nuttx/fs/mqueue/mq_unlink.c118
-rw-r--r--nuttx/fs/mqueue/mqueue.h23
-rw-r--r--nuttx/fs/semaphore/sem_unlink.c2
5 files changed, 149 insertions, 85 deletions
diff --git a/nuttx/fs/mqueue/mq_close.c b/nuttx/fs/mqueue/mq_close.c
index 4526f0771..a83772ee2 100644
--- a/nuttx/fs/mqueue/mq_close.c
+++ b/nuttx/fs/mqueue/mq_close.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched/mqueue/mq_close.c
+ * fs/mqueue/mq_close.c
*
- * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -107,7 +107,7 @@ int mq_close(mqd_t mqdes)
FAR struct tcb_s *rtcb = sched_self();
FAR struct task_group_s *group = rtcb->group;
FAR struct mqueue_inode_s *msgq;
- struct inode *inode ;
+ FAR struct inode *inode;
DEBUGASSERT(group);
@@ -128,11 +128,6 @@ int mq_close(mqd_t mqdes)
msgq = mqdes->msgq;
DEBUGASSERT(msgq && msgq->inode);
- /* Get the inode from the message queue structure */
-
- inode = msgq->inode;
- DEBUGASSERT(inode->u.i_mqueue == msgq);
-
/* Check if the calling task has a notification attached to
* the message queue via this mqdes.
*/
@@ -147,40 +142,65 @@ int mq_close(mqd_t mqdes)
}
#endif
+ /* Get the inode from the message queue structure */
+
+ inode = msgq->inode;
+ DEBUGASSERT(inode->u.i_mqueue == msgq);
+
/* Decrement the reference count on the inode */
- inode_semtake();
- if (inode->i_crefs > 0)
- {
- inode->i_crefs--;
- }
+ mq_release(inode);
+ }
- /* If the message queue was previously unlinked and the reference
- * count has decremented to zero, then release the message queue and
- * delete the inode now.
- */
+ return OK;
+}
- if (inode->i_crefs <= 0 && (inode->i_flags & FSNODEFLAG_DELETED) != 0)
- {
- /* Free the message queue (and any messages left in it) */
+/****************************************************************************
+ * Name: mq_close
+ *
+ * Description:
+ * Release a reference count on a message queue inode.
+ *
+ * Parameters:
+ * inode - The message queue inode
+ *
+ * Return Value:
+ * None
+ *
+ ****************************************************************************/
+
+void mq_release(FAR struct inode *inode)
+{
+ /* Decrement the reference count on the inode */
- mq_msgqfree(msgq);
+ inode_semtake();
+ if (inode->i_crefs > 0)
+ {
+ inode->i_crefs--;
+ }
- /* Release and free the inode container */
+ /* If the message queue was previously unlinked and the reference count
+ * has decremented to zero, then release the message queue and delete
+ * the inode now.
+ */
- inode_semgive();
- inode_free(inode->i_child);
- kmm_free(inode);
- return OK;
- }
+ if (inode->i_crefs <= 0 && (inode->i_flags & FSNODEFLAG_DELETED) != 0)
+ {
+ FAR struct mqueue_inode_s *msgq = inode->u.i_mqueue;
+ DEBUGASSERT(msgq);
+
+ /* Free the message queue (and any messages left in it) */
- /* Deallocate the message descriptor */
+ mq_msgqfree(msgq);
+ inode->u.i_mqueue = NULL;
- mq_desfree(mqdes);
+ /* Release and free the inode container */
- sched_unlock();
inode_semgive();
- }
+ inode_free(inode->i_child);
+ kmm_free(inode);
+ return;
+ }
- return OK;
+ inode_semgive();
}
diff --git a/nuttx/fs/mqueue/mq_open.c b/nuttx/fs/mqueue/mq_open.c
index 4731e3a33..15cae3f4f 100644
--- a/nuttx/fs/mqueue/mq_open.c
+++ b/nuttx/fs/mqueue/mq_open.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * sched/mqueue/mq_open.c
+ * fs/mqueue/mq_open.c
*
* Copyright (C) 2007-2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@@ -64,11 +64,6 @@
/****************************************************************************
* Pre-procesor Definitions
****************************************************************************/
-/* Configuration ************************************************************/
-
-#ifndef CONFIG_FS_MQUEUE_MPATH
-# define CONFIG_FS_MQUEUE_MPATH "/var/mqueue"
-#endif
/****************************************************************************
* Private Type Declarations
diff --git a/nuttx/fs/mqueue/mq_unlink.c b/nuttx/fs/mqueue/mq_unlink.c
index 3ee6840f7..1e7ae5db3 100644
--- a/nuttx/fs/mqueue/mq_unlink.c
+++ b/nuttx/fs/mqueue/mq_unlink.c
@@ -1,7 +1,7 @@
/************************************************************************
- * sched/mqueue/mq_unlink.c
+ * fs/mqueue/mq_unlink.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -39,10 +39,14 @@
#include <nuttx/config.h>
-#include <stdbool.h>
+#include <stdio.h>
#include <mqueue.h>
-#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/mqueue.h>
+
+#include "inode/inode.h"
#include "mqueue/mqueue.h"
/************************************************************************
@@ -88,58 +92,80 @@
*
************************************************************************/
-int mq_unlink(const char *mq_name)
+int mq_unlink(FAR const char *mq_name)
{
- FAR struct mqueue_inode_s *msgq;
- irqstate_t saved_state;
- int ret = ERROR;
-
- /* Verify the input values */
-
- if (mq_name)
- {
- sched_lock();
-
- /* Find the named message queue */
+ FAR struct inode *inode;
+ FAR const char *relpath = NULL;
+ char fullpath[MAX_MQUEUE_PATH];
+ int errcode;
+ int ret;
- msgq = mq_findnamed(mq_name);
- if (msgq)
- {
- /* If it is no longer connected, then we can just
- * discard the message queue now.
- */
+ /* Get the full path to the message queue */
- if (!msgq->nconnect)
- {
- /* Remove the message queue from the list of all
- * message queues
- */
+ snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name);
- saved_state = irqsave();
- (void)sq_rem((FAR sq_entry_t*)msgq, &g_msgqueues);
- irqrestore(saved_state);
+ /* Get the inode for this message queue. */
- /* Then deallocate it (and any messages left in it) */
+ sched_lock();
+ inode = inode_find(fullpath, &relpath);
+ if (!inode)
+ {
+ /* There is no inode that includes in this path */
- mq_msgqfree(msgq);
- }
+ errcode = ENOENT;
+ goto errout;
+ }
- /* If the message queue is still connected to a message descriptor,
- * then mark it for deletion when the last message descriptor is
- * closed
- */
+ /* Verify that what we found is, indeed, a message queue */
- else
- {
- msgq->unlinked = true;
- }
+ if (!INODE_IS_MQUEUE(inode))
+ {
+ errcode = ENXIO;
+ goto errout_with_inode;
+ }
- ret = OK;
- }
+ /* Refuse to unlink the inode if it has children. I.e., if it is
+ * functioning as a directory and the directory is not empty.
+ */
- sched_unlock();
+ inode_semtake();
+ if (inode->i_child != NULL)
+ {
+ errcode = ENOTEMPTY;
+ goto errout_with_semaphore;
}
- return ret;
+ /* Remove the old inode from the tree. Because we hold a reference count
+ * on the inode, it will not be deleted now. This will set the
+ * FSNODEFLAG_DELETED bit in the inode flags.
+ */
+
+ ret = inode_remove(fullpath);
+
+ /* inode_remove() should always fail with -EBUSY because we hae a reference
+ * on the inode. -EBUSY means taht the inode was, indeed, unlinked but
+ * thatis could not be freed because there are refrences.
+ */
+
+ DEBUGASSERT(ret >= 0 || ret == -EBUSY);
+ UNUSED(ret);
+
+ /* Now we do not release the reference count in the normal way (by calling
+ * inode release. Rather, we call sem_close(). sem_close will decrement
+ * the reference count on the inode. But it will also free the message queue
+ * if that reference count decrements to zero. Since we hold one reference,
+ * that can only occur if the message queue is not in-use.
+ */
+
+ inode_semgive();
+ mq_release(inode);
+ return OK;
+
+errout_with_semaphore:
+ inode_semgive();
+errout_with_inode:
+ inode_release(inode);
+errout:
+ set_errno(errcode);
+ return ERROR;
}
-
diff --git a/nuttx/fs/mqueue/mqueue.h b/nuttx/fs/mqueue/mqueue.h
index e18302188..89d5ab700 100644
--- a/nuttx/fs/mqueue/mqueue.h
+++ b/nuttx/fs/mqueue/mqueue.h
@@ -45,6 +45,13 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_FS_MQUEUE_MPATH
+# define CONFIG_FS_MQUEUE_MPATH "/var/mqueue"
+#endif
+
+/* Sizes of things */
#define MAX_MQUEUE_PATH 64
@@ -68,6 +75,22 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
+/****************************************************************************
+ * Name: mq_close
+ *
+ * Description:
+ * Release a reference count on a message queue inode.
+ *
+ * Parameters:
+ * inode - The message queue inode
+ *
+ * Return Value:
+ * None
+ *
+ ****************************************************************************/
+
+void mq_release(FAR struct inode *inode);
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/nuttx/fs/semaphore/sem_unlink.c b/nuttx/fs/semaphore/sem_unlink.c
index 399614273..6b10b1a6b 100644
--- a/nuttx/fs/semaphore/sem_unlink.c
+++ b/nuttx/fs/semaphore/sem_unlink.c
@@ -99,7 +99,7 @@
int sem_unlink(FAR const char *name)
{
FAR struct inode *inode;
- FAR const char *relpath = NULL;
+ FAR const char *relpath = NULL;
char fullpath[MAX_SEMPATH];
int errcode;
int ret;