|
4 | 4 | #include <linux/uio.h> |
5 | 5 | #include "internal.h" |
6 | 6 |
|
| 7 | +static inline void cachefiles_req_put(struct cachefiles_req *req) |
| 8 | +{ |
| 9 | + if (refcount_dec_and_test(&req->ref)) |
| 10 | + kfree(req); |
| 11 | +} |
| 12 | + |
7 | 13 | static int cachefiles_ondemand_fd_release(struct inode *inode, |
8 | 14 | struct file *file) |
9 | 15 | { |
@@ -299,7 +305,6 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, |
299 | 305 | { |
300 | 306 | struct cachefiles_req *req; |
301 | 307 | struct cachefiles_msg *msg; |
302 | | - unsigned long id = 0; |
303 | 308 | size_t n; |
304 | 309 | int ret = 0; |
305 | 310 | XA_STATE(xas, &cache->reqs, cache->req_id_next); |
@@ -330,41 +335,39 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, |
330 | 335 |
|
331 | 336 | xas_clear_mark(&xas, CACHEFILES_REQ_NEW); |
332 | 337 | cache->req_id_next = xas.xa_index + 1; |
| 338 | + refcount_inc(&req->ref); |
333 | 339 | xa_unlock(&cache->reqs); |
334 | 340 |
|
335 | | - id = xas.xa_index; |
336 | | - |
337 | 341 | if (msg->opcode == CACHEFILES_OP_OPEN) { |
338 | 342 | ret = cachefiles_ondemand_get_fd(req); |
339 | 343 | if (ret) { |
340 | 344 | cachefiles_ondemand_set_object_close(req->object); |
341 | | - goto error; |
| 345 | + goto out; |
342 | 346 | } |
343 | 347 | } |
344 | 348 |
|
345 | | - msg->msg_id = id; |
| 349 | + msg->msg_id = xas.xa_index; |
346 | 350 | msg->object_id = req->object->ondemand->ondemand_id; |
347 | 351 |
|
348 | 352 | if (copy_to_user(_buffer, msg, n) != 0) { |
349 | 353 | ret = -EFAULT; |
350 | 354 | if (msg->opcode == CACHEFILES_OP_OPEN) |
351 | 355 | close_fd(((struct cachefiles_open *)msg->data)->fd); |
352 | | - goto error; |
353 | 356 | } |
354 | | - |
355 | | - /* CLOSE request has no reply */ |
356 | | - if (msg->opcode == CACHEFILES_OP_CLOSE) { |
357 | | - xa_erase(&cache->reqs, id); |
358 | | - complete(&req->done); |
| 357 | +out: |
| 358 | + /* Remove error request and CLOSE request has no reply */ |
| 359 | + if (ret || msg->opcode == CACHEFILES_OP_CLOSE) { |
| 360 | + xas_reset(&xas); |
| 361 | + xas_lock(&xas); |
| 362 | + if (xas_load(&xas) == req) { |
| 363 | + req->error = ret; |
| 364 | + complete(&req->done); |
| 365 | + xas_store(&xas, NULL); |
| 366 | + } |
| 367 | + xas_unlock(&xas); |
359 | 368 | } |
360 | | - |
361 | | - return n; |
362 | | - |
363 | | -error: |
364 | | - xa_erase(&cache->reqs, id); |
365 | | - req->error = ret; |
366 | | - complete(&req->done); |
367 | | - return ret; |
| 369 | + cachefiles_req_put(req); |
| 370 | + return ret ? ret : n; |
368 | 371 | } |
369 | 372 |
|
370 | 373 | typedef int (*init_req_fn)(struct cachefiles_req *req, void *private); |
@@ -394,6 +397,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, |
394 | 397 | goto out; |
395 | 398 | } |
396 | 399 |
|
| 400 | + refcount_set(&req->ref, 1); |
397 | 401 | req->object = object; |
398 | 402 | init_completion(&req->done); |
399 | 403 | req->msg.opcode = opcode; |
@@ -455,7 +459,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, |
455 | 459 | wake_up_all(&cache->daemon_pollwq); |
456 | 460 | wait_for_completion(&req->done); |
457 | 461 | ret = req->error; |
458 | | - kfree(req); |
| 462 | + cachefiles_req_put(req); |
459 | 463 | return ret; |
460 | 464 | out: |
461 | 465 | /* Reset the object to close state in error handling path. |
|
0 commit comments