~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_rtbitmap.c

Version: ~ [ linux-5.9 ] ~ [ linux-5.8.14 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.70 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.150 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.200 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.238 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.238 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 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 xfs_rtbuf_verify_read(
 31         struct xfs_buf  *bp)
 32 {
 33         return;
 34 }
 35 
 36 static void
 37 xfs_rtbuf_verify_write(
 38         struct xfs_buf  *bp)
 39 {
 40         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 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         xfs_buf_t       **bpp)          /* output: buffer for the block */
 60 {
 61         xfs_buf_t       *bp;            /* block buffer, result */
 62         xfs_inode_t     *ip;            /* bitmap or summary inode */
 63         xfs_bmbt_irec_t map;
 64         int             nmap = 1;
 65         int             error;          /* error value */
 66 
 67         ip = issum ? mp->m_rsumip : mp->m_rbmip;
 68 
 69         error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
 70         if (error)
 71                 return error;
 72 
 73         if (nmap == 0 || !xfs_bmap_is_real_extent(&map))
 74                 return -EFSCORRUPTED;
 75 
 76         ASSERT(map.br_startblock != NULLFSBLOCK);
 77         error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 78                                    XFS_FSB_TO_DADDR(mp, map.br_startblock),
 79                                    mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
 80         if (error)
 81                 return error;
 82 
 83         xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
 84                                              : XFS_BLFT_RTBITMAP_BUF);
 85         *bpp = bp;
 86         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 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         xfs_rtword_t    *b;             /* current word in buffer */
102         int             bit;            /* bit number in the word */
103         xfs_rtblock_t   block;          /* bitmap block number */
104         xfs_buf_t       *bp;            /* buf for the block */
105         xfs_rtword_t    *bufp;          /* starting word in buffer */
106         int             error;          /* error value */
107         xfs_rtblock_t   firstbit;       /* first useful bit in the word */
108         xfs_rtblock_t   i;              /* current bit number rel. to start */
109         xfs_rtblock_t   len;            /* length of inspected area */
110         xfs_rtword_t    mask;           /* mask of relevant bits for value */
111         xfs_rtword_t    want;           /* mask for "good" values */
112         xfs_rtword_t    wdiff;          /* difference from wanted value */
113         int             word;           /* word number in the buffer */
114 
115         /*
116          * Compute and read in starting bitmap block for starting block.
117          */
118         block = XFS_BITTOBLOCK(mp, start);
119         error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
120         if (error) {
121                 return error;
122         }
123         bufp = bp->b_addr;
124         /*
125          * Get the first word's index & point to it.
126          */
127         word = XFS_BITTOWORD(mp, start);
128         b = &bufp[word];
129         bit = (int)(start & (XFS_NBWORD - 1));
130         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         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         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                 firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
146                 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                 if ((wdiff = (*b ^ want) & mask)) {
153                         /*
154                          * Different.  Mark where we are and return.
155                          */
156                         xfs_trans_brelse(tp, bp);
157                         i = bit - XFS_RTHIBIT(wdiff);
158                         *rtblock = start - i + 1;
159                         return 0;
160                 }
161                 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                 if (--word == -1 && i < len) {
167                         /*
168                          * If done with this block, get the previous one.
169                          */
170                         xfs_trans_brelse(tp, bp);
171                         error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
172                         if (error) {
173                                 return error;
174                         }
175                         bufp = bp->b_addr;
176                         word = XFS_BLOCKWMASK(mp);
177                         b = &bufp[word];
178                 } else {
179                         /*
180                          * Go on to the previous word in the buffer.
181                          */
182                         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         while (len - i >= XFS_NBWORD) {
195                 /*
196                  * Compute difference between actual and desired value.
197                  */
198                 if ((wdiff = *b ^ want)) {
199                         /*
200                          * Different, mark where we are and return.
201                          */
202                         xfs_trans_brelse(tp, bp);
203                         i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
204                         *rtblock = start - i + 1;
205                         return 0;
206                 }
207                 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                 if (--word == -1 && i < len) {
213                         /*
214                          * If done with this block, get the previous one.
215                          */
216                         xfs_trans_brelse(tp, bp);
217                         error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
218                         if (error) {
219                                 return error;
220                         }
221                         bufp = bp->b_addr;
222                         word = XFS_BLOCKWMASK(mp);
223                         b = &bufp[word];
224                 } else {
225                         /*
226                          * Go on to the previous word in the buffer.
227                          */
228                         b--;
229                 }
230         }
231         /*
232          * If not ending on a word boundary, deal with the last
233          * (partial) word.
234          */
235         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                 firstbit = XFS_NBWORD - (len - i);
241                 mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
242                 /*
243                  * Compute difference between actual and desired value.
244                  */
245                 if ((wdiff = (*b ^ want) & mask)) {
246                         /*
247                          * Different, mark where we are and return.
248                          */
249                         xfs_trans_brelse(tp, bp);
250                         i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
251                         *rtblock = start - i + 1;
252                         return 0;
253                 } else
254                         i = len;
255         }
256         /*
257          * No match, return that we scanned the whole area.
258          */
259         xfs_trans_brelse(tp, bp);
260         *rtblock = start - i + 1;
261         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 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         xfs_rtword_t    *b;             /* current word in buffer */
277         int             bit;            /* bit number in the word */
278         xfs_rtblock_t   block;          /* bitmap block number */
279         xfs_buf_t       *bp;            /* buf for the block */
280         xfs_rtword_t    *bufp;          /* starting word in buffer */
281         int             error;          /* error value */
282         xfs_rtblock_t   i;              /* current bit number rel. to start */
283         xfs_rtblock_t   lastbit;        /* last useful bit in the word */
284         xfs_rtblock_t   len;            /* length of inspected area */
285         xfs_rtword_t    mask;           /* mask of relevant bits for value */
286         xfs_rtword_t    want;           /* mask for "good" values */
287         xfs_rtword_t    wdiff;          /* difference from wanted value */
288         int             word;           /* word number in the buffer */
289 
290         /*
291          * Compute and read in starting bitmap block for starting block.
292          */
293         block = XFS_BITTOBLOCK(mp, start);
294         error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
295         if (error) {
296                 return error;
297         }
298         bufp = bp->b_addr;
299         /*
300          * Get the first word's index & point to it.
301          */
302         word = XFS_BITTOWORD(mp, start);
303         b = &bufp[word];
304         bit = (int)(start & (XFS_NBWORD - 1));
305         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         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         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                 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
321                 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                 if ((wdiff = (*b ^ want) & mask)) {
327                         /*
328                          * Different.  Mark where we are and return.
329                          */
330                         xfs_trans_brelse(tp, bp);
331                         i = XFS_RTLOBIT(wdiff) - bit;
332                         *rtblock = start + i - 1;
333                         return 0;
334                 }
335                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
341                         /*
342                          * If done with this block, get the previous one.
343                          */
344                         xfs_trans_brelse(tp, bp);
345                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
346                         if (error) {
347                                 return error;
348                         }
349                         b = bufp = bp->b_addr;
350                         word = 0;
351                 } else {
352                         /*
353                          * Go on to the previous word in the buffer.
354                          */
355                         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         while (len - i >= XFS_NBWORD) {
368                 /*
369                  * Compute difference between actual and desired value.
370                  */
371                 if ((wdiff = *b ^ want)) {
372                         /*
373                          * Different, mark where we are and return.
374                          */
375                         xfs_trans_brelse(tp, bp);
376                         i += XFS_RTLOBIT(wdiff);
377                         *rtblock = start + i - 1;
378                         return 0;
379                 }
380                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
386                         /*
387                          * If done with this block, get the next one.
388                          */
389                         xfs_trans_brelse(tp, bp);
390                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
391                         if (error) {
392                                 return error;
393                         }
394                         b = bufp = bp->b_addr;
395                         word = 0;
396                 } else {
397                         /*
398                          * Go on to the next word in the buffer.
399                          */
400                         b++;
401                 }
402         }
403         /*
404          * If not ending on a word boundary, deal with the last
405          * (partial) word.
406          */
407         if ((lastbit = len - i)) {
408                 /*
409                  * Calculate mask for all the relevant bits in this word.
410                  */
411                 mask = ((xfs_rtword_t)1 << lastbit) - 1;
412                 /*
413                  * Compute difference between actual and desired value.
414                  */
415                 if ((wdiff = (*b ^ want) & mask)) {
416                         /*
417                          * Different, mark where we are and return.
418                          */
419                         xfs_trans_brelse(tp, bp);
420                         i += XFS_RTLOBIT(wdiff);
421                         *rtblock = start + i - 1;
422                         return 0;
423                 } else
424                         i = len;
425         }
426         /*
427          * No match, return that we scanned the whole area.
428          */
429         xfs_trans_brelse(tp, bp);
430         *rtblock = start + i - 1;
431         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 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         xfs_buf_t       **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         xfs_buf_t       *bp;            /* buffer for the summary block */
455         int             error;          /* error value */
456         xfs_fsblock_t   sb;             /* summary fsblock */
457         int             so;             /* index into the summary file */
458         xfs_suminfo_t   *sp;            /* pointer to returned data */
459 
460         /*
461          * Compute entry number in the summary file.
462          */
463         so = XFS_SUMOFFS(mp, log, bbno);
464         /*
465          * Compute the block number in the summary file.
466          */
467         sb = XFS_SUMOFFSTOBLOCK(mp, so);
468         /*
469          * If we have an old buffer, and the block number matches, use that.
470          */
471         if (*rbpp && *rsb == sb)
472                 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                 if (*rbpp)
481                         xfs_trans_brelse(tp, *rbpp);
482                 error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
483                 if (error) {
484                         return error;
485                 }
486                 /*
487                  * Remember this buffer and block for the next call.
488                  */
489                 *rbpp = bp;
490                 *rsb = sb;
491         }
492         /*
493          * Point to the summary information, modify/log it, and/or copy it out.
494          */
495         sp = XFS_SUMPTR(mp, bp, so);
496         if (delta) {
497                 uint first = (uint)((char *)sp - (char *)bp->b_addr);
498 
499                 *sp += delta;
500                 if (mp->m_rsum_cache) {
501                         if (*sp == 0 && log == mp->m_rsum_cache[bbno])
502                                 mp->m_rsum_cache[bbno]++;
503                         if (*sp != 0 && log < mp->m_rsum_cache[bbno])
504                                 mp->m_rsum_cache[bbno] = log;
505                 }
506                 xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
507         }
508         if (sum)
509                 *sum = *sp;
510         return 0;
511 }
512 
513 int
514 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         xfs_buf_t       **rbpp,         /* in/out: summary block buffer */
521         xfs_fsblock_t   *rsb)           /* in/out: summary block number */
522 {
523         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 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         xfs_rtword_t    *b;             /* current word in buffer */
540         int             bit;            /* bit number in the word */
541         xfs_rtblock_t   block;          /* bitmap block number */
542         xfs_buf_t       *bp;            /* buf for the block */
543         xfs_rtword_t    *bufp;          /* starting word in buffer */
544         int             error;          /* error value */
545         xfs_rtword_t    *first;         /* first used word in the buffer */
546         int             i;              /* current bit number rel. to start */
547         int             lastbit;        /* last useful bit in word */
548         xfs_rtword_t    mask;           /* mask o frelevant bits for value */
549         int             word;           /* word number in the buffer */
550 
551         /*
552          * Compute starting bitmap block number.
553          */
554         block = XFS_BITTOBLOCK(mp, start);
555         /*
556          * Read the bitmap block, and point to its data.
557          */
558         error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
559         if (error) {
560                 return error;
561         }
562         bufp = bp->b_addr;
563         /*
564          * Compute the starting word's address, and starting bit.
565          */
566         word = XFS_BITTOWORD(mp, start);
567         first = b = &bufp[word];
568         bit = (int)(start & (XFS_NBWORD - 1));
569         /*
570          * 0 (allocated) => all zeroes; 1 (free) => all ones.
571          */
572         val = -val;
573         /*
574          * If not starting on a word boundary, deal with the first
575          * (partial) word.
576          */
577         if (bit) {
578                 /*
579                  * Compute first bit not changed and mask of relevant bits.
580                  */
581                 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
582                 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
583                 /*
584                  * Set/clear the active bits.
585                  */
586                 if (val)
587                         *b |= mask;
588                 else
589                         *b &= ~mask;
590                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
596                         /*
597                          * Log the changed part of this block.
598                          * Get the next one.
599                          */
600                         xfs_trans_log_buf(tp, bp,
601                                 (uint)((char *)first - (char *)bufp),
602                                 (uint)((char *)b - (char *)bufp));
603                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
604                         if (error) {
605                                 return error;
606                         }
607                         first = b = bufp = bp->b_addr;
608                         word = 0;
609                 } else {
610                         /*
611                          * Go on to the next word in the buffer
612                          */
613                         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         while (len - i >= XFS_NBWORD) {
626                 /*
627                  * Set the word value correctly.
628                  */
629                 *b = val;
630                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
636                         /*
637                          * Log the changed part of this block.
638                          * Get the next one.
639                          */
640                         xfs_trans_log_buf(tp, bp,
641                                 (uint)((char *)first - (char *)bufp),
642                                 (uint)((char *)b - (char *)bufp));
643                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
644                         if (error) {
645                                 return error;
646                         }
647                         first = b = bufp = bp->b_addr;
648                         word = 0;
649                 } else {
650                         /*
651                          * Go on to the next word in the buffer
652                          */
653                         b++;
654                 }
655         }
656         /*
657          * If not ending on a word boundary, deal with the last
658          * (partial) word.
659          */
660         if ((lastbit = len - i)) {
661                 /*
662                  * Compute a mask of relevant bits.
663                  */
664                 mask = ((xfs_rtword_t)1 << lastbit) - 1;
665                 /*
666                  * Set/clear the active bits.
667                  */
668                 if (val)
669                         *b |= mask;
670                 else
671                         *b &= ~mask;
672                 b++;
673         }
674         /*
675          * Log any remaining changed bytes.
676          */
677         if (b > first)
678                 xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
679                         (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 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         xfs_buf_t       **rbpp,         /* in/out: summary block buffer */
694         xfs_fsblock_t   *rsb)           /* in/out: summary block number */
695 {
696         xfs_rtblock_t   end;            /* end of the freed extent */
697         int             error;          /* error value */
698         xfs_rtblock_t   postblock;      /* first block freed > end */
699         xfs_rtblock_t   preblock;       /* first block freed < start */
700 
701         end = start + len - 1;
702         /*
703          * Modify the bitmap to mark this extent freed.
704          */
705         error = xfs_rtmodify_range(mp, tp, start, len, 1);
706         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         error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
715         if (error) {
716                 return error;
717         }
718         /*
719          * Find the next allocated block (end of allocated extent).
720          */
721         error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
722                 &postblock);
723         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         if (preblock < start) {
730                 error = xfs_rtmodify_summary(mp, tp,
731                         XFS_RTBLOCKLOG(start - preblock),
732                         XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
733                 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         if (postblock > end) {
742                 error = xfs_rtmodify_summary(mp, tp,
743                         XFS_RTBLOCKLOG(postblock - end),
744                         XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
745                 if (error) {
746                         return error;
747                 }
748         }
749         /*
750          * Increment the summary information corresponding to the entire
751          * (new) free extent.
752          */
753         error = xfs_rtmodify_summary(mp, tp,
754                 XFS_RTBLOCKLOG(postblock + 1 - preblock),
755                 XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
756         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 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         xfs_rtword_t    *b;             /* current word in buffer */
774         int             bit;            /* bit number in the word */
775         xfs_rtblock_t   block;          /* bitmap block number */
776         xfs_buf_t       *bp;            /* buf for the block */
777         xfs_rtword_t    *bufp;          /* starting word in buffer */
778         int             error;          /* error value */
779         xfs_rtblock_t   i;              /* current bit number rel. to start */
780         xfs_rtblock_t   lastbit;        /* last useful bit in word */
781         xfs_rtword_t    mask;           /* mask of relevant bits for value */
782         xfs_rtword_t    wdiff;          /* difference from wanted value */
783         int             word;           /* word number in the buffer */
784 
785         /*
786          * Compute starting bitmap block number
787          */
788         block = XFS_BITTOBLOCK(mp, start);
789         /*
790          * Read the bitmap block.
791          */
792         error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
793         if (error) {
794                 return error;
795         }
796         bufp = bp->b_addr;
797         /*
798          * Compute the starting word's address, and starting bit.
799          */
800         word = XFS_BITTOWORD(mp, start);
801         b = &bufp[word];
802         bit = (int)(start & (XFS_NBWORD - 1));
803         /*
804          * 0 (allocated) => all zero's; 1 (free) => all one's.
805          */
806         val = -val;
807         /*
808          * If not starting on a word boundary, deal with the first
809          * (partial) word.
810          */
811         if (bit) {
812                 /*
813                  * Compute first bit not examined.
814                  */
815                 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
816                 /*
817                  * Mask of relevant bits.
818                  */
819                 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
820                 /*
821                  * Compute difference between actual and desired value.
822                  */
823                 if ((wdiff = (*b ^ val) & mask)) {
824                         /*
825                          * Different, compute first wrong bit and return.
826                          */
827                         xfs_trans_brelse(tp, bp);
828                         i = XFS_RTLOBIT(wdiff) - bit;
829                         *new = start + i;
830                         *stat = 0;
831                         return 0;
832                 }
833                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
839                         /*
840                          * If done with this block, get the next one.
841                          */
842                         xfs_trans_brelse(tp, bp);
843                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
844                         if (error) {
845                                 return error;
846                         }
847                         b = bufp = bp->b_addr;
848                         word = 0;
849                 } else {
850                         /*
851                          * Go on to the next word in the buffer.
852                          */
853                         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         while (len - i >= XFS_NBWORD) {
866                 /*
867                  * Compute difference between actual and desired value.
868                  */
869                 if ((wdiff = *b ^ val)) {
870                         /*
871                          * Different, compute first wrong bit and return.
872                          */
873                         xfs_trans_brelse(tp, bp);
874                         i += XFS_RTLOBIT(wdiff);
875                         *new = start + i;
876                         *stat = 0;
877                         return 0;
878                 }
879                 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                 if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
885                         /*
886                          * If done with this block, get the next one.
887                          */
888                         xfs_trans_brelse(tp, bp);
889                         error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
890                         if (error) {
891                                 return error;
892                         }
893                         b = bufp = bp->b_addr;
894                         word = 0;
895                 } else {
896                         /*
897                          * Go on to the next word in the buffer.
898                          */
899                         b++;
900                 }
901         }
902         /*
903          * If not ending on a word boundary, deal with the last
904          * (partial) word.
905          */
906         if ((lastbit = len - i)) {
907                 /*
908                  * Mask of relevant bits.
909                  */
910                 mask = ((xfs_rtword_t)1 << lastbit) - 1;
911                 /*
912                  * Compute difference between actual and desired value.
913                  */
914                 if ((wdiff = (*b ^ val) & mask)) {
915                         /*
916                          * Different, compute first wrong bit and return.
917                          */
918                         xfs_trans_brelse(tp, bp);
919                         i += XFS_RTLOBIT(wdiff);
920                         *new = start + i;
921                         *stat = 0;
922                         return 0;
923                 } else
924                         i = len;
925         }
926         /*
927          * Successful, return.
928          */
929         xfs_trans_brelse(tp, bp);
930         *new = start + i;
931         *stat = 1;
932         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 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         xfs_rtblock_t   new;            /* dummy for xfs_rtcheck_range */
947         int             stat;
948         int             error;
949 
950         error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
951         if (error)
952                 return error;
953         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 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         int             error;          /* error value */
970         xfs_mount_t     *mp;            /* file system mount structure */
971         xfs_fsblock_t   sb;             /* summary file block number */
972         xfs_buf_t       *sumbp = NULL;  /* summary file block buffer */
973 
974         mp = tp->t_mountp;
975 
976         ASSERT(mp->m_rbmip->i_itemp != NULL);
977         ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
978 
979         error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
980         if (error)
981                 return error;
982 
983         /*
984          * Free the range of realtime blocks.
985          */
986         error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
987         if (error) {
988                 return error;
989         }
990         /*
991          * Mark more blocks free in the superblock.
992          */
993         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         if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
999             mp->m_sb.sb_rextents) {
1000                 if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
1001                         mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
1002                 *(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
1003                 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 xfs_rtalloc_query_range(
1011         struct xfs_trans                *tp,
1012         struct xfs_rtalloc_rec          *low_rec,
1013         struct xfs_rtalloc_rec          *high_rec,
1014         xfs_rtalloc_query_range_fn      fn,
1015         void                            *priv)
1016 {
1017         struct xfs_rtalloc_rec          rec;
1018         struct xfs_mount                *mp = tp->t_mountp;
1019         xfs_rtblock_t                   rtstart;
1020         xfs_rtblock_t                   rtend;
1021         xfs_rtblock_t                   rem;
1022         int                             is_free;
1023         int                             error = 0;
1024 
1025         if (low_rec->ar_startext > high_rec->ar_startext)
1026                 return -EINVAL;
1027         if (low_rec->ar_startext >= mp->m_sb.sb_rextents ||
1028             low_rec->ar_startext == high_rec->ar_startext)
1029                 return 0;
1030         if (high_rec->ar_startext > mp->m_sb.sb_rextents)
1031                 high_rec->ar_startext = mp->m_sb.sb_rextents;
1032 
1033         /* Iterate the bitmap, looking for discrepancies. */
1034         rtstart = low_rec->ar_startext;
1035         rem = high_rec->ar_startext - rtstart;
1036         while (rem) {
1037                 /* Is the first block free? */
1038                 error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend,
1039                                 &is_free);
1040                 if (error)
1041                         break;
1042 
1043                 /* How long does the extent go for? */
1044                 error = xfs_rtfind_forw(mp, tp, rtstart,
1045                                 high_rec->ar_startext - 1, &rtend);
1046                 if (error)
1047                         break;
1048 
1049                 if (is_free) {
1050                         rec.ar_startext = rtstart;
1051                         rec.ar_extcount = rtend - rtstart + 1;
1052 
1053                         error = fn(tp, &rec, priv);
1054                         if (error)
1055                                 break;
1056                 }
1057 
1058                 rem -= rtend - rtstart + 1;
1059                 rtstart = rtend + 1;
1060         }
1061 
1062         return error;
1063 }
1064 
1065 /* Find all the free records. */
1066 int
1067 xfs_rtalloc_query_all(
1068         struct xfs_trans                *tp,
1069         xfs_rtalloc_query_range_fn      fn,
1070         void                            *priv)
1071 {
1072         struct xfs_rtalloc_rec          keys[2];
1073 
1074         keys[0].ar_startext = 0;
1075         keys[1].ar_startext = tp->t_mountp->m_sb.sb_rextents - 1;
1076         keys[0].ar_extcount = keys[1].ar_extcount = 0;
1077 
1078         return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
1079 }
1080 
1081 /* Is the given extent all free? */
1082 int
1083 xfs_rtalloc_extent_is_free(
1084         struct xfs_mount                *mp,
1085         struct xfs_trans                *tp,
1086         xfs_rtblock_t                   start,
1087         xfs_extlen_t                    len,
1088         bool                            *is_free)
1089 {
1090         xfs_rtblock_t                   end;
1091         int                             matches;
1092         int                             error;
1093 
1094         error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches);
1095         if (error)
1096                 return error;
1097 
1098         *is_free = matches;
1099         return 0;
1100 }
1101 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp