diff options
-rw-r--r-- | drivers/usb/core/inode.c | 1 | ||||
-rw-r--r-- | fs/configfs/dir.c | 4 | ||||
-rw-r--r-- | fs/namei.c | 21 | ||||
-rw-r--r-- | fs/namespace.c | 6 | ||||
-rw-r--r-- | include/linux/dcache.h | 14 |
5 files changed, 35 insertions, 11 deletions
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 4a6366a42129..111a01a747fc 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -380,6 +380,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
380 | mutex_lock(&inode->i_mutex); | 380 | mutex_lock(&inode->i_mutex); |
381 | dentry_unhash(dentry); | 381 | dentry_unhash(dentry); |
382 | if (usbfs_empty(dentry)) { | 382 | if (usbfs_empty(dentry)) { |
383 | dont_mount(dentry); | ||
383 | drop_nlink(dentry->d_inode); | 384 | drop_nlink(dentry->d_inode); |
384 | drop_nlink(dentry->d_inode); | 385 | drop_nlink(dentry->d_inode); |
385 | dput(dentry); | 386 | dput(dentry); |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8e48b52205aa..0b502f80c691 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -645,6 +645,7 @@ static void detach_groups(struct config_group *group) | |||
645 | 645 | ||
646 | configfs_detach_group(sd->s_element); | 646 | configfs_detach_group(sd->s_element); |
647 | child->d_inode->i_flags |= S_DEAD; | 647 | child->d_inode->i_flags |= S_DEAD; |
648 | dont_mount(child); | ||
648 | 649 | ||
649 | mutex_unlock(&child->d_inode->i_mutex); | 650 | mutex_unlock(&child->d_inode->i_mutex); |
650 | 651 | ||
@@ -840,6 +841,7 @@ static int configfs_attach_item(struct config_item *parent_item, | |||
840 | mutex_lock(&dentry->d_inode->i_mutex); | 841 | mutex_lock(&dentry->d_inode->i_mutex); |
841 | configfs_remove_dir(item); | 842 | configfs_remove_dir(item); |
842 | dentry->d_inode->i_flags |= S_DEAD; | 843 | dentry->d_inode->i_flags |= S_DEAD; |
844 | dont_mount(dentry); | ||
843 | mutex_unlock(&dentry->d_inode->i_mutex); | 845 | mutex_unlock(&dentry->d_inode->i_mutex); |
844 | d_delete(dentry); | 846 | d_delete(dentry); |
845 | } | 847 | } |
@@ -882,6 +884,7 @@ static int configfs_attach_group(struct config_item *parent_item, | |||
882 | if (ret) { | 884 | if (ret) { |
883 | configfs_detach_item(item); | 885 | configfs_detach_item(item); |
884 | dentry->d_inode->i_flags |= S_DEAD; | 886 | dentry->d_inode->i_flags |= S_DEAD; |
887 | dont_mount(dentry); | ||
885 | } | 888 | } |
886 | configfs_adjust_dir_dirent_depth_after_populate(sd); | 889 | configfs_adjust_dir_dirent_depth_after_populate(sd); |
887 | mutex_unlock(&dentry->d_inode->i_mutex); | 890 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -1725,6 +1728,7 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) | |||
1725 | mutex_unlock(&configfs_symlink_mutex); | 1728 | mutex_unlock(&configfs_symlink_mutex); |
1726 | configfs_detach_group(&group->cg_item); | 1729 | configfs_detach_group(&group->cg_item); |
1727 | dentry->d_inode->i_flags |= S_DEAD; | 1730 | dentry->d_inode->i_flags |= S_DEAD; |
1731 | dont_mount(dentry); | ||
1728 | mutex_unlock(&dentry->d_inode->i_mutex); | 1732 | mutex_unlock(&dentry->d_inode->i_mutex); |
1729 | 1733 | ||
1730 | d_delete(dentry); | 1734 | d_delete(dentry); |
diff --git a/fs/namei.c b/fs/namei.c index 16df7277a92e..b86b96fe1dc3 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2176,8 +2176,10 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2176 | error = security_inode_rmdir(dir, dentry); | 2176 | error = security_inode_rmdir(dir, dentry); |
2177 | if (!error) { | 2177 | if (!error) { |
2178 | error = dir->i_op->rmdir(dir, dentry); | 2178 | error = dir->i_op->rmdir(dir, dentry); |
2179 | if (!error) | 2179 | if (!error) { |
2180 | dentry->d_inode->i_flags |= S_DEAD; | 2180 | dentry->d_inode->i_flags |= S_DEAD; |
2181 | dont_mount(dentry); | ||
2182 | } | ||
2181 | } | 2183 | } |
2182 | } | 2184 | } |
2183 | mutex_unlock(&dentry->d_inode->i_mutex); | 2185 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -2261,7 +2263,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2261 | if (!error) { | 2263 | if (!error) { |
2262 | error = dir->i_op->unlink(dir, dentry); | 2264 | error = dir->i_op->unlink(dir, dentry); |
2263 | if (!error) | 2265 | if (!error) |
2264 | dentry->d_inode->i_flags |= S_DEAD; | 2266 | dont_mount(dentry); |
2265 | } | 2267 | } |
2266 | } | 2268 | } |
2267 | mutex_unlock(&dentry->d_inode->i_mutex); | 2269 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -2572,17 +2574,20 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, | |||
2572 | return error; | 2574 | return error; |
2573 | 2575 | ||
2574 | target = new_dentry->d_inode; | 2576 | target = new_dentry->d_inode; |
2575 | if (target) { | 2577 | if (target) |
2576 | mutex_lock(&target->i_mutex); | 2578 | mutex_lock(&target->i_mutex); |
2577 | dentry_unhash(new_dentry); | ||
2578 | } | ||
2579 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) | 2579 | if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) |
2580 | error = -EBUSY; | 2580 | error = -EBUSY; |
2581 | else | 2581 | else { |
2582 | if (target) | ||
2583 | dentry_unhash(new_dentry); | ||
2582 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 2584 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); |
2585 | } | ||
2583 | if (target) { | 2586 | if (target) { |
2584 | if (!error) | 2587 | if (!error) { |
2585 | target->i_flags |= S_DEAD; | 2588 | target->i_flags |= S_DEAD; |
2589 | dont_mount(new_dentry); | ||
2590 | } | ||
2586 | mutex_unlock(&target->i_mutex); | 2591 | mutex_unlock(&target->i_mutex); |
2587 | if (d_unhashed(new_dentry)) | 2592 | if (d_unhashed(new_dentry)) |
2588 | d_rehash(new_dentry); | 2593 | d_rehash(new_dentry); |
@@ -2614,7 +2619,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, | |||
2614 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); | 2619 | error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); |
2615 | if (!error) { | 2620 | if (!error) { |
2616 | if (target) | 2621 | if (target) |
2617 | target->i_flags |= S_DEAD; | 2622 | dont_mount(new_dentry); |
2618 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) | 2623 | if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) |
2619 | d_move(old_dentry, new_dentry); | 2624 | d_move(old_dentry, new_dentry); |
2620 | } | 2625 | } |
diff --git a/fs/namespace.c b/fs/namespace.c index 8174c8ab5c70..f20cb57d1067 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1432,7 +1432,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) | |||
1432 | 1432 | ||
1433 | err = -ENOENT; | 1433 | err = -ENOENT; |
1434 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1434 | mutex_lock(&path->dentry->d_inode->i_mutex); |
1435 | if (IS_DEADDIR(path->dentry->d_inode)) | 1435 | if (cant_mount(path->dentry)) |
1436 | goto out_unlock; | 1436 | goto out_unlock; |
1437 | 1437 | ||
1438 | err = security_sb_check_sb(mnt, path); | 1438 | err = security_sb_check_sb(mnt, path); |
@@ -1623,7 +1623,7 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1623 | 1623 | ||
1624 | err = -ENOENT; | 1624 | err = -ENOENT; |
1625 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1625 | mutex_lock(&path->dentry->d_inode->i_mutex); |
1626 | if (IS_DEADDIR(path->dentry->d_inode)) | 1626 | if (cant_mount(path->dentry)) |
1627 | goto out1; | 1627 | goto out1; |
1628 | 1628 | ||
1629 | if (d_unlinked(path->dentry)) | 1629 | if (d_unlinked(path->dentry)) |
@@ -2234,7 +2234,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2234 | if (!check_mnt(root.mnt)) | 2234 | if (!check_mnt(root.mnt)) |
2235 | goto out2; | 2235 | goto out2; |
2236 | error = -ENOENT; | 2236 | error = -ENOENT; |
2237 | if (IS_DEADDIR(new.dentry->d_inode)) | 2237 | if (cant_mount(old.dentry)) |
2238 | goto out2; | 2238 | goto out2; |
2239 | if (d_unlinked(new.dentry)) | 2239 | if (d_unlinked(new.dentry)) |
2240 | goto out2; | 2240 | goto out2; |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 30b93b2a01a4..eebb617c17d8 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -186,6 +186,8 @@ d_iput: no no no yes | |||
186 | 186 | ||
187 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ | 187 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ |
188 | 188 | ||
189 | #define DCACHE_CANT_MOUNT 0x0100 | ||
190 | |||
189 | extern spinlock_t dcache_lock; | 191 | extern spinlock_t dcache_lock; |
190 | extern seqlock_t rename_lock; | 192 | extern seqlock_t rename_lock; |
191 | 193 | ||
@@ -358,6 +360,18 @@ static inline int d_unlinked(struct dentry *dentry) | |||
358 | return d_unhashed(dentry) && !IS_ROOT(dentry); | 360 | return d_unhashed(dentry) && !IS_ROOT(dentry); |
359 | } | 361 | } |
360 | 362 | ||
363 | static inline int cant_mount(struct dentry *dentry) | ||
364 | { | ||
365 | return (dentry->d_flags & DCACHE_CANT_MOUNT); | ||
366 | } | ||
367 | |||
368 | static inline void dont_mount(struct dentry *dentry) | ||
369 | { | ||
370 | spin_lock(&dentry->d_lock); | ||
371 | dentry->d_flags |= DCACHE_CANT_MOUNT; | ||
372 | spin_unlock(&dentry->d_lock); | ||
373 | } | ||
374 | |||
361 | static inline struct dentry *dget_parent(struct dentry *dentry) | 375 | static inline struct dentry *dget_parent(struct dentry *dentry) |
362 | { | 376 | { |
363 | struct dentry *ret; | 377 | struct dentry *ret; |