ubi 下ubi_ltree_entry获取与初始化过程

在ubi中,每次写读一个volume是,都会对当期的这个volume进加锁。用到的就是rw_semaphore。关于读写锁可以查看一下网上别人写的东西。


获取这个锁的函数(这里我主要以write为例来说明)是:

/**
 * leb_write_lock - lock logical eraseblock for writing.
 * @ubi: UBI device description object
 * @vol_id: volume ID
 * @lnum: logical eraseblock number
 *
 * This function locks a logical eraseblock for writing. Returns zero in case
 * of success and a negative error code in case of failure.
 */
static int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum)
{
	<span style="color:#CC0000;">struct ubi_ltree_entry *le;</span>//我们看到在这里,是定义了这样的一个结构体指针。

	le = ltree_add_entry(ubi, vol_id, lnum);//在这个函数里会进行对mutex的初始化操作。
	if (IS_ERR(le))
		return PTR_ERR(le);
	down_write(&le->mutex);//获取这个锁。
	return 0;
}

/**
 * struct ubi_ltree_entry - an entry in the lock tree.
 * @rb: links RB-tree nodes
 * @vol_id: volume ID of the locked logical eraseblock
 * @lnum: locked logical eraseblock number
 * @users: how many tasks are using this logical eraseblock or wait for it
 * @mutex: read/write mutex to implement read/write access serialization to
 *         the (@vol_id, @lnum) logical eraseblock
 *
 * This data structure is used in the EBA sub-system to implement per-LEB
 * locking. When a logical eraseblock is being locked - corresponding
 * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree).
 * See EBA sub-system for details.  //从这段话可以看出,在lock这个volume时,才把这样的一个结构体insert到lock tree.
 */
struct ubi_ltree_entry {
	struct rb_node rb;
	int vol_id;//对应的volume id 
	int lnum;//这个锁对应的lnum
	int users;
	struct rw_semaphore mutex;
};
/*
 * the rw-semaphore definition
 * -<span style="color:#FF0000;"> if count is 0 then there are no active readers or writers</span>
 * - if count is +ve then that is the number of active readers
 * <span style="color:#CC0000;">- if count is -1 then there is one active writer</span>
 * - if wait_list is not empty, then there are processes waiting for the semaphore
 */
struct rw_semaphore {
	__s32			count;//在ubi中,通过debug,这个值,在初始时完后是0。同时在获取一次后是-1.
	raw_spinlock_t		wait_lock;
	struct list_head	wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map dep_map;
#endif
};

通过上面的代码,其实主要的初始化不是在attach的时候,而是在你真正要lock这个volume的时候。



/**
 * ltree_add_entry - add new entry to the lock tree.
 * @ubi: UBI device description object
 * @vol_id: volume ID
 * @lnum: logical eraseblock number
 *
 * This function adds new entry for logical eraseblock (@vol_id, @lnum) to the
 * lock tree. If such entry is already there, its usage counter is increased.
 * Returns pointer to the lock tree entry or %-ENOMEM if memory allocation
 * failed.
 */
static struct ubi_ltree_entry *ltree_add_entry(struct ubi_device *ubi,
					       int vol_id, int lnum)
{
	struct ubi_ltree_entry *le, *le1, *le_free;

	le = kmalloc(sizeof(struct ubi_ltree_entry), GFP_NOFS);
	if (!le)
		return ERR_PTR(-ENOMEM);

	le->users = 0;
	init_rwsem(&le->mutex);//调用这个函数对rw mutex进行初始化。
	le->vol_id = vol_id;
	le->lnum = lnum;

	spin_lock(&ubi->ltree_lock);
	le1 = ltree_lookup(ubi, vol_id, lnum);  //查看这个对应 volume id 和lnum的mutex有没有已经被锁住。

	if (le1) {
		/*
		 * This logical eraseblock is already locked. The newly
		 * allocated lock entry is not needed.
		 */
		le_free = le;
		le = le1;
	} else {  //下面的操作就不用看了,就是把这个锁加入到lock tree中去。
        struct rb_node **p, *parent = NULL;

        /*
         * No lock entry, add the newly allocated one to the
         * @ubi->ltree RB-tree.
         */
        le_free = NULL;

        p = &ubi->ltree.rb_node;
        while (*p) {
            parent = *p;
            le1 = rb_entry(parent, struct ubi_ltree_entry, rb);

            if (vol_id < le1->vol_id)
                p = &(*p)->rb_left;
            else if (vol_id > le1->vol_id)
                p = &(*p)->rb_right;
            else {
                ubi_assert(lnum != le1->lnum);
                if (lnum < le1->lnum)
                    p = &(*p)->rb_left;
                else
                    p = &(*p)->rb_right;
            }
        }

        rb_link_node(&le->rb, parent, p);
        rb_insert_color(&le->rb, &ubi->ltree);
    }
    le->users += 1;
    spin_unlock(&ubi->ltree_lock);

    kfree(le_free);
    return le;
}


 
 

你可能感兴趣的:(ubi 下ubi_ltree_entry获取与初始化过程)