Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 : * All Rights Reserved.
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_trans_resv.h"
12 : #include "xfs_bit.h"
13 : #include "xfs_mount.h"
14 : #include "xfs_inode.h"
15 : #include "xfs_bmap.h"
16 : #include "xfs_trans.h"
17 : #include "xfs_rtalloc.h"
18 : #include "xfs_error.h"
19 :
20 : /*
21 : * Realtime allocator bitmap functions shared with userspace.
22 : */
23 :
24 : /*
25 : * Real time buffers need verifiers to avoid runtime warnings during IO.
26 : * We don't have anything to verify, however, so these are just dummy
27 : * operations.
28 : */
29 : static void
30 82583 : xfs_rtbuf_verify_read(
31 : struct xfs_buf *bp)
32 : {
33 82583 : return;
34 : }
35 :
36 : static void
37 425339 : xfs_rtbuf_verify_write(
38 : struct xfs_buf *bp)
39 : {
40 425339 : return;
41 : }
42 :
43 : const struct xfs_buf_ops xfs_rtbuf_ops = {
44 : .name = "rtbuf",
45 : .verify_read = xfs_rtbuf_verify_read,
46 : .verify_write = xfs_rtbuf_verify_write,
47 : };
48 :
49 : /*
50 : * Get a buffer for the bitmap or summary file block specified.
51 : * The buffer is returned read and locked.
52 : */
53 : int
54 657583802 : xfs_rtbuf_get(
55 : xfs_mount_t *mp, /* file system mount structure */
56 : xfs_trans_t *tp, /* transaction pointer */
57 : xfs_rtblock_t block, /* block number in bitmap or summary */
58 : int issum, /* is summary not bitmap */
59 : struct xfs_buf **bpp) /* output: buffer for the block */
60 : {
61 657583802 : struct xfs_buf *bp; /* block buffer, result */
62 657583802 : xfs_inode_t *ip; /* bitmap or summary inode */
63 657583802 : xfs_bmbt_irec_t map;
64 657583802 : int nmap = 1;
65 657583802 : int error; /* error value */
66 :
67 657583802 : ip = issum ? mp->m_rsumip : mp->m_rbmip;
68 :
69 657583802 : error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
70 657590101 : if (error)
71 : return error;
72 :
73 657590101 : if (XFS_IS_CORRUPT(mp, nmap == 0 || !xfs_bmap_is_written_extent(&map)))
74 0 : return -EFSCORRUPTED;
75 :
76 657590101 : ASSERT(map.br_startblock != NULLFSBLOCK);
77 1972777307 : error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
78 657590101 : XFS_FSB_TO_DADDR(mp, map.br_startblock),
79 : mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
80 657592508 : if (error)
81 : return error;
82 :
83 1296078959 : xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
84 : : XFS_BLFT_RTBITMAP_BUF);
85 657595005 : *bpp = bp;
86 657595005 : return 0;
87 : }
88 :
89 : /*
90 : * Searching backward from start to limit, find the first block whose
91 : * allocated/free state is different from start's.
92 : */
93 : int
94 9541577 : xfs_rtfind_back(
95 : xfs_mount_t *mp, /* file system mount point */
96 : xfs_trans_t *tp, /* transaction pointer */
97 : xfs_rtblock_t start, /* starting block to look at */
98 : xfs_rtblock_t limit, /* last block to look at */
99 : xfs_rtblock_t *rtblock) /* out: start block found */
100 : {
101 9541577 : xfs_rtword_t *b; /* current word in buffer */
102 9541577 : int bit; /* bit number in the word */
103 9541577 : xfs_rtblock_t block; /* bitmap block number */
104 9541577 : struct xfs_buf *bp; /* buf for the block */
105 9541577 : xfs_rtword_t *bufp; /* starting word in buffer */
106 9541577 : int error; /* error value */
107 9541577 : xfs_rtblock_t firstbit; /* first useful bit in the word */
108 9541577 : xfs_rtblock_t i; /* current bit number rel. to start */
109 9541577 : xfs_rtblock_t len; /* length of inspected area */
110 9541577 : xfs_rtword_t mask; /* mask of relevant bits for value */
111 9541577 : xfs_rtword_t want; /* mask for "good" values */
112 9541577 : xfs_rtword_t wdiff; /* difference from wanted value */
113 9541577 : int word; /* word number in the buffer */
114 :
115 : /*
116 : * Compute and read in starting bitmap block for starting block.
117 : */
118 9541577 : block = XFS_BITTOBLOCK(mp, start);
119 9541577 : error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
120 9541577 : if (error) {
121 : return error;
122 : }
123 9541577 : bufp = bp->b_addr;
124 : /*
125 : * Get the first word's index & point to it.
126 : */
127 9541577 : word = XFS_BITTOWORD(mp, start);
128 9541577 : b = &bufp[word];
129 9541577 : bit = (int)(start & (XFS_NBWORD - 1));
130 9541577 : len = start - limit + 1;
131 : /*
132 : * Compute match value, based on the bit at start: if 1 (free)
133 : * then all-ones, else all-zeroes.
134 : */
135 9541577 : want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
136 : /*
137 : * If the starting position is not word-aligned, deal with the
138 : * partial word.
139 : */
140 9541577 : if (bit < XFS_NBWORD - 1) {
141 : /*
142 : * Calculate first (leftmost) bit number to look at,
143 : * and mask for all the relevant bits in this word.
144 : */
145 9249677 : firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
146 9249677 : mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
147 : firstbit;
148 : /*
149 : * Calculate the difference between the value there
150 : * and what we're looking for.
151 : */
152 9249677 : if ((wdiff = (*b ^ want) & mask)) {
153 : /*
154 : * Different. Mark where we are and return.
155 : */
156 8592158 : xfs_trans_brelse(tp, bp);
157 8592158 : i = bit - XFS_RTHIBIT(wdiff);
158 8592158 : *rtblock = start - i + 1;
159 8592158 : return 0;
160 : }
161 657519 : i = bit - firstbit + 1;
162 : /*
163 : * Go on to previous block if that's where the previous word is
164 : * and we need the previous word.
165 : */
166 657519 : if (--word == -1 && i < len) {
167 : /*
168 : * If done with this block, get the previous one.
169 : */
170 4451 : xfs_trans_brelse(tp, bp);
171 4451 : error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
172 4451 : if (error) {
173 : return error;
174 : }
175 4451 : bufp = bp->b_addr;
176 4451 : word = XFS_BLOCKWMASK(mp);
177 4451 : b = &bufp[word];
178 : } else {
179 : /*
180 : * Go on to the previous word in the buffer.
181 : */
182 653068 : b--;
183 : }
184 : } else {
185 : /*
186 : * Starting on a word boundary, no partial word.
187 : */
188 : i = 0;
189 : }
190 : /*
191 : * Loop over whole words in buffers. When we use up one buffer
192 : * we move on to the previous one.
193 : */
194 46263654 : while (len - i >= XFS_NBWORD) {
195 : /*
196 : * Compute difference between actual and desired value.
197 : */
198 46200443 : if ((wdiff = *b ^ want)) {
199 : /*
200 : * Different, mark where we are and return.
201 : */
202 886208 : xfs_trans_brelse(tp, bp);
203 886208 : i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
204 886208 : *rtblock = start - i + 1;
205 886208 : return 0;
206 : }
207 45314235 : i += XFS_NBWORD;
208 : /*
209 : * Go on to previous block if that's where the previous word is
210 : * and we need the previous word.
211 : */
212 45314235 : if (--word == -1 && i < len) {
213 : /*
214 : * If done with this block, get the previous one.
215 : */
216 41739 : xfs_trans_brelse(tp, bp);
217 41739 : error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
218 41739 : if (error) {
219 0 : return error;
220 : }
221 41739 : bufp = bp->b_addr;
222 41739 : word = XFS_BLOCKWMASK(mp);
223 41739 : b = &bufp[word];
224 : } else {
225 : /*
226 : * Go on to the previous word in the buffer.
227 : */
228 45272496 : b--;
229 : }
230 : }
231 : /*
232 : * If not ending on a word boundary, deal with the last
233 : * (partial) word.
234 : */
235 63211 : if (len - i) {
236 : /*
237 : * Calculate first (leftmost) bit number to look at,
238 : * and mask for all the relevant bits in this word.
239 : */
240 0 : firstbit = XFS_NBWORD - (len - i);
241 0 : mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
242 : /*
243 : * Compute difference between actual and desired value.
244 : */
245 0 : if ((wdiff = (*b ^ want) & mask)) {
246 : /*
247 : * Different, mark where we are and return.
248 : */
249 0 : xfs_trans_brelse(tp, bp);
250 0 : i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
251 0 : *rtblock = start - i + 1;
252 0 : return 0;
253 : } else
254 : i = len;
255 : }
256 : /*
257 : * No match, return that we scanned the whole area.
258 : */
259 63211 : xfs_trans_brelse(tp, bp);
260 63211 : *rtblock = start - i + 1;
261 63211 : return 0;
262 : }
263 :
264 : /*
265 : * Searching forward from start to limit, find the first block whose
266 : * allocated/free state is different from start's.
267 : */
268 : int
269 131168376 : xfs_rtfind_forw(
270 : xfs_mount_t *mp, /* file system mount point */
271 : xfs_trans_t *tp, /* transaction pointer */
272 : xfs_rtblock_t start, /* starting block to look at */
273 : xfs_rtblock_t limit, /* last block to look at */
274 : xfs_rtblock_t *rtblock) /* out: start block found */
275 : {
276 131168376 : xfs_rtword_t *b; /* current word in buffer */
277 131168376 : int bit; /* bit number in the word */
278 131168376 : xfs_rtblock_t block; /* bitmap block number */
279 131168376 : struct xfs_buf *bp; /* buf for the block */
280 131168376 : xfs_rtword_t *bufp; /* starting word in buffer */
281 131168376 : int error; /* error value */
282 131168376 : xfs_rtblock_t i; /* current bit number rel. to start */
283 131168376 : xfs_rtblock_t lastbit; /* last useful bit in the word */
284 131168376 : xfs_rtblock_t len; /* length of inspected area */
285 131168376 : xfs_rtword_t mask; /* mask of relevant bits for value */
286 131168376 : xfs_rtword_t want; /* mask for "good" values */
287 131168376 : xfs_rtword_t wdiff; /* difference from wanted value */
288 131168376 : int word; /* word number in the buffer */
289 :
290 : /*
291 : * Compute and read in starting bitmap block for starting block.
292 : */
293 131168376 : block = XFS_BITTOBLOCK(mp, start);
294 131168376 : error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
295 131168376 : if (error) {
296 : return error;
297 : }
298 131168376 : bufp = bp->b_addr;
299 : /*
300 : * Get the first word's index & point to it.
301 : */
302 131168376 : word = XFS_BITTOWORD(mp, start);
303 131168376 : b = &bufp[word];
304 131168376 : bit = (int)(start & (XFS_NBWORD - 1));
305 131168376 : len = limit - start + 1;
306 : /*
307 : * Compute match value, based on the bit at start: if 1 (free)
308 : * then all-ones, else all-zeroes.
309 : */
310 131168376 : want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
311 : /*
312 : * If the starting position is not word-aligned, deal with the
313 : * partial word.
314 : */
315 131168376 : if (bit) {
316 : /*
317 : * Calculate last (rightmost) bit number to look at,
318 : * and mask for all the relevant bits in this word.
319 : */
320 113541162 : lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
321 113541162 : mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
322 : /*
323 : * Calculate the difference between the value there
324 : * and what we're looking for.
325 : */
326 113541162 : if ((wdiff = (*b ^ want) & mask)) {
327 : /*
328 : * Different. Mark where we are and return.
329 : */
330 29453392 : xfs_trans_brelse(tp, bp);
331 29453392 : i = XFS_RTLOBIT(wdiff) - bit;
332 29453392 : *rtblock = start + i - 1;
333 29453392 : return 0;
334 : }
335 84087770 : i = lastbit - bit;
336 : /*
337 : * Go on to next block if that's where the next word is
338 : * and we need the next word.
339 : */
340 84087770 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
341 : /*
342 : * If done with this block, get the previous one.
343 : */
344 304436 : xfs_trans_brelse(tp, bp);
345 304436 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
346 304436 : if (error) {
347 : return error;
348 : }
349 304436 : b = bufp = bp->b_addr;
350 304436 : word = 0;
351 : } else {
352 : /*
353 : * Go on to the previous word in the buffer.
354 : */
355 83783334 : b++;
356 : }
357 : } else {
358 : /*
359 : * Starting on a word boundary, no partial word.
360 : */
361 : i = 0;
362 : }
363 : /*
364 : * Loop over whole words in buffers. When we use up one buffer
365 : * we move on to the next one.
366 : */
367 >20427*10^7 : while (len - i >= XFS_NBWORD) {
368 : /*
369 : * Compute difference between actual and desired value.
370 : */
371 >20426*10^7 : if ((wdiff = *b ^ want)) {
372 : /*
373 : * Different, mark where we are and return.
374 : */
375 93754327 : xfs_trans_brelse(tp, bp);
376 93754327 : i += XFS_RTLOBIT(wdiff);
377 93754327 : *rtblock = start + i - 1;
378 93754327 : return 0;
379 : }
380 >20416*10^7 : i += XFS_NBWORD;
381 : /*
382 : * Go on to next block if that's where the next word is
383 : * and we need the next word.
384 : */
385 >20416*10^7 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
386 : /*
387 : * If done with this block, get the next one.
388 : */
389 189126385 : xfs_trans_brelse(tp, bp);
390 189126385 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
391 189126385 : if (error) {
392 0 : return error;
393 : }
394 189126385 : b = bufp = bp->b_addr;
395 189126385 : word = 0;
396 : } else {
397 : /*
398 : * Go on to the next word in the buffer.
399 : */
400 >20397*10^7 : b++;
401 : }
402 : }
403 : /*
404 : * If not ending on a word boundary, deal with the last
405 : * (partial) word.
406 : */
407 7960657 : if ((lastbit = len - i)) {
408 : /*
409 : * Calculate mask for all the relevant bits in this word.
410 : */
411 0 : mask = ((xfs_rtword_t)1 << lastbit) - 1;
412 : /*
413 : * Compute difference between actual and desired value.
414 : */
415 0 : if ((wdiff = (*b ^ want) & mask)) {
416 : /*
417 : * Different, mark where we are and return.
418 : */
419 0 : xfs_trans_brelse(tp, bp);
420 0 : i += XFS_RTLOBIT(wdiff);
421 0 : *rtblock = start + i - 1;
422 0 : return 0;
423 : } else
424 : i = len;
425 : }
426 : /*
427 : * No match, return that we scanned the whole area.
428 : */
429 7960657 : xfs_trans_brelse(tp, bp);
430 7960657 : *rtblock = start + i - 1;
431 7960657 : return 0;
432 : }
433 :
434 : /*
435 : * Read and/or modify the summary information for a given extent size,
436 : * bitmap block combination.
437 : * Keeps track of a current summary block, so we don't keep reading
438 : * it from the buffer cache.
439 : *
440 : * Summary information is returned in *sum if specified.
441 : * If no delta is specified, returns summary only.
442 : */
443 : int
444 116500788 : xfs_rtmodify_summary_int(
445 : xfs_mount_t *mp, /* file system mount structure */
446 : xfs_trans_t *tp, /* transaction pointer */
447 : int log, /* log2 of extent size */
448 : xfs_rtblock_t bbno, /* bitmap block number */
449 : int delta, /* change to make to summary info */
450 : struct xfs_buf **rbpp, /* in/out: summary block buffer */
451 : xfs_fsblock_t *rsb, /* in/out: summary block number */
452 : xfs_suminfo_t *sum) /* out: summary info for this block */
453 : {
454 116500788 : struct xfs_buf *bp; /* buffer for the summary block */
455 116500788 : int error; /* error value */
456 116500788 : xfs_fsblock_t sb; /* summary fsblock */
457 116500788 : int so; /* index into the summary file */
458 116500788 : xfs_suminfo_t *sp; /* pointer to returned data */
459 :
460 : /*
461 : * Compute entry number in the summary file.
462 : */
463 116500788 : so = XFS_SUMOFFS(mp, log, bbno);
464 : /*
465 : * Compute the block number in the summary file.
466 : */
467 116500788 : sb = XFS_SUMOFFSTOBLOCK(mp, so);
468 : /*
469 : * If we have an old buffer, and the block number matches, use that.
470 : */
471 116500788 : if (*rbpp && *rsb == sb)
472 97393806 : bp = *rbpp;
473 : /*
474 : * Otherwise we have to get the buffer.
475 : */
476 : else {
477 : /*
478 : * If there was an old one, get rid of it first.
479 : */
480 19106982 : if (*rbpp)
481 9565400 : xfs_trans_brelse(tp, *rbpp);
482 19106982 : error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
483 19106982 : if (error) {
484 : return error;
485 : }
486 : /*
487 : * Remember this buffer and block for the next call.
488 : */
489 19106982 : *rbpp = bp;
490 19106982 : *rsb = sb;
491 : }
492 : /*
493 : * Point to the summary information, modify/log it, and/or copy it out.
494 : */
495 116500788 : sp = XFS_SUMPTR(mp, bp, so);
496 116500788 : if (delta) {
497 15647043 : uint first = (uint)((char *)sp - (char *)bp->b_addr);
498 :
499 15647043 : *sp += delta;
500 15647043 : if (mp->m_rsum_cache) {
501 15647043 : if (*sp == 0 && log == mp->m_rsum_cache[bbno])
502 2894102 : mp->m_rsum_cache[bbno]++;
503 15647043 : if (*sp != 0 && log < mp->m_rsum_cache[bbno])
504 2997809 : mp->m_rsum_cache[bbno] = log;
505 : }
506 15647043 : xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
507 : }
508 116500788 : if (sum)
509 100853745 : *sum = *sp;
510 : return 0;
511 : }
512 :
513 : int
514 11936969 : xfs_rtmodify_summary(
515 : xfs_mount_t *mp, /* file system mount structure */
516 : xfs_trans_t *tp, /* transaction pointer */
517 : int log, /* log2 of extent size */
518 : xfs_rtblock_t bbno, /* bitmap block number */
519 : int delta, /* change to make to summary info */
520 : struct xfs_buf **rbpp, /* in/out: summary block buffer */
521 : xfs_fsblock_t *rsb) /* in/out: summary block number */
522 : {
523 11936969 : return xfs_rtmodify_summary_int(mp, tp, log, bbno,
524 : delta, rbpp, rsb, NULL);
525 : }
526 :
527 : /*
528 : * Set the given range of bitmap bits to the given value.
529 : * Do whatever I/O and logging is required.
530 : */
531 : int
532 9541577 : xfs_rtmodify_range(
533 : xfs_mount_t *mp, /* file system mount point */
534 : xfs_trans_t *tp, /* transaction pointer */
535 : xfs_rtblock_t start, /* starting block to modify */
536 : xfs_extlen_t len, /* length of extent to modify */
537 : int val) /* 1 for free, 0 for allocated */
538 : {
539 9541577 : xfs_rtword_t *b; /* current word in buffer */
540 9541577 : int bit; /* bit number in the word */
541 9541577 : xfs_rtblock_t block; /* bitmap block number */
542 9541577 : struct xfs_buf *bp; /* buf for the block */
543 9541577 : xfs_rtword_t *bufp; /* starting word in buffer */
544 9541577 : int error; /* error value */
545 9541577 : xfs_rtword_t *first; /* first used word in the buffer */
546 9541577 : int i; /* current bit number rel. to start */
547 9541577 : int lastbit; /* last useful bit in word */
548 9541577 : xfs_rtword_t mask; /* mask o frelevant bits for value */
549 9541577 : int word; /* word number in the buffer */
550 :
551 : /*
552 : * Compute starting bitmap block number.
553 : */
554 9541577 : block = XFS_BITTOBLOCK(mp, start);
555 : /*
556 : * Read the bitmap block, and point to its data.
557 : */
558 9541577 : error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
559 9541577 : if (error) {
560 : return error;
561 : }
562 9541577 : bufp = bp->b_addr;
563 : /*
564 : * Compute the starting word's address, and starting bit.
565 : */
566 9541577 : word = XFS_BITTOWORD(mp, start);
567 9541577 : first = b = &bufp[word];
568 9541577 : bit = (int)(start & (XFS_NBWORD - 1));
569 : /*
570 : * 0 (allocated) => all zeroes; 1 (free) => all ones.
571 : */
572 9541577 : val = -val;
573 : /*
574 : * If not starting on a word boundary, deal with the first
575 : * (partial) word.
576 : */
577 9541577 : if (bit) {
578 : /*
579 : * Compute first bit not changed and mask of relevant bits.
580 : */
581 9195617 : lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
582 9195617 : mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
583 : /*
584 : * Set/clear the active bits.
585 : */
586 9195617 : if (val)
587 2609428 : *b |= mask;
588 : else
589 6586189 : *b &= ~mask;
590 9195617 : i = lastbit - bit;
591 : /*
592 : * Go on to the next block if that's where the next word is
593 : * and we need the next word.
594 : */
595 9195617 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
596 : /*
597 : * Log the changed part of this block.
598 : * Get the next one.
599 : */
600 1282 : xfs_trans_log_buf(tp, bp,
601 : (uint)((char *)first - (char *)bufp),
602 : (uint)((char *)b - (char *)bufp));
603 1282 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
604 1282 : if (error) {
605 : return error;
606 : }
607 1282 : first = b = bufp = bp->b_addr;
608 1282 : word = 0;
609 : } else {
610 : /*
611 : * Go on to the next word in the buffer
612 : */
613 9194335 : b++;
614 : }
615 : } else {
616 : /*
617 : * Starting on a word boundary, no partial word.
618 : */
619 : i = 0;
620 : }
621 : /*
622 : * Loop over whole words in buffers. When we use up one buffer
623 : * we move on to the next one.
624 : */
625 11773675 : while (len - i >= XFS_NBWORD) {
626 : /*
627 : * Set the word value correctly.
628 : */
629 2232098 : *b = val;
630 2232098 : i += XFS_NBWORD;
631 : /*
632 : * Go on to the next block if that's where the next word is
633 : * and we need the next word.
634 : */
635 2232098 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
636 : /*
637 : * Log the changed part of this block.
638 : * Get the next one.
639 : */
640 924 : xfs_trans_log_buf(tp, bp,
641 924 : (uint)((char *)first - (char *)bufp),
642 924 : (uint)((char *)b - (char *)bufp));
643 924 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
644 924 : if (error) {
645 0 : return error;
646 : }
647 924 : first = b = bufp = bp->b_addr;
648 924 : word = 0;
649 : } else {
650 : /*
651 : * Go on to the next word in the buffer
652 : */
653 2231174 : b++;
654 : }
655 : }
656 : /*
657 : * If not ending on a word boundary, deal with the last
658 : * (partial) word.
659 : */
660 9541577 : if ((lastbit = len - i)) {
661 : /*
662 : * Compute a mask of relevant bits.
663 : */
664 4225949 : mask = ((xfs_rtword_t)1 << lastbit) - 1;
665 : /*
666 : * Set/clear the active bits.
667 : */
668 4225949 : if (val)
669 1123969 : *b |= mask;
670 : else
671 3101980 : *b &= ~mask;
672 4225949 : b++;
673 : }
674 : /*
675 : * Log any remaining changed bytes.
676 : */
677 9541577 : if (b > first)
678 9541577 : xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
679 9541577 : (uint)((char *)b - (char *)bufp - 1));
680 : return 0;
681 : }
682 :
683 : /*
684 : * Mark an extent specified by start and len freed.
685 : * Updates all the summary information as well as the bitmap.
686 : */
687 : int
688 2716341 : xfs_rtfree_range(
689 : xfs_mount_t *mp, /* file system mount point */
690 : xfs_trans_t *tp, /* transaction pointer */
691 : xfs_rtblock_t start, /* starting block to free */
692 : xfs_extlen_t len, /* length to free */
693 : struct xfs_buf **rbpp, /* in/out: summary block buffer */
694 : xfs_fsblock_t *rsb) /* in/out: summary block number */
695 : {
696 2716341 : xfs_rtblock_t end; /* end of the freed extent */
697 2716341 : int error; /* error value */
698 2716341 : xfs_rtblock_t postblock; /* first block freed > end */
699 2716341 : xfs_rtblock_t preblock; /* first block freed < start */
700 :
701 2716341 : end = start + len - 1;
702 : /*
703 : * Modify the bitmap to mark this extent freed.
704 : */
705 2716341 : error = xfs_rtmodify_range(mp, tp, start, len, 1);
706 2716341 : if (error) {
707 : return error;
708 : }
709 : /*
710 : * Assume we're freeing out of the middle of an allocated extent.
711 : * We need to find the beginning and end of the extent so we can
712 : * properly update the summary.
713 : */
714 2716341 : error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
715 2716341 : if (error) {
716 : return error;
717 : }
718 : /*
719 : * Find the next allocated block (end of allocated extent).
720 : */
721 2716341 : error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
722 : &postblock);
723 2716341 : if (error)
724 : return error;
725 : /*
726 : * If there are blocks not being freed at the front of the
727 : * old extent, add summary data for them to be allocated.
728 : */
729 2716341 : if (preblock < start) {
730 306209 : error = xfs_rtmodify_summary(mp, tp,
731 : XFS_RTBLOCKLOG(start - preblock),
732 306209 : XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
733 306209 : if (error) {
734 : return error;
735 : }
736 : }
737 : /*
738 : * If there are blocks not being freed at the end of the
739 : * old extent, add summary data for them to be allocated.
740 : */
741 2716341 : if (postblock > end) {
742 687524 : error = xfs_rtmodify_summary(mp, tp,
743 : XFS_RTBLOCKLOG(postblock - end),
744 687524 : XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
745 687524 : if (error) {
746 : return error;
747 : }
748 : }
749 : /*
750 : * Increment the summary information corresponding to the entire
751 : * (new) free extent.
752 : */
753 5432682 : error = xfs_rtmodify_summary(mp, tp,
754 2716341 : XFS_RTBLOCKLOG(postblock + 1 - preblock),
755 2716341 : XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
756 2716341 : return error;
757 : }
758 :
759 : /*
760 : * Check that the given range is either all allocated (val = 0) or
761 : * all free (val = 1).
762 : */
763 : int
764 298738914 : xfs_rtcheck_range(
765 : xfs_mount_t *mp, /* file system mount point */
766 : xfs_trans_t *tp, /* transaction pointer */
767 : xfs_rtblock_t start, /* starting block number of extent */
768 : xfs_extlen_t len, /* length of extent */
769 : int val, /* 1 for free, 0 for allocated */
770 : xfs_rtblock_t *new, /* out: first block not matching */
771 : int *stat) /* out: 1 for matches, 0 for not */
772 : {
773 298738914 : xfs_rtword_t *b; /* current word in buffer */
774 298738914 : int bit; /* bit number in the word */
775 298738914 : xfs_rtblock_t block; /* bitmap block number */
776 298738914 : struct xfs_buf *bp; /* buf for the block */
777 298738914 : xfs_rtword_t *bufp; /* starting word in buffer */
778 298738914 : int error; /* error value */
779 298738914 : xfs_rtblock_t i; /* current bit number rel. to start */
780 298738914 : xfs_rtblock_t lastbit; /* last useful bit in word */
781 298738914 : xfs_rtword_t mask; /* mask of relevant bits for value */
782 298738914 : xfs_rtword_t wdiff; /* difference from wanted value */
783 298738914 : int word; /* word number in the buffer */
784 :
785 : /*
786 : * Compute starting bitmap block number
787 : */
788 298738914 : block = XFS_BITTOBLOCK(mp, start);
789 : /*
790 : * Read the bitmap block.
791 : */
792 298738914 : error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
793 298737703 : if (error) {
794 : return error;
795 : }
796 298737703 : bufp = bp->b_addr;
797 : /*
798 : * Compute the starting word's address, and starting bit.
799 : */
800 298737703 : word = XFS_BITTOWORD(mp, start);
801 298737703 : b = &bufp[word];
802 298737703 : bit = (int)(start & (XFS_NBWORD - 1));
803 : /*
804 : * 0 (allocated) => all zero's; 1 (free) => all one's.
805 : */
806 298737703 : val = -val;
807 : /*
808 : * If not starting on a word boundary, deal with the first
809 : * (partial) word.
810 : */
811 298737703 : if (bit) {
812 : /*
813 : * Compute first bit not examined.
814 : */
815 275667195 : lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
816 : /*
817 : * Mask of relevant bits.
818 : */
819 275667195 : mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
820 : /*
821 : * Compute difference between actual and desired value.
822 : */
823 275667195 : if ((wdiff = (*b ^ val) & mask)) {
824 : /*
825 : * Different, compute first wrong bit and return.
826 : */
827 230095358 : xfs_trans_brelse(tp, bp);
828 230104962 : i = XFS_RTLOBIT(wdiff) - bit;
829 230104962 : *new = start + i;
830 230104962 : *stat = 0;
831 230104962 : return 0;
832 : }
833 45571837 : i = lastbit - bit;
834 : /*
835 : * Go on to next block if that's where the next word is
836 : * and we need the next word.
837 : */
838 45571837 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
839 : /*
840 : * If done with this block, get the next one.
841 : */
842 5966 : xfs_trans_brelse(tp, bp);
843 5966 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
844 5966 : if (error) {
845 : return error;
846 : }
847 5966 : b = bufp = bp->b_addr;
848 5966 : word = 0;
849 : } else {
850 : /*
851 : * Go on to the next word in the buffer.
852 : */
853 45565871 : b++;
854 : }
855 : } else {
856 : /*
857 : * Starting on a word boundary, no partial word.
858 : */
859 : i = 0;
860 : }
861 : /*
862 : * Loop over whole words in buffers. When we use up one buffer
863 : * we move on to the next one.
864 : */
865 71122061 : while (len - i >= XFS_NBWORD) {
866 : /*
867 : * Compute difference between actual and desired value.
868 : */
869 7505312 : if ((wdiff = *b ^ val)) {
870 : /*
871 : * Different, compute first wrong bit and return.
872 : */
873 5025599 : xfs_trans_brelse(tp, bp);
874 5025599 : i += XFS_RTLOBIT(wdiff);
875 5025599 : *new = start + i;
876 5025599 : *stat = 0;
877 5025599 : return 0;
878 : }
879 2479713 : i += XFS_NBWORD;
880 : /*
881 : * Go on to next block if that's where the next word is
882 : * and we need the next word.
883 : */
884 2479713 : if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
885 : /*
886 : * If done with this block, get the next one.
887 : */
888 1915 : xfs_trans_brelse(tp, bp);
889 1918 : error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
890 1918 : if (error) {
891 0 : return error;
892 : }
893 1918 : b = bufp = bp->b_addr;
894 1918 : word = 0;
895 : } else {
896 : /*
897 : * Go on to the next word in the buffer.
898 : */
899 2477798 : b++;
900 : }
901 : }
902 : /*
903 : * If not ending on a word boundary, deal with the last
904 : * (partial) word.
905 : */
906 63616749 : if ((lastbit = len - i)) {
907 : /*
908 : * Mask of relevant bits.
909 : */
910 25474351 : mask = ((xfs_rtword_t)1 << lastbit) - 1;
911 : /*
912 : * Compute difference between actual and desired value.
913 : */
914 25474351 : if ((wdiff = (*b ^ val) & mask)) {
915 : /*
916 : * Different, compute first wrong bit and return.
917 : */
918 20330177 : xfs_trans_brelse(tp, bp);
919 20330187 : i += XFS_RTLOBIT(wdiff);
920 20330187 : *new = start + i;
921 20330187 : *stat = 0;
922 20330187 : return 0;
923 : } else
924 : i = len;
925 : }
926 : /*
927 : * Successful, return.
928 : */
929 43286572 : xfs_trans_brelse(tp, bp);
930 43286571 : *new = start + i;
931 43286571 : *stat = 1;
932 43286571 : return 0;
933 : }
934 :
935 : #ifdef DEBUG
936 : /*
937 : * Check that the given extent (block range) is allocated already.
938 : */
939 : STATIC int /* error */
940 2716336 : xfs_rtcheck_alloc_range(
941 : xfs_mount_t *mp, /* file system mount point */
942 : xfs_trans_t *tp, /* transaction pointer */
943 : xfs_rtblock_t bno, /* starting block number of extent */
944 : xfs_extlen_t len) /* length of extent */
945 : {
946 2716336 : xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
947 2716336 : int stat;
948 2716336 : int error;
949 :
950 2716336 : error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
951 2716336 : if (error)
952 : return error;
953 2716336 : ASSERT(stat);
954 : return 0;
955 : }
956 : #else
957 : #define xfs_rtcheck_alloc_range(m,t,b,l) (0)
958 : #endif
959 : /*
960 : * Free an extent in the realtime subvolume. Length is expressed in
961 : * realtime extents, as is the block number.
962 : */
963 : int /* error */
964 2716336 : xfs_rtfree_extent(
965 : xfs_trans_t *tp, /* transaction pointer */
966 : xfs_rtblock_t bno, /* starting block number to free */
967 : xfs_extlen_t len) /* length of extent freed */
968 : {
969 2716336 : int error; /* error value */
970 2716336 : xfs_mount_t *mp; /* file system mount structure */
971 2716336 : xfs_fsblock_t sb; /* summary file block number */
972 2716336 : struct xfs_buf *sumbp = NULL; /* summary file block buffer */
973 :
974 2716336 : mp = tp->t_mountp;
975 :
976 2716336 : ASSERT(mp->m_rbmip->i_itemp != NULL);
977 2716336 : ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
978 :
979 2716336 : error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
980 2716336 : if (error)
981 : return error;
982 :
983 : /*
984 : * Free the range of realtime blocks.
985 : */
986 2716336 : error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
987 2716336 : if (error) {
988 : return error;
989 : }
990 : /*
991 : * Mark more blocks free in the superblock.
992 : */
993 2716336 : xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
994 : /*
995 : * If we've now freed all the blocks, reset the file sequence
996 : * number to 0.
997 : */
998 2716336 : if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
999 2716336 : mp->m_sb.sb_rextents) {
1000 1146 : if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM))
1001 0 : mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
1002 1146 : *(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
1003 1146 : xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
1004 : }
1005 : return 0;
1006 : }
1007 :
1008 : /* Find all the free records within a given range. */
1009 : int
1010 276317 : xfs_rtalloc_query_range(
1011 : struct xfs_mount *mp,
1012 : struct xfs_trans *tp,
1013 : const struct xfs_rtalloc_rec *low_rec,
1014 : const struct xfs_rtalloc_rec *high_rec,
1015 : xfs_rtalloc_query_range_fn fn,
1016 : void *priv)
1017 : {
1018 276317 : struct xfs_rtalloc_rec rec;
1019 276317 : xfs_rtblock_t rtstart;
1020 276317 : xfs_rtblock_t rtend;
1021 276317 : xfs_rtblock_t high_key;
1022 276317 : int is_free;
1023 276317 : int error = 0;
1024 :
1025 276317 : if (low_rec->ar_startext > high_rec->ar_startext)
1026 : return -EINVAL;
1027 276317 : if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1028 : low_rec->ar_startext == high_rec->ar_startext)
1029 : return 0;
1030 :
1031 276317 : high_key = min(high_rec->ar_startext, mp->m_sb.sb_rextents - 1);
1032 :
1033 : /* Iterate the bitmap, looking for discrepancies. */
1034 276317 : rtstart = low_rec->ar_startext;
1035 70749453 : while (rtstart <= high_key) {
1036 : /* Is the first block free? */
1037 70473576 : error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1038 : &is_free);
1039 70473576 : if (error)
1040 : break;
1041 :
1042 : /* How long does the extent go for? */
1043 70473576 : error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &rtend);
1044 70473576 : if (error)
1045 : break;
1046 :
1047 70473576 : if (is_free) {
1048 35306260 : rec.ar_startext = rtstart;
1049 35306260 : rec.ar_extcount = rtend - rtstart + 1;
1050 :
1051 35306260 : error = fn(mp, tp, &rec, priv);
1052 35306260 : if (error)
1053 : break;
1054 : }
1055 :
1056 70473136 : rtstart = rtend + 1;
1057 : }
1058 :
1059 : return error;
1060 : }
1061 :
1062 : /* Find all the free records. */
1063 : int
1064 226107 : xfs_rtalloc_query_all(
1065 : struct xfs_mount *mp,
1066 : struct xfs_trans *tp,
1067 : xfs_rtalloc_query_range_fn fn,
1068 : void *priv)
1069 : {
1070 226107 : struct xfs_rtalloc_rec keys[2];
1071 :
1072 226107 : keys[0].ar_startext = 0;
1073 226107 : keys[1].ar_startext = mp->m_sb.sb_rextents - 1;
1074 226107 : keys[0].ar_extcount = keys[1].ar_extcount = 0;
1075 :
1076 226107 : return xfs_rtalloc_query_range(mp, tp, &keys[0], &keys[1], fn, priv);
1077 : }
1078 :
1079 : /* Is the given extent all free? */
1080 : int
1081 163561986 : xfs_rtalloc_extent_is_free(
1082 : struct xfs_mount *mp,
1083 : struct xfs_trans *tp,
1084 : xfs_rtblock_t start,
1085 : xfs_extlen_t len,
1086 : bool *is_free)
1087 : {
1088 163561986 : xfs_rtblock_t end;
1089 163561986 : int matches;
1090 163561986 : int error;
1091 :
1092 163561986 : error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1093 163567970 : if (error)
1094 : return error;
1095 :
1096 163567970 : *is_free = matches;
1097 163567970 : return 0;
1098 : }
|