/*
         * The depth this cgroup is at.  The root is at depth zero and each
         * step down the hierarchy increments the level.  This along with
-        * ancestor_ids[] can determine whether a given cgroup is a
+        * ancestors[] can determine whether a given cgroup is a
         * descendant of another without traversing the hierarchy.
         */
        int level;
        /* Used to store internal freezer state */
        struct cgroup_freezer_state freezer;
 
-       /* ids of the ancestors at each level including self */
-       u64 ancestor_ids[];
+       /* All ancestors including self */
+       struct cgroup *ancestors[];
 };
 
 /*
        /* Unique id for this hierarchy. */
        int hierarchy_id;
 
-       /* The root cgroup.  Root is destroyed on its release. */
+       /*
+        * The root cgroup. The containing cgroup_root will be destroyed on its
+        * release. cgrp->ancestors[0] will be used overflowing into the
+        * following field. cgrp_ancestor_storage must immediately follow.
+        */
        struct cgroup cgrp;
 
-       /* for cgrp->ancestor_ids[0] */
-       u64 cgrp_ancestor_id_storage;
+       /* must follow cgrp for cgrp->ancestors[0], see above */
+       struct cgroup *cgrp_ancestor_storage;
 
        /* Number of cgroups in the hierarchy, used only for /proc/cgroups */
        atomic_t nr_cgrps;
 
 {
        if (cgrp->root != ancestor->root || cgrp->level < ancestor->level)
                return false;
-       return cgrp->ancestor_ids[ancestor->level] == cgroup_id(ancestor);
+       return cgrp->ancestors[ancestor->level] == ancestor;
 }
 
 /**
 static inline struct cgroup *cgroup_ancestor(struct cgroup *cgrp,
                                             int ancestor_level)
 {
-       if (cgrp->level < ancestor_level)
+       if (ancestor_level < 0 || ancestor_level > cgrp->level)
                return NULL;
-       while (cgrp && cgrp->level > ancestor_level)
-               cgrp = cgroup_parent(cgrp);
-       return cgrp;
+       return cgrp->ancestors[ancestor_level];
 }
 
 /**
 
        }
        root_cgrp->kn = kernfs_root_to_node(root->kf_root);
        WARN_ON_ONCE(cgroup_ino(root_cgrp) != 1);
-       root_cgrp->ancestor_ids[0] = cgroup_id(root_cgrp);
+       root_cgrp->ancestors[0] = root_cgrp;
 
        ret = css_populate_dir(&root_cgrp->self);
        if (ret)
        int ret;
 
        /* allocate the cgroup and its ID, 0 is reserved for the root */
-       cgrp = kzalloc(struct_size(cgrp, ancestor_ids, (level + 1)),
-                      GFP_KERNEL);
+       cgrp = kzalloc(struct_size(cgrp, ancestors, (level + 1)), GFP_KERNEL);
        if (!cgrp)
                return ERR_PTR(-ENOMEM);
 
 
        spin_lock_irq(&css_set_lock);
        for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
-               cgrp->ancestor_ids[tcgrp->level] = cgroup_id(tcgrp);
+               cgrp->ancestors[tcgrp->level] = tcgrp;
 
                if (tcgrp != cgrp) {
                        tcgrp->nr_descendants++;
 
 nft_sock_get_eval_cgroupv2(u32 *dest, struct sock *sk, const struct nft_pktinfo *pkt, u32 level)
 {
        struct cgroup *cgrp;
+       u64 cgid;
 
        if (!sk_fullsock(sk))
                return false;
 
-       cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
-       if (level > cgrp->level)
+       cgrp = cgroup_ancestor(sock_cgroup_ptr(&sk->sk_cgrp_data), level);
+       if (!cgrp)
                return false;
 
-       memcpy(dest, &cgrp->ancestor_ids[level], sizeof(u64));
-
+       cgid = cgroup_id(cgrp);
+       memcpy(dest, &cgid, sizeof(u64));
        return true;
 }
 #endif
 
                        break;
 
                // convert cgroup-id to a map index
-               cgrp_id = BPF_CORE_READ(cgrp, ancestor_ids[i]);
+               cgrp_id = BPF_CORE_READ(cgrp, ancestors[i], kn, id);
                elem = bpf_map_lookup_elem(&cgrp_idx, &cgrp_id);
                if (!elem)
                        continue;