Virtual File System
1. 概要
sys_open,sys_readなどのシステムコールのエントリルーチンと実際のファイルシステムの間に入るレイヤ。struct fileのf_opに登録されている処理を呼び出すことで実際のファイルシステムへ処理を渡す。
2. 処理概要
2.1 open処理
open()システムコールのエントリルーチンはsys_open()。sys_open()はdo_sys_open()を呼び出す。do_sys_open()はget_unused_fd()により未使用のファイルディスクリプタを取得し、ファイル管理用のfile構造体をdo_filp_open()で生成する。do_filp_open()はopen_namei()を呼び出す。open_namei()は実質open処理のほとんどを行なう。
do_sys_open()の処理概要
long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
{
char *tmp = getname(filename);
int fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
/* 未使用のファイルディスクリプタを取得 */
fd = get_unused_fd();
if (fd >= 0) {
/* file構造体を取得する */
struct file *f = do_filp_open(dfd, tmp, flags, mode);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f->f_dentry);
fd_install(fd, f);
}
}
putname(tmp);
}
return fd;
}
open_namei()の処理概要
int open_namei(int dfd, const char *pathname, int flag,
int mode, struct nameidata *nd)
{
:
if (!(flag & O_CREAT)) {
/*
* pathnameで指定されたファイル/ディレクトリを探す。
* struct nameidata(nd)が作成される。
* fileも作成されnd->intent.open.fileにポインタが保存される。
*/
error = path_lookup_open(dfd, pathname, lookup_flags(flag),
nd, flag);
if (error)
return error;
goto ok;
}
/* O_CREAT付きでopenされた時の処理 */
/* pathnameで指定されたファイル/ディレクトリの
* 親ディレクトリを探す
*/
error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
if (error)
return error;
:
do_last:
:
if (!path.dentry->d_inode) {
:
error = vfs_create(dir->d_inode, path.dentry, mode, nd);
:
goto ok;
}
/* 既に存在する */
:
ok:
error = may_open(nd, acc_mode, flag);
if (error)
goto exit;
return 0;
exit_dput:
:
}
2.2 Read処理
read()システムコールのエントリルーチンはsys_read()。sys_read()は渡されたfd(ファイルディスクリプタ)に対応するstruct fileを取得して、VFSのRead処理(vfs_read())を呼び出す。
vfs_read()はパーミッションのチェックなどを行った後、file->f_opに登録されているファイルシステムのReadルーチンを呼び出してファイルシステムに処理をさせる。
sys_read()処理の概要
sys_read(unsigned int fd, char __user * buf, size_t count)
{
/* ファイルディスクリプタに対応するstruct fileを取得 */
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
/* Virtual File SystemのRead処理へ */
ret = vfs_read(file, buf, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
}
return ret;
}
vfs_read()の処理概要
vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ret = rw_verify_area(READ, file, pos, count);
if (ret >= 0) {
count = ret;
ret = security_file_permission (file, MAY_READ);
if (!ret) {
/* fileが存在するファイルシステムのRead処理の呼び出し */
if (file->f_op->read)
ret = file->f_op->read(file, buf, count, pos);
else
ret = do_sync_read(file, buf, count, pos);
if (ret > 0) {
fsnotify_access(file->f_dentry);
current->rchar += ret;
}
current->syscr++;
}
}
return ret;
}
