1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Cache data I/O routines 3 * 4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #define FSCACHE_DEBUG_LEVEL PAGE 9 #include <linux/module.h> 10 #define FSCACHE_USE_NEW_IO_API 11 #include <linux/fscache-cache.h> 12 #include <linux/slab.h> 13 #include <linux/netfs.h> 14 #include "internal.h" 15 16 /* 17 * Start a cache read operation. 18 * - we return: 19 * -ENOMEM - out of memory, some pages may be being read 20 * -ERESTARTSYS - interrupted, some pages may be being read 21 * -ENOBUFS - no backing object or space available in which to cache any 22 * pages not being read 23 * -ENODATA - no data available in the backing object for some or all of 24 * the pages 25 * 0 - dispatched a read on all pages 26 */ 27 int __fscache_begin_read_operation(struct netfs_read_request *rreq, 28 struct fscache_cookie *cookie) 29 { 30 struct fscache_retrieval *op; 31 struct fscache_object *object; 32 bool wake_cookie = false; 33 int ret; 34 35 _enter("rr=%08x", rreq->debug_id); 36 37 fscache_stat(&fscache_n_retrievals); 38 39 if (hlist_empty(&cookie->backing_objects)) 40 goto nobufs; 41 42 if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) { 43 _leave(" = -ENOBUFS [invalidating]"); 44 return -ENOBUFS; 45 } 46 47 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 48 49 if (fscache_wait_for_deferred_lookup(cookie) < 0) 50 return -ERESTARTSYS; 51 52 op = fscache_alloc_retrieval(cookie, NULL, NULL, NULL); 53 if (!op) 54 return -ENOMEM; 55 trace_fscache_page_op(cookie, NULL, &op->op, fscache_page_op_retr_multi); 56 57 spin_lock(&cookie->lock); 58 59 if (!fscache_cookie_enabled(cookie) || 60 hlist_empty(&cookie->backing_objects)) 61 goto nobufs_unlock; 62 object = hlist_entry(cookie->backing_objects.first, 63 struct fscache_object, cookie_link); 64 65 __fscache_use_cookie(cookie); 66 atomic_inc(&object->n_reads); 67 __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); 68 69 if (fscache_submit_op(object, &op->op) < 0) 70 goto nobufs_unlock_dec; 71 spin_unlock(&cookie->lock); 72 73 fscache_stat(&fscache_n_retrieval_ops); 74 75 /* we wait for the operation to become active, and then process it 76 * *here*, in this thread, and not in the thread pool */ 77 ret = fscache_wait_for_operation_activation( 78 object, &op->op, 79 __fscache_stat(&fscache_n_retrieval_op_waits), 80 __fscache_stat(&fscache_n_retrievals_object_dead)); 81 if (ret < 0) 82 goto error; 83 84 /* ask the cache to honour the operation */ 85 ret = object->cache->ops->begin_read_operation(rreq, op); 86 87 error: 88 if (ret == -ENOMEM) 89 fscache_stat(&fscache_n_retrievals_nomem); 90 else if (ret == -ERESTARTSYS) 91 fscache_stat(&fscache_n_retrievals_intr); 92 else if (ret == -ENODATA) 93 fscache_stat(&fscache_n_retrievals_nodata); 94 else if (ret < 0) 95 fscache_stat(&fscache_n_retrievals_nobufs); 96 else 97 fscache_stat(&fscache_n_retrievals_ok); 98 99 fscache_put_retrieval(op); 100 _leave(" = %d", ret); 101 return ret; 102 103 nobufs_unlock_dec: 104 atomic_dec(&object->n_reads); 105 wake_cookie = __fscache_unuse_cookie(cookie); 106 nobufs_unlock: 107 spin_unlock(&cookie->lock); 108 fscache_put_retrieval(op); 109 if (wake_cookie) 110 __fscache_wake_unused_cookie(cookie); 111 nobufs: 112 fscache_stat(&fscache_n_retrievals_nobufs); 113 _leave(" = -ENOBUFS"); 114 return -ENOBUFS; 115 } 116 EXPORT_SYMBOL(__fscache_begin_read_operation); 117