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