xfs_rtbitmap.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. /*
  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"
  25. #include "xfs_sb.h"
  26. #include "xfs_ag.h"
  27. #include "xfs_mount.h"
  28. #include "xfs_inode.h"
  29. #include "xfs_bmap.h"
  30. #include "xfs_bmap_util.h"
  31. #include "xfs_bmap_btree.h"
  32. #include "xfs_alloc.h"
  33. #include "xfs_error.h"
  34. #include "xfs_trans.h"
  35. #include "xfs_trans_space.h"
  36. #include "xfs_trace.h"
  37. #include "xfs_buf.h"
  38. #include "xfs_icache.h"
  39. #include "xfs_dinode.h"
  40. /*
  41. * Realtime allocator bitmap functions shared with userspace.
  42. */
  43. /*
  44. * Get a buffer for the bitmap or summary file block specified.
  45. * The buffer is returned read and locked.
  46. */
  47. int
  48. xfs_rtbuf_get(
  49. xfs_mount_t *mp, /* file system mount structure */
  50. xfs_trans_t *tp, /* transaction pointer */
  51. xfs_rtblock_t block, /* block number in bitmap or summary */
  52. int issum, /* is summary not bitmap */
  53. xfs_buf_t **bpp) /* output: buffer for the block */
  54. {
  55. xfs_buf_t *bp; /* block buffer, result */
  56. xfs_inode_t *ip; /* bitmap or summary inode */
  57. xfs_bmbt_irec_t map;
  58. int nmap = 1;
  59. int error; /* error value */
  60. ip = issum ? mp->m_rsumip : mp->m_rbmip;
  61. error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
  62. if (error)
  63. return error;
  64. ASSERT(map.br_startblock != NULLFSBLOCK);
  65. error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
  66. XFS_FSB_TO_DADDR(mp, map.br_startblock),
  67. mp->m_bsize, 0, &bp, NULL);
  68. if (error)
  69. return error;
  70. ASSERT(!xfs_buf_geterror(bp));
  71. *bpp = bp;
  72. return 0;
  73. }
  74. /*
  75. * Searching backward from start to limit, find the first block whose
  76. * allocated/free state is different from start's.
  77. */
  78. int
  79. xfs_rtfind_back(
  80. xfs_mount_t *mp, /* file system mount point */
  81. xfs_trans_t *tp, /* transaction pointer */
  82. xfs_rtblock_t start, /* starting block to look at */
  83. xfs_rtblock_t limit, /* last block to look at */
  84. xfs_rtblock_t *rtblock) /* out: start block found */
  85. {
  86. xfs_rtword_t *b; /* current word in buffer */
  87. int bit; /* bit number in the word */
  88. xfs_rtblock_t block; /* bitmap block number */
  89. xfs_buf_t *bp; /* buf for the block */
  90. xfs_rtword_t *bufp; /* starting word in buffer */
  91. int error; /* error value */
  92. xfs_rtblock_t firstbit; /* first useful bit in the word */
  93. xfs_rtblock_t i; /* current bit number rel. to start */
  94. xfs_rtblock_t len; /* length of inspected area */
  95. xfs_rtword_t mask; /* mask of relevant bits for value */
  96. xfs_rtword_t want; /* mask for "good" values */
  97. xfs_rtword_t wdiff; /* difference from wanted value */
  98. int word; /* word number in the buffer */
  99. /*
  100. * Compute and read in starting bitmap block for starting block.
  101. */
  102. block = XFS_BITTOBLOCK(mp, start);
  103. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  104. if (error) {
  105. return error;
  106. }
  107. bufp = bp->b_addr;
  108. /*
  109. * Get the first word's index & point to it.
  110. */
  111. word = XFS_BITTOWORD(mp, start);
  112. b = &bufp[word];
  113. bit = (int)(start & (XFS_NBWORD - 1));
  114. len = start - limit + 1;
  115. /*
  116. * Compute match value, based on the bit at start: if 1 (free)
  117. * then all-ones, else all-zeroes.
  118. */
  119. want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
  120. /*
  121. * If the starting position is not word-aligned, deal with the
  122. * partial word.
  123. */
  124. if (bit < XFS_NBWORD - 1) {
  125. /*
  126. * Calculate first (leftmost) bit number to look at,
  127. * and mask for all the relevant bits in this word.
  128. */
  129. firstbit = XFS_RTMAX((xfs_srtblock_t)(bit - len + 1), 0);
  130. mask = (((xfs_rtword_t)1 << (bit - firstbit + 1)) - 1) <<
  131. firstbit;
  132. /*
  133. * Calculate the difference between the value there
  134. * and what we're looking for.
  135. */
  136. if ((wdiff = (*b ^ want) & mask)) {
  137. /*
  138. * Different. Mark where we are and return.
  139. */
  140. xfs_trans_brelse(tp, bp);
  141. i = bit - XFS_RTHIBIT(wdiff);
  142. *rtblock = start - i + 1;
  143. return 0;
  144. }
  145. i = bit - firstbit + 1;
  146. /*
  147. * Go on to previous block if that's where the previous word is
  148. * and we need the previous word.
  149. */
  150. if (--word == -1 && i < len) {
  151. /*
  152. * If done with this block, get the previous one.
  153. */
  154. xfs_trans_brelse(tp, bp);
  155. error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
  156. if (error) {
  157. return error;
  158. }
  159. bufp = bp->b_addr;
  160. word = XFS_BLOCKWMASK(mp);
  161. b = &bufp[word];
  162. } else {
  163. /*
  164. * Go on to the previous word in the buffer.
  165. */
  166. b--;
  167. }
  168. } else {
  169. /*
  170. * Starting on a word boundary, no partial word.
  171. */
  172. i = 0;
  173. }
  174. /*
  175. * Loop over whole words in buffers. When we use up one buffer
  176. * we move on to the previous one.
  177. */
  178. while (len - i >= XFS_NBWORD) {
  179. /*
  180. * Compute difference between actual and desired value.
  181. */
  182. if ((wdiff = *b ^ want)) {
  183. /*
  184. * Different, mark where we are and return.
  185. */
  186. xfs_trans_brelse(tp, bp);
  187. i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
  188. *rtblock = start - i + 1;
  189. return 0;
  190. }
  191. i += XFS_NBWORD;
  192. /*
  193. * Go on to previous block if that's where the previous word is
  194. * and we need the previous word.
  195. */
  196. if (--word == -1 && i < len) {
  197. /*
  198. * If done with this block, get the previous one.
  199. */
  200. xfs_trans_brelse(tp, bp);
  201. error = xfs_rtbuf_get(mp, tp, --block, 0, &bp);
  202. if (error) {
  203. return error;
  204. }
  205. bufp = bp->b_addr;
  206. word = XFS_BLOCKWMASK(mp);
  207. b = &bufp[word];
  208. } else {
  209. /*
  210. * Go on to the previous word in the buffer.
  211. */
  212. b--;
  213. }
  214. }
  215. /*
  216. * If not ending on a word boundary, deal with the last
  217. * (partial) word.
  218. */
  219. if (len - i) {
  220. /*
  221. * Calculate first (leftmost) bit number to look at,
  222. * and mask for all the relevant bits in this word.
  223. */
  224. firstbit = XFS_NBWORD - (len - i);
  225. mask = (((xfs_rtword_t)1 << (len - i)) - 1) << firstbit;
  226. /*
  227. * Compute difference between actual and desired value.
  228. */
  229. if ((wdiff = (*b ^ want) & mask)) {
  230. /*
  231. * Different, mark where we are and return.
  232. */
  233. xfs_trans_brelse(tp, bp);
  234. i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
  235. *rtblock = start - i + 1;
  236. return 0;
  237. } else
  238. i = len;
  239. }
  240. /*
  241. * No match, return that we scanned the whole area.
  242. */
  243. xfs_trans_brelse(tp, bp);
  244. *rtblock = start - i + 1;
  245. return 0;
  246. }
  247. /*
  248. * Searching forward from start to limit, find the first block whose
  249. * allocated/free state is different from start's.
  250. */
  251. int
  252. xfs_rtfind_forw(
  253. xfs_mount_t *mp, /* file system mount point */
  254. xfs_trans_t *tp, /* transaction pointer */
  255. xfs_rtblock_t start, /* starting block to look at */
  256. xfs_rtblock_t limit, /* last block to look at */
  257. xfs_rtblock_t *rtblock) /* out: start block found */
  258. {
  259. xfs_rtword_t *b; /* current word in buffer */
  260. int bit; /* bit number in the word */
  261. xfs_rtblock_t block; /* bitmap block number */
  262. xfs_buf_t *bp; /* buf for the block */
  263. xfs_rtword_t *bufp; /* starting word in buffer */
  264. int error; /* error value */
  265. xfs_rtblock_t i; /* current bit number rel. to start */
  266. xfs_rtblock_t lastbit; /* last useful bit in the word */
  267. xfs_rtblock_t len; /* length of inspected area */
  268. xfs_rtword_t mask; /* mask of relevant bits for value */
  269. xfs_rtword_t want; /* mask for "good" values */
  270. xfs_rtword_t wdiff; /* difference from wanted value */
  271. int word; /* word number in the buffer */
  272. /*
  273. * Compute and read in starting bitmap block for starting block.
  274. */
  275. block = XFS_BITTOBLOCK(mp, start);
  276. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  277. if (error) {
  278. return error;
  279. }
  280. bufp = bp->b_addr;
  281. /*
  282. * Get the first word's index & point to it.
  283. */
  284. word = XFS_BITTOWORD(mp, start);
  285. b = &bufp[word];
  286. bit = (int)(start & (XFS_NBWORD - 1));
  287. len = limit - start + 1;
  288. /*
  289. * Compute match value, based on the bit at start: if 1 (free)
  290. * then all-ones, else all-zeroes.
  291. */
  292. want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
  293. /*
  294. * If the starting position is not word-aligned, deal with the
  295. * partial word.
  296. */
  297. if (bit) {
  298. /*
  299. * Calculate last (rightmost) bit number to look at,
  300. * and mask for all the relevant bits in this word.
  301. */
  302. lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
  303. mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
  304. /*
  305. * Calculate the difference between the value there
  306. * and what we're looking for.
  307. */
  308. if ((wdiff = (*b ^ want) & mask)) {
  309. /*
  310. * Different. Mark where we are and return.
  311. */
  312. xfs_trans_brelse(tp, bp);
  313. i = XFS_RTLOBIT(wdiff) - bit;
  314. *rtblock = start + i - 1;
  315. return 0;
  316. }
  317. i = lastbit - bit;
  318. /*
  319. * Go on to next block if that's where the next word is
  320. * and we need the next word.
  321. */
  322. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  323. /*
  324. * If done with this block, get the previous one.
  325. */
  326. xfs_trans_brelse(tp, bp);
  327. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  328. if (error) {
  329. return error;
  330. }
  331. b = bufp = bp->b_addr;
  332. word = 0;
  333. } else {
  334. /*
  335. * Go on to the previous word in the buffer.
  336. */
  337. b++;
  338. }
  339. } else {
  340. /*
  341. * Starting on a word boundary, no partial word.
  342. */
  343. i = 0;
  344. }
  345. /*
  346. * Loop over whole words in buffers. When we use up one buffer
  347. * we move on to the next one.
  348. */
  349. while (len - i >= XFS_NBWORD) {
  350. /*
  351. * Compute difference between actual and desired value.
  352. */
  353. if ((wdiff = *b ^ want)) {
  354. /*
  355. * Different, mark where we are and return.
  356. */
  357. xfs_trans_brelse(tp, bp);
  358. i += XFS_RTLOBIT(wdiff);
  359. *rtblock = start + i - 1;
  360. return 0;
  361. }
  362. i += XFS_NBWORD;
  363. /*
  364. * Go on to next block if that's where the next word is
  365. * and we need the next word.
  366. */
  367. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  368. /*
  369. * If done with this block, get the next one.
  370. */
  371. xfs_trans_brelse(tp, bp);
  372. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  373. if (error) {
  374. return error;
  375. }
  376. b = bufp = bp->b_addr;
  377. word = 0;
  378. } else {
  379. /*
  380. * Go on to the next word in the buffer.
  381. */
  382. b++;
  383. }
  384. }
  385. /*
  386. * If not ending on a word boundary, deal with the last
  387. * (partial) word.
  388. */
  389. if ((lastbit = len - i)) {
  390. /*
  391. * Calculate mask for all the relevant bits in this word.
  392. */
  393. mask = ((xfs_rtword_t)1 << lastbit) - 1;
  394. /*
  395. * Compute difference between actual and desired value.
  396. */
  397. if ((wdiff = (*b ^ want) & mask)) {
  398. /*
  399. * Different, mark where we are and return.
  400. */
  401. xfs_trans_brelse(tp, bp);
  402. i += XFS_RTLOBIT(wdiff);
  403. *rtblock = start + i - 1;
  404. return 0;
  405. } else
  406. i = len;
  407. }
  408. /*
  409. * No match, return that we scanned the whole area.
  410. */
  411. xfs_trans_brelse(tp, bp);
  412. *rtblock = start + i - 1;
  413. return 0;
  414. }
  415. /*
  416. * Read and modify the summary information for a given extent size,
  417. * bitmap block combination.
  418. * Keeps track of a current summary block, so we don't keep reading
  419. * it from the buffer cache.
  420. */
  421. int
  422. xfs_rtmodify_summary(
  423. xfs_mount_t *mp, /* file system mount point */
  424. xfs_trans_t *tp, /* transaction pointer */
  425. int log, /* log2 of extent size */
  426. xfs_rtblock_t bbno, /* bitmap block number */
  427. int delta, /* change to make to summary info */
  428. xfs_buf_t **rbpp, /* in/out: summary block buffer */
  429. xfs_fsblock_t *rsb) /* in/out: summary block number */
  430. {
  431. xfs_buf_t *bp; /* buffer for the summary block */
  432. int error; /* error value */
  433. xfs_fsblock_t sb; /* summary fsblock */
  434. int so; /* index into the summary file */
  435. xfs_suminfo_t *sp; /* pointer to returned data */
  436. /*
  437. * Compute entry number in the summary file.
  438. */
  439. so = XFS_SUMOFFS(mp, log, bbno);
  440. /*
  441. * Compute the block number in the summary file.
  442. */
  443. sb = XFS_SUMOFFSTOBLOCK(mp, so);
  444. /*
  445. * If we have an old buffer, and the block number matches, use that.
  446. */
  447. if (rbpp && *rbpp && *rsb == sb)
  448. bp = *rbpp;
  449. /*
  450. * Otherwise we have to get the buffer.
  451. */
  452. else {
  453. /*
  454. * If there was an old one, get rid of it first.
  455. */
  456. if (rbpp && *rbpp)
  457. xfs_trans_brelse(tp, *rbpp);
  458. error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
  459. if (error) {
  460. return error;
  461. }
  462. /*
  463. * Remember this buffer and block for the next call.
  464. */
  465. if (rbpp) {
  466. *rbpp = bp;
  467. *rsb = sb;
  468. }
  469. }
  470. /*
  471. * Point to the summary information, modify and log it.
  472. */
  473. sp = XFS_SUMPTR(mp, bp, so);
  474. *sp += delta;
  475. xfs_trans_log_buf(tp, bp, (uint)((char *)sp - (char *)bp->b_addr),
  476. (uint)((char *)sp - (char *)bp->b_addr + sizeof(*sp) - 1));
  477. return 0;
  478. }
  479. /*
  480. * Set the given range of bitmap bits to the given value.
  481. * Do whatever I/O and logging is required.
  482. */
  483. int
  484. xfs_rtmodify_range(
  485. xfs_mount_t *mp, /* file system mount point */
  486. xfs_trans_t *tp, /* transaction pointer */
  487. xfs_rtblock_t start, /* starting block to modify */
  488. xfs_extlen_t len, /* length of extent to modify */
  489. int val) /* 1 for free, 0 for allocated */
  490. {
  491. xfs_rtword_t *b; /* current word in buffer */
  492. int bit; /* bit number in the word */
  493. xfs_rtblock_t block; /* bitmap block number */
  494. xfs_buf_t *bp; /* buf for the block */
  495. xfs_rtword_t *bufp; /* starting word in buffer */
  496. int error; /* error value */
  497. xfs_rtword_t *first; /* first used word in the buffer */
  498. int i; /* current bit number rel. to start */
  499. int lastbit; /* last useful bit in word */
  500. xfs_rtword_t mask; /* mask o frelevant bits for value */
  501. int word; /* word number in the buffer */
  502. /*
  503. * Compute starting bitmap block number.
  504. */
  505. block = XFS_BITTOBLOCK(mp, start);
  506. /*
  507. * Read the bitmap block, and point to its data.
  508. */
  509. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  510. if (error) {
  511. return error;
  512. }
  513. bufp = bp->b_addr;
  514. /*
  515. * Compute the starting word's address, and starting bit.
  516. */
  517. word = XFS_BITTOWORD(mp, start);
  518. first = b = &bufp[word];
  519. bit = (int)(start & (XFS_NBWORD - 1));
  520. /*
  521. * 0 (allocated) => all zeroes; 1 (free) => all ones.
  522. */
  523. val = -val;
  524. /*
  525. * If not starting on a word boundary, deal with the first
  526. * (partial) word.
  527. */
  528. if (bit) {
  529. /*
  530. * Compute first bit not changed and mask of relevant bits.
  531. */
  532. lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
  533. mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
  534. /*
  535. * Set/clear the active bits.
  536. */
  537. if (val)
  538. *b |= mask;
  539. else
  540. *b &= ~mask;
  541. i = lastbit - bit;
  542. /*
  543. * Go on to the next block if that's where the next word is
  544. * and we need the next word.
  545. */
  546. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  547. /*
  548. * Log the changed part of this block.
  549. * Get the next one.
  550. */
  551. xfs_trans_log_buf(tp, bp,
  552. (uint)((char *)first - (char *)bufp),
  553. (uint)((char *)b - (char *)bufp));
  554. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  555. if (error) {
  556. return error;
  557. }
  558. first = b = bufp = bp->b_addr;
  559. word = 0;
  560. } else {
  561. /*
  562. * Go on to the next word in the buffer
  563. */
  564. b++;
  565. }
  566. } else {
  567. /*
  568. * Starting on a word boundary, no partial word.
  569. */
  570. i = 0;
  571. }
  572. /*
  573. * Loop over whole words in buffers. When we use up one buffer
  574. * we move on to the next one.
  575. */
  576. while (len - i >= XFS_NBWORD) {
  577. /*
  578. * Set the word value correctly.
  579. */
  580. *b = val;
  581. i += XFS_NBWORD;
  582. /*
  583. * Go on to the next block if that's where the next word is
  584. * and we need the next word.
  585. */
  586. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  587. /*
  588. * Log the changed part of this block.
  589. * Get the next one.
  590. */
  591. xfs_trans_log_buf(tp, bp,
  592. (uint)((char *)first - (char *)bufp),
  593. (uint)((char *)b - (char *)bufp));
  594. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  595. if (error) {
  596. return error;
  597. }
  598. first = b = bufp = bp->b_addr;
  599. word = 0;
  600. } else {
  601. /*
  602. * Go on to the next word in the buffer
  603. */
  604. b++;
  605. }
  606. }
  607. /*
  608. * If not ending on a word boundary, deal with the last
  609. * (partial) word.
  610. */
  611. if ((lastbit = len - i)) {
  612. /*
  613. * Compute a mask of relevant bits.
  614. */
  615. bit = 0;
  616. mask = ((xfs_rtword_t)1 << lastbit) - 1;
  617. /*
  618. * Set/clear the active bits.
  619. */
  620. if (val)
  621. *b |= mask;
  622. else
  623. *b &= ~mask;
  624. b++;
  625. }
  626. /*
  627. * Log any remaining changed bytes.
  628. */
  629. if (b > first)
  630. xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
  631. (uint)((char *)b - (char *)bufp - 1));
  632. return 0;
  633. }
  634. /*
  635. * Mark an extent specified by start and len freed.
  636. * Updates all the summary information as well as the bitmap.
  637. */
  638. int
  639. xfs_rtfree_range(
  640. xfs_mount_t *mp, /* file system mount point */
  641. xfs_trans_t *tp, /* transaction pointer */
  642. xfs_rtblock_t start, /* starting block to free */
  643. xfs_extlen_t len, /* length to free */
  644. xfs_buf_t **rbpp, /* in/out: summary block buffer */
  645. xfs_fsblock_t *rsb) /* in/out: summary block number */
  646. {
  647. xfs_rtblock_t end; /* end of the freed extent */
  648. int error; /* error value */
  649. xfs_rtblock_t postblock; /* first block freed > end */
  650. xfs_rtblock_t preblock; /* first block freed < start */
  651. end = start + len - 1;
  652. /*
  653. * Modify the bitmap to mark this extent freed.
  654. */
  655. error = xfs_rtmodify_range(mp, tp, start, len, 1);
  656. if (error) {
  657. return error;
  658. }
  659. /*
  660. * Assume we're freeing out of the middle of an allocated extent.
  661. * We need to find the beginning and end of the extent so we can
  662. * properly update the summary.
  663. */
  664. error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
  665. if (error) {
  666. return error;
  667. }
  668. /*
  669. * Find the next allocated block (end of allocated extent).
  670. */
  671. error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
  672. &postblock);
  673. if (error)
  674. return error;
  675. /*
  676. * If there are blocks not being freed at the front of the
  677. * old extent, add summary data for them to be allocated.
  678. */
  679. if (preblock < start) {
  680. error = xfs_rtmodify_summary(mp, tp,
  681. XFS_RTBLOCKLOG(start - preblock),
  682. XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
  683. if (error) {
  684. return error;
  685. }
  686. }
  687. /*
  688. * If there are blocks not being freed at the end of the
  689. * old extent, add summary data for them to be allocated.
  690. */
  691. if (postblock > end) {
  692. error = xfs_rtmodify_summary(mp, tp,
  693. XFS_RTBLOCKLOG(postblock - end),
  694. XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
  695. if (error) {
  696. return error;
  697. }
  698. }
  699. /*
  700. * Increment the summary information corresponding to the entire
  701. * (new) free extent.
  702. */
  703. error = xfs_rtmodify_summary(mp, tp,
  704. XFS_RTBLOCKLOG(postblock + 1 - preblock),
  705. XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
  706. return error;
  707. }
  708. /*
  709. * Check that the given range is either all allocated (val = 0) or
  710. * all free (val = 1).
  711. */
  712. int
  713. xfs_rtcheck_range(
  714. xfs_mount_t *mp, /* file system mount point */
  715. xfs_trans_t *tp, /* transaction pointer */
  716. xfs_rtblock_t start, /* starting block number of extent */
  717. xfs_extlen_t len, /* length of extent */
  718. int val, /* 1 for free, 0 for allocated */
  719. xfs_rtblock_t *new, /* out: first block not matching */
  720. int *stat) /* out: 1 for matches, 0 for not */
  721. {
  722. xfs_rtword_t *b; /* current word in buffer */
  723. int bit; /* bit number in the word */
  724. xfs_rtblock_t block; /* bitmap block number */
  725. xfs_buf_t *bp; /* buf for the block */
  726. xfs_rtword_t *bufp; /* starting word in buffer */
  727. int error; /* error value */
  728. xfs_rtblock_t i; /* current bit number rel. to start */
  729. xfs_rtblock_t lastbit; /* last useful bit in word */
  730. xfs_rtword_t mask; /* mask of relevant bits for value */
  731. xfs_rtword_t wdiff; /* difference from wanted value */
  732. int word; /* word number in the buffer */
  733. /*
  734. * Compute starting bitmap block number
  735. */
  736. block = XFS_BITTOBLOCK(mp, start);
  737. /*
  738. * Read the bitmap block.
  739. */
  740. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  741. if (error) {
  742. return error;
  743. }
  744. bufp = bp->b_addr;
  745. /*
  746. * Compute the starting word's address, and starting bit.
  747. */
  748. word = XFS_BITTOWORD(mp, start);
  749. b = &bufp[word];
  750. bit = (int)(start & (XFS_NBWORD - 1));
  751. /*
  752. * 0 (allocated) => all zero's; 1 (free) => all one's.
  753. */
  754. val = -val;
  755. /*
  756. * If not starting on a word boundary, deal with the first
  757. * (partial) word.
  758. */
  759. if (bit) {
  760. /*
  761. * Compute first bit not examined.
  762. */
  763. lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
  764. /*
  765. * Mask of relevant bits.
  766. */
  767. mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
  768. /*
  769. * Compute difference between actual and desired value.
  770. */
  771. if ((wdiff = (*b ^ val) & mask)) {
  772. /*
  773. * Different, compute first wrong bit and return.
  774. */
  775. xfs_trans_brelse(tp, bp);
  776. i = XFS_RTLOBIT(wdiff) - bit;
  777. *new = start + i;
  778. *stat = 0;
  779. return 0;
  780. }
  781. i = lastbit - bit;
  782. /*
  783. * Go on to next block if that's where the next word is
  784. * and we need the next word.
  785. */
  786. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  787. /*
  788. * If done with this block, get the next one.
  789. */
  790. xfs_trans_brelse(tp, bp);
  791. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  792. if (error) {
  793. return error;
  794. }
  795. b = bufp = bp->b_addr;
  796. word = 0;
  797. } else {
  798. /*
  799. * Go on to the next word in the buffer.
  800. */
  801. b++;
  802. }
  803. } else {
  804. /*
  805. * Starting on a word boundary, no partial word.
  806. */
  807. i = 0;
  808. }
  809. /*
  810. * Loop over whole words in buffers. When we use up one buffer
  811. * we move on to the next one.
  812. */
  813. while (len - i >= XFS_NBWORD) {
  814. /*
  815. * Compute difference between actual and desired value.
  816. */
  817. if ((wdiff = *b ^ val)) {
  818. /*
  819. * Different, compute first wrong bit and return.
  820. */
  821. xfs_trans_brelse(tp, bp);
  822. i += XFS_RTLOBIT(wdiff);
  823. *new = start + i;
  824. *stat = 0;
  825. return 0;
  826. }
  827. i += XFS_NBWORD;
  828. /*
  829. * Go on to next block if that's where the next word is
  830. * and we need the next word.
  831. */
  832. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  833. /*
  834. * If done with this block, get the next one.
  835. */
  836. xfs_trans_brelse(tp, bp);
  837. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  838. if (error) {
  839. return error;
  840. }
  841. b = bufp = bp->b_addr;
  842. word = 0;
  843. } else {
  844. /*
  845. * Go on to the next word in the buffer.
  846. */
  847. b++;
  848. }
  849. }
  850. /*
  851. * If not ending on a word boundary, deal with the last
  852. * (partial) word.
  853. */
  854. if ((lastbit = len - i)) {
  855. /*
  856. * Mask of relevant bits.
  857. */
  858. mask = ((xfs_rtword_t)1 << lastbit) - 1;
  859. /*
  860. * Compute difference between actual and desired value.
  861. */
  862. if ((wdiff = (*b ^ val) & mask)) {
  863. /*
  864. * Different, compute first wrong bit and return.
  865. */
  866. xfs_trans_brelse(tp, bp);
  867. i += XFS_RTLOBIT(wdiff);
  868. *new = start + i;
  869. *stat = 0;
  870. return 0;
  871. } else
  872. i = len;
  873. }
  874. /*
  875. * Successful, return.
  876. */
  877. xfs_trans_brelse(tp, bp);
  878. *new = start + i;
  879. *stat = 1;
  880. return 0;
  881. }
  882. #ifdef DEBUG
  883. /*
  884. * Check that the given extent (block range) is allocated already.
  885. */
  886. STATIC int /* error */
  887. xfs_rtcheck_alloc_range(
  888. xfs_mount_t *mp, /* file system mount point */
  889. xfs_trans_t *tp, /* transaction pointer */
  890. xfs_rtblock_t bno, /* starting block number of extent */
  891. xfs_extlen_t len) /* length of extent */
  892. {
  893. xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
  894. int stat;
  895. int error;
  896. error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
  897. if (error)
  898. return error;
  899. ASSERT(stat);
  900. return 0;
  901. }
  902. #else
  903. #define xfs_rtcheck_alloc_range(m,t,b,l) (0)
  904. #endif
  905. /*
  906. * Free an extent in the realtime subvolume. Length is expressed in
  907. * realtime extents, as is the block number.
  908. */
  909. int /* error */
  910. xfs_rtfree_extent(
  911. xfs_trans_t *tp, /* transaction pointer */
  912. xfs_rtblock_t bno, /* starting block number to free */
  913. xfs_extlen_t len) /* length of extent freed */
  914. {
  915. int error; /* error value */
  916. xfs_mount_t *mp; /* file system mount structure */
  917. xfs_fsblock_t sb; /* summary file block number */
  918. xfs_buf_t *sumbp = NULL; /* summary file block buffer */
  919. mp = tp->t_mountp;
  920. ASSERT(mp->m_rbmip->i_itemp != NULL);
  921. ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
  922. error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
  923. if (error)
  924. return error;
  925. /*
  926. * Free the range of realtime blocks.
  927. */
  928. error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
  929. if (error) {
  930. return error;
  931. }
  932. /*
  933. * Mark more blocks free in the superblock.
  934. */
  935. xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
  936. /*
  937. * If we've now freed all the blocks, reset the file sequence
  938. * number to 0.
  939. */
  940. if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
  941. mp->m_sb.sb_rextents) {
  942. if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
  943. mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
  944. *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
  945. xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
  946. }
  947. return 0;
  948. }