無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

シンボリックリンク


シンボリックリンクは、symlinkシステムコールからvfs_symlink()がコールされ、ディレクトリinodeコールバックのsymlinkがコールされます。
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,
};

int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
       int error = may_create(dir, dentry);

       if (error)
               return error;

       if (!dir->i_op->symlink)
               return -EPERM;

       error = security_inode_symlink(dir, dentry, oldname);
       if (error)
               return error;

       error = dir->i_op->symlink(dir, dentry, oldname);
       if (!error)
               fsnotify_create(dir, dentry);
       return error;
}
シンボリックリンク名称の長さは、ブロックサイズ(通常は4K)を超えるとエラーで、__le32 ext2_inode_info.i_data[15](15×32/8=60)以下なら、ext2_inode_info.i_data[15](inodeブロック)に、それ以上ならpage_symlink()でinode->i_mapping(データブロック)に設定され、このinodeをext2_add_nondir()で、親ディレクトリに追加します。

シンボリックリンク名が、inodeブロックの設定なら、inodeコールバックはext2_fast_symlink_inode_operations。データブロックの設定なら、ext2_symlink_inode_operationsとなります。これはreadlinkシステムコールで、シンボリックリンク名称取得する故の実装となります。
struct ext2_inode_info {
       __le32  i_data[15];
       __u32   i_flags;
       __u32   i_faddr;
       __u8    i_frag_no;
       __u8    i_frag_size;
       __u16   i_state;
       __u32   i_file_acl;
       __u32   i_dir_acl;
       __u32   i_dtime;

       __u32   i_block_group;

       struct ext2_block_alloc_info *i_block_alloc_info;

       __u32   i_dir_start_lookup;
#ifdef CONFIG_EXT2_FS_XATTR
       struct rw_semaphore xattr_sem;
#endif
       rwlock_t i_meta_lock;

       struct mutex truncate_mutex;
       struct inode    vfs_inode;
       struct list_head i_orphan;      /* unlinked but open inodes */
};

static int ext2_symlink (struct inode * dir, struct dentry * dentry,
       const char * symname)
{
       struct super_block * sb = dir->i_sb;
       int err = -ENAMETOOLONG;
       unsigned l = strlen(symname)+1;
       struct inode * inode;

       if (l > sb->s_blocksize)
               goto out;

       dquot_initialize(dir);

       inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
       err = PTR_ERR(inode);
       if (IS_ERR(inode))
               goto out;

       if (l > sizeof (EXT2_I(inode)->i_data)) {
               inode->i_op = &ext2_symlink_inode_operations;
               if (test_opt(inode->i_sb, NOBH))
                       inode->i_mapping->a_ops = &ext2_nobh_aops;
               else
                       inode->i_mapping->a_ops = &ext2_aops;
               err = page_symlink(inode, symname, l);
               if (err)
                       goto out_fail;
       } else {
               inode->i_op = &ext2_fast_symlink_inode_operations;
               memcpy((char*)(EXT2_I(inode)->i_data),symname,l);
               inode->i_size = l-1;
       }
       mark_inode_dirty(inode);

       err = ext2_add_nondir(dentry, inode);
out:
       return err;

out_fail:
       inode_dec_link_count(inode);
       unlock_new_inode(inode);
       iput (inode);
       goto out;
}

inodeはvfsのinode属性、ext2_inode_infoはファイルシステム毎(ext2)のinode属性で、ext2_inode_info.vfs_inode=inodeで、container_ofマクロでvfs_inodeのinodeから、struct ext2_inode_infoのinodeを取得します。
static inline struct ext2_inode_info *EXT2_I(struct inode *inode)
{
       return container_of(inode, struct ext2_inode_info, vfs_inode);
}

補足

通常ファイルのinodeコールバックは、ext2_fast_symlink_inode_operations/ext2_symlink_inode_operationsの.readlinkが定義されておらず、従って通常ファイルでのreadlinkシステムコールはエラーとなり、readlinkコマンドの-fオプションは、カーネルマターでなくコマンドマターです。

ext3も掛かる実装は同じです。ただしデータブロックの設定時、ジャーナル処理が追加されます。


最終更新 2016/02/04 18:29:53 - north
(2015/03/15 17:33:40 作成)