partition.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * partition.c
  3.  *
  4.  * PURPOSE
  5.  *      Partition handling routines for the OSTA-UDF(tm) filesystem.
  6.  *
  7.  * CONTACTS
  8.  *      E-mail regarding any portion of the Linux UDF file system should be
  9.  *      directed to the development team mailing list (run by majordomo):
  10.  *              linux_udf@hpesjro.fc.hp.com
  11.  *
  12.  * COPYRIGHT
  13.  *      This file is distributed under the terms of the GNU General Public
  14.  *      License (GPL). Copies of the GPL can be obtained from:
  15.  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
  16.  *      Each contributing author retains all rights to their own work.
  17.  *
  18.  *  (C) 1998-2000 Ben Fennema
  19.  *
  20.  * HISTORY
  21.  *
  22.  * 12/06/98 blf  Created file. 
  23.  *
  24.  */
  25. #include "udfdecl.h"
  26. #include "udf_sb.h"
  27. #include "udf_i.h"
  28. #include <linux/fs.h>
  29. #include <linux/string.h>
  30. #include <linux/udf_fs.h>
  31. #include <linux/slab.h>
  32. inline Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
  33. {
  34. if (partition >= UDF_SB_NUMPARTS(sb))
  35. {
  36. udf_debug("block=%d, partition=%d, offset=%d: invalid partitionn",
  37. block, partition, offset);
  38. return 0xFFFFFFFF;
  39. }
  40. if (UDF_SB_PARTFUNC(sb, partition))
  41. return UDF_SB_PARTFUNC(sb, partition)(sb, block, partition, offset);
  42. else
  43. return UDF_SB_PARTROOT(sb, partition) + block + offset;
  44. }
  45. Uint32 udf_get_pblock_virt15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
  46. {
  47. struct buffer_head *bh = NULL;
  48. Uint32 newblock;
  49. Uint32 index;
  50. Uint32 loc;
  51. index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(Uint32);
  52. if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
  53. {
  54. udf_debug("Trying to access block beyond end of VAT (%d max %d)n",
  55. block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries);
  56. return 0xFFFFFFFF;
  57. }
  58. if (block >= index)
  59. {
  60. block -= index;
  61. newblock = 1 + (block / (sb->s_blocksize / sizeof(Uint32)));
  62. index = block % (sb->s_blocksize / sizeof(Uint32));
  63. }
  64. else
  65. {
  66. newblock = 0;
  67. index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block;
  68. }
  69. loc = udf_block_map(UDF_SB_VAT(sb), newblock);
  70. if (!(bh = sb_bread(sb, loc)))
  71. {
  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(((Uint32 *)bh->b_data)[index]);
  77. udf_release_data(bh);
  78. if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
  79. {
  80. udf_debug("recursive call to udf_get_pblock!n");
  81. return 0xFFFFFFFF;
  82. }
  83. return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
  84. }
  85. inline Uint32 udf_get_pblock_virt20(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
  86. {
  87. return udf_get_pblock_virt15(sb, block, partition, offset);
  88. }
  89. Uint32 udf_get_pblock_spar15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
  90. {
  91. int i;
  92. struct SparingTable *st = NULL;
  93. Uint32 packet = (block + offset) & ~(UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1);
  94. for (i=0; i<4; i++)
  95. {
  96. if (UDF_SB_TYPESPAR(sb,partition).s_spar_map[i] != NULL)
  97. {
  98. st = (struct SparingTable *)UDF_SB_TYPESPAR(sb,partition).s_spar_map[i]->b_data;
  99. break;
  100. }
  101. }
  102. if (st)
  103. {
  104. for (i=0; i<st->reallocationTableLen; i++)
  105. {
  106. if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0)
  107. break;
  108. else if (le32_to_cpu(st->mapEntry[i].origLocation) == packet)
  109. {
  110. return le32_to_cpu(st->mapEntry[i].mappedLocation) +
  111. ((block + offset) & (UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1));
  112. }
  113. else if (le32_to_cpu(st->mapEntry[i].origLocation) > packet)
  114. break;
  115. }
  116. }
  117. return UDF_SB_PARTROOT(sb,partition) + block + offset;
  118. }
  119. int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
  120. {
  121. struct udf_sparing_data *sdata;
  122. struct SparingTable *st = NULL;
  123. SparingEntry mapEntry;
  124. Uint32 packet;
  125. int i, j, k, l;
  126. for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
  127. {
  128. if (old_block > UDF_SB_PARTROOT(sb,i) &&
  129.     old_block < UDF_SB_PARTROOT(sb,i) + UDF_SB_PARTLEN(sb,i))
  130. {
  131. sdata = &UDF_SB_TYPESPAR(sb,i);
  132. packet = (old_block - UDF_SB_PARTROOT(sb,i)) & ~(sdata->s_packet_len - 1);
  133. for (j=0; j<4; j++)
  134. {
  135. if (UDF_SB_TYPESPAR(sb,i).s_spar_map[j] != NULL)
  136. {
  137. st = (struct SparingTable *)sdata->s_spar_map[j]->b_data;
  138. break;
  139. }
  140. }
  141. if (!st)
  142. return 1;
  143. for (k=0; k<st->reallocationTableLen; k++)
  144. {
  145. if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF)
  146. {
  147. for (; j<4; j++)
  148. {
  149. if (sdata->s_spar_map[j])
  150. {
  151. st = (struct SparingTable *)sdata->s_spar_map[j]->b_data;
  152. st->mapEntry[k].origLocation = cpu_to_le32(packet);
  153. udf_update_tag((char *)st, sizeof(struct SparingTable) + st->reallocationTableLen * sizeof(SparingEntry));
  154. mark_buffer_dirty(sdata->s_spar_map[j]);
  155. }
  156. }
  157. *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) +
  158. ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1));
  159. return 0;
  160. }
  161. else if (le32_to_cpu(st->mapEntry[k].origLocation) == packet)
  162. {
  163. *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) +
  164. ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1));
  165. return 0;
  166. }
  167. else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet)
  168. break;
  169. }
  170. for (l=k; l<st->reallocationTableLen; l++)
  171. {
  172. if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF)
  173. {
  174. for (; j<4; j++)
  175. {
  176. if (sdata->s_spar_map[j])
  177. {
  178. st = (struct SparingTable *)sdata->s_spar_map[j]->b_data;
  179. mapEntry = st->mapEntry[l];
  180. mapEntry.origLocation = cpu_to_le32(packet);
  181. memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(SparingEntry));
  182. st->mapEntry[k] = mapEntry;
  183. udf_update_tag((char *)st, sizeof(struct SparingTable) + st->reallocationTableLen * sizeof(SparingEntry));
  184. mark_buffer_dirty(sdata->s_spar_map[j]);
  185. }
  186. }
  187. *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) +
  188. ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1));
  189. return 0;
  190. }
  191. }
  192. return 1;
  193. }
  194. }
  195. if (i == UDF_SB_NUMPARTS(sb))
  196. {
  197. /* outside of partitions */
  198. /* for now, fail =) */
  199. return 1;
  200. }
  201. return 0;
  202. }