smmu学习笔记之iova的insert and find

iova 通过iova_insert_rbtree来将一个iova插入到rb tree
例如我们在调用    
static struct iova *
__insert_new_range(struct iova_domain *iovad,
    unsigned long pfn_lo, unsigned long pfn_hi)
{
    struct iova *iova;

    iova = alloc_and_init_iova(pfn_lo, pfn_hi);
    if (iova)
        iova_insert_rbtree(&iovad->rbroot, iova);

    return iova;
}
__insert_new_range 中首先通过alloc_and_init_iova 申请一个iova结构体,将pfn的最小值和最大值赋给iova
alloc_and_init_iova(unsigned long pfn_lo, unsigned long pfn_hi)
{
    struct iova *iova;

    iova = alloc_iova_mem();
    if (iova) {
        iova->pfn_lo = pfn_lo;
        iova->pfn_hi = pfn_hi;
    }

    return iova;
}
可以看到alloc_and_init_iova 是通过alloc_iova_mem 申请一个iova,然后将pfn_lo和pfn_hi 分别赋给iova
最后调用iova_insert_rbtree 来插入到rb tree

static void
iova_insert_rbtree(struct rb_root *root, struct iova *iova)
{
    struct rb_node **new = &(root->rb_node), *parent = NULL;
    /* Figure out where to put new node */
    while (*new) {
        struct iova *this = container_of(*new, struct iova, node);

        parent = *new;

        if (iova->pfn_lo < this->pfn_lo)
            new = &((*new)->rb_left);
        else if (iova->pfn_lo > this->pfn_lo)
            new = &((*new)->rb_right);
        else
            BUG(); /* this should not happen */
    }
    /* Add new node and rebalance tree. */
    rb_link_node(&iova->node, parent, new);
    rb_insert_color(&iova->node, root);
}
可见在iova_insert_rbtree 中是根据pfn_lo 来遍历rb tree的,当new为null时,也就是当前是符合pfn_lo的叶子节点是,调用rb_link_node 将这个new节点插入,这个典型的rb tree 查找.

通过find_iova 来查找一个
struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
{
    unsigned long flags;
    struct iova *iova;

    /* Take the lock so that no other thread is manipulating the rbtree */
    spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
    iova = private_find_iova(iovad, pfn);
    spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
    return iova;
}
继续调用
static struct iova *
private_find_iova(struct iova_domain *iovad, unsigned long pfn)
{
    struct rb_node *node = iovad->rbroot.rb_node;

    assert_spin_locked(&iovad->iova_rbtree_lock);

    while (node) {
        struct iova *iova = container_of(node, struct iova, node);

        /* If pfn falls within iova's range, return iova */
        if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
            return iova;
        }

        if (pfn < iova->pfn_lo)
            node = node->rb_left;
        else if (pfn > iova->pfn_lo)
            node = node->rb_right;
    }

    return NULL;
}

可以看到private_find_iova 也是根据pfn来找到等于pfn的rb节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值