History

io_uring: account fixed file references correctly in batch

We can't assume that the whole batch has fixed files in it. If it's a mix, or none at all, then we can end up doing a ref put that either messes up accounting, or causes an oops if we have no fixed files at all. Also ensure we free requests properly between inflight accounted and normal requests.

Jens Axboe committed 6 years ago

Commit 10fef4b1 parent 354420f1 file · +9 −5Browse files

Unified · Split

fs/io_uring.c+9−5
@@ -1207,21 +1207,24 @@ struct req_batch { · 1206 unmodified lines
12071207
12081208 static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb)
12091209 {
1210+ int fixed_refs = rb->to_free;
1211+
12101212 if (!rb->to_free)
12111213 return;
12121214 if (rb->need_iter) {
12131215 int i, inflight = 0;
12141216 unsigned long flags;
12151217
1218+ fixed_refs = 0;
12161219 for (i = 0; i < rb->to_free; i++) {
12171220 struct io_kiocb *req = rb->reqs[i];
12181221
1219− if (req->flags & REQ_F_FIXED_FILE)
1222+ if (req->flags & REQ_F_FIXED_FILE) {
12201223 req->file = NULL;
1224+ fixed_refs++;
1225+ }
12211226 if (req->flags & REQ_F_INFLIGHT)
12221227 inflight++;
1223− else
1224− rb->reqs[i] = NULL;
12251228 __io_req_aux_free(req);
12261229 }
12271230 if (!inflight)
@@ -1231,7 +1234,7 @@ static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb) · 3 unmodified lines
12311234 for (i = 0; i < rb->to_free; i++) {
12321235 struct io_kiocb *req = rb->reqs[i];
12331236
1234− if (req) {
1237+ if (req->flags & REQ_F_INFLIGHT) {
12351238 list_del(&req->inflight_entry);
12361239 if (!--inflight)
12371240 break;
@@ -1244,8 +1247,9 @@ static void io_free_req_many(struct io_ring_ctx *ctx, struct req_batch *rb) · 6 unmodified lines
12441247 }
12451248 do_free:
12461249 kmem_cache_free_bulk(req_cachep, rb->to_free, rb->reqs);
1250+ if (fixed_refs)
1251+ percpu_ref_put_many(&ctx->file_data->refs, fixed_refs);
12471252 percpu_ref_put_many(&ctx->refs, rb->to_free);
1248− percpu_ref_put_many(&ctx->file_data->refs, rb->to_free);
12491253 rb->to_free = rb->need_iter = 0;
12501254 }
12511255