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