diff --git a/ChangeLog b/ChangeLog index 485db96b22bf16003c340f163bef68e677e1d0fe..e40f8dc3d37042da1b1ac509c1de38d3f32c1c17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -181,5 +181,6 @@ * tools/Makefile.mkconfig: Under Cygwin, executable has a different name * tools/mkdeps.sh & arch/arm/src/Makefile: Corrected a problem makeing dependencies * tools/zipme.sh: Force directory name to be nuttx-xx.yy.zz + * fs/fs_opendir.c: Correct errors in semaphore usage that can cause deadlock. * Started m68322 diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 3d765a86794ed54764e05483e3ff483db130a892..9e4ca3b7d6da760dfe141aaac54648ee977a1e4f 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -616,6 +616,7 @@ Other memory: * tools/Makefile.mkconfig: Under Cygwin, executable has a different name * tools/mkdeps.sh & arch/arm/src/Makefile: Corrected a problem makeing dependencies * tools/zipme.sh: Force directory name to be nuttx-xx.yy.zz + * fs/fs_opendir.c: Correct errors in semaphore usage that can cause deadlock. * Started m68322 </pre></ul> diff --git a/fs/fs_opendir.c b/fs/fs_opendir.c index 6890de1ea25f8a5c4a6b1a972fa7cbfc3a78afe8..3fa32fc1ed4a1a8873444f2e694a7e65b7e67433 100644 --- a/fs/fs_opendir.c +++ b/fs/fs_opendir.c @@ -94,9 +94,9 @@ FAR DIR *opendir(const char *path) * request for the root inode. */ + inode_semtake(); if (!path || *path == 0 || strcmp(path, "/") == 0) { - inode_semgive(); inode = root_inode; isroot = TRUE; } @@ -106,12 +106,12 @@ FAR DIR *opendir(const char *path) if (*path != '/') { - return NULL; + ret = -ENOTDIR; + goto errout_with_semaphore; } /* Find the node matching the path. */ - inode_semtake(); inode = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, &relpath); } @@ -166,9 +166,11 @@ FAR DIR *opendir(const char *path) goto errout_with_direntry; } - /* Take reference to the mountpoint inode (fd_root) */ + /* Take reference to the mountpoint inode (fd_root). Note that we do + * not use inode_addref() because we already hold the tree semaphore. + */ - inode_addref(inode); + inode->i_crefs++; /* Perform the opendir() operation */ @@ -199,10 +201,12 @@ FAR DIR *opendir(const char *path) /* It looks we have a valid psuedo-filesystem node. Take two references * on the inode -- one for the parent (fd_root) and one for the child (fd_next). + * Note that we do not call inode_addref because we are holding + * the tree semaphore and that would result in deadlock. */ - inode_addref(inode); - inode_addref(inode); + inode->i_crefs++; + inode->i_crefs++; dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */ /* Flag the inode as belonging to the psuedo-filesystem */