From patchwork Tue Oct 17 16:44:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10012469 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 B0F21600CC for ; Tue, 17 Oct 2017 16:44:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A5DBE2899B for ; Tue, 17 Oct 2017 16:44:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 99F142899D; Tue, 17 Oct 2017 16:44:50 +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=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM 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 176262899B for ; Tue, 17 Oct 2017 16:44:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S937081AbdJQQor (ORCPT ); Tue, 17 Oct 2017 12:44:47 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:53799 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937041AbdJQQoL (ORCPT ); Tue, 17 Oct 2017 12:44:11 -0400 Received: by mail-wm0-f67.google.com with SMTP id q132so5176902wmd.2; Tue, 17 Oct 2017 09:44:10 -0700 (PDT) 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=tOUjudKm5qsVQ/Cb1MNIcwMRSH20C+2loULcxvudwz4=; b=DydoRjdE3y0esEy0lGbl4IWGjK+aiCQCUNO+4SCPo7yyyMFSxBjLoiPk87lotQhbv7 AatOp+MTkmpPVZtd9Jdjoxt4BwZx1gCoIdNp41Hdl6uaJD0B3+yrAsI3jrxq8nJVUNDv wG+qvcyHNhMsSqycpz2qjssqylqLI25hSETpWxFKqw+R+fy8KnI3LkXfdZ0nJthZWa6P oAN6HkFW8oVOgJ4lHIyiZUj0XUTdbdTl1B3D6LLGnZwvdj8ntebIe3zvqtOfw3yOudzu onQI/5TapMGW3w3B992OOvYj1tbrxHMe4Z0KkemHFHb1aHig+rQ0/cWAzJ7OUTk/n/bF XrBg== 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=tOUjudKm5qsVQ/Cb1MNIcwMRSH20C+2loULcxvudwz4=; b=nUOBsN2NgUXR0qk33Swkv1AR3Fp6ECmFdJ2qlnaLvO5HhS559yaSixBKVexaogWNJ9 lnTRsw8BbWwNro+HfO713Rf8xZXnipsQL4gqXO3Mgw4GocR5/R4PLp66/rmpEAk59E+n zFrQZRa/TdKS+vQj0LfrkbIq8UzhYQdCf6rMFVDf0ROSKLLOzEF5IQBCQqQlwT7JfBwz jF4QElXEOYPh4+KCTWKErCQbRsjjUvbJM6li8h6eaCtLOPOVTKLsG+cFNLZTpIrlEPKK 6H+qYxKI+Ju4kYIAcTiLO8bXupcuGR4V26puKyYIh62J27jumsdyHrXBygOXXave9WEO 53dA== X-Gm-Message-State: AMCzsaWu0LNjxhkZtPINwf5qxXLnTbUEl99J5wjZzQ06BNW8ONHeUA+i fqF1Qggcoahagn57e7VyYf9L+56M X-Google-Smtp-Source: AOwi7QDXXo8vqwhX1It46YMVp+zGSIYjMH48ESanq0mkNfxdT5NCKer/2aK56SVLluyIvu6wyUkSIA== X-Received: by 10.80.181.61 with SMTP id y58mr18097206edd.150.1508258649711; Tue, 17 Oct 2017 09:44:09 -0700 (PDT) Received: from localhost.localdomain (bzq-166-168-31-246.red.bezeqint.net. [31.168.166.246]) by smtp.gmail.com with ESMTPSA id c25sm8439979edb.28.2017.10.17.09.44.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 17 Oct 2017 09:44:09 -0700 (PDT) From: Amir Goldstein To: Miklos Szeredi Cc: Jeff Layton , "J . Bruce Fields" , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 10/14] ovl: obtain a non-pure-upper disconnected dentry Date: Tue, 17 Oct 2017 19:44:27 +0300 Message-Id: <1508258671-10800-11-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1508258671-10800-1-git-send-email-amir73il@gmail.com> References: <1508258671-10800-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 Instantiate an overlay dentry from lower real inode and optionally from upper real inode with origin xattr. This is needed for decoding an overlay inode that was encoded by real lower file handle and since then may or may not have been copied up and indexed. This implementation is currently limited to non-dir and merge dirs with single lower dir. For this reason, NFS export support currently requires overlay with single lower layer. Signed-off-by: Amir Goldstein --- fs/overlayfs/export.c | 44 +++++++++++++++++++++++++++++----------- fs/overlayfs/namei.c | 52 ++++++++++++++++++++++++++++++------------------ fs/overlayfs/overlayfs.h | 4 ++++ 3 files changed, 69 insertions(+), 31 deletions(-) diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index 7ebe04317647..476e2a74aca7 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c @@ -176,17 +176,13 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb, struct dentry *upper, struct dentry *lower) { + struct ovl_fs *ofs = sb->s_fs_info; struct inode *inode; struct dentry *dentry; + struct dentry *index = lower ? upper : NULL; struct ovl_entry *oe; - /* TODO: handle decoding of non pure upper */ - if (lower) { - dput(upper); - return ERR_PTR(-EINVAL); - } - - inode = ovl_get_inode(sb, upper, NULL, NULL); + inode = ovl_get_inode(sb, upper, lower, index); if (IS_ERR(inode)) { dput(upper); return ERR_CAST(inode); @@ -206,16 +202,40 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb, return dentry; } - oe = ovl_alloc_entry(0); + /* + * This implementation is currently limited to non-dir and merge dirs + * with single lower dir. For this reason, NFS export support currently + * requires overlay with single lower layer. + * + * TODO: use ovl_lookup or derivative to populate lowerstack with more + * lower dirs to support NFS export with multi lower layers. + */ + oe = ovl_alloc_entry(lower ? 1 : 0); if (!oe) { dput(dentry); return ERR_PTR(-ENOMEM); } - + if (lower) { + oe->lowerstack->dentry = dget(lower); + oe->lowerstack->mnt = ofs->lower_mnt[0]; + } dentry->d_fsdata = oe; - ovl_dentry_set_upper_alias(dentry); - if (d_is_dir(upper) && ovl_is_opaquedir(upper)) - ovl_dentry_set_opaque(dentry); + + if (upper) { + ovl_dentry_set_upper_alias(dentry); + if (d_is_dir(upper)) { + size_t len = 0; + char *redirect = ovl_get_redirect_xattr(upper, &len); + + if (redirect) + ovl_dentry_set_redirect(dentry, redirect); + if (ovl_is_opaquedir(upper)) + ovl_dentry_set_opaque(dentry); + } + } + + if (index) + ovl_set_flag(OVL_INDEX, inode); return dentry; diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 4f20af22bd0b..796c869559a9 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -26,8 +26,7 @@ struct ovl_lookup_data { char *redirect; }; -static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, - size_t prelen, const char *post) +char *ovl_get_redirect_xattr(struct dentry *dentry, size_t *len) { int res; char *s, *next, *buf = NULL; @@ -35,12 +34,12 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) - return 0; + return NULL; goto fail; } - buf = kzalloc(prelen + res + strlen(post) + 1, GFP_KERNEL); + buf = kzalloc(res + *len + 1, GFP_KERNEL); if (!buf) - return -ENOMEM; + return ERR_PTR(-ENOMEM); if (res == 0) goto invalid; @@ -59,22 +58,14 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, } else { if (strchr(buf, '/') != NULL) goto invalid; - - memmove(buf + prelen, buf, res); - memcpy(buf, d->name.name, prelen); } - strcat(buf, post); - kfree(d->redirect); - d->redirect = buf; - d->name.name = d->redirect; - d->name.len = strlen(d->redirect); - - return 0; + *len = res; + return buf; err_free: kfree(buf); - return 0; + return NULL; fail: pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res); goto err_free; @@ -83,6 +74,29 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, goto err_free; } +static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d, + size_t prelen, const char *post) +{ + size_t len = prelen + strlen(post); + char *buf = ovl_get_redirect_xattr(dentry, &len); + + if (IS_ERR_OR_NULL(buf)) + return PTR_ERR(buf); + + if (buf[0] != '/' && prelen) { + memmove(buf + prelen, buf, len); + memcpy(buf, d->name.name, prelen); + } + + strcat(buf, post); + kfree(d->redirect); + d->redirect = buf; + d->name.name = d->redirect; + d->name.len = strlen(d->redirect); + + return 0; +} + static int ovl_acceptable(void *mnt, struct dentry *dentry) { /* @@ -348,9 +362,9 @@ static int ovl_check_origin_fh(struct ovl_fh *fh, struct dentry *upperdentry, return -ESTALE; } -static int ovl_check_origin(struct dentry *upperdentry, - struct path *lowerstack, unsigned int numlower, - struct path **stackp, unsigned int *ctrp) +int ovl_check_origin(struct dentry *upperdentry, struct path *lowerstack, + unsigned int numlower, struct path **stackp, + unsigned int *ctrp) { struct ovl_fh *fh = ovl_get_origin_fh(upperdentry); int err; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 75a8b10d4e10..ffc5a955478e 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -271,8 +271,12 @@ static inline bool ovl_is_opaquedir(struct dentry *dentry) /* namei.c */ +char *ovl_get_redirect_xattr(struct dentry *dentry, size_t *len); int ovl_check_fh_len(struct ovl_fh *fh, int fh_len); struct dentry *ovl_decode_fh(struct ovl_fh *fh, struct vfsmount *mnt); +int ovl_check_origin(struct dentry *upperdentry, struct path *lowerstack, + unsigned int numlower, struct path **stackp, + unsigned int *ctrp); int ovl_verify_origin(struct dentry *dentry, struct dentry *origin, bool is_upper, bool set); int ovl_verify_index(struct dentry *index, struct vfsmount *mnt,