From patchwork Thu Jan 4 17:20:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10145249 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 92D3A6034B for ; Thu, 4 Jan 2018 17:21:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7691628790 for ; Thu, 4 Jan 2018 17:21:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6922128761; Thu, 4 Jan 2018 17:21:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ECD9328761 for ; Thu, 4 Jan 2018 17:21:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752480AbeADRVK (ORCPT ); Thu, 4 Jan 2018 12:21:10 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:38522 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751066AbeADRUz (ORCPT ); Thu, 4 Jan 2018 12:20:55 -0500 Received: by mail-wm0-f67.google.com with SMTP id 64so4652710wme.3; Thu, 04 Jan 2018 09:20:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tkU506fyMhZhYvxiwYyghz+iFe4kO5AaHCtvIv70Qmg=; b=tiGzY+6BbmdjLdKRr3OIoG2sQI4R1IAPgClQTQF5Qv0B39QtDylRDfx7kNlX0860MB y+hTC0ZjABVwiM5/1IZQLKRVTGBGIsh0+s+P9ScCMD2i/lbqMY5hVCU7tpgkdP+OKTy1 oD3frfa/Rcdk6CHLGaGDvMJNAvsTkTz6rEev/pW8rWOMVmqXG/Z0K5KzTvqz48Wad3Of 2dQ7mPUktgkFPvQ2R5/dTBi7chn4GXlX5eToUUpjs2AUK4bbw7c+N2S3EHAQJeDzfl92 g0zmQTvbcUN9PfZJdNrjpsSRUQkA1JhkNv8OLsKPgJv0bfNZmapn2F13MgPEQbRnYWlL bOJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tkU506fyMhZhYvxiwYyghz+iFe4kO5AaHCtvIv70Qmg=; b=Ps8aBX4eTSGijnHny4rLLqVwxJFTsFZ5NMWn653L+D4ZWJQyEh/mymjVERlt/KaU4j 5BHeMDdwTpfLwBc5jicNm2wvkYvXGb4HHTfKkFRPFOagqQjTmytxYtR+c280kwKnIAk3 JcAex0VQT4vCqz7PAE+Cf4Lmik0m2BsPoDTOELxKsG3F596LkkowxzH4YPGzLFAei6Bg L4b+pIcuu9pyTVdwihxnYSSno8e7v4TDCQxK/l0zD2FxM4ILGfl49LRHzf8U+IpnnRPZ GLTUjBdVPnZDO5bENVPWQJ3KMknrXWWEgnCXxJuxYPrFdRRI+B1u3cLgXkRTSGFoKcP1 Uhiw== X-Gm-Message-State: AKGB3mLYemD6ZvYU6PIYGR16h3DtkTU0gQnkf1XyPAVsGwhU5A1VnR9N zTBIOQRfHdQ2eZuhyRrRaooglQ== X-Google-Smtp-Source: ACJfBosdDRbcPhw4kcuGFPq9dZlpk9AqHIEUTzvHe1js4WRUige1ihewRy7m2L/JLREX9OrvFkTlQg== X-Received: by 10.28.249.12 with SMTP id x12mr176058wmh.122.1515086453714; Thu, 04 Jan 2018 09:20:53 -0800 (PST) Received: from localhost.localdomain (bzq-166-168-31-246.red.bezeqint.net. [31.168.166.246]) by smtp.gmail.com with ESMTPSA id c6sm2777750wmd.21.2018.01.04.09.20.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Jan 2018 09:20:53 -0800 (PST) From: Amir Goldstein To: Miklos Szeredi Cc: Jeff Layton , "J . Bruce Fields" , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 14/17] ovl: lookup connected ancestor of dir in inode cache Date: Thu, 4 Jan 2018 19:20:46 +0200 Message-Id: <1515086449-26563-15-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515086449-26563-1-git-send-email-amir73il@gmail.com> References: <1515086449-26563-1-git-send-email-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Decoding a dir file handle requires walking backward up to layer root and for lower dir also checking the index to see if any of the parents have been copied up. Lookup overlay ancestor dentry in inode/dentry cache by decoded real parents to shortcut looking up all the way back to layer root. Signed-off-by: Amir Goldstein --- fs/overlayfs/export.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++-- fs/overlayfs/inode.c | 8 +++-- fs/overlayfs/overlayfs.h | 3 +- 3 files changed, 93 insertions(+), 6 deletions(-) diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index ec4b9f29d40d..01c4e3f733c1 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -258,6 +258,87 @@ static struct dentry *ovl_lookup_real_one(struct dentry *parent, } /* + * Lookup an indexed or hashed overlay dentry by real inode. + */ +static struct dentry *ovl_lookup_real_inode(struct super_block *sb, + struct dentry *real, bool is_upper) +{ + struct dentry *this = NULL; + struct inode *inode; + + inode = ovl_lookup_inode(sb, real, is_upper); + if (IS_ERR(inode)) + return ERR_CAST(inode); + if (inode) { + this = d_find_any_alias(inode); + iput(inode); + } + + /* TODO: use index when looking up by origin inode */ + if (!this) + return NULL; + + if (WARN_ON(ovl_dentry_real_at(this, is_upper) != real)) { + dput(this); + this = ERR_PTR(-EIO); + } + + return this; +} + +/* + * Lookup an indexed or hashed overlay dentry, whose real dentry is an + * ancestor of @real. + */ +static struct dentry *ovl_lookup_real_ancestor(struct super_block *sb, + struct dentry *real, + bool is_upper) +{ + struct dentry *real_root = ovl_dentry_real_at(sb->s_root, is_upper); + struct dentry *next, *parent = NULL; + struct dentry *ancestor; + + if (real_root == real) + return dget(sb->s_root); + + /* Find the topmost indexed or hashed ancestor */ + next = dget(real); + for (;;) { + parent = dget_parent(next); + + /* + * Lookup a matching overlay dentry in inode/dentry + * cache or in index by real inode. + */ + ancestor = ovl_lookup_real_inode(sb, next, is_upper); + if (ancestor) + break; + + if (real_root == parent) { + ancestor = dget(sb->s_root); + break; + } + + /* + * If @real has been moved out of the layer root directory, + * we will eventully hit the real fs root. + */ + if (parent == next) { + ancestor = ERR_PTR(-EXDEV); + break; + } + + dput(next); + next = parent; + } + + dput(parent); + dput(next); + + return ancestor; +} + +/* * Lookup an overlay dentry whose real dentry is @real. * If @is_upper is true then we lookup an overlay dentry with the same path * as the real dentry. Otherwise, we need to consult index for lookup. @@ -268,7 +349,10 @@ static struct dentry *ovl_lookup_real(struct super_block *sb, struct dentry *connected; int err = 0; - connected = dget(sb->s_root); + connected = ovl_lookup_real_ancestor(sb, real, is_upper); + if (IS_ERR_OR_NULL(connected)) + return connected; + while (!err) { struct dentry *next, *this; struct dentry *parent = NULL; @@ -423,7 +507,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, goto out_err; } else if (is_deleted && origin.dentry && !d_is_dir(origin.dentry)) { /* Lookup deleted overlay inode by origin inode */ - inode = ovl_lookup_inode(sb, origin.dentry); + inode = ovl_lookup_inode(sb, origin.dentry, false); err = -ESTALE; if (!inode || atomic_read(&inode->i_count) == 1) goto out_err; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 8db3f466df60..038a62857580 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -639,15 +639,17 @@ static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, return true; } -struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *origin) +struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real, + bool is_upper) { - struct inode *inode, *key = d_inode(origin); + struct inode *inode, *key = d_inode(real); inode = ilookup5(sb, (unsigned long) key, ovl_inode_test, key); if (!inode) return NULL; - if (!ovl_verify_inode(inode, origin, NULL)) { + if (!ovl_verify_inode(inode, is_upper ? NULL : real, + is_upper ? real : NULL)) { iput(inode); return ERR_PTR(-ESTALE); } diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 7310e0eca383..d06299b27ec3 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -306,7 +306,8 @@ int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); bool ovl_is_private_xattr(const char *name); struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); -struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *origin); +struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real, + bool is_upper); struct inode *ovl_get_inode(struct super_block *sb, struct dentry *upperdentry, struct dentry *lowerdentry, struct dentry *index, unsigned int numlower);