extent.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:19k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/hfs/extent.c
  3.  *
  4.  * Copyright (C) 1995-1997  Paul H. Hargrove
  5.  * This file may be distributed under the terms of the GNU General Public License.
  6.  *
  7.  * This file contains the functions related to the extents B-tree.
  8.  *
  9.  * "XXX" in a comment is a note to myself to consider changing something.
  10.  *
  11.  * In function preconditions the term "valid" applied to a pointer to
  12.  * a structure means that the pointer is non-NULL and the structure it
  13.  * points to has all fields initialized to consistent values.
  14.  */
  15. #include "hfs.h"
  16. /*================ File-local data type ================*/
  17. /* An extent record on disk*/
  18. struct hfs_raw_extent {
  19. hfs_word_t block1;
  20. hfs_word_t length1;
  21. hfs_word_t block2;
  22. hfs_word_t length2;
  23. hfs_word_t block3;
  24. hfs_word_t length3;
  25. };
  26. /*================ File-local functions ================*/
  27. /*
  28.  * build_key
  29.  */
  30. static inline void build_key(struct hfs_ext_key *key,
  31.      const struct hfs_fork *fork, hfs_u16 block)
  32. {
  33. key->KeyLen = 7;
  34. key->FkType = fork->fork;
  35. hfs_put_nl(fork->entry->cnid, key->FNum);
  36. hfs_put_hs(block,             key->FABN);
  37. }
  38. /*
  39.  * lock_bitmap()
  40.  *
  41.  * Get an exclusive lock on the B-tree bitmap.
  42.  */
  43. static inline void lock_bitmap(struct hfs_mdb *mdb) {
  44. while (mdb->bitmap_lock) {
  45. hfs_sleep_on(&mdb->bitmap_wait);
  46. }
  47. mdb->bitmap_lock = 1;
  48. }
  49. /*
  50.  * unlock_bitmap()
  51.  *
  52.  * Relinquish an exclusive lock on the B-tree bitmap.
  53.  */
  54. static inline void unlock_bitmap(struct hfs_mdb *mdb) {
  55. mdb->bitmap_lock = 0;
  56. hfs_wake_up(&mdb->bitmap_wait);
  57. }
  58. /*
  59.  * dump_ext()
  60.  *
  61.  * prints the content of a extent for debugging purposes.
  62.  */
  63. #if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
  64. static void dump_ext(const char *msg, const struct hfs_extent *e) {
  65. if (e) {
  66. hfs_warn("%s (%d-%d) (%d-%d) (%d-%d)n", msg,
  67.  e->start,
  68.  e->start + e->length[0] - 1,
  69.  e->start + e->length[0],
  70.  e->start + e->length[0] + e->length[1] - 1,
  71.  e->start + e->length[0] + e->length[1],
  72.  e->end);
  73. } else {
  74. hfs_warn("%s NULLn", msg);
  75. }
  76. }
  77. #else
  78. #define dump_ext(A,B) {}
  79. #endif
  80. /*
  81.  * read_extent()
  82.  * 
  83.  * Initializes a (struct hfs_extent) from a (struct hfs_raw_extent) and
  84.  * the number of the starting block for the extent.
  85.  *
  86.  * Note that the callers must check that to,from != NULL
  87.  */
  88. static void read_extent(struct hfs_extent *to,
  89. const struct hfs_raw_extent *from,
  90. hfs_u16 start)
  91. {
  92. to->start = start;
  93. to->block[0]  = hfs_get_hs(from->block1);
  94. to->length[0] = hfs_get_hs(from->length1);
  95. to->block[1]  = hfs_get_hs(from->block2);
  96. to->length[1] = hfs_get_hs(from->length2);
  97. to->block[2]  = hfs_get_hs(from->block3);
  98. to->length[2] = hfs_get_hs(from->length3);
  99. to->end = start + to->length[0] + to->length[1] + to->length[2] - 1;
  100. to->next = to->prev = NULL;
  101. to->count = 0;
  102. }
  103. /*
  104.  * write_extent()
  105.  * 
  106.  * Initializes a (struct hfs_raw_extent) from a (struct hfs_extent).
  107.  *
  108.  * Note that the callers must check that to,from != NULL
  109.  */
  110. static void write_extent(struct hfs_raw_extent *to,
  111.  const struct hfs_extent *from)
  112. {
  113. hfs_put_hs(from->block[0], to->block1);
  114. hfs_put_hs(from->length[0], to->length1);
  115. hfs_put_hs(from->block[1], to->block2);
  116. hfs_put_hs(from->length[1], to->length2);
  117. hfs_put_hs(from->block[2], to->block3);
  118. hfs_put_hs(from->length[2], to->length3);
  119. }
  120. /*
  121.  * decode_extent()
  122.  *
  123.  * Given an extent record and allocation block offset into the file,
  124.  * return the number of the corresponding allocation block on disk,
  125.  * or -1 if the desired block is not mapped by the given extent.
  126.  *
  127.  * Note that callers must check that extent != NULL
  128.  */
  129. static int decode_extent(const struct hfs_extent * extent, int block)
  130. {
  131. if (!extent || (block < extent->start) || (block > extent->end) ||
  132.     (extent->end == (hfs_u16)(extent->start - 1))) {
  133. return -1;
  134. }
  135. block -= extent->start;
  136. if (block < extent->length[0]) {
  137. return block + extent->block[0];
  138. }
  139. block -= extent->length[0];
  140. if (block < extent->length[1]) {
  141. return block + extent->block[1];
  142. }
  143. return block + extent->block[2] - extent->length[1];
  144. }
  145. /*
  146.  * relse_ext()
  147.  *
  148.  * Reduce the reference count of an in-core extent record by one,
  149.  * removing it from memory if the count falls to zero.
  150.  */
  151. static void relse_ext(struct hfs_extent *ext)
  152. {
  153. if (--ext->count || !ext->start) {
  154. return;
  155. }
  156. ext->prev->next = ext->next;
  157. if (ext->next) {
  158. ext->next->prev = ext->prev;
  159. }
  160. HFS_DELETE(ext);
  161. }
  162. /*
  163.  * set_cache()
  164.  * 
  165.  * Changes the 'cache' field of the fork.
  166.  */
  167. static inline void set_cache(struct hfs_fork *fork, struct hfs_extent *ext)
  168. {
  169. struct hfs_extent *tmp = fork->cache;
  170. ++ext->count;
  171. fork->cache = ext;
  172. relse_ext(tmp);
  173. }
  174. /*
  175.  * find_ext()
  176.  *
  177.  * Given a pointer to a (struct hfs_file) and an allocation block
  178.  * number in the file, find the extent record containing that block.
  179.  * Returns a pointer to the extent record on success or NULL on failure.
  180.  * The 'cache' field of 'fil' also points to the extent so it has a
  181.  * reference count of at least 2.
  182.  *
  183.  * Callers must check that fil != NULL
  184.  */
  185. static struct hfs_extent * find_ext(struct hfs_fork *fork, int alloc_block)
  186. {
  187.         struct hfs_cat_entry *entry = fork->entry;
  188. struct hfs_btree *tr= entry->mdb->ext_tree;
  189. struct hfs_ext_key target, *key;
  190. struct hfs_brec brec;
  191. struct hfs_extent *ext, *ptr;
  192. int tmp;
  193. if (alloc_block < 0) {
  194. ext = &fork->first;
  195. goto found;
  196. }
  197. ext = fork->cache;
  198. if (!ext || (alloc_block < ext->start)) {
  199. ext = &fork->first;
  200. }
  201. while (ext->next && (alloc_block > ext->end)) {
  202. ext = ext->next;
  203. }
  204. if ((alloc_block <= ext->end) && (alloc_block >= ext->start)) {
  205. goto found;
  206. }
  207. /* time to read more extents */
  208. if (!HFS_NEW(ext)) {
  209. goto bail3;
  210. }
  211. build_key(&target, fork, alloc_block);
  212. tmp = hfs_bfind(&brec, tr, HFS_BKEY(&target), HFS_BFIND_READ_LE);
  213. if (tmp < 0) {
  214. goto bail2;
  215. }
  216. key = (struct hfs_ext_key *)brec.key;
  217. if ((hfs_get_nl(key->FNum) != hfs_get_nl(target.FNum)) ||
  218.     (key->FkType != fork->fork)) {
  219. goto bail1;
  220. }
  221. read_extent(ext, brec.data, hfs_get_hs(key->FABN));
  222. hfs_brec_relse(&brec, NULL);
  223. if ((alloc_block > ext->end) && (alloc_block < ext->start)) {
  224. /* something strange happened */
  225. goto bail2;
  226. }
  227. ptr = fork->cache;
  228. if (!ptr || (alloc_block < ptr->start)) {
  229. ptr = &fork->first;
  230. }
  231. while (ptr->next && (alloc_block > ptr->end)) {
  232. ptr = ptr->next;
  233. }
  234. if (ext->start == ptr->start) {
  235. /* somebody beat us to it. */
  236. HFS_DELETE(ext);
  237. ext = ptr;
  238. } else if (ext->start < ptr->start) {
  239. /* insert just before ptr */
  240. ptr->prev->next = ext;
  241. ext->prev = ptr->prev;
  242. ext->next = ptr;
  243. ptr->prev = ext;
  244. } else {
  245. /* insert at end */
  246. ptr->next = ext;
  247. ext->prev = ptr;
  248. }
  249.  found:
  250. ++ext->count; /* for return value */
  251. set_cache(fork, ext);
  252. return ext;
  253.  bail1:
  254. hfs_brec_relse(&brec, NULL);
  255.  bail2:
  256. HFS_DELETE(ext);
  257.  bail3:
  258. return NULL;
  259. }
  260. /*
  261.  * delete_extent()
  262.  *
  263.  * Description:
  264.  *   Deletes an extent record from a fork, reducing its physical length.
  265.  * Input Variable(s):
  266.  *   struct hfs_fork *fork: the fork
  267.  *   struct hfs_extent *ext: the current last extent for 'fork'
  268.  * Output Variable(s):
  269.  *   NONE
  270.  * Returns:
  271.  *   void
  272.  * Preconditions:
  273.  *   'fork' points to a valid (struct hfs_fork)
  274.  *   'ext' point to a valid (struct hfs_extent) which is the last in 'fork'
  275.  *    and which is not also the first extent in 'fork'.
  276.  * Postconditions:
  277.  *   The extent record has been removed if possible, and a warning has been
  278.  *   printed otherwise.
  279.  */
  280. static void delete_extent(struct hfs_fork *fork, struct hfs_extent *ext)
  281. {
  282. struct hfs_mdb *mdb = fork->entry->mdb;
  283. struct hfs_ext_key key;
  284. int error;
  285. if (fork->cache == ext) {
  286. set_cache(fork, ext->prev);
  287. }
  288. ext->prev->next = NULL;
  289. if (ext->count != 1) {
  290. hfs_warn("hfs_truncate: extent has count %d.n", ext->count);
  291. }
  292. lock_bitmap(mdb);
  293. error = hfs_clear_vbm_bits(mdb, ext->block[2], ext->length[2]);
  294. if (error) {
  295. hfs_warn("hfs_truncate: error %d freeing blocks.n", error);
  296. }
  297. error = hfs_clear_vbm_bits(mdb, ext->block[1], ext->length[1]);
  298. if (error) {
  299. hfs_warn("hfs_truncate: error %d freeing blocks.n", error);
  300. }
  301. error = hfs_clear_vbm_bits(mdb, ext->block[0], ext->length[0]);
  302. if (error) {
  303. hfs_warn("hfs_truncate: error %d freeing blocks.n", error);
  304. }
  305. unlock_bitmap(mdb);
  306. build_key(&key, fork, ext->start);
  307. error = hfs_bdelete(mdb->ext_tree, HFS_BKEY(&key));
  308. if (error) {
  309. hfs_warn("hfs_truncate: error %d deleting an extent.n", error);
  310. }
  311. HFS_DELETE(ext);
  312. }
  313. /*
  314.  * new_extent()
  315.  *
  316.  * Description:
  317.  *   Adds a new extent record to a fork, extending its physical length.
  318.  * Input Variable(s):
  319.  *   struct hfs_fork *fork: the fork to extend
  320.  *   struct hfs_extent *ext: the current last extent for 'fork'
  321.  *   hfs_u16 ablock: the number of allocation blocks in 'fork'.
  322.  *   hfs_u16 start: first allocation block to add to 'fork'.
  323.  *   hfs_u16 len: the number of allocation blocks to add to 'fork'.
  324.  *   hfs_u32 ablksz: number of sectors in an allocation block.
  325.  * Output Variable(s):
  326.  *   NONE
  327.  * Returns:
  328.  *   (struct hfs_extent *) the new extent or NULL
  329.  * Preconditions:
  330.  *   'fork' points to a valid (struct hfs_fork)
  331.  *   'ext' point to a valid (struct hfs_extent) which is the last in 'fork'
  332.  *   'ablock', 'start', 'len' and 'ablksz' are what they claim to be.
  333.  * Postconditions:
  334.  *   If NULL is returned then no changes have been made to 'fork'.
  335.  *   If the return value is non-NULL that it is the extent that has been
  336.  *   added to 'fork' both in memory and on disk.  The 'psize' field of
  337.  *   'fork' has been updated to reflect the new physical size.
  338.  */
  339. static struct hfs_extent *new_extent(struct hfs_fork *fork,
  340.      struct hfs_extent *ext,
  341.      hfs_u16 ablock, hfs_u16 start,
  342.      hfs_u16 len, hfs_u16 ablksz)
  343. {
  344. struct hfs_raw_extent raw;
  345. struct hfs_ext_key key;
  346. int error;
  347. if (fork->entry->cnid == htonl(HFS_EXT_CNID)) {
  348. /* Limit extents tree to the record in the MDB */
  349. return NULL;
  350. }
  351. if (!HFS_NEW(ext->next)) {
  352. return NULL;
  353. }
  354. ext->next->prev = ext;
  355. ext->next->next = NULL;
  356. ext = ext->next;
  357. relse_ext(ext->prev);
  358. ext->start = ablock;
  359. ext->block[0] = start;
  360. ext->length[0] = len;
  361. ext->block[1] = 0;
  362. ext->length[1] = 0;
  363. ext->block[2] = 0;
  364. ext->length[2] = 0;
  365. ext->end = ablock + len - 1;
  366. ext->count = 1;
  367. write_extent(&raw, ext);
  368. build_key(&key, fork, ablock);
  369. error = hfs_binsert(fork->entry->mdb->ext_tree, 
  370.     HFS_BKEY(&key), &raw, sizeof(raw));
  371. if (error) {
  372. ext->prev->next = NULL;
  373. HFS_DELETE(ext);
  374. return NULL;
  375. }
  376. set_cache(fork, ext);
  377. return ext;
  378. }
  379. /*
  380.  * update_ext()
  381.  *
  382.  * Given a (struct hfs_fork) write an extent record back to disk.
  383.  */
  384. static void update_ext(struct hfs_fork *fork, struct hfs_extent *ext)
  385. {
  386. struct hfs_ext_key target;
  387. struct hfs_brec brec;
  388. if (ext->start) {
  389. build_key(&target, fork, ext->start);
  390. if (!hfs_bfind(&brec, fork->entry->mdb->ext_tree,
  391.        HFS_BKEY(&target), HFS_BFIND_WRITE)) {
  392. write_extent(brec.data, ext);
  393. hfs_brec_relse(&brec, NULL);
  394. }
  395. }
  396. }
  397. /*
  398.  * zero_blocks()
  399.  * 
  400.  * Zeros-out 'num' allocation blocks beginning with 'start'.
  401.  */
  402. static int zero_blocks(struct hfs_mdb *mdb, int start, int num) {
  403. hfs_buffer buf;
  404. int end;
  405. int j;
  406. start = mdb->fs_start + start * mdb->alloc_blksz;
  407. end = start + num * mdb->alloc_blksz;
  408. for (j=start; j<end; ++j) {
  409. if (hfs_buffer_ok(buf = hfs_buffer_get(mdb->sys_mdb, j, 0))) {
  410. memset(hfs_buffer_data(buf), 0, HFS_SECTOR_SIZE);
  411. hfs_buffer_dirty(buf);
  412. hfs_buffer_put(buf);
  413. }
  414. }
  415. return 0;
  416. }
  417. /*
  418.  * shrink_fork()
  419.  *
  420.  * Try to remove enough allocation blocks from 'fork'
  421.  * so that it is 'ablocks' allocation blocks long. 
  422.  */
  423. static void shrink_fork(struct hfs_fork *fork, int ablocks)
  424. {
  425. struct hfs_mdb *mdb = fork->entry->mdb;
  426. struct hfs_extent *ext;
  427. int i, error, next, count;
  428. hfs_u32 ablksz = mdb->alloc_blksz;
  429. next =  (fork->psize / ablksz) - 1;
  430. ext = find_ext(fork, next);
  431. while (ext && ext->start && (ext->start >= ablocks)) {
  432. next = ext->start - 1;
  433. delete_extent(fork, ext);
  434. ext = find_ext(fork, next);
  435. }
  436. if (!ext) {
  437. fork->psize = (next + 1) * ablksz;
  438. return;
  439. }
  440. if ((count = next + 1 - ablocks) > 0) {
  441. for (i=2; (i>=0) && !ext->length[i]; --i) {};
  442. lock_bitmap(mdb);
  443. while (count && (ext->length[i] <= count)) {
  444. ext->end -= ext->length[i];
  445. count -= ext->length[i];
  446. error = hfs_clear_vbm_bits(mdb, ext->block[i],
  447.    ext->length[i]);
  448. if (error) {
  449. hfs_warn("hfs_truncate: error %d freeing "
  450.        "blocks.n", error);
  451. }
  452. ext->block[i] = ext->length[i] = 0;
  453. --i;
  454. }
  455. if (count) {
  456. ext->end -= count;
  457. ext->length[i] -= count;
  458. error = hfs_clear_vbm_bits(mdb, ext->block[i] +
  459.        ext->length[i], count);
  460. if (error) {
  461. hfs_warn("hfs_truncate: error %d freeing "
  462.        "blocks.n", error);
  463. }
  464. }
  465. unlock_bitmap(mdb);
  466. update_ext(fork, ext);
  467. }
  468. fork->psize = ablocks * ablksz;
  469. }
  470. /*
  471.  * grow_fork()
  472.  *
  473.  * Try to add enough allocation blocks to 'fork'
  474.  * so that it is 'ablock' allocation blocks long. 
  475.  */
  476. static int grow_fork(struct hfs_fork *fork, int ablocks)
  477. {
  478. struct hfs_cat_entry *entry = fork->entry;
  479. struct hfs_mdb *mdb = entry->mdb;
  480. struct hfs_extent *ext;
  481. int i, start, err;
  482. hfs_u16 need, len=0;
  483. hfs_u32 ablksz = mdb->alloc_blksz;
  484. hfs_u32 blocks, clumpablks;
  485. blocks = fork->psize;
  486. need = ablocks - blocks/ablksz;
  487. if (need < 1) { /* no need to grow the fork */
  488. return 0;
  489. }
  490. /* round up to clumpsize */
  491. if (entry->u.file.clumpablks) {
  492. clumpablks = entry->u.file.clumpablks;
  493. } else {
  494. clumpablks = mdb->clumpablks;
  495. }
  496. need = ((need + clumpablks - 1) / clumpablks) * clumpablks;
  497. /* find last extent record and try to extend it */
  498. if (!(ext = find_ext(fork, blocks/ablksz - 1))) {
  499. /* somehow we couldn't find the end of the file! */
  500. return -1;
  501. }
  502. /* determine which is the last used extent in the record */
  503. /* then try to allocate the blocks immediately following it */
  504. for (i=2; (i>=0) && !ext->length[i]; --i) {};
  505. if (i>=0) {
  506. /* try to extend the last extent */
  507. start = ext->block[i] + ext->length[i];
  508. err = 0;
  509. lock_bitmap(mdb);
  510. len = hfs_vbm_count_free(mdb, start);
  511. if (!len) {
  512. unlock_bitmap(mdb);
  513. goto more_extents;
  514. }
  515. if (need < len) {
  516. len = need;
  517. }
  518. err = hfs_set_vbm_bits(mdb, start, len);
  519. unlock_bitmap(mdb);
  520. if (err) {
  521. relse_ext(ext);
  522. return -1;
  523. }
  524. zero_blocks(mdb, start, len);
  525. ext->length[i] += len;
  526. ext->end += len;
  527. blocks = (fork->psize += len * ablksz);
  528. need -= len;
  529. update_ext(fork, ext);
  530. }
  531. more_extents:
  532. /* add some more extents */
  533. while (need) {
  534. len = need;
  535. err = 0;
  536. lock_bitmap(mdb);
  537. start = hfs_vbm_search_free(mdb, &len);
  538. if (need < len) {
  539. len = need;
  540. }
  541. err = hfs_set_vbm_bits(mdb, start, len);
  542. unlock_bitmap(mdb);
  543. if (!len || err) {
  544. relse_ext(ext);
  545. return -1;
  546. }
  547. zero_blocks(mdb, start, len);
  548. /* determine which is the first free extent in the record */
  549. for (i=0; (i<3) && ext->length[i]; ++i) {};
  550. if (i < 3) {
  551. ext->block[i] = start;
  552. ext->length[i] = len;
  553. ext->end += len;
  554. update_ext(fork, ext);
  555. } else {
  556. if (!(ext = new_extent(fork, ext, blocks/ablksz,
  557.        start, len, ablksz))) {
  558. lock_bitmap(mdb);
  559. hfs_clear_vbm_bits(mdb, start, len);
  560. unlock_bitmap(mdb);
  561. return -1;
  562. }
  563. }
  564. blocks = (fork->psize += len * ablksz);
  565. need -= len;
  566. }
  567. set_cache(fork, ext);
  568. relse_ext(ext);
  569. return 0;
  570. }
  571. /*================ Global functions ================*/
  572. /*
  573.  * hfs_ext_compare()
  574.  *
  575.  * Description:
  576.  *   This is the comparison function used for the extents B-tree.  In
  577.  *   comparing extent B-tree entries, the file id is the most
  578.  *   significant field (compared as unsigned ints); the fork type is
  579.  *   the second most significant field (compared as unsigned chars);
  580.  *   and the allocation block number field is the least significant
  581.  *   (compared as unsigned ints).
  582.  * Input Variable(s):
  583.  *   struct hfs_ext_key *key1: pointer to the first key to compare
  584.  *   struct hfs_ext_key *key2: pointer to the second key to compare
  585.  * Output Variable(s):
  586.  *   NONE
  587.  * Returns:
  588.  *   int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2
  589.  * Preconditions:
  590.  *   key1 and key2 point to "valid" (struct hfs_ext_key)s.
  591.  * Postconditions:
  592.  *   This function has no side-effects */
  593. int hfs_ext_compare(const struct hfs_ext_key *key1,
  594.     const struct hfs_ext_key *key2)
  595. {
  596. unsigned int tmp;
  597. int retval;
  598. tmp = hfs_get_hl(key1->FNum) - hfs_get_hl(key2->FNum);
  599. if (tmp != 0) {
  600. retval = (int)tmp;
  601. } else {
  602. tmp = (unsigned char)key1->FkType - (unsigned char)key2->FkType;
  603. if (tmp != 0) {
  604. retval = (int)tmp;
  605. } else {
  606. retval = (int)(hfs_get_hs(key1->FABN)
  607.        - hfs_get_hs(key2->FABN));
  608. }
  609. }
  610. return retval;
  611. }
  612. /*
  613.  * hfs_extent_adj()
  614.  *
  615.  * Given an hfs_fork shrink or grow the fork to hold the
  616.  * forks logical size.
  617.  */
  618. void hfs_extent_adj(struct hfs_fork *fork)
  619. {
  620. if (fork) {
  621. hfs_u32 blks, ablocks, ablksz;
  622. if (fork->lsize > HFS_FORK_MAX) {
  623. fork->lsize = HFS_FORK_MAX;
  624. }
  625. blks = (fork->lsize+HFS_SECTOR_SIZE-1) >> HFS_SECTOR_SIZE_BITS;
  626. ablksz = fork->entry->mdb->alloc_blksz;
  627. ablocks = (blks + ablksz - 1) / ablksz;
  628. if (blks > fork->psize) {
  629. grow_fork(fork, ablocks);
  630. if (blks > fork->psize) {
  631. fork->lsize =
  632. fork->psize >> HFS_SECTOR_SIZE_BITS;
  633. }
  634. } else if (blks < fork->psize) {
  635. shrink_fork(fork, ablocks);
  636. }
  637. }
  638. }
  639. /*
  640.  * hfs_extent_map()
  641.  *
  642.  * Given an hfs_fork and a block number within the fork, return the
  643.  * number of the corresponding physical block on disk, or zero on
  644.  * error.
  645.  */
  646. int hfs_extent_map(struct hfs_fork *fork, int block, int create) 
  647. {
  648. int ablksz, ablock, offset, tmp;
  649. struct hfs_extent *ext;
  650. if (!fork || !fork->entry || !fork->entry->mdb) {
  651. return 0;
  652. }
  653. #if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
  654. hfs_warn("hfs_extent_map: ablock %d of file %d, fork %dn",
  655.  block, fork->entry->cnid, fork->fork);
  656. #endif
  657. if (block < 0) {
  658. hfs_warn("hfs_extent_map: block < 0n");
  659. return 0;
  660. }
  661. if (block > (HFS_FORK_MAX >> HFS_SECTOR_SIZE_BITS)) {
  662. hfs_warn("hfs_extent_map: block(0x%08x) > big; cnid=%d "
  663.  "fork=%dn", block, fork->entry->cnid, fork->fork);
  664. return 0;
  665. }
  666. ablksz = fork->entry->mdb->alloc_blksz;
  667. offset = fork->entry->mdb->fs_start + (block % ablksz);
  668. ablock = block / ablksz;
  669. if (block >= fork->psize) {
  670. if (!create || (grow_fork(fork, ablock + 1) < 0))
  671. return 0;
  672. }
  673. #if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
  674. hfs_warn("(lblock %d offset %d)n", ablock, offset);
  675. #endif
  676. if ((ext = find_ext(fork, ablock))) {
  677. dump_ext("trying new: ", ext);
  678. tmp = decode_extent(ext, ablock);
  679. relse_ext(ext);
  680. if (tmp >= 0) {
  681. return tmp*ablksz + offset;
  682. }
  683. return 0;
  684. }
  685. /*
  686.  * hfs_extent_out()
  687.  *
  688.  * Copy the first extent record from a (struct hfs_fork) to a (struct
  689.  * raw_extent), record (normally the one in the catalog entry).
  690.  */
  691. void hfs_extent_out(const struct hfs_fork *fork, hfs_byte_t dummy[12])
  692. {
  693. struct hfs_raw_extent *ext = (struct hfs_raw_extent *)dummy;
  694. if (fork && ext) {
  695. write_extent(ext, &fork->first);
  696. dump_ext("extent out: ", &fork->first);
  697. }
  698. }
  699. /*
  700.  * hfs_extent_in()
  701.  *
  702.  * Copy an raw_extent to the 'first' and 'cache' fields of an hfs_fork.
  703.  */
  704. void hfs_extent_in(struct hfs_fork *fork, const hfs_byte_t dummy[12])
  705. {
  706. const struct hfs_raw_extent *ext =
  707. (const struct hfs_raw_extent *)dummy;
  708. if (fork && ext) {
  709. read_extent(&fork->first, ext, 0);
  710. fork->cache = &fork->first;
  711. fork->first.count = 2;
  712. dump_ext("extent in: ", &fork->first);
  713. }
  714. }
  715. /* 
  716.  * hfs_extent_free()
  717.  *
  718.  * Removes from memory all extents associated with 'fil'.
  719.  */
  720. void hfs_extent_free(struct hfs_fork *fork)
  721. {
  722. if (fork) {
  723. set_cache(fork, &fork->first);
  724.         if (fork->first.next) {
  725.         hfs_warn("hfs_extent_free: extents in use!n");
  726. }
  727. }
  728. }