diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-27 19:10:40 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-27 19:10:40 +0000 |
commit | 70616853600900cb04a615ac620792553dbe1c7d (patch) | |
tree | fa1bff7d0b322944b98459c80ffe9bd8f2fa3ba9 /nuttx/fs | |
parent | 9f53bc85a64da31a21ede71a112f2f6c0486417b (diff) | |
download | px4-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.c | 15 | ||||
-rw-r--r-- | nuttx/fs/fs_inoderemove.c | 3 | ||||
-rw-r--r-- | nuttx/fs/fs_umount.c | 45 |
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; |