From patchwork Wed Jun 7 07:51:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9770817 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 32F0A60364 for ; Wed, 7 Jun 2017 07:51:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D0A82848D for ; Wed, 7 Jun 2017 07:51:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1224C28528; Wed, 7 Jun 2017 07:51:39 +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 95E1F2848D for ; Wed, 7 Jun 2017 07:51:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751513AbdFGHvg (ORCPT ); Wed, 7 Jun 2017 03:51:36 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:32887 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751491AbdFGHvc (ORCPT ); Wed, 7 Jun 2017 03:51:32 -0400 Received: by mail-wr0-f195.google.com with SMTP id v104so471028wrb.0; Wed, 07 Jun 2017 00:51:31 -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=QfBzenVrggLt39icEQHFumOplV1IhCEHoeUzC0UqMlE=; b=hMha+Ehre6dR2j4H8mLug1tN32E0bgLR3ZmfAJZBsWkv21C6nT1qtkPibTWZ/KHqRI Nsb+PnzUtXuzC8gbwu6MLkYjypKJloIf+5U+HcbL71VXIbky4SL327RqbVEdYKs8tLY2 eJGZAShe9xnx2/cTqkQ1odCnvI8rGUFYILRxmIORbgGOTT71E4i/WxZorClWIz9qIUy5 34QkZ+TqBFHgrqy+viDGEos3qJAK3es4y3Q+ulUZ61ysm26tGr3vxsEKfCUdP4IqVEA3 hQlhboetxU6KzDFQ7F7ZsAJSi9xxiR4MDs4k/HjOlUTwMkR9rYbZZTmKuuYlfVT1z2t5 LtWg== 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=QfBzenVrggLt39icEQHFumOplV1IhCEHoeUzC0UqMlE=; b=rxeSZTypcF/gHNQTKRqMS/dqjgvq6F4rmVzKV4LjsjNb0d7+02ivhNA967q/W3mYr/ MGEEjdGdPHs/xe2oybjlW4PnUi19e0jlj8TCQYPtSj1BWzcZ5G2jzx1VvSamZ9hX3/eJ 0Ln/YseR46pNJi3AxvQ52A8I4+BCOFsJL2zATcTA6egaubfRtB5kWJC8VYdCQGzN4Hon r52UWrt40dFoT3TxqrRD4epmmzC/9suORF3iQdzSUrjGbnO0V6Ys9YA/JsnQkgFMiff8 rje6hpw2bIWEqxa2R3Aj0TXdK2d5FaIYqzZ7KIkhEWC02bi5ScnCcruVK18knbGvAkJ5 DCtw== X-Gm-Message-State: AODbwcCrr+QduFvxKXqxh9mo2lbM9AtWsGSmvL/7aICuEthJ/OJ28Ech xpLk29u5dGVAKQ== X-Received: by 10.223.136.103 with SMTP id e36mr19220724wre.73.1496821890969; Wed, 07 Jun 2017 00:51:30 -0700 (PDT) Received: from amir-VirtualBox.lan (bzq-79-179-137-123.red.bezeqint.net. [79.179.137.123]) by smtp.gmail.com with ESMTPSA id 91sm307202wrn.24.2017.06.07.00.51.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 07 Jun 2017 00:51:30 -0700 (PDT) From: Amir Goldstein To: Miklos Szeredi Cc: Al Viro , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 13/20] ovl: adjust overlay inode nlink for indexed inodes Date: Wed, 7 Jun 2017 10:51:17 +0300 Message-Id: <1496821884-5178-14-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1496821884-5178-1-git-send-email-amir73il@gmail.com> References: <1496821884-5178-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 If overlay inode has an indexed realinode, decrement 1 nlink for the index entry. Overlay inode nlink does not account for all the lower hardlinks that have not been copied up yet. Those will be added to nlink as they get copied up and won't decrement nlink when they get unlinked or renamed over. The important thing to take care of is that overlay inode nlink doesn't drop to zero when there are still upper hardlinks or non covered lower hardlinks. An overlay inode zero nlink stands for an orphan indexed inode. This is the case where some of the lower hardlinks were copied up, modified, and then all copied up upper hardlinks has been unlinked, but there are still non covered lower hardlinks. Return the overlay inode nlinks for indexed upper inodes on stat(2). Signed-off-by: Amir Goldstein --- fs/overlayfs/dir.c | 17 +++++++++++++---- fs/overlayfs/inode.c | 25 ++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index a60c075f62f6..3bb226ffa552 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -733,9 +733,16 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir) return err; } +static bool ovl_type_indexed_lower(struct dentry *dentry) +{ + enum ovl_path_type type = ovl_path_type(dentry); + + return !OVL_TYPE_UPPER(type) && OVL_TYPE_INDEX(type); +} + static int ovl_do_remove(struct dentry *dentry, bool is_dir) { - enum ovl_path_type type; + bool indexed_lower; int err; const struct cred *old_cred; @@ -747,7 +754,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) if (err) goto out_drop_write; - type = ovl_path_type(dentry); + /* An indexed lower hardlink is not counted in overlay nlink */ + indexed_lower = ovl_type_indexed_lower(dentry); old_cred = ovl_override_creds(dentry->d_sb); if (!ovl_lower_positive(dentry)) @@ -758,7 +766,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) if (!err) { if (is_dir) clear_nlink(dentry->d_inode); - else + else if (!indexed_lower) drop_nlink(dentry->d_inode); } out_drop_write: @@ -953,7 +961,8 @@ static int ovl_rename(struct inode *olddir, struct dentry *old, flags |= RENAME_EXCHANGE; cleanup_whiteout = true; } - if (!new_is_dir && new->d_inode) + /* An indexed lower hardlink is not counted in overlay nlink */ + if (!new_is_dir && new->d_inode && !ovl_type_indexed_lower(new)) new_drop_nlink = true; } diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 1f8276d7df32..6e85a2a7fcdc 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -126,6 +126,15 @@ int ovl_getattr(const struct path *path, struct kstat *stat, if (is_dir && OVL_TYPE_MERGE(type)) stat->nlink = 1; + /* + * Return the overlay inode nlinks for indexed upper inodes. + * Overlay nlink accounts for all upper hardlinks excluding the + * index hardlink entry. + * TODO: add count of non-covered lower hardlinks. + */ + if (!is_dir && OVL_TYPE_UPPER(type) && OVL_TYPE_INDEX(type)) + stat->nlink = dentry->d_inode->i_nlink; + out: revert_creds(old_cred); @@ -542,6 +551,7 @@ struct inode *ovl_get_inode(struct super_block *sb, struct ovl_inode_info *oi) { struct inode *realinode = oi->realinode; unsigned long hashval = (unsigned long) realinode; + unsigned int nlink = realinode->i_nlink; struct inode *inode; /* @@ -560,12 +570,25 @@ struct inode *ovl_get_inode(struct super_block *sb, struct ovl_inode_info *oi) if (oi->index && d_inode(oi->index)) { WARN_ON(oi->is_upper && d_inode(oi->index) != realinode); realinode = d_inode(oi->index); + /* + * Decrement 1 nlink for the index entry. Overlay inode nlink + * does not account for all the lower hardlinks that have not + * been copied up yet. Those will be added to nlink as they get + * copied up and won't decrement nlink when they get unlinked + * or renamed over. + * An overlay inode zero nlink stands for an orphan indexed + * inode - an inode that was copied up, modified, and then the + * copied up alias has been unlinked. + */ + nlink = realinode->i_nlink; + if (!WARN_ON(!nlink)) + nlink--; } inode = iget5_locked(sb, hashval, ovl_inode_test, ovl_inode_set, oi); if (inode && inode->i_state & I_NEW) { ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); - set_nlink(inode, realinode->i_nlink); + set_nlink(inode, nlink); unlock_new_inode(inode); }