The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fd8c98a52f7178d8071cf201f2eb14f00d904a7d

commit fd8c98a52f7178d8071cf201f2eb14f00d904a7d
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2023-03-16 11:31:06 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
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

Reply via email to