본문 바로가기

Core BSP 분석/리눅스 커널 핵심 분석

덴트리 캐시

unlink라는 시스템 콜을 따라가면 아래 함수를 볼 수 있다.
여기서 lookup_hash(&nd) 함수를 좀 파고들어가 보자.

static long do_unlinkat(int dfd, const char __user *pathname)
{
    int error;
    char *name;
    struct dentry *dentry;
    struct nameidata nd;
    struct inode *inode = NULL;
...
    nd.flags &= ~LOOKUP_PARENT;

    mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
    dentry = lookup_hash(&nd);
}

아래와 같은 함수 호출 체인을 볼 수 있는데, 덴트리는 덴트리 캐시에서 덴트리 인스턴스를 찾는 것이다.
static struct dentry *lookup_hash(struct nameidata *nd)
{
    return __lookup_hash(&nd->last, nd->path.dentry, nd);
}

static struct dentry *__lookup_hash(struct qstr *name,
        struct dentry *base, struct nameidata *nd)
{
    bool need_lookup;
    struct dentry *dentry;

    dentry = lookup_dcache(name, base, nd, &need_lookup);
    if (!need_lookup)
        return dentry;

    return lookup_real(base->d_inode, dentry, nd);
}

d_hash(parent, hash); 라는 함수를 호출해서 해시 테이블 포멧의 덴트리 캐시 리스트를 가져온다.

static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
                    struct nameidata *nd, bool *need_lookup)
{
    struct dentry *dentry;
    int error;

    *need_lookup = false;
    dentry = d_lookup(dir, name);
..
}
struct dentry *d_lookup(struct dentry *parent, struct qstr *name)
{
    struct dentry *dentry;
    unsigned seq;

        do {
                seq = read_seqbegin(&rename_lock);
                dentry = __d_lookup(parent, name);
                if (dentry)
            break;
    } while (read_seqretry(&rename_lock, seq));
    return dentry;
}

struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
{
    unsigned int len = name->len;
    unsigned int hash = name->hash;
    const unsigned char *str = name->name;
    struct hlist_bl_head *b = d_hash(parent, hash);
    struct hlist_bl_node *node;
..
}

결국 *d_hash() 함수를 통해 덴트리 캐시를 처리하는 해시 테이블에 접근한다.
dentry_hashtable은 0xC17C8200에 있다.
  (static struct hlist_bl_head *) dentry_hashtable = 0xC17C8200 = __bss_stop+0x9117E0 -> (
    (struct hlist_bl_node *) first = 0x0 =  -> NULL)
static inline struct hlist_bl_head *d_hash(const struct dentry *parent,
                    unsigned int hash)
{
    hash += (unsigned long) parent / L1_CACHE_BYTES;
    hash = hash + (hash >> D_HASHBITS);
    return dentry_hashtable + (hash & D_HASHMASK);
}

0xC17C8200 란 주소와 이 리스트의 구조체만 가지고 리스트의 내용을 깔 수가 있는데 다음에 찾자.