partition.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * partition.c
  3. *
  4. * PURPOSE
  5. * Partition handling routines for the OSTA-UDF(tm) filesystem.
  6. *
  7. * COPYRIGHT
  8. * This file is distributed under the terms of the GNU General Public
  9. * License (GPL). Copies of the GPL can be obtained from:
  10. * ftp://prep.ai.mit.edu/pub/gnu/GPL
  11. * Each contributing author retains all rights to their own work.
  12. *
  13. * (C) 1998-2001 Ben Fennema
  14. *
  15. * HISTORY
  16. *
  17. * 12/06/98 blf Created file.
  18. *
  19. */
  20. #include "udfdecl.h"
  21. #include "udf_sb.h"
  22. #include "udf_i.h"
  23. #include <linux/fs.h>
  24. #include <linux/string.h>
  25. #include <linux/udf_fs.h>
  26. #include <linux/slab.h>
  27. #include <linux/buffer_head.h>
  28. inline uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
  29. uint16_t partition, uint32_t offset)
  30. {
  31. if (partition >= UDF_SB_NUMPARTS(sb)) {
  32. udf_debug
  33. ("block=%d, partition=%d, offset=%d: invalid partition\n",
  34. block, partition, offset);
  35. return 0xFFFFFFFF;
  36. }
  37. if (UDF_SB_PARTFUNC(sb, partition))
  38. return UDF_SB_PARTFUNC(sb, partition) (sb, block, partition,
  39. offset);
  40. else
  41. return UDF_SB_PARTROOT(sb, partition) + block + offset;
  42. }
  43. uint32_t udf_get_pblock_virt15(struct super_block * sb, uint32_t block,
  44. uint16_t partition, uint32_t offset)
  45. {
  46. struct buffer_head *bh = NULL;
  47. uint32_t newblock;
  48. uint32_t index;
  49. uint32_t loc;
  50. index =
  51. (sb->s_blocksize -
  52. UDF_SB_TYPEVIRT(sb, partition).s_start_offset) / sizeof(uint32_t);
  53. if (block > UDF_SB_TYPEVIRT(sb, partition).s_num_entries) {
  54. udf_debug
  55. ("Trying to access block beyond end of VAT (%d max %d)\n",
  56. block, UDF_SB_TYPEVIRT(sb, partition).s_num_entries);
  57. return 0xFFFFFFFF;
  58. }
  59. if (block >= index) {
  60. block -= index;
  61. newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
  62. index = block % (sb->s_blocksize / sizeof(uint32_t));
  63. } else {
  64. newblock = 0;
  65. index =
  66. UDF_SB_TYPEVIRT(sb,
  67. partition).s_start_offset /
  68. sizeof(uint32_t) + block;
  69. }
  70. loc = udf_block_map(UDF_SB_VAT(sb), newblock);
  71. if (!(bh = sb_bread(sb, loc))) {
  72. udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
  73. sb, block, partition, loc, index);
  74. return 0xFFFFFFFF;
  75. }
  76. loc = le32_to_cpu(((__le32 *) bh->b_data)[index]);
  77. brelse(bh);
  78. if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition) {
  79. udf_debug("recursive call to udf_get_pblock!\n");
  80. return 0xFFFFFFFF;
  81. }
  82. return udf_get_pblock(sb, loc,
  83. UDF_I_LOCATION(UDF_SB_VAT(sb)).
  84. partitionReferenceNum, offset);
  85. }
  86. inline uint32_t udf_get_pblock_virt20(struct super_block * sb, uint32_t block,
  87. uint16_t partition, uint32_t offset)
  88. {
  89. return udf_get_pblock_virt15(sb, block, partition, offset);
  90. }
  91. uint32_t udf_get_pblock_spar15(struct super_block * sb, uint32_t block,
  92. uint16_t partition, uint32_t offset)
  93. {
  94. int i;
  95. struct sparingTable *st = NULL;
  96. uint32_t packet =
  97. (block + offset) & ~(UDF_SB_TYPESPAR(sb, partition).s_packet_len -
  98. 1);
  99. for (i = 0; i < 4; i++) {
  100. if (UDF_SB_TYPESPAR(sb, partition).s_spar_map[i] != NULL) {
  101. st = (struct sparingTable *)UDF_SB_TYPESPAR(sb,
  102. partition).
  103. s_spar_map[i]->b_data;
  104. break;
  105. }
  106. }
  107. if (st) {
  108. for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) {
  109. if (le32_to_cpu(st->mapEntry[i].origLocation) >=
  110. 0xFFFFFFF0)
  111. break;
  112. else if (le32_to_cpu(st->mapEntry[i].origLocation) ==
  113. packet) {
  114. return le32_to_cpu(st->mapEntry[i].
  115. mappedLocation) + ((block +
  116. offset) &
  117. (UDF_SB_TYPESPAR
  118. (sb,
  119. partition).
  120. s_packet_len
  121. - 1));
  122. } else if (le32_to_cpu(st->mapEntry[i].origLocation) >
  123. packet)
  124. break;
  125. }
  126. }
  127. return UDF_SB_PARTROOT(sb, partition) + block + offset;
  128. }
  129. int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
  130. {
  131. struct udf_sparing_data *sdata;
  132. struct sparingTable *st = NULL;
  133. struct sparingEntry mapEntry;
  134. uint32_t packet;
  135. int i, j, k, l;
  136. for (i = 0; i < UDF_SB_NUMPARTS(sb); i++) {
  137. if (old_block > UDF_SB_PARTROOT(sb, i) &&
  138. old_block < UDF_SB_PARTROOT(sb, i) + UDF_SB_PARTLEN(sb, i))
  139. {
  140. sdata = &UDF_SB_TYPESPAR(sb, i);
  141. packet =
  142. (old_block -
  143. UDF_SB_PARTROOT(sb,
  144. i)) & ~(sdata->s_packet_len - 1);
  145. for (j = 0; j < 4; j++) {
  146. if (UDF_SB_TYPESPAR(sb, i).s_spar_map[j] !=
  147. NULL) {
  148. st = (struct sparingTable *)sdata->
  149. s_spar_map[j]->b_data;
  150. break;
  151. }
  152. }
  153. if (!st)
  154. return 1;
  155. for (k = 0; k < le16_to_cpu(st->reallocationTableLen);
  156. k++) {
  157. if (le32_to_cpu(st->mapEntry[k].origLocation) ==
  158. 0xFFFFFFFF) {
  159. for (; j < 4; j++) {
  160. if (sdata->s_spar_map[j]) {
  161. st = (struct
  162. sparingTable *)
  163. sdata->
  164. s_spar_map[j]->
  165. b_data;
  166. st->mapEntry[k].
  167. origLocation =
  168. cpu_to_le32(packet);
  169. udf_update_tag((char *)
  170. st,
  171. sizeof
  172. (struct
  173. sparingTable)
  174. +
  175. le16_to_cpu
  176. (st->
  177. reallocationTableLen)
  178. *
  179. sizeof
  180. (struct
  181. sparingEntry));
  182. mark_buffer_dirty
  183. (sdata->
  184. s_spar_map[j]);
  185. }
  186. }
  187. *new_block =
  188. le32_to_cpu(st->mapEntry[k].
  189. mappedLocation) +
  190. ((old_block -
  191. UDF_SB_PARTROOT(sb,
  192. i)) & (sdata->
  193. s_packet_len
  194. - 1));
  195. return 0;
  196. } else
  197. if (le32_to_cpu
  198. (st->mapEntry[k].origLocation) ==
  199. packet) {
  200. *new_block =
  201. le32_to_cpu(st->mapEntry[k].
  202. mappedLocation) +
  203. ((old_block -
  204. UDF_SB_PARTROOT(sb,
  205. i)) & (sdata->
  206. s_packet_len
  207. - 1));
  208. return 0;
  209. } else
  210. if (le32_to_cpu
  211. (st->mapEntry[k].origLocation) > packet)
  212. break;
  213. }
  214. for (l = k; l < le16_to_cpu(st->reallocationTableLen);
  215. l++) {
  216. if (le32_to_cpu(st->mapEntry[l].origLocation) ==
  217. 0xFFFFFFFF) {
  218. for (; j < 4; j++) {
  219. if (sdata->s_spar_map[j]) {
  220. st = (struct
  221. sparingTable *)
  222. sdata->
  223. s_spar_map[j]->
  224. b_data;
  225. mapEntry =
  226. st->mapEntry[l];
  227. mapEntry.origLocation =
  228. cpu_to_le32(packet);
  229. memmove(&st->
  230. mapEntry[k + 1],
  231. &st->
  232. mapEntry[k],
  233. (l -
  234. k) *
  235. sizeof(struct
  236. sparingEntry));
  237. st->mapEntry[k] =
  238. mapEntry;
  239. udf_update_tag((char *)
  240. st,
  241. sizeof
  242. (struct
  243. sparingTable)
  244. +
  245. le16_to_cpu
  246. (st->
  247. reallocationTableLen)
  248. *
  249. sizeof
  250. (struct
  251. sparingEntry));
  252. mark_buffer_dirty
  253. (sdata->
  254. s_spar_map[j]);
  255. }
  256. }
  257. *new_block =
  258. le32_to_cpu(st->mapEntry[k].
  259. mappedLocation) +
  260. ((old_block -
  261. UDF_SB_PARTROOT(sb,
  262. i)) & (sdata->
  263. s_packet_len
  264. - 1));
  265. return 0;
  266. }
  267. }
  268. return 1;
  269. }
  270. }
  271. if (i == UDF_SB_NUMPARTS(sb)) {
  272. /* outside of partitions */
  273. /* for now, fail =) */
  274. return 1;
  275. }
  276. return 0;
  277. }