aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/partition.c')
-rw-r--r--fs/udf/partition.c273
1 files changed, 176 insertions, 97 deletions
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index 467a26171cd9..a95d830a674d 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -28,106 +28,120 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/buffer_head.h> 29#include <linux/buffer_head.h>
30 30
31inline uint32_t udf_get_pblock(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) 31inline uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
32 uint16_t partition, uint32_t offset)
32{ 33{
33 if (partition >= UDF_SB_NUMPARTS(sb)) 34 if (partition >= UDF_SB_NUMPARTS(sb)) {
34 { 35 udf_debug
35 udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n", 36 ("block=%d, partition=%d, offset=%d: invalid partition\n",
36 block, partition, offset); 37 block, partition, offset);
37 return 0xFFFFFFFF; 38 return 0xFFFFFFFF;
38 } 39 }
39 if (UDF_SB_PARTFUNC(sb, partition)) 40 if (UDF_SB_PARTFUNC(sb, partition))
40 return UDF_SB_PARTFUNC(sb, partition)(sb, block, partition, offset); 41 return UDF_SB_PARTFUNC(sb, partition) (sb, block, partition,
42 offset);
41 else 43 else
42 return UDF_SB_PARTROOT(sb, partition) + block + offset; 44 return UDF_SB_PARTROOT(sb, partition) + block + offset;
43} 45}
44 46
45uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) 47uint32_t udf_get_pblock_virt15(struct super_block * sb, uint32_t block,
48 uint16_t partition, uint32_t offset)
46{ 49{
47 struct buffer_head *bh = NULL; 50 struct buffer_head *bh = NULL;
48 uint32_t newblock; 51 uint32_t newblock;
49 uint32_t index; 52 uint32_t index;
50 uint32_t loc; 53 uint32_t loc;
51 54
52 index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(uint32_t); 55 index =
56 (sb->s_blocksize -
57 UDF_SB_TYPEVIRT(sb, partition).s_start_offset) / sizeof(uint32_t);
53 58
54 if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries) 59 if (block > UDF_SB_TYPEVIRT(sb, partition).s_num_entries) {
55 { 60 udf_debug
56 udf_debug("Trying to access block beyond end of VAT (%d max %d)\n", 61 ("Trying to access block beyond end of VAT (%d max %d)\n",
57 block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries); 62 block, UDF_SB_TYPEVIRT(sb, partition).s_num_entries);
58 return 0xFFFFFFFF; 63 return 0xFFFFFFFF;
59 } 64 }
60 65
61 if (block >= index) 66 if (block >= index) {
62 {
63 block -= index; 67 block -= index;
64 newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); 68 newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
65 index = block % (sb->s_blocksize / sizeof(uint32_t)); 69 index = block % (sb->s_blocksize / sizeof(uint32_t));
66 } 70 } else {
67 else
68 {
69 newblock = 0; 71 newblock = 0;
70 index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(uint32_t) + block; 72 index =
73 UDF_SB_TYPEVIRT(sb,
74 partition).s_start_offset /
75 sizeof(uint32_t) + block;
71 } 76 }
72 77
73 loc = udf_block_map(UDF_SB_VAT(sb), newblock); 78 loc = udf_block_map(UDF_SB_VAT(sb), newblock);
74 79
75 if (!(bh = sb_bread(sb, loc))) 80 if (!(bh = sb_bread(sb, loc))) {
76 {
77 udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n", 81 udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
78 sb, block, partition, loc, index); 82 sb, block, partition, loc, index);
79 return 0xFFFFFFFF; 83 return 0xFFFFFFFF;
80 } 84 }
81 85
82 loc = le32_to_cpu(((__le32 *)bh->b_data)[index]); 86 loc = le32_to_cpu(((__le32 *) bh->b_data)[index]);
83 87
84 brelse(bh); 88 brelse(bh);
85 89
86 if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition) 90 if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition) {
87 {
88 udf_debug("recursive call to udf_get_pblock!\n"); 91 udf_debug("recursive call to udf_get_pblock!\n");
89 return 0xFFFFFFFF; 92 return 0xFFFFFFFF;
90 } 93 }
91 94
92 return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset); 95 return udf_get_pblock(sb, loc,
96 UDF_I_LOCATION(UDF_SB_VAT(sb)).
97 partitionReferenceNum, offset);
93} 98}
94 99
95inline uint32_t udf_get_pblock_virt20(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) 100inline uint32_t udf_get_pblock_virt20(struct super_block * sb, uint32_t block,
101 uint16_t partition, uint32_t offset)
96{ 102{
97 return udf_get_pblock_virt15(sb, block, partition, offset); 103 return udf_get_pblock_virt15(sb, block, partition, offset);
98} 104}
99 105
100uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) 106uint32_t udf_get_pblock_spar15(struct super_block * sb, uint32_t block,
107 uint16_t partition, uint32_t offset)
101{ 108{
102 int i; 109 int i;
103 struct sparingTable *st = NULL; 110 struct sparingTable *st = NULL;
104 uint32_t packet = (block + offset) & ~(UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1); 111 uint32_t packet =
112 (block + offset) & ~(UDF_SB_TYPESPAR(sb, partition).s_packet_len -
113 1);
105 114
106 for (i=0; i<4; i++) 115 for (i = 0; i < 4; i++) {
107 { 116 if (UDF_SB_TYPESPAR(sb, partition).s_spar_map[i] != NULL) {
108 if (UDF_SB_TYPESPAR(sb,partition).s_spar_map[i] != NULL) 117 st = (struct sparingTable *)UDF_SB_TYPESPAR(sb,
109 { 118 partition).
110 st = (struct sparingTable *)UDF_SB_TYPESPAR(sb,partition).s_spar_map[i]->b_data; 119 s_spar_map[i]->b_data;
111 break; 120 break;
112 } 121 }
113 } 122 }
114 123
115 if (st) 124 if (st) {
116 { 125 for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) {
117 for (i=0; i<le16_to_cpu(st->reallocationTableLen); i++) 126 if (le32_to_cpu(st->mapEntry[i].origLocation) >=
118 { 127 0xFFFFFFF0)
119 if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0)
120 break; 128 break;
121 else if (le32_to_cpu(st->mapEntry[i].origLocation) == packet) 129 else if (le32_to_cpu(st->mapEntry[i].origLocation) ==
122 { 130 packet) {
123 return le32_to_cpu(st->mapEntry[i].mappedLocation) + 131 return le32_to_cpu(st->mapEntry[i].
124 ((block + offset) & (UDF_SB_TYPESPAR(sb,partition).s_packet_len - 1)); 132 mappedLocation) + ((block +
125 } 133 offset) &
126 else if (le32_to_cpu(st->mapEntry[i].origLocation) > packet) 134 (UDF_SB_TYPESPAR
135 (sb,
136 partition).
137 s_packet_len
138 - 1));
139 } else if (le32_to_cpu(st->mapEntry[i].origLocation) >
140 packet)
127 break; 141 break;
128 } 142 }
129 } 143 }
130 return UDF_SB_PARTROOT(sb,partition) + block + offset; 144 return UDF_SB_PARTROOT(sb, partition) + block + offset;
131} 145}
132 146
133int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) 147int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
@@ -138,19 +152,21 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
138 uint32_t packet; 152 uint32_t packet;
139 int i, j, k, l; 153 int i, j, k, l;
140 154
141 for (i=0; i<UDF_SB_NUMPARTS(sb); i++) 155 for (i = 0; i < UDF_SB_NUMPARTS(sb); i++) {
142 { 156 if (old_block > UDF_SB_PARTROOT(sb, i) &&
143 if (old_block > UDF_SB_PARTROOT(sb,i) && 157 old_block < UDF_SB_PARTROOT(sb, i) + UDF_SB_PARTLEN(sb, i))
144 old_block < UDF_SB_PARTROOT(sb,i) + UDF_SB_PARTLEN(sb,i))
145 { 158 {
146 sdata = &UDF_SB_TYPESPAR(sb,i); 159 sdata = &UDF_SB_TYPESPAR(sb, i);
147 packet = (old_block - UDF_SB_PARTROOT(sb,i)) & ~(sdata->s_packet_len - 1); 160 packet =
148 161 (old_block -
149 for (j=0; j<4; j++) 162 UDF_SB_PARTROOT(sb,
150 { 163 i)) & ~(sdata->s_packet_len - 1);
151 if (UDF_SB_TYPESPAR(sb,i).s_spar_map[j] != NULL) 164
152 { 165 for (j = 0; j < 4; j++) {
153 st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; 166 if (UDF_SB_TYPESPAR(sb, i).s_spar_map[j] !=
167 NULL) {
168 st = (struct sparingTable *)sdata->
169 s_spar_map[j]->b_data;
154 break; 170 break;
155 } 171 }
156 } 172 }
@@ -158,60 +174,123 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
158 if (!st) 174 if (!st)
159 return 1; 175 return 1;
160 176
161 for (k=0; k<le16_to_cpu(st->reallocationTableLen); k++) 177 for (k = 0; k < le16_to_cpu(st->reallocationTableLen);
162 { 178 k++) {
163 if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF) 179 if (le32_to_cpu(st->mapEntry[k].origLocation) ==
164 { 180 0xFFFFFFFF) {
165 for (; j<4; j++) 181 for (; j < 4; j++) {
166 { 182 if (sdata->s_spar_map[j]) {
167 if (sdata->s_spar_map[j]) 183 st = (struct
168 { 184 sparingTable *)
169 st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; 185 sdata->
170 st->mapEntry[k].origLocation = cpu_to_le32(packet); 186 s_spar_map[j]->
171 udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry)); 187 b_data;
172 mark_buffer_dirty(sdata->s_spar_map[j]); 188 st->mapEntry[k].
189 origLocation =
190 cpu_to_le32(packet);
191 udf_update_tag((char *)
192 st,
193 sizeof
194 (struct
195 sparingTable)
196 +
197 le16_to_cpu
198 (st->
199 reallocationTableLen)
200 *
201 sizeof
202 (struct
203 sparingEntry));
204 mark_buffer_dirty
205 (sdata->
206 s_spar_map[j]);
173 } 207 }
174 } 208 }
175 *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + 209 *new_block =
176 ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); 210 le32_to_cpu(st->mapEntry[k].
211 mappedLocation) +
212 ((old_block -
213 UDF_SB_PARTROOT(sb,
214 i)) & (sdata->
215 s_packet_len
216 - 1));
177 return 0; 217 return 0;
178 } 218 } else
179 else if (le32_to_cpu(st->mapEntry[k].origLocation) == packet) 219 if (le32_to_cpu
180 { 220 (st->mapEntry[k].origLocation) ==
181 *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + 221 packet) {
182 ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); 222 *new_block =
223 le32_to_cpu(st->mapEntry[k].
224 mappedLocation) +
225 ((old_block -
226 UDF_SB_PARTROOT(sb,
227 i)) & (sdata->
228 s_packet_len
229 - 1));
183 return 0; 230 return 0;
184 } 231 } else
185 else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet) 232 if (le32_to_cpu
233 (st->mapEntry[k].origLocation) > packet)
186 break; 234 break;
187 } 235 }
188 for (l=k; l<le16_to_cpu(st->reallocationTableLen); l++) 236 for (l = k; l < le16_to_cpu(st->reallocationTableLen);
189 { 237 l++) {
190 if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF) 238 if (le32_to_cpu(st->mapEntry[l].origLocation) ==
191 { 239 0xFFFFFFFF) {
192 for (; j<4; j++) 240 for (; j < 4; j++) {
193 { 241 if (sdata->s_spar_map[j]) {
194 if (sdata->s_spar_map[j]) 242 st = (struct
195 { 243 sparingTable *)
196 st = (struct sparingTable *)sdata->s_spar_map[j]->b_data; 244 sdata->
197 mapEntry = st->mapEntry[l]; 245 s_spar_map[j]->
198 mapEntry.origLocation = cpu_to_le32(packet); 246 b_data;
199 memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(struct sparingEntry)); 247 mapEntry =
200 st->mapEntry[k] = mapEntry; 248 st->mapEntry[l];
201 udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry)); 249 mapEntry.origLocation =
202 mark_buffer_dirty(sdata->s_spar_map[j]); 250 cpu_to_le32(packet);
251 memmove(&st->
252 mapEntry[k + 1],
253 &st->
254 mapEntry[k],
255 (l -
256 k) *
257 sizeof(struct
258 sparingEntry));
259 st->mapEntry[k] =
260 mapEntry;
261 udf_update_tag((char *)
262 st,
263 sizeof
264 (struct
265 sparingTable)
266 +
267 le16_to_cpu
268 (st->
269 reallocationTableLen)
270 *
271 sizeof
272 (struct
273 sparingEntry));
274 mark_buffer_dirty
275 (sdata->
276 s_spar_map[j]);
203 } 277 }
204 } 278 }
205 *new_block = le32_to_cpu(st->mapEntry[k].mappedLocation) + 279 *new_block =
206 ((old_block - UDF_SB_PARTROOT(sb,i)) & (sdata->s_packet_len - 1)); 280 le32_to_cpu(st->mapEntry[k].
281 mappedLocation) +
282 ((old_block -
283 UDF_SB_PARTROOT(sb,
284 i)) & (sdata->
285 s_packet_len
286 - 1));
207 return 0; 287 return 0;
208 } 288 }
209 } 289 }
210 return 1; 290 return 1;
211 } 291 }
212 } 292 }
213 if (i == UDF_SB_NUMPARTS(sb)) 293 if (i == UDF_SB_NUMPARTS(sb)) {
214 {
215 /* outside of partitions */ 294 /* outside of partitions */
216 /* for now, fail =) */ 295 /* for now, fail =) */
217 return 1; 296 return 1;