11d57628fSDongsheng Yang // SPDX-License-Identifier: GPL-2.0-or-later 21d57628fSDongsheng Yang 31d57628fSDongsheng Yang #include "cache.h" 41d57628fSDongsheng Yang #include "backing_dev.h" 51d57628fSDongsheng Yang #include "cache_dev.h" 61d57628fSDongsheng Yang #include "dm_pcache.h" 71d57628fSDongsheng Yang 81d57628fSDongsheng Yang static int cache_data_head_init(struct pcache_cache *cache) 91d57628fSDongsheng Yang { 101d57628fSDongsheng Yang struct pcache_cache_segment *next_seg; 111d57628fSDongsheng Yang struct pcache_cache_data_head *data_head; 121d57628fSDongsheng Yang 131d57628fSDongsheng Yang data_head = get_data_head(cache); 141d57628fSDongsheng Yang next_seg = get_cache_segment(cache); 151d57628fSDongsheng Yang if (!next_seg) 161d57628fSDongsheng Yang return -EBUSY; 171d57628fSDongsheng Yang 181d57628fSDongsheng Yang cache_seg_get(next_seg); 191d57628fSDongsheng Yang data_head->head_pos.cache_seg = next_seg; 201d57628fSDongsheng Yang data_head->head_pos.seg_off = 0; 211d57628fSDongsheng Yang 221d57628fSDongsheng Yang return 0; 231d57628fSDongsheng Yang } 241d57628fSDongsheng Yang 251d57628fSDongsheng Yang /** 261d57628fSDongsheng Yang * cache_data_alloc - Allocate data for a cache key. 271d57628fSDongsheng Yang * @cache: Pointer to the cache structure. 281d57628fSDongsheng Yang * @key: Pointer to the cache key to allocate data for. 291d57628fSDongsheng Yang * 301d57628fSDongsheng Yang * This function tries to allocate space from the cache segment specified by the 311d57628fSDongsheng Yang * data head. If the remaining space in the segment is insufficient to allocate 321d57628fSDongsheng Yang * the requested length for the cache key, it will allocate whatever is available 331d57628fSDongsheng Yang * and adjust the key's length accordingly. This function does not allocate 341d57628fSDongsheng Yang * space that crosses segment boundaries. 351d57628fSDongsheng Yang */ 361d57628fSDongsheng Yang static int cache_data_alloc(struct pcache_cache *cache, struct pcache_cache_key *key) 371d57628fSDongsheng Yang { 381d57628fSDongsheng Yang struct pcache_cache_data_head *data_head; 391d57628fSDongsheng Yang struct pcache_cache_pos *head_pos; 401d57628fSDongsheng Yang struct pcache_cache_segment *cache_seg; 411d57628fSDongsheng Yang u32 seg_remain; 421d57628fSDongsheng Yang u32 allocated = 0, to_alloc; 431d57628fSDongsheng Yang int ret = 0; 441d57628fSDongsheng Yang 451d57628fSDongsheng Yang preempt_disable(); 461d57628fSDongsheng Yang data_head = get_data_head(cache); 471d57628fSDongsheng Yang again: 481d57628fSDongsheng Yang to_alloc = key->len - allocated; 491d57628fSDongsheng Yang if (!data_head->head_pos.cache_seg) { 501d57628fSDongsheng Yang seg_remain = 0; 511d57628fSDongsheng Yang } else { 521d57628fSDongsheng Yang cache_pos_copy(&key->cache_pos, &data_head->head_pos); 531d57628fSDongsheng Yang key->seg_gen = key->cache_pos.cache_seg->gen; 541d57628fSDongsheng Yang 551d57628fSDongsheng Yang head_pos = &data_head->head_pos; 561d57628fSDongsheng Yang cache_seg = head_pos->cache_seg; 571d57628fSDongsheng Yang seg_remain = cache_seg_remain(head_pos); 581d57628fSDongsheng Yang } 591d57628fSDongsheng Yang 601d57628fSDongsheng Yang if (seg_remain > to_alloc) { 611d57628fSDongsheng Yang /* If remaining space in segment is sufficient for the cache key, allocate it. */ 621d57628fSDongsheng Yang cache_pos_advance(head_pos, to_alloc); 631d57628fSDongsheng Yang allocated += to_alloc; 641d57628fSDongsheng Yang cache_seg_get(cache_seg); 651d57628fSDongsheng Yang } else if (seg_remain) { 661d57628fSDongsheng Yang /* If remaining space is not enough, allocate the remaining space and adjust the cache key length. */ 671d57628fSDongsheng Yang cache_pos_advance(head_pos, seg_remain); 681d57628fSDongsheng Yang key->len = seg_remain; 691d57628fSDongsheng Yang 701d57628fSDongsheng Yang /* Get for key: obtain a reference to the cache segment for the key. */ 711d57628fSDongsheng Yang cache_seg_get(cache_seg); 721d57628fSDongsheng Yang /* Put for head_pos->cache_seg: release the reference for the current head's segment. */ 731d57628fSDongsheng Yang cache_seg_put(head_pos->cache_seg); 741d57628fSDongsheng Yang head_pos->cache_seg = NULL; 751d57628fSDongsheng Yang } else { 761d57628fSDongsheng Yang /* Initialize a new data head if no segment is available. */ 771d57628fSDongsheng Yang ret = cache_data_head_init(cache); 781d57628fSDongsheng Yang if (ret) 791d57628fSDongsheng Yang goto out; 801d57628fSDongsheng Yang 811d57628fSDongsheng Yang goto again; 821d57628fSDongsheng Yang } 831d57628fSDongsheng Yang 841d57628fSDongsheng Yang out: 851d57628fSDongsheng Yang preempt_enable(); 861d57628fSDongsheng Yang 871d57628fSDongsheng Yang return ret; 881d57628fSDongsheng Yang } 891d57628fSDongsheng Yang 901d57628fSDongsheng Yang static int cache_copy_from_req_bio(struct pcache_cache *cache, struct pcache_cache_key *key, 911d57628fSDongsheng Yang struct pcache_request *pcache_req, u32 bio_off) 921d57628fSDongsheng Yang { 931d57628fSDongsheng Yang struct pcache_cache_pos *pos = &key->cache_pos; 941d57628fSDongsheng Yang struct pcache_segment *segment; 951d57628fSDongsheng Yang 961d57628fSDongsheng Yang segment = &pos->cache_seg->segment; 971d57628fSDongsheng Yang 981d57628fSDongsheng Yang return segment_copy_from_bio(segment, pos->seg_off, key->len, pcache_req->bio, bio_off); 991d57628fSDongsheng Yang } 1001d57628fSDongsheng Yang 1011d57628fSDongsheng Yang static int cache_copy_to_req_bio(struct pcache_cache *cache, struct pcache_request *pcache_req, 1021d57628fSDongsheng Yang u32 bio_off, u32 len, struct pcache_cache_pos *pos, u64 key_gen) 1031d57628fSDongsheng Yang { 1041d57628fSDongsheng Yang struct pcache_cache_segment *cache_seg = pos->cache_seg; 1051d57628fSDongsheng Yang struct pcache_segment *segment = &cache_seg->segment; 1061d57628fSDongsheng Yang int ret; 1071d57628fSDongsheng Yang 1081d57628fSDongsheng Yang spin_lock(&cache_seg->gen_lock); 1091d57628fSDongsheng Yang if (key_gen < cache_seg->gen) { 1101d57628fSDongsheng Yang spin_unlock(&cache_seg->gen_lock); 1111d57628fSDongsheng Yang return -EINVAL; 1121d57628fSDongsheng Yang } 1131d57628fSDongsheng Yang 1141d57628fSDongsheng Yang ret = segment_copy_to_bio(segment, pos->seg_off, len, pcache_req->bio, bio_off); 1151d57628fSDongsheng Yang spin_unlock(&cache_seg->gen_lock); 1161d57628fSDongsheng Yang 1171d57628fSDongsheng Yang return ret; 1181d57628fSDongsheng Yang } 1191d57628fSDongsheng Yang 1201d57628fSDongsheng Yang /** 1211d57628fSDongsheng Yang * miss_read_end_req - Handle the end of a miss read request. 1221d57628fSDongsheng Yang * @backing_req: Pointer to the request structure. 1231d57628fSDongsheng Yang * @read_ret: Return value of read. 1241d57628fSDongsheng Yang * 1251d57628fSDongsheng Yang * This function is called when a backing request to read data from 1261d57628fSDongsheng Yang * the backing_dev is completed. If the key associated with the request 1271d57628fSDongsheng Yang * is empty (a placeholder), it allocates cache space for the key, 1281d57628fSDongsheng Yang * copies the data read from the bio into the cache, and updates 1291d57628fSDongsheng Yang * the key's status. If the key has been overwritten by a write 1301d57628fSDongsheng Yang * request during this process, it will be deleted from the cache 1311d57628fSDongsheng Yang * tree and no further action will be taken. 1321d57628fSDongsheng Yang */ 1331d57628fSDongsheng Yang static void miss_read_end_req(struct pcache_backing_dev_req *backing_req, int read_ret) 1341d57628fSDongsheng Yang { 1351d57628fSDongsheng Yang void *priv_data = backing_req->priv_data; 1361d57628fSDongsheng Yang struct pcache_request *pcache_req = backing_req->req.upper_req; 1371d57628fSDongsheng Yang struct pcache_cache *cache = backing_req->backing_dev->cache; 1381d57628fSDongsheng Yang int ret; 1391d57628fSDongsheng Yang 1401d57628fSDongsheng Yang if (priv_data) { 1411d57628fSDongsheng Yang struct pcache_cache_key *key; 1421d57628fSDongsheng Yang struct pcache_cache_subtree *cache_subtree; 1431d57628fSDongsheng Yang 1441d57628fSDongsheng Yang key = (struct pcache_cache_key *)priv_data; 1451d57628fSDongsheng Yang cache_subtree = key->cache_subtree; 1461d57628fSDongsheng Yang 1471d57628fSDongsheng Yang /* if this key was deleted from cache_subtree by a write, key->flags should be cleared, 1481d57628fSDongsheng Yang * so if cache_key_empty() return true, this key is still in cache_subtree 1491d57628fSDongsheng Yang */ 1501d57628fSDongsheng Yang spin_lock(&cache_subtree->tree_lock); 1511d57628fSDongsheng Yang if (cache_key_empty(key)) { 1521d57628fSDongsheng Yang /* Check if the backing request was successful. */ 1531d57628fSDongsheng Yang if (read_ret) { 1541d57628fSDongsheng Yang cache_key_delete(key); 1551d57628fSDongsheng Yang goto unlock; 1561d57628fSDongsheng Yang } 1571d57628fSDongsheng Yang 1581d57628fSDongsheng Yang /* Allocate cache space for the key and copy data from the backing_dev. */ 1591d57628fSDongsheng Yang ret = cache_data_alloc(cache, key); 1601d57628fSDongsheng Yang if (ret) { 1611d57628fSDongsheng Yang cache_key_delete(key); 1621d57628fSDongsheng Yang goto unlock; 1631d57628fSDongsheng Yang } 1641d57628fSDongsheng Yang 1651d57628fSDongsheng Yang ret = cache_copy_from_req_bio(cache, key, pcache_req, backing_req->req.bio_off); 1661d57628fSDongsheng Yang if (ret) { 1671d57628fSDongsheng Yang cache_seg_put(key->cache_pos.cache_seg); 1681d57628fSDongsheng Yang cache_key_delete(key); 1691d57628fSDongsheng Yang goto unlock; 1701d57628fSDongsheng Yang } 1711d57628fSDongsheng Yang key->flags &= ~PCACHE_CACHE_KEY_FLAGS_EMPTY; 1721d57628fSDongsheng Yang key->flags |= PCACHE_CACHE_KEY_FLAGS_CLEAN; 1731d57628fSDongsheng Yang 1741d57628fSDongsheng Yang /* Append the key to the cache. */ 1751d57628fSDongsheng Yang ret = cache_key_append(cache, key, false); 1761d57628fSDongsheng Yang if (ret) { 1771d57628fSDongsheng Yang cache_seg_put(key->cache_pos.cache_seg); 1781d57628fSDongsheng Yang cache_key_delete(key); 1791d57628fSDongsheng Yang goto unlock; 1801d57628fSDongsheng Yang } 1811d57628fSDongsheng Yang } 1821d57628fSDongsheng Yang unlock: 1831d57628fSDongsheng Yang spin_unlock(&cache_subtree->tree_lock); 1841d57628fSDongsheng Yang cache_key_put(key); 1851d57628fSDongsheng Yang } 1861d57628fSDongsheng Yang } 1871d57628fSDongsheng Yang 1881d57628fSDongsheng Yang /** 1891d57628fSDongsheng Yang * submit_cache_miss_req - Submit a backing request when cache data is missing 1901d57628fSDongsheng Yang * @cache: The cache context that manages cache operations 1911d57628fSDongsheng Yang * @backing_req: The cache request containing information about the read request 1921d57628fSDongsheng Yang * 1931d57628fSDongsheng Yang * This function is used to handle cases where a cache read request cannot locate 1941d57628fSDongsheng Yang * the required data in the cache. When such a miss occurs during `cache_subtree_walk`, 1951d57628fSDongsheng Yang * it triggers a backing read request to fetch data from the backing storage. 1961d57628fSDongsheng Yang * 1971d57628fSDongsheng Yang * If `pcache_req->priv_data` is set, it points to a `pcache_cache_key`, representing 1981d57628fSDongsheng Yang * a new cache key to be inserted into the cache. The function calls `cache_key_insert` 1991d57628fSDongsheng Yang * to attempt adding the key. On insertion failure, it releases the key reference and 2001d57628fSDongsheng Yang * clears `priv_data` to avoid further processing. 2011d57628fSDongsheng Yang */ 2021d57628fSDongsheng Yang static void submit_cache_miss_req(struct pcache_cache *cache, struct pcache_backing_dev_req *backing_req) 2031d57628fSDongsheng Yang { 2041d57628fSDongsheng Yang if (backing_req->priv_data) { 2051d57628fSDongsheng Yang struct pcache_cache_key *key; 2061d57628fSDongsheng Yang 2071d57628fSDongsheng Yang /* Attempt to insert the key into the cache if priv_data is set */ 2081d57628fSDongsheng Yang key = (struct pcache_cache_key *)backing_req->priv_data; 2091d57628fSDongsheng Yang cache_key_insert(&cache->req_key_tree, key, true); 2101d57628fSDongsheng Yang } 2111d57628fSDongsheng Yang backing_dev_req_submit(backing_req, false); 2121d57628fSDongsheng Yang } 2131d57628fSDongsheng Yang 2141d57628fSDongsheng Yang static void cache_miss_req_free(struct pcache_backing_dev_req *backing_req) 2151d57628fSDongsheng Yang { 2161d57628fSDongsheng Yang struct pcache_cache_key *key; 2171d57628fSDongsheng Yang 2181d57628fSDongsheng Yang if (backing_req->priv_data) { 2191d57628fSDongsheng Yang key = backing_req->priv_data; 2201d57628fSDongsheng Yang backing_req->priv_data = NULL; 2211d57628fSDongsheng Yang cache_key_put(key); /* for ->priv_data */ 2221d57628fSDongsheng Yang cache_key_put(key); /* for init ref in alloc */ 2231d57628fSDongsheng Yang } 2241d57628fSDongsheng Yang 2251d57628fSDongsheng Yang backing_dev_req_end(backing_req); 2261d57628fSDongsheng Yang } 2271d57628fSDongsheng Yang 2281d57628fSDongsheng Yang static struct pcache_backing_dev_req *cache_miss_req_alloc(struct pcache_cache *cache, 2291d57628fSDongsheng Yang struct pcache_request *parent, 2301d57628fSDongsheng Yang gfp_t gfp_mask) 2311d57628fSDongsheng Yang { 2321d57628fSDongsheng Yang struct pcache_backing_dev *backing_dev = cache->backing_dev; 2331d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 2341d57628fSDongsheng Yang struct pcache_cache_key *key = NULL; 2351d57628fSDongsheng Yang struct pcache_backing_dev_req_opts req_opts = { 0 }; 2361d57628fSDongsheng Yang 2371d57628fSDongsheng Yang req_opts.type = BACKING_DEV_REQ_TYPE_REQ; 2381d57628fSDongsheng Yang req_opts.gfp_mask = gfp_mask; 2391d57628fSDongsheng Yang req_opts.req.upper_req = parent; 2401d57628fSDongsheng Yang 2411d57628fSDongsheng Yang backing_req = backing_dev_req_alloc(backing_dev, &req_opts); 2421d57628fSDongsheng Yang if (!backing_req) 2431d57628fSDongsheng Yang return NULL; 2441d57628fSDongsheng Yang 2451d57628fSDongsheng Yang key = cache_key_alloc(&cache->req_key_tree, gfp_mask); 2461d57628fSDongsheng Yang if (!key) 2471d57628fSDongsheng Yang goto free_backing_req; 2481d57628fSDongsheng Yang 2491d57628fSDongsheng Yang cache_key_get(key); 2501d57628fSDongsheng Yang backing_req->priv_data = key; 2511d57628fSDongsheng Yang 2521d57628fSDongsheng Yang return backing_req; 2531d57628fSDongsheng Yang 2541d57628fSDongsheng Yang free_backing_req: 2551d57628fSDongsheng Yang cache_miss_req_free(backing_req); 2561d57628fSDongsheng Yang return NULL; 2571d57628fSDongsheng Yang } 2581d57628fSDongsheng Yang 2591d57628fSDongsheng Yang static void cache_miss_req_init(struct pcache_cache *cache, 2601d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req, 2611d57628fSDongsheng Yang struct pcache_request *parent, 2621d57628fSDongsheng Yang u32 off, u32 len, bool insert_key) 2631d57628fSDongsheng Yang { 2641d57628fSDongsheng Yang struct pcache_cache_key *key; 2651d57628fSDongsheng Yang struct pcache_backing_dev_req_opts req_opts = { 0 }; 2661d57628fSDongsheng Yang 2671d57628fSDongsheng Yang req_opts.type = BACKING_DEV_REQ_TYPE_REQ; 2681d57628fSDongsheng Yang req_opts.req.upper_req = parent; 2691d57628fSDongsheng Yang req_opts.req.req_off = off; 2701d57628fSDongsheng Yang req_opts.req.len = len; 2711d57628fSDongsheng Yang req_opts.end_fn = miss_read_end_req; 2721d57628fSDongsheng Yang 2731d57628fSDongsheng Yang backing_dev_req_init(backing_req, &req_opts); 2741d57628fSDongsheng Yang 2751d57628fSDongsheng Yang if (insert_key) { 2761d57628fSDongsheng Yang key = backing_req->priv_data; 2771d57628fSDongsheng Yang key->off = parent->off + off; 2781d57628fSDongsheng Yang key->len = len; 2791d57628fSDongsheng Yang key->flags |= PCACHE_CACHE_KEY_FLAGS_EMPTY; 2801d57628fSDongsheng Yang } else { 2811d57628fSDongsheng Yang key = backing_req->priv_data; 2821d57628fSDongsheng Yang backing_req->priv_data = NULL; 2831d57628fSDongsheng Yang cache_key_put(key); 2841d57628fSDongsheng Yang cache_key_put(key); 2851d57628fSDongsheng Yang } 2861d57628fSDongsheng Yang } 2871d57628fSDongsheng Yang 2881d57628fSDongsheng Yang static struct pcache_backing_dev_req *get_pre_alloc_req(struct pcache_cache_subtree_walk_ctx *ctx) 2891d57628fSDongsheng Yang { 2901d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 2911d57628fSDongsheng Yang struct pcache_request *pcache_req = ctx->pcache_req; 2921d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 2931d57628fSDongsheng Yang 2941d57628fSDongsheng Yang if (ctx->pre_alloc_req) { 2951d57628fSDongsheng Yang backing_req = ctx->pre_alloc_req; 2961d57628fSDongsheng Yang ctx->pre_alloc_req = NULL; 2971d57628fSDongsheng Yang 2981d57628fSDongsheng Yang return backing_req; 2991d57628fSDongsheng Yang } 3001d57628fSDongsheng Yang 3011d57628fSDongsheng Yang return cache_miss_req_alloc(cache, pcache_req, GFP_NOWAIT); 3021d57628fSDongsheng Yang } 3031d57628fSDongsheng Yang 3041d57628fSDongsheng Yang /* 3051d57628fSDongsheng Yang * In the process of walking the cache tree to locate cached data, this 3061d57628fSDongsheng Yang * function handles the situation where the requested data range lies 3071d57628fSDongsheng Yang * entirely before an existing cache node (`key_tmp`). This outcome 3081d57628fSDongsheng Yang * signifies that the target data is absent from the cache (cache miss). 3091d57628fSDongsheng Yang * 3101d57628fSDongsheng Yang * To fulfill this portion of the read request, the function creates a 3111d57628fSDongsheng Yang * backing request (`backing_req`) for the missing data range represented 3121d57628fSDongsheng Yang * by `key`. It then appends this request to the submission list in the 3131d57628fSDongsheng Yang * `ctx`, which will later be processed to retrieve the data from backing 3141d57628fSDongsheng Yang * storage. After setting up the backing request, `req_done` in `ctx` is 3151d57628fSDongsheng Yang * updated to reflect the length of the handled range, and the range 3161d57628fSDongsheng Yang * in `key` is adjusted by trimming off the portion that is now handled. 3171d57628fSDongsheng Yang * 3181d57628fSDongsheng Yang * The scenario handled here: 3191d57628fSDongsheng Yang * 3201d57628fSDongsheng Yang * |--------| key_tmp (existing cached range) 3211d57628fSDongsheng Yang * |====| key (requested range, preceding key_tmp) 3221d57628fSDongsheng Yang * 3231d57628fSDongsheng Yang * Since `key` is before `key_tmp`, it signifies that the requested data 3241d57628fSDongsheng Yang * range is missing in the cache (cache miss) and needs retrieval from 3251d57628fSDongsheng Yang * backing storage. 3261d57628fSDongsheng Yang */ 3271d57628fSDongsheng Yang static int read_before(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, 3281d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx *ctx) 3291d57628fSDongsheng Yang { 3301d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 3311d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 3321d57628fSDongsheng Yang 3331d57628fSDongsheng Yang /* 3341d57628fSDongsheng Yang * In this scenario, `key` represents a range that precedes `key_tmp`, 3351d57628fSDongsheng Yang * meaning the requested data range is missing from the cache tree 3361d57628fSDongsheng Yang * and must be retrieved from the backing_dev. 3371d57628fSDongsheng Yang */ 3381d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 3391d57628fSDongsheng Yang if (!backing_req) 3401d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 3411d57628fSDongsheng Yang 3421d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, key->len, true); 3431d57628fSDongsheng Yang 3441d57628fSDongsheng Yang list_add(&backing_req->node, ctx->submit_req_list); 3451d57628fSDongsheng Yang ctx->req_done += key->len; 3461d57628fSDongsheng Yang cache_key_cutfront(key, key->len); 3471d57628fSDongsheng Yang 3481d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 3491d57628fSDongsheng Yang } 3501d57628fSDongsheng Yang 3511d57628fSDongsheng Yang /* 3521d57628fSDongsheng Yang * During cache_subtree_walk, this function manages a scenario where part of the 3531d57628fSDongsheng Yang * requested data range overlaps with an existing cache node (`key_tmp`). 3541d57628fSDongsheng Yang * 3551d57628fSDongsheng Yang * |----------------| key_tmp (existing cached range) 3561d57628fSDongsheng Yang * |===========| key (requested range, overlapping the tail of key_tmp) 3571d57628fSDongsheng Yang */ 3581d57628fSDongsheng Yang static int read_overlap_tail(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, 3591d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx *ctx) 3601d57628fSDongsheng Yang { 3611d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 3621d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 3631d57628fSDongsheng Yang u32 io_len; 3641d57628fSDongsheng Yang int ret; 3651d57628fSDongsheng Yang 3661d57628fSDongsheng Yang /* 3671d57628fSDongsheng Yang * Calculate the length of the non-overlapping portion of `key` 3681d57628fSDongsheng Yang * before `key_tmp`, representing the data missing in the cache. 3691d57628fSDongsheng Yang */ 3701d57628fSDongsheng Yang io_len = cache_key_lstart(key_tmp) - cache_key_lstart(key); 3711d57628fSDongsheng Yang if (io_len) { 3721d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 3731d57628fSDongsheng Yang if (!backing_req) 3741d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 3751d57628fSDongsheng Yang 3761d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, io_len, true); 3771d57628fSDongsheng Yang 3781d57628fSDongsheng Yang list_add(&backing_req->node, ctx->submit_req_list); 3791d57628fSDongsheng Yang ctx->req_done += io_len; 3801d57628fSDongsheng Yang cache_key_cutfront(key, io_len); 3811d57628fSDongsheng Yang } 3821d57628fSDongsheng Yang 3831d57628fSDongsheng Yang /* 3841d57628fSDongsheng Yang * Handle the overlapping portion by calculating the length of 3851d57628fSDongsheng Yang * the remaining data in `key` that coincides with `key_tmp`. 3861d57628fSDongsheng Yang */ 3871d57628fSDongsheng Yang io_len = cache_key_lend(key) - cache_key_lstart(key_tmp); 3881d57628fSDongsheng Yang if (cache_key_empty(key_tmp)) { 3891d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 3901d57628fSDongsheng Yang if (!backing_req) 3911d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 3921d57628fSDongsheng Yang 3931d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, io_len, false); 3941d57628fSDongsheng Yang submit_cache_miss_req(cache, backing_req); 3951d57628fSDongsheng Yang } else { 3961d57628fSDongsheng Yang ret = cache_copy_to_req_bio(ctx->cache_tree->cache, ctx->pcache_req, ctx->req_done, 3971d57628fSDongsheng Yang io_len, &key_tmp->cache_pos, key_tmp->seg_gen); 3981d57628fSDongsheng Yang if (ret) { 3991d57628fSDongsheng Yang if (ret == -EINVAL) { 4001d57628fSDongsheng Yang cache_key_delete(key_tmp); 4011d57628fSDongsheng Yang return SUBTREE_WALK_RET_RESEARCH; 4021d57628fSDongsheng Yang } 4031d57628fSDongsheng Yang 4041d57628fSDongsheng Yang ctx->ret = ret; 4051d57628fSDongsheng Yang return SUBTREE_WALK_RET_ERR; 4061d57628fSDongsheng Yang } 4071d57628fSDongsheng Yang } 4081d57628fSDongsheng Yang 4091d57628fSDongsheng Yang ctx->req_done += io_len; 4101d57628fSDongsheng Yang cache_key_cutfront(key, io_len); 4111d57628fSDongsheng Yang 4121d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 4131d57628fSDongsheng Yang } 4141d57628fSDongsheng Yang 4151d57628fSDongsheng Yang /* 4161d57628fSDongsheng Yang * |----| key_tmp (existing cached range) 4171d57628fSDongsheng Yang * |==========| key (requested range) 4181d57628fSDongsheng Yang */ 4191d57628fSDongsheng Yang static int read_overlap_contain(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, 4201d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx *ctx) 4211d57628fSDongsheng Yang { 4221d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 4231d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 4241d57628fSDongsheng Yang u32 io_len; 4251d57628fSDongsheng Yang int ret; 4261d57628fSDongsheng Yang 4271d57628fSDongsheng Yang /* 4281d57628fSDongsheng Yang * Calculate the non-overlapping part of `key` before `key_tmp` 4291d57628fSDongsheng Yang * to identify the missing data length. 4301d57628fSDongsheng Yang */ 4311d57628fSDongsheng Yang io_len = cache_key_lstart(key_tmp) - cache_key_lstart(key); 4321d57628fSDongsheng Yang if (io_len) { 4331d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 4341d57628fSDongsheng Yang if (!backing_req) 4351d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 4361d57628fSDongsheng Yang 4371d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, io_len, true); 4381d57628fSDongsheng Yang 4391d57628fSDongsheng Yang list_add(&backing_req->node, ctx->submit_req_list); 4401d57628fSDongsheng Yang 4411d57628fSDongsheng Yang ctx->req_done += io_len; 4421d57628fSDongsheng Yang cache_key_cutfront(key, io_len); 4431d57628fSDongsheng Yang } 4441d57628fSDongsheng Yang 4451d57628fSDongsheng Yang /* 4461d57628fSDongsheng Yang * Handle the overlapping portion between `key` and `key_tmp`. 4471d57628fSDongsheng Yang */ 4481d57628fSDongsheng Yang io_len = key_tmp->len; 4491d57628fSDongsheng Yang if (cache_key_empty(key_tmp)) { 4501d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 4511d57628fSDongsheng Yang if (!backing_req) 4521d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 4531d57628fSDongsheng Yang 4541d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, io_len, false); 4551d57628fSDongsheng Yang submit_cache_miss_req(cache, backing_req); 4561d57628fSDongsheng Yang } else { 4571d57628fSDongsheng Yang ret = cache_copy_to_req_bio(ctx->cache_tree->cache, ctx->pcache_req, ctx->req_done, 4581d57628fSDongsheng Yang io_len, &key_tmp->cache_pos, key_tmp->seg_gen); 4591d57628fSDongsheng Yang if (ret) { 4601d57628fSDongsheng Yang if (ret == -EINVAL) { 4611d57628fSDongsheng Yang cache_key_delete(key_tmp); 4621d57628fSDongsheng Yang return SUBTREE_WALK_RET_RESEARCH; 4631d57628fSDongsheng Yang } 4641d57628fSDongsheng Yang 4651d57628fSDongsheng Yang ctx->ret = ret; 4661d57628fSDongsheng Yang return SUBTREE_WALK_RET_ERR; 4671d57628fSDongsheng Yang } 4681d57628fSDongsheng Yang } 4691d57628fSDongsheng Yang 4701d57628fSDongsheng Yang ctx->req_done += io_len; 4711d57628fSDongsheng Yang cache_key_cutfront(key, io_len); 4721d57628fSDongsheng Yang 4731d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 4741d57628fSDongsheng Yang } 4751d57628fSDongsheng Yang 4761d57628fSDongsheng Yang /* 4771d57628fSDongsheng Yang * |-----------| key_tmp (existing cached range) 4781d57628fSDongsheng Yang * |====| key (requested range, fully within key_tmp) 4791d57628fSDongsheng Yang * 4801d57628fSDongsheng Yang * If `key_tmp` contains valid cached data, this function copies the relevant 4811d57628fSDongsheng Yang * portion to the request's bio. Otherwise, it sends a backing request to 4821d57628fSDongsheng Yang * fetch the required data range. 4831d57628fSDongsheng Yang */ 4841d57628fSDongsheng Yang static int read_overlap_contained(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, 4851d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx *ctx) 4861d57628fSDongsheng Yang { 4871d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 4881d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 4891d57628fSDongsheng Yang struct pcache_cache_pos pos; 4901d57628fSDongsheng Yang int ret; 4911d57628fSDongsheng Yang 4921d57628fSDongsheng Yang /* 4931d57628fSDongsheng Yang * Check if `key_tmp` is empty, indicating a miss. If so, initiate 4941d57628fSDongsheng Yang * a backing request to fetch the required data for `key`. 4951d57628fSDongsheng Yang */ 4961d57628fSDongsheng Yang if (cache_key_empty(key_tmp)) { 4971d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 4981d57628fSDongsheng Yang if (!backing_req) 4991d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 5001d57628fSDongsheng Yang 5011d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, key->len, false); 5021d57628fSDongsheng Yang submit_cache_miss_req(cache, backing_req); 5031d57628fSDongsheng Yang } else { 5041d57628fSDongsheng Yang cache_pos_copy(&pos, &key_tmp->cache_pos); 5051d57628fSDongsheng Yang cache_pos_advance(&pos, cache_key_lstart(key) - cache_key_lstart(key_tmp)); 5061d57628fSDongsheng Yang 5071d57628fSDongsheng Yang ret = cache_copy_to_req_bio(ctx->cache_tree->cache, ctx->pcache_req, ctx->req_done, 5081d57628fSDongsheng Yang key->len, &pos, key_tmp->seg_gen); 5091d57628fSDongsheng Yang if (ret) { 5101d57628fSDongsheng Yang if (ret == -EINVAL) { 5111d57628fSDongsheng Yang cache_key_delete(key_tmp); 5121d57628fSDongsheng Yang return SUBTREE_WALK_RET_RESEARCH; 5131d57628fSDongsheng Yang } 5141d57628fSDongsheng Yang 5151d57628fSDongsheng Yang ctx->ret = ret; 5161d57628fSDongsheng Yang return SUBTREE_WALK_RET_ERR; 5171d57628fSDongsheng Yang } 5181d57628fSDongsheng Yang } 5191d57628fSDongsheng Yang 5201d57628fSDongsheng Yang ctx->req_done += key->len; 5211d57628fSDongsheng Yang cache_key_cutfront(key, key->len); 5221d57628fSDongsheng Yang 5231d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 5241d57628fSDongsheng Yang } 5251d57628fSDongsheng Yang 5261d57628fSDongsheng Yang /* 5271d57628fSDongsheng Yang * |--------| key_tmp (existing cached range) 5281d57628fSDongsheng Yang * |==========| key (requested range, overlapping the head of key_tmp) 5291d57628fSDongsheng Yang */ 5301d57628fSDongsheng Yang static int read_overlap_head(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, 5311d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx *ctx) 5321d57628fSDongsheng Yang { 5331d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 5341d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req; 5351d57628fSDongsheng Yang struct pcache_cache_pos pos; 5361d57628fSDongsheng Yang u32 io_len; 5371d57628fSDongsheng Yang int ret; 5381d57628fSDongsheng Yang 5391d57628fSDongsheng Yang io_len = cache_key_lend(key_tmp) - cache_key_lstart(key); 5401d57628fSDongsheng Yang 5411d57628fSDongsheng Yang if (cache_key_empty(key_tmp)) { 5421d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 5431d57628fSDongsheng Yang if (!backing_req) 5441d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 5451d57628fSDongsheng Yang 5461d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, io_len, false); 5471d57628fSDongsheng Yang submit_cache_miss_req(cache, backing_req); 5481d57628fSDongsheng Yang } else { 5491d57628fSDongsheng Yang cache_pos_copy(&pos, &key_tmp->cache_pos); 5501d57628fSDongsheng Yang cache_pos_advance(&pos, cache_key_lstart(key) - cache_key_lstart(key_tmp)); 5511d57628fSDongsheng Yang 5521d57628fSDongsheng Yang ret = cache_copy_to_req_bio(ctx->cache_tree->cache, ctx->pcache_req, ctx->req_done, 5531d57628fSDongsheng Yang io_len, &pos, key_tmp->seg_gen); 5541d57628fSDongsheng Yang if (ret) { 5551d57628fSDongsheng Yang if (ret == -EINVAL) { 5561d57628fSDongsheng Yang cache_key_delete(key_tmp); 5571d57628fSDongsheng Yang return SUBTREE_WALK_RET_RESEARCH; 5581d57628fSDongsheng Yang } 5591d57628fSDongsheng Yang 5601d57628fSDongsheng Yang ctx->ret = ret; 5611d57628fSDongsheng Yang return SUBTREE_WALK_RET_ERR; 5621d57628fSDongsheng Yang } 5631d57628fSDongsheng Yang } 5641d57628fSDongsheng Yang 5651d57628fSDongsheng Yang ctx->req_done += io_len; 5661d57628fSDongsheng Yang cache_key_cutfront(key, io_len); 5671d57628fSDongsheng Yang 5681d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 5691d57628fSDongsheng Yang } 5701d57628fSDongsheng Yang 5711d57628fSDongsheng Yang /** 5721d57628fSDongsheng Yang * read_walk_finally - Finalizes the cache read tree walk by submitting any 5731d57628fSDongsheng Yang * remaining backing requests 5741d57628fSDongsheng Yang * @ctx: Context structure holding information about the cache, 5751d57628fSDongsheng Yang * read request, and submission list 5761d57628fSDongsheng Yang * @ret: the return value after this walk. 5771d57628fSDongsheng Yang * 5781d57628fSDongsheng Yang * This function is called at the end of the `cache_subtree_walk` during a 5791d57628fSDongsheng Yang * cache read operation. It completes the walk by checking if any data 5801d57628fSDongsheng Yang * requested by `key` was not found in the cache tree, and if so, it sends 5811d57628fSDongsheng Yang * a backing request to retrieve that data. Then, it iterates through the 5821d57628fSDongsheng Yang * submission list of backing requests created during the walk, removing 5831d57628fSDongsheng Yang * each request from the list and submitting it. 5841d57628fSDongsheng Yang * 5851d57628fSDongsheng Yang * The scenario managed here includes: 5861d57628fSDongsheng Yang * - Sending a backing request for the remaining length of `key` if it was 5871d57628fSDongsheng Yang * not fulfilled by existing cache entries. 5881d57628fSDongsheng Yang * - Iterating through `ctx->submit_req_list` to submit each backing request 5891d57628fSDongsheng Yang * enqueued during the walk. 5901d57628fSDongsheng Yang * 5911d57628fSDongsheng Yang * This ensures all necessary backing requests for cache misses are submitted 5921d57628fSDongsheng Yang * to the backing storage to retrieve any data that could not be found in 5931d57628fSDongsheng Yang * the cache. 5941d57628fSDongsheng Yang */ 5951d57628fSDongsheng Yang static int read_walk_finally(struct pcache_cache_subtree_walk_ctx *ctx, int ret) 5961d57628fSDongsheng Yang { 5971d57628fSDongsheng Yang struct pcache_cache *cache = ctx->cache_tree->cache; 5981d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req, *next_req; 5991d57628fSDongsheng Yang struct pcache_cache_key *key = ctx->key; 6001d57628fSDongsheng Yang 6011d57628fSDongsheng Yang list_for_each_entry_safe(backing_req, next_req, ctx->submit_req_list, node) { 6021d57628fSDongsheng Yang list_del_init(&backing_req->node); 6031d57628fSDongsheng Yang submit_cache_miss_req(ctx->cache_tree->cache, backing_req); 6041d57628fSDongsheng Yang } 6051d57628fSDongsheng Yang 6061d57628fSDongsheng Yang if (ret != SUBTREE_WALK_RET_OK) 6071d57628fSDongsheng Yang return ret; 6081d57628fSDongsheng Yang 6091d57628fSDongsheng Yang if (key->len) { 6101d57628fSDongsheng Yang backing_req = get_pre_alloc_req(ctx); 6111d57628fSDongsheng Yang if (!backing_req) 6121d57628fSDongsheng Yang return SUBTREE_WALK_RET_NEED_REQ; 6131d57628fSDongsheng Yang 6141d57628fSDongsheng Yang cache_miss_req_init(cache, backing_req, ctx->pcache_req, ctx->req_done, key->len, true); 6151d57628fSDongsheng Yang submit_cache_miss_req(cache, backing_req); 6161d57628fSDongsheng Yang ctx->req_done += key->len; 6171d57628fSDongsheng Yang } 6181d57628fSDongsheng Yang 6191d57628fSDongsheng Yang return SUBTREE_WALK_RET_OK; 6201d57628fSDongsheng Yang } 6211d57628fSDongsheng Yang 6221d57628fSDongsheng Yang /* 6231d57628fSDongsheng Yang * This function is used within `cache_subtree_walk` to determine whether the 6241d57628fSDongsheng Yang * read operation has covered the requested data length. It compares the 6251d57628fSDongsheng Yang * amount of data processed (`ctx->req_done`) with the total data length 6261d57628fSDongsheng Yang * specified in the original request (`ctx->pcache_req->data_len`). 6271d57628fSDongsheng Yang * 6281d57628fSDongsheng Yang * If `req_done` meets or exceeds the required data length, the function 6291d57628fSDongsheng Yang * returns `true`, indicating the walk is complete. Otherwise, it returns `false`, 6301d57628fSDongsheng Yang * signaling that additional data processing is needed to fulfill the request. 6311d57628fSDongsheng Yang */ 6321d57628fSDongsheng Yang static bool read_walk_done(struct pcache_cache_subtree_walk_ctx *ctx) 6331d57628fSDongsheng Yang { 6341d57628fSDongsheng Yang return (ctx->req_done >= ctx->pcache_req->data_len); 6351d57628fSDongsheng Yang } 6361d57628fSDongsheng Yang 6371d57628fSDongsheng Yang /** 6381d57628fSDongsheng Yang * cache_read - Process a read request by traversing the cache tree 6391d57628fSDongsheng Yang * @cache: Cache structure holding cache trees and related configurations 6401d57628fSDongsheng Yang * @pcache_req: Request structure with information about the data to read 6411d57628fSDongsheng Yang * 6421d57628fSDongsheng Yang * This function attempts to fulfill a read request by traversing the cache tree(s) 6431d57628fSDongsheng Yang * to locate cached data for the requested range. If parts of the data are missing 6441d57628fSDongsheng Yang * in the cache, backing requests are generated to retrieve the required segments. 6451d57628fSDongsheng Yang * 6461d57628fSDongsheng Yang * The function operates by initializing a key for the requested data range and 6471d57628fSDongsheng Yang * preparing a context (`walk_ctx`) to manage the cache tree traversal. The context 6481d57628fSDongsheng Yang * includes pointers to functions (e.g., `read_before`, `read_overlap_tail`) that handle 6491d57628fSDongsheng Yang * specific conditions encountered during the traversal. The `walk_finally` and `walk_done` 6501d57628fSDongsheng Yang * functions manage the end stages of the traversal, while the `delete_key_list` and 6511d57628fSDongsheng Yang * `submit_req_list` lists track any keys to be deleted or requests to be submitted. 6521d57628fSDongsheng Yang * 6531d57628fSDongsheng Yang * The function first calculates the requested range and checks if it fits within the 6541d57628fSDongsheng Yang * current cache tree (based on the tree's size limits). It then locks the cache tree 6551d57628fSDongsheng Yang * and performs a search to locate any matching keys. If there are outdated keys, 6561d57628fSDongsheng Yang * these are deleted, and the search is restarted to ensure accurate data retrieval. 6571d57628fSDongsheng Yang * 6581d57628fSDongsheng Yang * If the requested range spans multiple cache trees, the function moves on to the 6591d57628fSDongsheng Yang * next tree once the current range has been processed. This continues until the 6601d57628fSDongsheng Yang * entire requested data length has been handled. 6611d57628fSDongsheng Yang */ 6621d57628fSDongsheng Yang static int cache_read(struct pcache_cache *cache, struct pcache_request *pcache_req) 6631d57628fSDongsheng Yang { 6641d57628fSDongsheng Yang struct pcache_cache_key key_data = { .off = pcache_req->off, .len = pcache_req->data_len }; 6651d57628fSDongsheng Yang struct pcache_cache_subtree *cache_subtree; 6661d57628fSDongsheng Yang struct pcache_cache_key *key_tmp = NULL, *key_next; 6671d57628fSDongsheng Yang struct rb_node *prev_node = NULL; 6681d57628fSDongsheng Yang struct pcache_cache_key *key = &key_data; 6691d57628fSDongsheng Yang struct pcache_cache_subtree_walk_ctx walk_ctx = { 0 }; 6701d57628fSDongsheng Yang struct pcache_backing_dev_req *backing_req, *next_req; 6711d57628fSDongsheng Yang LIST_HEAD(delete_key_list); 6721d57628fSDongsheng Yang LIST_HEAD(submit_req_list); 6731d57628fSDongsheng Yang int ret; 6741d57628fSDongsheng Yang 6751d57628fSDongsheng Yang walk_ctx.cache_tree = &cache->req_key_tree; 6761d57628fSDongsheng Yang walk_ctx.req_done = 0; 6771d57628fSDongsheng Yang walk_ctx.pcache_req = pcache_req; 6781d57628fSDongsheng Yang walk_ctx.before = read_before; 6791d57628fSDongsheng Yang walk_ctx.overlap_tail = read_overlap_tail; 6801d57628fSDongsheng Yang walk_ctx.overlap_head = read_overlap_head; 6811d57628fSDongsheng Yang walk_ctx.overlap_contain = read_overlap_contain; 6821d57628fSDongsheng Yang walk_ctx.overlap_contained = read_overlap_contained; 6831d57628fSDongsheng Yang walk_ctx.walk_finally = read_walk_finally; 6841d57628fSDongsheng Yang walk_ctx.walk_done = read_walk_done; 6851d57628fSDongsheng Yang walk_ctx.delete_key_list = &delete_key_list; 6861d57628fSDongsheng Yang walk_ctx.submit_req_list = &submit_req_list; 6871d57628fSDongsheng Yang 6881d57628fSDongsheng Yang next: 6891d57628fSDongsheng Yang key->off = pcache_req->off + walk_ctx.req_done; 6901d57628fSDongsheng Yang key->len = pcache_req->data_len - walk_ctx.req_done; 6911d57628fSDongsheng Yang if (key->len > PCACHE_CACHE_SUBTREE_SIZE - (key->off & PCACHE_CACHE_SUBTREE_SIZE_MASK)) 6921d57628fSDongsheng Yang key->len = PCACHE_CACHE_SUBTREE_SIZE - (key->off & PCACHE_CACHE_SUBTREE_SIZE_MASK); 6931d57628fSDongsheng Yang 6941d57628fSDongsheng Yang cache_subtree = get_subtree(&cache->req_key_tree, key->off); 6951d57628fSDongsheng Yang spin_lock(&cache_subtree->tree_lock); 6961d57628fSDongsheng Yang search: 6971d57628fSDongsheng Yang prev_node = cache_subtree_search(cache_subtree, key, NULL, NULL, &delete_key_list); 6981d57628fSDongsheng Yang if (!list_empty(&delete_key_list)) { 6991d57628fSDongsheng Yang list_for_each_entry_safe(key_tmp, key_next, &delete_key_list, list_node) { 7001d57628fSDongsheng Yang list_del_init(&key_tmp->list_node); 7011d57628fSDongsheng Yang cache_key_delete(key_tmp); 7021d57628fSDongsheng Yang } 7031d57628fSDongsheng Yang goto search; 7041d57628fSDongsheng Yang } 7051d57628fSDongsheng Yang 7061d57628fSDongsheng Yang walk_ctx.start_node = prev_node; 7071d57628fSDongsheng Yang walk_ctx.key = key; 7081d57628fSDongsheng Yang 7091d57628fSDongsheng Yang ret = cache_subtree_walk(&walk_ctx); 7101d57628fSDongsheng Yang if (ret == SUBTREE_WALK_RET_RESEARCH) 7111d57628fSDongsheng Yang goto search; 7121d57628fSDongsheng Yang spin_unlock(&cache_subtree->tree_lock); 7131d57628fSDongsheng Yang 7141d57628fSDongsheng Yang if (ret == SUBTREE_WALK_RET_ERR) { 7151d57628fSDongsheng Yang ret = walk_ctx.ret; 7161d57628fSDongsheng Yang goto out; 7171d57628fSDongsheng Yang } 7181d57628fSDongsheng Yang 7191d57628fSDongsheng Yang if (ret == SUBTREE_WALK_RET_NEED_REQ) { 7201d57628fSDongsheng Yang walk_ctx.pre_alloc_req = cache_miss_req_alloc(cache, pcache_req, GFP_NOIO); 7211d57628fSDongsheng Yang pcache_dev_debug(CACHE_TO_PCACHE(cache), "allocate pre_alloc_req with GFP_NOIO"); 7221d57628fSDongsheng Yang } 7231d57628fSDongsheng Yang 7241d57628fSDongsheng Yang if (walk_ctx.req_done < pcache_req->data_len) 7251d57628fSDongsheng Yang goto next; 7261d57628fSDongsheng Yang ret = 0; 7271d57628fSDongsheng Yang out: 7281d57628fSDongsheng Yang if (walk_ctx.pre_alloc_req) 7291d57628fSDongsheng Yang cache_miss_req_free(walk_ctx.pre_alloc_req); 7301d57628fSDongsheng Yang 7311d57628fSDongsheng Yang list_for_each_entry_safe(backing_req, next_req, &submit_req_list, node) { 7321d57628fSDongsheng Yang list_del_init(&backing_req->node); 7331d57628fSDongsheng Yang backing_dev_req_end(backing_req); 7341d57628fSDongsheng Yang } 7351d57628fSDongsheng Yang 7361d57628fSDongsheng Yang return ret; 7371d57628fSDongsheng Yang } 7381d57628fSDongsheng Yang 7391d57628fSDongsheng Yang static int cache_write(struct pcache_cache *cache, struct pcache_request *pcache_req) 7401d57628fSDongsheng Yang { 7411d57628fSDongsheng Yang struct pcache_cache_subtree *cache_subtree; 7421d57628fSDongsheng Yang struct pcache_cache_key *key; 7431d57628fSDongsheng Yang u64 offset = pcache_req->off; 7441d57628fSDongsheng Yang u32 length = pcache_req->data_len; 7451d57628fSDongsheng Yang u32 io_done = 0; 7461d57628fSDongsheng Yang int ret; 7471d57628fSDongsheng Yang 7481d57628fSDongsheng Yang while (true) { 7491d57628fSDongsheng Yang if (io_done >= length) 7501d57628fSDongsheng Yang break; 7511d57628fSDongsheng Yang 7521d57628fSDongsheng Yang key = cache_key_alloc(&cache->req_key_tree, GFP_NOIO); 7531d57628fSDongsheng Yang key->off = offset + io_done; 7541d57628fSDongsheng Yang key->len = length - io_done; 7551d57628fSDongsheng Yang if (key->len > PCACHE_CACHE_SUBTREE_SIZE - (key->off & PCACHE_CACHE_SUBTREE_SIZE_MASK)) 7561d57628fSDongsheng Yang key->len = PCACHE_CACHE_SUBTREE_SIZE - (key->off & PCACHE_CACHE_SUBTREE_SIZE_MASK); 7571d57628fSDongsheng Yang 7581d57628fSDongsheng Yang ret = cache_data_alloc(cache, key); 7591d57628fSDongsheng Yang if (ret) { 7601d57628fSDongsheng Yang cache_key_put(key); 7611d57628fSDongsheng Yang goto err; 7621d57628fSDongsheng Yang } 7631d57628fSDongsheng Yang 7641d57628fSDongsheng Yang ret = cache_copy_from_req_bio(cache, key, pcache_req, io_done); 7651d57628fSDongsheng Yang if (ret) { 7661d57628fSDongsheng Yang cache_seg_put(key->cache_pos.cache_seg); 7671d57628fSDongsheng Yang cache_key_put(key); 7681d57628fSDongsheng Yang goto err; 7691d57628fSDongsheng Yang } 7701d57628fSDongsheng Yang 7711d57628fSDongsheng Yang cache_subtree = get_subtree(&cache->req_key_tree, key->off); 7721d57628fSDongsheng Yang spin_lock(&cache_subtree->tree_lock); 7731d57628fSDongsheng Yang cache_key_insert(&cache->req_key_tree, key, true); 7741d57628fSDongsheng Yang ret = cache_key_append(cache, key, pcache_req->bio->bi_opf & REQ_FUA); 7751d57628fSDongsheng Yang if (ret) { 7761d57628fSDongsheng Yang cache_seg_put(key->cache_pos.cache_seg); 7771d57628fSDongsheng Yang cache_key_delete(key); 7781d57628fSDongsheng Yang goto unlock; 7791d57628fSDongsheng Yang } 7801d57628fSDongsheng Yang 7811d57628fSDongsheng Yang io_done += key->len; 7821d57628fSDongsheng Yang spin_unlock(&cache_subtree->tree_lock); 7831d57628fSDongsheng Yang } 7841d57628fSDongsheng Yang 7851d57628fSDongsheng Yang return 0; 7861d57628fSDongsheng Yang unlock: 7871d57628fSDongsheng Yang spin_unlock(&cache_subtree->tree_lock); 7881d57628fSDongsheng Yang err: 7891d57628fSDongsheng Yang return ret; 7901d57628fSDongsheng Yang } 7911d57628fSDongsheng Yang 7921d57628fSDongsheng Yang /** 7931d57628fSDongsheng Yang * cache_flush - Flush all ksets to persist any pending cache data 7941d57628fSDongsheng Yang * @cache: Pointer to the cache structure 7951d57628fSDongsheng Yang * 7961d57628fSDongsheng Yang * This function iterates through all ksets associated with the provided `cache` 7971d57628fSDongsheng Yang * and ensures that any data marked for persistence is written to media. For each 7981d57628fSDongsheng Yang * kset, it acquires the kset lock, then invokes `cache_kset_close`, which handles 7991d57628fSDongsheng Yang * the persistence logic for that kset. 8001d57628fSDongsheng Yang * 8011d57628fSDongsheng Yang * If `cache_kset_close` encounters an error, the function exits immediately with 8021d57628fSDongsheng Yang * the respective error code, preventing the flush operation from proceeding to 8031d57628fSDongsheng Yang * subsequent ksets. 8041d57628fSDongsheng Yang */ 8051d57628fSDongsheng Yang int cache_flush(struct pcache_cache *cache) 8061d57628fSDongsheng Yang { 8071d57628fSDongsheng Yang struct pcache_cache_kset *kset; 808*4466dd3dSQianfeng Rong int ret; 809*4466dd3dSQianfeng Rong u32 i; 8101d57628fSDongsheng Yang 8111d57628fSDongsheng Yang for (i = 0; i < cache->n_ksets; i++) { 8121d57628fSDongsheng Yang kset = get_kset(cache, i); 8131d57628fSDongsheng Yang 8141d57628fSDongsheng Yang spin_lock(&kset->kset_lock); 8151d57628fSDongsheng Yang ret = cache_kset_close(cache, kset); 8161d57628fSDongsheng Yang spin_unlock(&kset->kset_lock); 8171d57628fSDongsheng Yang 8181d57628fSDongsheng Yang if (ret) 8191d57628fSDongsheng Yang return ret; 8201d57628fSDongsheng Yang } 8211d57628fSDongsheng Yang 8221d57628fSDongsheng Yang return 0; 8231d57628fSDongsheng Yang } 8241d57628fSDongsheng Yang 8251d57628fSDongsheng Yang int pcache_cache_handle_req(struct pcache_cache *cache, struct pcache_request *pcache_req) 8261d57628fSDongsheng Yang { 8271d57628fSDongsheng Yang struct bio *bio = pcache_req->bio; 8281d57628fSDongsheng Yang 8291d57628fSDongsheng Yang if (unlikely(bio->bi_opf & REQ_PREFLUSH)) 8301d57628fSDongsheng Yang return cache_flush(cache); 8311d57628fSDongsheng Yang 8321d57628fSDongsheng Yang if (bio_data_dir(bio) == READ) 8331d57628fSDongsheng Yang return cache_read(cache, pcache_req); 8341d57628fSDongsheng Yang 8351d57628fSDongsheng Yang return cache_write(cache, pcache_req); 8361d57628fSDongsheng Yang } 837