xref: /OK3568_Linux_fs/kernel/block/badblocks.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Bad block management
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * - Heavily based on MD badblocks code from Neil Brown
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2015, Intel Corporation.
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/badblocks.h>
11*4882a593Smuzhiyun #include <linux/seqlock.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/stddef.h>
16*4882a593Smuzhiyun #include <linux/types.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /**
20*4882a593Smuzhiyun  * badblocks_check() - check a given range for bad sectors
21*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
22*4882a593Smuzhiyun  * @s:		sector (start) at which to check for badblocks
23*4882a593Smuzhiyun  * @sectors:	number of sectors to check for badblocks
24*4882a593Smuzhiyun  * @first_bad:	pointer to store location of the first badblock
25*4882a593Smuzhiyun  * @bad_sectors: pointer to store number of badblocks after @first_bad
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  * We can record which blocks on each device are 'bad' and so just
28*4882a593Smuzhiyun  * fail those blocks, or that stripe, rather than the whole device.
29*4882a593Smuzhiyun  * Entries in the bad-block table are 64bits wide.  This comprises:
30*4882a593Smuzhiyun  * Length of bad-range, in sectors: 0-511 for lengths 1-512
31*4882a593Smuzhiyun  * Start of bad-range, sector offset, 54 bits (allows 8 exbibytes)
32*4882a593Smuzhiyun  *  A 'shift' can be set so that larger blocks are tracked and
33*4882a593Smuzhiyun  *  consequently larger devices can be covered.
34*4882a593Smuzhiyun  * 'Acknowledged' flag - 1 bit. - the most significant bit.
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  * Locking of the bad-block table uses a seqlock so badblocks_check
37*4882a593Smuzhiyun  * might need to retry if it is very unlucky.
38*4882a593Smuzhiyun  * We will sometimes want to check for bad blocks in a bi_end_io function,
39*4882a593Smuzhiyun  * so we use the write_seqlock_irq variant.
40*4882a593Smuzhiyun  *
41*4882a593Smuzhiyun  * When looking for a bad block we specify a range and want to
42*4882a593Smuzhiyun  * know if any block in the range is bad.  So we binary-search
43*4882a593Smuzhiyun  * to the last range that starts at-or-before the given endpoint,
44*4882a593Smuzhiyun  * (or "before the sector after the target range")
45*4882a593Smuzhiyun  * then see if it ends after the given start.
46*4882a593Smuzhiyun  *
47*4882a593Smuzhiyun  * Return:
48*4882a593Smuzhiyun  *  0: there are no known bad blocks in the range
49*4882a593Smuzhiyun  *  1: there are known bad block which are all acknowledged
50*4882a593Smuzhiyun  * -1: there are bad blocks which have not yet been acknowledged in metadata.
51*4882a593Smuzhiyun  * plus the start/length of the first bad section we overlap.
52*4882a593Smuzhiyun  */
badblocks_check(struct badblocks * bb,sector_t s,int sectors,sector_t * first_bad,int * bad_sectors)53*4882a593Smuzhiyun int badblocks_check(struct badblocks *bb, sector_t s, int sectors,
54*4882a593Smuzhiyun 			sector_t *first_bad, int *bad_sectors)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	int hi;
57*4882a593Smuzhiyun 	int lo;
58*4882a593Smuzhiyun 	u64 *p = bb->page;
59*4882a593Smuzhiyun 	int rv;
60*4882a593Smuzhiyun 	sector_t target = s + sectors;
61*4882a593Smuzhiyun 	unsigned seq;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (bb->shift > 0) {
64*4882a593Smuzhiyun 		/* round the start down, and the end up */
65*4882a593Smuzhiyun 		s >>= bb->shift;
66*4882a593Smuzhiyun 		target += (1<<bb->shift) - 1;
67*4882a593Smuzhiyun 		target >>= bb->shift;
68*4882a593Smuzhiyun 		sectors = target - s;
69*4882a593Smuzhiyun 	}
70*4882a593Smuzhiyun 	/* 'target' is now the first block after the bad range */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun retry:
73*4882a593Smuzhiyun 	seq = read_seqbegin(&bb->lock);
74*4882a593Smuzhiyun 	lo = 0;
75*4882a593Smuzhiyun 	rv = 0;
76*4882a593Smuzhiyun 	hi = bb->count;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	/* Binary search between lo and hi for 'target'
79*4882a593Smuzhiyun 	 * i.e. for the last range that starts before 'target'
80*4882a593Smuzhiyun 	 */
81*4882a593Smuzhiyun 	/* INVARIANT: ranges before 'lo' and at-or-after 'hi'
82*4882a593Smuzhiyun 	 * are known not to be the last range before target.
83*4882a593Smuzhiyun 	 * VARIANT: hi-lo is the number of possible
84*4882a593Smuzhiyun 	 * ranges, and decreases until it reaches 1
85*4882a593Smuzhiyun 	 */
86*4882a593Smuzhiyun 	while (hi - lo > 1) {
87*4882a593Smuzhiyun 		int mid = (lo + hi) / 2;
88*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[mid]);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		if (a < target)
91*4882a593Smuzhiyun 			/* This could still be the one, earlier ranges
92*4882a593Smuzhiyun 			 * could not.
93*4882a593Smuzhiyun 			 */
94*4882a593Smuzhiyun 			lo = mid;
95*4882a593Smuzhiyun 		else
96*4882a593Smuzhiyun 			/* This and later ranges are definitely out. */
97*4882a593Smuzhiyun 			hi = mid;
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 	/* 'lo' might be the last that started before target, but 'hi' isn't */
100*4882a593Smuzhiyun 	if (hi > lo) {
101*4882a593Smuzhiyun 		/* need to check all range that end after 's' to see if
102*4882a593Smuzhiyun 		 * any are unacknowledged.
103*4882a593Smuzhiyun 		 */
104*4882a593Smuzhiyun 		while (lo >= 0 &&
105*4882a593Smuzhiyun 		       BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
106*4882a593Smuzhiyun 			if (BB_OFFSET(p[lo]) < target) {
107*4882a593Smuzhiyun 				/* starts before the end, and finishes after
108*4882a593Smuzhiyun 				 * the start, so they must overlap
109*4882a593Smuzhiyun 				 */
110*4882a593Smuzhiyun 				if (rv != -1 && BB_ACK(p[lo]))
111*4882a593Smuzhiyun 					rv = 1;
112*4882a593Smuzhiyun 				else
113*4882a593Smuzhiyun 					rv = -1;
114*4882a593Smuzhiyun 				*first_bad = BB_OFFSET(p[lo]);
115*4882a593Smuzhiyun 				*bad_sectors = BB_LEN(p[lo]);
116*4882a593Smuzhiyun 			}
117*4882a593Smuzhiyun 			lo--;
118*4882a593Smuzhiyun 		}
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (read_seqretry(&bb->lock, seq))
122*4882a593Smuzhiyun 		goto retry;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	return rv;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_check);
127*4882a593Smuzhiyun 
badblocks_update_acked(struct badblocks * bb)128*4882a593Smuzhiyun static void badblocks_update_acked(struct badblocks *bb)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	u64 *p = bb->page;
131*4882a593Smuzhiyun 	int i;
132*4882a593Smuzhiyun 	bool unacked = false;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	if (!bb->unacked_exist)
135*4882a593Smuzhiyun 		return;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	for (i = 0; i < bb->count ; i++) {
138*4882a593Smuzhiyun 		if (!BB_ACK(p[i])) {
139*4882a593Smuzhiyun 			unacked = true;
140*4882a593Smuzhiyun 			break;
141*4882a593Smuzhiyun 		}
142*4882a593Smuzhiyun 	}
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	if (!unacked)
145*4882a593Smuzhiyun 		bb->unacked_exist = 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun /**
149*4882a593Smuzhiyun  * badblocks_set() - Add a range of bad blocks to the table.
150*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
151*4882a593Smuzhiyun  * @s:		first sector to mark as bad
152*4882a593Smuzhiyun  * @sectors:	number of sectors to mark as bad
153*4882a593Smuzhiyun  * @acknowledged: weather to mark the bad sectors as acknowledged
154*4882a593Smuzhiyun  *
155*4882a593Smuzhiyun  * This might extend the table, or might contract it if two adjacent ranges
156*4882a593Smuzhiyun  * can be merged. We binary-search to find the 'insertion' point, then
157*4882a593Smuzhiyun  * decide how best to handle it.
158*4882a593Smuzhiyun  *
159*4882a593Smuzhiyun  * Return:
160*4882a593Smuzhiyun  *  0: success
161*4882a593Smuzhiyun  *  1: failed to set badblocks (out of space)
162*4882a593Smuzhiyun  */
badblocks_set(struct badblocks * bb,sector_t s,int sectors,int acknowledged)163*4882a593Smuzhiyun int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
164*4882a593Smuzhiyun 			int acknowledged)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	u64 *p;
167*4882a593Smuzhiyun 	int lo, hi;
168*4882a593Smuzhiyun 	int rv = 0;
169*4882a593Smuzhiyun 	unsigned long flags;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if (bb->shift < 0)
172*4882a593Smuzhiyun 		/* badblocks are disabled */
173*4882a593Smuzhiyun 		return 1;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (bb->shift) {
176*4882a593Smuzhiyun 		/* round the start down, and the end up */
177*4882a593Smuzhiyun 		sector_t next = s + sectors;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		s >>= bb->shift;
180*4882a593Smuzhiyun 		next += (1<<bb->shift) - 1;
181*4882a593Smuzhiyun 		next >>= bb->shift;
182*4882a593Smuzhiyun 		sectors = next - s;
183*4882a593Smuzhiyun 	}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	write_seqlock_irqsave(&bb->lock, flags);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	p = bb->page;
188*4882a593Smuzhiyun 	lo = 0;
189*4882a593Smuzhiyun 	hi = bb->count;
190*4882a593Smuzhiyun 	/* Find the last range that starts at-or-before 's' */
191*4882a593Smuzhiyun 	while (hi - lo > 1) {
192*4882a593Smuzhiyun 		int mid = (lo + hi) / 2;
193*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[mid]);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 		if (a <= s)
196*4882a593Smuzhiyun 			lo = mid;
197*4882a593Smuzhiyun 		else
198*4882a593Smuzhiyun 			hi = mid;
199*4882a593Smuzhiyun 	}
200*4882a593Smuzhiyun 	if (hi > lo && BB_OFFSET(p[lo]) > s)
201*4882a593Smuzhiyun 		hi = lo;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (hi > lo) {
204*4882a593Smuzhiyun 		/* we found a range that might merge with the start
205*4882a593Smuzhiyun 		 * of our new range
206*4882a593Smuzhiyun 		 */
207*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[lo]);
208*4882a593Smuzhiyun 		sector_t e = a + BB_LEN(p[lo]);
209*4882a593Smuzhiyun 		int ack = BB_ACK(p[lo]);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 		if (e >= s) {
212*4882a593Smuzhiyun 			/* Yes, we can merge with a previous range */
213*4882a593Smuzhiyun 			if (s == a && s + sectors >= e)
214*4882a593Smuzhiyun 				/* new range covers old */
215*4882a593Smuzhiyun 				ack = acknowledged;
216*4882a593Smuzhiyun 			else
217*4882a593Smuzhiyun 				ack = ack && acknowledged;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 			if (e < s + sectors)
220*4882a593Smuzhiyun 				e = s + sectors;
221*4882a593Smuzhiyun 			if (e - a <= BB_MAX_LEN) {
222*4882a593Smuzhiyun 				p[lo] = BB_MAKE(a, e-a, ack);
223*4882a593Smuzhiyun 				s = e;
224*4882a593Smuzhiyun 			} else {
225*4882a593Smuzhiyun 				/* does not all fit in one range,
226*4882a593Smuzhiyun 				 * make p[lo] maximal
227*4882a593Smuzhiyun 				 */
228*4882a593Smuzhiyun 				if (BB_LEN(p[lo]) != BB_MAX_LEN)
229*4882a593Smuzhiyun 					p[lo] = BB_MAKE(a, BB_MAX_LEN, ack);
230*4882a593Smuzhiyun 				s = a + BB_MAX_LEN;
231*4882a593Smuzhiyun 			}
232*4882a593Smuzhiyun 			sectors = e - s;
233*4882a593Smuzhiyun 		}
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 	if (sectors && hi < bb->count) {
236*4882a593Smuzhiyun 		/* 'hi' points to the first range that starts after 's'.
237*4882a593Smuzhiyun 		 * Maybe we can merge with the start of that range
238*4882a593Smuzhiyun 		 */
239*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[hi]);
240*4882a593Smuzhiyun 		sector_t e = a + BB_LEN(p[hi]);
241*4882a593Smuzhiyun 		int ack = BB_ACK(p[hi]);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 		if (a <= s + sectors) {
244*4882a593Smuzhiyun 			/* merging is possible */
245*4882a593Smuzhiyun 			if (e <= s + sectors) {
246*4882a593Smuzhiyun 				/* full overlap */
247*4882a593Smuzhiyun 				e = s + sectors;
248*4882a593Smuzhiyun 				ack = acknowledged;
249*4882a593Smuzhiyun 			} else
250*4882a593Smuzhiyun 				ack = ack && acknowledged;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 			a = s;
253*4882a593Smuzhiyun 			if (e - a <= BB_MAX_LEN) {
254*4882a593Smuzhiyun 				p[hi] = BB_MAKE(a, e-a, ack);
255*4882a593Smuzhiyun 				s = e;
256*4882a593Smuzhiyun 			} else {
257*4882a593Smuzhiyun 				p[hi] = BB_MAKE(a, BB_MAX_LEN, ack);
258*4882a593Smuzhiyun 				s = a + BB_MAX_LEN;
259*4882a593Smuzhiyun 			}
260*4882a593Smuzhiyun 			sectors = e - s;
261*4882a593Smuzhiyun 			lo = hi;
262*4882a593Smuzhiyun 			hi++;
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 	if (sectors == 0 && hi < bb->count) {
266*4882a593Smuzhiyun 		/* we might be able to combine lo and hi */
267*4882a593Smuzhiyun 		/* Note: 's' is at the end of 'lo' */
268*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[hi]);
269*4882a593Smuzhiyun 		int lolen = BB_LEN(p[lo]);
270*4882a593Smuzhiyun 		int hilen = BB_LEN(p[hi]);
271*4882a593Smuzhiyun 		int newlen = lolen + hilen - (s - a);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 		if (s >= a && newlen < BB_MAX_LEN) {
274*4882a593Smuzhiyun 			/* yes, we can combine them */
275*4882a593Smuzhiyun 			int ack = BB_ACK(p[lo]) && BB_ACK(p[hi]);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 			p[lo] = BB_MAKE(BB_OFFSET(p[lo]), newlen, ack);
278*4882a593Smuzhiyun 			memmove(p + hi, p + hi + 1,
279*4882a593Smuzhiyun 				(bb->count - hi - 1) * 8);
280*4882a593Smuzhiyun 			bb->count--;
281*4882a593Smuzhiyun 		}
282*4882a593Smuzhiyun 	}
283*4882a593Smuzhiyun 	while (sectors) {
284*4882a593Smuzhiyun 		/* didn't merge (it all).
285*4882a593Smuzhiyun 		 * Need to add a range just before 'hi'
286*4882a593Smuzhiyun 		 */
287*4882a593Smuzhiyun 		if (bb->count >= MAX_BADBLOCKS) {
288*4882a593Smuzhiyun 			/* No room for more */
289*4882a593Smuzhiyun 			rv = 1;
290*4882a593Smuzhiyun 			break;
291*4882a593Smuzhiyun 		} else {
292*4882a593Smuzhiyun 			int this_sectors = sectors;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 			memmove(p + hi + 1, p + hi,
295*4882a593Smuzhiyun 				(bb->count - hi) * 8);
296*4882a593Smuzhiyun 			bb->count++;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 			if (this_sectors > BB_MAX_LEN)
299*4882a593Smuzhiyun 				this_sectors = BB_MAX_LEN;
300*4882a593Smuzhiyun 			p[hi] = BB_MAKE(s, this_sectors, acknowledged);
301*4882a593Smuzhiyun 			sectors -= this_sectors;
302*4882a593Smuzhiyun 			s += this_sectors;
303*4882a593Smuzhiyun 		}
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	bb->changed = 1;
307*4882a593Smuzhiyun 	if (!acknowledged)
308*4882a593Smuzhiyun 		bb->unacked_exist = 1;
309*4882a593Smuzhiyun 	else
310*4882a593Smuzhiyun 		badblocks_update_acked(bb);
311*4882a593Smuzhiyun 	write_sequnlock_irqrestore(&bb->lock, flags);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return rv;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_set);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun /**
318*4882a593Smuzhiyun  * badblocks_clear() - Remove a range of bad blocks to the table.
319*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
320*4882a593Smuzhiyun  * @s:		first sector to mark as bad
321*4882a593Smuzhiyun  * @sectors:	number of sectors to mark as bad
322*4882a593Smuzhiyun  *
323*4882a593Smuzhiyun  * This may involve extending the table if we spilt a region,
324*4882a593Smuzhiyun  * but it must not fail.  So if the table becomes full, we just
325*4882a593Smuzhiyun  * drop the remove request.
326*4882a593Smuzhiyun  *
327*4882a593Smuzhiyun  * Return:
328*4882a593Smuzhiyun  *  0: success
329*4882a593Smuzhiyun  *  1: failed to clear badblocks
330*4882a593Smuzhiyun  */
badblocks_clear(struct badblocks * bb,sector_t s,int sectors)331*4882a593Smuzhiyun int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	u64 *p;
334*4882a593Smuzhiyun 	int lo, hi;
335*4882a593Smuzhiyun 	sector_t target = s + sectors;
336*4882a593Smuzhiyun 	int rv = 0;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (bb->shift > 0) {
339*4882a593Smuzhiyun 		/* When clearing we round the start up and the end down.
340*4882a593Smuzhiyun 		 * This should not matter as the shift should align with
341*4882a593Smuzhiyun 		 * the block size and no rounding should ever be needed.
342*4882a593Smuzhiyun 		 * However it is better the think a block is bad when it
343*4882a593Smuzhiyun 		 * isn't than to think a block is not bad when it is.
344*4882a593Smuzhiyun 		 */
345*4882a593Smuzhiyun 		s += (1<<bb->shift) - 1;
346*4882a593Smuzhiyun 		s >>= bb->shift;
347*4882a593Smuzhiyun 		target >>= bb->shift;
348*4882a593Smuzhiyun 		sectors = target - s;
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	write_seqlock_irq(&bb->lock);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	p = bb->page;
354*4882a593Smuzhiyun 	lo = 0;
355*4882a593Smuzhiyun 	hi = bb->count;
356*4882a593Smuzhiyun 	/* Find the last range that starts before 'target' */
357*4882a593Smuzhiyun 	while (hi - lo > 1) {
358*4882a593Smuzhiyun 		int mid = (lo + hi) / 2;
359*4882a593Smuzhiyun 		sector_t a = BB_OFFSET(p[mid]);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 		if (a < target)
362*4882a593Smuzhiyun 			lo = mid;
363*4882a593Smuzhiyun 		else
364*4882a593Smuzhiyun 			hi = mid;
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 	if (hi > lo) {
367*4882a593Smuzhiyun 		/* p[lo] is the last range that could overlap the
368*4882a593Smuzhiyun 		 * current range.  Earlier ranges could also overlap,
369*4882a593Smuzhiyun 		 * but only this one can overlap the end of the range.
370*4882a593Smuzhiyun 		 */
371*4882a593Smuzhiyun 		if ((BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) &&
372*4882a593Smuzhiyun 		    (BB_OFFSET(p[lo]) < target)) {
373*4882a593Smuzhiyun 			/* Partial overlap, leave the tail of this range */
374*4882a593Smuzhiyun 			int ack = BB_ACK(p[lo]);
375*4882a593Smuzhiyun 			sector_t a = BB_OFFSET(p[lo]);
376*4882a593Smuzhiyun 			sector_t end = a + BB_LEN(p[lo]);
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 			if (a < s) {
379*4882a593Smuzhiyun 				/* we need to split this range */
380*4882a593Smuzhiyun 				if (bb->count >= MAX_BADBLOCKS) {
381*4882a593Smuzhiyun 					rv = -ENOSPC;
382*4882a593Smuzhiyun 					goto out;
383*4882a593Smuzhiyun 				}
384*4882a593Smuzhiyun 				memmove(p+lo+1, p+lo, (bb->count - lo) * 8);
385*4882a593Smuzhiyun 				bb->count++;
386*4882a593Smuzhiyun 				p[lo] = BB_MAKE(a, s-a, ack);
387*4882a593Smuzhiyun 				lo++;
388*4882a593Smuzhiyun 			}
389*4882a593Smuzhiyun 			p[lo] = BB_MAKE(target, end - target, ack);
390*4882a593Smuzhiyun 			/* there is no longer an overlap */
391*4882a593Smuzhiyun 			hi = lo;
392*4882a593Smuzhiyun 			lo--;
393*4882a593Smuzhiyun 		}
394*4882a593Smuzhiyun 		while (lo >= 0 &&
395*4882a593Smuzhiyun 		       (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) &&
396*4882a593Smuzhiyun 		       (BB_OFFSET(p[lo]) < target)) {
397*4882a593Smuzhiyun 			/* This range does overlap */
398*4882a593Smuzhiyun 			if (BB_OFFSET(p[lo]) < s) {
399*4882a593Smuzhiyun 				/* Keep the early parts of this range. */
400*4882a593Smuzhiyun 				int ack = BB_ACK(p[lo]);
401*4882a593Smuzhiyun 				sector_t start = BB_OFFSET(p[lo]);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 				p[lo] = BB_MAKE(start, s - start, ack);
404*4882a593Smuzhiyun 				/* now low doesn't overlap, so.. */
405*4882a593Smuzhiyun 				break;
406*4882a593Smuzhiyun 			}
407*4882a593Smuzhiyun 			lo--;
408*4882a593Smuzhiyun 		}
409*4882a593Smuzhiyun 		/* 'lo' is strictly before, 'hi' is strictly after,
410*4882a593Smuzhiyun 		 * anything between needs to be discarded
411*4882a593Smuzhiyun 		 */
412*4882a593Smuzhiyun 		if (hi - lo > 1) {
413*4882a593Smuzhiyun 			memmove(p+lo+1, p+hi, (bb->count - hi) * 8);
414*4882a593Smuzhiyun 			bb->count -= (hi - lo - 1);
415*4882a593Smuzhiyun 		}
416*4882a593Smuzhiyun 	}
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	badblocks_update_acked(bb);
419*4882a593Smuzhiyun 	bb->changed = 1;
420*4882a593Smuzhiyun out:
421*4882a593Smuzhiyun 	write_sequnlock_irq(&bb->lock);
422*4882a593Smuzhiyun 	return rv;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_clear);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun /**
427*4882a593Smuzhiyun  * ack_all_badblocks() - Acknowledge all bad blocks in a list.
428*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
429*4882a593Smuzhiyun  *
430*4882a593Smuzhiyun  * This only succeeds if ->changed is clear.  It is used by
431*4882a593Smuzhiyun  * in-kernel metadata updates
432*4882a593Smuzhiyun  */
ack_all_badblocks(struct badblocks * bb)433*4882a593Smuzhiyun void ack_all_badblocks(struct badblocks *bb)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	if (bb->page == NULL || bb->changed)
436*4882a593Smuzhiyun 		/* no point even trying */
437*4882a593Smuzhiyun 		return;
438*4882a593Smuzhiyun 	write_seqlock_irq(&bb->lock);
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	if (bb->changed == 0 && bb->unacked_exist) {
441*4882a593Smuzhiyun 		u64 *p = bb->page;
442*4882a593Smuzhiyun 		int i;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 		for (i = 0; i < bb->count ; i++) {
445*4882a593Smuzhiyun 			if (!BB_ACK(p[i])) {
446*4882a593Smuzhiyun 				sector_t start = BB_OFFSET(p[i]);
447*4882a593Smuzhiyun 				int len = BB_LEN(p[i]);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 				p[i] = BB_MAKE(start, len, 1);
450*4882a593Smuzhiyun 			}
451*4882a593Smuzhiyun 		}
452*4882a593Smuzhiyun 		bb->unacked_exist = 0;
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 	write_sequnlock_irq(&bb->lock);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ack_all_badblocks);
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun /**
459*4882a593Smuzhiyun  * badblocks_show() - sysfs access to bad-blocks list
460*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
461*4882a593Smuzhiyun  * @page:	buffer received from sysfs
462*4882a593Smuzhiyun  * @unack:	weather to show unacknowledged badblocks
463*4882a593Smuzhiyun  *
464*4882a593Smuzhiyun  * Return:
465*4882a593Smuzhiyun  *  Length of returned data
466*4882a593Smuzhiyun  */
badblocks_show(struct badblocks * bb,char * page,int unack)467*4882a593Smuzhiyun ssize_t badblocks_show(struct badblocks *bb, char *page, int unack)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	size_t len;
470*4882a593Smuzhiyun 	int i;
471*4882a593Smuzhiyun 	u64 *p = bb->page;
472*4882a593Smuzhiyun 	unsigned seq;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	if (bb->shift < 0)
475*4882a593Smuzhiyun 		return 0;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun retry:
478*4882a593Smuzhiyun 	seq = read_seqbegin(&bb->lock);
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	len = 0;
481*4882a593Smuzhiyun 	i = 0;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	while (len < PAGE_SIZE && i < bb->count) {
484*4882a593Smuzhiyun 		sector_t s = BB_OFFSET(p[i]);
485*4882a593Smuzhiyun 		unsigned int length = BB_LEN(p[i]);
486*4882a593Smuzhiyun 		int ack = BB_ACK(p[i]);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 		i++;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 		if (unack && ack)
491*4882a593Smuzhiyun 			continue;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 		len += snprintf(page+len, PAGE_SIZE-len, "%llu %u\n",
494*4882a593Smuzhiyun 				(unsigned long long)s << bb->shift,
495*4882a593Smuzhiyun 				length << bb->shift);
496*4882a593Smuzhiyun 	}
497*4882a593Smuzhiyun 	if (unack && len == 0)
498*4882a593Smuzhiyun 		bb->unacked_exist = 0;
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	if (read_seqretry(&bb->lock, seq))
501*4882a593Smuzhiyun 		goto retry;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	return len;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_show);
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun /**
508*4882a593Smuzhiyun  * badblocks_store() - sysfs access to bad-blocks list
509*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
510*4882a593Smuzhiyun  * @page:	buffer received from sysfs
511*4882a593Smuzhiyun  * @len:	length of data received from sysfs
512*4882a593Smuzhiyun  * @unack:	weather to show unacknowledged badblocks
513*4882a593Smuzhiyun  *
514*4882a593Smuzhiyun  * Return:
515*4882a593Smuzhiyun  *  Length of the buffer processed or -ve error.
516*4882a593Smuzhiyun  */
badblocks_store(struct badblocks * bb,const char * page,size_t len,int unack)517*4882a593Smuzhiyun ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len,
518*4882a593Smuzhiyun 			int unack)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun 	unsigned long long sector;
521*4882a593Smuzhiyun 	int length;
522*4882a593Smuzhiyun 	char newline;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	switch (sscanf(page, "%llu %d%c", &sector, &length, &newline)) {
525*4882a593Smuzhiyun 	case 3:
526*4882a593Smuzhiyun 		if (newline != '\n')
527*4882a593Smuzhiyun 			return -EINVAL;
528*4882a593Smuzhiyun 		fallthrough;
529*4882a593Smuzhiyun 	case 2:
530*4882a593Smuzhiyun 		if (length <= 0)
531*4882a593Smuzhiyun 			return -EINVAL;
532*4882a593Smuzhiyun 		break;
533*4882a593Smuzhiyun 	default:
534*4882a593Smuzhiyun 		return -EINVAL;
535*4882a593Smuzhiyun 	}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	if (badblocks_set(bb, sector, length, !unack))
538*4882a593Smuzhiyun 		return -ENOSPC;
539*4882a593Smuzhiyun 	else
540*4882a593Smuzhiyun 		return len;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_store);
543*4882a593Smuzhiyun 
__badblocks_init(struct device * dev,struct badblocks * bb,int enable)544*4882a593Smuzhiyun static int __badblocks_init(struct device *dev, struct badblocks *bb,
545*4882a593Smuzhiyun 		int enable)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun 	bb->dev = dev;
548*4882a593Smuzhiyun 	bb->count = 0;
549*4882a593Smuzhiyun 	if (enable)
550*4882a593Smuzhiyun 		bb->shift = 0;
551*4882a593Smuzhiyun 	else
552*4882a593Smuzhiyun 		bb->shift = -1;
553*4882a593Smuzhiyun 	if (dev)
554*4882a593Smuzhiyun 		bb->page = devm_kzalloc(dev, PAGE_SIZE, GFP_KERNEL);
555*4882a593Smuzhiyun 	else
556*4882a593Smuzhiyun 		bb->page = kzalloc(PAGE_SIZE, GFP_KERNEL);
557*4882a593Smuzhiyun 	if (!bb->page) {
558*4882a593Smuzhiyun 		bb->shift = -1;
559*4882a593Smuzhiyun 		return -ENOMEM;
560*4882a593Smuzhiyun 	}
561*4882a593Smuzhiyun 	seqlock_init(&bb->lock);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	return 0;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun /**
567*4882a593Smuzhiyun  * badblocks_init() - initialize the badblocks structure
568*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
569*4882a593Smuzhiyun  * @enable:	weather to enable badblocks accounting
570*4882a593Smuzhiyun  *
571*4882a593Smuzhiyun  * Return:
572*4882a593Smuzhiyun  *  0: success
573*4882a593Smuzhiyun  *  -ve errno: on error
574*4882a593Smuzhiyun  */
badblocks_init(struct badblocks * bb,int enable)575*4882a593Smuzhiyun int badblocks_init(struct badblocks *bb, int enable)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun 	return __badblocks_init(NULL, bb, enable);
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_init);
580*4882a593Smuzhiyun 
devm_init_badblocks(struct device * dev,struct badblocks * bb)581*4882a593Smuzhiyun int devm_init_badblocks(struct device *dev, struct badblocks *bb)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun 	if (!bb)
584*4882a593Smuzhiyun 		return -EINVAL;
585*4882a593Smuzhiyun 	return __badblocks_init(dev, bb, 1);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(devm_init_badblocks);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun /**
590*4882a593Smuzhiyun  * badblocks_exit() - free the badblocks structure
591*4882a593Smuzhiyun  * @bb:		the badblocks structure that holds all badblock information
592*4882a593Smuzhiyun  */
badblocks_exit(struct badblocks * bb)593*4882a593Smuzhiyun void badblocks_exit(struct badblocks *bb)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun 	if (!bb)
596*4882a593Smuzhiyun 		return;
597*4882a593Smuzhiyun 	if (bb->dev)
598*4882a593Smuzhiyun 		devm_kfree(bb->dev, bb->page);
599*4882a593Smuzhiyun 	else
600*4882a593Smuzhiyun 		kfree(bb->page);
601*4882a593Smuzhiyun 	bb->page = NULL;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(badblocks_exit);
604