Fix reference count problem

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@258 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-05-27 19:10:40 +00:00
parent a0153a1ed2
commit 3f5d4be4a9
7 changed files with 73 additions and 17 deletions

View File

@ -152,5 +152,6 @@
* Added stat() to fs layer * Added stat() to fs layer
* Added stat() supported to FAT * Added stat() supported to FAT
* Fixed reference counting errors associated with mounted filesystems
* Started m68322 * Started m68322

View File

@ -586,6 +586,7 @@ Other memory:
* Added stat() to fs layer * Added stat() to fs layer
* Added stat() supported to FAT * Added stat() supported to FAT
* Fixed reference counting errors associated with mounted filesystems
* Started m68322 * Started m68322
</pre></ul> </pre></ul>

View File

@ -53,6 +53,9 @@
* Definitions * Definitions
****************************************************************************/ ****************************************************************************/
#define TEST_USE_STAT 1
#define TEST_SHOW_DIRECTORIES 1
/**************************************************************************** /****************************************************************************
* Private Types * Private Types
****************************************************************************/ ****************************************************************************/
@ -83,6 +86,7 @@ static char g_namebuffer[256];
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
#ifdef TEST_USE_STAT
static void show_stat(const char *path, struct stat *ps) static void show_stat(const char *path, struct stat *ps)
{ {
printf("%s stat:\n", path); printf("%s stat:\n", path);
@ -111,15 +115,17 @@ static void show_stat(const char *path, struct stat *ps)
printf("\tsize : %d (bytes)\n", ps->st_size); printf("\tsize : %d (bytes)\n", ps->st_size);
printf("\tblock size : %d (bytes)\n", ps->st_blksize); printf("\tblock size : %d (bytes)\n", ps->st_blksize);
printf("\tsize : %d (blocks)\n", ps->st_blocks); printf("\tsize : %d (blocks)\n", ps->st_blocks);
printf("\taccess time : %d (blocks)\n", ps->st_atime); printf("\taccess time : %d\n", ps->st_atime);
printf("\tmodify time : %d (blocks)\n", ps->st_mtime); printf("\tmodify time : %d\n", ps->st_mtime);
printf("\tchange time : %d (blocks)\n", ps->st_ctime); printf("\tchange time : %d\n", ps->st_ctime);
} }
#endif
/**************************************************************************** /****************************************************************************
* Name: show_directories * Name: show_directories
****************************************************************************/ ****************************************************************************/
#ifdef TEST_SHOW_DIRECTORIES
static void show_directories(const char *path, int indent) static void show_directories(const char *path, int indent)
{ {
DIR *dirp; DIR *dirp;
@ -157,6 +163,9 @@ static void show_directories(const char *path, int indent)
closedir(dirp); closedir(dirp);
} }
#else
# define show_directories(p,i)
#endif
/**************************************************************************** /****************************************************************************
* Name: fail_read_open * Name: fail_read_open
@ -446,6 +455,7 @@ static void succeed_rename(const char *oldpath, const char *newpath)
* Name: fail_stat * Name: fail_stat
****************************************************************************/ ****************************************************************************/
#ifdef TEST_USE_STAT
static void fail_stat(const char *path, int expectederror) static void fail_stat(const char *path, int expectederror)
{ {
struct stat buf; struct stat buf;
@ -469,11 +479,15 @@ static void fail_stat(const char *path, int expectederror)
g_nerrors++; g_nerrors++;
} }
} }
#else
# define fail_stat(p,e);
#endif
/**************************************************************************** /****************************************************************************
* Name: succeed_stat * Name: succeed_stat
****************************************************************************/ ****************************************************************************/
#ifdef TEST_USE_STAT
static void succeed_stat(const char *path) static void succeed_stat(const char *path)
{ {
struct stat buf; struct stat buf;
@ -494,6 +508,9 @@ static void succeed_stat(const char *path)
show_stat(path, &buf); show_stat(path, &buf);
} }
} }
#else
#define succeed_stat(p)
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions

View File

@ -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, static int fat_bind(FAR struct inode *blkdriver, const void *data,
void **handle); 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_unlink(struct inode *mountpt, const char *relpath);
static int fat_mkdir(struct inode *mountpt, const char *relpath, static int fat_mkdir(struct inode *mountpt, const char *relpath,
mode_t mode); 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; struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle;
int ret; int ret;
@ -1551,9 +1551,16 @@ static int fat_unbind(void *handle)
(void)inode->u.i_bops->close(inode); (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;
}
} }
} }

View File

@ -136,6 +136,7 @@ STATUS inode_remove(const char *path)
*/ */
node->i_flags |= FSNODEFLAG_DELETED; node->i_flags |= FSNODEFLAG_DELETED;
return -EBUSY;
} }
else else
{ {
@ -149,5 +150,5 @@ STATUS inode_remove(const char *path)
/* The node does not exist or it has references */ /* The node does not exist or it has references */
return ERROR; return -ENOENT;
} }

View File

@ -92,7 +92,8 @@
int umount(const char *target) int umount(const char *target)
{ {
FAR struct inode *mountpt_inode; FAR struct inode *mountpt_inode;
int errcode; FAR struct inode *blkdrvr_inode = NULL;
int errcode = OK;
int status; int status;
/* Verify required pointer arguments */ /* Verify required pointer arguments */
@ -138,7 +139,7 @@ int umount(const char *target)
*/ */
inode_semtake(); /* Hold the semaphore through the unbind logic */ 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) if (status < 0)
{ {
/* The inode is unhappy with the blkdrvr for some reason */ /* The inode is unhappy with the blkdrvr for some reason */
@ -156,15 +157,39 @@ int umount(const char *target)
mountpt_inode->i_private = NULL; mountpt_inode->i_private = NULL;
/* Remove the 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_semgive(); /* Need to release for inode_release */
inode_release(mountpt_inode);
inode_semtake(); /* Need to hold for inode_remove */
status = inode_remove(target); status = inode_remove(target);
inode_semgive(); 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 */ /* A lot of goto's! But they make the error handling much simpler */
@ -172,6 +197,10 @@ int umount(const char *target)
inode_semgive(); inode_semgive();
errout_with_mountpt: errout_with_mountpt:
inode_release(mountpt_inode); inode_release(mountpt_inode);
if (blkdrvr_inode)
{
inode_release(blkdrvr_inode);
}
errout: errout:
*get_errno_ptr() = errcode; *get_errno_ptr() = errcode;
return ERROR; return ERROR;

View File

@ -157,7 +157,7 @@ struct mountpt_operations
/* General volume-related mountpoint operations: */ /* General volume-related mountpoint operations: */
int (*bind)(FAR struct inode *blkdriver, const void *data, void **handle); int (*bind)(FAR struct inode *blkdriver, const void *data, void **handle);
int (*unbind)(void *handle); int (*unbind)(void *handle, FAR struct inode **blkdriver);
int (*unlink)(struct inode *mountpt, const char *relpath); int (*unlink)(struct inode *mountpt, const char *relpath);
int (*mkdir)(struct inode *mountpt, const char *relpath, mode_t mode); int (*mkdir)(struct inode *mountpt, const char *relpath, mode_t mode);