tmpfs_readdir(): unlock the locked node.
During readdir() we guarantee that the tn_dir.tn_parent does not go away, but it might be replaced by a parallel rename. Read tn_parent only once, then use the cached value. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
175f92d15a
commit
e9ef39b7bd
@ -1147,8 +1147,9 @@ static int
|
|||||||
tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
||||||
struct uio *uio)
|
struct uio *uio)
|
||||||
{
|
{
|
||||||
int error;
|
struct tmpfs_node *parent;
|
||||||
struct dirent dent;
|
struct dirent dent;
|
||||||
|
int error;
|
||||||
|
|
||||||
TMPFS_VALIDATE_DIR(node);
|
TMPFS_VALIDATE_DIR(node);
|
||||||
MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT);
|
MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT);
|
||||||
@ -1157,12 +1158,13 @@ tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
|
|||||||
* Return ENOENT if the current node is already removed.
|
* Return ENOENT if the current node is already removed.
|
||||||
*/
|
*/
|
||||||
TMPFS_ASSERT_LOCKED(node);
|
TMPFS_ASSERT_LOCKED(node);
|
||||||
if (node->tn_dir.tn_parent == NULL)
|
parent = node->tn_dir.tn_parent;
|
||||||
|
if (parent == NULL)
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
|
|
||||||
TMPFS_NODE_LOCK(node->tn_dir.tn_parent);
|
TMPFS_NODE_LOCK(parent);
|
||||||
dent.d_fileno = node->tn_dir.tn_parent->tn_id;
|
dent.d_fileno = parent->tn_id;
|
||||||
TMPFS_NODE_UNLOCK(node->tn_dir.tn_parent);
|
TMPFS_NODE_UNLOCK(parent);
|
||||||
|
|
||||||
dent.d_type = DT_DIR;
|
dent.d_type = DT_DIR;
|
||||||
dent.d_namlen = 2;
|
dent.d_namlen = 2;
|
||||||
|
Loading…
Reference in New Issue
Block a user