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:
parent
a0153a1ed2
commit
3f5d4be4a9
@ -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
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user