diff options
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r-- | fs/overlayfs/inode.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index a619addecafc..321511ed8c42 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -598,18 +598,30 @@ static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, | |||
598 | return true; | 598 | return true; |
599 | } | 599 | } |
600 | 600 | ||
601 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry) | 601 | struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, |
602 | struct dentry *index) | ||
602 | { | 603 | { |
603 | struct dentry *lowerdentry = ovl_dentry_lower(dentry); | 604 | struct dentry *lowerdentry = ovl_dentry_lower(dentry); |
604 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; | 605 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; |
605 | struct inode *inode; | 606 | struct inode *inode; |
607 | /* Already indexed or could be indexed on copy up? */ | ||
608 | bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); | ||
609 | |||
610 | if (WARN_ON(upperdentry && indexed && !lowerdentry)) | ||
611 | return ERR_PTR(-EIO); | ||
606 | 612 | ||
607 | if (!realinode) | 613 | if (!realinode) |
608 | realinode = d_inode(lowerdentry); | 614 | realinode = d_inode(lowerdentry); |
609 | 615 | ||
610 | if (!S_ISDIR(realinode->i_mode) && | 616 | /* |
611 | (upperdentry || (lowerdentry && ovl_indexdir(dentry->d_sb)))) { | 617 | * Copy up origin (lower) may exist for non-indexed upper, but we must |
612 | struct inode *key = d_inode(lowerdentry ?: upperdentry); | 618 | * not use lower as hash key in that case. |
619 | * Hash inodes that are or could be indexed by origin inode and | ||
620 | * non-indexed upper inodes that could be hard linked by upper inode. | ||
621 | */ | ||
622 | if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) { | ||
623 | struct inode *key = d_inode(indexed ? lowerdentry : | ||
624 | upperdentry); | ||
613 | unsigned int nlink; | 625 | unsigned int nlink; |
614 | 626 | ||
615 | inode = iget5_locked(dentry->d_sb, (unsigned long) key, | 627 | inode = iget5_locked(dentry->d_sb, (unsigned long) key, |