xfs_rtbitmap.c 25 KB

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