[930baca] | 1 | #include <assert.h>
|
---|
| 2 | #include <errno.h>
|
---|
| 3 | #include "mfs.h"
|
---|
| 4 | #include "mfs_utils.h"
|
---|
| 5 |
|
---|
[155f792] | 6 | static int read_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock);
|
---|
[930baca] | 7 |
|
---|
| 8 | /*Given the position in the file expressed in
|
---|
| 9 | *bytes, this function returns the on-disk block
|
---|
| 10 | *relative to that position.
|
---|
| 11 | *Returns zero if the block does not exist.
|
---|
| 12 | */
|
---|
| 13 | int read_map(uint32_t *b, const struct mfs_node *mnode, const uint32_t pos)
|
---|
| 14 | {
|
---|
| 15 | int r;
|
---|
| 16 |
|
---|
| 17 | assert(mnode);
|
---|
| 18 | assert(mnode->instance);
|
---|
| 19 |
|
---|
| 20 | const struct mfs_sb_info *sbi = mnode->instance->sbi;
|
---|
| 21 | assert(sbi);
|
---|
| 22 |
|
---|
| 23 | const int block_size = sbi->block_size;
|
---|
| 24 |
|
---|
| 25 | /*Compute relative block number in file*/
|
---|
| 26 | int rblock = pos / block_size;
|
---|
| 27 |
|
---|
[155f792] | 28 | if (mnode->ino_i->i_size < (int32_t) pos) {
|
---|
[930baca] | 29 | r = EOK;
|
---|
[155f792] | 30 | *b = 0;
|
---|
[930baca] | 31 | goto out;
|
---|
| 32 | }
|
---|
| 33 |
|
---|
[155f792] | 34 | r = read_map_ondisk(b, mnode, rblock);
|
---|
[930baca] | 35 | out:
|
---|
| 36 | return r;
|
---|
| 37 | }
|
---|
| 38 |
|
---|
[155f792] | 39 | static int read_map_ondisk(uint32_t *b, const struct mfs_node *mnode, int rblock)
|
---|
[930baca] | 40 | {
|
---|
| 41 | block_t *bi1, *bi2;
|
---|
[155f792] | 42 | int r, nr_direct, nr_indirect;
|
---|
| 43 | int ptrs_per_block;
|
---|
[930baca] | 44 |
|
---|
| 45 | assert(mnode);
|
---|
[155f792] | 46 | const struct mfs_ino_info *ino_i = mnode->ino_i;
|
---|
[930baca] | 47 |
|
---|
[155f792] | 48 | assert(ino_i);
|
---|
[930baca] | 49 | assert(mnode->instance);
|
---|
| 50 |
|
---|
| 51 | const struct mfs_sb_info *sbi = mnode->instance->sbi;
|
---|
| 52 | assert(sbi);
|
---|
| 53 |
|
---|
[155f792] | 54 | const int fs_version = sbi->fs_version;
|
---|
| 55 |
|
---|
| 56 | if (fs_version == MFS_VERSION_V1) {
|
---|
| 57 | nr_direct = V1_NR_DIRECT_ZONES;
|
---|
| 58 | nr_indirect = V1_NR_INDIRECT_ZONES;
|
---|
| 59 | ptrs_per_block = MFS_BLOCKSIZE / sizeof(uint16_t);
|
---|
| 60 | } else {
|
---|
| 61 | nr_direct = V2_NR_DIRECT_ZONES;
|
---|
| 62 | nr_indirect = V2_NR_INDIRECT_ZONES;
|
---|
| 63 | ptrs_per_block = sbi->block_size / sizeof(uint32_t);
|
---|
| 64 | }
|
---|
[930baca] | 65 |
|
---|
[155f792] | 66 | if (rblock < nr_direct) {
|
---|
| 67 | *b = ino_i->i_dzone[rblock];
|
---|
[930baca] | 68 | r = EOK;
|
---|
| 69 | goto out;
|
---|
| 70 | }
|
---|
[155f792] | 71 | rblock -= nr_direct - 1;
|
---|
[930baca] | 72 |
|
---|
| 73 | /*Check if the wanted block is in the single indirect zone*/
|
---|
| 74 | if (rblock < ptrs_per_block) {
|
---|
[155f792] | 75 | if (ino_i->i_izone[0] == 0) {
|
---|
[930baca] | 76 | r = -1;
|
---|
| 77 | goto out;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
[155f792] | 80 | r = read_ind_block(bi2, mnode->instance, ino_i->i_izone[0]);
|
---|
[930baca] | 81 |
|
---|
| 82 | if (r != EOK)
|
---|
| 83 | goto out;
|
---|
| 84 |
|
---|
[155f792] | 85 | *b = fs_version == MFS_VERSION_V1 ?
|
---|
| 86 | ((uint16_t *) bi1->data)[rblock] :
|
---|
| 87 | ((uint32_t *) bi1->data)[rblock];
|
---|
[930baca] | 88 | goto out_block;
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | rblock -= ptrs_per_block - 1;
|
---|
| 92 |
|
---|
| 93 | /*The wanted block is in the double indirect zone*/
|
---|
| 94 | uint32_t di_block = rblock / ptrs_per_block;
|
---|
| 95 |
|
---|
| 96 | /*read the first indirect zone*/
|
---|
[155f792] | 97 | if (ino_i->i_izone[1] == 0) {
|
---|
[930baca] | 98 | r = -1;
|
---|
| 99 | goto out;
|
---|
| 100 | }
|
---|
| 101 |
|
---|
[155f792] | 102 | r = read_ind_block(bi1, mnode->instance, ino_i->i_izone[1]);
|
---|
[930baca] | 103 |
|
---|
| 104 | if (r != EOK)
|
---|
| 105 | goto out;
|
---|
| 106 |
|
---|
| 107 | /*read the second indirect zone*/
|
---|
[155f792] | 108 | if (fs_version == MFS_VERSION_V1) {
|
---|
| 109 | r = read_ind_block(bi2, mnode->instance,
|
---|
| 110 | ((uint16_t *) bi1->data)[di_block]);
|
---|
| 111 |
|
---|
| 112 | if (r != EOK)
|
---|
| 113 | goto out_block;
|
---|
| 114 |
|
---|
| 115 | *b = ((uint16_t *) bi2->data)[rblock % ptrs_per_block];
|
---|
| 116 | } else {
|
---|
| 117 | r = read_ind_block(bi2, mnode->instance,
|
---|
[930baca] | 118 | ((uint32_t *) bi1->data)[di_block]);
|
---|
| 119 |
|
---|
[155f792] | 120 | if (r != EOK)
|
---|
| 121 | goto out_block;
|
---|
[930baca] | 122 |
|
---|
[155f792] | 123 | *b = ((uint32_t *) bi2->data)[rblock % ptrs_per_block];
|
---|
| 124 | }
|
---|
[930baca] | 125 | block_put(bi2);
|
---|
| 126 |
|
---|
| 127 | out_block:
|
---|
| 128 | block_put(bi1);
|
---|
| 129 | out:
|
---|
| 130 | return r;
|
---|
| 131 | }
|
---|
| 132 |
|
---|