summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-27 19:10:40 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-27 19:10:40 +0000
commit70616853600900cb04a615ac620792553dbe1c7d (patch)
treefa1bff7d0b322944b98459c80ffe9bd8f2fa3ba9 /nuttx/fs
parent9f53bc85a64da31a21ede71a112f2f6c0486417b (diff)
downloadpx4-nuttx-70616853600900cb04a615ac620792553dbe1c7d.tar.gz
px4-nuttx-70616853600900cb04a615ac620792553dbe1c7d.tar.bz2
px4-nuttx-70616853600900cb04a615ac620792553dbe1c7d.zip
Fix reference count problem
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@258 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/fs_fat32.c15
-rw-r--r--nuttx/fs/fs_inoderemove.c3
-rw-r--r--nuttx/fs/fs_umount.c45
3 files changed, 50 insertions, 13 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index e8677e1be..098353cd5 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -91,7 +91,7 @@ static int fat_rewinddir(struct inode *mountpt, struct internal_dir_s *dir);
static int fat_bind(FAR struct inode *blkdriver, const void *data,
void **handle);
-static int fat_unbind(void *handle);
+static int fat_unbind(void *handle, FAR struct inode **blkdriver);
static int fat_unlink(struct inode *mountpt, const char *relpath);
static int fat_mkdir(struct inode *mountpt, const char *relpath,
mode_t mode);
@@ -1517,7 +1517,7 @@ static int fat_bind(FAR struct inode *blkdriver, const void *data,
*
****************************************************************************/
-static int fat_unbind(void *handle)
+static int fat_unbind(void *handle, FAR struct inode **blkdriver)
{
struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle;
int ret;
@@ -1551,9 +1551,16 @@ static int fat_unbind(void *handle)
(void)inode->u.i_bops->close(inode);
}
- /* Release our reference to the block driver */
+ /* We hold a reference to the block driver but should
+ * not but mucking with inodes in this context. So, we will just return
+ * our contained reference to the block driver inode and let the umount
+ * logic dispose of it.
+ */
- inode_release(inode);
+ if (blkdriver)
+ {
+ *blkdriver = inode;
+ }
}
}
diff --git a/nuttx/fs/fs_inoderemove.c b/nuttx/fs/fs_inoderemove.c
index 633222567..c227cfacc 100644
--- a/nuttx/fs/fs_inoderemove.c
+++ b/nuttx/fs/fs_inoderemove.c
@@ -136,6 +136,7 @@ STATUS inode_remove(const char *path)
*/
node->i_flags |= FSNODEFLAG_DELETED;
+ return -EBUSY;
}
else
{
@@ -149,5 +150,5 @@ STATUS inode_remove(const char *path)
/* The node does not exist or it has references */
- return ERROR;
+ return -ENOENT;
}
diff --git a/nuttx/fs/fs_umount.c b/nuttx/fs/fs_umount.c
index 347719982..d6a6351f4 100644
--- a/nuttx/fs/fs_umount.c
+++ b/nuttx/fs/fs_umount.c
@@ -92,7 +92,8 @@
int umount(const char *target)
{
FAR struct inode *mountpt_inode;
- int errcode;
+ FAR struct inode *blkdrvr_inode = NULL;
+ int errcode = OK;
int status;
/* Verify required pointer arguments */
@@ -138,7 +139,7 @@ int umount(const char *target)
*/
inode_semtake(); /* Hold the semaphore through the unbind logic */
- status = mountpt_inode->u.i_mops->unbind( mountpt_inode->i_private );
+ status = mountpt_inode->u.i_mops->unbind( mountpt_inode->i_private, &blkdrvr_inode);
if (status < 0)
{
/* The inode is unhappy with the blkdrvr for some reason */
@@ -156,15 +157,39 @@ int umount(const char *target)
mountpt_inode->i_private = NULL;
- /* Remove the inode */
-
- inode_semgive(); /* Need to release for inode_release */
- inode_release(mountpt_inode);
+ /* 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)
+ */
- inode_semtake(); /* Need to hold for inode_remove */
status = inode_remove(target);
inode_semgive();
- return status;
+
+ /* The return value of -EBUSY is normal (in fact, it should
+ * not be OK)
+ */
+
+ if (status != OK && status != -EBUSY)
+ {
+ errcode = -status;
+ 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 */
+
+ if (blkdrvr_inode)
+ {
+ inode_release(blkdrvr_inode);
+ }
+
+ return OK;
/* A lot of goto's! But they make the error handling much simpler */
@@ -172,6 +197,10 @@ int umount(const char *target)
inode_semgive();
errout_with_mountpt:
inode_release(mountpt_inode);
+ if (blkdrvr_inode)
+ {
+ inode_release(blkdrvr_inode);
+ }
errout:
*get_errno_ptr() = errcode;
return ERROR;