summaryrefslogtreecommitdiff
path: root/fs/file.c
diff options
context:
space:
mode:
authorMateusz Guzik <mjguzik@gmail.com>2024-11-16 07:41:28 +0100
committerChristian Brauner <brauner@kernel.org>2024-12-02 11:24:49 +0100
commita48bdf80ce6938f8c1de6a56fed7c4f6f46904e9 (patch)
treef04be21997dc78c5a4d80deb21742d785d594ae5 /fs/file.c
parent40384c840ea1944d7c5a392e8975ed088ecf0b37 (diff)
fs: delay sysctl_nr_open check in expand_files()
Suppose a thread sharing the table started a resize, while sysctl_nr_open got lowered to a value which prohibits it. This is still going to go through with and without the patch, which is fine. Further suppose another thread shows up to do a matching expansion while resize_in_progress == true. It is going to error out since it performs the sysctl_nr_open check *before* finding out if there is an expansion in progress. But the aformentioned thread is going to succeded, so the error is spurious (and it would not happen if the thread showed up a little bit later). Checking the sysctl *after* we know there are no pending updates sorts it out. While here annotate the thing as unlikely. Signed-off-by: Mateusz Guzik <mjguzik@gmail.com> Link: https://lore.kernel.org/r/20241116064128.280870-1-mjguzik@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/file.c b/fs/file.c
index fb1011cf6b4a..019fb9acf91b 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -278,10 +278,6 @@ repeat:
if (nr < fdt->max_fds)
return 0;
- /* Can we expand? */
- if (nr >= sysctl_nr_open)
- return -EMFILE;
-
if (unlikely(files->resize_in_progress)) {
spin_unlock(&files->file_lock);
wait_event(files->resize_wait, !files->resize_in_progress);
@@ -289,6 +285,10 @@ repeat:
goto repeat;
}
+ /* Can we expand? */
+ if (unlikely(nr >= sysctl_nr_open))
+ return -EMFILE;
+
/* All good, so we try */
files->resize_in_progress = true;
error = expand_fdtable(files, nr);