2015년 10월 24일 토요일

[Linux Kernel] 120주차(2015.10.24) vfs_caches_init()

ARM10C : 120 주차
일시 : 2015.10.24 (120 주차 스터디 진행)
모임명 : NAVER_개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

120 주차 진도

  • 119주차 진도를 복습하였습니다.
  • buffer_init()
    • buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행
  • key_init()
    • null funtion()
  • security_init()
    • null funtion()
  • dbg_late_init()
    • null funtion()
  • vfs_caches_init()
  • 지난주는 자기 충전의 시간을 가지고 다시 커널 소스 분석을 시작합니다.
  • vfs_caches_init()
    • start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c
      • vfs_caches_init 925 ~/kernel/iamroot/linux-stable/init/main.c
    • files_init 3485 ~/kernel/iamroot/linux-stable/fs/dcache.c

main.c::start_kernel()

// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];
    // ATAG,DTB 정보로 사용

...

    // totalram_pages: 총 free된 page 수
    fork_init(totalram_pages);
    // task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
    // max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함

    proc_caches_init();
    // sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
    // 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행

    buffer_init();
    // buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행

    key_init(); // null funtion
    security_init(); // null funtion
    dbg_late_init(); // null funtion

    // totalram_pages: 총 free된 page 수
    vfs_caches_init(totalram_pages);

dcache.c::vfs_caches_init()

  • call: start_kernel()->vfs_caches_init()
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

    // dcache_init에서 한일:
    //
    // struct dentry를 위한 kmem_cache 생성
    // dentry_cache: kmem_cache#5

    inode_init();

    // inode_init에서 한일:
    //
    // struct inode를 위한 kmem_cache 생성
    // inode_cachep: kmem_cache#4

    // mempages: 총 free된 page 수 - XXX
    files_init(mempages);

file_table.c::files_init()

  • call: start_kernel()->vfs_caches_init()
    • files_init()
// ARM10C 20151003
// mempages: 총 free된 page 수 - XXX
void __init files_init(unsigned long mempages)
{ 
    unsigned long n;

    // sizeof(struct file): 160 bytes,
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL,
    // kmem_cache_create("filp", 160, 0, 0x42000, NULL): kmem_cache#3
    filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
            SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
    // filp_cachep: kmem_cache#3

    /*
     * One file with associated inode and dcache is very roughly 1K.
     * Per default don't use more than 10% of our memory for files. 
     */ 

    // mempages: 총 free된 page 수 - XXX, PAGE_SIZE: 0x1000
    n = (mempages * (PAGE_SIZE / 1024)) / 10;
    // n: (총 free된 page 수 - XXX) * 4 / 10

    // NOTE:
    // max_t((총 free된 page 수 - XXX) * 4 / 10, 8192) 의 결과값?
    // 계산하여 결과를 구하기 힘듬 (총 free된 page 수 - XXX) * 4 / 10 로 가정하고 분석 진행

    // n: (총 free된 page 수 - XXX) * 4 / 10, NR_FILE: 8192
    // max_t((총 free된 page 수 - XXX) * 4 / 10, 8192): (총 free된 page 수 - XXX) * 4 / 10
    files_stat.max_files = max_t(unsigned long, n, NR_FILE);
    // files_stat.max_files: (총 free된 page 수 - XXX) * 4 / 10

    files_defer_init();

    // files_defer_init에서 한일:
    // sysctl_nr_open_max: 0x3FFFFFE0

// 2015/10/03 종료
// 2015/10/24 시작

    percpu_counter_init(&nr_files, 0);

percpu_counter.h::percpu_counter_init()

  • call: start_kernel()->vfs_caches_init()
    • dcache_init()
    • inode_init()
    • files_init()
// ARM10C 20151024
// &nr_files, 0
#define percpu_counter_init(fbc, value)                 \
    ({                              \
        static struct lock_class_key __key;         \
                                    \
        __percpu_counter_init(fbc, value, &__key);      \
    })

percpu_counter.c::__percpu_counter_init()

  • call: start_kernel()->vfs_caches_init()
    • dcache_init()
    • inode_init()
    • files_init()
    • percpu_counter_init()
      • __percpu_counter_init()
// ARM10C 20151024
// &nr_files, 0, &__key
int __percpu_counter_init(struct percpu_counter *fbc, s64 amount,
              struct lock_class_key *key)
{
    // &fbc->lock: &(&vm_committed_as)->lock
    raw_spin_lock_init(&fbc->lock);

    // raw_spin_lock_init에서 한일:
    // (&(&(&(&vm_committed_as)->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
    // (&(&(&(&vm_committed_as)->lock)->wait_lock)->rlock)->magic: 0xdead4ead
    // (&(&(&(&vm_committed_as)->lock)->wait_lock)->rlock)->owner: 0xffffffff
    // (&(&(&(&vm_committed_as)->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff

    // &fbc->lock: &(&vm_committed_as)->lock, key: &__key
    lockdep_set_class(&fbc->lock, key); // null function

    // fbc->count: (&vm_committed_as)->count, amount: 0
    fbc->count = amount;
    // fbc->count: (&vm_committed_as)->count: 0

    // fbc->counters: (&vm_committed_as)->counters,
    // alloc_percpu(s32): kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
    fbc->counters = alloc_percpu(s32);
    // fbc->counters: (&vm_committed_as)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소

    // fbc->counters: (&vm_committed_as)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
    if (!fbc->counters)
        return -ENOMEM;

    // fbc: &vm_committed_as
    debug_percpu_counter_activate(fbc); // null function

#ifdef CONFIG_HOTPLUG_CPU // CONFIG_HOTPLUG_CPU=y
    // &fbc->list: &(&vm_committed_as)->list
    INIT_LIST_HEAD(&fbc->list);

    // INIT_LIST_HEAD에서 한일:
    // (&(&vm_committed_as)->list)->next: &(&vm_committed_as)->list
    // (&(&vm_committed_as)->list)->prev: &(&vm_committed_as)->list

    spin_lock(&percpu_counters_lock);

    // spin_lock에서 한일:
    // &percpu_counters_lock을 사용한 spin lock 수행

    // &fbc->list: &(&vm_committed_as)->list
    list_add(&fbc->list, &percpu_counters);

    // list_add에서 한일:
    // list head 인 &percpu_counters에 &(&vm_committed_as)->list를 연결함

    spin_unlock(&percpu_counters_lock);

    // spin_lock에서 한일:
    // &percpu_counters_lock을 사용한 spin unlock 수행
#endif
    return 0;
    // return 0
}
EXPORT_SYMBOL(__percpu_counter_init);
  • percpu_counter_init에서 한일:
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->magic: 0xdead4ead
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->owner: 0xffffffff
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
    • (&(&nr_files)->list)->next: &(&nr_files)->list
    • (&(&nr_files)->list)->prev: &(&nr_files)->list
    • (&nr_files)->count: 0
    • (&nr_files)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
    • list head 인 &percpu_counters에 &(&nr_files)->list를 연결함

dcache.c::vfs_caches_init()

  • return: start_kernel()->vfs_caches_init()->files_init()
  • files_init에서 한일:
    • filp_cachep: kmem_cache#3
    • files_stat.max_files: (총 free된 page 수 - XXX) * 4 / 10

    - sysctl_nr_open_max: 0x3FFFFFE0

    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->magic: 0xdead4ead
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->owner: 0xffffffff
    • (&(&(&(&nr_files)->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
    • (&(&nr_files)->list)->next: &(&nr_files)->list
    • (&(&nr_files)->list)->prev: &(&nr_files)->list
    • (&nr_files)->count: 0
    • (&nr_files)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
    • list head 인 &percpu_counters에 &(&nr_files)->list를 연결함
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

    // dcache_init에서 한일:
    //
    // struct dentry를 위한 kmem_cache 생성
    // dentry_cache: kmem_cache#5

    inode_init();

    // inode_init에서 한일:
    //
    // struct inode를 위한 kmem_cache 생성
    // inode_cachep: kmem_cache#4

    // mempages: 총 free된 page 수 - XXX
    files_init(mempages);

    mnt_init();

namespace.c::mnt_init()

  • mnt_cahce를 할당받는다.
// ARM10C 20151024
void __init mnt_init(void)
{
    unsigned u;
    int err;

    // sizeof(struct mount): 152 bytes, SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("mnt_cache", 152, 0, 0x42000, NULL): kmem_cache#2
    mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
            0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
// ARM10C 20151024
// "mnt_cache", sizeof(struct mount): 152 bytes, 0, 0x00042000, NULL
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "mnt_cache", size: 152, align: 0, flags: 0x42000, ctor: NULL
    // kmem_cache_create_memcg(NULL, "mnt_cache", 152, 0, 0x42000, NULL): kmem_cache#2
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // return kmem_cache#2
}
EXPORT_SYMBOL(kmem_cache_create);
  • alloc_large_system_hash
```namespace.c
// ARM10C 20151024
void __init mnt_init(void)
{
    unsigned u;
    int err;

    // sizeof(struct mount): 152 bytes, SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("mnt_cache", 152, 0, 0x42000, NULL): kmem_cache#2
    mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
            0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
    // mnt_cache: kmem_cache#2

    // sizeof(struct hlist_head): 4 bytes, mhash_entries: 0
    // alloc_large_system_hash("Mount-cache", 4, 0, 19, 0, &m_hash_shift, &m_hash_mask, 0, 0): 16kB만큼 할당받은 메모리 주소
    mount_hashtable = alloc_large_system_hash("Mount-cache",
                sizeof(struct hlist_head),
                mhash_entries, 19,
                0,
                &m_hash_shift, &m_hash_mask, 0, 0);

page_alloc.c::alloc_large_system_hash()

// ARM10C 20151024
// [mCA] tablename: "Mount-cache", bucketsize: 4,
// numentries: 0, scale: 19,
// flags: 0,
// *_hash_shift : &m_hash_shift, *_hash_mask : &m_hash_mask,
// low_limit: 0, high_limit: 0
void *__init alloc_large_system_hash(const char *tablename,
                     unsigned long bucketsize,
                     unsigned long numentries,
                     int scale,
                     int flags,
                     unsigned int *_hash_shift,
                     unsigned int *_hash_mask,
                     unsigned long low_limit,
                     unsigned long high_limit)
{
    // [mCA] high_limit: 0
    unsigned long long max = high_limit;
    // [mCA] max : 0

    unsigned long log2qty, size;
    void *table = NULL;
    // [mCA] table: NULL

    /* allow the kernel cmdline to have a say */
    // [mCA] numentries: 0
    if (!numentries) {
        // [mCA] numentries : 0 이므로 if문 실행

        /* round applicable memory size up to nearest megabyte */
        // [mCA] static unsigned long __meminitdata nr_kernel_pages
        // [mCA] nr_kernel_pages : 0x2EFD6
        numentries = nr_kernel_pages;
        // [mCA] numentries : 0x2EFD6

        /* It isn't necessary when PAGE_SIZE >= 1MB */
        // [mCA] PAGE_SHIFT: 12
        if (PAGE_SHIFT < 20)
            // [mCA] numentries : 0x2EFD6, PAGE_SIZE: 0x1000, (1UL << 20) / 0x1000): 0xFF
            numentries = round_up(numentries, (1<<20)/PAGE_SIZE);
            // [mCA] numentries : 0x2F000

        /* limit to 1 bucket per 2^scale bytes of low memory */
        // [mCA] scale : (19 > 12), PAGE_SHIFT: 12
        if (scale > PAGE_SHIFT)
            // [mCA] numentries: 0x2F000, scale: 19, PAGE_SHIFT: 12
            numentries >>= (scale - PAGE_SHIFT);
            // [mCA] numentries >>= (scale : 19 - PAGE_SHIFT: 12)
            // [mCA] numentries : 0x5E0 : 0x2F000 >> 7:
        else
            numentries <<= (PAGE_SHIFT - scale);

        /* Make sure we've got at least a 0-order allocation.. */
        // [mCA] unlikely (0x00000000) : flags : 0x00000000 & HASH_SMALL 0x00000002
        if (unlikely(flags & HASH_SMALL)) {
            /* Makes no sense without HASH_EARLY */
            WARN_ON(!(flags & HASH_EARLY));

            if (!(numentries >> *_hash_shift)) {
                numentries = 1UL << *_hash_shift;
                BUG_ON(!numentries);
            }
        } else if (unlikely((numentries * bucketsize) < PAGE_SIZE))
        // [mCA] unlikely(0x2F000 : (0x5E0 * 4) < 0x1000)
            numentries = PAGE_SIZE / bucketsize;
    }

    // [mCA] numentries : 0x5E0 : 1504
    numentries = roundup_pow_of_two(numentries);
    // [mCA] numentries : 1024

    /* limit allocation size to 1/16 total memory by default */
    // [mCA] max : 0
    if (max == 0) {
        // [mCA] nr_all_pages: 0x7EA00, PAGE_SHIFT: 12
        max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
        // [mCA] max = (nr_all_pages : 0x7EA0000 : 0x7EA00000 >> 4 : 0x7EA00  << 12) >> 4

        // [mCA] max : 0x7EA0000, bucketsize : 4
        do_div(max, bucketsize);
        // [mCA] max : 0x1FA8000
    }

    // [mCA] max : 0x1FA8000 : min(0x1FA8000, 0x80000000ULL)
    max = min(max, 0x80000000ULL);
    // [mCA] max : 0x1FA8000

    // [mCA] numentries :   1024 < 0, low_limit: 0
    if (numentries < low_limit)
        numentries = low_limit;

    // [mCA] numentries :   1024 > 33193984 : 0x1FA8000
    if (numentries > max)
        numentries = max;

    // [mCA] numentries :  1024
    log2qty = ilog2(numentries);
    // [mCA] log2qty : 12 : ilog2(1024)

    do {
        // [mCA] bucketsize: 4, log2qty : 12
        size = bucketsize << log2qty;
        // [mCA] size = 0x4000 (16kB) : 4 << 12

        // [mCA] 0x00000000 : flags : 0x00000001 & HASH_EARLY : 0x00000001, hashdist: 0
        if (flags & HASH_EARLY)
            table = alloc_bootmem_nopanic(size);
        else if (hashdist)
            table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
        else {
            /*
             * If bucketsize is not a power-of-two, we may free
             * some pages at the end of hash table which
             * alloc_pages_exact() automatically does
             */
            // [mCA] size: 0x4000 (16kB), get_order(0x4000): 2, MAX_ORDER: 11
            if (get_order(size) < MAX_ORDER) {
                // [mCA] size: 0x4000 (16kB), GFP_ATOMIC: 0x20u
                // [mCA] alloc_pages_exact(0x4000, 0x20): migratetype이 MIGRATE_UNMOVABLE인 order 2의 page의 가상주소
                table = alloc_pages_exact(size, GFP_ATOMIC);
                // [mCA] table: migratetype이 MIGRATE_UNMOVABLE인 order 2의 page의 가상주소

                // [mCA] alloc_pages_exact 에서 한일:
                // migratetype이 MIGRATE_UNMOVABLE인 order 2의 page의 가상메모리 공간을 할당받고
                // migratetype이 MIGRATE_UNMOVABLE인 order 2의 page들의 _count를 1로 set (order 2이면 page 4개)
                // 각각의 page의 _count 값을 바꾸어 page를 split 함

                // [mCA] table: migratetype이 MIGRATE_UNMOVABLE인 order 2의 page의 가상주소, size: 0x4000 (16kB), GFP_ATOMIC: 0x20u
                kmemleak_alloc(table, size, 1, GFP_ATOMIC); // null function
            }
        }
    } while (!table && size > PAGE_SIZE && --log2qty);

    // [mCA] table : 16kB만큼 할당받은 메모리 주소
    if (!table)
        panic("Failed to allocate %s hash table\n", tablename);

    printk(KERN_INFO "%s hash table entries: %ld (order: %d, %lu bytes)\n",
           tablename,
           (1UL << log2qty),
           ilog2(size) - PAGE_SHIFT,
           size);
    // [mCA] Mount-cache hash table entries: 4096 (order: 2, 4096 bytes)

    // [mCA] _hash_shift : &m_hash_shift
    if (_hash_shift)
        // [mCA] log2qty : 12
        *_hash_shift = log2qty;
        // [mCA] *_hash_shift: m_hash_shift: 12

    // [mCA] _hash_mask : m_hash_mask
    if (_hash_mask)
        // [mCA] log2qty : 12, _hash_mask : m_hash_mask
        *_hash_mask = (1 << log2qty) - 1;
        // [mCA] *_hash_mask : (4095) 0xFFF : (1 << 12 ) - 1

    // [mCA] table : 16kB만큼 할당받은 메모리 주소
    return table;
    // [mCA] return 16kB만큼 할당받은 메모리 주소
}
// ARM10C 20151024
void __init mnt_init(void)
{
    unsigned u;
    int err;

    // sizeof(struct mount): 152 bytes, SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("mnt_cache", 152, 0, 0x42000, NULL): kmem_cache#2
    mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
            0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
    // mnt_cache: kmem_cache#2

    // sizeof(struct hlist_head): 4 bytes, mhash_entries: 0
    // alloc_large_system_hash("Mount-cache", 4, 0, 19, 0, &m_hash_shift, &m_hash_mask, 0, 0): 16kB만큼 할당받은 메모리 주소
    mount_hashtable = alloc_large_system_hash("Mount-cache",
                sizeof(struct hlist_head),
                mhash_entries, 19,
                0,
                &m_hash_shift, &m_hash_mask, 0, 0);
    // mount_hashtable: 16kB만큼 할당받은 메모리 주소

log

8be65be..4cba12e  master     -> origin/master
Updating 8be65be..4cba12e
Fast-forward
arch/arm/include/asm/bitops.h      |   2 +
arch/arm/include/asm/memory.h      |   3 +
arch/arm/include/asm/page.h        |   2 +
fs/dcache.c                        |  17 +++++
fs/file_table.c                    |  13 ++++
fs/mount.h                         |   7 +-
fs/namespace.c                     |  15 ++++
include/asm-generic/getorder.h     |  11 +++
include/asm-generic/memory_model.h |   1 +
include/linux/gfp.h                |   1 +
include/linux/kmemleak.h           |   1 +
include/linux/log2.h               |   2 +
include/linux/mm.h                 |  14 ++++
include/linux/mmzone.h             |   1 +
include/linux/mount.h              |   2 +
include/linux/page-flags.h         |   4 +
include/linux/percpu_counter.h     |   5 ++
include/linux/slab.h               |   2 +
include/linux/slub_def.h           |   1 +
include/linux/types.h              |   6 +-
init/main.c                        |   4 +
lib/percpu_counter.c               |   2 +
mm/internal.h                      |   2 +
mm/page_alloc.c                    | 202 ++++++++++++++++++++++++++++++++++++++++++--------
mm/slab_common.c                   |   7 ++
25 files changed, 294 insertions(+), 33 deletions(-)

2015년 10월 10일 토요일

[Linux Kernel] 119주차(2015.10.10) buffer_init(), key_init(), security_init(), dbg_late_init(), vfs_caches_init();

ARM10C : 119 주차
일시 : 2015.10.10 (119 주차 스터디 진행)
모임명 : NAVER_개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

119 주차 진도

  • 10월 03일 진도로 다시 복습을 했습니다.
  • proc_caches_init()
    • sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
    • 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행
  • buffer_init()부터 소스 코드 분석을 계속했습니다.
  • buffer_init()
    • buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행
  • key_init() 
    • null funtion()
  • security_init() - null funtion()
  • dbg_late_init() - null funtion()
  • vfs_caches_init() 

main.c::start_kernel()

// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];
    // ATAG,DTB 정보로 사용
...

    anon_vma_init();
    // anon vma 를 사용하기 위한 kmem_cache 할당자 초기화 수행

    thread_info_cache_init(); // null function
    cred_init();
    // credentials 를 사용하기 위한 kmem_cache 할당자 초기화 수행

    // totalram_pages: 총 free된 page 수
    fork_init(totalram_pages);
    // task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
    // max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함

    proc_caches_init();
    // sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
    // 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행

    buffer_init();

buffer.c::buffer_init()

  • call :
    • start_kernel()->buffer_init()
  • buffer_head 를 할당합니다.
// ARM10C 20151003
void __init buffer_init(void)
{
    unsigned long nrpages;

    // sizeof(struct buffer_head): 56 bytes,
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_DESTROY_BY_RCU: 0x00080000UL
    // kmem_cache_create("buffer_head", 56, 0, 0xE0000, NULL): kmem_cache#7
    bh_cachep = kmem_cache_create("buffer_head",
            sizeof(struct buffer_head), 0,
                (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                SLAB_MEM_SPREAD),
                NULL);
// ARM10C 20151003
// "buffer_head", sizeof(struct buffer_head): 56 bytes, 0, 0x000E0000, NULL
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "buffer_head", size: 56, align: 0, flags: 0xE0000, ctor: NULL
    // kmem_cache_create_memcg(NULL, "buffer_head", 56, 0, 0xE0000, NULL): kmem_cache#7
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // bh_cachep: kmem_cache#7
}
// ARM10C 20151003
void __init buffer_init(void)
{
    unsigned long nrpages;

    // sizeof(struct buffer_head): 56 bytes,
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_DESTROY_BY_RCU: 0x00080000UL
    // kmem_cache_create("buffer_head", 56, 0, 0xE0000, NULL): kmem_cache#7
    bh_cachep = kmem_cache_create("buffer_head",
            sizeof(struct buffer_head), 0,
                (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                SLAB_MEM_SPREAD),
                NULL);
    // bh_cachep: kmem_cache#7

    /*
     * Limit the bh occupancy to 10% of ZONE_NORMAL
     */
    // nr_free_buffer_pages(): 0x7f7d6
    nrpages = (nr_free_buffer_pages() * 10) / 100;
  • start_kernel()->buffer_init()->nr_free_zone_pages()
// ARM10C 20151003
unsigned long nr_free_buffer_pages(void)
{
    // NOTE:
    // nr_free_zone_pages(0): 0x7f7d6 값은 정확한 값이 아님
    // 이전의 주석 결과 값을 이용하여 진행함

    // GFP_USER: 0x200D0, gfp_zone(0x200D0): 0
    // nr_free_zone_pages(0): 0x7f7d6
    return nr_free_zone_pages(gfp_zone(GFP_USER));
}
EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
  • start_kernel()->buffer_init()->nr_free_zone_pages()->nr_free_zone_pages()
// ARM10C 20151003
// 0
static unsigned long nr_free_zone_pages(int offset)
{
    struct zoneref *z;
    struct zone *zone;

    /* Just pick one node, since fallback list is circular */
    unsigned long sum = 0;

    // numa_node_id(): 0, GFP_KERNEL: 0xD0
    struct zonelist *zonelist = node_zonelist(numa_node_id(), GFP_KERNEL);
    // zonelist: contig_page_data->node_zonelists

    // zonelist: contig_page_data->node_zonelists, offset: 0
    for_each_zone_zonelist(zone, z, zonelist, offset) {
    // for (z = first_zones_zonelist(contig_page_data->node_zonelists, 0, 0, &zone);
    //          zone; z = next_zones_zonelist(++z, 0, 0, &zone))
        // [1st] z: contig_page_data->node_zonelists->_zonerefs[1]
        // [1st] zone: contig_page_data->node_zones[0]
        // [2nd] z: contig_page_data->node_zonelists->_zonerefs[0]
        // [2nd] zone: contig_page_data->node_zones[1]

        // [1st]: zone->managed_pages: contig_page_data->node_zones[0]->managed_pages: 0x2efd6
        // [2nd]: zone->managed_pages: contig_page_data->node_zones[1]->managed_pages: 0x50800
        unsigned long size = zone->managed_pages;
        // [1st]: size: 0x2efd6
        // [2nd]: size: 0x50800

        // [1st] zone: contig_page_data->node_zones[0]
        // [1st] high_wmark_pages(contig_page_data->node_zones[0]): 0
        // [2st] zone: contig_page_data->node_zones[1]
        // [2st] high_wmark_pages(contig_page_data->node_zones[1]): 0
        unsigned long high = high_wmark_pages(zone);
        // [1st]: high: 0
        // [2nd]: high: 0

        // [1st]: size: 0x2efd6
        // [2nd]: size: 0x50800
        if (size > high)
            // [1st] sum: 0
            // [2nd]: sum: 0x2efd6
            sum += size - high;
            // [1st]: sum: 0x2efd6
            // [2nd]: sum: 0x7f7d6
    }

    // sum: 0x7f7d6
    return sum;
    // return 0x7f7d6
}
// ARM10C 20151003
unsigned long nr_free_buffer_pages(void)
{
    // NOTE:
    // nr_free_zone_pages(0): 0x7f7d6 값은 정확한 값이 아님
    // 이전의 주석 결과 값을 이용하여 진행함

    // GFP_USER: 0x200D0, gfp_zone(0x200D0): 0
    // nr_free_zone_pages(0): 0x7f7d6
    return nr_free_zone_pages(gfp_zone(GFP_USER));
    // return 0x7f7d6
}
EXPORT_SYMBOL_GPL(nr_free_buffer_pages);
  • hotcpu_notifier()
// ARM10C 20151003
void __init buffer_init(void)
{
    unsigned long nrpages;

    // sizeof(struct buffer_head): 56 bytes,
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_DESTROY_BY_RCU: 0x00080000UL
    // kmem_cache_create("buffer_head", 56, 0, 0xE0000, NULL): kmem_cache#7
    bh_cachep = kmem_cache_create("buffer_head",
            sizeof(struct buffer_head), 0,
                (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                SLAB_MEM_SPREAD),
                NULL);
    // bh_cachep: kmem_cache#7

    /*
     * Limit the bh occupancy to 10% of ZONE_NORMAL
     */
    // nr_free_buffer_pages(): 0x7f7d6
    nrpages = (nr_free_buffer_pages() * 10) / 100;
    // nrpages: 0xcbfb

    // nrpages: 0xcbfb, PAGE_SIZE: 0x1000, sizeof(struct buffer_head): 56 bytes
    max_buffer_heads = nrpages * (PAGE_SIZE / sizeof(struct buffer_head));
    // max_buffer_heads: 0x3a2a93

    hotcpu_notifier(buffer_cpu_notify, 0);
// ARM10C 20151003
// buffer_cpu_notify, 0
#define hotcpu_notifier(fn, pri)    cpu_notifier(fn, pri)
// ARM10C 20151003
// cpu_notifier(buffer_cpu_notify, 0):
// {
//  static struct notifier_block buffer_cpu_notify_nb =
//      { .notifier_call = buffer_cpu_notify, .priority = 0 };
//  register_cpu_notifier(&buffer_cpu_notify_nb);
// }
#define cpu_notifier(fn, pri) {                 \
    static struct notifier_block fn##_nb =          \
        { .notifier_call = fn, .priority = pri };   \
    register_cpu_notifier(&fn##_nb);            \
}
// ARM10C 20151003
// &buffer_cpu_notify_nb
int __ref register_cpu_notifier(struct notifier_block *nb)
{
    int ret;
    cpu_maps_update_begin();
    // waiter를 만들어 mutex를 lock을 시도하며 기다리다 가능할 때 mutex lock한다.

    // &cpu_chain, nb: &hotplug_cfd_notifier
    // raw_notifier_chain_register(&cpu_chain, &hotplug_cfd_notifier): 0
    //
    // &cpu_chain, nb: &buffer_cpu_notify_nb
    // raw_notifier_chain_register(&cpu_chain, &buffer_cpu_notify_nb): 0
    ret = raw_notifier_chain_register(&cpu_chain, nb);
    // ret: 0


    // raw_notifier_chain_register(&buffer_cpu_notify_nb) 에서 한일:
    //
    // (&cpu_chain)->head: &buffer_cpu_notify_nb
    // (&buffer_cpu_notify_nb)->next은 (&hotplug_cfd_notifier)->next로 대입

    cpu_maps_update_done();
    // mutex를 기다리는(waiter)가 있으면 깨우고 아니면 mutex unlock한다.

    // ret: 0
    return ret;
    // return 0
}
  • hotcpu_notifier 에서 한일:
    • (&cpu_chain)->head: &buffer_cpu_notify_nb
    • (&buffer_cpu_notify_nb)->next은 (&hotplug_cfd_notifier)->next로 대입

start_kernel()

  • return buffer_init()
// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];
    // ATAG,DTB 정보로 사용

...

    cred_init();
    // credentials 를 사용하기 위한 kmem_cache 할당자 초기화 수행

    // totalram_pages: 총 free된 page 수
    fork_init(totalram_pages);
    // task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
    // max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함

    proc_caches_init();
    // sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
    // 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행

    buffer_init();
    // buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행
  • key_init()
// ARM10C 20151003
#define key_init()          do { } while(0)
  • security_init()
// ARM10C 20151003
static inline int security_init(void)
{
    return 0;
}
  • dbg_late_init()
// ARM10C 20151003
#define dbg_late_init()
// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
    char * command_line;
    extern const struct kernel_param __start___param[], __stop___param[];
    // ATAG,DTB 정보로 사용

...

    cred_init();
    // credentials 를 사용하기 위한 kmem_cache 할당자 초기화 수행

    // totalram_pages: 총 free된 page 수
    fork_init(totalram_pages);
    // task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
    // max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함

    proc_caches_init();
    // sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
    // 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행

    buffer_init();
    // buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행

    key_init(); // null funtion
    security_init(); // null funtion
    dbg_late_init(); // null funtion

    // totalram_pages: 총 free된 page 수
    vfs_caches_init(totalram_pages);

dcache.c:vfs_caches_init()

  • call
    • start_kerne()->vfs_caches_init()
  • name_cache를 할당받음
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
// ARM10C 20151003
// "names_cache", 4096, 0, 0x42000, NULL
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "names_cache", size: 4096, align: 0, flags: 0x42000, ctor: NULL
    // kmem_cache_create_memcg(NULL, "names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // return kmem_cache#6
}
  • dcache_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

dcache.c::dcache_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
  • dentry를 할당 받는다.
// ARM10C 20151003
static void __init dcache_init(void)
{
    unsigned int loop;

    /* 
     * A constructor could be added for stable state like the lists,
     * but it is probably not worth it because of the cache nature
     * of the dcache. 
     */
    // sizeof(struct dentry): 140 bytes
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_MEM_SPREAD: 0x00100000UL
    // KMEM_CACHE(dentry, 0x160000):
    // kmem_cache_create("dentry", sizeof(struct dentry), __alignof__(struct dentry), (0x160000), NULL): kmem_cache#5
    dentry_cache = KMEM_CACHE(dentry,
        SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
// ARM10C 20151003
// #define KMEM_CACHE(dentry, 0x160000):
// kmem_cache_create("dentry", sizeof(struct dentry), __alignof__(struct dentry), (0x160000), NULL)
#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
        sizeof(struct __struct), __alignof__(struct __struct),\
        (__flags), NULL)
// ARM10C 20151003
// "dentry", sizeof(struct dentry): 140 bytes, __alignof__(struct dentry): 4, (0x160000), NULL
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "dentry", size: 140, align: 4, flags: 0x160000, ctor: NULL
    // kmem_cache_create_memcg(NULL, "dentry", 140, 4, 0x160000, NULL): kmem_cache#5
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // return kmem_cache#5
}
  • hashdist에서 리턴함.
// ARM10C 20151003
static void __init dcache_init(void)
{
    unsigned int loop;

    /* 
     * A constructor could be added for stable state like the lists,
     * but it is probably not worth it because of the cache nature
     * of the dcache. 
     */
    // sizeof(struct dentry): 140 bytes
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_MEM_SPREAD: 0x00100000UL
    // KMEM_CACHE(dentry, 0x160000):
    // kmem_cache_create("dentry", sizeof(struct dentry), __alignof__(struct dentry), (0x160000), NULL): kmem_cache#5
    dentry_cache = KMEM_CACHE(dentry,
        SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
    // dentry_cache: kmem_cache#5

    /* Hash may have been set up in dcache_init_early */
    // hashdist: 0
    if (!hashdist)
        return;
        // return 수행

    dentry_hashtable =
        alloc_large_system_hash("Dentry cache",
                    sizeof(struct hlist_bl_head),
                    dhash_entries,
                    13,
                    0,
                    &d_hash_shift,
                    &d_hash_mask,
                    0,
                    0);

    for (loop = 0; loop < (1U << d_hash_shift); loop++)
        INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
}
  • dcache_init에서 한일:
    • struct dentry를 위한 kmem_cache 생성
    • dentry_cache: kmem_cache#5

dcache.c::vfs_caches_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

    // dcache_init에서 한일:
    //
    // struct dentry를 위한 kmem_cache 생성
    // dentry_cache: kmem_cache#5

    inode_init();

inode.c::inode_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
  • inode_cache를 할당받는다.
// ARM10C 20151003
void __init inode_init(void)
{
    unsigned int loop;

    /* inode slab cache */
    // sizeof(struct inode): 394 bytes,
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_MEM_SPREAD: 0x00100000UL,
    // kmem_cache_create("inode_cache", 394, 0, 0x160000, init_once): kmem_cache#4
    inode_cachep = kmem_cache_create("inode_cache",
                     sizeof(struct inode),
                     0,
                     (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                     SLAB_MEM_SPREAD),
                     init_once);
// ARM10C 20151003
// "inode_cache", sizeof(struct inode): 394 bytes, 0, 0x160000, init_once
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "inode_cache", size: 394, align: 0, flags: 0x160000, ctor: init_once
    // kmem_cache_create_memcg(NULL, "inode_cache", 394, 4, 0x160000, init_once): kmem_cache#4
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // return kmem_cache#4
}
  • hashdist에서 리턴한다.
// ARM10C 20151003
void __init inode_init(void)
{
    unsigned int loop;

    /* inode slab cache */
    // sizeof(struct inode): 394 bytes,
    // SLAB_RECLAIM_ACCOUNT: 0x00020000UL, SLAB_PANIC: 0x00040000UL, SLAB_MEM_SPREAD: 0x00100000UL,
    // kmem_cache_create("inode_cache", 394, 0, 0x160000, init_once): kmem_cache#4
    inode_cachep = kmem_cache_create("inode_cache",
                     sizeof(struct inode),
                     0,
                     (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
                     SLAB_MEM_SPREAD),
                     init_once);
    // inode_cachep: kmem_cache#4

    /* Hash may have been set up in inode_init_early */
    // hashdist: 0
    if (!hashdist)
        return;
        // return 수행

    inode_hashtable =
        alloc_large_system_hash("Inode-cache",
                    sizeof(struct hlist_head),
                    ihash_entries,
                    14,
                    0,
                    &i_hash_shift,
                    &i_hash_mask,
                    0,
                    0);

    for (loop = 0; loop < (1U << i_hash_shift); loop++)
        INIT_HLIST_HEAD(&inode_hashtable[loop]);
}
  • inode_init에서 한일:
    • struct inode를 위한 kmem_cache 생성
    • inode_cachep: kmem_cache#4

dcache.c::vfs_caches_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

    // dcache_init에서 한일:
    //
    // struct dentry를 위한 kmem_cache 생성
    // dentry_cache: kmem_cache#5

    inode_init();
    // inode_init에서 한일:
    //
    // struct inode를 위한 kmem_cache 생성
    // inode_cachep: kmem_cache#4

    // mempages: 총 free된 page 수 - XXX
    files_init(mempages);

file_table.c::files_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
    • files_init()
  • filp 를 할당받는다.
// ARM10C 20151003
// mempages: 총 free된 page 수 - XXX
void __init files_init(unsigned long mempages)
{ 
    unsigned long n;

    // sizeof(struct file): 160 bytes,
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL,
    // kmem_cache_create("filp", 160, 0, 0x42000, NULL): kmem_cache#3
    filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
            SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
// ARM10C 20151003
// "filp", sizeof(struct file): 160 bytes, 0, 0x42000, NULL
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
          unsigned long flags, void (*ctor)(void *))
{
    // name: "filp", size: 160, align: 0, flags: 0x42000, ctor: NULL
    // kmem_cache_create_memcg(NULL, "filp", 160, 0, 0x42000, NULL): kmem_cache#3
    return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
    // return kmem_cache#3
}
// ARM10C 20151003
// mempages: 총 free된 page 수 - XXX
void __init files_init(unsigned long mempages)
{ 
    unsigned long n;

    // sizeof(struct file): 160 bytes,
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL,
    // kmem_cache_create("filp", 160, 0, 0x42000, NULL): kmem_cache#3
    filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
            SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
    // filp_cachep: kmem_cache#3

    /*
     * One file with associated inode and dcache is very roughly 1K.
     * Per default don't use more than 10% of our memory for files. 
     */ 

    // mempages: 총 free된 page 수 - XXX, PAGE_SIZE: 0x1000
    n = (mempages * (PAGE_SIZE / 1024)) / 10;
    // n: (총 free된 page 수 - XXX) * 4 / 10

    // NOTE:
    // max_t((총 free된 page 수 - XXX) * 4 / 10, 8192) 의 결과값?
    // 계산하여 결과를 구하기 힘듬 (총 free된 page 수 - XXX) * 4 / 10 로 가정하고 분석 진행

    // n: (총 free된 page 수 - XXX) * 4 / 10, NR_FILE: 8192
    // max_t((총 free된 page 수 - XXX) * 4 / 10, 8192): (총 free된 page 수 - XXX) * 4 / 10
    files_stat.max_files = max_t(unsigned long, n, NR_FILE);
    // files_stat.max_files: (총 free된 page 수 - XXX) * 4 / 10

    files_defer_init();

file.c::files_defer_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
    • files_init()
      • files_defer_init()
// ARM10C 20151003
void __init files_defer_init(void)
{
    // sysctl_nr_open_max: 0x100000, INT_MAX: 0x7FFFFFFF
    // min(0x7FFFFFFF, 0x3FFFFFFF): 0x3FFFFFFF, -BITS_PER_LONG: 0xFFFFFFE0
    sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) &
                 -BITS_PER_LONG;
    // sysctl_nr_open_max: 0x3FFFFFE0
}
  • files_defer_init에서 한일:
    • sysctl_nr_open_max: 0x3FFFFFE0

dcache.c::vfs_caches_init()

  • call
    • start_kerne()->vfs_caches_init()
      • kmem_cache_create(); // names_cache
    • dcache_init()
    • inode_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
    unsigned long reserve;

    /* Base hash sizes on available memory, with a reserve equal to
           150% of current kernel size */

    // NOTE:
    // mempages 값과 nr_free_pages() 의 값을 정확히 알 수 없음
    // 계산된 reserve의 값을 XXX 로 함

    // mempages: 총 free된 page 수, nr_free_pages(): 현재의 free pages 수
    reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
    // reserve: XXX

    // mempages: 총 free된 page 수, reserve: XXX
    mempages -= reserve;
    // mempages: 총 free된 page 수 - XXX

    // PATH_MAX: 4096
    // SLAB_HWCACHE_ALIGN: 0x00002000UL, SLAB_PANIC: 0x00040000UL
    // kmem_cache_create("names_cache", 4096, 0, 0x42000, NULL): kmem_cache#6
    names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
            SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    // names_cachep: kmem_cache#6

    dcache_init();

    // dcache_init에서 한일:
    //
    // struct dentry를 위한 kmem_cache 생성
    // dentry_cache: kmem_cache#5

    inode_init();
    // inode_init에서 한일:
    //
    // struct inode를 위한 kmem_cache 생성
    // inode_cachep: kmem_cache#4

    // mempages: 총 free된 page 수 - XXX
    files_init(mempages);

log

  • 1st log
e356946..8be65be  master     -> origin/master
Updating e356946..8be65be
Fast-forward
arch/arm/include/asm/atomic.h               |  3 +-
arch/arm/include/asm/mmu.h                  |  6 ++-
arch/arm/include/asm/pgtable-2level-types.h |  1 +
arch/arm/include/asm/processor.h            |  5 +-
fs/buffer.c                                 | 19 +++++++
fs/dcache.c                                 | 20 +++++++
fs/fat/inode.c                              |  1 +
fs/file.c                                   |  2 +-
fs/file_table.c                             |  7 +++
fs/inode.c                                  |  5 ++
include/asm-generic/atomic-long.h           |  2 +
include/asm-generic/bitsperlong.h           |  1 +
include/asm-generic/cputime_jiffies.h       |  1 +
include/linux/auxvec.h                      |  2 +
include/linux/backing-dev.h                 |  2 +
include/linux/binfmts.h                     |  1 +
include/linux/bio.h                         |  2 +
include/linux/blkdev.h                      |  2 +-
include/linux/buffer_head.h                 |  5 +-
include/linux/cgroup.h                      |  1 +
include/linux/completion.h                  |  2 +
include/linux/cpu.h                         | 12 ++++-
include/linux/cpumask.h                     |  2 +
include/linux/cred.h                        |  1 +
include/linux/dcache.h                      | 15 +++++-
include/linux/fdtable.h                     |  8 +++
include/linux/fs.h                          | 30 ++++++++---
include/linux/fs_struct.h                   |  2 +
include/linux/gfp.h                         | 19 +++++++
include/linux/iocontext.h                   |  1 +
include/linux/kconfig.h                     |  1 +
include/linux/ktime.h                       |  3 ++
include/linux/list_bl.h                     |  2 +
include/linux/llist.h                       |  1 +
include/linux/lockref.h                     |  7 +++
include/linux/mm_types.h                    | 49 +++++++++++++----
include/linux/mutex.h                       |  3 ++
include/linux/nsproxy.h                     |  2 +
include/linux/path.h                        |  2 +
include/linux/pid.h                         |  6 +++
include/linux/pipe_fs_i.h                   |  1 +
include/linux/plist.h                       |  4 ++
include/linux/posix_acl.h                   |  1 +
include/linux/radix-tree.h                  |  1 +
include/linux/rbtree.h                      |  1 +
include/linux/rwlock_types.h                |  8 +--
include/linux/sched.h                       | 22 +++++++-
include/linux/seccomp.h                     |  3 +-
include/linux/sem.h                         |  4 +-
include/linux/seqlock.h                     |  1 +
include/linux/signal.h                      |  2 +
include/linux/slab.h                        | 15 ++++++
include/linux/swap.h                        |  1 +
include/linux/task_io_accounting.h          |  5 +-
include/linux/tty.h                         |  1 +
include/linux/types.h                       | 17 +++++-
include/linux/uidgid.h                      |  2 +
include/linux/uprobes.h                     |  3 +-
include/uapi/asm-generic/posix_types.h      |  4 ++
include/uapi/asm-generic/resource.h         |  2 +
include/uapi/asm-generic/siginfo.h          |  1 +
include/uapi/linux/futex.h                  |  1 +
include/uapi/linux/limits.h                 |  2 +
include/uapi/linux/resource.h               |  2 +
include/uapi/linux/time.h                   |  2 +
init/main.c                                 |  5 ++
ipc/sem.c                                   |  1 +
kernel/audit.h                              |  1 +
kernel/bounds.c                             |  3 +-
kernel/cpu.c                                | 16 ++++++
kernel/fork.c                               | 41 ++++++++++++--
kernel/futex.c                              |  1 +
kernel/locking/rtmutex_common.h             |  1 +
kernel/notifier.c                           | 11 ++++
kernel/nsproxy.c                            |  7 +++
kernel/sched/sched.h                        |  3 ++
lib/percpu_counter.c                        |  1 +
mm/page_alloc.c                             | 10 ++++
mm/slab_common.c                            | 83 +++++++++++++++++++++++++++--
79 files changed, 498 insertions(+), 48 deletions(-)