io_uring: kill extra io_uring_types.h includes
[platform/kernel/linux-starfive.git] / io_uring / filetable.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/file.h>
5 #include <linux/mm.h>
6 #include <linux/slab.h>
7 #include <linux/nospec.h>
8 #include <linux/io_uring.h>
9
10 #include <uapi/linux/io_uring.h>
11
12 #include "io_uring.h"
13 #include "rsrc.h"
14 #include "filetable.h"
15
16 static int io_file_bitmap_get(struct io_ring_ctx *ctx)
17 {
18         struct io_file_table *table = &ctx->file_table;
19         unsigned long nr = ctx->nr_user_files;
20         int ret;
21
22         do {
23                 ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint);
24                 if (ret != nr)
25                         return ret;
26
27                 if (!table->alloc_hint)
28                         break;
29
30                 nr = table->alloc_hint;
31                 table->alloc_hint = 0;
32         } while (1);
33
34         return -ENFILE;
35 }
36
37 bool io_alloc_file_tables(struct io_file_table *table, unsigned nr_files)
38 {
39         table->files = kvcalloc(nr_files, sizeof(table->files[0]),
40                                 GFP_KERNEL_ACCOUNT);
41         if (unlikely(!table->files))
42                 return false;
43
44         table->bitmap = bitmap_zalloc(nr_files, GFP_KERNEL_ACCOUNT);
45         if (unlikely(!table->bitmap)) {
46                 kvfree(table->files);
47                 return false;
48         }
49
50         return true;
51 }
52
53 void io_free_file_tables(struct io_file_table *table)
54 {
55         kvfree(table->files);
56         bitmap_free(table->bitmap);
57         table->files = NULL;
58         table->bitmap = NULL;
59 }
60
61 static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
62                                  unsigned int issue_flags, u32 slot_index)
63         __must_hold(&req->ctx->uring_lock)
64 {
65         struct io_ring_ctx *ctx = req->ctx;
66         bool needs_switch = false;
67         struct io_fixed_file *file_slot;
68         int ret;
69
70         if (io_is_uring_fops(file))
71                 return -EBADF;
72         if (!ctx->file_data)
73                 return -ENXIO;
74         if (slot_index >= ctx->nr_user_files)
75                 return -EINVAL;
76
77         slot_index = array_index_nospec(slot_index, ctx->nr_user_files);
78         file_slot = io_fixed_file_slot(&ctx->file_table, slot_index);
79
80         if (file_slot->file_ptr) {
81                 struct file *old_file;
82
83                 ret = io_rsrc_node_switch_start(ctx);
84                 if (ret)
85                         goto err;
86
87                 old_file = (struct file *)(file_slot->file_ptr & FFS_MASK);
88                 ret = io_queue_rsrc_removal(ctx->file_data, slot_index,
89                                             ctx->rsrc_node, old_file);
90                 if (ret)
91                         goto err;
92                 file_slot->file_ptr = 0;
93                 io_file_bitmap_clear(&ctx->file_table, slot_index);
94                 needs_switch = true;
95         }
96
97         ret = io_scm_file_account(ctx, file);
98         if (!ret) {
99                 *io_get_tag_slot(ctx->file_data, slot_index) = 0;
100                 io_fixed_file_set(file_slot, file);
101                 io_file_bitmap_set(&ctx->file_table, slot_index);
102         }
103 err:
104         if (needs_switch)
105                 io_rsrc_node_switch(ctx, ctx->file_data);
106         if (ret)
107                 fput(file);
108         return ret;
109 }
110
111 /*
112  * Note when io_fixed_fd_install() returns error value, it will ensure
113  * fput() is called correspondingly.
114  */
115 int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags,
116                         struct file *file, unsigned int file_slot)
117 {
118         bool alloc_slot = file_slot == IORING_FILE_INDEX_ALLOC;
119         struct io_ring_ctx *ctx = req->ctx;
120         int ret;
121
122         io_ring_submit_lock(ctx, issue_flags);
123
124         if (alloc_slot) {
125                 ret = io_file_bitmap_get(ctx);
126                 if (unlikely(ret < 0))
127                         goto err;
128                 file_slot = ret;
129         } else {
130                 file_slot--;
131         }
132
133         ret = io_install_fixed_file(req, file, issue_flags, file_slot);
134         if (!ret && alloc_slot)
135                 ret = file_slot;
136 err:
137         io_ring_submit_unlock(ctx, issue_flags);
138         if (unlikely(ret < 0))
139                 fput(file);
140         return ret;
141 }