131주차 (2016.01.23) vfs_caches_init()


#1
KernelStudy : 131 주차
일시 : 2016.01.23 (131 주차 스터디 진행)
모임명 : KernelStudy_ARM
장소 : 토즈 서현점
장소지원 : 공개 소프트웨어 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

============

131 주차 진도

  • 130 주차 진도를 복습하였습니다.

  • vfs_caches_init()

  • start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c
  • vfs_caches_init 925 ~/kernel/iamroot/linux-stable/init/main.c
  • mnt_init 3807 ~/kernel/iamroot/linux-stable/fs/dcache.c
  • kobject_create_and_add 3926 ~/kernel/iamroot/linux-stable/fs/namespace.c
  • kobject_add 828 retval = kobject_add(kobj, parent, “%s”, name);
  • kobject_add_varg 457 retval = kobject_add_varg(kobj, parent, fmt, args);
  • kobject_set_name_vargs 395 retval = kobject_set_name_vargs(kobj, fmt, vargs);
  • 130주차 함수 호출 구조

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
      • sysfs_add_one()
        • sysfs_ns_type()
        • sysfs_name_hash()
          • partial_name_hash()
        • sysfs_get()
        • sysfs_link_sibling()

main.c::start_kernel()

  • call: start_kernel()->vfs_caches_init()
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern const struct kernel_param __start___param[], __stop___param[];
	// ATAG,DTB 정보로 사용

...

    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_cache_init()

  • call: start_kernel()
  • vfs_caches_init()
// ARM10C 20151003
// totalram_pages: 총 free된 page 수
void __init vfs_caches_init(unsigned long mempages)
{
	unsigned long reserve;

	// 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();

	inode_init();

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

	mnt_init();

namespace.c::mnt_init()

  • call: start_kernel()->vfs_caches_init()
    • mnt_init()
// 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만큼 할당받은 메모리 주소

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

	// mount_hashtable: 16kB만큼 할당받은 메모리 주소, mountpoint_hashtable: 16kB만큼 할당받은 메모리 주소
	if (!mount_hashtable || !mountpoint_hashtable)
		panic("Failed to allocate mount hash table\n");

	// m_hash_mask: 0xFFF
	for (u = 0; u <= m_hash_mask; u++)
		// u: 0
		INIT_HLIST_HEAD(&mount_hashtable[u]);

		// INIT_HLIST_HEAD 에서 한일:
		// ((&mount_hashtable[0])->first = NULL)

		// u: 1...4095 까지 loop 수행

	// mp_hash_mask: 0xFFF
	for (u = 0; u <= mp_hash_mask; u++)
		// u: 0
		INIT_HLIST_HEAD(&mountpoint_hashtable[u]);

		// INIT_HLIST_HEAD 에서 한일:
		// ((&mountpoint_hashtable[0])->first = NULL)

		// u: 1...4095 까지 loop 수행

	// sysfs_init(): 0
	err = sysfs_init();
	// err: 0

	// err: 0
	if (err)
		printk(KERN_WARNING "%s: sysfs_init error: %d\n",
			__func__, err);
	fs_kobj = kobject_create_and_add("fs", NULL);

kobject.c::kobject_create_and_add()

  • call: start_kernel()->vfs_caches_init()->mnt_init()
    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
// ARM10C 20160109
// "fs", NULL
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
	struct kobject *kobj;
	int retval;

	// kobject_create(): kmem_cache#30-oX (struct kobject)
	kobj = kobject_create();

	// kobj: kmem_cache#30-oX (struct kobject)
	if (!kobj)
		return NULL;

	// kobj: kmem_cache#30-oX (struct kobject), parent: NULL, name: "fs"
	retval = kobject_add(kobj, parent, "%s", name);

kobject.c::kobject_add()

  • call: start_kernel()->vfs_caches_init()->mnt_init()
    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_add()
// ARM10C 20160109
// kobj: kmem_cache#30-oX (struct kobject), parent: NULL, "%s", name: "fs"
int kobject_add(struct kobject *kobj, struct kobject *parent,
		const char *fmt, ...)
{
	va_list args;
	int retval;

	// kobj: kmem_cache#30-oX (struct kobject)
	if (!kobj)
		return -EINVAL;

	// kobj->state_initialized: (kmem_cache#30-oX (struct kobject))->state_initialized: 1
	if (!kobj->state_initialized) {
		printk(KERN_ERR "kobject '%s' (%p): tried to add an "
		       "uninitialized object, something is seriously wrong.\n",
		       kobject_name(kobj), kobj);
		dump_stack();
		return -EINVAL;
	}

	// fmt: "%s"
	va_start(args, fmt);

	// va_start에서 한일:
	// (args): (((char *) &("%s")) + 4): "fs"

	// kobj: kmem_cache#30-oX (struct kobject), parent: NULL, fmt: "%s", args: "fs"
	retval = kobject_add_varg(kobj, parent, fmt, args);

kobject.c::kobject_set_name_vargs()

  • call: start_kernel()->vfs_caches_init()->mnt_init()
    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_add()
        • kobject_add_varg()
// ARM10C 20160109
// kobj: kmem_cache#30-oX (struct kobject), parent: NULL, fmt: "%s", args: "fs"
static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
			    const char *fmt, va_list vargs)
{
	int retval;

	// kobj: kmem_cache#30-oX (struct kobject), fmt: "%s", vargs: "fs"
	retval = kobject_set_name_vargs(kobj, fmt, vargs);

kobject.c::kobject_set_name_vargs()

  • call: start_kernel()->vfs_caches_init()->mnt_init()
    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_add()
        • kobject_add_varg()
          • kobject_add_vargs()
// ARM10C 20160109
// kobj: kmem_cache#30-oX (struct kobject), fmt: "%s", vargs: "fs"
int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
				  va_list vargs)
{
	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: NULL
	const char *old_name = kobj->name;
	// old_name: NULL

	char *s;

	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: NULL, fmt: "%s"
	if (kobj->name && !fmt)
		return 0;

	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: NULL
	// GFP_KERNEL: 0xD0, fmt: "%s", vargs: "fs"
	// kvasprintf(GFP_KERNEL: 0xD0, "%s", "fs"): kmem_cache#30-oX: "fs"
	kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: kmem_cache#30-oX: "fs"

	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: kmem_cache#30-oX: "fs"
	if (!kobj->name)
		return -ENOMEM;

// 2016/01/09 종료

	/* ewww... some of these buggers have '/' in the name ... */
	while ((s = strchr(kobj->name, '/')))
		s[0] = '!';

	kfree(old_name);

kobject.c::kobject_set_name_vargs()

  • call: start_kernel()->vfs_caches_init()->mnt_init()
    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_add()
        • kobject_add_varg()
          • kobject_add_vargs()
            • kfree()
void kfree(const void *x)
{
	struct page *page;

	// x: kmem_cache#30-o11
	void *object = (void *)x;
	// object: kmem_cache#30-o11

	// _RET_IP_: __builtin_return_address(0), object: kmem_cache#30-o11
	trace_kfree(_RET_IP_, x);

	// x: kmem_cache#30-o11, ZERO_OR_NULL_PTR(kmem_cache#30-o11): 0
	if (unlikely(ZERO_OR_NULL_PTR(x)))
		return;

	// x: kmem_cache#30-o11
	// virt_to_head_page(kmem_cache#30-o11): kmem_cache#30-o11의 page 주소
	page = virt_to_head_page(x);
	// page: kmem_cache#30-o11의 page 주소

	// page: kmem_cache#30-o11의 page 주소
	// PageSlab(kmem_cache#30-o11의 page 주소): 1
	if (unlikely(!PageSlab(page))) {
		BUG_ON(!PageCompound(page));
		kfree_hook(x);
		__free_memcg_kmem_pages(page, compound_order(page));
		return;
	}

// 2014/11/29 종료
// 2014/12/06 시작

	// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
	// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
	slab_free(page->slab_cache, page, object, _RET_IP_);

	// slab_free에서 한일:
	// (kmem_cache#30)->cpu_slab: struct kmem_cache_cpu 자료구조를 사용하기 위해 할당받은 pcp 16 byte 메모리 공간을 구하여
	// kmem_cache#30-o11의 freepointer의 값을
	// ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅
	// 값 s->cpu_slab->freelist와 c->freelist를 비교, 값 s->cpu_slab->tid와 tid을 비교 하여
	// 같을 경우에 s->cpu_slab->freelist와 s->cpu_slab->tid을 각각 object, next_tid(tid) 값으로 갱신하여
	// freelist와 tid 값을 변경함
	// kmem_cache_cpu의 freelist, tid 의 값을 변경함
}
EXPORT_SYMBOL(kfree);

kojbect.c::kobject_add_varg()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
static int kobject_add_internal(struct kobject *kobj)
{
	int error = 0;
	struct kobject *parent;

	if (!kobj)
		return -ENOENT;

	if (!kobj->name || !kobj->name[0]) {
		WARN(1, "kobject: (%p): attempted to be registered with empty "
			 "name!\n", kobj);
		return -EINVAL;
	}

	parent = kobject_get(kobj->parent);
  • kobject_get()
struct kobject *kobject_get(struct kobject *kobj)
{
	if (kobj)
		kref_get(&kobj->kref);
	return kobj;
}

kobject.c::kobject_add()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()

kobject.c::kobject_add_internal()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
// ARM10C 20160116
// kobj: kmem_cache#30-oX (struct kobject)
static int kobject_add_internal(struct kobject *kobj)
{
	int error = 0;
	// error: 0

	struct kobject *parent;

	// kobj: kmem_cache#30-oX (struct kobject)
	if (!kobj)
		return -ENOENT;

	// kobj->name: (kmem_cache#30-oX (struct kobject))->name: "fs"
	if (!kobj->name || !kobj->name[0]) {
		WARN(1, "kobject: (%p): attempted to be registered with empty "
			 "name!\n", kobj);
		return -EINVAL;
	}

	// kobj->parent: (kmem_cache#30-oX (struct kobject))->parent: NULL
	// kobject_get(NULL): NULL
	parent = kobject_get(kobj->parent);
	// parent: NULL

	/* join kset if set, use it as parent if we do not already have one */
	// kobj->kset: (kmem_cache#30-oX (struct kobject))->kset: NULL
	if (kobj->kset) {
		if (!parent)
			parent = kobject_get(&kobj->kset->kobj);
		kobj_kset_join(kobj);
		kobj->parent = parent;
	}

	// kobj: kmem_cache#30-oX (struct kobject),
	// kobject_name(kmem_cache#30-oX (struct kobject)): "fs", parent: NULL,
	// kobj->kset: (kmem_cache#30-oX (struct kobject))->kset: NULL
	pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
		 kobject_name(kobj), kobj, __func__,
		 parent ? kobject_name(parent) : "<NULL>",
		 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
	// "kobject: 'fs' (kmem_cache#30-oX): kobject_add_internal: parent: '<NULL>', set: '<NULL>'\n"

	// kobj: kmem_cache#30-oX (struct kobject)
	error = create_dir(kobj);

dir.c::create_dir()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: carete_dir()

// ARM10C 20160116
// kobj: kmem_cache#30-oX (struct kobject), parent_sd: &sysfs_root, type: 0,
// kobject_name(kmem_cache#30-oX (struct kobject)): "fs", ns: NULL, &sd
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      enum kobj_ns_type type,
		      const char *name, const void *ns,
		      struct sysfs_dirent **p_sd)
{
	// S_IFDIR: 0040000, S_IRWXU: 00700, S_IRUGO: 00444, S_IXUGO: 00111
	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
	// mode: 0x41ED

	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	/* allocate */
	// name: "fs", mode: 0x41ED, SYSFS_DIR: 0x0001
	// sysfs_new_dirent("fs", 0x41ED, 0x0001): kmem_cache#1-oX (struct sysfs_dirent)
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
  • sysfs_new_dirent에서 한일: // sysfs_dir_cachep: kmem_cache#1을 이용하여 struct sysfs_dirent 메모리를 할당받음 // kmem_cache#1-oX (struct sysfs_dirent) // // (&(&sysfs_ino_ida)->idr)->id_free: NULL // (&(&sysfs_ino_ida)->idr)->id_free_cnt: 6 // (&(&sysfs_ino_ida)->idr)->top: kmem_cache#21-o7 (struct idr_layer) // (&(&sysfs_ino_ida)->idr)->layers: 1 // (&sysfs_ino_ida)->free_bitmap: NULL // // (kmem_cache#21-o7 (struct idr_layer))->ary[0]: NULL // (kmem_cache#21-o7 (struct idr_layer))->layer: 0 // (kmem_cache#21-o7 (struct idr_layer))->ary[0]: kmem_cache#27-oX (struct ida_bitmap) // (kmem_cache#21-o7 (struct idr_layer))->count: 1 // // (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 0 bit를 1로 set 수행 // // (kmem_cache#1-oX (struct sysfs_dirent))->s_ino: 2 // // (&(kmem_cache#1-oX (struct sysfs_dirent))->s_count)->counter: 1 // (&(kmem_cache#1-oX (struct sysfs_dirent))->s_active)->counter: 0 // (kmem_cache#1-oX (struct sysfs_dirent))->s_name: “fs” // (kmem_cache#1-oX (struct sysfs_dirent))->s_mode: 0x41ED // (kmem_cache#1-oX (struct sysfs_dirent))->s_flags: 0x2001

dir.c::create_dir()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: carete_dir()

// ARM10C 20160116
// kobj: kmem_cache#30-oX (struct kobject), parent_sd: &sysfs_root, type: 0,
// kobject_name(kmem_cache#30-oX (struct kobject)): "fs", ns: NULL, &sd
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      enum kobj_ns_type type,
		      const char *name, const void *ns,
		      struct sysfs_dirent **p_sd)
{
	// S_IFDIR: 0040000, S_IRWXU: 00700, S_IRUGO: 00444, S_IXUGO: 00111
	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
	// mode: 0x41ED

	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	/* allocate */
	// name: "fs", mode: 0x41ED, SYSFS_DIR: 0x0001
	// sysfs_new_dirent("fs", 0x41ED, 0x0001): kmem_cache#1-oX (struct sysfs_dirent)
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
  • sysfs_new_dirent에서 한일: // sysfs_dir_cachep: kmem_cache#1을 이용하여 struct sysfs_dirent 메모리를 할당받음 // kmem_cache#1-oX (struct sysfs_dirent) // // (&(&sysfs_ino_ida)->idr)->id_free: NULL // (&(&sysfs_ino_ida)->idr)->id_free_cnt: 6 // (&(&sysfs_ino_ida)->idr)->top: kmem_cache#21-o7 (struct idr_layer) // (&(&sysfs_ino_ida)->idr)->layers: 1 // (&sysfs_ino_ida)->free_bitmap: NULL // // (kmem_cache#21-o7 (struct idr_layer))->ary[0]: NULL // (kmem_cache#21-o7 (struct idr_layer))->layer: 0 // (kmem_cache#21-o7 (struct idr_layer))->ary[0]: kmem_cache#27-oX (struct ida_bitmap) // (kmem_cache#21-o7 (struct idr_layer))->count: 1 // // (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 0 bit를 1로 set 수행 // // (kmem_cache#1-oX (struct sysfs_dirent))->s_ino: 2 // // (&(kmem_cache#1-oX (struct sysfs_dirent))->s_count)->counter: 1 // (&(kmem_cache#1-oX (struct sysfs_dirent))->s_active)->counter: 0 // (kmem_cache#1-oX (struct sysfs_dirent))->s_name: “fs” // (kmem_cache#1-oX (struct sysfs_dirent))->s_mode: 0x41ED // (kmem_cache#1-oX (struct sysfs_dirent))->s_flags: 0x2001

  • configfs_attach_attr()

  • sysfs_new_dirent()

  • dir.c::sysfs_alloc_ino()

static int sysfs_alloc_ino(unsigned int *pino)
{
	int ino, rc;

 retry:
	spin_lock(&sysfs_ino_lock);
	rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
	spin_unlock(&sysfs_ino_lock);

	if (rc == -EAGAIN) {
		if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
			goto retry;
		rc = -ENOMEM;
	}

	*pino = ino;
	return rc;
}
  • return sysfs_alloc_ino() 가 한일.

dir.c::create_dir()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: carete_dir()

    • sysfs_new_dirent()
  • struct sysfs_dirent *sd

// sizeof(struct sysfs_dirent): 64 bytes
struct sysfs_dirent {
	atomic_t		s_count;
	atomic_t		s_active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC // CONFIG_DEBUG_LOCK_ALLOC=n
	struct lockdep_map	dep_map;
#endif
	struct sysfs_dirent	*s_parent;
	const char		*s_name;

	struct rb_node		s_rb;

	union {
		struct completion	*completion;
		struct sysfs_dirent	*removed_list;
	} u;

	const void		*s_ns; /* namespace tag */
	unsigned int		s_hash; /* ns + name hash */
	union {
		struct sysfs_elem_dir		s_dir;
		struct sysfs_elem_symlink	s_symlink;
		struct sysfs_elem_attr		s_attr;
	};

	unsigned short		s_flags;
	umode_t			s_mode;
	unsigned int		s_ino;
	struct sysfs_inode_attrs *s_iattr;
};
// ARM10C 20160116
// kobj: kmem_cache#30-oX (struct kobject), parent_sd: &sysfs_root, type: 0,
// kobject_name(kmem_cache#30-oX (struct kobject)): "fs", ns: NULL, &sd
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      enum kobj_ns_type type,
		      const char *name, const void *ns,
		      struct sysfs_dirent **p_sd)
{
	// S_IFDIR: 0040000, S_IRWXU: 00700, S_IRUGO: 00444, S_IXUGO: 00111
	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
	// mode: 0x41ED

	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	/* allocate */
	// name: "fs", mode: 0x41ED, SYSFS_DIR: 0x0001
	// sysfs_new_dirent("fs", 0x41ED, 0x0001): kmem_cache#1-oX (struct sysfs_dirent)
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
	// sd: kmem_cache#1-oX (struct sysfs_dirent)

	// sd: kmem_cache#1-oX (struct sysfs_dirent)
	if (!sd)
		return -ENOMEM;

	sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
	sd->s_ns = ns;
	sd->s_dir.kobj = kobj;

	/* link in */
	sysfs_addrm_start(&acxt);

dir.c::sysfs_addrm_start()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: carete_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()

``dir.c void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt) __acquires(sysfs_mutex) { memset(acxt, 0, sizeof(*acxt));

mutex_lock(&sysfs_mutex);

}


* sysfs_addrm_start()에서 한일

## dir.c::create_dir()

* call: start_kernel()->vfs_caches_init()->mnt_init()
  - kmem_cache_create()
  - alloc_large_system_hash() : mnt_cache
  - alloc_large_system_hash() : Mount-cache
  - alloc_large_system_hash() : Mountpoint-cache
  - INIT_HLIST_HEAD() : &mount_hashtable[u]
  - INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
  - sysfs_init()
  - kobject_create_and_add() : fs
    - kobject_create()
    - kobject_add()

* call: kojbect_add()
  - kobject_add_varg()
    - kobject_set_name_vargs()
	  - kfree()
    - kobject_add_internal()
      - create_dir()

* call: create_dir()
  - sysfs_new_dirent()
  - sysfs_addrm_start()
  
```dir.c
// ARM10C 20160116
// kobj: kmem_cache#30-oX (struct kobject), parent_sd: &sysfs_root, type: 0,
// kobject_name(kmem_cache#30-oX (struct kobject)): "fs", ns: NULL, &sd
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
		      enum kobj_ns_type type,
		      const char *name, const void *ns,
		      struct sysfs_dirent **p_sd)
{
	// S_IFDIR: 0040000, S_IRWXU: 00700, S_IRUGO: 00444, S_IXUGO: 00111
	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
	// mode: 0x41ED

	struct sysfs_addrm_cxt acxt;
	struct sysfs_dirent *sd;
	int rc;

	/* allocate */
	// name: "fs", mode: 0x41ED, SYSFS_DIR: 0x0001
	// sysfs_new_dirent("fs", 0x41ED, 0x0001): kmem_cache#1-oX (struct sysfs_dirent)
	sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
	// sd: kmem_cache#1-oX (struct sysfs_dirent)

	// sd: kmem_cache#1-oX (struct sysfs_dirent)
	if (!sd)
		return -ENOMEM;

	sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
	sd->s_ns = ns;
	sd->s_dir.kobj = kobj;

	/* link in */
	sysfs_addrm_start(&acxt);
	rc = sysfs_add_one(&acxt, sd, parent_sd);

dir.c::sysfs_add_one()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
		  struct sysfs_dirent *parent_sd)
{
	int ret;

	ret = __sysfs_add_one(acxt, sd, parent_sd);

	if (ret == -EEXIST)
		sysfs_warn_dup(parent_sd, sd->s_name);
	return ret;
}

dir.c::__sysfs_add_one()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
      • sysfs_add_one()
  • struct sysfs_inode_attrs

// ARM10C 20151205
struct sysfs_inode_attrs {
	struct iattr	ia_iattr;
	void		*ia_secdata;
	u32		ia_secdata_len;
};
int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
		    struct sysfs_dirent *parent_sd)
{
	struct sysfs_inode_attrs *ps_iattr;
	int ret;

	if (!!sysfs_ns_type(parent_sd) != !!sd->s_ns) {
		WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
			sysfs_ns_type(parent_sd) ? "required" : "invalid",
			parent_sd->s_name, sd->s_name);
		return -EINVAL;
	}

	sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
	sd->s_parent = sysfs_get(parent_sd);

	ret = sysfs_link_sibling(sd);
	if (ret)
		return ret;

	/* Update timestamps on the parent */
	ps_iattr = parent_sd->s_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 */
	sd->s_flags &= ~SYSFS_FLAG_REMOVED;

	return 0;
}
  • sysfs.h::sysfs_ns_type()
static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd)
{
	return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT;
}

dir.c::__sysfs_add_one()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
      • sysfs_add_one()
        • sysfs_ns_type()
        • sysfs_name_hash()
static unsigned int sysfs_name_hash(const char *name, const void *ns)
{
	unsigned long hash = init_name_hash();
	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 < 1)
		hash += 2;
	if (hash >= INT_MAX)
		hash = INT_MAX - 1;
	return hash;
}
  • partial_name_hash()
static inline unsigned long
partial_name_hash(unsigned long c, unsigned long prevhash)
{
	return (prevhash + (c << 4) + (c >> 4)) * 11;
}
  • return 0x4662

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
      • sysfs_add_one()
        • sysfs_ns_type()
        • sysfs_name_hash()
          • partial_name_hash()
        • sysfs_get()
        • sysfs_link_sibling()
  • sysfs_get()

// ARM10C 20151205
// sd: &sysfs_root
struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
{
	// sd: &sysfs_root
	// __sysfs_get(&sysfs_root): 2
	return __sysfs_get(sd);
	// return 2

	// __sysfs_get에서 한일:
	// (&sysfs_root)->s_count: 2
}
EXPORT_SYMBOL_GPL(sysfs_get);

dir.c::sysfs_link_sibling()

  • call: start_kernel()->vfs_caches_init()->mnt_init()

    • kmem_cache_create()
    • alloc_large_system_hash() : mnt_cache
    • alloc_large_system_hash() : Mount-cache
    • alloc_large_system_hash() : Mountpoint-cache
    • INIT_HLIST_HEAD() : &mount_hashtable[u]
    • INIT_HLIST_HEAD() : &mountpoint_hashtable[u]
    • sysfs_init()
    • kobject_create_and_add() : fs
      • kobject_create()
      • kobject_add()
  • call: kojbect_add()

    • kobject_add_varg()
      • kobject_set_name_vargs()
        • kfree()
      • kobject_add_internal()
        • create_dir()
  • call: create_dir()

    • sysfs_new_dirent()
    • sysfs_addrm_start()
    • sysfs_add_one()
      • sysfs_add_one()
        • sysfs_ns_type()
        • sysfs_name_hash()
          • partial_name_hash()
        • sysfs_get()
        • sysfs_link_sibling()
static int sysfs_link_sibling(struct sysfs_dirent *sd)
{
	struct rb_node **node = &sd->s_parent->s_dir.children.rb_node;
	struct rb_node *parent = NULL;

	if (sysfs_type(sd) == SYSFS_DIR)
		sd->s_parent->s_dir.subdirs++;

	while (*node) {
		struct sysfs_dirent *pos;
		int result;

		pos = to_sysfs_dirent(*node);
		parent = *node;
		result = sysfs_sd_compare(sd, pos);
		if (result < 0)
			node = &pos->s_rb.rb_left;
		else if (result > 0)
			node = &pos->s_rb.rb_right;
		else
			return -EEXIST;
	}
	/* add new node and rebalance the tree */
	rb_link_node(&sd->s_rb, parent, node);
	rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children);
	return 0;
}

log

  • 1st log
2574bd1..943e482  master     -> origin/master
Updating 2574bd1..943e482
Fast-forward
fs/mount.h             |  1 +
fs/namespace.c         | 31 ++++++++++++++++
include/linux/dcache.h |  1 +
include/linux/fs.h     |  2 +
include/linux/idr.h    |  3 ++
include/linux/mount.h  |  1 +
lib/idr.c              | 99 +++++++++++++++++++++++++++++++++++++++++---------
mm/shmem.c             |  3 ++
8 files changed, 123 insertions(+), 18 deletions(-)