lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Thu, 21 Jun 2012 23:06:05 +0200
From:	Peter Zijlstra <peterz@...radead.org>
To:	Rik van Riel <riel@...hat.com>
Cc:	linux-mm@...ck.org, akpm@...ux-foundation.org, aarcange@...hat.com,
	minchan@...il.com, kosaki.motohiro@...il.com, andi@...stfloor.org,
	hannes@...xchg.org, mel@....ul.ie, linux-kernel@...r.kernel.org,
	Rik van Riel <riel@...riel.com>
Subject: Re: [PATCH -mm 2/7] mm: get unmapped area from VMA tree

On Mon, 2012-06-18 at 18:05 -0400, Rik van Riel wrote:
> +       /* Find the left-most free area of sufficient size. */


Just because there's nothing better than writing it yourself.. I tried
writing something that does the above. The below is the result, it
doesn't use your uncle functions and is clearly limited to two
traversals and thus trivially still O(log n). [ although I think with a
bit of effort you can prove the same for your version ].

---

static inline struct vm_area_struct *vma_of(struct rb_node *node)
{
        return container_of(node, struct vm_area_struct, vm_rb);
}

static inline unsigned long max_gap_of(struct rb_node *node)
{
        return vma_of(node)->free_gap;
}

static unsigned long gap_of(struct rb_node *node)
{
        struct vm_area_struct *vma = vma_of(node);

        if (!vma->vm_prev)
                return vma->vm_start;

        return vma->vm_start - vma->vm_prev->vm_end;
}

static bool node_better(struct rb_node *node, struct rb_node *best)
{
        if (!best)
                return true;

        return vma_of(node)->vm_start < vma_of(best)->vm_start;
}

unsigned long find_leftmost_gap(struct mm_struct *mm, unsigned long len)
{
        struct rb_node *node = mm->mm_rb.rb_node, *best = NULL, *tree = NULL;

        /*
         * Do a search for TASK_UNMAPPED_BASE + len, all nodes right of this
         * boundary should be considered. Path nodes are immediate candidates,
         * their right sub-tree is stored for later consideration in case
         * the immediate path doesn't yield a suitable node.
         */
        while (node) {
                if (vma_of(node)->vm_start - len >= TASK_UNMAPPED_BASE) {
                        /*
                         * If our node has a big enough hole, track it.
                         */
                        if (gap_of(node) > len && node_better(node, best))
                                best = node;

                        /*
                         * In case we flunk out on the path nodes, keep track 
                         * of the right sub-trees which have big enough holes.
                         */
                        if (node->rb_right && max_gap_of(node-rb_right) >= len &&
                            node_better(node->rb_right, tree))
                                tree = node->rb_right;

                        node = node->rb_left;
                        continue;
                }
                node = node->rb_right;
        }

        if (best)
                return vma_of(best)->vm_start - len;

        /*
         * Our stored subtree must be entirely right of TASK_UNMAPPED_BASE + len
         * so do a simple search for leftmost hole of appropriate size.
         */
        while (tree) {
                if (gap_of(tree) >= len && node_better(tree, best))
                        best = tree;

                if (tree->rb_left && max_gap_of(tree->rb_left) >= len) {
                        tree = tree->rb_left;
                        continue;
                }

                tree = tree->rb_right;
        }

        if (best)
                return vma_of(best)->vm_start - len;

        /*
         * Ok, so no path node, nor right sub-tree had a properly sized hole
         * we could use, use the rightmost address in the tree.
         */
        node = mm->mm_rb.rb_node;
        while (node && node->rb_right)
                node = node->rb_right;

        return max(vma_of(node)->vm_end, TASK_UNMAPPED_BASE);
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ