Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp1342323imm; Tue, 2 Oct 2018 06:49:31 -0700 (PDT) X-Google-Smtp-Source: ACcGV6218ggaf4JiqEolLR+HIqACTolC2TaTlUOlE/J0AN6Qd3W/6/Q5KQXYn9OoLMJytgFUfm1Q X-Received: by 2002:a17:902:22cc:: with SMTP id o12-v6mr17026306plg.108.1538488171324; Tue, 02 Oct 2018 06:49:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538488171; cv=none; d=google.com; s=arc-20160816; b=WXbg2IT+hKteYD/zM2jyGvtbaPKOKKFdA+HmIk0+4QTCBhQWc0/fZAa+YfOLp4JZ2b 2xGydBtrPa+zgjJ9GF1+h0il70wB1L4bOHxg08wZOS36Ib8ByztdPyOx/JS7P85kswd8 ht0zBDkND2Nvd0l+F9lPKnyu9k6QLTClVwDTBq2hnFgfldpNxpxndp6JoxYdXfpjsJON LpxfkBfHZPzmseY2AtWci3XVtWQxf5EdWDMviH/KpQSkgvcGYoZn32fSKrNu4y1rT0y+ 2u6ebL1D3/8beEuT+Nky154ahkpx+rJTL4rZR/JIZexpLjgiWIHEJS57Q0v6rfzd/8Kf r+Sw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from; bh=U/MtbNYeXjv7FpfV5puFrlfHMFiI+eLmGqeI+Pb3Kno=; b=bGrTY/jYj80634KbPvpTlDSYI41EGvsvfdNncPM3AwWnDaXKTkGJieeQUq7lUDoiJA NuSySo0An7KOHETN7JI/BBpovifx2UfTMqOrn2HGJxmXrGl0jf5KsYACmaGZ8gBa4jbn GxGsVDUBXgzW0pZbYR9zwwdboj86ul7q0ctWBn9uMmfr/cEK5f/LQWCqMbcOqmi/q0XJ LxImHTnU6JPjYAq+vPJ5TVwpK4ULT5iliRr1080P44MTOAQ/ECxT+TQKFk5ngkZVxNPq m4STykAKCF+PMjiSrie0N0mKKRK73yWR23LG1QUDMR0YCcGGu8qsKQVA0AMWGOtRrb7/ 5pnQ== 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 j7-v6si957821pgj.532.2018.10.02.06.49.16; Tue, 02 Oct 2018 06:49:31 -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 S1732264AbeJBURp (ORCPT + 99 others); Tue, 2 Oct 2018 16:17:45 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:35276 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732244AbeJBURo (ORCPT ); Tue, 2 Oct 2018 16:17:44 -0400 Received: from localhost (24-104-73-23-ip-static.hfc.comcastbusiness.net [24.104.73.23]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id C7A4F5AA; Tue, 2 Oct 2018 13:34:20 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Amir Goldstein , Miklos Szeredi , Mark Salyzyn Subject: [PATCH 4.14 109/137] ovl: hash non-dir by lower inode for fsnotify Date: Tue, 2 Oct 2018 06:25:10 -0700 Message-Id: <20181002132506.146641790@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181002132458.446916963@linuxfoundation.org> References: <20181002132458.446916963@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Amir Goldstein commit 764baba80168ad3adafb521d2ab483ccbc49e344 upstream. Commit 31747eda41ef ("ovl: hash directory inodes for fsnotify") fixed an issue of inotify watch on directory that stops getting events after dropping dentry caches. A similar issue exists for non-dir non-upper files, for example: $ mkdir -p lower upper work merged $ touch lower/foo $ mount -t overlay -o lowerdir=lower,workdir=work,upperdir=upper none merged $ inotifywait merged/foo & $ echo 2 > /proc/sys/vm/drop_caches $ cat merged/foo inotifywait doesn't get the OPEN event, because ovl_lookup() called from 'cat' allocates a new overlay inode and does not reuse the watched inode. Fix this by hashing non-dir overlay inodes by lower real inode in the following cases that were not hashed before this change: - A non-upper overlay mount - A lower non-hardlink when index=off A helper ovl_hash_bylower() was added to put all the logic and documentation about which real inode an overlay inode is hashed by into one place. The issue dates back to initial version of overlayfs, but this patch depends on ovl_inode code that was introduced in kernel v4.13. Cc: #v4.13 Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi Signed-off-by: Mark Salyzyn #4.14 Signed-off-by: Greg Kroah-Hartman --- fs/overlayfs/inode.c | 62 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 18 deletions(-) --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -14,6 +14,7 @@ #include #include #include "overlayfs.h" +#include "ovl_entry.h" int ovl_setattr(struct dentry *dentry, struct iattr *attr) { @@ -608,39 +609,63 @@ static bool ovl_verify_inode(struct inod return true; } +/* + * Does overlay inode need to be hashed by lower inode? + */ +static bool ovl_hash_bylower(struct super_block *sb, struct dentry *upper, + struct dentry *lower, struct dentry *index) +{ + struct ovl_fs *ofs = sb->s_fs_info; + + /* No, if pure upper */ + if (!lower) + return false; + + /* Yes, if already indexed */ + if (index) + return true; + + /* Yes, if won't be copied up */ + if (!ofs->upper_mnt) + return true; + + /* No, if lower hardlink is or will be broken on copy up */ + if ((upper || !ovl_indexdir(sb)) && + !d_is_dir(lower) && d_inode(lower)->i_nlink > 1) + return false; + + /* No, if non-indexed upper with NFS export */ + if (sb->s_export_op && upper) + return false; + + /* Otherwise, hash by lower inode for fsnotify */ + return true; +} + struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, struct dentry *index) { + struct super_block *sb = dentry->d_sb; struct dentry *lowerdentry = ovl_dentry_lower(dentry); struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; struct inode *inode; - /* Already indexed or could be indexed on copy up? */ - bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); - struct dentry *origin = indexed ? lowerdentry : NULL; + bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry, index); bool is_dir; - if (WARN_ON(upperdentry && indexed && !lowerdentry)) - return ERR_PTR(-EIO); - if (!realinode) realinode = d_inode(lowerdentry); /* - * Copy up origin (lower) may exist for non-indexed non-dir upper, but - * we must not use lower as hash key in that case. - * Hash non-dir that is or could be indexed by origin inode. - * Hash dir that is or could be merged by origin inode. - * Hash pure upper and non-indexed non-dir by upper inode. + * Copy up origin (lower) may exist for non-indexed upper, but we must + * not use lower as hash key if this is a broken hardlink. */ is_dir = S_ISDIR(realinode->i_mode); - if (is_dir) - origin = lowerdentry; - - if (upperdentry || origin) { - struct inode *key = d_inode(origin ?: upperdentry); + if (upperdentry || bylower) { + struct inode *key = d_inode(bylower ? lowerdentry : + upperdentry); unsigned int nlink = is_dir ? 1 : realinode->i_nlink; - inode = iget5_locked(dentry->d_sb, (unsigned long) key, + inode = iget5_locked(sb, (unsigned long) key, ovl_inode_test, ovl_inode_set, key); if (!inode) goto out_nomem; @@ -664,7 +689,8 @@ struct inode *ovl_get_inode(struct dentr nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); set_nlink(inode, nlink); } else { - inode = new_inode(dentry->d_sb); + /* Lower hardlink that will be broken on copy up */ + inode = new_inode(sb); if (!inode) goto out_nomem; }