xfs_rtbitmap.c 25 KB

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