정말 오랜만에 다시 글을 올리는 것 같습니다. 한동안 다른 분야의 일에 매진해 봤지만, 역시 리눅스, 특히 커널에 관련된 일을 하는것이 가장 재미있다는 점을 알게 되었습니다.
다시 시작하면서 파일 시스템에 대해서 한동안 살펴볼 생각입니다.
먼저 파일시스템의 등록과 해제에 관련된 함수를 자세히 살펴 보겠습니다.
파일 시스템의 등록과 해제에 관련된 함수들은 다음과 같이 구성되어 있다.
파일시스템을 등록하거나 해제할 때 사용하는 인자로는 file_system_type 구조체를 사용한다. 이 구조체는 다음과 같은 형태로 되어 있으며, 파일시스템의 이름 및 슈퍼블럭(struct super_block)을 가리키는 구조로 되어 있다.
현재 등록되어 있는 파일시스템들의 목록은 /proc/filesystems 파일을 통해서 확인할 수 있다. 이것은 fs/filesystems.c 에 있는 file_systems 변수를 통해서 목록을 얻을 수 있다.
각각은 file_system_type의 next 필드를 통해서 연결되어 있다.
새로운 파일시스템을 등록하는 register_filesystem() 함수에서는 먼저 동일한 이름의 파일시스템이 이미 올라와 있는지를 살펴본다. 만약 이미 동일한 이름의 파일시스템이 적재되어 있다면 -EBUSY를 리턴하며 그렇지 않다면 파일시스템을 전체 링크드 리스트에 추가하게 된다. fine_filesystem은 다음과 같은 코드로 구성되어 있다.
만약, 이름이 일치하는 파일시스템이 발견되지 않는다면 링크드 리스트의 제일 마지막에 대한 next 변수의 주소가 반환된다. 이것은 register_filesystem에서 사용되어 새로 추가된 파일시스템의 주소를 가리키게 된다. 즉, 제일 마지막 위치에 파일시스템이 등록된다.
파일시스템 해지 작업은 링크드리스트에서 제거하는 작업으로 반대의 수순을 밟기 때문에 따로 설명하지는 않겠다.
참고로, 마운트에 관련된 간단한 언급을 하도록 하겠다. 파일시스템은 등록을 했다고 해서 바로 사용할 수 있는 것은 아니다. 파일시스템을 특정 장치(블럭디바이스)에 마운트하는 과정을 거친 후에야 사용이 가능하다. 마운트를 위해서는 sys_mount() 시스템콜이 제공된다. 이 시스템 콜을 통해서 마운트된 파일시스템들은 struct vfsmount 구조체를 통해서 관리된다.
마운트 된 파일시스템들의 리스트는 mnt_list 필드를 통해서 확인 가능하며, 현재 프로세스와 관련해서 마운트된 파일시스템들은 current->namespace->list 를 통해서 확인이 가능하다. 마운트 관련된 내용은 파일 시스템 관련된 오퍼레이션들을 모두 살펴본 후 나중에 정리하도록 하겠다.
다시 시작하면서 파일 시스템에 대해서 한동안 살펴볼 생각입니다.
먼저 파일시스템의 등록과 해제에 관련된 함수를 자세히 살펴 보겠습니다.
파일 시스템의 등록과 해제에 관련된 함수들은 다음과 같이 구성되어 있다.
67 int register_filesystem(struct file_system_type * fs)
68 {
69 int res = 0;
70 struct file_system_type ** p;
71
72 BUG_ON(strchr(fs->name, '.'));
73 if (fs->next)
74 return -EBUSY;
75 INIT_LIST_HEAD(&fs->fs_supers);
76 write_lock(&file_systems_lock);
77 p = find_filesystem(fs->name, strlen(fs->name));
78 if (*p)
79 res = -EBUSY;
80 else
81 *p = fs;
82 write_unlock(&file_systems_lock);
83 return res;
84 }
100 int unregister_filesystem(struct file_system_type * fs)
101 {
102 struct file_system_type ** tmp;
103
104 write_lock(&file_systems_lock); 105 tmp = &file_systems;
106 while (*tmp) {
107 if (fs == *tmp) {
108 *tmp = fs->next;
109 fs->next = NULL;
110 write_unlock(&file_systems_lock);
111 return 0;
112 }
113 tmp = &(*tmp)->next;
114 }
115 write_unlock(&file_systems_lock);
116 return -EINVAL;
117 }
68 {
69 int res = 0;
70 struct file_system_type ** p;
71
72 BUG_ON(strchr(fs->name, '.'));
73 if (fs->next)
74 return -EBUSY;
75 INIT_LIST_HEAD(&fs->fs_supers);
76 write_lock(&file_systems_lock);
77 p = find_filesystem(fs->name, strlen(fs->name));
78 if (*p)
79 res = -EBUSY;
80 else
81 *p = fs;
82 write_unlock(&file_systems_lock);
83 return res;
84 }
100 int unregister_filesystem(struct file_system_type * fs)
101 {
102 struct file_system_type ** tmp;
103
104 write_lock(&file_systems_lock); 105 tmp = &file_systems;
106 while (*tmp) {
107 if (fs == *tmp) {
108 *tmp = fs->next;
109 fs->next = NULL;
110 write_unlock(&file_systems_lock);
111 return 0;
112 }
113 tmp = &(*tmp)->next;
114 }
115 write_unlock(&file_systems_lock);
116 return -EINVAL;
117 }
파일시스템을 등록하거나 해제할 때 사용하는 인자로는 file_system_type 구조체를 사용한다. 이 구조체는 다음과 같은 형태로 되어 있으며, 파일시스템의 이름 및 슈퍼블럭(struct super_block)을 가리키는 구조로 되어 있다.
1390 struct file_system_type {
1391 const char *name;
1392 int fs_flags;
1393 int (*get_sb) (struct file_system_type *, int,
1394 const char *, void *, struct vfsmount *);
1395 void (*kill_sb) (struct super_block *);
1396 struct module *owner;
1397 struct file_system_type * next;
1398 struct list_head fs_supers;
1399 struct lock_class_key s_lock_key;
1400 struct lock_class_key s_umount_key;
1401 };
1391 const char *name;
1392 int fs_flags;
1393 int (*get_sb) (struct file_system_type *, int,
1394 const char *, void *, struct vfsmount *);
1395 void (*kill_sb) (struct super_block *);
1396 struct module *owner;
1397 struct file_system_type * next;
1398 struct list_head fs_supers;
1399 struct lock_class_key s_lock_key;
1400 struct lock_class_key s_umount_key;
1401 };
현재 등록되어 있는 파일시스템들의 목록은 /proc/filesystems 파일을 통해서 확인할 수 있다. 이것은 fs/filesystems.c 에 있는 file_systems 변수를 통해서 목록을 얻을 수 있다.
각각은 file_system_type의 next 필드를 통해서 연결되어 있다.
새로운 파일시스템을 등록하는 register_filesystem() 함수에서는 먼저 동일한 이름의 파일시스템이 이미 올라와 있는지를 살펴본다. 만약 이미 동일한 이름의 파일시스템이 적재되어 있다면 -EBUSY를 리턴하며 그렇지 않다면 파일시스템을 전체 링크드 리스트에 추가하게 된다. fine_filesystem은 다음과 같은 코드로 구성되어 있다.
44 static struct file_system_type **find_filesystem(const char *name, unsigned len)
45 {
46 struct file_system_type **p;
47 for (p=&file_systems; *p; p=&(*p)->next)
48 if (strlen((*p)->name) == len &&
49 strncmp((*p)->name, name, len) == 0)
50 break;
51 return p;
52 }
45 {
46 struct file_system_type **p;
47 for (p=&file_systems; *p; p=&(*p)->next)
48 if (strlen((*p)->name) == len &&
49 strncmp((*p)->name, name, len) == 0)
50 break;
51 return p;
52 }
만약, 이름이 일치하는 파일시스템이 발견되지 않는다면 링크드 리스트의 제일 마지막에 대한 next 변수의 주소가 반환된다. 이것은 register_filesystem에서 사용되어 새로 추가된 파일시스템의 주소를 가리키게 된다. 즉, 제일 마지막 위치에 파일시스템이 등록된다.
파일시스템 해지 작업은 링크드리스트에서 제거하는 작업으로 반대의 수순을 밟기 때문에 따로 설명하지는 않겠다.
참고로, 마운트에 관련된 간단한 언급을 하도록 하겠다. 파일시스템은 등록을 했다고 해서 바로 사용할 수 있는 것은 아니다. 파일시스템을 특정 장치(블럭디바이스)에 마운트하는 과정을 거친 후에야 사용이 가능하다. 마운트를 위해서는 sys_mount() 시스템콜이 제공된다. 이 시스템 콜을 통해서 마운트된 파일시스템들은 struct vfsmount 구조체를 통해서 관리된다.
38 struct vfsmount {
39 struct list_head mnt_hash;
40 struct vfsmount *mnt_parent; /* fs we are mounted on */
41 struct dentry *mnt_mountpoint; /* dentry of mountpoint */
42 struct dentry *mnt_root; /* root of the mounted tree */
43 struct super_block *mnt_sb; /* pointer to superblock */
44 struct list_head mnt_mounts; /* list of children, anchored here */
45 struct list_head mnt_child; /* and going through their mnt_child */
46 int mnt_flags;
47 /* 4 bytes hole on 64bits arches */
48 char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
49 struct list_head mnt_list;
50 struct list_head mnt_expire; /* link in fs-specific expiry list */
51 struct list_head mnt_share; /* circular list of shared mounts */
52 struct list_head mnt_slave_list;/* list of slave mounts */
53 struct list_head mnt_slave; /* slave list entry */
54 struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
55 struct mnt_namespace *mnt_ns; /* containing namespace */
56 /*
57 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
58 * to let these frequently modified fields in a separate cache line
59 * (so that reads of mnt_flags wont ping-pong on SMP machines)
60 */
61 atomic_t mnt_count;
62 int mnt_expiry_mark; /* true if marked for expiry */
63 int mnt_pinned;
64 };
39 struct list_head mnt_hash;
40 struct vfsmount *mnt_parent; /* fs we are mounted on */
41 struct dentry *mnt_mountpoint; /* dentry of mountpoint */
42 struct dentry *mnt_root; /* root of the mounted tree */
43 struct super_block *mnt_sb; /* pointer to superblock */
44 struct list_head mnt_mounts; /* list of children, anchored here */
45 struct list_head mnt_child; /* and going through their mnt_child */
46 int mnt_flags;
47 /* 4 bytes hole on 64bits arches */
48 char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
49 struct list_head mnt_list;
50 struct list_head mnt_expire; /* link in fs-specific expiry list */
51 struct list_head mnt_share; /* circular list of shared mounts */
52 struct list_head mnt_slave_list;/* list of slave mounts */
53 struct list_head mnt_slave; /* slave list entry */
54 struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
55 struct mnt_namespace *mnt_ns; /* containing namespace */
56 /*
57 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
58 * to let these frequently modified fields in a separate cache line
59 * (so that reads of mnt_flags wont ping-pong on SMP machines)
60 */
61 atomic_t mnt_count;
62 int mnt_expiry_mark; /* true if marked for expiry */
63 int mnt_pinned;
64 };
마운트 된 파일시스템들의 리스트는 mnt_list 필드를 통해서 확인 가능하며, 현재 프로세스와 관련해서 마운트된 파일시스템들은 current->namespace->list 를 통해서 확인이 가능하다. 마운트 관련된 내용은 파일 시스템 관련된 오퍼레이션들을 모두 살펴본 후 나중에 정리하도록 하겠다.
'Linux > Filesystem' 카테고리의 다른 글
| HAMMER 파일 시스템 (0) | 2007/12/06 |
|---|---|
| FUSE 파일 시스템 Overview (0) | 2007/11/12 |
| 파일 시스템의 주요 구조체들 (0) | 2007/11/12 |
| 파일 시스템 등록과 해지에 관련된 함수 살펴보기 (0) | 2007/11/09 |
TAG filesystem
이올린에 북마크하기
이올린에 추천하기

