diff options
author | hujianyang <hujianyang@huawei.com> | 2015-01-06 03:10:01 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2015-01-08 08:47:20 -0500 |
commit | a425c037f3dd8a56469158ab5f37beb46402d958 (patch) | |
tree | b412f83087392ee4b96c6be8437c782ad53a775b /fs | |
parent | 2f83fd8c2849a388082f30d755a75c1e67c4643b (diff) |
ovl: Fix opaque regression in ovl_lookup
Current multi-layer support overlayfs has a regression in
.lookup(). If there is a directory in upperdir and a regular
file has same name in lowerdir in a merged directory, lower
file is hidden and upper directory is set to opaque in former
case. But it is changed in present code.
In lowerdir lookup path, if a found inode is not directory,
the type checking of previous inode is missing. This inode
will be copied to the lowerstack of ovl_entry directly.
That will lead to several wrong conditions, for example,
the reading of the directory in upperdir may return an error
like:
ls: reading directory .: Not a directory
This patch makes the lowerdir lookup path check the opaque
for non-directory file too.
Signed-off-by: hujianyang <hujianyang@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/super.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 6ca8ea8cb9b2..9e94f4acef1a 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -372,7 +372,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
372 | bool opaque = false; | 372 | bool opaque = false; |
373 | struct path lowerpath = poe->lowerstack[i]; | 373 | struct path lowerpath = poe->lowerstack[i]; |
374 | 374 | ||
375 | opaque = false; | ||
376 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); | 375 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); |
377 | err = PTR_ERR(this); | 376 | err = PTR_ERR(this); |
378 | if (IS_ERR(this)) { | 377 | if (IS_ERR(this)) { |
@@ -395,20 +394,24 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
395 | */ | 394 | */ |
396 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) | 395 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) |
397 | opaque = true; | 396 | opaque = true; |
398 | /* | 397 | |
399 | * If this is a non-directory then stop here. | 398 | if (prev && (!S_ISDIR(prev->d_inode->i_mode) || |
400 | * | 399 | !S_ISDIR(this->d_inode->i_mode))) { |
401 | * FIXME: check for opaqueness maybe better done in remove code. | 400 | /* |
402 | */ | 401 | * FIXME: check for upper-opaqueness maybe better done |
403 | if (!S_ISDIR(this->d_inode->i_mode)) { | 402 | * in remove code. |
404 | opaque = true; | 403 | */ |
405 | } else if (prev && (!S_ISDIR(prev->d_inode->i_mode) || | ||
406 | !S_ISDIR(this->d_inode->i_mode))) { | ||
407 | if (prev == upperdentry) | 404 | if (prev == upperdentry) |
408 | upperopaque = true; | 405 | upperopaque = true; |
409 | dput(this); | 406 | dput(this); |
410 | break; | 407 | break; |
411 | } | 408 | } |
409 | /* | ||
410 | * If this is a non-directory then stop here. | ||
411 | */ | ||
412 | if (!S_ISDIR(this->d_inode->i_mode)) | ||
413 | opaque = true; | ||
414 | |||
412 | stack[ctr].dentry = this; | 415 | stack[ctr].dentry = this; |
413 | stack[ctr].mnt = lowerpath.mnt; | 416 | stack[ctr].mnt = lowerpath.mnt; |
414 | ctr++; | 417 | ctr++; |