From patchwork Mon Feb 11 19:00:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Axboe X-Patchwork-Id: 10806679 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 372836C2 for ; Mon, 11 Feb 2019 19:01:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 28C86293A8 for ; Mon, 11 Feb 2019 19:01:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1CD012B246; Mon, 11 Feb 2019 19:01:12 +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.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,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 9517C293A8 for ; Mon, 11 Feb 2019 19:01:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733008AbfBKTBL (ORCPT ); Mon, 11 Feb 2019 14:01:11 -0500 Received: from mail-it1-f196.google.com ([209.85.166.196]:53344 "EHLO mail-it1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733275AbfBKTBK (ORCPT ); Mon, 11 Feb 2019 14:01:10 -0500 Received: by mail-it1-f196.google.com with SMTP id g85so881209ita.3 for ; Mon, 11 Feb 2019 11:01:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel-dk.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=98aDYmP2NlaZN4eCHJfDt4iyzmD8E6C6eVhxrKQfagM=; b=0q4oihl88JIVkVj7P5QQTgA6OP50+YL+2zLfKSyeZ1Gq9zdKPLsshQ57dbzoAN6OBW wNSuIHitUvk3kJ024E9GUVkklM8zcWUGBvNNYQP+6d0PAlrDp4FJW7oCYvPz1RmD4rX8 9vQV+WfmA7yEJM7g4Y7W4m7LAb+Qa4qVJQihSjhOs0DKhXJMAzzJWZPZxa2/xAQTj4gC 6sIDhAnGUSCNVDRBqHMBTT9SwGXqtbu8dGYa8KVUAlYBV7Vivd2c5ilCSPSAFBVJjNmB gjp/gUecSx3coA8wINzE4NN33RdMZUo8GgWLV7PEyJxCmmYE6KI9DxDuQwbOcRK1Gt2p DOzg== 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=98aDYmP2NlaZN4eCHJfDt4iyzmD8E6C6eVhxrKQfagM=; b=uEQSscUYGID0BIHTe3tF29l/OPeogwdyryYX0wO7K2jl7apbYwMSAC5UPmNkCbF/Aq LgjB0/omXuwhbi8mr4swmJEGHvXuPkVCP80q2JuN3ok7ltYAC++Hdy6K7AmZn6jVWyIa 2nRWLGt3HzaljaulEGDd0WL5NaOhC5M3hyiJthsv1L/Fx3wdRduvt6yGMrP2QjJOI8w6 HFrrjamji8lunMPHyfX+pTZCFQPPn21pMP56yZiJjXBxRC8rn3lrZFkLvNiM2LmBwgWm rOdqtFgR5rdG5EcXkhGiTgIK3cWa4l1oJOgqNk3DSJm4QURsuu7HNKNp1k55vexizy2R 4z8A== X-Gm-Message-State: AHQUAuaDdqg24rarg0zuoPY6THjlHl6tK1BljeVNwMsit1uMDli8hpaf tTDShQcJOpbAHqG3PRZcPuyje0nvcN3LsA== X-Google-Smtp-Source: AHgI3IaQYakLqu4d7tsSe4uUHefkCjp4UQz3CghdYTsIDZMfwaRJHygmOW+QJvjw/FwjrJTQOX+n3g== X-Received: by 2002:a05:660c:a48:: with SMTP id j8mr563250itl.26.1549911669620; Mon, 11 Feb 2019 11:01:09 -0800 (PST) Received: from x1.localdomain ([216.160.245.98]) by smtp.gmail.com with ESMTPSA id h184sm62446ith.41.2019.02.11.11.01.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Feb 2019 11:01:08 -0800 (PST) From: Jens Axboe To: linux-aio@kvack.org, linux-block@vger.kernel.org, linux-api@vger.kernel.org Cc: hch@lst.de, jmoyer@redhat.com, avi@scylladb.com, jannh@google.com, viro@ZenIV.linux.org.uk, Jens Axboe Subject: [PATCH 08/19] fs: add fget_many() and fput_many() Date: Mon, 11 Feb 2019 12:00:38 -0700 Message-Id: <20190211190049.7888-10-axboe@kernel.dk> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190211190049.7888-1-axboe@kernel.dk> References: <20190211190049.7888-1-axboe@kernel.dk> Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some uses cases repeatedly get and put references to the same file, but the only exposed interface is doing these one at the time. As each of these entail an atomic inc or dec on a shared structure, that cost can add up. Add fget_many(), which works just like fget(), except it takes an argument for how many references to get on the file. Ditto fput_many(), which can drop an arbitrary number of references to a file. Reviewed-by: Hannes Reinecke Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- fs/file.c | 15 ++++++++++----- fs/file_table.c | 9 +++++++-- include/linux/file.h | 2 ++ include/linux/fs.h | 4 +++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/fs/file.c b/fs/file.c index 3209ee271c41..97df385d6ab0 100644 --- a/fs/file.c +++ b/fs/file.c @@ -705,7 +705,7 @@ void do_close_on_exec(struct files_struct *files) spin_unlock(&files->file_lock); } -static struct file *__fget(unsigned int fd, fmode_t mask) +static struct file *__fget(unsigned int fd, fmode_t mask, unsigned int refs) { struct files_struct *files = current->files; struct file *file; @@ -720,7 +720,7 @@ static struct file *__fget(unsigned int fd, fmode_t mask) */ if (file->f_mode & mask) file = NULL; - else if (!get_file_rcu(file)) + else if (!get_file_rcu_many(file, refs)) goto loop; } rcu_read_unlock(); @@ -728,15 +728,20 @@ static struct file *__fget(unsigned int fd, fmode_t mask) return file; } +struct file *fget_many(unsigned int fd, unsigned int refs) +{ + return __fget(fd, FMODE_PATH, refs); +} + struct file *fget(unsigned int fd) { - return __fget(fd, FMODE_PATH); + return __fget(fd, FMODE_PATH, 1); } EXPORT_SYMBOL(fget); struct file *fget_raw(unsigned int fd) { - return __fget(fd, 0); + return __fget(fd, 0, 1); } EXPORT_SYMBOL(fget_raw); @@ -767,7 +772,7 @@ static unsigned long __fget_light(unsigned int fd, fmode_t mask) return 0; return (unsigned long)file; } else { - file = __fget(fd, mask); + file = __fget(fd, mask, 1); if (!file) return 0; return FDPUT_FPUT | (unsigned long)file; diff --git a/fs/file_table.c b/fs/file_table.c index 5679e7fcb6b0..155d7514a094 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -326,9 +326,9 @@ void flush_delayed_fput(void) static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput); -void fput(struct file *file) +void fput_many(struct file *file, unsigned int refs) { - if (atomic_long_dec_and_test(&file->f_count)) { + if (atomic_long_sub_and_test(refs, &file->f_count)) { struct task_struct *task = current; if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { @@ -347,6 +347,11 @@ void fput(struct file *file) } } +void fput(struct file *file) +{ + fput_many(file, 1); +} + /* * synchronous analog of fput(); for kernel threads that might be needed * in some umount() (and thus can't use flush_delayed_fput() without diff --git a/include/linux/file.h b/include/linux/file.h index 6b2fb032416c..3fcddff56bc4 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -13,6 +13,7 @@ struct file; extern void fput(struct file *); +extern void fput_many(struct file *, unsigned int); struct file_operations; struct vfsmount; @@ -44,6 +45,7 @@ static inline void fdput(struct fd fd) } extern struct file *fget(unsigned int fd); +extern struct file *fget_many(unsigned int fd, unsigned int refs); extern struct file *fget_raw(unsigned int fd); extern unsigned long __fdget(unsigned int fd); extern unsigned long __fdget_raw(unsigned int fd); diff --git a/include/linux/fs.h b/include/linux/fs.h index 61aa210f0c2b..80e1b199a4b1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -952,7 +952,9 @@ static inline struct file *get_file(struct file *f) atomic_long_inc(&f->f_count); return f; } -#define get_file_rcu(x) atomic_long_inc_not_zero(&(x)->f_count) +#define get_file_rcu_many(x, cnt) \ + atomic_long_add_unless(&(x)->f_count, (cnt), 0) +#define get_file_rcu(x) get_file_rcu_many((x), 1) #define fput_atomic(x) atomic_long_add_unless(&(x)->f_count, -1, 1) #define file_count(x) atomic_long_read(&(x)->f_count)