ファイルシステムはext3
- どこのレイヤーを処理してるのかを見失わないように
- dentry
- inodeオブジェクト
- super_block
- ext3_*
struct inode_operations ext3_dir_inode_operations = {
.lookup = ext3_lookup,
}
- lookup ... dentry操作の抽象化
- iget ... inode操作の抽象化 ... ext3層でinode操作
- inode->i_op->lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
- reallookup
- lookup ---> ext3_lookup
- iget .. inodeオブジェクト割当、super_blockのread_inodeでディスクinode情報で初期化
- iget_locked ...
-
- ifind_fast ... スピンロック,ディスクの待ち合わせ?
- find_inode_fast ... inodeオブジェクトテーブルの探索
- ext3_read_inode ... ディスクinodeの情報を読み取り、inodeオブジェクトにセットする
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
down(&dir->i_sem);
FIXME
result = d_lookup(parent, name);
if (!result) {
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
result = dir->i_op->lookup(dir, dentry, nd);
if (result)
dput(dentry);
else
result = dentry;
}
up(&dir->i_sem);
return result;
}
up(&dir->i_sem);
if (result->d_op && result->d_op->d_revalidate) {
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
result = ERR_PTR(-ENOENT);
}
}
return result;
}
static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode;
struct ext3_dir_entry_2 * de;
struct buffer_head * bh;
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
unsigned long ino = le32_to_cpu(de->inode);
brelse (bh);
inode = iget(dir->i_sb, ino);
if (!inode)
return ERR_PTR(-EACCES);
}
if (inode)
return d_splice_alias(inode, dentry);
d_add(dentry, inode);
return NULL;
}
static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
inode = iget(dir->i_sb, ino);
}
1389 static inline struct inode *iget(struct super_block *sb, unsigned long ino)
1390 {
1391 struct inode *inode = iget_locked(sb, ino);
1392
1393 if (inode && (inode->i_state & I_NEW)) {
1394 sb->s_op->read_inode(inode);
1395 unlock_new_inode(inode);
1396 }
1397
1398 return inode;
1399 }
932 struct inode *iget_locked(struct super_block *sb, unsigned long ino)
933 {
934 struct hlist_head *head = inode_hashtable + hash(sb, ino);
935 struct inode *inode;
936
937 inode = ifind_fast(sb, head, ino);
938 if (inode)
939 return inode;
940
944 return get_new_inode_fast(sb, head, ino);
945 }
805 static inline struct inode *ifind_fast(struct super_block *sb,
806 struct hlist_head *head, unsigned long ino)
807 {
808 struct inode *inode;
809
810 spin_lock(&inode_lock);
811 inode = find_inode_fast(sb, head, ino);
812 if (inode) {
813 __iget(inode);
814 spin_unlock(&inode_lock);
815 wait_on_inode(inode);
816 return inode;
817 }
818 spin_unlock(&inode_lock);
819 return NULL;
820 }
221
224 void __iget(struct inode * inode)
225 {
226 if (atomic_read(&inode->i_count)) {
227 atomic_inc(&inode->i_count);
228 return;
229 }
230 atomic_inc(&inode->i_count);
231 if (!(inode->i_state & (I_DIRTY|I_LOCK)))
232 list_move(&inode->i_list, &inode_in_use);
233 inodes_stat.nr_unused--;
234 }
524
528 static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino)
529 {
530 struct hlist_node *node;
531 struct inode * inode = NULL;
532
533 repeat:
534 hlist_for_each (node, head) {
535 inode = hlist_entry(node, struct inode, i_hash);
536 if (inode->i_ino != ino)
537 continue;
538 if (inode->i_sb != sb)
539 continue;
540 if (inode->i_state & (I_FREEING|I_CLEAR)) {
541 __wait_on_freeing_inode(inode);
542 goto repeat;
543 }
544 break;
545 }
546 return node ? inode : NULL;
547 }
static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino)
{
struct inode * inode;
inode = alloc_inode(sb);
if (inode) {
struct inode * old;
spin_lock(&inode_lock);
old = find_inode_fast(sb, head, ino);
if (!old) {
inode->i_ino = ino;
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
hlist_add_head(&inode->i_hash, head);
inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock);
return inode;
}
__iget(old);
spin_unlock(&inode_lock);
destroy_inode(inode);
inode = old;
wait_on_inode(inode);
}
return inode;
}
static struct inode *alloc_inode(struct super_block *sb)
{
static struct address_space_operations empty_aops;
static struct inode_operations empty_iops;
static struct file_operations empty_fops;
struct inode *inode;
if (sb->s_op->alloc_inode)
inode = sb->s_op->alloc_inode(sb);
else
inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
if (inode) {
struct address_space * const mapping = &inode->i_data;
inode->i_sb = sb;
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0;
atomic_set(&inode->i_count, 1);
inode->i_sock = 0;
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
inode->i_nlink = 1;
atomic_set(&inode->i_writecount, 0);
inode->i_size = 0;
inode->i_blocks = 0;
inode->i_bytes = 0;
inode->i_generation = 0;
#ifdef CONFIG_QUOTA
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
#endif
inode->i_pipe = NULL;
inode->i_bdev = NULL;
inode->i_cdev = NULL;
inode->i_rdev = 0;
inode->i_security = NULL;
inode->dirtied_when = 0;
if (security_inode_alloc(inode)) {
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
kmem_cache_free(inode_cachep, (inode));
return NULL;
}
mapping->a_ops = &empty_aops;
mapping->host = inode;
mapping->flags = 0;
mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
mapping->assoc_mapping = NULL;
mapping->backing_dev_info = &default_backing_dev_info;
if (sb->s_bdev) {
struct backing_dev_info *bdi;
bdi = sb->s_bdev->bd_inode_backing_dev_info;
if (!bdi)
bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
mapping->backing_dev_info = bdi;
}
memset(&inode->u, 0, sizeof(inode->u));
inode->i_mapping = mapping;
}
return inode;
}