datastream.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /*
  2. * linux/fs/befs/datastream.c
  3. *
  4. * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com>
  5. *
  6. * Based on portions of file.c by Makoto Kato <m_kato@ga2.so-net.ne.jp>
  7. *
  8. * Many thanks to Dominic Giampaolo, author of "Practical File System
  9. * Design with the Be File System", for such a helpful book.
  10. *
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/buffer_head.h>
  14. #include <linux/string.h>
  15. #include "befs.h"
  16. #include "datastream.h"
  17. #include "io.h"
  18. const befs_inode_addr BAD_IADDR = { 0, 0, 0 };
  19. static int befs_find_brun_direct(struct super_block *sb,
  20. const befs_data_stream *data,
  21. befs_blocknr_t blockno, befs_block_run *run);
  22. static int befs_find_brun_indirect(struct super_block *sb,
  23. const befs_data_stream *data,
  24. befs_blocknr_t blockno,
  25. befs_block_run *run);
  26. static int befs_find_brun_dblindirect(struct super_block *sb,
  27. const befs_data_stream *data,
  28. befs_blocknr_t blockno,
  29. befs_block_run *run);
  30. /**
  31. * befs_read_datastream - get buffer_head containing data, starting from pos.
  32. * @sb: Filesystem superblock
  33. * @ds: datastream to find data with
  34. * @pos: start of data
  35. * @off: offset of data in buffer_head->b_data
  36. *
  37. * Returns pointer to buffer_head containing data starting with offset @off,
  38. * if you don't need to know offset just set @off = NULL.
  39. */
  40. struct buffer_head *
  41. befs_read_datastream(struct super_block *sb, const befs_data_stream *ds,
  42. befs_off_t pos, uint *off)
  43. {
  44. struct buffer_head *bh;
  45. befs_block_run run;
  46. befs_blocknr_t block; /* block coresponding to pos */
  47. befs_debug(sb, "---> %s %llu", __func__, pos);
  48. block = pos >> BEFS_SB(sb)->block_shift;
  49. if (off)
  50. *off = pos - (block << BEFS_SB(sb)->block_shift);
  51. if (befs_fblock2brun(sb, ds, block, &run) != BEFS_OK) {
  52. befs_error(sb, "BeFS: Error finding disk addr of block %lu",
  53. (unsigned long)block);
  54. befs_debug(sb, "<--- %s ERROR", __func__);
  55. return NULL;
  56. }
  57. bh = befs_bread_iaddr(sb, run);
  58. if (!bh) {
  59. befs_error(sb, "BeFS: Error reading block %lu from datastream",
  60. (unsigned long)block);
  61. return NULL;
  62. }
  63. befs_debug(sb, "<--- %s read data, starting at %llu", __func__, pos);
  64. return bh;
  65. }
  66. /**
  67. * befs_fblock2brun - give back block run for fblock
  68. * @sb: the superblock
  69. * @data: datastream to read from
  70. * @fblock: the blocknumber with the file position to find
  71. * @run: The found run is passed back through this pointer
  72. *
  73. * Takes a file position and gives back a brun who's starting block
  74. * is block number fblock of the file.
  75. *
  76. * Returns BEFS_OK or BEFS_ERR.
  77. *
  78. * Calls specialized functions for each of the three possible
  79. * datastream regions.
  80. *
  81. * 2001-11-15 Will Dyson
  82. */
  83. int
  84. befs_fblock2brun(struct super_block *sb, const befs_data_stream *data,
  85. befs_blocknr_t fblock, befs_block_run *run)
  86. {
  87. int err;
  88. befs_off_t pos = fblock << BEFS_SB(sb)->block_shift;
  89. if (pos < data->max_direct_range) {
  90. err = befs_find_brun_direct(sb, data, fblock, run);
  91. } else if (pos < data->max_indirect_range) {
  92. err = befs_find_brun_indirect(sb, data, fblock, run);
  93. } else if (pos < data->max_double_indirect_range) {
  94. err = befs_find_brun_dblindirect(sb, data, fblock, run);
  95. } else {
  96. befs_error(sb,
  97. "befs_fblock2brun() was asked to find block %lu, "
  98. "which is not mapped by the datastream\n",
  99. (unsigned long)fblock);
  100. err = BEFS_ERR;
  101. }
  102. return err;
  103. }
  104. /**
  105. * befs_read_lsmylink - read long symlink from datastream.
  106. * @sb: Filesystem superblock
  107. * @ds: Datastream to read from
  108. * @buff: Buffer in which to place long symlink data
  109. * @len: Length of the long symlink in bytes
  110. *
  111. * Returns the number of bytes read
  112. */
  113. size_t
  114. befs_read_lsymlink(struct super_block *sb, const befs_data_stream *ds,
  115. void *buff, befs_off_t len)
  116. {
  117. befs_off_t bytes_read = 0; /* bytes readed */
  118. u16 plen;
  119. struct buffer_head *bh;
  120. befs_debug(sb, "---> %s length: %llu", __func__, len);
  121. while (bytes_read < len) {
  122. bh = befs_read_datastream(sb, ds, bytes_read, NULL);
  123. if (!bh) {
  124. befs_error(sb, "BeFS: Error reading datastream block "
  125. "starting from %llu", bytes_read);
  126. befs_debug(sb, "<--- %s ERROR", __func__);
  127. return bytes_read;
  128. }
  129. plen = ((bytes_read + BEFS_SB(sb)->block_size) < len) ?
  130. BEFS_SB(sb)->block_size : len - bytes_read;
  131. memcpy(buff + bytes_read, bh->b_data, plen);
  132. brelse(bh);
  133. bytes_read += plen;
  134. }
  135. befs_debug(sb, "<--- %s read %u bytes", __func__, (unsigned int)
  136. bytes_read);
  137. return bytes_read;
  138. }
  139. /**
  140. * befs_count_blocks - blocks used by a file
  141. * @sb: Filesystem superblock
  142. * @ds: Datastream of the file
  143. *
  144. * Counts the number of fs blocks that the file represented by
  145. * inode occupies on the filesystem, counting both regular file
  146. * data and filesystem metadata (and eventually attribute data
  147. * when we support attributes)
  148. */
  149. befs_blocknr_t
  150. befs_count_blocks(struct super_block *sb, const befs_data_stream *ds)
  151. {
  152. befs_blocknr_t blocks;
  153. befs_blocknr_t datablocks; /* File data blocks */
  154. befs_blocknr_t metablocks; /* FS metadata blocks */
  155. struct befs_sb_info *befs_sb = BEFS_SB(sb);
  156. befs_debug(sb, "---> %s", __func__);
  157. datablocks = ds->size >> befs_sb->block_shift;
  158. if (ds->size & (befs_sb->block_size - 1))
  159. datablocks += 1;
  160. metablocks = 1; /* Start with 1 block for inode */
  161. /* Size of indirect block */
  162. if (ds->size > ds->max_direct_range)
  163. metablocks += ds->indirect.len;
  164. /*
  165. * Double indir block, plus all the indirect blocks it maps.
  166. * In the double-indirect range, all block runs of data are
  167. * BEFS_DBLINDIR_BRUN_LEN blocks long. Therefore, we know
  168. * how many data block runs are in the double-indirect region,
  169. * and from that we know how many indirect blocks it takes to
  170. * map them. We assume that the indirect blocks are also
  171. * BEFS_DBLINDIR_BRUN_LEN blocks long.
  172. */
  173. if (ds->size > ds->max_indirect_range && ds->max_indirect_range != 0) {
  174. uint dbl_bytes;
  175. uint dbl_bruns;
  176. uint indirblocks;
  177. dbl_bytes =
  178. ds->max_double_indirect_range - ds->max_indirect_range;
  179. dbl_bruns =
  180. dbl_bytes / (befs_sb->block_size * BEFS_DBLINDIR_BRUN_LEN);
  181. indirblocks = dbl_bruns / befs_iaddrs_per_block(sb);
  182. metablocks += ds->double_indirect.len;
  183. metablocks += indirblocks;
  184. }
  185. blocks = datablocks + metablocks;
  186. befs_debug(sb, "<--- %s %u blocks", __func__, (unsigned int)blocks);
  187. return blocks;
  188. }
  189. /**
  190. * befs_find_brun_direct - find a direct block run in the datastream
  191. * @sb: the superblock
  192. * @data: the datastream
  193. * @blockno: the blocknumber to find
  194. * @run: The found run is passed back through this pointer
  195. *
  196. * Finds the block run that starts at file block number blockno
  197. * in the file represented by the datastream data, if that
  198. * blockno is in the direct region of the datastream.
  199. *
  200. * Return value is BEFS_OK if the blockrun is found, BEFS_ERR
  201. * otherwise.
  202. *
  203. * Algorithm:
  204. * Linear search. Checks each element of array[] to see if it
  205. * contains the blockno-th filesystem block. This is necessary
  206. * because the block runs map variable amounts of data. Simply
  207. * keeps a count of the number of blocks searched so far (sum),
  208. * incrementing this by the length of each block run as we come
  209. * across it. Adds sum to *count before returning (this is so
  210. * you can search multiple arrays that are logicaly one array,
  211. * as in the indirect region code).
  212. *
  213. * When/if blockno is found, if blockno is inside of a block
  214. * run as stored on disk, we offset the start and length members
  215. * of the block run, so that blockno is the start and len is
  216. * still valid (the run ends in the same place).
  217. */
  218. static int
  219. befs_find_brun_direct(struct super_block *sb, const befs_data_stream *data,
  220. befs_blocknr_t blockno, befs_block_run *run)
  221. {
  222. int i;
  223. const befs_block_run *array = data->direct;
  224. befs_blocknr_t sum;
  225. befs_debug(sb, "---> %s, find %lu", __func__, (unsigned long)blockno);
  226. for (i = 0, sum = 0; i < BEFS_NUM_DIRECT_BLOCKS;
  227. sum += array[i].len, i++) {
  228. if (blockno >= sum && blockno < sum + (array[i].len)) {
  229. int offset = blockno - sum;
  230. run->allocation_group = array[i].allocation_group;
  231. run->start = array[i].start + offset;
  232. run->len = array[i].len - offset;
  233. befs_debug(sb, "---> %s, "
  234. "found %lu at direct[%d]", __func__,
  235. (unsigned long)blockno, i);
  236. return BEFS_OK;
  237. }
  238. }
  239. befs_error(sb, "%s failed to find file block %lu", __func__,
  240. (unsigned long)blockno);
  241. befs_debug(sb, "---> %s ERROR", __func__);
  242. return BEFS_ERR;
  243. }
  244. /**
  245. * befs_find_brun_indirect - find a block run in the datastream
  246. * @sb: the superblock
  247. * @data: the datastream
  248. * @blockno: the blocknumber to find
  249. * @run: The found run is passed back through this pointer
  250. *
  251. * Finds the block run that starts at file block number blockno
  252. * in the file represented by the datastream data, if that
  253. * blockno is in the indirect region of the datastream.
  254. *
  255. * Return value is BEFS_OK if the blockrun is found, BEFS_ERR
  256. * otherwise.
  257. *
  258. * Algorithm:
  259. * For each block in the indirect run of the datastream, read
  260. * it in and search through it for search_blk.
  261. *
  262. * XXX:
  263. * Really should check to make sure blockno is inside indirect
  264. * region.
  265. */
  266. static int
  267. befs_find_brun_indirect(struct super_block *sb,
  268. const befs_data_stream *data,
  269. befs_blocknr_t blockno,
  270. befs_block_run *run)
  271. {
  272. int i, j;
  273. befs_blocknr_t sum = 0;
  274. befs_blocknr_t indir_start_blk;
  275. befs_blocknr_t search_blk;
  276. struct buffer_head *indirblock;
  277. befs_disk_block_run *array;
  278. befs_block_run indirect = data->indirect;
  279. befs_blocknr_t indirblockno = iaddr2blockno(sb, &indirect);
  280. int arraylen = befs_iaddrs_per_block(sb);
  281. befs_debug(sb, "---> %s, find %lu", __func__, (unsigned long)blockno);
  282. indir_start_blk = data->max_direct_range >> BEFS_SB(sb)->block_shift;
  283. search_blk = blockno - indir_start_blk;
  284. /* Examine blocks of the indirect run one at a time */
  285. for (i = 0; i < indirect.len; i++) {
  286. indirblock = sb_bread(sb, indirblockno + i);
  287. if (indirblock == NULL) {
  288. befs_error(sb, "---> %s failed to read "
  289. "disk block %lu from the indirect brun",
  290. __func__, (unsigned long)indirblockno + i);
  291. befs_debug(sb, "<--- %s ERROR", __func__);
  292. return BEFS_ERR;
  293. }
  294. array = (befs_disk_block_run *) indirblock->b_data;
  295. for (j = 0; j < arraylen; ++j) {
  296. int len = fs16_to_cpu(sb, array[j].len);
  297. if (search_blk >= sum && search_blk < sum + len) {
  298. int offset = search_blk - sum;
  299. run->allocation_group =
  300. fs32_to_cpu(sb, array[j].allocation_group);
  301. run->start =
  302. fs16_to_cpu(sb, array[j].start) + offset;
  303. run->len =
  304. fs16_to_cpu(sb, array[j].len) - offset;
  305. brelse(indirblock);
  306. befs_debug(sb,
  307. "<--- %s found file block "
  308. "%lu at indirect[%d]", __func__,
  309. (unsigned long)blockno,
  310. j + (i * arraylen));
  311. return BEFS_OK;
  312. }
  313. sum += len;
  314. }
  315. brelse(indirblock);
  316. }
  317. /* Only fallthrough is an error */
  318. befs_error(sb, "BeFS: %s failed to find "
  319. "file block %lu", __func__, (unsigned long)blockno);
  320. befs_debug(sb, "<--- %s ERROR", __func__);
  321. return BEFS_ERR;
  322. }
  323. /**
  324. * befs_find_brun_dblindirect - find a block run in the datastream
  325. * @sb: the superblock
  326. * @data: the datastream
  327. * @blockno: the blocknumber to find
  328. * @run: The found run is passed back through this pointer
  329. *
  330. * Finds the block run that starts at file block number blockno
  331. * in the file represented by the datastream data, if that
  332. * blockno is in the double-indirect region of the datastream.
  333. *
  334. * Return value is BEFS_OK if the blockrun is found, BEFS_ERR
  335. * otherwise.
  336. *
  337. * Algorithm:
  338. * The block runs in the double-indirect region are different.
  339. * They are always allocated 4 fs blocks at a time, so each
  340. * block run maps a constant amount of file data. This means
  341. * that we can directly calculate how many block runs into the
  342. * double-indirect region we need to go to get to the one that
  343. * maps a particular filesystem block.
  344. *
  345. * We do this in two stages. First we calculate which of the
  346. * inode addresses in the double-indirect block will point us
  347. * to the indirect block that contains the mapping for the data,
  348. * then we calculate which of the inode addresses in that
  349. * indirect block maps the data block we are after.
  350. *
  351. * Oh, and once we've done that, we actually read in the blocks
  352. * that contain the inode addresses we calculated above. Even
  353. * though the double-indirect run may be several blocks long,
  354. * we can calculate which of those blocks will contain the index
  355. * we are after and only read that one. We then follow it to
  356. * the indirect block and perform a similar process to find
  357. * the actual block run that maps the data block we are interested
  358. * in.
  359. *
  360. * Then we offset the run as in befs_find_brun_array() and we are
  361. * done.
  362. */
  363. static int
  364. befs_find_brun_dblindirect(struct super_block *sb,
  365. const befs_data_stream *data,
  366. befs_blocknr_t blockno,
  367. befs_block_run *run)
  368. {
  369. int dblindir_indx;
  370. int indir_indx;
  371. int offset;
  372. int dbl_which_block;
  373. int which_block;
  374. int dbl_block_indx;
  375. int block_indx;
  376. off_t dblindir_leftover;
  377. befs_blocknr_t blockno_at_run_start;
  378. struct buffer_head *dbl_indir_block;
  379. struct buffer_head *indir_block;
  380. befs_block_run indir_run;
  381. befs_disk_inode_addr *iaddr_array;
  382. befs_blocknr_t indir_start_blk =
  383. data->max_indirect_range >> BEFS_SB(sb)->block_shift;
  384. off_t dbl_indir_off = blockno - indir_start_blk;
  385. /* number of data blocks mapped by each of the iaddrs in
  386. * the indirect block pointed to by the double indirect block
  387. */
  388. size_t iblklen = BEFS_DBLINDIR_BRUN_LEN;
  389. /* number of data blocks mapped by each of the iaddrs in
  390. * the double indirect block
  391. */
  392. size_t diblklen = iblklen * befs_iaddrs_per_block(sb)
  393. * BEFS_DBLINDIR_BRUN_LEN;
  394. befs_debug(sb, "---> %s find %lu", __func__, (unsigned long)blockno);
  395. /* First, discover which of the double_indir->indir blocks
  396. * contains pos. Then figure out how much of pos that
  397. * accounted for. Then discover which of the iaddrs in
  398. * the indirect block contains pos.
  399. */
  400. dblindir_indx = dbl_indir_off / diblklen;
  401. dblindir_leftover = dbl_indir_off % diblklen;
  402. indir_indx = dblindir_leftover / diblklen;
  403. /* Read double indirect block */
  404. dbl_which_block = dblindir_indx / befs_iaddrs_per_block(sb);
  405. if (dbl_which_block > data->double_indirect.len) {
  406. befs_error(sb, "The double-indirect index calculated by "
  407. "%s, %d, is outside the range "
  408. "of the double-indirect block", __func__,
  409. dblindir_indx);
  410. return BEFS_ERR;
  411. }
  412. dbl_indir_block =
  413. sb_bread(sb, iaddr2blockno(sb, &data->double_indirect) +
  414. dbl_which_block);
  415. if (dbl_indir_block == NULL) {
  416. befs_error(sb, "%s couldn't read the "
  417. "double-indirect block at blockno %lu", __func__,
  418. (unsigned long)
  419. iaddr2blockno(sb, &data->double_indirect) +
  420. dbl_which_block);
  421. return BEFS_ERR;
  422. }
  423. dbl_block_indx =
  424. dblindir_indx - (dbl_which_block * befs_iaddrs_per_block(sb));
  425. iaddr_array = (befs_disk_inode_addr *) dbl_indir_block->b_data;
  426. indir_run = fsrun_to_cpu(sb, iaddr_array[dbl_block_indx]);
  427. brelse(dbl_indir_block);
  428. /* Read indirect block */
  429. which_block = indir_indx / befs_iaddrs_per_block(sb);
  430. if (which_block > indir_run.len) {
  431. befs_error(sb, "The indirect index calculated by "
  432. "%s, %d, is outside the range "
  433. "of the indirect block", __func__, indir_indx);
  434. return BEFS_ERR;
  435. }
  436. indir_block =
  437. sb_bread(sb, iaddr2blockno(sb, &indir_run) + which_block);
  438. if (indir_block == NULL) {
  439. befs_error(sb, "%s couldn't read the indirect block "
  440. "at blockno %lu", __func__, (unsigned long)
  441. iaddr2blockno(sb, &indir_run) + which_block);
  442. return BEFS_ERR;
  443. }
  444. block_indx = indir_indx - (which_block * befs_iaddrs_per_block(sb));
  445. iaddr_array = (befs_disk_inode_addr *) indir_block->b_data;
  446. *run = fsrun_to_cpu(sb, iaddr_array[block_indx]);
  447. brelse(indir_block);
  448. blockno_at_run_start = indir_start_blk;
  449. blockno_at_run_start += diblklen * dblindir_indx;
  450. blockno_at_run_start += iblklen * indir_indx;
  451. offset = blockno - blockno_at_run_start;
  452. run->start += offset;
  453. run->len -= offset;
  454. befs_debug(sb, "Found file block %lu in double_indirect[%d][%d],"
  455. " double_indirect_leftover = %lu", (unsigned long)
  456. blockno, dblindir_indx, indir_indx, dblindir_leftover);
  457. return BEFS_OK;
  458. }