From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C4AEEC43382 for ; Fri, 28 Sep 2018 17:22:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6FE2420676 for ; Fri, 28 Sep 2018 17:22:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=android.com header.i=@android.com header.b="wADK4z76" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6FE2420676 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=android.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729497AbeI1Xrc (ORCPT ); Fri, 28 Sep 2018 19:47:32 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:36023 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726934AbeI1Xrb (ORCPT ); Fri, 28 Sep 2018 19:47:31 -0400 Received: by mail-pg1-f194.google.com with SMTP id f18-v6so1429348pgv.3 for ; Fri, 28 Sep 2018 10:22:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=jixE4dktc9tg/BVvAzQI2i/55DQM6A5/+8EwamwF8ok=; b=wADK4z76JHbyl2EsFn19f7bkHwUTye3F0w/zZ3Y6TtLO2md6329WXHKTJhoxWRA2EI 8tPglGYAYcOP/pFpJ1ZzbO5vsKU+CnxI12Vl/owUhIFlUPXi8NQeBm1h7vLDCndPZezu jK0I5khr+Qdvb78Ba/XZINiba92i1er44kr9qCa4N/qVXUZVr12LqF82z+YXPej148p1 jjO0CEU1713sG1pYV+0ag/cWPwN8q19+oRjQxi6uNUAJbVOvXva0bfVuAa2AUBcLSReX TZ2O2n0gYp1s6SSzodhgsELwix9PWFBz2aPX92ulRzSpbrVNLd8xH5DEPbR5HIOPkgqv UHGw== 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:mime-version :content-transfer-encoding; bh=jixE4dktc9tg/BVvAzQI2i/55DQM6A5/+8EwamwF8ok=; b=Fa9CMzlcIDA68fYLwkmk6noZ/uOFRQlMhZYBoPxzWGGClYM1m5UllbPZiWlX91NUAH dng2Zpjb0QJEjt42d9aXeKsfBSQnQypddwgXzUWtbSbhEif8viztjbo/EDaebVOIWJOU /cxiBIiNlhm1+bo9BRyz3YmIHOUHAQDM3RDxmQBIgtEEX4/3/tF2Y0XvdTgjjJ1A6i83 sk+XmhPQrbMsbKR2ljjM2NWwmJLq4lJc4o5sxYyV5ZaOIoUCx7RUuNQZyAgfDczXtP0v YGVRj1yKW4ojAB4Jsy6h3qZtMHMMqVUmb3UIAl8bL8zujspEnx4TxvrVUaSgCmd7McIT 5hLw== X-Gm-Message-State: ABuFfohCA8ehOtZmR/PVwOjW1YI3dewwZQVzkC3QekKfpJSw6RLc5THE 5mq9ronICpGRfB7s4K4iHeOS3/gl0hg= X-Google-Smtp-Source: ACcGV63Mm9pEZNJylVSF9kohqZCwEFVCwEWRNunSKJUdj3q01FqWgPZQED8izxHU8t2R6swVakFnvQ== X-Received: by 2002:aa7:86cb:: with SMTP id h11-v6mr17723929pfo.58.1538155365467; Fri, 28 Sep 2018 10:22:45 -0700 (PDT) Received: from nebulus.mtv.corp.google.com ([2620:0:1000:1612:b4fb:6752:f21f:3502]) by smtp.gmail.com with ESMTPSA id i2-v6sm8584369pgq.35.2018.09.28.10.22.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 28 Sep 2018 10:22:44 -0700 (PDT) From: Mark Salyzyn To: linux-kernel@vger.kernel.org Cc: Mark Salyzyn , Amir Goldstein , Miklos Szeredi , stable@vger.kernel.org, linux-unionfs@vger.kernel.org, Greg KH , Miklos Szeredi Subject: ovl: hash non-dir by lower inode for fsnotify Date: Fri, 28 Sep 2018 10:22:12 -0700 Message-Id: <20180928172223.38233-1-salyzyn@android.com> X-Mailer: git-send-email 2.19.0.605.g01d371f741-goog MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org (cherry pick from commit 764baba80168ad3adafb521d2ab483ccbc49e344) 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. Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi Cc: #v4.13 Signed-off-by: Mark Salyzyn #4.14 Cc: Cc: Cc: Greg KH --- fs/overlayfs/inode.c | 62 +++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index d60900b615f9..efed50304b49 100644 --- 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 inode *inode, struct dentry *lowerdentry, 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 dentry *dentry, struct dentry *upperdentry, 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; } -- 2.19.0.605.g01d371f741-goog