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@hootie.lvld.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
26 #include "udfdecl.h"
27 #include "udf_sb.h"
28 #include "udf_i.h"
29
30 #include <linux/fs.h>
31 #include <linux/string.h>
32 #include <linux/udf_fs.h>
33 #include <linux/malloc.h>
34
35 inline Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
36 {
37 if (partition >= UDF_SB_NUMPARTS(sb))
38 {
39 udf_debug("block=%d, partition=%d, offset=%d: invalid partition\n",
40 block, partition, offset);
41 return 0xFFFFFFFF;
42 }
43 if (UDF_SB_PARTFUNC(sb, partition))
44 return UDF_SB_PARTFUNC(sb, partition)(sb, block, partition, offset);
45 else
46 return UDF_SB_PARTROOT(sb, partition) + block + offset;
47 }
48
49 Uint32 udf_get_pblock_virt15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
50 {
51 struct buffer_head *bh = NULL;
52 Uint32 newblock;
53 Uint32 index;
54 Uint32 loc;
55
56 index = (sb->s_blocksize - UDF_SB_TYPEVIRT(sb,partition).s_start_offset) / sizeof(Uint32);
57
58 if (block > UDF_SB_TYPEVIRT(sb,partition).s_num_entries)
59 {
60 udf_debug("Trying to access block beyond end of VAT (%d max %d)\n",
61 block, UDF_SB_TYPEVIRT(sb,partition).s_num_entries);
62 return 0xFFFFFFFF;
63 }
64
65 if (block >= index)
66 {
67 block -= index;
68 newblock = 1 + (block / (sb->s_blocksize / sizeof(Uint32)));
69 index = block % (sb->s_blocksize / sizeof(Uint32));
70 }
71 else
72 {
73 newblock = 0;
74 index = UDF_SB_TYPEVIRT(sb,partition).s_start_offset / sizeof(Uint32) + block;
75 }
76
77 loc = udf_locked_block_map(UDF_SB_VAT(sb), newblock);
78
79 if (!(bh = bread(sb->s_dev, loc, sb->s_blocksize)))
80 {
81 udf_debug("get_pblock(UDF_VIRTUAL_MAP:%p,%d,%d) VAT: %d[%d]\n",
82 sb, block, partition, loc, index);
83 return 0xFFFFFFFF;
84 }
85
86 loc = le32_to_cpu(((Uint32 *)bh->b_data)[index]);
87
88 udf_release_data(bh);
89
90 if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition)
91 {
92 udf_debug("recursive call to udf_get_pblock!\n");
93 return 0xFFFFFFFF;
94 }
95
96 return udf_get_pblock(sb, loc, UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum, offset);
97 }
98
99 inline Uint32 udf_get_pblock_virt20(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
100 {
101 return udf_get_pblock_virt15(sb, block, partition, offset);
102 }
103
104 Uint32 udf_get_pblock_spar15(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
105 {
106 Uint32 packet = (block + offset) >> UDF_SB_TYPESPAR(sb,partition).s_spar_pshift;
107 Uint32 index = 0;
108
109 if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 8)
110 index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap8[packet];
111 else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 16)
112 index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap16[packet];
113 else if (UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize == 32)
114 index = UDF_SB_TYPESPAR(sb,partition).s_spar_remap.s_spar_remap32[packet];
115
116 if (index == ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_indexsize)-1))
117 return UDF_SB_PARTROOT(sb,partition) + block + offset;
118
119 packet = UDF_SB_TYPESPAR(sb,partition).s_spar_map[index];
120 return packet + ((block + offset) & ((1 << UDF_SB_TYPESPAR(sb,partition).s_spar_pshift)-1));
121 }
122
123 void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata, int partlen)
124 {
125 Uint16 ident;
126 Uint32 spartable;
127 int i;
128 struct buffer_head *bh;
129 struct SparingTable *st;
130
131 for (i=0; i<4; i++)
132 {
133 if (!(spartable = sdata->s_spar_loc[i]))
134 continue;
135
136 bh = udf_read_tagged(sb, spartable, spartable, &ident);
137
138 if (!bh)
139 {
140 sdata->s_spar_loc[i] = 0;
141 continue;
142 }
143
144 if (ident == 0)
145 {
146 st = (struct SparingTable *)bh->b_data;
147 if (!strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)))
148 {
149 SparingEntry *se;
150 Uint16 rtl = le16_to_cpu(st->reallocationTableLen);
151 int index;
152
153 if (!sdata->s_spar_map)
154 {
155 int num = 1, mapsize;
156 sdata->s_spar_indexsize = 8;
157 while (rtl*sizeof(Uint32) >= (1 << sdata->s_spar_indexsize))
158 {
159 num ++;
160 sdata->s_spar_indexsize <<= 1;
161 }
162 mapsize = (rtl * sizeof(Uint32)) +
163 ((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num);
164 sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL);
165 sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl];
166 memset(sdata->s_spar_map, 0xFF, mapsize);
167 }
168
169 index = sizeof(struct SparingTable);
170 for (i=0; i<rtl; i++)
171 {
172 if (index > sb->s_blocksize)
173 {
174 udf_release_data(bh);
175 bh = udf_tread(sb, ++spartable, sb->s_blocksize);
176 if (!bh)
177 {
178 sdata->s_spar_loc[i] = 0;
179 continue;
180 }
181 index = 0;
182 }
183 se = (SparingEntry *)&(bh->b_data[index]);
184 index += sizeof(SparingEntry);
185
186 if (sdata->s_spar_map[i] == 0xFFFFFFFF)
187 sdata->s_spar_map[i] = le32_to_cpu(se->mappedLocation);
188 else if (sdata->s_spar_map[i] != le32_to_cpu(se->mappedLocation))
189 {
190 udf_debug("Found conflicting Sparing Data (%d vs %d for entry %d)\n",
191 sdata->s_spar_map[i], le32_to_cpu(se->mappedLocation), i);
192 }
193
194 if (le32_to_cpu(se->origLocation) < 0xFFFFFFF0)
195 {
196 int packet = le32_to_cpu(se->origLocation) >> sdata->s_spar_pshift;
197 if (sdata->s_spar_indexsize == 8)
198 {
199 if (sdata->s_spar_remap.s_spar_remap8[packet] == 0xFF)
200 sdata->s_spar_remap.s_spar_remap8[packet] = i;
201 else if (sdata->s_spar_remap.s_spar_remap8[packet] != i)
202 {
203 udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
204 sdata->s_spar_remap.s_spar_remap8[packet], i);
205 }
206 }
207 else if (sdata->s_spar_indexsize == 16)
208 {
209 if (sdata->s_spar_remap.s_spar_remap16[packet] == 0xFFFF)
210 sdata->s_spar_remap.s_spar_remap16[packet] = i;
211 else if (sdata->s_spar_remap.s_spar_remap16[packet] != i)
212 {
213 udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
214 sdata->s_spar_remap.s_spar_remap16[packet], i);
215 }
216 }
217 else if (sdata->s_spar_indexsize == 32)
218 {
219 if (sdata->s_spar_remap.s_spar_remap32[packet] == 0xFFFFFFFF)
220 sdata->s_spar_remap.s_spar_remap32[packet] = i;
221 else if (sdata->s_spar_remap.s_spar_remap32[packet] != i)
222 {
223 udf_debug("Found conflicting Sparing Data (%d vs %d)\n",
224 sdata->s_spar_remap.s_spar_remap32[packet], i);
225 }
226 }
227 }
228 }
229 }
230 }
231 udf_release_data(bh);
232 }
233 }
234
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.