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