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:
kib 2019-10-03 19:55:05 +00:00
parent 175f92d15a
commit e9ef39b7bd

View File

@ -1147,8 +1147,9 @@ static int
tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node,
struct uio *uio)
{
int error;
struct tmpfs_node *parent;
struct dirent dent;
int error;
TMPFS_VALIDATE_DIR(node);
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.
*/
TMPFS_ASSERT_LOCKED(node);
if (node->tn_dir.tn_parent == NULL)
parent = node->tn_dir.tn_parent;
if (parent == NULL)
return (ENOENT);
TMPFS_NODE_LOCK(node->tn_dir.tn_parent);
dent.d_fileno = node->tn_dir.tn_parent->tn_id;
TMPFS_NODE_UNLOCK(node->tn_dir.tn_parent);
TMPFS_NODE_LOCK(parent);
dent.d_fileno = parent->tn_id;
TMPFS_NODE_UNLOCK(parent);
dent.d_type = DT_DIR;
dent.d_namlen = 2;