diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-09-29 15:48:52 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-09-29 15:48:52 -0600 |
commit | e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7 (patch) | |
tree | f7b007c79502fd72466690bd1a67de0e42b6df20 | |
parent | 43b185f9cb9da1bde9caa42ad9daede6d7c10b4d (diff) | |
download | px4-nuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.tar.gz px4-nuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.tar.bz2 px4-nuttx-e66fe204e0f9eed047fccdbd7b7fd31f264a2bc7.zip |
Completes the re-implementation of mq_unlink()
-rw-r--r-- | nuttx/fs/mqueue/mq_close.c | 84 | ||||
-rw-r--r-- | nuttx/fs/mqueue/mq_open.c | 7 | ||||
-rw-r--r-- | nuttx/fs/mqueue/mq_unlink.c | 118 | ||||
-rw-r--r-- | nuttx/fs/mqueue/mqueue.h | 23 | ||||
-rw-r--r-- | nuttx/fs/semaphore/sem_unlink.c | 2 |
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; |