147주차 (2016.06.11) proc_root_init()


#1
Neuromancer : 147 주차
일시 : 2016.06.11 (147주차 스터디 진행)
모임명 : neuromancer.kr
장소 : 토즈 서현점
장소지원 : 공개 소프트웨어 개발자 커뮤니티 지원 프로그램
참여인원 : 2명

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

147주차 진도

  • 147차 시작 위치
  • start_kernel 1 ~/init/main.c
  • proc_root_init 937 ~/init/main.c
  • proc_symlink 215 ~/proc/root.c
  • __proc_create 597 ent = __proc_create(&parent, name,

147주차 함수 호출 구조

  • calll: start_kernel()
  • proc_root_init()
  • proc_root_init()
  • proc_init_inodecache()
  • register_filesystem()
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()

start_kernel()

  • call: start_kernel()
  • proc_root_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 초기화 수행

...

	vfs_caches_init(totalram_pages);
	// virtual file system을 위한 names, dentry, inode, filp, mount cache 생성 후
	// file system 을 위한 초기화 수행 및 mount 수행, block, char dev 사용을 위한 초기화 수행

	signals_init();
	// signal을 사용하기 위한 kmem_cache 를 생성

	/* rootfs populating might need page-writeback */
	page_writeback_init();
	// page writeback을 위한 global_dirty_limit, ratelimit_pages 값을 초기화 수행

#ifdef CONFIG_PROC_FS // CONFIG_PROC_FS=y
	proc_root_init();

proc_root_init()

  • calll: start_kernel()
  • proc_root_init()
  • call: call_root_init()
// ARM10C 20160604
void __init proc_root_init(void)
{
	int err;

	proc_init_inodecache();

	// proc_init_inodecache 에서 한일:
	// struct proc_inode 크기 만큼의 메모리를 할당항는 kmem_cache 할당자를 생성함
	// proc_inode_cachep: kmem_cache#n#28 (struct proc_inode)

	// register_filesystem(&proc_fs_type): 0
	err = register_filesystem(&proc_fs_type);
	// err: 0

	// register_filesystem에서 한일:
	// (&bd_type)->next: &proc_fs_type
	//
	// file system 연결 결과
	// file_systems: sysfs_fs_type -> rootfs_fs_type -> shmem_fs_type -> bd_type -> proc_fs_type

	// err: 0
	if (err)
		return;

	proc_self_init();

	// proc_self_init 에서 한일:
	// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 2 개를 할당 받음
	//
	// (&(&proc_inum_ida)->idr)->id_free 이 idr object new 1번을 가르킴
	// |
	// |-> ---------------------------------------------------------------------------------------------------------------------------
	//     | idr object new 1         | idr object new 0     | idr object 6         | idr object 5         | .... | idr object 0     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//     | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | .... | ary[0]: NULL     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//
	// (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 1)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 8
	//
	// (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8)
	// (&(&proc_inum_ida)->idr)->layers: 1
	// (&(&proc_inum_ida)->idr)->id_free: (idr object new 0)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 7
	//
	// (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 1 bit를 1로 set 수행
	// (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 2
	//
	// kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 1) 의 memory 공간을 반환함
	//
	// self_inum: 0xF0000001

	// proc_symlink("mounts", NULL, "self/mounts"): kmem_cache#29-oX (struct proc_dir_entry)
	proc_symlink("mounts", NULL, "self/mounts");

proc_symlink()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
// ARM10C 20160604
// "mounts", NULL, "self/mounts"
// ARM10C 20160611
// "net", NULL, "self/net"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	// &parent, name: "net"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "net", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);

__proc_create()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • call: __proc_create()
// ARM10C 20160604
// &parent, name: "mounts", 0120777, 1
// ARM10C 20160611
// &parent, name: "net", 0120777, 1
// ARM10C 20160611
// &parent, name: "sysvipc", 0040555, 2
// // ARM10C 20160611
// &parent, name: "tty/ldiscs", mode: 0100444, 1
static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
					  const char *name,
					  umode_t mode,
					  nlink_t nlink)
{
	struct proc_dir_entry *ent = NULL;
	// ent: NULL

	const char *fn = name;
	// fn: "mounts"

	unsigned int len;

	/* make sure name is valid */
	// name: "mounts", strlen("mounts"): 6
	if (!name || !strlen(name))
		goto out;

	// name: "mounts", parent: &parent, &fn: &"mounts"
	// xlate_proc_name("mounts", &parent, "mounts"): 0
	if (xlate_proc_name(name, parent, &fn) != 0)
		goto out;

	// xlate_proc_name 에서 한일:
	// parent: &proc_root

	/* At this point there must not be any '/' characters beyond *fn */
	// fn: "mounts", strchr("mounts", '/'): NULL
	if (strchr(fn, '/'))
		goto out;

	// fn: "mounts", strlen("mounts"): 6
	len = strlen(fn);
	// len: 6

	// ent: NULL, sizeof(struct proc_dir_entry): 91 bytes, len: 6, GFP_KERNEL: 0xD0
	// kzalloc(98, GFP_KERNEL: 0xD0): kmem_cache#29-oX
	ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (!ent)
		goto out;

	// ent->name: (kmem_cache#29-oX (struct proc_dir_entry))->name, fn: "mounts", len: 6
	memcpy(ent->name, fn, len + 1);
	// ent->name: (kmem_cache#29-oX (struct proc_dir_entry))->name: "mounts"

	// ent->namelen: (kmem_cache#29-oX (struct proc_dir_entry))->namelen, len: 6
	ent->namelen = len;
	// ent->namelen: (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6

	// ent->mode: (kmem_cache#29-oX (struct proc_dir_entry))->mode, mode: 0120777
	ent->mode = mode;
	// ent->mode: (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777

	// ent->nlink: (kmem_cache#29-oX (struct proc_dir_entry))->nlink, nlink: 1
	ent->nlink = nlink;
	// ent->nlink: (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1

	// &ent->count: &(kmem_cache#29-oX (struct proc_dir_entry))->count
	atomic_set(&ent->count, 1);

	// atomic_set 에서 한일:
	// (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1

// 2016/06/04 종료
// 2016/06/11 시작

	// &ent->pde_unload_lock: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock
	spin_lock_init(&ent->pde_unload_lock);

	// spin_lock_init에서 한일:
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행
	//
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } }
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff

	// &ent->pde_openers: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers
	INIT_LIST_HEAD(&ent->pde_openers);

	// INIT_LIST_HEAD 에서 한일:
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
out:
	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	return ent;
	// return kmem_cache#29-oX (struct proc_dir_entry)
}

proc_symlink()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
// ARM10C 20160604
// "mounts", NULL, "self/mounts"
// ARM10C 20160611
// "net", NULL, "self/net"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// __proc_create 에서 한일:
	// struct proc_dir_entry 만큼 메모리를 할당 받음 kmem_cache#29-oX (struct proc_dir_entry)
	//
	// (kmem_cache#29-oX (struct proc_dir_entry))->name: "mounts"
	// (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6
	// (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777
	// (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1
	// (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } }
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	//
	// parent: &proc_root

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);

kmalloc()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc() : ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL)
  • call: kmalloc()
// ARM10C 20160611
// 12, GFP_KERNEL: 0xD0
static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
	// size: 172
	if (__builtin_constant_p(size)) {
		// size: 172, KMALLOC_MAX_CACHE_SIZE: 0x2000
		if (size > KMALLOC_MAX_CACHE_SIZE)
			return kmalloc_large(size, flags);

#ifndef CONFIG_SLOB // CONFIG_SLOB=n
		// flags: 0xD0, GFP_DMA: 0x01u
		if (!(flags & GFP_DMA)) {
			// size: 172, kmalloc_index(172): 8
			int index = kmalloc_index(size);
			// index: 8

			// index: 8
			if (!index)
				return ZERO_SIZE_PTR;

			// index: 8, kmalloc_caches[8]: kmem_cache#27->name: flags: 0xD0, size: 172
			return kmem_cache_alloc_trace(kmalloc_caches[index],
					flags, size);
			// return kmem_cache#27-o0
		}
#endif
	}
	return __kmalloc(size, flags);
}

proc_symlink()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc()
  • return proc_symlink()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// __proc_create 에서 한일:
	// struct proc_dir_entry 만큼 메모리를 할당 받음 kmem_cache#29-oX (struct proc_dir_entry)
	//
	// (kmem_cache#29-oX (struct proc_dir_entry))->name: "mounts"
	// (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6
	// (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777
	// (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1
	// (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } }
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	//
	// parent: &proc_root

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX

		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX
		if (ent->data) {
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX, dest: "self/mounts"
			// strcpy(kmem_cache#30-oX, "self/mounts"): kmem_cache#30-oX: "self/mounts"
			strcpy((char*)ent->data,dest);
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: "self/mounts"

			// parent: &proc_root, ent: kmem_cache#29-oX (struct proc_dir_entry),
			// proc_register(&proc_root, kmem_cache#29-oX (struct proc_dir_entry)): 0
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}

proc_register()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
  • call: proc_register()
// ARM10C 20160611
// parent: &proc_root, ent: kmem_cache#29-oX (struct proc_dir_entry)
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
	struct proc_dir_entry *tmp;
	int ret;
	
	// &dp->low_ino: &(kmem_cache#29-oX (struct proc_dir_entry))->low_ino
	// proc_alloc_inum(&(kmem_cache#29-oX (struct proc_dir_entry))->low_ino): 0
	ret = proc_alloc_inum(&dp->low_ino);

proc_alloc_inum()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
  • call: proc_register()
  • proc_alloc_inum()
  • call: proc_alloc_inum()
// ARM10C 20160604
// &self_inum
int proc_alloc_inum(unsigned int *inum)
{
	unsigned int i;
	int error;

retry:
	// GFP_KERNEL: 0xD0, ida_pre_get(&proc_inum_ida, 0xD0): 1
	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
		return -ENOMEM;

ida_pre_get()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
  • call: proc_register()
  • proc_alloc_inum()
  • call: proc_alloc_inum()
  • ida_pre_get()
  • __idr_pre_get에서 한일: // idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 2 개를 할당 받음 // // (&(&proc_inum_ida)->idr)->id_free 이 idr object new 1번을 가르킴 // | // |-> --------------------------------------------------------------------------------------------------------------------------- // | idr object new 1 | idr object new 0 | idr object 6 | idr object 5 | … | idr object 0 | // --------------------------------------------------------------------------------------------------------------------------- // | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | … | ary[0]: NULL | // --------------------------------------------------------------------------------------------------------------------------- // // (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 1) // (&(&proc_inum_ida)->idr)->id_free_cnt: 8
// ARM10C 20160604
// &self_inum
int proc_alloc_inum(unsigned int *inum)
{
	unsigned int i;
	int error;

retry:
	// GFP_KERNEL: 0xD0, ida_pre_get(&proc_inum_ida, 0xD0): 1
	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
		return -ENOMEM;

	// __idr_pre_get에서 한일:
	// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 2 개를 할당 받음
	//
	// (&(&proc_inum_ida)->idr)->id_free 이 idr object new 1번을 가르킴
	// |
	// |-> ---------------------------------------------------------------------------------------------------------------------------
	//     | idr object new 1         | idr object new 0     | idr object 6         | idr object 5         | .... | idr object 0     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//     | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | .... | ary[0]: NULL     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//
	// (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 1)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 8

	spin_lock_irq(&proc_inum_lock);

	// spin_lock_irq 에서 한일:
	// &proc_inum_lock 을 사용하여 spin lock을 수행

    // ida_get_new(&proc_inum_ida, &i): 0
	error = ida_get_new(&proc_inum_ida, &i);
	// error: 0

	// ida_get_new 에서 한일:
	// (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8)
	// (&(&proc_inum_ida)->idr)->layers: 1
	// (&(&proc_inum_ida)->idr)->id_free: (idr object new 0)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 7
	//
	// (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 1 bit를 1로 set 수행
	// (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 2
	//
	// i: 1
	//
	// kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 1) 의 memory 공간을 반환함

	spin_unlock_irq(&proc_inum_lock);

	// spin_unlock_irq 에서 한일:
	// &proc_inum_lock 을 사용하여 spin lock을 수행

	// error: 0
	if (error == -EAGAIN)
		goto retry;
	else if (error)
		return error;

	// i: 1, UINT_MAX: 0xFFFFFFFF, PROC_DYNAMIC_FIRST: 0xF0000000
	if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
		spin_lock_irq(&proc_inum_lock);
		ida_remove(&proc_inum_ida, i);
		spin_unlock_irq(&proc_inum_lock);
		return -ENOSPC;
	}

	// *inum: self_inum, PROC_DYNAMIC_FIRST: 0xF0000000, i: 1
	*inum = PROC_DYNAMIC_FIRST + i;
	// *inum: self_inum: 0xF0000001

	return 0;
	// return 0
}
  • return:
// ARM10C 20160604
// &proc_inum_ida, GFP_KERNEL: 0xD0
int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
{
	/* allocate idr_layers */
	// &ida->idr: &(&unnamed_dev_ida)->idr, gfp_mask: 0x20
	// __idr_pre_get(&(&unnamed_dev_ida)->idr, 0x20): 1
	if (!__idr_pre_get(&ida->idr, gfp_mask))
		return 0;

__idr_pre_get()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
  • call: proc_register()
  • proc_alloc_inum()
  • call: proc_alloc_inum()
  • ida_pre_get()
  • call: ida_pre_get()
  • __idr_pre_get()
  • call: __idr_pre_get()

// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)
  • __proc_create 에서 한일:

// struct proc_dir_entry 만큼 메모리를 할당 받음 kmem_cache#29-oX (struct proc_dir_entry) // // (kmem_cache#29-oX (struct proc_dir_entry))->name: “mounts” // (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6 // (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777 // (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1 // (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1 // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행 // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } } // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list // // parent: &proc_root

// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX

		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX
		if (ent->data) {
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX, dest: "self/mounts"
			// strcpy(kmem_cache#30-oX, "self/mounts"): kmem_cache#30-oX: "self/mounts"
			strcpy((char*)ent->data,dest);
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: "self/mounts"

			// parent: NULL, ent: kmem_cache#29-oX (struct proc_dir_entry),
			// proc_register(NULL, kmem_cache#29-oX (struct proc_dir_entry)): 0
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}

generic.c::proc_register()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc()
  • strcpy()
  • proc_register()
  • call: proc_register()
// ARM10C 20160611
// parent: &proc_root, ent: kmem_cache#29-oX (struct proc_dir_entry)
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
	struct proc_dir_entry *tmp;
	int ret;
	
	// &dp->low_ino: &(kmem_cache#29-oX (struct proc_dir_entry))->low_ino
	// proc_alloc_inum(&(kmem_cache#29-oX (struct proc_dir_entry))->low_ino): 0
	ret = proc_alloc_inum(&dp->low_ino);

generic.c::proc_register()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc()
  • strcpy()
  • proc_register()
  • call: proc_register()
  • proc_alloc_inum()
  • call: proc_alloc_inum()
// ARM10C 20160611
// &dp->low_ino: &(kmem_cache#29-oX (struct proc_dir_entry))->low_ino
int proc_alloc_inum(unsigned int *inum)
{
	unsigned int i;
	int error;

retry:
	// GFP_KERNEL: 0xD0, ida_pre_get(&proc_inum_ida, 0xD0): 1
	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
		return -ENOMEM;

	// __idr_pre_get에서 한일:
	// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 2 개를 할당 받음
	//
	// (&(&proc_inum_ida)->idr)->id_free 이 idr object new 1번을 가르킴
	// |
	// |-> ---------------------------------------------------------------------------------------------------------------------------
	//     | idr object new 1         | idr object new 0     | idr object 6         | idr object 5         | .... | idr object 0     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//     | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | .... | ary[0]: NULL     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//
	// (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 1)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 8

	spin_lock_irq(&proc_inum_lock);

	// spin_lock_irq 에서 한일:
	// &proc_inum_lock 을 사용하여 spin lock을 수행

	// ida_get_new(&proc_inum_ida, &i): 0
	error = ida_get_new(&proc_inum_ida, &i);
	// error: 0

	// ida_get_new 에서 한일:
	// (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8)
	// (&(&proc_inum_ida)->idr)->layers: 1
	// (&(&proc_inum_ida)->idr)->id_free: (idr object new 0)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 7
	//
	// (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 1 bit를 1로 set 수행
	// (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 2
	//
	// i: 1
	//
	// kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 1) 의 memory 공간을 반환함

	spin_unlock_irq(&proc_inum_lock);

	// spin_unlock_irq 에서 한일:
	// &proc_inum_lock 을 사용하여 spin lock을 수행
	
	// error: 0
	if (error == -EAGAIN)
		goto retry;
	else if (error)
		return error;

	// i: 1, UINT_MAX: 0xFFFFFFFF, PROC_DYNAMIC_FIRST: 0xF0000000
	if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
		spin_lock_irq(&proc_inum_lock);
		ida_remove(&proc_inum_ida, i);
		spin_unlock_irq(&proc_inum_lock);
		return -ENOSPC;
	}

	// *inum: self_inum, PROC_DYNAMIC_FIRST: 0xF0000000, i: 1
	*inum = PROC_DYNAMIC_FIRST + i;
	// *inum: self_inum: 0xF0000001

	return 0;
	// return 0
}
  • return: proc_alloc_inum()->proc_register()

proc_register()

  • call: start_kernel()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
  • __proc_create()
  • kmalloc((ent->size=strlen(dest))+1)
  • strcpy()
  • proc_register()
  • call: proc_register()
  • proc_alloc_inum()
  • return: proc_alloc_inum()->proc_register()
// ARM10C 20160611
// parent: &proc_root, ent: kmem_cache#29-oX (struct proc_dir_entry)
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
	struct proc_dir_entry *tmp;
	int ret;
	
	// &dp->low_ino: &(kmem_cache#29-oX (struct proc_dir_entry))->low_ino
	// proc_alloc_inum(&(kmem_cache#29-oX (struct proc_dir_entry))->low_ino): 0
	ret = proc_alloc_inum(&dp->low_ino);
	// ret: 0
  • proc_alloc_inum 에서 한일:

// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 1 개를 할당 받음 // // (&(&proc_inum_ida)->idr)->id_free 이 idr object new 2번을 가르킴 // | // |-> --------------------------------------------------------------------------------------------------------------------------- // | idr object new 2 | idr object new 0 | idr object 6 | idr object 5 | … | idr object 0 | // --------------------------------------------------------------------------------------------------------------------------- // | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | … | ary[0]: NULL | // --------------------------------------------------------------------------------------------------------------------------- // // (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 2) // (&(&proc_inum_ida)->idr)->id_free_cnt: 8 // // (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8) // (&(&proc_inum_ida)->idr)->layers: 1 // (&(&proc_inum_ida)->idr)->id_free: (idr object new 0) // (&(&proc_inum_ida)->idr)->id_free_cnt: 7 // // (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 2 bit를 1로 set 수행 // (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 3 // // kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 2) 의 memory 공간을 반환함 // // (kmem_cache#29-oX (struct proc_dir_entry))->low_ino: 0xF0000002

// ARM10C 20160611
// parent: &proc_root, ent: kmem_cache#29-oX (struct proc_dir_entry)
static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
	struct proc_dir_entry *tmp;
	int ret;
	
	// &dp->low_ino: &(kmem_cache#29-oX (struct proc_dir_entry))->low_ino
	// proc_alloc_inum(&(kmem_cache#29-oX (struct proc_dir_entry))->low_ino): 0
	ret = proc_alloc_inum(&dp->low_ino);
	// ret: 0

	// ret: 0
	if (ret)
		return ret;

	// dp->mode: (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777,
	// S_ISDIR(0120777): 0, S_ISLNK(0120777): 1
	if (S_ISDIR(dp->mode)) {
		dp->proc_fops = &proc_dir_operations;
		dp->proc_iops = &proc_dir_inode_operations;
		dir->nlink++;
	} else if (S_ISLNK(dp->mode)) {
		// dp->proc_iops: (kmem_cache#29-oX (struct proc_dir_entry))->proc_iops
		dp->proc_iops = &proc_link_inode_operations;
		// dp->proc_iops: (kmem_cache#29-oX (struct proc_dir_entry))->proc_iops: &proc_link_inode_operations
	} else if (S_ISREG(dp->mode)) {
		BUG_ON(dp->proc_fops == NULL);
		dp->proc_iops = &proc_file_inode_operations;
	} else {
		WARN_ON(1);
		return -EINVAL;
	}

	spin_lock(&proc_subdir_lock);

	// spin_lock 에서 한일:
	// &proc_subdir_lock 을 이용하여 spin lock 을 수행

	// dir: &proc_root, dir->subdir: (&proc_root)->subdir: NULL
	for (tmp = dir->subdir; tmp; tmp = tmp->next)
		if (strcmp(tmp->name, dp->name) == 0) {
			WARN(1, "proc_dir_entry '%s/%s' already registered\n",
				dir->name, dp->name);
			break;
		}

	// dp->next: (kmem_cache#29-oX (struct proc_dir_entry))->next, dir->subdir: (&proc_root)->subdir: NULL
	dp->next = dir->subdir;
	// dp->next: (kmem_cache#29-oX (struct proc_dir_entry))->next: NULL

	// dp->parent: (kmem_cache#29-oX (struct proc_dir_entry))->parent, dir: &proc_root
	dp->parent = dir;
	// dp->parent: (kmem_cache#29-oX (struct proc_dir_entry))->parent: &proc_root

	// dir->subdir: (&proc_root)->subdir, dp: kmem_cache#29-oX (struct proc_dir_entry)
	dir->subdir = dp;
	// dir->subdir: (&proc_root)->subdir: kmem_cache#29-oX (struct proc_dir_entry)

	spin_unlock(&proc_subdir_lock);

	// spin_unlock 에서 한일:
	// &proc_subdir_lock 을 이용하여 spin unlock 을 수행

	return 0;
	// return 0
}
  • S_ISDIR()
// ARM10C 20160611
// dp->mode: (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777
#define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)
  • S_ISLNK()
// ARM10C 20160611
// S_IFMT: 00170000
// S_IFLNK: 0120000
// dp->mode: (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777
#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)

generic.c::proc_symlink()

  • call: start_kernel()
  • page_writeback_init()
  • proc_root_init()
  • call: call_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • call: proc_symlink()
// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX

		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX
		if (ent->data) {
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX, dest: "self/mounts"
			// strcpy(kmem_cache#30-oX, "self/mounts"): kmem_cache#30-oX: "self/mounts"
			strcpy((char*)ent->data,dest);
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: "self/mounts"

			// parent: NULL, ent: kmem_cache#29-oX (struct proc_dir_entry),
			// proc_register(NULL, kmem_cache#29-oX (struct proc_dir_entry)): 0
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}
  • // proc_register 에서 한일:

// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 1 개를 할당 받음 // // (&(&proc_inum_ida)->idr)->id_free 이 idr object new 2번을 가르킴 // | // |-> --------------------------------------------------------------------------------------------------------------------------- // | idr object new 2 | idr object new 0 | idr object 6 | idr object 5 | … | idr object 0 | // --------------------------------------------------------------------------------------------------------------------------- // | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | … | ary[0]: NULL | // --------------------------------------------------------------------------------------------------------------------------- // // (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 2) // (&(&proc_inum_ida)->idr)->id_free_cnt: 8 // // (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8) // (&(&proc_inum_ida)->idr)->layers: 1 // (&(&proc_inum_ida)->idr)->id_free: (idr object new 0) // (&(&proc_inum_ida)->idr)->id_free_cnt: 7 // // (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 2 bit를 1로 set 수행 // (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 3 // // kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 2) 의 memory 공간을 반환함 // // (kmem_cache#29-oX (struct proc_dir_entry))->low_ino: 0xF0000002 // (kmem_cache#29-oX (struct proc_dir_entry))->proc_iops: &proc_link_inode_operations // (kmem_cache#29-oX (struct proc_dir_entry))->next: NULL // (kmem_cache#29-oX (struct proc_dir_entry))->parent: &proc_root // // (&proc_root)->subdir: kmem_cache#29-oX (struct proc_dir_entry)

// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX

		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX
		if (ent->data) {
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX, dest: "self/mounts"
			// strcpy(kmem_cache#30-oX, "self/mounts"): kmem_cache#30-oX: "self/mounts"
			strcpy((char*)ent->data,dest);
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: "self/mounts"

			// parent: NULL, ent: kmem_cache#29-oX (struct proc_dir_entry),
			// proc_register(NULL, kmem_cache#29-oX (struct proc_dir_entry)): 0
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}
		} else {
			kfree(ent);
			ent = NULL;
		}
	}

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	return ent;
	// return kmem_cache#29-oX (struct proc_dir_entry)
}
EXPORT_SYMBOL(proc_symlink);

generic.c::proc_root_init()

  • call: start_kernel()
  • page_writeback_init()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_symlink 에서 한일:

// struct proc_dir_entry 만큼 메모리를 할당 받음 kmem_cache#29-oX (struct proc_dir_entry) // // (kmem_cache#29-oX (struct proc_dir_entry))->name: “mounts” // (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6 // (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777 // (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1 // (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1 // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행 // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } } // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff // ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list // &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list // // parent: &proc_root // // (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: “self/mounts” // // idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 1 개를 할당 받음 // // (&(&proc_inum_ida)->idr)->id_free 이 idr object new 2번을 가르킴 // | // |-> --------------------------------------------------------------------------------------------------------------------------- // | idr object new 2 | idr object new 0 | idr object 6 | idr object 5 | … | idr object 0 | // --------------------------------------------------------------------------------------------------------------------------- // | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | … | ary[0]: NULL | // --------------------------------------------------------------------------------------------------------------------------- // // (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 2) // (&(&proc_inum_ida)->idr)->id_free_cnt: 8 // // (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8) // (&(&proc_inum_ida)->idr)->layers: 1 // (&(&proc_inum_ida)->idr)->id_free: (idr object new 0) // (&(&proc_inum_ida)->idr)->id_free_cnt: 7 // // (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 2 bit를 1로 set 수행 // (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 3 // // kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 2) 의 memory 공간을 반환함 // // (kmem_cache#29-oX (struct proc_dir_entry))->low_ino: 0xF0000002 // (kmem_cache#29-oX (struct proc_dir_entry))->proc_iops: &proc_link_inode_operations // (kmem_cache#29-oX (struct proc_dir_entry))->next: NULL // (kmem_cache#29-oX (struct proc_dir_entry))->parent: &proc_root // // (&proc_root)->subdir: kmem_cache#29-oX (struct proc_dir_entry)

// ARM10C 20160604
void __init proc_root_init(void)
{
	int err;

	proc_init_inodecache();

	// proc_init_inodecache 에서 한일:
	// struct proc_inode 크기 만큼의 메모리를 할당항는 kmem_cache 할당자를 생성함
	// proc_inode_cachep: kmem_cache#n#28 (struct proc_inode)

	// register_filesystem(&proc_fs_type): 0
	err = register_filesystem(&proc_fs_type);
	// err: 0

	// register_filesystem에서 한일:
	// (&bd_type)->next: &proc_fs_type
	//
	// file system 연결 결과
	// file_systems: sysfs_fs_type -> rootfs_fs_type -> shmem_fs_type -> bd_type -> proc_fs_type

	// err: 0
	if (err)
		return;

	proc_self_init();

	// proc_self_init 에서 한일:
	// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 2 개를 할당 받음
	//
	// (&(&proc_inum_ida)->idr)->id_free 이 idr object new 1번을 가르킴
	// |
	// |-> ---------------------------------------------------------------------------------------------------------------------------
	//     | idr object new 1         | idr object new 0     | idr object 6         | idr object 5         | .... | idr object 0     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//     | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | .... | ary[0]: NULL     |
	//     ---------------------------------------------------------------------------------------------------------------------------
	//
	// (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 1)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 8
	//
	// (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8)
	// (&(&proc_inum_ida)->idr)->layers: 1
	// (&(&proc_inum_ida)->idr)->id_free: (idr object new 0)
	// (&(&proc_inum_ida)->idr)->id_free_cnt: 7
	//
	// (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 1 bit를 1로 set 수행
	// (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 2
	//
	// kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 1) 의 memory 공간을 반환함
	//
	// self_inum: 0xF0000001

	// proc_symlink("mounts", NULL, "self/mounts"): kmem_cache#29-oX (struct proc_dir_entry)
	proc_symlink("mounts", NULL, "self/mounts");

	proc_net_init();

generic.c::proc_net_init()

  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
#ifdef CONFIG_NET
extern int proc_net_init(void);
#else
static inline int proc_net_init(void) { return 0; }
#endif
int __init proc_net_init(void)
{
	proc_symlink("net", NULL, "self/net");

	return register_pernet_subsys(&proc_net_ns_ops);
}

generic.c::proc_symlink()

  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
  • proc_symlink(): net, self/net
// ARM10C 20160604
// "mounts", NULL, "self/mounts"
struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

	// &parent, name: "mounts"
	// S_IFLNK: 0120000, S_IRUGO: 00444, S_IWUGO: 00222, S_IXUGO: 00111
	// __proc_create(NULL, "mounts", 0120777, 1): kmem_cache#29-oX (struct proc_dir_entry)
	ent = __proc_create(&parent, name,
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
	// ent: kmem_cache#29-oX (struct proc_dir_entry)

	// __proc_create 에서 한일:
	// struct proc_dir_entry 만큼 메모리를 할당 받음 kmem_cache#29-oX (struct proc_dir_entry)
	//
	// (kmem_cache#29-oX (struct proc_dir_entry))->name: "mounts"
	// (kmem_cache#29-oX (struct proc_dir_entry))->namelen: 6
	// (kmem_cache#29-oX (struct proc_dir_entry))->mode: 0120777
	// (kmem_cache#29-oX (struct proc_dir_entry))->nlink: 1
	// (&(kmem_cache#29-oX (struct proc_dir_entry))->count)->counter: 1
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock을 이용한 spin lock 초기화 수행
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->raw_lock: { { 0 } }
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->magic: 0xdead4ead
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner: 0xffffffff
	// ((&(kmem_cache#29-oX (struct proc_dir_entry))->pde_unload_lock)->rlock)->owner_cpu: 0xffffffff
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->next: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	// &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list->prev: &(kmem_cache#29-oX (struct proc_dir_entry))->pde_openers->i_sb_list
	//
	// parent: &proc_root

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	if (ent) {
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data, dest: "self/mounts", strlen("self/mounts"): 11
		// ent->size: (kmem_cache#29-oX (struct proc_dir_entry))->size: 11, GFP_KERNEL: 0xD0,
		// kmalloc(12, GFP_KERNEL: 0xD0): kmem_cache#30-oX
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX

		// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX
		if (ent->data) {
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX, dest: "self/mounts"
			// strcpy(kmem_cache#30-oX, "self/mounts"): kmem_cache#30-oX: "self/mounts"
			strcpy((char*)ent->data,dest);
			// ent->data: (kmem_cache#29-oX (struct proc_dir_entry))->data: kmem_cache#30-oX: "self/mounts"

			// parent: NULL, ent: kmem_cache#29-oX (struct proc_dir_entry),
			// proc_register(NULL, kmem_cache#29-oX (struct proc_dir_entry)): 0
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}

			// proc_register 에서 한일:
			// idr_layer_cache를 사용하여 struct idr_layer 의 메모리 kmem_cache#21-oX를 1 개를 할당 받음
			//
			// (&(&proc_inum_ida)->idr)->id_free 이 idr object new 2번을 가르킴
			// |
			// |-> ---------------------------------------------------------------------------------------------------------------------------
			//     | idr object new 2         | idr object new 0     | idr object 6         | idr object 5         | .... | idr object 0     |
			//     ---------------------------------------------------------------------------------------------------------------------------
			//     | ary[0]: idr object new 0 | ary[0]: idr object 6 | ary[0]: idr object 5 | ary[0]: idr object 4 | .... | ary[0]: NULL     |
			//     ---------------------------------------------------------------------------------------------------------------------------
			//
			// (&(&proc_inum_ida)->idr)->id_free: kmem_cache#21-oX (idr object new 2)
			// (&(&proc_inum_ida)->idr)->id_free_cnt: 8
			//
			// (&(&proc_inum_ida)->idr)->top: kmem_cache#21-oX (struct idr_layer) (idr object 8)
			// (&(&proc_inum_ida)->idr)->layers: 1
			// (&(&proc_inum_ida)->idr)->id_free: (idr object new 0)
			// (&(&proc_inum_ida)->idr)->id_free_cnt: 7
			//
			// (kmem_cache#27-oX (struct ida_bitmap))->bitmap 의 2 bit를 1로 set 수행
			// (kmem_cache#27-oX (struct ida_bitmap))->nr_busy: 3
			//
			// kmem_cache인 kmem_cache#21 에서 할당한 object인 kmem_cache#21-oX (idr object new 2) 의 memory 공간을 반환함
			//
			// (kmem_cache#29-oX (struct proc_dir_entry))->low_ino: 0xF0000002
			// (kmem_cache#29-oX (struct proc_dir_entry))->proc_iops: &proc_link_inode_operations
			// (kmem_cache#29-oX (struct proc_dir_entry))->next: NULL
			// (kmem_cache#29-oX (struct proc_dir_entry))->parent: &proc_root
			//
			// (&proc_root)->subdir: kmem_cache#29-oX (struct proc_dir_entry)
		} else {
			kfree(ent);
			ent = NULL;
		}
	}

	// ent: kmem_cache#29-oX (struct proc_dir_entry)
	return ent;
	// return kmem_cache#29-oX (struct proc_dir_entry)
}
EXPORT_SYMBOL(proc_symlink);

proc_net_init()

  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
  • proc_symlink(): net, self/net
  • register_pernet_subsys()
  • call: register_pernet_subsys()
int register_pernet_subsys(struct pernet_operations *ops)
{
	int error;
	mutex_lock(&net_mutex);
	error =  register_pernet_operations(first_device, ops);
	mutex_unlock(&net_mutex);
	return error;
}
EXPORT_SYMBOL_GPL(register_pernet_subsys);

register_pernet_operations()

  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
  • proc_symlink(): net, self/net
  • register_pernet_subsys()
  • call: register_pernet_subsys()
  • mutex_lock()
  • register_pernet_operations()
  • call: register_pernet_operations()
static int register_pernet_operations(struct list_head *list,
				      struct pernet_operations *ops)
{
	int error;

	if (ops->id) {
again:
		error = ida_get_new_above(&net_generic_ids, 1, ops->id);
		if (error < 0) {
			if (error == -EAGAIN) {
				ida_pre_get(&net_generic_ids, GFP_KERNEL);
				goto again;
			}
			return error;
		}
		max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
	}
	error = __register_pernet_operations(list, ops);
	if (error) {
		rcu_barrier();
		if (ops->id)
			ida_remove(&net_generic_ids, *ops->id);
	}

	return error;
}

__register_pernet_operations()

  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
  • proc_symlink(): net, self/net
  • register_pernet_subsys()
  • call: register_pernet_subsys()
  • mutex_lock()
  • register_pernet_operations()
  • call: register_pernet_operations()
#ifdef CONFIG_NET_NS
static int __register_pernet_operations(struct list_head *list,
					struct pernet_operations *ops)
{
	struct net *net;
	int error;
	LIST_HEAD(net_exit_list);

	list_add_tail(&ops->list, list);
	if (ops->init || (ops->id && ops->size)) {
		for_each_net(net) {
			error = ops_init(ops, net);
			if (error)
				goto out_undo;
			list_add_tail(&net->exit_list, &net_exit_list);
		}
	}
	return 0;

out_undo:
	/* If I have an error cleanup all namespaces I initialized */
	list_del(&ops->list);
	ops_exit_list(ops, &net_exit_list);
	ops_free_list(ops, &net_exit_list);
	return error;
}
  • call: start_kernel()
  • proc_root_init()
  • call: proc_root_init()
  • proc_init_inodecache()
  • register_filesystem(&proc_fs_type)
  • proc_self_init()
  • proc_symlink()
  • proc_net_init()
  • call: proc_net_init()
  • proc_symlink(): net, self/net
  • register_pernet_subsys()
  • call: register_pernet_subsys()
  • mutex_lock()
  • register_pernet_operations()
  • call: register_pernet_operations()
  • ida_get_new_above()
  • __register_pernet_operaitions()
  • return: register_pernet_subsys()
int register_pernet_subsys(struct pernet_operations *ops)
{
	int error;
	mutex_lock(&net_mutex);
	error =  register_pernet_operations(first_device, ops);
	mutex_unlock(&net_mutex);
	return error;
}
EXPORT_SYMBOL_GPL(register_pernet_subsys);

log

  • 1st
3b41bb2..540aca8  master     -> origin/master
Updating 3b41bb2..540aca8
Fast-forward
fs/proc/generic.c         | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
fs/proc/internal.h        |   1 +
fs/proc/root.c            |  52 ++++++++++++++++++++++++++++++++++++
include/linux/fs.h        |   1 +
include/linux/gfp.h       |   1 +
include/linux/idr.h       |  16 +++++++++++
include/linux/list.h      |   2 ++
include/linux/slab.h      |   2 ++
include/linux/spinlock.h  |   4 +++
include/uapi/linux/stat.h |   8 ++++++
lib/idr.c                 |   4 +++
11 files changed, 289 insertions(+), 12 deletions(-)
  • 2nd
540aca8..a562949  master     -> origin/master
Updating 540aca8..a562949
Fast-forward
drivers/of/base.c           |  34 +++++++++++++++++++++
fs/proc/generic.c           | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
fs/proc/internal.h          |   8 +++--
fs/proc/proc_devtree.c      |  54 ++++++++++++++++++++++++++++++++-
fs/proc/proc_net.c          |  59 ++++++++++++++++++++++++++++++++++++
fs/proc/proc_sysctl.c       |  58 ++++++++++++++++++++++++++++++++++++
fs/proc/proc_tty.c          | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/proc/root.c              | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
include/linux/kernel.h      |   1 +
include/linux/list.h        |  11 +++++++
include/linux/mutex.h       |  18 +++++++++++
include/linux/of.h          |  10 +++++--
include/linux/proc_fs.h     |  58 ++++++++++++++++++++++++++++++++++++
include/linux/spinlock.h    |   4 +++
include/linux/stat.h        |   9 ++++++
include/linux/sysctl.h      |   5 ++++
include/net/net_namespace.h |  32 +++++++++++++-------
include/uapi/linux/stat.h   |  11 +++++++
kernel/locking/mutex.c      |   2 ++
kernel/sysctl.c             |   3 ++
lib/string.c                |   1 +
net/core/net_namespace.c    |  81 +++++++++++++++++++++++++++++++++++++++++++++++++-
22 files changed, 1188 insertions(+), 23 deletions(-)