kernfs_addrm_start kernfs_add_one

来源:互联网 发布:instagram拍照软件好吗 编辑:程序博客网 时间:2024/06/04 00:24

linux内核版本3.14.3

文件/fs/kernfs/dir.c

/**
 * kernfs_addrm_start - 为kernfs_node添加/删除准备
 * @acxt: 指向要使用的kernfs_addrm_cxt的指针
 *
 * 该方法在调用方需要添加或删除kernfs_node的时候调用,该方法需要
 * kernfs_mutex.  @acxt是用来保存和传递内容到其他的addrm(add/remove)方法
 *
 * LOCKING:
 * Kernel thread context (may sleep).  kernfs_mutex is locked on
 * return.
 */
void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt)
__acquires(kernfs_mutex)
{
        memset(acxt, 0, sizeof(*acxt));

        mutex_lock(&kernfs_mutex);
}

这里的缩写让我很难办,addrm是(add/rm),cxt是context,看下面的结构体就可以理解了


文件/fs/kernfs/kernfs-internal.h

/*
 * Context structure to be used while adding/removing nodes.看英文更容易明白缩写到底是啥
 */
struct kernfs_addrm_cxt {
        struct kernfs_node*removed;
};


文件/fs/kernfs/dir.c

/**
 * kernfs_add_one - 无警告添加kernfs_node到parent
 * @acxt: 用于add/remove的context
 * @kn: 用来添加的kernfs_node
 *
 * 该调用必须已经初始化过@kn->parent.  如果@kn是一个目录,
 * 该方法会增加parent的inode的nlink,并链接到parent的 children list.
 *
 * 该方法应该在kernfs_addrm_start()和kernfs_addrm_finish()
 * 之间调用,并应该和和kernfs_addrm_start()传递相同的@acxt.
 *
 * LOCKING:
 * Determined by kernfs_addrm_start().
 *
 * RETURNS:
 * 成功返回0, 如果给定的entry名称已存在返回-EEXIST
 */
int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn)
{
        struct kernfs_node *parent = kn->parent;
        bool has_ns = kernfs_ns_enabled(parent);
        struct kernfs_iattrs *ps_iattr;
        int ret;

        if (has_ns != (bool)kn->ns) {
                WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n",  has_ns ? "required" : "invalid", parent->name, kn->name);
                return -EINVAL;
        }

        if (kernfs_type(parent) != KERNFS_DIR)
        return -EINVAL;

        if (parent->flags & KERNFS_REMOVED)
        return -ENOENT;

        kn->hash = kernfs_name_hash(kn->name, kn->ns);

        ret = kernfs_link_sibling(kn);
        if (ret)
                return ret;

        /* 更新parent的时间戳*/
        ps_iattr = parent->iattr;
        if (ps_iattr) {
                struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
                ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
        }

        /* Mark the entry added into directory tree */
        kn->flags &= ~KERNFS_REMOVED;

        return 0;
}


/**
 * kernfs_name_hash
 * @name: 转hash的以Null('\0')结尾的字符串
 * @ns:   转hash的命名空间tag
 *
 * Returns 31 bit hash of ns + name (so it fits in an off_t )
 */
static unsigned int kernfs_name_hash(const char *name, const void *ns)
{
        unsigned long hash = init_name_hash();//#define init_name_hash()                0
        unsigned int len = strlen(name);
        while (len--)
                hash = partial_name_hash(*name++, hash);
        hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31));
        hash &= 0x7fffffffU;
        /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */
        if (hash < 2)
                hash += 2;
        if (hash >= INT_MAX)
                hash = INT_MAX - 1;
        return hash;
}


文件/include/linux/dcache.h

/* partial hash update function. Assume roughly 4 bits per character */
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
        return (prevhash + (c << 4) + (c >> 4)) * 11;
}


我想这里就到此为止吧,所谓的kernfs_name_hash无非是把name这个字符串通过一个复杂的计算方法转换为一个unsigned int的数值,据说是为了查找方便,而这个复杂的算法,就先不研究了

0 0
原创粉丝点击