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/fs_umount.c | |
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/fs_umount.c')
-rw-r--r-- | nuttx/fs/fs_umount.c | 45 |
1 files changed, 37 insertions, 8 deletions
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; |