diff options
| -rw-r--r-- | drivers/usb/core/inode.c | 1 | ||||
| -rw-r--r-- | fs/configfs/dir.c | 4 | ||||
| -rw-r--r-- | fs/jfs/super.c | 13 | ||||
| -rw-r--r-- | fs/logfs/super.c | 14 | ||||
| -rw-r--r-- | fs/namei.c | 21 | ||||
| -rw-r--r-- | fs/namespace.c | 6 | ||||
| -rw-r--r-- | fs/sysv/dir.c | 2 | ||||
| -rw-r--r-- | include/linux/dcache.h | 14 |
8 files changed, 49 insertions, 26 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/jfs/super.c b/fs/jfs/super.c index 157382fa6256..b66832ac33ac 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
| @@ -446,10 +446,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 446 | /* initialize the mount flag and determine the default error handler */ | 446 | /* initialize the mount flag and determine the default error handler */ |
| 447 | flag = JFS_ERR_REMOUNT_RO; | 447 | flag = JFS_ERR_REMOUNT_RO; |
| 448 | 448 | ||
| 449 | if (!parse_options((char *) data, sb, &newLVSize, &flag)) { | 449 | if (!parse_options((char *) data, sb, &newLVSize, &flag)) |
| 450 | kfree(sbi); | 450 | goto out_kfree; |
| 451 | return -EINVAL; | ||
| 452 | } | ||
| 453 | sbi->flag = flag; | 451 | sbi->flag = flag; |
| 454 | 452 | ||
| 455 | #ifdef CONFIG_JFS_POSIX_ACL | 453 | #ifdef CONFIG_JFS_POSIX_ACL |
| @@ -458,7 +456,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 458 | 456 | ||
| 459 | if (newLVSize) { | 457 | if (newLVSize) { |
| 460 | printk(KERN_ERR "resize option for remount only\n"); | 458 | printk(KERN_ERR "resize option for remount only\n"); |
| 461 | return -EINVAL; | 459 | goto out_kfree; |
| 462 | } | 460 | } |
| 463 | 461 | ||
| 464 | /* | 462 | /* |
| @@ -478,7 +476,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 478 | inode = new_inode(sb); | 476 | inode = new_inode(sb); |
| 479 | if (inode == NULL) { | 477 | if (inode == NULL) { |
| 480 | ret = -ENOMEM; | 478 | ret = -ENOMEM; |
| 481 | goto out_kfree; | 479 | goto out_unload; |
| 482 | } | 480 | } |
| 483 | inode->i_ino = 0; | 481 | inode->i_ino = 0; |
| 484 | inode->i_nlink = 1; | 482 | inode->i_nlink = 1; |
| @@ -550,9 +548,10 @@ out_mount_failed: | |||
| 550 | make_bad_inode(sbi->direct_inode); | 548 | make_bad_inode(sbi->direct_inode); |
| 551 | iput(sbi->direct_inode); | 549 | iput(sbi->direct_inode); |
| 552 | sbi->direct_inode = NULL; | 550 | sbi->direct_inode = NULL; |
| 553 | out_kfree: | 551 | out_unload: |
| 554 | if (sbi->nls_tab) | 552 | if (sbi->nls_tab) |
| 555 | unload_nls(sbi->nls_tab); | 553 | unload_nls(sbi->nls_tab); |
| 554 | out_kfree: | ||
| 556 | kfree(sbi); | 555 | kfree(sbi); |
| 557 | return ret; | 556 | return ret; |
| 558 | } | 557 | } |
diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 5866ee6e1327..d7c23ed8349a 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c | |||
| @@ -333,27 +333,27 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt) | |||
| 333 | goto fail; | 333 | goto fail; |
| 334 | 334 | ||
| 335 | sb->s_root = d_alloc_root(rootdir); | 335 | sb->s_root = d_alloc_root(rootdir); |
| 336 | if (!sb->s_root) | 336 | if (!sb->s_root) { |
| 337 | goto fail2; | 337 | iput(rootdir); |
| 338 | goto fail; | ||
| 339 | } | ||
| 338 | 340 | ||
| 339 | super->s_erase_page = alloc_pages(GFP_KERNEL, 0); | 341 | super->s_erase_page = alloc_pages(GFP_KERNEL, 0); |
| 340 | if (!super->s_erase_page) | 342 | if (!super->s_erase_page) |
| 341 | goto fail2; | 343 | goto fail; |
| 342 | memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE); | 344 | memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE); |
| 343 | 345 | ||
| 344 | /* FIXME: check for read-only mounts */ | 346 | /* FIXME: check for read-only mounts */ |
| 345 | err = logfs_make_writeable(sb); | 347 | err = logfs_make_writeable(sb); |
| 346 | if (err) | 348 | if (err) |
| 347 | goto fail3; | 349 | goto fail1; |
| 348 | 350 | ||
| 349 | log_super("LogFS: Finished mounting\n"); | 351 | log_super("LogFS: Finished mounting\n"); |
| 350 | simple_set_mnt(mnt, sb); | 352 | simple_set_mnt(mnt, sb); |
| 351 | return 0; | 353 | return 0; |
| 352 | 354 | ||
| 353 | fail3: | 355 | fail1: |
| 354 | __free_page(super->s_erase_page); | 356 | __free_page(super->s_erase_page); |
| 355 | fail2: | ||
| 356 | iput(rootdir); | ||
| 357 | fail: | 357 | fail: |
| 358 | iput(logfs_super(sb)->s_master_inode); | 358 | iput(logfs_super(sb)->s_master_inode); |
| 359 | return -EIO; | 359 | return -EIO; |
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/fs/sysv/dir.c b/fs/sysv/dir.c index 4e50286a4cc3..1dabed286b4c 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
| @@ -164,8 +164,8 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_ | |||
| 164 | name, de->name)) | 164 | name, de->name)) |
| 165 | goto found; | 165 | goto found; |
| 166 | } | 166 | } |
| 167 | dir_put_page(page); | ||
| 167 | } | 168 | } |
| 168 | dir_put_page(page); | ||
| 169 | 169 | ||
| 170 | if (++n >= npages) | 170 | if (++n >= npages) |
| 171 | n = 0; | 171 | n = 0; |
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; |
