summaryrefslogtreecommitdiff
path: root/fs/file_table.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2018-11-21 10:32:39 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-12-08 08:44:08 +0100
commitd9e7b466d2cfc56406d412d4e9c86c2fde9c0b61 (patch)
tree9b5d781d28f8ec54a8b25d76470b8333e378f006 /fs/file_table.c
parent34837976947de8f8a13ac64ffebc9d7ac635e561 (diff)
fs: add fget_many() and fput_many()
commit 091141a42e15fe47ada737f3996b317072afcefb upstream. 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 <hare@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/file_table.c')
-rw-r--r--fs/file_table.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/file_table.c b/fs/file_table.c
index ad17e05ebf95..747bb386b446 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -261,9 +261,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))) {
@@ -282,6 +282,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