forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/drivers/mtd/ubi/fastmap-wl.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012 Linutronix GmbH
34 * Copyright (c) 2014 sigma star gmbh
45 * Author: Richard Weinberger <richard@nod.at>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; version 2.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13
- * the GNU General Public License for more details.
14
- *
156 */
167
178 /**
....@@ -106,6 +97,33 @@
10697 return e;
10798 }
10899
100
+/*
101
+ * has_enough_free_count - whether ubi has enough free pebs to fill fm pools
102
+ * @ubi: UBI device description object
103
+ * @is_wl_pool: whether UBI is filling wear leveling pool
104
+ *
105
+ * This helper function checks whether there are enough free pebs (deducted
106
+ * by fastmap pebs) to fill fm_pool and fm_wl_pool, above rule works after
107
+ * there is at least one of free pebs is filled into fm_wl_pool.
108
+ * For wear leveling pool, UBI should also reserve free pebs for bad pebs
109
+ * handling, because there maybe no enough free pebs for user volumes after
110
+ * producing new bad pebs.
111
+ */
112
+static bool has_enough_free_count(struct ubi_device *ubi, bool is_wl_pool)
113
+{
114
+ int fm_used = 0; // fastmap non anchor pebs.
115
+ int beb_rsvd_pebs;
116
+
117
+ if (!ubi->free.rb_node)
118
+ return false;
119
+
120
+ beb_rsvd_pebs = is_wl_pool ? ubi->beb_rsvd_pebs : 0;
121
+ if (ubi->fm_wl_pool.size > 0 && !(ubi->ro_mode || ubi->fm_disabled))
122
+ fm_used = ubi->fm_size / ubi->leb_size - 1;
123
+
124
+ return ubi->free_count - beb_rsvd_pebs > fm_used;
125
+}
126
+
109127 /**
110128 * ubi_refill_pools - refills all fastmap PEB pools.
111129 * @ubi: UBI device description object
....@@ -125,10 +143,23 @@
125143 wl_pool->size = 0;
126144 pool->size = 0;
127145
146
+ if (ubi->fm_anchor) {
147
+ wl_tree_add(ubi->fm_anchor, &ubi->free);
148
+ ubi->free_count++;
149
+ ubi->fm_anchor = NULL;
150
+ }
151
+
152
+ if (!ubi->fm_disabled)
153
+ /*
154
+ * All available PEBs are in ubi->free, now is the time to get
155
+ * the best anchor PEBs.
156
+ */
157
+ ubi->fm_anchor = ubi_wl_get_fm_peb(ubi, 1);
158
+
128159 for (;;) {
129160 enough = 0;
130161 if (pool->size < pool->max_size) {
131
- if (!ubi->free.rb_node)
162
+ if (!has_enough_free_count(ubi, false))
132163 break;
133164
134165 e = wl_get_wle(ubi);
....@@ -141,8 +172,7 @@
141172 enough++;
142173
143174 if (wl_pool->size < wl_pool->max_size) {
144
- if (!ubi->free.rb_node ||
145
- (ubi->free_count - ubi->beb_rsvd_pebs < 5))
175
+ if (!has_enough_free_count(ubi, true))
146176 break;
147177
148178 e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
....@@ -199,7 +229,7 @@
199229 */
200230 int ubi_wl_get_peb(struct ubi_device *ubi)
201231 {
202
- int ret, retried = 0;
232
+ int ret, attempts = 0;
203233 struct ubi_fm_pool *pool = &ubi->fm_pool;
204234 struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
205235
....@@ -224,12 +254,12 @@
224254
225255 if (pool->used == pool->size) {
226256 spin_unlock(&ubi->wl_lock);
227
- if (retried) {
257
+ attempts++;
258
+ if (attempts == 10) {
228259 ubi_err(ubi, "Unable to get a free PEB from user WL pool");
229260 ret = -ENOSPC;
230261 goto out;
231262 }
232
- retried = 1;
233263 up_read(&ubi->fm_eba_sem);
234264 ret = produce_free_peb(ubi);
235265 if (ret < 0) {
....@@ -298,8 +328,8 @@
298328 return 0;
299329 }
300330
301
- /* No luck, trigger wear leveling to produce a new anchor PEB */
302331 ubi->fm_do_produce_anchor = 1;
332
+ /* No luck, trigger wear leveling to produce a new anchor PEB. */
303333 if (ubi->wl_scheduled) {
304334 spin_unlock(&ubi->wl_lock);
305335 return 0;