diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-12 17:09:36 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-07-12 17:09:36 -0400 |
| commit | c83727a6565278dd330748daac046721284adfc2 (patch) | |
| tree | 20c45571c2f387ab51983fb2379f04b2c795dd31 | |
| parent | 7fbb58a06517443ff68f36f4f1867ba978eac5dd (diff) | |
| parent | 75a6f82a0d10ef8f13cd8fe7212911a0252ab99e (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS fixes from Al Viro:
"Fixes for this cycle regression in overlayfs and a couple of
long-standing (== all the way back to 2.6.12, at least) bugs"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
freeing unlinked file indefinitely delayed
fix a braino in ovl_d_select_inode()
9p: don't leave a half-initialized inode sitting around
| -rw-r--r-- | fs/9p/vfs_inode.c | 3 | ||||
| -rw-r--r-- | fs/9p/vfs_inode_dotl.c | 3 | ||||
| -rw-r--r-- | fs/dcache.c | 7 | ||||
| -rw-r--r-- | fs/overlayfs/inode.c | 3 |
4 files changed, 10 insertions, 6 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 510040b04c96..b1dc51888048 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -540,8 +540,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, | |||
| 540 | unlock_new_inode(inode); | 540 | unlock_new_inode(inode); |
| 541 | return inode; | 541 | return inode; |
| 542 | error: | 542 | error: |
| 543 | unlock_new_inode(inode); | 543 | iget_failed(inode); |
| 544 | iput(inode); | ||
| 545 | return ERR_PTR(retval); | 544 | return ERR_PTR(retval); |
| 546 | 545 | ||
| 547 | } | 546 | } |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 09e4433717b8..e8aa57dc8d6d 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
| @@ -149,8 +149,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, | |||
| 149 | unlock_new_inode(inode); | 149 | unlock_new_inode(inode); |
| 150 | return inode; | 150 | return inode; |
| 151 | error: | 151 | error: |
| 152 | unlock_new_inode(inode); | 152 | iget_failed(inode); |
| 153 | iput(inode); | ||
| 154 | return ERR_PTR(retval); | 153 | return ERR_PTR(retval); |
| 155 | 154 | ||
| 156 | } | 155 | } |
diff --git a/fs/dcache.c b/fs/dcache.c index 7a3f3e5f9cea..5c8ea15e73a5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -642,7 +642,7 @@ static inline bool fast_dput(struct dentry *dentry) | |||
| 642 | 642 | ||
| 643 | /* | 643 | /* |
| 644 | * If we have a d_op->d_delete() operation, we sould not | 644 | * If we have a d_op->d_delete() operation, we sould not |
| 645 | * let the dentry count go to zero, so use "put__or_lock". | 645 | * let the dentry count go to zero, so use "put_or_lock". |
| 646 | */ | 646 | */ |
| 647 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) | 647 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) |
| 648 | return lockref_put_or_lock(&dentry->d_lockref); | 648 | return lockref_put_or_lock(&dentry->d_lockref); |
| @@ -697,7 +697,7 @@ static inline bool fast_dput(struct dentry *dentry) | |||
| 697 | */ | 697 | */ |
| 698 | smp_rmb(); | 698 | smp_rmb(); |
| 699 | d_flags = ACCESS_ONCE(dentry->d_flags); | 699 | d_flags = ACCESS_ONCE(dentry->d_flags); |
| 700 | d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST; | 700 | d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED; |
| 701 | 701 | ||
| 702 | /* Nothing to do? Dropping the reference was all we needed? */ | 702 | /* Nothing to do? Dropping the reference was all we needed? */ |
| 703 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) | 703 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) |
| @@ -776,6 +776,9 @@ repeat: | |||
| 776 | if (unlikely(d_unhashed(dentry))) | 776 | if (unlikely(d_unhashed(dentry))) |
| 777 | goto kill_it; | 777 | goto kill_it; |
| 778 | 778 | ||
| 779 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) | ||
| 780 | goto kill_it; | ||
| 781 | |||
| 779 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { | 782 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { |
| 780 | if (dentry->d_op->d_delete(dentry)) | 783 | if (dentry->d_op->d_delete(dentry)) |
| 781 | goto kill_it; | 784 | goto kill_it; |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index f140e3dbfb7b..d9da5a4e9382 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
| @@ -343,6 +343,9 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) | |||
| 343 | struct path realpath; | 343 | struct path realpath; |
| 344 | enum ovl_path_type type; | 344 | enum ovl_path_type type; |
| 345 | 345 | ||
| 346 | if (d_is_dir(dentry)) | ||
| 347 | return d_backing_inode(dentry); | ||
| 348 | |||
| 346 | type = ovl_path_real(dentry, &realpath); | 349 | type = ovl_path_real(dentry, &realpath); |
| 347 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { | 350 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { |
| 348 | err = ovl_want_write(dentry); | 351 | err = ovl_want_write(dentry); |
