- 论坛徽章:
- 0
|
- int vfs_rmdir(struct inode *dir, struct dentry *dentry)
- {
- int error = may_delete(dir, dentry, 1);
- if (error)
- return error;
- if (!dir->i_op || !dir->i_op->rmdir)
- return -EPERM;
- DQUOT_INIT(dir);
- mutex_lock(&dentry->d_inode->i_mutex);
- dentry_unhash(dentry);
- if (d_mountpoint(dentry))
- error = -EBUSY;
- else {
- error = security_inode_rmdir(dir, dentry);
- if (!error) {
- error = dir->i_op->rmdir(dir, dentry);
- if (!error)
- dentry->d_inode->i_flags |= S_DEAD;
- }
- }
- mutex_unlock(&dentry->d_inode->i_mutex);
- if (!error) {
- /*
- * linux-2.6.20.7/fs/namei.c
- *
- * potentially trigger-1
- */
- d_delete(dentry);
- }
- dput(dentry);
- return error;
- }
复制代码
- void d_delete(struct dentry * dentry)
- {
- int isdir = 0;
- /*
- * Are we the only user?
- */
- spin_lock(&dcache_lock);
- spin_lock(&dentry->d_lock);
- isdir = S_ISDIR(dentry->d_inode->i_mode);
-
- if (atomic_read(&dentry->d_count) == 1) {
- dentry_iput(dentry);
- fsnotify_nameremove(dentry, isdir);
- /* remove this and other inotify debug checks after 2.6.18 */
- dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
- /*
- * linux-2.6.20.7/fs/dcache.c
- *
- * potentially trigger-2
- */
- return;
- }
- if (!d_unhashed(dentry))
- __d_drop(dentry);
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- fsnotify_nameremove(dentry, isdir);
- }
复制代码
- void dput(struct dentry *dentry)
- {
- if (!dentry)
- return;
- repeat:
- if (atomic_read(&dentry->d_count) == 1)
- might_sleep();
-
- if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
- return;
- /*
- * linux-2.6.20.7/fs/dcache.c
- *
- * ¥6
- * potentially race @ here
- */
- spin_lock(&dentry->d_lock);
-
- if (atomic_read(&dentry->d_count)) {
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- return;
- }
- /*
- * AV: ->d_delete() is _NOT_ allowed to block now.
- */
- if (dentry->d_op && dentry->d_op->d_delete) {
- if (dentry->d_op->d_delete(dentry))
- goto unhash_it;
- }
- /* Unreachable? Get rid of it */
- if (d_unhashed(dentry))
- goto kill_it;
-
- if (list_empty(&dentry->d_lru)) {
- dentry->d_flags |= DCACHE_REFERENCED;
- list_add(&dentry->d_lru, &dentry_unused);
- dentry_stat.nr_unused++;
- }
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- return;
- unhash_it:
- __d_drop(dentry);
- kill_it: {
- struct dentry *parent;
- /* If dentry was on d_lru list,
- * delete it from there
- */
- if (!list_empty(&dentry->d_lru)) {
- list_del(&dentry->d_lru);
- dentry_stat.nr_unused--;
- }
- list_del(&dentry->d_u.d_child);
- dentry_stat.nr_dentry--; /* For d_free, below */
-
- /* drops the locks,
- * at that point nobody can reach this dentry
- */
- dentry_iput(dentry);
-
- parent = dentry->d_parent;
- d_free(dentry);
-
- if (dentry == parent)
- return;
- dentry = parent;
- goto repeat;
- }
- }
复制代码 |
|