diff options
| author | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-16 05:02:56 -0500 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-16 05:02:56 -0500 |
| commit | 8ee6059c58ea525f76b4efb98f8f66845f697efc (patch) | |
| tree | 548cb4a104a2d00b0e8a01d7019e9c8c4c64f2cb | |
| parent | 3ee23ff1025a18796607cf4110a8ffa8e2d163fd (diff) | |
ovl: simplify lookup
If encountering a non-directory, then stop looking at lower layers.
In this case the oe->opaque flag is not set anymore, which doesn't matter
since existence of lower file is now checked at remove/rename time.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
| -rw-r--r-- | fs/overlayfs/super.c | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index c0463fb80f41..a19fbcde16bd 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
| @@ -473,7 +473,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
| 473 | unsigned int ctr = 0; | 473 | unsigned int ctr = 0; |
| 474 | struct inode *inode = NULL; | 474 | struct inode *inode = NULL; |
| 475 | bool upperopaque = false; | 475 | bool upperopaque = false; |
| 476 | struct dentry *this, *prev = NULL; | 476 | bool stop = false; |
| 477 | bool isdir = false; | ||
| 478 | struct dentry *this; | ||
| 477 | unsigned int i; | 479 | unsigned int i; |
| 478 | int err; | 480 | int err; |
| 479 | 481 | ||
| @@ -494,23 +496,26 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
| 494 | if (ovl_is_whiteout(this)) { | 496 | if (ovl_is_whiteout(this)) { |
| 495 | dput(this); | 497 | dput(this); |
| 496 | this = NULL; | 498 | this = NULL; |
| 497 | upperopaque = true; | 499 | stop = upperopaque = true; |
| 498 | } else if (poe->numlower && ovl_is_opaquedir(this)) { | 500 | } else if (!d_is_dir(this)) { |
| 499 | upperopaque = true; | 501 | stop = true; |
| 502 | } else { | ||
| 503 | isdir = true; | ||
| 504 | if (poe->numlower && ovl_is_opaquedir(this)) | ||
| 505 | stop = upperopaque = true; | ||
| 500 | } | 506 | } |
| 501 | } | 507 | } |
| 502 | upperdentry = prev = this; | 508 | upperdentry = this; |
| 503 | } | 509 | } |
| 504 | 510 | ||
| 505 | if (!upperopaque && poe->numlower) { | 511 | if (!stop && poe->numlower) { |
| 506 | err = -ENOMEM; | 512 | err = -ENOMEM; |
| 507 | stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL); | 513 | stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL); |
| 508 | if (!stack) | 514 | if (!stack) |
| 509 | goto out_put_upper; | 515 | goto out_put_upper; |
| 510 | } | 516 | } |
| 511 | 517 | ||
| 512 | for (i = 0; !upperopaque && i < poe->numlower; i++) { | 518 | for (i = 0; !stop && i < poe->numlower; i++) { |
| 513 | bool opaque = false; | ||
| 514 | struct path lowerpath = poe->lowerstack[i]; | 519 | struct path lowerpath = poe->lowerstack[i]; |
| 515 | 520 | ||
| 516 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); | 521 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); |
| @@ -530,35 +535,26 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
| 530 | break; | 535 | break; |
| 531 | } | 536 | } |
| 532 | /* | 537 | /* |
| 533 | * Only makes sense to check opaque dir if this is not the | 538 | * If this is a non-directory then stop here. |
| 534 | * lowermost layer. | ||
| 535 | */ | 539 | */ |
| 536 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) | 540 | if (!d_is_dir(this)) { |
| 537 | opaque = true; | 541 | if (isdir) { |
| 538 | 542 | dput(this); | |
| 539 | if (prev && (!S_ISDIR(prev->d_inode->i_mode) || | 543 | break; |
| 540 | !S_ISDIR(this->d_inode->i_mode))) { | 544 | } |
| 545 | stop = true; | ||
| 546 | } else { | ||
| 541 | /* | 547 | /* |
| 542 | * FIXME: check for upper-opaqueness maybe better done | 548 | * Only makes sense to check opaque dir if this is not |
| 543 | * in remove code. | 549 | * the lowermost layer. |
| 544 | */ | 550 | */ |
| 545 | if (prev == upperdentry) | 551 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) |
| 546 | upperopaque = true; | 552 | stop = true; |
| 547 | dput(this); | ||
| 548 | break; | ||
| 549 | } | 553 | } |
| 550 | /* | ||
| 551 | * If this is a non-directory then stop here. | ||
| 552 | */ | ||
| 553 | if (!S_ISDIR(this->d_inode->i_mode)) | ||
| 554 | opaque = true; | ||
| 555 | 554 | ||
| 556 | stack[ctr].dentry = this; | 555 | stack[ctr].dentry = this; |
| 557 | stack[ctr].mnt = lowerpath.mnt; | 556 | stack[ctr].mnt = lowerpath.mnt; |
| 558 | ctr++; | 557 | ctr++; |
| 559 | prev = this; | ||
| 560 | if (opaque) | ||
| 561 | break; | ||
| 562 | } | 558 | } |
| 563 | 559 | ||
| 564 | oe = ovl_alloc_entry(ctr); | 560 | oe = ovl_alloc_entry(ctr); |
