FS: Add the ability to mount a file system on top of en existing node in the psuedo-file system

This commit is contained in:
Gregory Nutt
2015-06-11 10:10:25 -06:00
parent da0ef76237
commit 4607a8435f
2 changed files with 83 additions and 33 deletions
+42 -13
View File
@@ -266,25 +266,54 @@ int mount(FAR const char *source, FAR const char *target,
goto errout;
}
inode_semtake();
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* Check if the inode already exists */
mountpt_inode = inode_find(target, NULL);
if (mountpt_inode != NULL)
{
/* Yes... Is is a directory node (i.e., not a driver or other special
* node.
*/
if (INODE_IS_SPECIAL(mountpt_inode))
{
fdbg("ERROR: target %s exists and is a special nodes\n", target);
errcode = -ENOTDIR;
goto errout_with_semaphore;
}
/* Successfully found. The reference count on the inode has been
* incremented.
*/
DEBUGASSERT(mountpt_inode->u.i_mops == NULL);
}
else
#endif
/* Insert a dummy node -- we need to hold the inode semaphore
* to do this because we will have a momentarily bad structure.
*/
inode_semtake();
ret = inode_reserve(target, &mountpt_inode);
if (ret < 0)
{
/* inode_reserve can fail for a couple of reasons, but the most likely
* one is that the inode already exists. inode_reserve may return:
*
* -EINVAL - 'path' is invalid for this operation
* -EEXIST - An inode already exists at 'path'
* -ENOMEM - Failed to allocate in-memory resources for the operation
*/
ret = inode_reserve(target, &mountpt_inode);
if (ret < 0)
{
/* inode_reserve can fail for a couple of reasons, but the most likely
* one is that the inode already exists. inode_reserve may return:
*
* -EINVAL - 'path' is invalid for this operation
* -EEXIST - An inode already exists at 'path'
* -ENOMEM - Failed to allocate in-memory resources for the operation
*/
fdbg("ERROR: Failed to reserve inode\n");
errcode = -ret;
goto errout_with_semaphore;
fdbg("ERROR: Failed to reserve inode for target %s\n", target);
errcode = -ret;
goto errout_with_semaphore;
}
}
/* Bind the block driver to an instance of the file system. The file
+41 -20
View File
@@ -41,6 +41,8 @@
#include <sys/mount.h>
#include <errno.h>
#include <assert.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
@@ -152,34 +154,53 @@ int umount2(FAR const char *target, unsigned int flags)
goto errout_with_semaphore;
}
/* Successfully unbound */
/* Successfully unbound. Convert the mountpoint inode to regular
* pseudo-file inode.
*/
mountpt_inode->i_flags &= ~FSNODEFLAG_TYPE_MASK;
mountpt_inode->i_private = NULL;
mountpt_inode->u.i_mops = NULL;
/* Successfully unbound, remove the mountpoint inode from
* the inode tree. The inode will not be deleted yet because
* there is still at least reference on it (from the mount)
*/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* If the node has children, then do not delete it. */
ret = inode_remove(target);
inode_semgive();
/* The return value of -EBUSY is normal (in fact, it should
* not be OK)
*/
if (ret != OK && ret != -EBUSY)
if (mountpt_inode->i_child != NULL)
{
errcode = -ret;
goto errout_with_mountpt;
/* Just decrement the reference count (without deleting it) */
DEBUGASSERT(mountpt_inode->i_crefs > 0);
mountpt_inode->i_crefs--;
}
else
#endif
{
/* Remove the mountpoint inode from the inode tree. The inode will
* not be deleted yet because there is still at least reference on
* it (from the mount)
*/
/* Release the mountpoint inode and any block driver inode
* returned by the file system unbind above. This should cause
* the inode to be deleted (unless there are other references)
*/
ret = inode_remove(target);
inode_semgive();
inode_release(mountpt_inode);
/* The return value of -EBUSY is normal (in fact, it should
* not be OK)
*/
if (ret != OK && ret != -EBUSY)
{
errcode = -ret;
goto errout_with_mountpt;
}
/* Release the mountpoint inode and any block driver inode
* returned by the file system unbind above. This should cause
* the inode to be deleted (unless there are other references)
*/
inode_release(mountpt_inode);
}
/* Did the unbind method return a contained block driver */