git: fd8c98a52f71 - main - tarfs: Correctly track link count.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 16 Mar 2023 12:19:59 UTC
The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=fd8c98a52f7178d8071cf201f2eb14f00d904a7d commit fd8c98a52f7178d8071cf201f2eb14f00d904a7d Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2023-03-16 11:31:06 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2023-03-16 11:31:22 +0000 tarfs: Correctly track link count. Sponsored by: Juniper Networks, Inc. Sponsored by: Klara, Inc. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D39019 --- sys/fs/tarfs/tarfs_subr.c | 13 +++++++++++++ sys/fs/tarfs/tarfs_vfsops.c | 7 +++---- tests/sys/fs/tarfs/tarfs_test.sh | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/sys/fs/tarfs/tarfs_subr.c b/sys/fs/tarfs/tarfs_subr.c index 0cba43a8c21b..6aa7eaedb773 100644 --- a/sys/fs/tarfs/tarfs_subr.c +++ b/sys/fs/tarfs/tarfs_subr.c @@ -384,6 +384,18 @@ tarfs_free_node(struct tarfs_node *tnp) tmp = tnp->tmp; switch (tnp->type) { + case VREG: + if (tnp->nlink-- > 1) + return; + if (tnp->other != NULL) + tarfs_free_node(tnp->other); + break; + case VDIR: + if (tnp->nlink-- > 2) + return; + if (tnp->parent != NULL && tnp->parent != tnp) + tarfs_free_node(tnp->parent); + break; case VLNK: if (tnp->link.name) free(tnp->link.name, M_TARFSNAME); @@ -397,6 +409,7 @@ tarfs_free_node(struct tarfs_node *tnp) free(tnp->blk, M_TARFSBLK); if (tnp->ino >= TARFS_MININO) free_unr(tmp->ino_unr, tnp->ino); + TAILQ_REMOVE(&tmp->allnodes, tnp, entries); free(tnp, M_TARFSNODE); tmp->nfiles--; } diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c index 03dc598f4b69..9d7297eb9d73 100644 --- a/sys/fs/tarfs/tarfs_vfsops.c +++ b/sys/fs/tarfs/tarfs_vfsops.c @@ -406,16 +406,14 @@ static void tarfs_free_mount(struct tarfs_mount *tmp) { struct mount *mp; - struct tarfs_node *tnp; + struct tarfs_node *tnp, *tnp_next; MPASS(tmp != NULL); TARFS_DPF(ALLOC, "%s: Freeing mount structure %p\n", __func__, tmp); TARFS_DPF(ALLOC, "%s: freeing tarfs_node structures\n", __func__); - while (!TAILQ_EMPTY(&tmp->allnodes)) { - tnp = TAILQ_FIRST(&tmp->allnodes); - TAILQ_REMOVE(&tmp->allnodes, tnp, entries); + TAILQ_FOREACH_SAFE(tnp, &tmp->allnodes, entries, tnp_next) { tarfs_free_node(tnp); } @@ -744,6 +742,7 @@ again: error = EINVAL; goto bad; } + tnp->other->nlink++; break; case TAR_TYPE_SYMLINK: if (link == NULL) { diff --git a/tests/sys/fs/tarfs/tarfs_test.sh b/tests/sys/fs/tarfs/tarfs_test.sh index 6e44a8081cb2..50d98f857e06 100644 --- a/tests/sys/fs/tarfs/tarfs_test.sh +++ b/tests/sys/fs/tarfs/tarfs_test.sh @@ -59,6 +59,8 @@ tarfs_basic_body() { atf_check_equal "$(stat -f%d,%i "${mnt}"/sparse_file)" "$(stat -L -f%d,%i "${mnt}"/short_link)" atf_check_equal "$(stat -f%d,%i "${mnt}"/sparse_file)" "$(stat -L -f%d,%i "${mnt}"/long_link)" atf_check_equal "$(sha256 -q "${mnt}"/sparse_file)" ${sum} + atf_check_equal "$(stat -f%l "${mnt}"/sparse_file)" 2 + atf_check_equal "$(stat -f%l "${mnt}"/hard_link)" 2 } tarfs_basic_cleanup() { umount "${mnt}" || true