xfs_rtbitmap.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  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. #include "xfs_rtalloc.h"
  41. /*
  42. * Realtime allocator bitmap functions shared with userspace.
  43. */
  44. /*
  45. * Get a buffer for the bitmap or summary file block specified.
  46. * The buffer is returned read and locked.
  47. */
  48. int
  49. xfs_rtbuf_get(
  50. xfs_mount_t *mp, /* file system mount structure */
  51. xfs_trans_t *tp, /* transaction pointer */
  52. xfs_rtblock_t block, /* block number in bitmap or summary */
  53. int issum, /* is summary not bitmap */
  54. xfs_buf_t **bpp) /* output: buffer for the block */
  55. {
  56. xfs_buf_t *bp; /* block buffer, result */
  57. xfs_inode_t *ip; /* bitmap or summary inode */
  58. xfs_bmbt_irec_t map;
  59. int nmap = 1;
  60. int error; /* error value */
  61. ip = issum ? mp->m_rsumip : mp->m_rbmip;
  62. error = xfs_bmapi_read(ip, block, 1, &map, &nmap, XFS_DATA_FORK);
  63. if (error)
  64. return error;
  65. ASSERT(map.br_startblock != NULLFSBLOCK);
  66. error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
  67. XFS_FSB_TO_DADDR(mp, map.br_startblock),
  68. mp->m_bsize, 0, &bp, NULL);
  69. if (error)
  70. return error;
  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/or 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. * Summary information is returned in *sum if specified.
  422. * If no delta is specified, returns summary only.
  423. */
  424. int
  425. xfs_rtmodify_summary_int(
  426. xfs_mount_t *mp, /* file system mount structure */
  427. xfs_trans_t *tp, /* transaction pointer */
  428. int log, /* log2 of extent size */
  429. xfs_rtblock_t bbno, /* bitmap block number */
  430. int delta, /* change to make to summary info */
  431. xfs_buf_t **rbpp, /* in/out: summary block buffer */
  432. xfs_fsblock_t *rsb, /* in/out: summary block number */
  433. xfs_suminfo_t *sum) /* out: summary info for this block */
  434. {
  435. xfs_buf_t *bp; /* buffer for the summary block */
  436. int error; /* error value */
  437. xfs_fsblock_t sb; /* summary fsblock */
  438. int so; /* index into the summary file */
  439. xfs_suminfo_t *sp; /* pointer to returned data */
  440. /*
  441. * Compute entry number in the summary file.
  442. */
  443. so = XFS_SUMOFFS(mp, log, bbno);
  444. /*
  445. * Compute the block number in the summary file.
  446. */
  447. sb = XFS_SUMOFFSTOBLOCK(mp, so);
  448. /*
  449. * If we have an old buffer, and the block number matches, use that.
  450. */
  451. if (*rbpp && *rsb == sb)
  452. bp = *rbpp;
  453. /*
  454. * Otherwise we have to get the buffer.
  455. */
  456. else {
  457. /*
  458. * If there was an old one, get rid of it first.
  459. */
  460. if (*rbpp)
  461. xfs_trans_brelse(tp, *rbpp);
  462. error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
  463. if (error) {
  464. return error;
  465. }
  466. /*
  467. * Remember this buffer and block for the next call.
  468. */
  469. *rbpp = bp;
  470. *rsb = sb;
  471. }
  472. /*
  473. * Point to the summary information, modify/log it, and/or copy it out.
  474. */
  475. sp = XFS_SUMPTR(mp, bp, so);
  476. if (delta) {
  477. uint first = (uint)((char *)sp - (char *)bp->b_addr);
  478. *sp += delta;
  479. xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
  480. }
  481. if (sum)
  482. *sum = *sp;
  483. return 0;
  484. }
  485. int
  486. xfs_rtmodify_summary(
  487. xfs_mount_t *mp, /* file system mount structure */
  488. xfs_trans_t *tp, /* transaction pointer */
  489. int log, /* log2 of extent size */
  490. xfs_rtblock_t bbno, /* bitmap block number */
  491. int delta, /* change to make to summary info */
  492. xfs_buf_t **rbpp, /* in/out: summary block buffer */
  493. xfs_fsblock_t *rsb) /* in/out: summary block number */
  494. {
  495. return xfs_rtmodify_summary_int(mp, tp, log, bbno,
  496. delta, rbpp, rsb, NULL);
  497. }
  498. /*
  499. * Set the given range of bitmap bits to the given value.
  500. * Do whatever I/O and logging is required.
  501. */
  502. int
  503. xfs_rtmodify_range(
  504. xfs_mount_t *mp, /* file system mount point */
  505. xfs_trans_t *tp, /* transaction pointer */
  506. xfs_rtblock_t start, /* starting block to modify */
  507. xfs_extlen_t len, /* length of extent to modify */
  508. int val) /* 1 for free, 0 for allocated */
  509. {
  510. xfs_rtword_t *b; /* current word in buffer */
  511. int bit; /* bit number in the word */
  512. xfs_rtblock_t block; /* bitmap block number */
  513. xfs_buf_t *bp; /* buf for the block */
  514. xfs_rtword_t *bufp; /* starting word in buffer */
  515. int error; /* error value */
  516. xfs_rtword_t *first; /* first used word in the buffer */
  517. int i; /* current bit number rel. to start */
  518. int lastbit; /* last useful bit in word */
  519. xfs_rtword_t mask; /* mask o frelevant bits for value */
  520. int word; /* word number in the buffer */
  521. /*
  522. * Compute starting bitmap block number.
  523. */
  524. block = XFS_BITTOBLOCK(mp, start);
  525. /*
  526. * Read the bitmap block, and point to its data.
  527. */
  528. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  529. if (error) {
  530. return error;
  531. }
  532. bufp = bp->b_addr;
  533. /*
  534. * Compute the starting word's address, and starting bit.
  535. */
  536. word = XFS_BITTOWORD(mp, start);
  537. first = b = &bufp[word];
  538. bit = (int)(start & (XFS_NBWORD - 1));
  539. /*
  540. * 0 (allocated) => all zeroes; 1 (free) => all ones.
  541. */
  542. val = -val;
  543. /*
  544. * If not starting on a word boundary, deal with the first
  545. * (partial) word.
  546. */
  547. if (bit) {
  548. /*
  549. * Compute first bit not changed and mask of relevant bits.
  550. */
  551. lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
  552. mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
  553. /*
  554. * Set/clear the active bits.
  555. */
  556. if (val)
  557. *b |= mask;
  558. else
  559. *b &= ~mask;
  560. i = lastbit - bit;
  561. /*
  562. * Go on to the next block if that's where the next word is
  563. * and we need the next word.
  564. */
  565. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  566. /*
  567. * Log the changed part of this block.
  568. * Get the next one.
  569. */
  570. xfs_trans_log_buf(tp, bp,
  571. (uint)((char *)first - (char *)bufp),
  572. (uint)((char *)b - (char *)bufp));
  573. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  574. if (error) {
  575. return error;
  576. }
  577. first = b = bufp = bp->b_addr;
  578. word = 0;
  579. } else {
  580. /*
  581. * Go on to the next word in the buffer
  582. */
  583. b++;
  584. }
  585. } else {
  586. /*
  587. * Starting on a word boundary, no partial word.
  588. */
  589. i = 0;
  590. }
  591. /*
  592. * Loop over whole words in buffers. When we use up one buffer
  593. * we move on to the next one.
  594. */
  595. while (len - i >= XFS_NBWORD) {
  596. /*
  597. * Set the word value correctly.
  598. */
  599. *b = val;
  600. i += XFS_NBWORD;
  601. /*
  602. * Go on to the next block if that's where the next word is
  603. * and we need the next word.
  604. */
  605. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  606. /*
  607. * Log the changed part of this block.
  608. * Get the next one.
  609. */
  610. xfs_trans_log_buf(tp, bp,
  611. (uint)((char *)first - (char *)bufp),
  612. (uint)((char *)b - (char *)bufp));
  613. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  614. if (error) {
  615. return error;
  616. }
  617. first = b = bufp = bp->b_addr;
  618. word = 0;
  619. } else {
  620. /*
  621. * Go on to the next word in the buffer
  622. */
  623. b++;
  624. }
  625. }
  626. /*
  627. * If not ending on a word boundary, deal with the last
  628. * (partial) word.
  629. */
  630. if ((lastbit = len - i)) {
  631. /*
  632. * Compute a mask of relevant bits.
  633. */
  634. bit = 0;
  635. mask = ((xfs_rtword_t)1 << lastbit) - 1;
  636. /*
  637. * Set/clear the active bits.
  638. */
  639. if (val)
  640. *b |= mask;
  641. else
  642. *b &= ~mask;
  643. b++;
  644. }
  645. /*
  646. * Log any remaining changed bytes.
  647. */
  648. if (b > first)
  649. xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp),
  650. (uint)((char *)b - (char *)bufp - 1));
  651. return 0;
  652. }
  653. /*
  654. * Mark an extent specified by start and len freed.
  655. * Updates all the summary information as well as the bitmap.
  656. */
  657. int
  658. xfs_rtfree_range(
  659. xfs_mount_t *mp, /* file system mount point */
  660. xfs_trans_t *tp, /* transaction pointer */
  661. xfs_rtblock_t start, /* starting block to free */
  662. xfs_extlen_t len, /* length to free */
  663. xfs_buf_t **rbpp, /* in/out: summary block buffer */
  664. xfs_fsblock_t *rsb) /* in/out: summary block number */
  665. {
  666. xfs_rtblock_t end; /* end of the freed extent */
  667. int error; /* error value */
  668. xfs_rtblock_t postblock; /* first block freed > end */
  669. xfs_rtblock_t preblock; /* first block freed < start */
  670. end = start + len - 1;
  671. /*
  672. * Modify the bitmap to mark this extent freed.
  673. */
  674. error = xfs_rtmodify_range(mp, tp, start, len, 1);
  675. if (error) {
  676. return error;
  677. }
  678. /*
  679. * Assume we're freeing out of the middle of an allocated extent.
  680. * We need to find the beginning and end of the extent so we can
  681. * properly update the summary.
  682. */
  683. error = xfs_rtfind_back(mp, tp, start, 0, &preblock);
  684. if (error) {
  685. return error;
  686. }
  687. /*
  688. * Find the next allocated block (end of allocated extent).
  689. */
  690. error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1,
  691. &postblock);
  692. if (error)
  693. return error;
  694. /*
  695. * If there are blocks not being freed at the front of the
  696. * old extent, add summary data for them to be allocated.
  697. */
  698. if (preblock < start) {
  699. error = xfs_rtmodify_summary(mp, tp,
  700. XFS_RTBLOCKLOG(start - preblock),
  701. XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb);
  702. if (error) {
  703. return error;
  704. }
  705. }
  706. /*
  707. * If there are blocks not being freed at the end of the
  708. * old extent, add summary data for them to be allocated.
  709. */
  710. if (postblock > end) {
  711. error = xfs_rtmodify_summary(mp, tp,
  712. XFS_RTBLOCKLOG(postblock - end),
  713. XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb);
  714. if (error) {
  715. return error;
  716. }
  717. }
  718. /*
  719. * Increment the summary information corresponding to the entire
  720. * (new) free extent.
  721. */
  722. error = xfs_rtmodify_summary(mp, tp,
  723. XFS_RTBLOCKLOG(postblock + 1 - preblock),
  724. XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb);
  725. return error;
  726. }
  727. /*
  728. * Check that the given range is either all allocated (val = 0) or
  729. * all free (val = 1).
  730. */
  731. int
  732. xfs_rtcheck_range(
  733. xfs_mount_t *mp, /* file system mount point */
  734. xfs_trans_t *tp, /* transaction pointer */
  735. xfs_rtblock_t start, /* starting block number of extent */
  736. xfs_extlen_t len, /* length of extent */
  737. int val, /* 1 for free, 0 for allocated */
  738. xfs_rtblock_t *new, /* out: first block not matching */
  739. int *stat) /* out: 1 for matches, 0 for not */
  740. {
  741. xfs_rtword_t *b; /* current word in buffer */
  742. int bit; /* bit number in the word */
  743. xfs_rtblock_t block; /* bitmap block number */
  744. xfs_buf_t *bp; /* buf for the block */
  745. xfs_rtword_t *bufp; /* starting word in buffer */
  746. int error; /* error value */
  747. xfs_rtblock_t i; /* current bit number rel. to start */
  748. xfs_rtblock_t lastbit; /* last useful bit in word */
  749. xfs_rtword_t mask; /* mask of relevant bits for value */
  750. xfs_rtword_t wdiff; /* difference from wanted value */
  751. int word; /* word number in the buffer */
  752. /*
  753. * Compute starting bitmap block number
  754. */
  755. block = XFS_BITTOBLOCK(mp, start);
  756. /*
  757. * Read the bitmap block.
  758. */
  759. error = xfs_rtbuf_get(mp, tp, block, 0, &bp);
  760. if (error) {
  761. return error;
  762. }
  763. bufp = bp->b_addr;
  764. /*
  765. * Compute the starting word's address, and starting bit.
  766. */
  767. word = XFS_BITTOWORD(mp, start);
  768. b = &bufp[word];
  769. bit = (int)(start & (XFS_NBWORD - 1));
  770. /*
  771. * 0 (allocated) => all zero's; 1 (free) => all one's.
  772. */
  773. val = -val;
  774. /*
  775. * If not starting on a word boundary, deal with the first
  776. * (partial) word.
  777. */
  778. if (bit) {
  779. /*
  780. * Compute first bit not examined.
  781. */
  782. lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
  783. /*
  784. * Mask of relevant bits.
  785. */
  786. mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
  787. /*
  788. * Compute difference between actual and desired value.
  789. */
  790. if ((wdiff = (*b ^ val) & mask)) {
  791. /*
  792. * Different, compute first wrong bit and return.
  793. */
  794. xfs_trans_brelse(tp, bp);
  795. i = XFS_RTLOBIT(wdiff) - bit;
  796. *new = start + i;
  797. *stat = 0;
  798. return 0;
  799. }
  800. i = lastbit - bit;
  801. /*
  802. * Go on to next block if that's where the next word is
  803. * and we need the next word.
  804. */
  805. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  806. /*
  807. * If done with this block, get the next one.
  808. */
  809. xfs_trans_brelse(tp, bp);
  810. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  811. if (error) {
  812. return error;
  813. }
  814. b = bufp = bp->b_addr;
  815. word = 0;
  816. } else {
  817. /*
  818. * Go on to the next word in the buffer.
  819. */
  820. b++;
  821. }
  822. } else {
  823. /*
  824. * Starting on a word boundary, no partial word.
  825. */
  826. i = 0;
  827. }
  828. /*
  829. * Loop over whole words in buffers. When we use up one buffer
  830. * we move on to the next one.
  831. */
  832. while (len - i >= XFS_NBWORD) {
  833. /*
  834. * Compute difference between actual and desired value.
  835. */
  836. if ((wdiff = *b ^ val)) {
  837. /*
  838. * Different, compute first wrong bit and return.
  839. */
  840. xfs_trans_brelse(tp, bp);
  841. i += XFS_RTLOBIT(wdiff);
  842. *new = start + i;
  843. *stat = 0;
  844. return 0;
  845. }
  846. i += XFS_NBWORD;
  847. /*
  848. * Go on to next block if that's where the next word is
  849. * and we need the next word.
  850. */
  851. if (++word == XFS_BLOCKWSIZE(mp) && i < len) {
  852. /*
  853. * If done with this block, get the next one.
  854. */
  855. xfs_trans_brelse(tp, bp);
  856. error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
  857. if (error) {
  858. return error;
  859. }
  860. b = bufp = bp->b_addr;
  861. word = 0;
  862. } else {
  863. /*
  864. * Go on to the next word in the buffer.
  865. */
  866. b++;
  867. }
  868. }
  869. /*
  870. * If not ending on a word boundary, deal with the last
  871. * (partial) word.
  872. */
  873. if ((lastbit = len - i)) {
  874. /*
  875. * Mask of relevant bits.
  876. */
  877. mask = ((xfs_rtword_t)1 << lastbit) - 1;
  878. /*
  879. * Compute difference between actual and desired value.
  880. */
  881. if ((wdiff = (*b ^ val) & mask)) {
  882. /*
  883. * Different, compute first wrong bit and return.
  884. */
  885. xfs_trans_brelse(tp, bp);
  886. i += XFS_RTLOBIT(wdiff);
  887. *new = start + i;
  888. *stat = 0;
  889. return 0;
  890. } else
  891. i = len;
  892. }
  893. /*
  894. * Successful, return.
  895. */
  896. xfs_trans_brelse(tp, bp);
  897. *new = start + i;
  898. *stat = 1;
  899. return 0;
  900. }
  901. #ifdef DEBUG
  902. /*
  903. * Check that the given extent (block range) is allocated already.
  904. */
  905. STATIC int /* error */
  906. xfs_rtcheck_alloc_range(
  907. xfs_mount_t *mp, /* file system mount point */
  908. xfs_trans_t *tp, /* transaction pointer */
  909. xfs_rtblock_t bno, /* starting block number of extent */
  910. xfs_extlen_t len) /* length of extent */
  911. {
  912. xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */
  913. int stat;
  914. int error;
  915. error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat);
  916. if (error)
  917. return error;
  918. ASSERT(stat);
  919. return 0;
  920. }
  921. #else
  922. #define xfs_rtcheck_alloc_range(m,t,b,l) (0)
  923. #endif
  924. /*
  925. * Free an extent in the realtime subvolume. Length is expressed in
  926. * realtime extents, as is the block number.
  927. */
  928. int /* error */
  929. xfs_rtfree_extent(
  930. xfs_trans_t *tp, /* transaction pointer */
  931. xfs_rtblock_t bno, /* starting block number to free */
  932. xfs_extlen_t len) /* length of extent freed */
  933. {
  934. int error; /* error value */
  935. xfs_mount_t *mp; /* file system mount structure */
  936. xfs_fsblock_t sb; /* summary file block number */
  937. xfs_buf_t *sumbp = NULL; /* summary file block buffer */
  938. mp = tp->t_mountp;
  939. ASSERT(mp->m_rbmip->i_itemp != NULL);
  940. ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
  941. error = xfs_rtcheck_alloc_range(mp, tp, bno, len);
  942. if (error)
  943. return error;
  944. /*
  945. * Free the range of realtime blocks.
  946. */
  947. error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb);
  948. if (error) {
  949. return error;
  950. }
  951. /*
  952. * Mark more blocks free in the superblock.
  953. */
  954. xfs_trans_mod_sb(tp, XFS_TRANS_SB_FREXTENTS, (long)len);
  955. /*
  956. * If we've now freed all the blocks, reset the file sequence
  957. * number to 0.
  958. */
  959. if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
  960. mp->m_sb.sb_rextents) {
  961. if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
  962. mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
  963. *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
  964. xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
  965. }
  966. return 0;
  967. }