From patchwork Sun Jan 15 13:57:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9517423 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 AEFEB601DA for ; Sun, 15 Jan 2017 13:58:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9E7E22793B for ; Sun, 15 Jan 2017 13:58:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9363C282E2; Sun, 15 Jan 2017 13:58:01 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID 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 B278C2793B for ; Sun, 15 Jan 2017 13:58:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751151AbdAON57 (ORCPT ); Sun, 15 Jan 2017 08:57:59 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:36595 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751138AbdAON56 (ORCPT ); Sun, 15 Jan 2017 08:57:58 -0500 Received: by mail-wm0-f68.google.com with SMTP id r126so24159946wmr.3; Sun, 15 Jan 2017 05:57:57 -0800 (PST) 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=F1fTElJ0KcutLGUJF4s3ZRyaJrGzV0s7+QT3R0MS6aY=; b=SaIsQn9PP9yacPthchDK92KNH0VG+hiMtHJ+s8gTNsyPst3sPFrJs9jXaULz2xoIGX WDqVTQQKMZTpofBqJwC+vQEF2CV6/OpQPuG5HpVbTOeglZTqh/4s01mVEaBjiOfUuewd ExnshkYbkGRuDa7k7kdMySwMbmfodMWm7i3ogYimio6EQdLwwdVgVTnxSvkNqY4ZoJJK A2kfTL2vHdvCzw6Js29MaMHMFJZ3CjIsygyootK5ZvnY7jGgseRQuEUkbmoDXsiGCuM7 u6W1y668atykgL/6+d4Jo89AIansyngAqhwmrMZwQ/akPUGbDnR7scIj476t5FKZzawW r2ug== 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=F1fTElJ0KcutLGUJF4s3ZRyaJrGzV0s7+QT3R0MS6aY=; b=sJxx21jOzM8hVRlgU6Q+EJr+U91e90zIqpvtRPx9b/kb+rRwcIX3xIqsq1qtt8fFIg Fxz3A1NsV/39UzmsWX51G5B7YZBDdDHqkO1bQaAgvimEIRqvcqHxoC0IHbjTA40158Tb GCf4mmDFvnfGsmLP0EHlMs0Pc5kxAhzZDSUy/k2evH2lXIbg03ZtV6DHuY9fqQlrNOJT S+1JQsOcBYuhw4vuFswgi5SyOIG9Q7lC1ejOry0Z6D0rhAOVQgU5OhplO6L/CTnKgjZm JXesQlQKDg4cT0PxxbgNz7RYK3YktyL8dBbESRL1caCaWpYMc5u+yD2t69eVbfweWqFN /sWQ== X-Gm-Message-State: AIkVDXJNAT9ZdOBzp8GsvgsUv8QcSYrKvKu/o1TgLYL4V0oXYEoGynmg6k4K1glnkk4G4A== X-Received: by 10.223.161.194 with SMTP id v2mr18920770wrv.63.1484488676514; Sun, 15 Jan 2017 05:57:56 -0800 (PST) Received: from amir-VirtualBox.ctera.local (bzq-82-81-193-202.cablep.bezeqint.net. [82.81.193.202]) by smtp.gmail.com with ESMTPSA id v143sm6987295wmv.4.2017.01.15.05.57.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 15 Jan 2017 05:57:55 -0800 (PST) From: Amir Goldstein To: Miklos Szeredi Cc: Al Viro , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 4/6] ovl: copy up regular file using O_TMPFILE Date: Sun, 15 Jan 2017 15:57:30 +0200 Message-Id: <1484488652-611-5-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1484488652-611-1-git-send-email-amir73il@gmail.com> References: <1484488652-611-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 In preparation for concurrent copy up, implement copy up of regular file as O_TMPFILE that is linked to upperdir instead of a file in workdir that is moved to upperdir. Suggested-by: Al Viro Signed-off-by: Amir Goldstein --- fs/overlayfs/copy_up.c | 28 +++++++++++++++++++++------- fs/overlayfs/overlayfs.h | 2 ++ fs/overlayfs/util.c | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 429990a..d3b6c15 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -20,6 +20,7 @@ #include #include #include "overlayfs.h" +#include "ovl_entry.h" #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) @@ -232,7 +233,8 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, struct dentry *dentry, struct path *lowerpath, - struct kstat *stat, const char *link) + struct kstat *stat, const char *link, + bool tmpfile) { struct inode *wdir = workdir->d_inode; struct inode *udir = upperdir->d_inode; @@ -262,12 +264,17 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, if (new_creds) old_creds = override_creds(new_creds); - temp = ovl_lookup_temp(workdir, dentry); + if (tmpfile) + temp = ovl_alloc_tmpfile(upperdir, stat->mode); + else + temp = ovl_lookup_temp(workdir, dentry); err = PTR_ERR(temp); if (IS_ERR(temp)) goto out1; - err = ovl_create_real(wdir, temp, &cattr, NULL, true); + err = 0; + if (!tmpfile) + err = ovl_create_real(wdir, temp, &cattr, NULL, true); if (new_creds) { revert_creds(old_creds); @@ -299,11 +306,14 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, if (err) goto out_cleanup; - err = ovl_do_rename(wdir, temp, udir, upper, 0); + if (tmpfile) + err = ovl_link_tmpfile(temp, udir, upper); + else + err = ovl_do_rename(wdir, temp, udir, upper, 0); if (err) goto out_cleanup; - newdentry = dget(temp); + newdentry = dget(tmpfile ? upper : temp); ovl_dentry_update(dentry, newdentry); ovl_inode_update(d_inode(dentry), d_inode(newdentry)); out2: @@ -314,7 +324,8 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, return err; out_cleanup: - ovl_cleanup(wdir, temp); + if (!tmpfile) + ovl_cleanup(wdir, temp); goto out2; } @@ -338,6 +349,9 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, struct dentry *lowerdentry = lowerpath->dentry; struct dentry *upperdir; const char *link = NULL; + struct ovl_fs *ofs = dentry->d_sb->s_fs_info; + /* Should we copyup with O_TMPFILE or with workdir? */ + bool tmpfile = S_ISREG(stat->mode) && ofs->tmpfile; if (WARN_ON(!workdir)) return -EROFS; @@ -369,7 +383,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, } err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath, - stat, link); + stat, link, tmpfile); if (!err) { /* Restore timestamps on parent (best effort) */ ovl_set_timestamps(upperdir, &pstat); diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 190b03f..59d1c38 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -178,6 +178,8 @@ u64 ovl_dentry_version_get(struct dentry *dentry); bool ovl_is_whiteout(struct dentry *dentry); struct file *ovl_path_open(struct path *path, int flags); struct dentry *ovl_alloc_tmpfile(struct dentry *parent, umode_t mode); +int ovl_link_tmpfile(struct dentry *temp, struct inode *dir, + struct dentry *dentry); /* namei.c */ int ovl_path_next(int idx, struct dentry *dentry, struct path *path); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index e6facb1..0fbf41c 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -281,3 +281,23 @@ struct dentry *ovl_alloc_tmpfile(struct dentry *parent, umode_t mode) return temp; } + +int ovl_link_tmpfile(struct dentry *temp, struct inode *dir, + struct dentry *dentry) +{ + struct inode *inode = temp->d_inode; + int err; + + if (WARN_ON_ONCE(!inode || inode->i_nlink)) + return -ENOENT; + + /* Make tempfile linkable */ + spin_lock(&inode->i_lock); + if (!inode->i_nlink) + inode->i_state |= I_LINKABLE; + spin_unlock(&inode->i_lock); + + err = ovl_do_link(temp, dir, dentry, true); + + return err; +}