negative dentry


Rev.2を表示中。最新版はこちら

negative dentryはinodeを有していないdentryで、unlinkのプロセスの中で作成されるnegative dentryを見てみます。

引数のdirは親ディレクトリ、dentryはunlinkするファイルです。may_delete()/d_mountpoint(dentry)で、対象ファイルをunlinkしてもいいかどうかのチェックし、OKならdir->i_op->unlink()で、実デバイスのdirからdentryを削除し、d_delete()でキャッシュリスト回収の処理を行います。この時、他から参照されていないなら、このdentryはnegative dentryになります。
int vfs_unlink(struct inode *dir, struct dentry *dentry)
{
       int error = may_delete(dir, dentry, 0);

       if (error)
               return error;

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

       mutex_lock(&dentry->d_inode->i_mutex);
       if (d_mountpoint(dentry))
               error = -EBUSY;
       else {
               error = security_inode_unlink(dir, dentry);
               if (!error) {
                       error = dir->i_op->unlink(dir, dentry);
                       if (!error)
                               dont_mount(dentry);
               }
       }
       mutex_unlock(&dentry->d_inode->i_mutex);

       if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
               fsnotify_link_count(dentry->d_inode);
               d_delete(dentry);
       }

       return error;
}
dentry->d_count == 1は、unlinkコマンド以外(unlinkでコールされた場合)は、このファイルを参照していない時、dentry_unlink_inode()をコールし、dentry->d_inode = NULLとする事で、inodeを有しないdentryとするnegative dentryとし復帰します。__d_drop()はコールされず、dentryキャッシュは存在し続けることになります。

なお、dentry->d_flags &= ~DCACHE_CANT_MOUNTとし、マウント不可であってもnegative dentryのディレクトリは全てマウント可能となります。マウントポイントはvfs管理下でinodeの有無と関係ないからです。ただしunlinkから呼ばれる場合、may_delete()でディレクトリの場合だとエラーとなり、このケースでは削除dentryがディレクトリちなることはありません。他のファーズからコールされるケースの処理です。
void d_delete(struct dentry * dentry)
{
       struct inode *inode;
       int isdir = 0;

again:
       spin_lock(&dentry->d_lock);
       inode = dentry->d_inode;
       isdir = S_ISDIR(inode->i_mode);
       if (dentry->d_count == 1) {
               if (inode && !spin_trylock(&inode->i_lock)) {
                       spin_unlock(&dentry->d_lock);
                       cpu_relax();
                       goto again;
               }
               dentry->d_flags &= ~DCACHE_CANT_MOUNT;
               dentry_unlink_inode(dentry);
               fsnotify_nameremove(dentry, isdir);
               return;
       }

       if (!d_unhashed(dentry))
               __d_drop(dentry);

       spin_unlock(&dentry->d_lock);

       fsnotify_nameremove(dentry, isdir);
}
削除するdentryをdentry->d_inode = NULとしnegative dentryとし、list_del_init()で親のdentryにリストされているノードd_aliasを初期化して、親からのパスを削除します。

切り離されたinodeは匿名inodeとなるわけですが、他から参照されていないなら、iput()でinode自身も削除/開放されます。
static void dentry_unlink_inode(struct dentry * dentry)
       __releases(dentry->d_lock)
       __releases(dentry->d_inode->i_lock)
{
       struct inode *inode = dentry->d_inode;
       dentry->d_inode = NULL;
       list_del_init(&dentry->d_alias);
       dentry_rcuwalk_barrier(dentry);
       spin_unlock(&dentry->d_lock);
       spin_unlock(&inode->i_lock);
       if (!inode->i_nlink)
               fsnotify_inoderemove(inode);
       if (dentry->d_op && dentry->d_op->d_iput)
               dentry->d_op->d_iput(dentry, inode);
       else
               iput(inode);
}

追記

下記HPを参考にさせて頂きました。negative dentryの目的は?についても説明がされています。
hibomaのはてなダイアリ

最終更新 2014/03/13 23:40:39 - north
(2014/03/13 23:39:46 作成)


検索

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