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 /fs/overlayfs | |
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>
Diffstat (limited to 'fs/overlayfs')
-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); |