xref: /spdk/lib/ftl/ftl_l2p.c (revision cdb0726b95631d46eaf4f2e39ddb6533f150fd27)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "ftl_l2p.h"
7 #include "ftl_nv_cache.h"
8 #include "ftl_l2p_flat.h"
9 #include "ftl_core.h"
10 
11 
12 /* TODO: Verify why function pointers had worse performance than compile time constants */
13 #define FTL_L2P_OP(name)	ftl_l2p_flat_ ## name
14 
15 
16 int
17 ftl_l2p_init(struct spdk_ftl_dev *dev)
18 {
19 	TAILQ_INIT(&dev->l2p_deferred_pins);
20 	return FTL_L2P_OP(init)(dev);
21 }
22 
23 void
24 ftl_l2p_deinit(struct spdk_ftl_dev *dev)
25 {
26 	FTL_L2P_OP(deinit)(dev);
27 }
28 
29 static inline void
30 ftl_l2p_pin_ctx_init(struct ftl_l2p_pin_ctx *pin_ctx, uint64_t lba, uint64_t count,
31 		     ftl_l2p_pin_cb cb, void *cb_ctx)
32 {
33 	pin_ctx->lba = lba;
34 	pin_ctx->count = count;
35 	pin_ctx->cb = cb;
36 	pin_ctx->cb_ctx = cb_ctx;
37 }
38 
39 void
40 ftl_l2p_pin(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t count, ftl_l2p_pin_cb cb, void *cb_ctx,
41 	    struct ftl_l2p_pin_ctx *pin_ctx)
42 {
43 	ftl_l2p_pin_ctx_init(pin_ctx, lba, count, cb, cb_ctx);
44 	FTL_L2P_OP(pin)(dev, pin_ctx);
45 }
46 
47 void
48 ftl_l2p_unpin(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t count)
49 {
50 	FTL_L2P_OP(unpin)(dev, lba, count);
51 }
52 
53 void
54 ftl_l2p_pin_skip(struct spdk_ftl_dev *dev, ftl_l2p_pin_cb cb, void *cb_ctx,
55 		 struct ftl_l2p_pin_ctx *pin_ctx)
56 {
57 	ftl_l2p_pin_ctx_init(pin_ctx, FTL_LBA_INVALID, 0, cb, cb_ctx);
58 	cb(dev, 0, pin_ctx);
59 }
60 
61 void
62 ftl_l2p_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr)
63 {
64 	FTL_L2P_OP(set)(dev, lba, addr);
65 }
66 
67 ftl_addr
68 ftl_l2p_get(struct spdk_ftl_dev *dev, uint64_t lba)
69 {
70 	return FTL_L2P_OP(get)(dev, lba);
71 }
72 
73 void
74 ftl_l2p_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
75 {
76 	FTL_L2P_OP(clear)(dev, cb, cb_ctx);
77 }
78 
79 void
80 ftl_l2p_process(struct spdk_ftl_dev *dev)
81 {
82 	struct ftl_l2p_pin_ctx *pin_ctx;
83 
84 	pin_ctx = TAILQ_FIRST(&dev->l2p_deferred_pins);
85 	if (pin_ctx) {
86 		TAILQ_REMOVE(&dev->l2p_deferred_pins, pin_ctx, link);
87 		FTL_L2P_OP(pin)(dev, pin_ctx);
88 	}
89 
90 	FTL_L2P_OP(process)(dev);
91 }
92 
93 bool
94 ftl_l2p_is_halted(struct spdk_ftl_dev *dev)
95 {
96 	if (!TAILQ_EMPTY(&dev->l2p_deferred_pins)) {
97 		return false;
98 	}
99 
100 	return FTL_L2P_OP(is_halted)(dev);
101 }
102 
103 void
104 ftl_l2p_halt(struct spdk_ftl_dev *dev)
105 {
106 	return FTL_L2P_OP(halt)(dev);
107 }
108 
109 void
110 ftl_l2p_update_base(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr new_addr, ftl_addr old_addr)
111 {
112 	ftl_addr current_addr;
113 
114 	/* Updating L2P for data in base device - used by compaction and GC, may be invalidated by user write.
115 	 * Split off from updating L2P in cache due to extra edge cases for handling dirty shutdown in the cache case.
116 	 * Also some assumptions are not the same (can't assign INVALID address for base device - trim cases are done on cache)
117 	 */
118 	assert(ftl_check_core_thread(dev));
119 	assert(new_addr != FTL_ADDR_INVALID);
120 	assert(old_addr != FTL_ADDR_INVALID);
121 	assert(!ftl_addr_in_nvc(dev, new_addr));
122 
123 	current_addr = ftl_l2p_get(dev, lba);
124 
125 	if (current_addr == old_addr) {
126 		/* DO NOT CHANGE ORDER - START (need to set L2P (and valid bits), before invalidating old ones,
127 		 * due to dirty shutdown from shm recovery - it's ok to have too many bits set, but not ok to
128 		 * have too many cleared) */
129 		ftl_l2p_set(dev, lba, new_addr);
130 		/* DO NOT CHANGE ORDER - END */
131 	} else {
132 		/* new addr could be set by running p2l checkpoint but in the time window between
133 		 * p2l checkpoint completion and l2p set operation new data could be written on
134 		 * open chunk so this address need to be invalidated */
135 		ftl_invalidate_addr(dev, new_addr);
136 	}
137 
138 	ftl_invalidate_addr(dev, old_addr);
139 }
140 
141 void
142 ftl_l2p_pin_complete(struct spdk_ftl_dev *dev, int status, struct ftl_l2p_pin_ctx *pin_ctx)
143 {
144 	if (spdk_unlikely(status == -EAGAIN)) {
145 		TAILQ_INSERT_TAIL(&dev->l2p_deferred_pins, pin_ctx, link);
146 	} else {
147 		pin_ctx->cb(dev, status, pin_ctx);
148 	}
149 }
150