Blame view
fs/udf/partition.c
8.65 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * partition.c * * PURPOSE * Partition handling routines for the OSTA-UDF(tm) filesystem. * |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 14 15 16 |
* COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 1998-2001 Ben Fennema * * HISTORY * |
28de7948a UDF: coding style... |
17 |
* 12/06/98 blf Created file. |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 21 22 23 24 25 26 |
* */ #include "udfdecl.h" #include "udf_sb.h" #include "udf_i.h" #include <linux/fs.h> #include <linux/string.h> |
1da177e4c Linux-2.6.12-rc2 |
27 |
#include <linux/buffer_head.h> |
7db09be62 udf: Use of s_all... |
28 |
#include <linux/mutex.h> |
1da177e4c Linux-2.6.12-rc2 |
29 |
|
22ba0317c udf: fs/udf/parti... |
30 31 |
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) |
1da177e4c Linux-2.6.12-rc2 |
32 |
{ |
6c79e987d udf: remove some ... |
33 34 35 |
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; if (partition >= sbi->s_partitions) { |
a983f368f udf: Neaten udf_d... |
36 37 38 |
udf_debug("block=%d, partition=%d, offset=%d: invalid partition ", block, partition, offset); |
1da177e4c Linux-2.6.12-rc2 |
39 40 |
return 0xFFFFFFFF; } |
6c79e987d udf: remove some ... |
41 42 43 |
map = &sbi->s_partmaps[partition]; if (map->s_partition_func) return map->s_partition_func(sb, block, partition, offset); |
1da177e4c Linux-2.6.12-rc2 |
44 |
else |
6c79e987d udf: remove some ... |
45 |
return map->s_partition_root + block + offset; |
1da177e4c Linux-2.6.12-rc2 |
46 |
} |
28de7948a UDF: coding style... |
47 |
uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, |
cb00ea352 UDF: coding style... |
48 |
uint16_t partition, uint32_t offset) |
1da177e4c Linux-2.6.12-rc2 |
49 50 51 52 53 |
{ struct buffer_head *bh = NULL; uint32_t newblock; uint32_t index; uint32_t loc; |
6c79e987d udf: remove some ... |
54 55 |
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; |
4b11111ab udf: fix coding s... |
56 |
struct udf_virtual_data *vdata; |
fa5e08156 udf: Handle VAT p... |
57 |
struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode); |
1da177e4c Linux-2.6.12-rc2 |
58 |
|
6c79e987d udf: remove some ... |
59 |
map = &sbi->s_partmaps[partition]; |
4b11111ab udf: fix coding s... |
60 |
vdata = &map->s_type_specific.s_virtual; |
1da177e4c Linux-2.6.12-rc2 |
61 |
|
4b11111ab udf: fix coding s... |
62 |
if (block > vdata->s_num_entries) { |
a983f368f udf: Neaten udf_d... |
63 64 65 |
udf_debug("Trying to access block beyond end of VAT (%d max %d) ", block, vdata->s_num_entries); |
1da177e4c Linux-2.6.12-rc2 |
66 67 |
return 0xFFFFFFFF; } |
fa5e08156 udf: Handle VAT p... |
68 |
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
47c9358a0 udf: Fix bug in V... |
69 70 |
loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data + vdata->s_start_offset))[block]); |
fa5e08156 udf: Handle VAT p... |
71 72 73 |
goto translate; } index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t); |
cb00ea352 UDF: coding style... |
74 |
if (block >= index) { |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 |
block -= index; newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t))); index = block % (sb->s_blocksize / sizeof(uint32_t)); |
cb00ea352 UDF: coding style... |
78 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
79 |
newblock = 0; |
4b11111ab udf: fix coding s... |
80 |
index = vdata->s_start_offset / sizeof(uint32_t) + block; |
1da177e4c Linux-2.6.12-rc2 |
81 |
} |
6c79e987d udf: remove some ... |
82 |
loc = udf_block_map(sbi->s_vat_inode, newblock); |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
4b11111ab udf: fix coding s... |
84 85 |
bh = sb_bread(sb, loc); if (!bh) { |
1da177e4c Linux-2.6.12-rc2 |
86 87 |
udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d] ", |
cb00ea352 UDF: coding style... |
88 |
sb, block, partition, loc, index); |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
return 0xFFFFFFFF; } |
28de7948a UDF: coding style... |
91 |
loc = le32_to_cpu(((__le32 *)bh->b_data)[index]); |
1da177e4c Linux-2.6.12-rc2 |
92 |
|
3bf25cb40 udf: use get_bh() |
93 |
brelse(bh); |
1da177e4c Linux-2.6.12-rc2 |
94 |
|
fa5e08156 udf: Handle VAT p... |
95 |
translate: |
48d6d8ff7 udf: cache struct... |
96 |
if (iinfo->i_location.partitionReferenceNum == partition) { |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 100 |
udf_debug("recursive call to udf_get_pblock! "); return 0xFFFFFFFF; } |
cb00ea352 UDF: coding style... |
101 |
return udf_get_pblock(sb, loc, |
48d6d8ff7 udf: cache struct... |
102 |
iinfo->i_location.partitionReferenceNum, |
28de7948a UDF: coding style... |
103 |
offset); |
1da177e4c Linux-2.6.12-rc2 |
104 |
} |
4b11111ab udf: fix coding s... |
105 |
inline uint32_t udf_get_pblock_virt20(struct super_block *sb, uint32_t block, |
cb00ea352 UDF: coding style... |
106 |
uint16_t partition, uint32_t offset) |
1da177e4c Linux-2.6.12-rc2 |
107 108 109 |
{ return udf_get_pblock_virt15(sb, block, partition, offset); } |
6c79e987d udf: remove some ... |
110 |
uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block, |
cb00ea352 UDF: coding style... |
111 |
uint16_t partition, uint32_t offset) |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 |
{ int i; struct sparingTable *st = NULL; |
6c79e987d udf: remove some ... |
115 116 117 |
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; uint32_t packet; |
4b11111ab udf: fix coding s... |
118 |
struct udf_sparing_data *sdata; |
6c79e987d udf: remove some ... |
119 120 |
map = &sbi->s_partmaps[partition]; |
4b11111ab udf: fix coding s... |
121 122 |
sdata = &map->s_type_specific.s_sparing; packet = (block + offset) & ~(sdata->s_packet_len - 1); |
1da177e4c Linux-2.6.12-rc2 |
123 |
|
cb00ea352 UDF: coding style... |
124 |
for (i = 0; i < 4; i++) { |
4b11111ab udf: fix coding s... |
125 126 127 |
if (sdata->s_spar_map[i] != NULL) { st = (struct sparingTable *) sdata->s_spar_map[i]->b_data; |
1da177e4c Linux-2.6.12-rc2 |
128 129 130 |
break; } } |
cb00ea352 UDF: coding style... |
131 132 |
if (st) { for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) { |
4b11111ab udf: fix coding s... |
133 134 135 |
struct sparingEntry *entry = &st->mapEntry[i]; u32 origLoc = le32_to_cpu(entry->origLocation); if (origLoc >= 0xFFFFFFF0) |
1da177e4c Linux-2.6.12-rc2 |
136 |
break; |
4b11111ab udf: fix coding s... |
137 138 139 140 141 |
else if (origLoc == packet) return le32_to_cpu(entry->mappedLocation) + ((block + offset) & (sdata->s_packet_len - 1)); else if (origLoc > packet) |
1da177e4c Linux-2.6.12-rc2 |
142 143 144 |
break; } } |
28de7948a UDF: coding style... |
145 |
|
6c79e987d udf: remove some ... |
146 |
return map->s_partition_root + block + offset; |
1da177e4c Linux-2.6.12-rc2 |
147 148 149 150 151 152 153 154 155 |
} int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block) { struct udf_sparing_data *sdata; struct sparingTable *st = NULL; struct sparingEntry mapEntry; uint32_t packet; int i, j, k, l; |
6c79e987d udf: remove some ... |
156 |
struct udf_sb_info *sbi = UDF_SB(sb); |
4b11111ab udf: fix coding s... |
157 158 |
u16 reallocationTableLen; struct buffer_head *bh; |
7db09be62 udf: Use of s_all... |
159 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
160 |
|
7db09be62 udf: Use of s_all... |
161 |
mutex_lock(&sbi->s_alloc_mutex); |
6c79e987d udf: remove some ... |
162 163 164 165 166 |
for (i = 0; i < sbi->s_partitions; i++) { struct udf_part_map *map = &sbi->s_partmaps[i]; if (old_block > map->s_partition_root && old_block < map->s_partition_root + map->s_partition_len) { sdata = &map->s_type_specific.s_sparing; |
4b11111ab udf: fix coding s... |
167 168 |
packet = (old_block - map->s_partition_root) & ~(sdata->s_packet_len - 1); |
cb00ea352 UDF: coding style... |
169 |
|
4b11111ab udf: fix coding s... |
170 171 172 173 |
for (j = 0; j < 4; j++) if (sdata->s_spar_map[j] != NULL) { st = (struct sparingTable *) sdata->s_spar_map[j]->b_data; |
1da177e4c Linux-2.6.12-rc2 |
174 175 |
break; } |
1da177e4c Linux-2.6.12-rc2 |
176 |
|
7db09be62 udf: Use of s_all... |
177 178 179 180 |
if (!st) { ret = 1; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
181 |
|
4b11111ab udf: fix coding s... |
182 183 184 185 186 187 188 |
reallocationTableLen = le16_to_cpu(st->reallocationTableLen); for (k = 0; k < reallocationTableLen; k++) { struct sparingEntry *entry = &st->mapEntry[k]; u32 origLoc = le32_to_cpu(entry->origLocation); if (origLoc == 0xFFFFFFFF) { |
cb00ea352 UDF: coding style... |
189 |
for (; j < 4; j++) { |
4b11111ab udf: fix coding s... |
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
int len; bh = sdata->s_spar_map[j]; if (!bh) continue; st = (struct sparingTable *) bh->b_data; entry->origLocation = cpu_to_le32(packet); len = sizeof(struct sparingTable) + reallocationTableLen * sizeof(struct sparingEntry); udf_update_tag((char *)st, len); mark_buffer_dirty(bh); |
1da177e4c Linux-2.6.12-rc2 |
205 |
} |
4b11111ab udf: fix coding s... |
206 207 208 209 210 |
*new_block = le32_to_cpu( entry->mappedLocation) + ((old_block - map->s_partition_root) & (sdata->s_packet_len - 1)); |
7db09be62 udf: Use of s_all... |
211 212 |
ret = 0; goto out; |
4b11111ab udf: fix coding s... |
213 214 215 216 217 218 |
} else if (origLoc == packet) { *new_block = le32_to_cpu( entry->mappedLocation) + ((old_block - map->s_partition_root) & (sdata->s_packet_len - 1)); |
7db09be62 udf: Use of s_all... |
219 220 |
ret = 0; goto out; |
4b11111ab udf: fix coding s... |
221 |
} else if (origLoc > packet) |
1da177e4c Linux-2.6.12-rc2 |
222 223 |
break; } |
28de7948a UDF: coding style... |
224 |
|
4b11111ab udf: fix coding s... |
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
for (l = k; l < reallocationTableLen; l++) { struct sparingEntry *entry = &st->mapEntry[l]; u32 origLoc = le32_to_cpu(entry->origLocation); if (origLoc != 0xFFFFFFFF) continue; for (; j < 4; j++) { bh = sdata->s_spar_map[j]; if (!bh) continue; st = (struct sparingTable *)bh->b_data; mapEntry = st->mapEntry[l]; mapEntry.origLocation = cpu_to_le32(packet); memmove(&st->mapEntry[k + 1], &st->mapEntry[k], (l - k) * sizeof(struct sparingEntry)); st->mapEntry[k] = mapEntry; udf_update_tag((char *)st, sizeof(struct sparingTable) + reallocationTableLen * sizeof(struct sparingEntry)); mark_buffer_dirty(bh); |
1da177e4c Linux-2.6.12-rc2 |
251 |
} |
4b11111ab udf: fix coding s... |
252 253 254 255 256 |
*new_block = le32_to_cpu( st->mapEntry[k].mappedLocation) + ((old_block - map->s_partition_root) & (sdata->s_packet_len - 1)); |
7db09be62 udf: Use of s_all... |
257 258 |
ret = 0; goto out; |
1da177e4c Linux-2.6.12-rc2 |
259 |
} |
28de7948a UDF: coding style... |
260 |
|
7db09be62 udf: Use of s_all... |
261 262 |
ret = 1; goto out; |
28de7948a UDF: coding style... |
263 |
} /* if old_block */ |
1da177e4c Linux-2.6.12-rc2 |
264 |
} |
28de7948a UDF: coding style... |
265 |
|
6c79e987d udf: remove some ... |
266 |
if (i == sbi->s_partitions) { |
1da177e4c Linux-2.6.12-rc2 |
267 268 |
/* outside of partitions */ /* for now, fail =) */ |
7db09be62 udf: Use of s_all... |
269 |
ret = 1; |
1da177e4c Linux-2.6.12-rc2 |
270 |
} |
7db09be62 udf: Use of s_all... |
271 272 273 |
out: mutex_unlock(&sbi->s_alloc_mutex); return ret; |
1da177e4c Linux-2.6.12-rc2 |
274 |
} |
bfb257a59 udf: Add read-onl... |
275 276 277 278 279 280 |
static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, uint16_t partition, uint32_t offset) { struct super_block *sb = inode->i_sb; struct udf_part_map *map; |
5ca4e4be8 Remove struct typ... |
281 |
struct kernel_lb_addr eloc; |
bfb257a59 udf: Add read-onl... |
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
uint32_t elen; sector_t ext_offset; struct extent_position epos = {}; uint32_t phyblock; if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) != (EXT_RECORDED_ALLOCATED >> 30)) phyblock = 0xFFFFFFFF; else { map = &UDF_SB(sb)->s_partmaps[partition]; /* map to sparable/physical partition desc */ phyblock = udf_get_pblock(sb, eloc.logicalBlockNum, map->s_partition_num, ext_offset + offset); } brelse(epos.bh); return phyblock; } uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block, uint16_t partition, uint32_t offset) { struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; struct udf_meta_data *mdata; uint32_t retblk; struct inode *inode; udf_debug("READING from METADATA "); map = &sbi->s_partmaps[partition]; mdata = &map->s_type_specific.s_metadata; inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe; /* We shouldn't mount such media... */ BUG_ON(!inode); retblk = udf_try_read_meta(inode, block, partition, offset); |
3080a74ea udf: Skip mirror ... |
320 |
if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) { |
a40ecd7b3 udf: Rename udf_w... |
321 322 |
udf_warn(sb, "error reading from METADATA, trying to read from MIRROR "); |
ed47a7d00 udf: Cleanup meta... |
323 |
if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) { |
3080a74ea udf: Skip mirror ... |
324 325 |
mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc, map->s_partition_num); |
ed47a7d00 udf: Cleanup meta... |
326 |
mdata->s_flags |= MF_MIRROR_FE_LOADED; |
3080a74ea udf: Skip mirror ... |
327 |
} |
bfb257a59 udf: Add read-onl... |
328 329 330 331 332 333 334 335 |
inode = mdata->s_mirror_fe; if (!inode) return 0xFFFFFFFF; retblk = udf_try_read_meta(inode, block, partition, offset); } return retblk; } |