ハードlink


リンク可能条件
#define S_APPEND        8
#define S_IMMUTABLE     16

#define IS_APPEND(inode)        ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode)     ((inode)->i_flags & S_IMMUTABLE)
・リンク先/リンク元が同じデバイス(dir->i_sb != inode->i_sb)
・リンク先ファイルを有していない
・リンク先親ディレクトリはファイル作成可能(write and exec permissions)
・リンク先親dir.inodeのlinkコールバックが定義されている。(procfs等は定義されておらずリンクできません)
・リンク元ファイルはS_APPEND(chattrコマンド +a:追記のみ)でない
・リンク元ファイルはS_IMMUTABLE(chattrコマンド +i:変更不可)でない
・リンク元はディレクトリでない

old_dentry: リンク元ファイルのdentry
dir : リンク先ファイルの親ディレクトリinode
new_dentry: リンク先ファイルのdentry

new_dentry->d_inode = old_dentry->d_inode;(inodeアドレスを共有します。)
inode->i_nlink++(リンクカウント:リンクファイルが削除されてもinode->i_coun=0であってもinode->i_nlink !=0 ならinodeは削除されません。);

リンクファイルinode->i_dentryにnew_dentry->d_aliasがリストされ、リンクファイル(dentry)からリンクされている全dentryが取得でき、splice/automnt等のinodeでなくキャッシュdentryに掛かる実装故です。
int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
{
       struct inode *inode = old_dentry->d_inode;
       int error;

       if (!inode)
               return -ENOENT;

       error = may_create(dir, new_dentry, NULL);
       if (error)
               return error;

       if (dir->i_sb != inode->i_sb)
               return -EXDEV;

       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
               return -EPERM;
       if (!dir->i_op || !dir->i_op->link)
               return -EPERM;
       if (S_ISDIR(old_dentry->d_inode->i_mode))
               return -EPERM;

       error = security_inode_link(old_dentry, dir, new_dentry);
       if (error)
               return error;

       down(&old_dentry->d_inode->i_sem);
       DQUOT_INIT(dir);
       error = dir->i_op->link(old_dentry, dir, new_dentry);
       up(&old_dentry->d_inode->i_sem);
       if (!error) {
               inode_dir_notify(dir, DN_CREATE);
               security_inode_post_link(old_dentry, dir, new_dentry);
       }
       return error;
}

static inline int may_create(struct inode *dir, struct dentry *child,
                            struct nameidata *nd)
{
       if (child->d_inode)
               return -EEXIST;
       if (IS_DEADDIR(dir))
               return -ENOENT;
       return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}

static struct inode_operations ramfs_dir_inode_operations = {
       .create         = ramfs_create,
       .lookup         = simple_lookup,
       .link           = simple_link,
       .unlink         = simple_unlink,
       .symlink        = ramfs_symlink,
       .mkdir          = ramfs_mkdir,
       .rmdir          = simple_rmdir,
       .mknod          = ramfs_mknod,
       .rename         = simple_rename,
};

int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
       struct inode *inode = old_dentry->d_inode;

       inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
       inc_nlink(inode);
       ihold(inode);
       dget(dentry);
       d_instantiate(dentry, inode);
       return 0;
}

void d_instantiate(struct dentry *entry, struct inode * inode)
{
       if (!list_empty(&entry->d_alias)) BUG();
       spin_lock(&dcache_lock);
       if (inode)
               list_add(&entry->d_alias, &inode->i_dentry);
       entry->d_inode = inode;
       spin_unlock(&dcache_lock);
       security_d_instantiate(entry, inode);
}

追記

リンクファイルのタイプスタンプinode->i_ctime(Change)及び、リンク先dirのinode->i_ctime(Change)inode->i_mtime(Modify)が更新されます。リンク先dir更新はリンクに掛かる更新でなく、ファイル作成故の更新です。

ディレクトリはdentry以外のキャッシュを有する実装故という事なのか、実装からすると何故ディレクトリのハードリンクを不可とするのか疑問です。


最終更新 2016/12/23 14:17:20 - north
(2016/12/23 14:17:20 作成)


検索

アクセス数
3689342
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。