Skip to content

Latest commit

 

History

History
1176 lines (967 loc) · 35.1 KB

a10c_121.md

File metadata and controls

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

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

121 주차 진도

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

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

	mnt_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를 연결함

namespace.c::mnt_init()

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

// 2015/10/24 종료
	if (!mount_hashtable || !mountpoint_hashtable)
		panic("Failed to allocate mount hash table\n");

	for (u = 0; u <= m_hash_mask; u++)
	    // u: 0,
		// INIT_HLIST_HEAD(&mount_hashtable[0]: (((&mount_hash_table[0])->first = NULL) 
		INIT_HLIST_HEAD(&mount_hashtable[u]);
		// 1~4095까지 mount_hashtable 초기화

	for (u = 0; u <= mp_hash_mask; u++)
	    // u: 0,
		// INIT_HLIST_HEAD(&mountpoint_hashtable[0]: (((&mountpoint_hashtable[0])->first = NULL) 
		INIT_HLIST_HEAD(&mountpoint_hashtable[u]);
		// 1~4095까지 mountpoint_hashtable 초기화

	err = sysfs_init();
  • lish.h::INIT_HLIST_HEAD()
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)

mount.c::sysfs_init()

  • start_kernel()->vfs_caches_init()
  • mnt_init()
  • sysfs_init()
int __init sysfs_init(void)
{
    // ENOMEM: 12
    int err = -ENOMEM;

	sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
					      sizeof(struct sysfs_dirent),
					      0, 0, NULL);

	if (!sysfs_dir_cachep)
		goto out;

	err = sysfs_inode_init();
	if (err)
		goto out_err;
  • struct sysfs_dirent
struct sysfs_dirent {
	atomic_t		s_count;
	atomic_t		s_active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	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;
};
  • struct sysfs_elem_dir
struct sysfs_elem_dir {
	struct kobject		*kobj;

	unsigned long		subdirs;
	/* children rbtree starts here and goes through sd->s_rb */
	struct rb_root		children;
};
  • struct sysfs_elem_symlink
struct sysfs_elem_symlink {
	struct sysfs_dirent	*target_sd;
};
  • struct sysfs_elem_attr
struct sysfs_elem_attr {
	union {
		struct attribute	*attr;
		struct bin_attribute	*bin_attr;
	};
	struct sysfs_open_dirent *open;
};
  • struct inode_attrs
struct sysfs_inode_attrs {
	struct iattr	ia_iattr;
	void		*ia_secdata;
	u32		ia_secdata_len;
};
  • kmem_cache_create()
struct kmem_cache *
kmem_cache_create(const char *name, size_t size, size_t align,
		  unsigned long flags, void (*ctor)(void *))
{
	return kmem_cache_create_memcg(NULL, name, size, align, flags, ctor, NULL);
	// return kmem_cache#1	
}
EXPORT_SYMBOL(kmem_cache_create);

sysfs_inode_init()

  • start_kernel()->vfs_caches_init()
  • mnt_init()
  • sysfs_init()
    • sysfs_inode_init()
int __init sysfs_inode_init(void)
{
	return bdi_init(&sysfs_backing_dev_info);
}

backing-dev.c::bdi_init()

  • start_kernel()->vfs_caches_init()
  • mnt_init()
  • sysfs_init()
    • sysfs_inode_init()
  • struct backing_dev_info
struct backing_dev_info {
	struct list_head bdi_list;
	unsigned long ra_pages;	/* max readahead in PAGE_CACHE_SIZE units */
	unsigned long state;	/* Always use atomic bitops on this */
	unsigned int capabilities; /* Device capabilities */
	congested_fn *congested_fn; /* Function pointer if device is md/dm */
	void *congested_data;	/* Pointer to aux data for congested func */

	char *name;

	struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];

	unsigned long bw_time_stamp;	/* last time write bw is updated */
	unsigned long dirtied_stamp;
	unsigned long written_stamp;	/* pages written at bw_time_stamp */
	unsigned long write_bandwidth;	/* the estimated write bandwidth */
	unsigned long avg_write_bandwidth; /* further smoothed write bw */

	/*
	 * The base dirty throttle rate, re-calculated on every 200ms.
	 * All the bdi tasks' dirty rate will be curbed under it.
	 * @dirty_ratelimit tracks the estimated @balanced_dirty_ratelimit
	 * in small steps and is much more smooth/stable than the latter.
	 */
	unsigned long dirty_ratelimit;
	unsigned long balanced_dirty_ratelimit;

	struct fprop_local_percpu completions;
	int dirty_exceeded;

	unsigned int min_ratio;
	unsigned int max_ratio, max_prop_frac;

	struct bdi_writeback wb;  /* default writeback info for this bdi */
	spinlock_t wb_lock;	  /* protects work_list & wb.dwork scheduling */

	struct list_head work_list;

	struct device *dev;

	struct timer_list laptop_mode_wb_timer;

#ifdef CONFIG_DEBUG_FS
	struct dentry *debug_dir;
	struct dentry *debug_stats;
#endif
};
int bdi_init(struct backing_dev_info *bdi)
{
	int i, err;

	bdi->dev = NULL;

	bdi->min_ratio = 0;
	bdi->max_ratio = 100;
	bdi->max_prop_frac = FPROP_FRAC_BASE;
	spin_lock_init(&bdi->wb_lock);
	INIT_LIST_HEAD(&bdi->bdi_list);
	INIT_LIST_HEAD(&bdi->work_list);

	bdi_wb_init(&bdi->wb, bdi);

bdi_wb_init()

  • struct bdi_writeback
  • sizeof(strcut bid_writeback) : 104Bytes
struct bdi_writeback {
	struct backing_dev_info *bdi;	/* our parent bdi */
	unsigned int nr;

	unsigned long last_old_flush;	/* last old data flush */

	struct delayed_work dwork;	/* work item used for writeback */
	struct list_head b_dirty;	/* dirty inodes */
	struct list_head b_io;		/* parked for writeback */
	struct list_head b_more_io;	/* parked for more writeback */
	spinlock_t list_lock;		/* protects the b_* lists */
};
  • struct backing_dev_info
struct backing_dev_info {
	struct list_head bdi_list;
	unsigned long ra_pages;	/* max readahead in PAGE_CACHE_SIZE units */
	unsigned long state;	/* Always use atomic bitops on this */
	unsigned int capabilities; /* Device capabilities */
	congested_fn *congested_fn; /* Function pointer if device is md/dm */
	void *congested_data;	/* Pointer to aux data for congested func */

	char *name;

	struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];

	unsigned long bw_time_stamp;	/* last time write bw is updated */
	unsigned long dirtied_stamp;
	unsigned long written_stamp;	/* pages written at bw_time_stamp */
	unsigned long write_bandwidth;	/* the estimated write bandwidth */
	unsigned long avg_write_bandwidth; /* further smoothed write bw */

	/*
	 * The base dirty throttle rate, re-calculated on every 200ms.
	 * All the bdi tasks' dirty rate will be curbed under it.
	 * @dirty_ratelimit tracks the estimated @balanced_dirty_ratelimit
	 * in small steps and is much more smooth/stable than the latter.
	 */
	unsigned long dirty_ratelimit;
	unsigned long balanced_dirty_ratelimit;

	struct fprop_local_percpu completions;
	int dirty_exceeded;

	unsigned int min_ratio;
	unsigned int max_ratio, max_prop_frac;

	struct bdi_writeback wb;  /* default writeback info for this bdi */
	spinlock_t wb_lock;	  /* protects work_list & wb.dwork scheduling */

	struct list_head work_list;

	struct device *dev;

	struct timer_list laptop_mode_wb_timer;

#ifdef CONFIG_DEBUG_FS
	struct dentry *debug_dir;
	struct dentry *debug_stats;
#endif
};
static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
{
	memset(wb, 0, sizeof(*wb));

	wb->bdi = bdi;
	wb->last_old_flush = jiffies;
	INIT_LIST_HEAD(&wb->b_dirty);
	INIT_LIST_HEAD(&wb->b_io);
	INIT_LIST_HEAD(&wb->b_more_io);
	spin_lock_init(&wb->list_lock);
	INIT_DELAYED_WORK(&wb->dwork, bdi_writeback_workfn);
}
  • INIT_LIST_HEAD()
static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}
  • INIT_DELAYED_WORK()
#define INIT_DELAYED_WORK(_work, _func)					\
	__INIT_DELAYED_WORK(_work, _func, 0)
  • __INIT_DELAYED_WORK()
#define __INIT_DELAYED_WORK(_work, _func, _tflags)			\
	do {								\
		INIT_WORK(&(_work)->work, (_func));			\
		__setup_timer(&(_work)->timer, delayed_work_timer_fn,	\
			      (unsigned long)(_work),			\
			      (_tflags) | TIMER_IRQSAFE);		\
	} while (0)
- INIT_WORK
#define INIT_WORK(_work, _func)						\
	do {								\
		__INIT_WORK((_work), (_func), 0);			\
	} while (0)
  - __INIT_WORK()
static inline void __init_work(struct work_struct *work, int onstack) { }

따라서 이들 매크로를 풀면.


  • __setup_timer()
#define __setup_timer(_timer, _fn, _data, _flags)			\
	do {								\
		__init_timer((_timer), (_flags));			\
		(_timer)->function = (_fn);				\
		(_timer)->data = (_data);				\
	} while (0)
 - __init_timer()
#define __init_timer(_timer, _flags)					\
	init_timer_key((_timer), (_flags), NULL, NULL)

따라서 정리하면.

  • sysfs_inode_init에서 한일:
  • (&sysfs_backing_dev_info)->dev: NULL
  • (&sysfs_backing_dev_info)->min_ratio: 0
  • (&sysfs_backing_dev_info)->max_ratio: 100
  • (&sysfs_backing_dev_info)->max_prop_frac: 0x400
  • &(&sysfs_backing_dev_info)->wb_lock 을 이용한 spinlock 초기화 수행
  • (&(&sysfs_backing_dev_info)->bdi_list)->next: &(&sysfs_backing_dev_info)->bdi_list
  • (&(&sysfs_backing_dev_info)->bdi_list)->prev: &(&sysfs_backing_dev_info)->bdi_list
  • (&(&sysfs_backing_dev_info)->work_list)->next: &(&sysfs_backing_dev_info)->work_list
  • (&(&sysfs_backing_dev_info)->work_list)->prev: &(&sysfs_backing_dev_info)->work_list
  • (&sysfs_backing_dev_info)->wb 의 맴버값을 0으로 초기화함
  • (&(&sysfs_backing_dev_info)->wb)->bdi: &sysfs_backing_dev_info
  • (&(&sysfs_backing_dev_info)->wb)->last_old_flush: XXX
  • (&(&(&sysfs_backing_dev_info)->wb)->b_dirty)->next: &(&(&sysfs_backing_dev_info)->wb)->b_dirty
  • (&(&(&sysfs_backing_dev_info)->wb)->b_dirty)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_dirty
  • (&(&(&sysfs_backing_dev_info)->wb)->b_io)->next: &(&(&sysfs_backing_dev_info)->wb)->b_io
  • (&(&(&sysfs_backing_dev_info)->wb)->b_io)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_io
  • (&(&(&sysfs_backing_dev_info)->wb)->b_more_io)->next: &(&(&sysfs_backing_dev_info)->wb)->b_more_io
  • (&(&(&sysfs_backing_dev_info)->wb)->b_more_io)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_more_io
  • &(&(&sysfs_backing_dev_info)->wb)->list_lock 을 이용한 spinlock 초기화 수행
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->data: { 0xFFFFFFE0 }
  • (&(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry)->next: &(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry
  • (&(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry)->prev: &(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->func: bdi_writeback_workfn
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->entry.next: NULL
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->base: [pcp0] tvec_bases | 0x2
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->slack: -1
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->function = (delayed_work_timer_fn);
  • (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->data = ((unsigned long)(&(&(&sysfs_backing_dev_info)->wb)->dwork));
  • (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
  • (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->magic: 0xdead4ead
  • (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->owner: 0xffffffff
  • (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
  • (&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list)->next: &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list
  • (&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list)->prev: &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list
  • (&(&sysfs_backing_dev_info)->bdi_stat[0...3])->count: 0
  • (&(&sysfs_backing_dev_info)->bdi_stat[0...3])->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
  • list head 인 &percpu_counters에 &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list를 연결함
  • (&sysfs_backing_dev_info)->dirty_exceeded: 0
  • (&sysfs_backing_dev_info)->bw_time_stamp: XXX
  • (&sysfs_backing_dev_info)->written_stamp: 0
  • (&sysfs_backing_dev_info)->balanced_dirty_ratelimit: 0x6400
  • (&sysfs_backing_dev_info)->dirty_ratelimit: 0x6400
  • (&sysfs_backing_dev_info)->write_bandwidth: 0x6400
  • (&sysfs_backing_dev_info)->avg_write_bandwidth: 0x6400
  • (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
  • (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->magic: 0xdead4ead
  • (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->owner: 0xffffffff
  • (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
  • (&(&(&(&sysfs_backing_dev_info)->completions)->events)->list)->next: &(&(&(&sysfs_backing_dev_info)->completions)->events)->list
  • (&(&(&(&sysfs_backing_dev_info)->completions)->events)->list)->prev: &(&(&(&sysfs_backing_dev_info)->completions)->events)->list
  • (&(&(&sysfs_backing_dev_info)->completions)->events)->count: 0
  • (&(&(&sysfs_backing_dev_info)->completions)->events)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
  • list head 인 &percpu_counters에 &(&(&(&sysfs_backing_dev_info)->completions)->events)->list를 연결함
  • (&(&sysfs_backing_dev_info)->completions)->period: 0
  • &(&(&sysfs_backing_dev_info)->completions)->lock을 이용한 spinlock 초기화 수행

backing-dev.c::bid_init()

int bdi_init(struct backing_dev_info *bdi)
{
	int i, err;

	bdi->dev = NULL;

	bdi->min_ratio = 0;
	bdi->max_ratio = 100;
	bdi->max_prop_frac = FPROP_FRAC_BASE;
	spin_lock_init(&bdi->wb_lock);
	INIT_LIST_HEAD(&bdi->bdi_list);
	INIT_LIST_HEAD(&bdi->work_list);

	bdi_wb_init(&bdi->wb, bdi);

	for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
		err = percpu_counter_init(&bdi->bdi_stat[i], 0);
		if (err)
			goto err;
	}
int bdi_init(struct backing_dev_info *bdi)
{
...
	for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
		err = percpu_counter_init(&bdi->bdi_stat[i], 0);
		if (err)
			goto err;
	}

    bdi->dirty_exceeded = 0;

	bdi->bw_time_stamp = jiffies;
	bdi->written_stamp = 0;

	bdi->balanced_dirty_ratelimit = INIT_BW;
	bdi->dirty_ratelimit = INIT_BW;
	bdi->write_bandwidth = INIT_BW;
	bdi->avg_write_bandwidth = INIT_BW;

	err = fprop_local_init_percpu(&bdi->completions);
  • fprop_local_init_percpu()
int bdi_init(struct backing_dev_info *bdi)
{
...
	err = fprop_local_init_percpu(&bdi->completions);
	if (err) {
err:
		while (i--)
			percpu_counter_destroy(&bdi->bdi_stat[i]);
	}

	return err;
}
EXPORT_SYMBOL(bdi_init);

mount.c::sysfs_init()

// ARM10C 20151031
int __init sysfs_init(void)
{
	// ENOMEM: 12
	int err = -ENOMEM;
	// err: -12

	// sizeof(struct sysfs_dirent): 64 bytes
	// kmem_cache_create("sysfs_dir_cache", 64, 0, 0, NULL): kmem_cache#1
	sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache",
					      sizeof(struct sysfs_dirent),
					      0, 0, NULL);
	// sysfs_dir_cachep: kmem_cache#1

	// sysfs_dir_cachep: kmem_cache#1
	if (!sysfs_dir_cachep)
		goto out;

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

	// sysfs_inode_init에서 한일:
	// (&sysfs_backing_dev_info)->dev: NULL
	// (&sysfs_backing_dev_info)->min_ratio: 0
	// (&sysfs_backing_dev_info)->max_ratio: 100
	// (&sysfs_backing_dev_info)->max_prop_frac: 0x400
	// &(&sysfs_backing_dev_info)->wb_lock 을 이용한 spinlock 초기화 수행
	// (&(&sysfs_backing_dev_info)->bdi_list)->next: &(&sysfs_backing_dev_info)->bdi_list
	// (&(&sysfs_backing_dev_info)->bdi_list)->prev: &(&sysfs_backing_dev_info)->bdi_list
	// (&(&sysfs_backing_dev_info)->work_list)->next: &(&sysfs_backing_dev_info)->work_list
	// (&(&sysfs_backing_dev_info)->work_list)->prev: &(&sysfs_backing_dev_info)->work_list
	//
	// (&sysfs_backing_dev_info)->wb 의 맴버값을 0으로 초기화함
	// (&(&sysfs_backing_dev_info)->wb)->bdi: &sysfs_backing_dev_info
	// (&(&sysfs_backing_dev_info)->wb)->last_old_flush: XXX
	// (&(&(&sysfs_backing_dev_info)->wb)->b_dirty)->next: &(&(&sysfs_backing_dev_info)->wb)->b_dirty
	// (&(&(&sysfs_backing_dev_info)->wb)->b_dirty)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_dirty
	// (&(&(&sysfs_backing_dev_info)->wb)->b_io)->next: &(&(&sysfs_backing_dev_info)->wb)->b_io
	// (&(&(&sysfs_backing_dev_info)->wb)->b_io)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_io
	// (&(&(&sysfs_backing_dev_info)->wb)->b_more_io)->next: &(&(&sysfs_backing_dev_info)->wb)->b_more_io
	// (&(&(&sysfs_backing_dev_info)->wb)->b_more_io)->prev: &(&(&sysfs_backing_dev_info)->wb)->b_more_io
	// &(&(&sysfs_backing_dev_info)->wb)->list_lock 을 이용한 spinlock 초기화 수행
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->data: { 0xFFFFFFE0 }
	// (&(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry)->next: &(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry
	// (&(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry)->prev: &(&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->entry
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->work)->func: bdi_writeback_workfn
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->entry.next: NULL
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->base: [pcp0] tvec_bases | 0x2
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->slack: -1
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->function = (delayed_work_timer_fn);
	// (&(&(&(&sysfs_backing_dev_info)->wb)->dwork)->timer)->data = ((unsigned long)(&(&(&sysfs_backing_dev_info)->wb)->dwork));
	//
	// (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
	// (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->magic: 0xdead4ead
	// (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->owner: 0xffffffff
	// (&(&(&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
	// (&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list)->next: &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list
	// (&(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list)->prev: &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list
	// (&(&sysfs_backing_dev_info)->bdi_stat[0...3])->count: 0
	// (&(&sysfs_backing_dev_info)->bdi_stat[0...3])->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
	// list head 인 &percpu_counters에 &(&(&sysfs_backing_dev_info)->bdi_stat[0...3])->list를 연결함
	//
	// (&sysfs_backing_dev_info)->dirty_exceeded: 0
	// (&sysfs_backing_dev_info)->bw_time_stamp: XXX
	// (&sysfs_backing_dev_info)->written_stamp: 0
	// (&sysfs_backing_dev_info)->balanced_dirty_ratelimit: 0x6400
	// (&sysfs_backing_dev_info)->dirty_ratelimit: 0x6400
	// (&sysfs_backing_dev_info)->write_bandwidth: 0x6400
	// (&sysfs_backing_dev_info)->avg_write_bandwidth: 0x6400
	//
	// (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->raw_lock: { { 0 } }
	// (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->magic: 0xdead4ead
	// (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->owner: 0xffffffff
	// (&(&(&(&(&(&sysfs_backing_dev_info)->completions)->events)->lock)->wait_lock)->rlock)->owner_cpu: 0xffffffff
	// (&(&(&(&sysfs_backing_dev_info)->completions)->events)->list)->next: &(&(&(&sysfs_backing_dev_info)->completions)->events)->list
	// (&(&(&(&sysfs_backing_dev_info)->completions)->events)->list)->prev: &(&(&(&sysfs_backing_dev_info)->completions)->events)->list
	// (&(&(&sysfs_backing_dev_info)->completions)->events)->count: 0
	// (&(&(&sysfs_backing_dev_info)->completions)->events)->counters: kmem_cache#26-o0 에서 할당된 4 bytes 메모리 주소
	// list head 인 &percpu_counters에 &(&(&(&sysfs_backing_dev_info)->completions)->events)->list를 연결함
	// (&(&sysfs_backing_dev_info)->completions)->period: 0
	// &(&(&sysfs_backing_dev_info)->completions)->lock을 이용한 spinlock 초기화 수행

	if (err)
		goto out_err;

	err = register_filesystem(&sysfs_fs_type);

filesystem.c::registar_filesystem()

int register_filesystem(struct file_system_type * fs)
{
	int res = 0;
	struct file_system_type ** p;

	BUG_ON(strchr(fs->name, '.'));
	if (fs->next)
		return -EBUSY;
	write_lock(&file_systems_lock);
	p = find_filesystem(fs->name, strlen(fs->name));
	if (*p)
		res = -EBUSY;
	else
		*p = fs;
	write_unlock(&file_systems_lock);
	return res;
}
  • write_lock(&file_systems_lock);

  • p = fine_filesystem(fs->name, strlen(fs->name));

  • struct file_system_type

struct file_system_type {
	const char *name;
	int fs_flags;
#define FS_REQUIRES_DEV		1 
#define FS_BINARY_MOUNTDATA	2
#define FS_HAS_SUBTYPE		4
#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
#define FS_USERNS_DEV_MOUNT	16 /* A userns mount does not imply MNT_NODEV */
#define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
	struct dentry *(*mount) (struct file_system_type *, int,
		       const char *, void *);
	void (*kill_sb) (struct super_block *);
	struct module *owner;
	struct file_system_type * next;
	struct hlist_head fs_supers;

	struct lock_class_key s_lock_key;
	struct lock_class_key s_umount_key;
	struct lock_class_key s_vfs_rename_key;
	struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];

	struct lock_class_key i_lock_key;
	struct lock_class_key i_mutex_key;
	struct lock_class_key i_mutex_dir_key;
};
static struct file_system_type **find_filesystem(const char *name, unsigned len)
{
	struct file_system_type **p;
	for (p=&file_systems; *p; p=&(*p)->next)
		if (strlen((*p)->name) == len &&
		    strncmp((*p)->name, name, len) == 0)
			break;
	return p;
}
  • register_filesystem()
int register_filesystem(struct file_system_type * fs)
{
	int res = 0;
	struct file_system_type ** p;

	BUG_ON(strchr(fs->name, '.'));
	if (fs->next)
		return -EBUSY;
	write_lock(&file_systems_lock);
	p = find_filesystem(fs->name, strlen(fs->name));
	if (*p)
		res = -EBUSY;
	else
		*p = fs;
	write_unlock(&file_systems_lock);
	return res;
}

mount.c::sysfs_init()

  • register_filesystem에서 한일
  • file_systems: &sysfs_fs_type
// ARM10C 20151031
int __init sysfs_init(void)
{
...
	err = register_filesystem(&sysfs_fs_type);

	if (!err) {
		sysfs_mnt = kern_mount(&sysfs_fs_type);
		if (IS_ERR(sysfs_mnt)) {
			printk(KERN_ERR "sysfs: could not mount!\n");
			err = PTR_ERR(sysfs_mnt);
			sysfs_mnt = NULL;
			unregister_filesystem(&sysfs_fs_type);
			goto out_err;
		}
	} else
		goto out_err;
  • kern_mount(&sysfs_fs_type)
#define kern_mount(type) kern_mount_data(type, NULL)
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{
	struct vfsmount *mnt;
	mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
	if (!IS_ERR(mnt)) {
		/*
		 * it is a longterm mount, don't release mnt until
		 * we unmount before file sys is unregistered
		*/
		real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
	}
	return mnt;
}
EXPORT_SYMBOL_GPL(kern_mount_data);
  • vfs_kern_mount()

namespace.c::vfs_kern_mount()

struct vfsmount *
vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
	struct mount *mnt;
	struct dentry *root;

    // type: &sysfs_
	if (!type)
		return ERR_PTR(-ENODEV);

	mnt = alloc_vfsmnt(name);
	if (!mnt)
		return ERR_PTR(-ENOMEM);

	if (flags & MS_KERNMOUNT)
		mnt->mnt.mnt_flags = MNT_INTERNAL;

	root = mount_fs(type, flags, name, data);
	if (IS_ERR(root)) {
		free_vfsmnt(mnt);
		return ERR_CAST(root);
	}

	mnt->mnt.mnt_root = root;
	mnt->mnt.mnt_sb = root->d_sb;
	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
	mnt->mnt_parent = mnt;
	lock_mount_hash();
	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
	unlock_mount_hash();
	return &mnt->mnt;
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);

->aaloc_vfsmnt()

static struct mount *alloc_vfsmnt(const char *name)
{
	struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
  • kmem_cache_zalloc()
static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags)
{
	return kmem_cache_alloc(k, flags | __GFP_ZERO);
}
  • kmem_cache_alloc()
void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
{
	void *ret = slab_alloc(s, gfpflags, _RET_IP_);
	trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size,
				s->size, gfpflags);
}
EXPORT_SYMBOL(kmem_cache_alloc);
static struct mount *alloc_vfsmnt(const char *name)
{
	struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);

    if (mnt) {
		int err;

		err = mnt_alloc_id(mnt);
  • mnt_alloc_id()
static int mnt_alloc_id(struct mount *mnt)
{
	int res;

retry:
	ida_pre_get(&mnt_id_ida, GFP_KERNEL);
	spin_lock(&mnt_id_lock);
	res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id);
	if (!res)
		mnt_id_start = mnt->mnt_id + 1;
	spin_unlock(&mnt_id_lock);
	if (res == -EAGAIN)
		goto retry;

	return res;
}
  • ida_pre_get()
int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
{
	/* allocate idr_layers */
	if (!__idr_pre_get(&ida->idr, gfp_mask))
		return 0;

	/* allocate free_bitmap */
	if (!ida->free_bitmap) {
		struct ida_bitmap *bitmap;

		bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
		if (!bitmap)
			return 0;

		free_bitmap(ida, bitmap);
	}

	return 1;
}
EXPORT_SYMBOL(ida_pre_get);
  • __idr_pre_get()
int __idr_pre_get(struct idr *idp, gfp_t gfp_mask)
{
	while (idp->id_free_cnt < MAX_IDR_FREE) {
		struct idr_layer *new;
		new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
		if (new == NULL)
			return (0);
		move_to_free_list(idp, new);
	}
	return 1;
}
EXPORT_SYMBOL(__idr_pre_get);
static struct mount *alloc_vfsmnt(const char *name)
{
	struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
...

		err = mnt_alloc_id(mnt);

		if (err)
			goto out_free_cache;

		if (name) {
			mnt->mnt_devname = kstrdup(name, GFP_KERNEL);
			if (!mnt->mnt_devname)
				goto out_free_id;
		}

#ifdef CONFIG_SMP
		mnt->mnt_pcp = alloc_percpu(struct mnt_pcp);
		if (!mnt->mnt_pcp)
			goto out_free_devname;

		this_cpu_add(mnt->mnt_pcp->mnt_count, 1);
#else
		mnt->mnt_count = 1;
		mnt->mnt_writers = 0;
#endif

		INIT_HLIST_NODE(&mnt->mnt_hash);
		INIT_LIST_HEAD(&mnt->mnt_child);
		INIT_LIST_HEAD(&mnt->mnt_mounts);
		INIT_LIST_HEAD(&mnt->mnt_list);
		INIT_LIST_HEAD(&mnt->mnt_expire);
		INIT_LIST_HEAD(&mnt->mnt_share);
		INIT_LIST_HEAD(&mnt->mnt_slave_list);
		INIT_LIST_HEAD(&mnt->mnt_slave);
#ifdef CONFIG_FSNOTIFY
		INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
#endif
	}
	return mnt;

#ifdef CONFIG_SMP
out_free_devname:
	kfree(mnt->mnt_devname);
#endif
out_free_id:
	mnt_free_id(mnt);
out_free_cache:
	kmem_cache_free(mnt_cache, mnt);
	return NULL;
}

log

a463952..6b8f3eb  master     -> origin/master
Updating a463952..6b8f3eb
Fast-forward
arch/arm/include/asm/page.h           |   1 +
fs/fs-writeback.c                     |   1 +
fs/namespace.c                        |  19 +++++++++++++++
fs/sysfs/inode.c                      |  65 +++++++++++++++++++++++++++++++++++++++++++++++++++
fs/sysfs/mount.c                      |  73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/sysfs/sysfs.h                      |  10 +++++++-
include/asm-generic/percpu.h          |   3 +++
include/linux/backing-dev.h           |   7 +++++-
include/linux/flex_proportions.h      |   5 ++++
include/linux/list.h                  |  10 ++++++++
include/linux/lockdep.h               |   2 ++
include/linux/percpu_counter.h        |   4 ++++
include/linux/rbtree.h                |   1 +
include/linux/slub_def.h              |   1 +
include/linux/spinlock.h              |   9 +++++++
include/linux/spinlock_types.h        |   1 +
include/linux/sysfs.h                 |   2 +-
include/linux/timer.h                 |  18 +++++++++++++-
include/linux/types.h                 |   1 +
include/linux/workqueue.h             |  40 +++++++++++++++++++++++++++++++
include/uapi/asm-generic/errno-base.h |   2 ++
kernel/timer.c                        |  40 +++++++++++++++++++++++++++----
lib/flex_proportions.c                |  28 ++++++++++++++++++++++
lib/percpu_counter.c                  |   2 ++
mm/backing-dev.c                      | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
mm/slab_common.c                      |   7 ++++++
26 files changed, 513 insertions(+), 9 deletions(-)
  • 2nd log
d153cd2..a463952  master     -> origin/master
Updating d153cd2..a463952
Fast-forward
fs/namespace.c       |   8 ++-
include/linux/log2.h |   2 +
mm/page_alloc.c      | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------
3 files changed, 245 insertions(+), 175 deletions(-)
  • 3th log
6b8f3eb..97a9fed  master     -> origin/master
Updating 6b8f3eb..97a9fed
Fast-forward
arch/arm/include/asm/spinlock.h       |   1 +
arch/arm/include/asm/spinlock_types.h |   2 ++
fs/filesystems.c                      |  44 ++++++++++++++++++++++++++++++++++
fs/mount.h                            |   1 +
fs/namespace.c                        |  67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/sysfs/mount.c                      |  10 ++++++++
include/linux/dcache.h                |   1 +
include/linux/fs.h                    |   3 +++
include/linux/gfp.h                   |   1 +
include/linux/idr.h                   | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/lockdep.h               |   1 +
include/linux/mount.h                 |   1 +
include/linux/preempt.h               |   1 +
include/linux/rwlock.h                |   2 ++
include/linux/rwlock_api_smp.h        |   2 ++
include/linux/rwlock_types.h          |  39 ++++++++++++++++++++++++++++++-
include/linux/slab.h                  |  32 +++++++++++++++++++++++--
include/linux/spinlock.h              |   6 +++++
include/linux/spinlock_types.h        |  35 +++++++++++++++++++++++++++
include/uapi/linux/fs.h               |   2 ++
kernel/locking/spinlock.c             |   2 ++
kernel/locking/spinlock_debug.c       |   2 ++
lib/idr.c                             | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/string.c                          |   4 ++++
mm/slub.c                             |  15 ++++++++++++
25 files changed, 550 insertions(+), 3 deletions(-)