親ディレクトリ/カレントディレクトリ
Rev.1を表示中。最新版はこちら。
親ディレクトリ/カレントディレクトリは、link_walk()の実装から、バーチャルなディレクトリかと思っていましたが、そうでなく、ハードリンクとして実ディレクトリとして作成されます。lsコマンド一覧です。左からnode番号/パーミッション/ハードリンク数となります。hoge1/hoge2/.はhoge1/hoge2とinode番号163877と共有(ハードリンク)、hoge1/hoge2/..はhoge1/.(kitamura/hoge1)とinode番号163876と共有(ハードリンク)しています。
従って、新規にディレクトリを作成すると、.ディレクトリのハードリンク数は、自分自身inodeと親inodeの2、..ディレクトリのハードリンク数は、自分自身inodeと親inode、親inodeの.ディレクトリの3となります。
[root@localhost kitamura]# mkdir hoge1 [root@localhost kitamura]# mkdir hoge1/hoge2 [root@localhost kitamura]# ls -lia hoge1/ 合計 12 163876 drwxr-xr-x 3 root root 4096 4月 2 02:07 . 147478 drwxrwxrwx. 47 kitamura kitamura 4096 4月 2 02:06 .. 163877 drwxr-xr-x 2 root root 4096 4月 2 02:07 hoge2 [root@localhost kitamura]# ls -lia hoge1/hoge2/ 合計 8 163877 drwxr-xr-x 2 root root 4096 4月 2 02:07 . 163876 drwxr-xr-x 3 root root 4096 4月 2 02:07 ..ディレクトリ作成は、ディレクトリ用inodeの.mkdirコールバックで行います。ext2_mkdir()はext2ファイルシステムの.mkdirです。
ext2_new_inode()でディレクトリinodeを取得した後、ext2_make_empty()でカレント/親ディレクトリを作成します。
const struct inode_operations ext2_dir_inode_operations = {
.create = ext2_create,
.lookup = ext2_lookup,
.link = ext2_link,
.unlink = ext2_unlink,
.symlink = ext2_symlink,
.mkdir = ext2_mkdir,
.rmdir = ext2_rmdir,
.mknod = ext2_mknod,
.rename = ext2_rename,
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
.get_acl = ext2_get_acl,
};
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
{
struct inode * inode;
int err = -EMLINK;
if (dir->i_nlink >= EXT2_LINK_MAX)
goto out;
dquot_initialize(dir);
inode_inc_link_count(dir);
inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_dir;
inode->i_op = &ext2_dir_inode_operations;
inode->i_fop = &ext2_dir_operations;
if (test_opt(inode->i_sb, NOBH))
inode->i_mapping->a_ops = &ext2_nobh_aops;
else
inode->i_mapping->a_ops = &ext2_aops;
inode_inc_link_count(inode);
err = ext2_make_empty(inode, dir);
if (err)
goto out_fail;
err = ext2_add_link(dentry, inode);
if (err)
goto out_fail;
d_instantiate(dentry, inode);
unlock_new_inode(inode);
out:
return err;
out_fail:
inode_dec_link_count(inode);
inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode);
out_dir:
inode_dec_link_count(dir);
goto out;
}
inodeは新規に作成されたディレクトリで、*parentはその親ディレクトリです。ディレクトリ名"."をinode->i_inoとし、 ".."をparent->i_inoとするinodeをハードリンクとして作成し、ext2_commit_chunk()でこのpageをdirtyとし、デバイスに書き込まれます。
int ext2_make_empty(struct inode *inode, struct inode *parent)
{
struct page *page = grab_cache_page(inode->i_mapping, 0);
unsigned chunk_size = ext2_chunk_size(inode);
struct ext2_dir_entry_2 * de;
int err;
void *kaddr;
if (!page)
return -ENOMEM;
err = ext2_prepare_chunk(page, 0, chunk_size);
if (err) {
unlock_page(page);
goto fail;
}
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, chunk_size);
de = (struct ext2_dir_entry_2 *)kaddr;
de->name_len = 1;
de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1));
memcpy (de->name, ".\0\0", 4);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
de->name_len = 2;
de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1));
de->inode = cpu_to_le32(parent->i_ino);
memcpy (de->name, "..\0", 4);
ext2_set_de_type (de, inode);
kunmap_atomic(kaddr, KM_USER0);
err = ext2_commit_chunk(page, 0, chunk_size);
fail:
page_cache_release(page);
return err;
}





