Received: by 10.192.165.156 with SMTP id m28csp285558imm; Tue, 17 Apr 2018 10:05:47 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+Xw5QqmXtOLOwBB8k2GdrQ5ilHGpbize6HdMez9XDY65sd8s55ICclTgMR8SdW2gK2tKnC X-Received: by 2002:a17:902:6689:: with SMTP id e9-v6mr2845242plk.176.1523984746980; Tue, 17 Apr 2018 10:05:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523984746; cv=none; d=google.com; s=arc-20160816; b=Aj85z707/Mi+SyRls9QNkcaU8u0hJbJvgrlWpJmI7G4OBS13ra1uLmaYeLoFo/Hj/l caO5ekRpFwWau/Bpvwil6c9kx7FP2bDn8qLFH2nDO0zzA9z7NmqRsNVGFe9wa1+3qWNB 75FSJurs5BZpGjDFjqqM3KPfuCy8VHgAiChbnt7KKqzDPhmkDB8XvWhCtuLOaO1RxXq2 mDTL+40hj187gtHrrKSezvl4+eI8BpZYHApj5YA2c4Wnrdk2BZFGAwdJyJe5ucju8G8x LSGhTq/oTMAyxFACHPAS0s+CiwwYyc4B3q+/L0/Qmw+2ICLhGNKBtxVsmeyU48n90ftS UdQw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=tCGneiZJOcQvUPJ8PiyMxLnlL2GVXMvvB8nGOxVxa74=; b=Zd4ZVc8+AdA0pisP+2vVLg6smNfMsi1+fH3TnVyeBWIC+rPXrgueZWgqYiv7JiLEWU kyhWCZwNNo6LoBKQSbD6917bEWefO6glmhDcYtKy48wS6bjR28S6+g21vhVJU59+Kawn 6qrstdbguG9MASOXy/6yP7u0bhLbSKmNIVCwwoKZKBHjq/nJCjfU32U1gKInUReaB0xp bMS8E5tOCBS3fh3sWfR+iliZKcyS/mCPC6/9+P8B7O5muABsaFikgBoVl/tBpQMh+dSX x1TxVGotragA94lyxwsMdNFUNFOjMxCi+hUg1SmR/edSCGSHr4iBJb5iCXmkkI7NW5su BZWA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q127si1125586pga.326.2018.04.17.10.05.32; Tue, 17 Apr 2018 10:05:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753909AbeDQQBu (ORCPT + 99 others); Tue, 17 Apr 2018 12:01:50 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:60560 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753873AbeDQQBp (ORCPT ); Tue, 17 Apr 2018 12:01:45 -0400 Received: from localhost (unknown [46.44.180.42]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id D8C72DF3; Tue, 17 Apr 2018 16:01:44 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Eddie Horng , Amir Goldstein , Miklos Szeredi Subject: [PATCH 4.16 46/68] ovl: set i_ino to the value of st_ino for NFS export Date: Tue, 17 Apr 2018 17:57:59 +0200 Message-Id: <20180417155751.212310899@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180417155749.341779147@linuxfoundation.org> References: <20180417155749.341779147@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Amir Goldstein commit 695b46e76b62447e506cddc87e088236498008e5 upstream. Eddie Horng reported that readdir of an overlayfs directory that was exported via NFSv3 returns entries with d_type set to DT_UNKNOWN. The reason is that while preparing the response for readdirplus, nfsd checks inside encode_entryplus_baggage() that a child dentry's inode number matches the value of d_ino returns by overlayfs readdir iterator. Because the overlayfs inodes use arbitrary inode numbers that are not correlated with the values of st_ino/d_ino, NFSv3 falls back to not encoding d_type. Although this is an allowed behavior, we can fix it for the case of all overlayfs layers on the same underlying filesystem. When NFS export is enabled and d_ino is consistent with st_ino (samefs), set the same value also to i_ino in ovl_fill_inode() for all overlayfs inodes, nfsd readdirplus sanity checks will pass. ovl_fill_inode() may be called from ovl_new_inode(), before real inode was created with ino arg 0. In that case, i_ino will be updated to real upper inode i_ino on ovl_inode_init() or ovl_inode_update(). Reported-by: Eddie Horng Tested-by: Eddie Horng Signed-off-by: Amir Goldstein Fixes: 8383f1748829 ("ovl: wire up NFS export operations") Cc: #v4.16 Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/overlayfs/inode.c | 21 +++++++++++++++++---- fs/overlayfs/util.c | 8 +++++++- 2 files changed, 24 insertions(+), 5 deletions(-) --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -459,9 +459,20 @@ static inline void ovl_lockdep_annotate_ #endif } -static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev) +static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev, + unsigned long ino) { - inode->i_ino = get_next_ino(); + /* + * When NFS export is enabled and d_ino is consistent with st_ino + * (samefs), set the same value to i_ino, because nfsd readdirplus + * compares d_ino values to i_ino values of child entries. When called + * from ovl_new_inode(), ino arg is 0, so i_ino will be updated to real + * upper inode i_ino on ovl_inode_init() or ovl_inode_update(). + */ + if (inode->i_sb->s_export_op && ovl_same_sb(inode->i_sb)) + inode->i_ino = ino; + else + inode->i_ino = get_next_ino(); inode->i_mode = mode; inode->i_flags |= S_NOCMTIME; #ifdef CONFIG_FS_POSIX_ACL @@ -597,7 +608,7 @@ struct inode *ovl_new_inode(struct super inode = new_inode(sb); if (inode) - ovl_fill_inode(inode, mode, rdev); + ovl_fill_inode(inode, mode, rdev, 0); return inode; } @@ -710,6 +721,7 @@ struct inode *ovl_get_inode(struct super struct inode *inode; bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry, index); bool is_dir; + unsigned long ino = 0; if (!realinode) realinode = d_inode(lowerdentry); @@ -748,13 +760,14 @@ struct inode *ovl_get_inode(struct super if (!is_dir) nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); set_nlink(inode, nlink); + ino = key->i_ino; } else { /* Lower hardlink that will be broken on copy up */ inode = new_inode(sb); if (!inode) goto out_nomem; } - ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); + ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev, ino); ovl_inode_init(inode, upperdentry, lowerdentry); if (upperdentry && ovl_is_impuredir(upperdentry)) --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -279,12 +279,16 @@ void ovl_dentry_set_redirect(struct dent void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, struct dentry *lowerdentry) { + struct inode *realinode = d_inode(upperdentry ?: lowerdentry); + if (upperdentry) OVL_I(inode)->__upperdentry = upperdentry; if (lowerdentry) OVL_I(inode)->lower = igrab(d_inode(lowerdentry)); - ovl_copyattr(d_inode(upperdentry ?: lowerdentry), inode); + ovl_copyattr(realinode, inode); + if (!inode->i_ino) + inode->i_ino = realinode->i_ino; } void ovl_inode_update(struct inode *inode, struct dentry *upperdentry) @@ -299,6 +303,8 @@ void ovl_inode_update(struct inode *inod smp_wmb(); OVL_I(inode)->__upperdentry = upperdentry; if (inode_unhashed(inode)) { + if (!inode->i_ino) + inode->i_ino = upperinode->i_ino; inode->i_private = upperinode; __insert_inode_hash(inode, (unsigned long) upperinode); }