Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3476870imm; Tue, 29 May 2018 07:55:59 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqHeY2dqG9G18aAi+hg46DBkBfwquHqFnf4d0D6ooNUwkXDcBlPiVCu5lCJZyAl4DvBaNBA X-Received: by 2002:a63:9402:: with SMTP id m2-v6mr14032430pge.8.1527605759136; Tue, 29 May 2018 07:55:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527605759; cv=none; d=google.com; s=arc-20160816; b=WwfGorvNky+/RmwBMXJvaJc/hTSDrGt3UVdyTEfA6sFnyUUHDHTMgsSfYcuiyfxRSE uHtcTGtMOBbtWgDyCwX6jRRfO9CRKBUwKjGOtLXVbMW8nQpabrWCAkXTVnbTMmO2gZFV yPZn6lQkXobRClJBFSnCeqmPN8KCyAQXUNnTvaYwRoUeyksbwQGjiRWQzbACyqWfbsp5 OaSHH0YOgNp9pOCtHlvnxbDEOZdcuTfoLp+okD97Ky8GmsIdw5d7bblZ93e+YbROg0D7 qeKRB1/0MQ/UHHUU53H266pLVPVy9A6UGXNDYSqzZYP9XaJrhkhf+Bakga3FaVwdgeY8 sPJQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=tgxLat16T6Labvt5iGVJI5Bgwc5je1uyrX7lKmIMj6w=; b=WpIR5ox8D3Z4XuIrClnyoafDf4Erl/8A3T2NBwxJPNXEcfuG3qWi2/sw8Qt00DL5TO EGXUyyd2eHd+keZCyrs6125fNXmQcZfFpPxP8M2hBXNZ7DQOZlbztOSjKOGUxwENa6kz RbdhixsmqbnkhWX81siMZrwoGo9En8q9dOJPFptKbvACYO8BYUQna9JxsPScRnCjZUVz L0ZiJeGc7iltZgb2Ww2HUj5rWIriekihTTIOjw+yuJ1rSYEl04OrLqzq/Wu2vOCv4Az6 RRMm8QDv5wDvO5f+3+ByFBXhAPOGocmOwHa8gvT1XJd/kck7wEEU1mj3N5QS02pgGYkf 6rtg== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q19-v6si4281988pgn.392.2018.05.29.07.55.45; Tue, 29 May 2018 07:55:59 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S936579AbeE2Oxj (ORCPT + 99 others); Tue, 29 May 2018 10:53:39 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:41892 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935486AbeE2Oqb (ORCPT ); Tue, 29 May 2018 10:46:31 -0400 Received: by mail-wr0-f195.google.com with SMTP id u12-v6so25970859wrn.8 for ; Tue, 29 May 2018 07:46:31 -0700 (PDT) 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=tgxLat16T6Labvt5iGVJI5Bgwc5je1uyrX7lKmIMj6w=; b=Umo/xup/3x68lC75cCnFxo048uxpft3FtHqYCMenSfZUQyCSbcDozCdb9f87T6gwlA AgmdxpGpPaEHJf7ifPA6GIzrEVYraKscdAxhqlkGX4cEyLBWx3m6tdoKW9X5Qa6sJBEw EgXTS0IyXYczmqbx/wKtLXiAPXTsNXoJJbvXGTXO/WCOvlqLNFED2SfdYC27Pjp94Wpk 6OLCxw/u6v0nkocqeyJA1CiFZjLkYLd9QRYREZBmA1dgRv20B4B1GoHfcOjSkgRqKkgH 0QxK8sWQNiqBtVrEZXujEspVCfotF6uxFGP5enWFOLpQQP+RlyqydmdDy1+KMfsr+wIk Gv1g== X-Gm-Message-State: ALKqPwflwz6rwzhekWTVc4i1UclimRqn2afmvmfTZ9avQJaE+GRBiBvw tfSBXO/rJGywjDRekOiEvet4Y3ZG3nE= X-Received: by 2002:adf:e084:: with SMTP id c4-v6mr12942333wri.199.1527605189753; Tue, 29 May 2018 07:46:29 -0700 (PDT) Received: from veci.piliscsaba.redhat.com (catv-176-63-54-97.catv.broadband.hu. [176.63.54.97]) by smtp.gmail.com with ESMTPSA id n71-v6sm20942227wmi.14.2018.05.29.07.46.28 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 29 May 2018 07:46:29 -0700 (PDT) From: Miklos Szeredi To: linux-unionfs@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 12/28] ovl: Fix ovl_getattr() to get number of blocks from lower Date: Tue, 29 May 2018 16:45:56 +0200 Message-Id: <20180529144612.16675-13-mszeredi@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180529144612.16675-1-mszeredi@redhat.com> References: <20180529144612.16675-1-mszeredi@redhat.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Vivek Goyal If an inode has been copied up metadata only, then we need to query the number of blocks from lower and fill up the stat->st_blocks. We need to be careful about races where we are doing stat on one cpu and data copy up is taking place on other cpu. We want to return stat->st_blocks either from lower or stable upper and not something in between. Hence, ovl_has_upperdata() is called first to figure out whether block reporting will take place from lower or upper. We now support metacopy dentries in middle layer. That means number of blocks reporting needs to come from lowest data dentry and this could be different from lower dentry. Hence we end up making a separate vfs_getxattr() call for metacopy dentries to get number of blocks. Signed-off-by: Vivek Goyal Reviewed-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/overlayfs/inode.c | 35 ++++++++++++++++++++++++++++++++++- fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/util.c | 16 ++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 350e38c5ce7d..6a6693150c37 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -145,6 +145,9 @@ int ovl_getattr(const struct path *path, struct kstat *stat, bool samefs = ovl_same_sb(dentry->d_sb); struct ovl_layer *lower_layer = NULL; int err; + bool metacopy_blocks = false; + + metacopy_blocks = ovl_is_metacopy_dentry(dentry); type = ovl_path_real(dentry, &realpath); old_cred = ovl_override_creds(dentry->d_sb); @@ -166,7 +169,8 @@ int ovl_getattr(const struct path *path, struct kstat *stat, lower_layer = ovl_layer_lower(dentry); } else if (OVL_TYPE_ORIGIN(type)) { struct kstat lowerstat; - u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0); + u32 lowermask = STATX_INO | STATX_BLOCKS | + (!is_dir ? STATX_NLINK : 0); ovl_path_lower(dentry, &realpath); err = vfs_getattr(&realpath, &lowerstat, @@ -195,6 +199,35 @@ int ovl_getattr(const struct path *path, struct kstat *stat, stat->ino = lowerstat.ino; lower_layer = ovl_layer_lower(dentry); } + + /* + * If we are querying a metacopy dentry and lower + * dentry is data dentry, then use the blocks we + * queried just now. We don't have to do additional + * vfs_getattr(). If lower itself is metacopy, then + * additional vfs_getattr() is unavoidable. + */ + if (metacopy_blocks && + realpath.dentry == ovl_dentry_lowerdata(dentry)) { + stat->blocks = lowerstat.blocks; + metacopy_blocks = false; + } + } + + if (metacopy_blocks) { + /* + * If lower is not same as lowerdata or if there was + * no origin on upper, we can end up here. + */ + struct kstat lowerdatastat; + u32 lowermask = STATX_BLOCKS; + + ovl_path_lowerdata(dentry, &realpath); + err = vfs_getattr(&realpath, &lowerdatastat, + lowermask, flags); + if (err) + goto out; + stat->blocks = lowerdatastat.blocks; } } diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 13b2151cf4df..ae06fd531b75 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -271,6 +271,7 @@ int ovl_nlink_start(struct dentry *dentry, bool *locked); void ovl_nlink_end(struct dentry *dentry, bool locked); int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir); int ovl_check_metacopy_xattr(struct dentry *dentry); +bool ovl_is_metacopy_dentry(struct dentry *dentry); static inline bool ovl_is_impuredir(struct dentry *dentry) { diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 7c7b95d5da1f..4f9c2ecee74c 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -825,3 +825,19 @@ int ovl_check_metacopy_xattr(struct dentry *dentry) pr_warn_ratelimited("overlayfs: failed to get metacopy (%i)\n", res); return res; } + +bool ovl_is_metacopy_dentry(struct dentry *dentry) +{ + struct ovl_entry *oe = dentry->d_fsdata; + + if (!d_is_reg(dentry)) + return false; + + if (ovl_dentry_upper(dentry)) { + if (!ovl_has_upperdata(d_inode(dentry))) + return true; + return false; + } + + return (oe->numlower > 1); +} -- 2.14.3