diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index 9921bbe6fef..5d9030c0e4c 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -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 diff --git a/fs/mount/fs_umount2.c b/fs/mount/fs_umount2.c index 1611bb6dcae..796d7e37b24 100644 --- a/fs/mount/fs_umount2.c +++ b/fs/mount/fs_umount2.c @@ -41,6 +41,8 @@ #include #include +#include + #include #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 */