| @@ -1,2740 +1,2740 @@ | | | @@ -1,2740 +1,2740 @@ |
1 | /* $NetBSD: udf_allocation.c,v 1.24 2009/06/18 15:06:38 reinoud Exp $ */ | | 1 | /* $NetBSD: udf_allocation.c,v 1.25 2009/06/18 15:09:18 reinoud Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006, 2008 Reinoud Zandijk | | 4 | * Copyright (c) 2006, 2008 Reinoud Zandijk |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | | 26 | * |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | #ifndef lint | | 30 | #ifndef lint |
31 | __KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.24 2009/06/18 15:06:38 reinoud Exp $"); | | 31 | __KERNEL_RCSID(0, "$NetBSD: udf_allocation.c,v 1.25 2009/06/18 15:09:18 reinoud Exp $"); |
32 | #endif /* not lint */ | | 32 | #endif /* not lint */ |
33 | | | 33 | |
34 | | | 34 | |
35 | #if defined(_KERNEL_OPT) | | 35 | #if defined(_KERNEL_OPT) |
36 | #include "opt_compat_netbsd.h" | | 36 | #include "opt_compat_netbsd.h" |
37 | #endif | | 37 | #endif |
38 | | | 38 | |
39 | /* TODO strip */ | | 39 | /* TODO strip */ |
40 | #include <sys/param.h> | | 40 | #include <sys/param.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
42 | #include <sys/sysctl.h> | | 42 | #include <sys/sysctl.h> |
43 | #include <sys/namei.h> | | 43 | #include <sys/namei.h> |
44 | #include <sys/proc.h> | | 44 | #include <sys/proc.h> |
45 | #include <sys/kernel.h> | | 45 | #include <sys/kernel.h> |
46 | #include <sys/vnode.h> | | 46 | #include <sys/vnode.h> |
47 | #include <miscfs/genfs/genfs_node.h> | | 47 | #include <miscfs/genfs/genfs_node.h> |
48 | #include <sys/mount.h> | | 48 | #include <sys/mount.h> |
49 | #include <sys/buf.h> | | 49 | #include <sys/buf.h> |
50 | #include <sys/file.h> | | 50 | #include <sys/file.h> |
51 | #include <sys/device.h> | | 51 | #include <sys/device.h> |
52 | #include <sys/disklabel.h> | | 52 | #include <sys/disklabel.h> |
53 | #include <sys/ioctl.h> | | 53 | #include <sys/ioctl.h> |
54 | #include <sys/malloc.h> | | 54 | #include <sys/malloc.h> |
55 | #include <sys/dirent.h> | | 55 | #include <sys/dirent.h> |
56 | #include <sys/stat.h> | | 56 | #include <sys/stat.h> |
57 | #include <sys/conf.h> | | 57 | #include <sys/conf.h> |
58 | #include <sys/kauth.h> | | 58 | #include <sys/kauth.h> |
59 | #include <sys/kthread.h> | | 59 | #include <sys/kthread.h> |
60 | #include <dev/clock_subr.h> | | 60 | #include <dev/clock_subr.h> |
61 | | | 61 | |
62 | #include <fs/udf/ecma167-udf.h> | | 62 | #include <fs/udf/ecma167-udf.h> |
63 | #include <fs/udf/udf_mount.h> | | 63 | #include <fs/udf/udf_mount.h> |
64 | | | 64 | |
65 | #include "udf.h" | | 65 | #include "udf.h" |
66 | #include "udf_subr.h" | | 66 | #include "udf_subr.h" |
67 | #include "udf_bswap.h" | | 67 | #include "udf_bswap.h" |
68 | | | 68 | |
69 | | | 69 | |
70 | #define VTOI(vnode) ((struct udf_node *) vnode->v_data) | | 70 | #define VTOI(vnode) ((struct udf_node *) vnode->v_data) |
71 | | | 71 | |
72 | static void udf_record_allocation_in_node(struct udf_mount *ump, | | 72 | static void udf_record_allocation_in_node(struct udf_mount *ump, |
73 | struct buf *buf, uint16_t vpart_num, uint64_t *mapping, | | 73 | struct buf *buf, uint16_t vpart_num, uint64_t *mapping, |
74 | struct long_ad *node_ad_cpy); | | 74 | struct long_ad *node_ad_cpy); |
75 | | | 75 | |
76 | /* | | 76 | /* |
77 | * IDEA/BUSY: Each udf_node gets its own extentwalker state for all operations; | | 77 | * IDEA/BUSY: Each udf_node gets its own extentwalker state for all operations; |
78 | * this will hopefully/likely reduce O(nlog(n)) to O(1) for most functionality | | 78 | * this will hopefully/likely reduce O(nlog(n)) to O(1) for most functionality |
79 | * since actions are most likely sequencial and thus seeking doesn't need | | 79 | * since actions are most likely sequencial and thus seeking doesn't need |
80 | * searching for the same or adjacent position again. | | 80 | * searching for the same or adjacent position again. |
81 | */ | | 81 | */ |
82 | | | 82 | |
83 | /* --------------------------------------------------------------------- */ | | 83 | /* --------------------------------------------------------------------- */ |
84 | | | 84 | |
85 | #if 0 | | 85 | #if 0 |
86 | #if 1 | | 86 | #if 1 |
87 | static void | | 87 | static void |
88 | udf_node_dump(struct udf_node *udf_node) { | | 88 | udf_node_dump(struct udf_node *udf_node) { |
89 | struct file_entry *fe; | | 89 | struct file_entry *fe; |
90 | struct extfile_entry *efe; | | 90 | struct extfile_entry *efe; |
91 | struct icb_tag *icbtag; | | 91 | struct icb_tag *icbtag; |
92 | struct long_ad s_ad; | | 92 | struct long_ad s_ad; |
93 | uint64_t inflen; | | 93 | uint64_t inflen; |
94 | uint32_t icbflags, addr_type; | | 94 | uint32_t icbflags, addr_type; |
95 | uint32_t len, lb_num; | | 95 | uint32_t len, lb_num; |
96 | uint32_t flags; | | 96 | uint32_t flags; |
97 | int part_num; | | 97 | int part_num; |
98 | int lb_size, eof, slot; | | 98 | int lb_size, eof, slot; |
99 | | | 99 | |
100 | if ((udf_verbose & UDF_DEBUG_NODEDUMP) == 0) | | 100 | if ((udf_verbose & UDF_DEBUG_NODEDUMP) == 0) |
101 | return; | | 101 | return; |
102 | | | 102 | |
103 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 103 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
104 | | | 104 | |
105 | fe = udf_node->fe; | | 105 | fe = udf_node->fe; |
106 | efe = udf_node->efe; | | 106 | efe = udf_node->efe; |
107 | if (fe) { | | 107 | if (fe) { |
108 | icbtag = &fe->icbtag; | | 108 | icbtag = &fe->icbtag; |
109 | inflen = udf_rw64(fe->inf_len); | | 109 | inflen = udf_rw64(fe->inf_len); |
110 | } else { | | 110 | } else { |
111 | icbtag = &efe->icbtag; | | 111 | icbtag = &efe->icbtag; |
112 | inflen = udf_rw64(efe->inf_len); | | 112 | inflen = udf_rw64(efe->inf_len); |
113 | } | | 113 | } |
114 | | | 114 | |
115 | icbflags = udf_rw16(icbtag->flags); | | 115 | icbflags = udf_rw16(icbtag->flags); |
116 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 116 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
117 | | | 117 | |
118 | printf("udf_node_dump %p :\n", udf_node); | | 118 | printf("udf_node_dump %p :\n", udf_node); |
119 | | | 119 | |
120 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 120 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
121 | printf("\tIntern alloc, len = %"PRIu64"\n", inflen); | | 121 | printf("\tIntern alloc, len = %"PRIu64"\n", inflen); |
122 | return; | | 122 | return; |
123 | } | | 123 | } |
124 | | | 124 | |
125 | printf("\tInflen = %"PRIu64"\n", inflen); | | 125 | printf("\tInflen = %"PRIu64"\n", inflen); |
126 | printf("\t\t"); | | 126 | printf("\t\t"); |
127 | | | 127 | |
128 | slot = 0; | | 128 | slot = 0; |
129 | for (;;) { | | 129 | for (;;) { |
130 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 130 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
131 | if (eof) | | 131 | if (eof) |
132 | break; | | 132 | break; |
133 | part_num = udf_rw16(s_ad.loc.part_num); | | 133 | part_num = udf_rw16(s_ad.loc.part_num); |
134 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 134 | lb_num = udf_rw32(s_ad.loc.lb_num); |
135 | len = udf_rw32(s_ad.len); | | 135 | len = udf_rw32(s_ad.len); |
136 | flags = UDF_EXT_FLAGS(len); | | 136 | flags = UDF_EXT_FLAGS(len); |
137 | len = UDF_EXT_LEN(len); | | 137 | len = UDF_EXT_LEN(len); |
138 | | | 138 | |
139 | printf("["); | | 139 | printf("["); |
140 | if (part_num >= 0) | | 140 | if (part_num >= 0) |
141 | printf("part %d, ", part_num); | | 141 | printf("part %d, ", part_num); |
142 | printf("lb_num %d, len %d", lb_num, len); | | 142 | printf("lb_num %d, len %d", lb_num, len); |
143 | if (flags) | | 143 | if (flags) |
144 | printf(", flags %d", flags>>30); | | 144 | printf(", flags %d", flags>>30); |
145 | printf("] "); | | 145 | printf("] "); |
146 | | | 146 | |
147 | if (flags == UDF_EXT_REDIRECT) { | | 147 | if (flags == UDF_EXT_REDIRECT) { |
148 | printf("\n\textent END\n\tallocation extent\n\t\t"); | | 148 | printf("\n\textent END\n\tallocation extent\n\t\t"); |
149 | } | | 149 | } |
150 | | | 150 | |
151 | slot++; | | 151 | slot++; |
152 | } | | 152 | } |
153 | printf("\n\tl_ad END\n\n"); | | 153 | printf("\n\tl_ad END\n\n"); |
154 | } | | 154 | } |
155 | #else | | 155 | #else |
156 | #define udf_node_dump(a) | | 156 | #define udf_node_dump(a) |
157 | #endif | | 157 | #endif |
158 | | | 158 | |
159 | | | 159 | |
160 | static void | | 160 | static void |
161 | udf_assert_allocated(struct udf_mount *ump, uint16_t vpart_num, | | 161 | udf_assert_allocated(struct udf_mount *ump, uint16_t vpart_num, |
162 | uint32_t lb_num, uint32_t num_lb) | | 162 | uint32_t lb_num, uint32_t num_lb) |
163 | { | | 163 | { |
164 | struct udf_bitmap *bitmap; | | 164 | struct udf_bitmap *bitmap; |
165 | struct part_desc *pdesc; | | 165 | struct part_desc *pdesc; |
166 | uint32_t ptov; | | 166 | uint32_t ptov; |
167 | uint32_t bitval; | | 167 | uint32_t bitval; |
168 | uint8_t *bpos; | | 168 | uint8_t *bpos; |
169 | int bit; | | 169 | int bit; |
170 | int phys_part; | | 170 | int phys_part; |
171 | int ok; | | 171 | int ok; |
172 | | | 172 | |
173 | DPRINTF(PARANOIA, ("udf_assert_allocated: check virt lbnum %d " | | 173 | DPRINTF(PARANOIA, ("udf_assert_allocated: check virt lbnum %d " |
174 | "part %d + %d sect\n", lb_num, vpart_num, num_lb)); | | 174 | "part %d + %d sect\n", lb_num, vpart_num, num_lb)); |
175 | | | 175 | |
176 | /* get partition backing up this vpart_num */ | | 176 | /* get partition backing up this vpart_num */ |
177 | pdesc = ump->partitions[ump->vtop[vpart_num]]; | | 177 | pdesc = ump->partitions[ump->vtop[vpart_num]]; |
178 | | | 178 | |
179 | switch (ump->vtop_tp[vpart_num]) { | | 179 | switch (ump->vtop_tp[vpart_num]) { |
180 | case UDF_VTOP_TYPE_PHYS : | | 180 | case UDF_VTOP_TYPE_PHYS : |
181 | case UDF_VTOP_TYPE_SPARABLE : | | 181 | case UDF_VTOP_TYPE_SPARABLE : |
182 | /* free space to freed or unallocated space bitmap */ | | 182 | /* free space to freed or unallocated space bitmap */ |
183 | ptov = udf_rw32(pdesc->start_loc); | | 183 | ptov = udf_rw32(pdesc->start_loc); |
184 | phys_part = ump->vtop[vpart_num]; | | 184 | phys_part = ump->vtop[vpart_num]; |
185 | | | 185 | |
186 | /* use unallocated bitmap */ | | 186 | /* use unallocated bitmap */ |
187 | bitmap = &ump->part_unalloc_bits[phys_part]; | | 187 | bitmap = &ump->part_unalloc_bits[phys_part]; |
188 | | | 188 | |
189 | /* if no bitmaps are defined, bail out */ | | 189 | /* if no bitmaps are defined, bail out */ |
190 | if (bitmap->bits == NULL) | | 190 | if (bitmap->bits == NULL) |
191 | break; | | 191 | break; |
192 | | | 192 | |
193 | /* check bits */ | | 193 | /* check bits */ |
194 | KASSERT(bitmap->bits); | | 194 | KASSERT(bitmap->bits); |
195 | ok = 1; | | 195 | ok = 1; |
196 | bpos = bitmap->bits + lb_num/8; | | 196 | bpos = bitmap->bits + lb_num/8; |
197 | bit = lb_num % 8; | | 197 | bit = lb_num % 8; |
198 | while (num_lb > 0) { | | 198 | while (num_lb > 0) { |
199 | bitval = (1 << bit); | | 199 | bitval = (1 << bit); |
200 | DPRINTF(PARANOIA, ("XXX : check %d, %p, bit %d\n", | | 200 | DPRINTF(PARANOIA, ("XXX : check %d, %p, bit %d\n", |
201 | lb_num, bpos, bit)); | | 201 | lb_num, bpos, bit)); |
202 | KASSERT(bitmap->bits + lb_num/8 == bpos); | | 202 | KASSERT(bitmap->bits + lb_num/8 == bpos); |
203 | if (*bpos & bitval) { | | 203 | if (*bpos & bitval) { |
204 | printf("\tlb_num %d is NOT marked busy\n", | | 204 | printf("\tlb_num %d is NOT marked busy\n", |
205 | lb_num); | | 205 | lb_num); |
206 | ok = 0; | | 206 | ok = 0; |
207 | } | | 207 | } |
208 | lb_num++; num_lb--; | | 208 | lb_num++; num_lb--; |
209 | bit = (bit + 1) % 8; | | 209 | bit = (bit + 1) % 8; |
210 | if (bit == 0) | | 210 | if (bit == 0) |
211 | bpos++; | | 211 | bpos++; |
212 | } | | 212 | } |
213 | if (!ok) { | | 213 | if (!ok) { |
214 | /* KASSERT(0); */ | | 214 | /* KASSERT(0); */ |
215 | } | | 215 | } |
216 | | | 216 | |
217 | break; | | 217 | break; |
218 | case UDF_VTOP_TYPE_VIRT : | | 218 | case UDF_VTOP_TYPE_VIRT : |
219 | /* TODO check space */ | | 219 | /* TODO check space */ |
220 | KASSERT(num_lb == 1); | | 220 | KASSERT(num_lb == 1); |
221 | break; | | 221 | break; |
222 | case UDF_VTOP_TYPE_META : | | 222 | case UDF_VTOP_TYPE_META : |
223 | /* TODO check space in the metadata bitmap */ | | 223 | /* TODO check space in the metadata bitmap */ |
224 | default: | | 224 | default: |
225 | /* not implemented */ | | 225 | /* not implemented */ |
226 | break; | | 226 | break; |
227 | } | | 227 | } |
228 | } | | 228 | } |
229 | | | 229 | |
230 | | | 230 | |
231 | static void | | 231 | static void |
232 | udf_node_sanity_check(struct udf_node *udf_node, | | 232 | udf_node_sanity_check(struct udf_node *udf_node, |
233 | uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) | | 233 | uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) |
234 | { | | 234 | { |
235 | union dscrptr *dscr; | | 235 | union dscrptr *dscr; |
236 | struct file_entry *fe; | | 236 | struct file_entry *fe; |
237 | struct extfile_entry *efe; | | 237 | struct extfile_entry *efe; |
238 | struct icb_tag *icbtag; | | 238 | struct icb_tag *icbtag; |
239 | struct long_ad s_ad; | | 239 | struct long_ad s_ad; |
240 | uint64_t inflen, logblksrec; | | 240 | uint64_t inflen, logblksrec; |
241 | uint32_t icbflags, addr_type; | | 241 | uint32_t icbflags, addr_type; |
242 | uint32_t len, lb_num, l_ea, l_ad, max_l_ad; | | 242 | uint32_t len, lb_num, l_ea, l_ad, max_l_ad; |
243 | uint16_t part_num; | | 243 | uint16_t part_num; |
244 | uint8_t *data_pos; | | 244 | uint8_t *data_pos; |
245 | int dscr_size, lb_size, flags, whole_lb; | | 245 | int dscr_size, lb_size, flags, whole_lb; |
246 | int i, slot, eof; | | 246 | int i, slot, eof; |
247 | | | 247 | |
248 | // KASSERT(mutex_owned(&udf_node->ump->allocate_mutex)); | | 248 | // KASSERT(mutex_owned(&udf_node->ump->allocate_mutex)); |
249 | | | 249 | |
250 | if (1) | | 250 | if (1) |
251 | udf_node_dump(udf_node); | | 251 | udf_node_dump(udf_node); |
252 | | | 252 | |
253 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 253 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
254 | | | 254 | |
255 | fe = udf_node->fe; | | 255 | fe = udf_node->fe; |
256 | efe = udf_node->efe; | | 256 | efe = udf_node->efe; |
257 | if (fe) { | | 257 | if (fe) { |
258 | dscr = (union dscrptr *) fe; | | 258 | dscr = (union dscrptr *) fe; |
259 | icbtag = &fe->icbtag; | | 259 | icbtag = &fe->icbtag; |
260 | inflen = udf_rw64(fe->inf_len); | | 260 | inflen = udf_rw64(fe->inf_len); |
261 | dscr_size = sizeof(struct file_entry) -1; | | 261 | dscr_size = sizeof(struct file_entry) -1; |
262 | logblksrec = udf_rw64(fe->logblks_rec); | | 262 | logblksrec = udf_rw64(fe->logblks_rec); |
263 | l_ad = udf_rw32(fe->l_ad); | | 263 | l_ad = udf_rw32(fe->l_ad); |
264 | l_ea = udf_rw32(fe->l_ea); | | 264 | l_ea = udf_rw32(fe->l_ea); |
265 | } else { | | 265 | } else { |
266 | dscr = (union dscrptr *) efe; | | 266 | dscr = (union dscrptr *) efe; |
267 | icbtag = &efe->icbtag; | | 267 | icbtag = &efe->icbtag; |
268 | inflen = udf_rw64(efe->inf_len); | | 268 | inflen = udf_rw64(efe->inf_len); |
269 | dscr_size = sizeof(struct extfile_entry) -1; | | 269 | dscr_size = sizeof(struct extfile_entry) -1; |
270 | logblksrec = udf_rw64(efe->logblks_rec); | | 270 | logblksrec = udf_rw64(efe->logblks_rec); |
271 | l_ad = udf_rw32(efe->l_ad); | | 271 | l_ad = udf_rw32(efe->l_ad); |
272 | l_ea = udf_rw32(efe->l_ea); | | 272 | l_ea = udf_rw32(efe->l_ea); |
273 | } | | 273 | } |
274 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; | | 274 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; |
275 | max_l_ad = lb_size - dscr_size - l_ea; | | 275 | max_l_ad = lb_size - dscr_size - l_ea; |
276 | icbflags = udf_rw16(icbtag->flags); | | 276 | icbflags = udf_rw16(icbtag->flags); |
277 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 277 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
278 | | | 278 | |
279 | /* check if tail is zero */ | | 279 | /* check if tail is zero */ |
280 | DPRINTF(PARANOIA, ("Sanity check blank tail\n")); | | 280 | DPRINTF(PARANOIA, ("Sanity check blank tail\n")); |
281 | for (i = l_ad; i < max_l_ad; i++) { | | 281 | for (i = l_ad; i < max_l_ad; i++) { |
282 | if (data_pos[i] != 0) | | 282 | if (data_pos[i] != 0) |
283 | printf( "sanity_check: violation: node byte %d " | | 283 | printf( "sanity_check: violation: node byte %d " |
284 | "has value %d\n", i, data_pos[i]); | | 284 | "has value %d\n", i, data_pos[i]); |
285 | } | | 285 | } |
286 | | | 286 | |
287 | /* reset counters */ | | 287 | /* reset counters */ |
288 | *cnt_inflen = 0; | | 288 | *cnt_inflen = 0; |
289 | *cnt_logblksrec = 0; | | 289 | *cnt_logblksrec = 0; |
290 | | | 290 | |
291 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 291 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
292 | KASSERT(l_ad <= max_l_ad); | | 292 | KASSERT(l_ad <= max_l_ad); |
293 | KASSERT(l_ad == inflen); | | 293 | KASSERT(l_ad == inflen); |
294 | *cnt_inflen = inflen; | | 294 | *cnt_inflen = inflen; |
295 | return; | | 295 | return; |
296 | } | | 296 | } |
297 | | | 297 | |
298 | /* start counting */ | | 298 | /* start counting */ |
299 | whole_lb = 1; | | 299 | whole_lb = 1; |
300 | slot = 0; | | 300 | slot = 0; |
301 | for (;;) { | | 301 | for (;;) { |
302 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 302 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
303 | if (eof) | | 303 | if (eof) |
304 | break; | | 304 | break; |
305 | KASSERT(whole_lb == 1); | | 305 | KASSERT(whole_lb == 1); |
306 | | | 306 | |
307 | part_num = udf_rw16(s_ad.loc.part_num); | | 307 | part_num = udf_rw16(s_ad.loc.part_num); |
308 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 308 | lb_num = udf_rw32(s_ad.loc.lb_num); |
309 | len = udf_rw32(s_ad.len); | | 309 | len = udf_rw32(s_ad.len); |
310 | flags = UDF_EXT_FLAGS(len); | | 310 | flags = UDF_EXT_FLAGS(len); |
311 | len = UDF_EXT_LEN(len); | | 311 | len = UDF_EXT_LEN(len); |
312 | | | 312 | |
313 | if (flags != UDF_EXT_REDIRECT) { | | 313 | if (flags != UDF_EXT_REDIRECT) { |
314 | *cnt_inflen += len; | | 314 | *cnt_inflen += len; |
315 | if (flags == UDF_EXT_ALLOCATED) { | | 315 | if (flags == UDF_EXT_ALLOCATED) { |
316 | *cnt_logblksrec += (len + lb_size -1) / lb_size; | | 316 | *cnt_logblksrec += (len + lb_size -1) / lb_size; |
317 | } | | 317 | } |
318 | } else { | | 318 | } else { |
319 | KASSERT(len == lb_size); | | 319 | KASSERT(len == lb_size); |
320 | } | | 320 | } |
321 | /* check allocation */ | | 321 | /* check allocation */ |
322 | if (flags == UDF_EXT_ALLOCATED) | | 322 | if (flags == UDF_EXT_ALLOCATED) |
323 | udf_assert_allocated(udf_node->ump, part_num, lb_num, | | 323 | udf_assert_allocated(udf_node->ump, part_num, lb_num, |
324 | (len + lb_size - 1) / lb_size); | | 324 | (len + lb_size - 1) / lb_size); |
325 | | | 325 | |
326 | /* check whole lb */ | | 326 | /* check whole lb */ |
327 | whole_lb = ((len % lb_size) == 0); | | 327 | whole_lb = ((len % lb_size) == 0); |
328 | | | 328 | |
329 | slot++; | | 329 | slot++; |
330 | } | | 330 | } |
331 | /* rest should be zero (ad_off > l_ad < max_l_ad - adlen) */ | | 331 | /* rest should be zero (ad_off > l_ad < max_l_ad - adlen) */ |
332 | | | 332 | |
333 | KASSERT(*cnt_inflen == inflen); | | 333 | KASSERT(*cnt_inflen == inflen); |
334 | KASSERT(*cnt_logblksrec == logblksrec); | | 334 | KASSERT(*cnt_logblksrec == logblksrec); |
335 | | | 335 | |
336 | // KASSERT(mutex_owned(&udf_node->ump->allocate_mutex)); | | 336 | // KASSERT(mutex_owned(&udf_node->ump->allocate_mutex)); |
337 | } | | 337 | } |
338 | #else | | 338 | #else |
339 | static void | | 339 | static void |
340 | udf_node_sanity_check(struct udf_node *udf_node, | | 340 | udf_node_sanity_check(struct udf_node *udf_node, |
341 | uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) { | | 341 | uint64_t *cnt_inflen, uint64_t *cnt_logblksrec) { |
342 | struct file_entry *fe; | | 342 | struct file_entry *fe; |
343 | struct extfile_entry *efe; | | 343 | struct extfile_entry *efe; |
344 | struct icb_tag *icbtag; | | 344 | struct icb_tag *icbtag; |
345 | uint64_t inflen, logblksrec; | | 345 | uint64_t inflen, logblksrec; |
346 | int dscr_size, lb_size; | | 346 | int dscr_size, lb_size; |
347 | | | 347 | |
348 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 348 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
349 | | | 349 | |
350 | fe = udf_node->fe; | | 350 | fe = udf_node->fe; |
351 | efe = udf_node->efe; | | 351 | efe = udf_node->efe; |
352 | if (fe) { | | 352 | if (fe) { |
353 | icbtag = &fe->icbtag; | | 353 | icbtag = &fe->icbtag; |
354 | inflen = udf_rw64(fe->inf_len); | | 354 | inflen = udf_rw64(fe->inf_len); |
355 | dscr_size = sizeof(struct file_entry) -1; | | 355 | dscr_size = sizeof(struct file_entry) -1; |
356 | logblksrec = udf_rw64(fe->logblks_rec); | | 356 | logblksrec = udf_rw64(fe->logblks_rec); |
357 | } else { | | 357 | } else { |
358 | icbtag = &efe->icbtag; | | 358 | icbtag = &efe->icbtag; |
359 | inflen = udf_rw64(efe->inf_len); | | 359 | inflen = udf_rw64(efe->inf_len); |
360 | dscr_size = sizeof(struct extfile_entry) -1; | | 360 | dscr_size = sizeof(struct extfile_entry) -1; |
361 | logblksrec = udf_rw64(efe->logblks_rec); | | 361 | logblksrec = udf_rw64(efe->logblks_rec); |
362 | } | | 362 | } |
363 | *cnt_logblksrec = logblksrec; | | 363 | *cnt_logblksrec = logblksrec; |
364 | *cnt_inflen = inflen; | | 364 | *cnt_inflen = inflen; |
365 | } | | 365 | } |
366 | #endif | | 366 | #endif |
367 | | | 367 | |
368 | /* --------------------------------------------------------------------- */ | | 368 | /* --------------------------------------------------------------------- */ |
369 | | | 369 | |
370 | int | | 370 | int |
371 | udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, | | 371 | udf_translate_vtop(struct udf_mount *ump, struct long_ad *icb_loc, |
372 | uint32_t *lb_numres, uint32_t *extres) | | 372 | uint32_t *lb_numres, uint32_t *extres) |
373 | { | | 373 | { |
374 | struct part_desc *pdesc; | | 374 | struct part_desc *pdesc; |
375 | struct spare_map_entry *sme; | | 375 | struct spare_map_entry *sme; |
376 | struct long_ad s_icb_loc; | | 376 | struct long_ad s_icb_loc; |
377 | uint64_t foffset, end_foffset; | | 377 | uint64_t foffset, end_foffset; |
378 | uint32_t lb_size, len; | | 378 | uint32_t lb_size, len; |
379 | uint32_t lb_num, lb_rel, lb_packet; | | 379 | uint32_t lb_num, lb_rel, lb_packet; |
380 | uint32_t udf_rw32_lbmap, ext_offset; | | 380 | uint32_t udf_rw32_lbmap, ext_offset; |
381 | uint16_t vpart; | | 381 | uint16_t vpart; |
382 | int rel, part, error, eof, slot, flags; | | 382 | int rel, part, error, eof, slot, flags; |
383 | | | 383 | |
384 | assert(ump && icb_loc && lb_numres); | | 384 | assert(ump && icb_loc && lb_numres); |
385 | | | 385 | |
386 | vpart = udf_rw16(icb_loc->loc.part_num); | | 386 | vpart = udf_rw16(icb_loc->loc.part_num); |
387 | lb_num = udf_rw32(icb_loc->loc.lb_num); | | 387 | lb_num = udf_rw32(icb_loc->loc.lb_num); |
388 | if (vpart > UDF_VTOP_RAWPART) | | 388 | if (vpart > UDF_VTOP_RAWPART) |
389 | return EINVAL; | | 389 | return EINVAL; |
390 | | | 390 | |
391 | translate_again: | | 391 | translate_again: |
392 | part = ump->vtop[vpart]; | | 392 | part = ump->vtop[vpart]; |
393 | pdesc = ump->partitions[part]; | | 393 | pdesc = ump->partitions[part]; |
394 | | | 394 | |
395 | switch (ump->vtop_tp[vpart]) { | | 395 | switch (ump->vtop_tp[vpart]) { |
396 | case UDF_VTOP_TYPE_RAW : | | 396 | case UDF_VTOP_TYPE_RAW : |
397 | /* 1:1 to the end of the device */ | | 397 | /* 1:1 to the end of the device */ |
398 | *lb_numres = lb_num; | | 398 | *lb_numres = lb_num; |
399 | *extres = INT_MAX; | | 399 | *extres = INT_MAX; |
400 | return 0; | | 400 | return 0; |
401 | case UDF_VTOP_TYPE_PHYS : | | 401 | case UDF_VTOP_TYPE_PHYS : |
402 | /* transform into its disc logical block */ | | 402 | /* transform into its disc logical block */ |
403 | if (lb_num > udf_rw32(pdesc->part_len)) | | 403 | if (lb_num > udf_rw32(pdesc->part_len)) |
404 | return EINVAL; | | 404 | return EINVAL; |
405 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); | | 405 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); |
406 | | | 406 | |
407 | /* extent from here to the end of the partition */ | | 407 | /* extent from here to the end of the partition */ |
408 | *extres = udf_rw32(pdesc->part_len) - lb_num; | | 408 | *extres = udf_rw32(pdesc->part_len) - lb_num; |
409 | return 0; | | 409 | return 0; |
410 | case UDF_VTOP_TYPE_VIRT : | | 410 | case UDF_VTOP_TYPE_VIRT : |
411 | /* only maps one logical block, lookup in VAT */ | | 411 | /* only maps one logical block, lookup in VAT */ |
412 | if (lb_num >= ump->vat_entries) /* XXX > or >= ? */ | | 412 | if (lb_num >= ump->vat_entries) /* XXX > or >= ? */ |
413 | return EINVAL; | | 413 | return EINVAL; |
414 | | | 414 | |
415 | /* lookup in virtual allocation table file */ | | 415 | /* lookup in virtual allocation table file */ |
416 | mutex_enter(&ump->allocate_mutex); | | 416 | mutex_enter(&ump->allocate_mutex); |
417 | error = udf_vat_read(ump->vat_node, | | 417 | error = udf_vat_read(ump->vat_node, |
418 | (uint8_t *) &udf_rw32_lbmap, 4, | | 418 | (uint8_t *) &udf_rw32_lbmap, 4, |
419 | ump->vat_offset + lb_num * 4); | | 419 | ump->vat_offset + lb_num * 4); |
420 | mutex_exit(&ump->allocate_mutex); | | 420 | mutex_exit(&ump->allocate_mutex); |
421 | | | 421 | |
422 | if (error) | | 422 | if (error) |
423 | return error; | | 423 | return error; |
424 | | | 424 | |
425 | lb_num = udf_rw32(udf_rw32_lbmap); | | 425 | lb_num = udf_rw32(udf_rw32_lbmap); |
426 | | | 426 | |
427 | /* transform into its disc logical block */ | | 427 | /* transform into its disc logical block */ |
428 | if (lb_num > udf_rw32(pdesc->part_len)) | | 428 | if (lb_num > udf_rw32(pdesc->part_len)) |
429 | return EINVAL; | | 429 | return EINVAL; |
430 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); | | 430 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); |
431 | | | 431 | |
432 | /* just one logical block */ | | 432 | /* just one logical block */ |
433 | *extres = 1; | | 433 | *extres = 1; |
434 | return 0; | | 434 | return 0; |
435 | case UDF_VTOP_TYPE_SPARABLE : | | 435 | case UDF_VTOP_TYPE_SPARABLE : |
436 | /* check if the packet containing the lb_num is remapped */ | | 436 | /* check if the packet containing the lb_num is remapped */ |
437 | lb_packet = lb_num / ump->sparable_packet_size; | | 437 | lb_packet = lb_num / ump->sparable_packet_size; |
438 | lb_rel = lb_num % ump->sparable_packet_size; | | 438 | lb_rel = lb_num % ump->sparable_packet_size; |
439 | | | 439 | |
440 | for (rel = 0; rel < udf_rw16(ump->sparing_table->rt_l); rel++) { | | 440 | for (rel = 0; rel < udf_rw16(ump->sparing_table->rt_l); rel++) { |
441 | sme = &ump->sparing_table->entries[rel]; | | 441 | sme = &ump->sparing_table->entries[rel]; |
442 | if (lb_packet == udf_rw32(sme->org)) { | | 442 | if (lb_packet == udf_rw32(sme->org)) { |
443 | /* NOTE maps to absolute disc logical block! */ | | 443 | /* NOTE maps to absolute disc logical block! */ |
444 | *lb_numres = udf_rw32(sme->map) + lb_rel; | | 444 | *lb_numres = udf_rw32(sme->map) + lb_rel; |
445 | *extres = ump->sparable_packet_size - lb_rel; | | 445 | *extres = ump->sparable_packet_size - lb_rel; |
446 | return 0; | | 446 | return 0; |
447 | } | | 447 | } |
448 | } | | 448 | } |
449 | | | 449 | |
450 | /* transform into its disc logical block */ | | 450 | /* transform into its disc logical block */ |
451 | if (lb_num > udf_rw32(pdesc->part_len)) | | 451 | if (lb_num > udf_rw32(pdesc->part_len)) |
452 | return EINVAL; | | 452 | return EINVAL; |
453 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); | | 453 | *lb_numres = lb_num + udf_rw32(pdesc->start_loc); |
454 | | | 454 | |
455 | /* rest of block */ | | 455 | /* rest of block */ |
456 | *extres = ump->sparable_packet_size - lb_rel; | | 456 | *extres = ump->sparable_packet_size - lb_rel; |
457 | return 0; | | 457 | return 0; |
458 | case UDF_VTOP_TYPE_META : | | 458 | case UDF_VTOP_TYPE_META : |
459 | /* we have to look into the file's allocation descriptors */ | | 459 | /* we have to look into the file's allocation descriptors */ |
460 | | | 460 | |
461 | /* use metadatafile allocation mutex */ | | 461 | /* use metadatafile allocation mutex */ |
462 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 462 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
463 | | | 463 | |
464 | UDF_LOCK_NODE(ump->metadata_node, 0); | | 464 | UDF_LOCK_NODE(ump->metadata_node, 0); |
465 | | | 465 | |
466 | /* get first overlapping extent */ | | 466 | /* get first overlapping extent */ |
467 | foffset = 0; | | 467 | foffset = 0; |
468 | slot = 0; | | 468 | slot = 0; |
469 | for (;;) { | | 469 | for (;;) { |
470 | udf_get_adslot(ump->metadata_node, | | 470 | udf_get_adslot(ump->metadata_node, |
471 | slot, &s_icb_loc, &eof); | | 471 | slot, &s_icb_loc, &eof); |
472 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, " | | 472 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, " |
473 | "len = %d, lb_num = %d, part = %d\n", | | 473 | "len = %d, lb_num = %d, part = %d\n", |
474 | slot, eof, | | 474 | slot, eof, |
475 | UDF_EXT_FLAGS(udf_rw32(s_icb_loc.len)), | | 475 | UDF_EXT_FLAGS(udf_rw32(s_icb_loc.len)), |
476 | UDF_EXT_LEN(udf_rw32(s_icb_loc.len)), | | 476 | UDF_EXT_LEN(udf_rw32(s_icb_loc.len)), |
477 | udf_rw32(s_icb_loc.loc.lb_num), | | 477 | udf_rw32(s_icb_loc.loc.lb_num), |
478 | udf_rw16(s_icb_loc.loc.part_num))); | | 478 | udf_rw16(s_icb_loc.loc.part_num))); |
479 | if (eof) { | | 479 | if (eof) { |
480 | DPRINTF(TRANSLATE, | | 480 | DPRINTF(TRANSLATE, |
481 | ("Meta partition translation " | | 481 | ("Meta partition translation " |
482 | "failed: can't seek location\n")); | | 482 | "failed: can't seek location\n")); |
483 | UDF_UNLOCK_NODE(ump->metadata_node, 0); | | 483 | UDF_UNLOCK_NODE(ump->metadata_node, 0); |
484 | return EINVAL; | | 484 | return EINVAL; |
485 | } | | 485 | } |
486 | len = udf_rw32(s_icb_loc.len); | | 486 | len = udf_rw32(s_icb_loc.len); |
487 | flags = UDF_EXT_FLAGS(len); | | 487 | flags = UDF_EXT_FLAGS(len); |
488 | len = UDF_EXT_LEN(len); | | 488 | len = UDF_EXT_LEN(len); |
489 | | | 489 | |
490 | if (flags == UDF_EXT_REDIRECT) { | | 490 | if (flags == UDF_EXT_REDIRECT) { |
491 | slot++; | | 491 | slot++; |
492 | continue; | | 492 | continue; |
493 | } | | 493 | } |
494 | | | 494 | |
495 | end_foffset = foffset + len; | | 495 | end_foffset = foffset + len; |
496 | | | 496 | |
497 | if (end_foffset > lb_num * lb_size) | | 497 | if (end_foffset > lb_num * lb_size) |
498 | break; /* found */ | | 498 | break; /* found */ |
499 | foffset = end_foffset; | | 499 | foffset = end_foffset; |
500 | slot++; | | 500 | slot++; |
501 | } | | 501 | } |
502 | /* found overlapping slot */ | | 502 | /* found overlapping slot */ |
503 | ext_offset = lb_num * lb_size - foffset; | | 503 | ext_offset = lb_num * lb_size - foffset; |
504 | | | 504 | |
505 | /* process extent offset */ | | 505 | /* process extent offset */ |
506 | lb_num = udf_rw32(s_icb_loc.loc.lb_num); | | 506 | lb_num = udf_rw32(s_icb_loc.loc.lb_num); |
507 | vpart = udf_rw16(s_icb_loc.loc.part_num); | | 507 | vpart = udf_rw16(s_icb_loc.loc.part_num); |
508 | lb_num += (ext_offset + lb_size -1) / lb_size; | | 508 | lb_num += (ext_offset + lb_size -1) / lb_size; |
509 | ext_offset = 0; | | 509 | ext_offset = 0; |
510 | | | 510 | |
511 | UDF_UNLOCK_NODE(ump->metadata_node, 0); | | 511 | UDF_UNLOCK_NODE(ump->metadata_node, 0); |
512 | if (flags != UDF_EXT_ALLOCATED) { | | 512 | if (flags != UDF_EXT_ALLOCATED) { |
513 | DPRINTF(TRANSLATE, ("Metadata partition translation " | | 513 | DPRINTF(TRANSLATE, ("Metadata partition translation " |
514 | "failed: not allocated\n")); | | 514 | "failed: not allocated\n")); |
515 | return EINVAL; | | 515 | return EINVAL; |
516 | } | | 516 | } |
517 | | | 517 | |
518 | /* | | 518 | /* |
519 | * vpart and lb_num are updated, translate again since we | | 519 | * vpart and lb_num are updated, translate again since we |
520 | * might be mapped on sparable media | | 520 | * might be mapped on sparable media |
521 | */ | | 521 | */ |
522 | goto translate_again; | | 522 | goto translate_again; |
523 | default: | | 523 | default: |
524 | printf("UDF vtop translation scheme %d unimplemented yet\n", | | 524 | printf("UDF vtop translation scheme %d unimplemented yet\n", |
525 | ump->vtop_tp[vpart]); | | 525 | ump->vtop_tp[vpart]); |
526 | } | | 526 | } |
527 | | | 527 | |
528 | return EINVAL; | | 528 | return EINVAL; |
529 | } | | 529 | } |
530 | | | 530 | |
531 | | | 531 | |
532 | /* XXX provisional primitive braindead version */ | | 532 | /* XXX provisional primitive braindead version */ |
533 | /* TODO use ext_res */ | | 533 | /* TODO use ext_res */ |
534 | void | | 534 | void |
535 | udf_translate_vtop_list(struct udf_mount *ump, uint32_t sectors, | | 535 | udf_translate_vtop_list(struct udf_mount *ump, uint32_t sectors, |
536 | uint16_t vpart_num, uint64_t *lmapping, uint64_t *pmapping) | | 536 | uint16_t vpart_num, uint64_t *lmapping, uint64_t *pmapping) |
537 | { | | 537 | { |
538 | struct long_ad loc; | | 538 | struct long_ad loc; |
539 | uint32_t lb_numres, ext_res; | | 539 | uint32_t lb_numres, ext_res; |
540 | int sector; | | 540 | int sector; |
541 | | | 541 | |
542 | for (sector = 0; sector < sectors; sector++) { | | 542 | for (sector = 0; sector < sectors; sector++) { |
543 | memset(&loc, 0, sizeof(struct long_ad)); | | 543 | memset(&loc, 0, sizeof(struct long_ad)); |
544 | loc.loc.part_num = udf_rw16(vpart_num); | | 544 | loc.loc.part_num = udf_rw16(vpart_num); |
545 | loc.loc.lb_num = udf_rw32(*lmapping); | | 545 | loc.loc.lb_num = udf_rw32(*lmapping); |
546 | udf_translate_vtop(ump, &loc, &lb_numres, &ext_res); | | 546 | udf_translate_vtop(ump, &loc, &lb_numres, &ext_res); |
547 | *pmapping = lb_numres; | | 547 | *pmapping = lb_numres; |
548 | lmapping++; pmapping++; | | 548 | lmapping++; pmapping++; |
549 | } | | 549 | } |
550 | } | | 550 | } |
551 | | | 551 | |
552 | | | 552 | |
553 | /* --------------------------------------------------------------------- */ | | 553 | /* --------------------------------------------------------------------- */ |
554 | | | 554 | |
555 | /* | | 555 | /* |
556 | * Translate an extent (in logical_blocks) into logical block numbers; used | | 556 | * Translate an extent (in logical_blocks) into logical block numbers; used |
557 | * for read and write operations. DOESNT't check extents. | | 557 | * for read and write operations. DOESNT't check extents. |
558 | */ | | 558 | */ |
559 | | | 559 | |
560 | int | | 560 | int |
561 | udf_translate_file_extent(struct udf_node *udf_node, | | 561 | udf_translate_file_extent(struct udf_node *udf_node, |
562 | uint32_t from, uint32_t num_lb, | | 562 | uint32_t from, uint32_t num_lb, |
563 | uint64_t *map) | | 563 | uint64_t *map) |
564 | { | | 564 | { |
565 | struct udf_mount *ump; | | 565 | struct udf_mount *ump; |
566 | struct icb_tag *icbtag; | | 566 | struct icb_tag *icbtag; |
567 | struct long_ad t_ad, s_ad; | | 567 | struct long_ad t_ad, s_ad; |
568 | uint64_t transsec; | | 568 | uint64_t transsec; |
569 | uint64_t foffset, end_foffset; | | 569 | uint64_t foffset, end_foffset; |
570 | uint32_t transsec32; | | 570 | uint32_t transsec32; |
571 | uint32_t lb_size; | | 571 | uint32_t lb_size; |
572 | uint32_t ext_offset; | | 572 | uint32_t ext_offset; |
573 | uint32_t lb_num, len; | | 573 | uint32_t lb_num, len; |
574 | uint32_t overlap, translen; | | 574 | uint32_t overlap, translen; |
575 | uint16_t vpart_num; | | 575 | uint16_t vpart_num; |
576 | int eof, error, flags; | | 576 | int eof, error, flags; |
577 | int slot, addr_type, icbflags; | | 577 | int slot, addr_type, icbflags; |
578 | | | 578 | |
579 | if (!udf_node) | | 579 | if (!udf_node) |
580 | return ENOENT; | | 580 | return ENOENT; |
581 | | | 581 | |
582 | KASSERT(num_lb > 0); | | 582 | KASSERT(num_lb > 0); |
583 | | | 583 | |
584 | UDF_LOCK_NODE(udf_node, 0); | | 584 | UDF_LOCK_NODE(udf_node, 0); |
585 | | | 585 | |
586 | /* initialise derivative vars */ | | 586 | /* initialise derivative vars */ |
587 | ump = udf_node->ump; | | 587 | ump = udf_node->ump; |
588 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 588 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
589 | | | 589 | |
590 | if (udf_node->fe) { | | 590 | if (udf_node->fe) { |
591 | icbtag = &udf_node->fe->icbtag; | | 591 | icbtag = &udf_node->fe->icbtag; |
592 | } else { | | 592 | } else { |
593 | icbtag = &udf_node->efe->icbtag; | | 593 | icbtag = &udf_node->efe->icbtag; |
594 | } | | 594 | } |
595 | icbflags = udf_rw16(icbtag->flags); | | 595 | icbflags = udf_rw16(icbtag->flags); |
596 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 596 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
597 | | | 597 | |
598 | /* do the work */ | | 598 | /* do the work */ |
599 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 599 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
600 | *map = UDF_TRANS_INTERN; | | 600 | *map = UDF_TRANS_INTERN; |
601 | UDF_UNLOCK_NODE(udf_node, 0); | | 601 | UDF_UNLOCK_NODE(udf_node, 0); |
602 | return 0; | | 602 | return 0; |
603 | } | | 603 | } |
604 | | | 604 | |
605 | /* find first overlapping extent */ | | 605 | /* find first overlapping extent */ |
606 | foffset = 0; | | 606 | foffset = 0; |
607 | slot = 0; | | 607 | slot = 0; |
608 | for (;;) { | | 608 | for (;;) { |
609 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 609 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
610 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " | | 610 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " |
611 | "lb_num = %d, part = %d\n", slot, eof, | | 611 | "lb_num = %d, part = %d\n", slot, eof, |
612 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)), | | 612 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)), |
613 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 613 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
614 | udf_rw32(s_ad.loc.lb_num), | | 614 | udf_rw32(s_ad.loc.lb_num), |
615 | udf_rw16(s_ad.loc.part_num))); | | 615 | udf_rw16(s_ad.loc.part_num))); |
616 | if (eof) { | | 616 | if (eof) { |
617 | DPRINTF(TRANSLATE, | | 617 | DPRINTF(TRANSLATE, |
618 | ("Translate file extent " | | 618 | ("Translate file extent " |
619 | "failed: can't seek location\n")); | | 619 | "failed: can't seek location\n")); |
620 | UDF_UNLOCK_NODE(udf_node, 0); | | 620 | UDF_UNLOCK_NODE(udf_node, 0); |
621 | return EINVAL; | | 621 | return EINVAL; |
622 | } | | 622 | } |
623 | len = udf_rw32(s_ad.len); | | 623 | len = udf_rw32(s_ad.len); |
624 | flags = UDF_EXT_FLAGS(len); | | 624 | flags = UDF_EXT_FLAGS(len); |
625 | len = UDF_EXT_LEN(len); | | 625 | len = UDF_EXT_LEN(len); |
626 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 626 | lb_num = udf_rw32(s_ad.loc.lb_num); |
627 | | | 627 | |
628 | if (flags == UDF_EXT_REDIRECT) { | | 628 | if (flags == UDF_EXT_REDIRECT) { |
629 | slot++; | | 629 | slot++; |
630 | continue; | | 630 | continue; |
631 | } | | 631 | } |
632 | | | 632 | |
633 | end_foffset = foffset + len; | | 633 | end_foffset = foffset + len; |
634 | | | 634 | |
635 | if (end_foffset > from * lb_size) | | 635 | if (end_foffset > from * lb_size) |
636 | break; /* found */ | | 636 | break; /* found */ |
637 | foffset = end_foffset; | | 637 | foffset = end_foffset; |
638 | slot++; | | 638 | slot++; |
639 | } | | 639 | } |
640 | /* found overlapping slot */ | | 640 | /* found overlapping slot */ |
641 | ext_offset = from * lb_size - foffset; | | 641 | ext_offset = from * lb_size - foffset; |
642 | | | 642 | |
643 | for (;;) { | | 643 | for (;;) { |
644 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 644 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
645 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " | | 645 | DPRINTF(ADWLK, ("slot %d, eof = %d, flags = %d, len = %d, " |
646 | "lb_num = %d, part = %d\n", slot, eof, | | 646 | "lb_num = %d, part = %d\n", slot, eof, |
647 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)), | | 647 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)), |
648 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 648 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
649 | udf_rw32(s_ad.loc.lb_num), | | 649 | udf_rw32(s_ad.loc.lb_num), |
650 | udf_rw16(s_ad.loc.part_num))); | | 650 | udf_rw16(s_ad.loc.part_num))); |
651 | if (eof) { | | 651 | if (eof) { |
652 | DPRINTF(TRANSLATE, | | 652 | DPRINTF(TRANSLATE, |
653 | ("Translate file extent " | | 653 | ("Translate file extent " |
654 | "failed: past eof\n")); | | 654 | "failed: past eof\n")); |
655 | UDF_UNLOCK_NODE(udf_node, 0); | | 655 | UDF_UNLOCK_NODE(udf_node, 0); |
656 | return EINVAL; | | 656 | return EINVAL; |
657 | } | | 657 | } |
658 | | | 658 | |
659 | len = udf_rw32(s_ad.len); | | 659 | len = udf_rw32(s_ad.len); |
660 | flags = UDF_EXT_FLAGS(len); | | 660 | flags = UDF_EXT_FLAGS(len); |
661 | len = UDF_EXT_LEN(len); | | 661 | len = UDF_EXT_LEN(len); |
662 | | | 662 | |
663 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 663 | lb_num = udf_rw32(s_ad.loc.lb_num); |
664 | vpart_num = udf_rw16(s_ad.loc.part_num); | | 664 | vpart_num = udf_rw16(s_ad.loc.part_num); |
665 | | | 665 | |
666 | end_foffset = foffset + len; | | 666 | end_foffset = foffset + len; |
667 | | | 667 | |
668 | /* process extent, don't forget to advance on ext_offset! */ | | 668 | /* process extent, don't forget to advance on ext_offset! */ |
669 | lb_num += (ext_offset + lb_size -1) / lb_size; | | 669 | lb_num += (ext_offset + lb_size -1) / lb_size; |
670 | overlap = (len - ext_offset + lb_size -1) / lb_size; | | 670 | overlap = (len - ext_offset + lb_size -1) / lb_size; |
671 | ext_offset = 0; | | 671 | ext_offset = 0; |
672 | | | 672 | |
673 | /* | | 673 | /* |
674 | * note that the while(){} is nessisary for the extent that | | 674 | * note that the while(){} is nessisary for the extent that |
675 | * the udf_translate_vtop() returns doens't have to span the | | 675 | * the udf_translate_vtop() returns doens't have to span the |
676 | * whole extent. | | 676 | * whole extent. |
677 | */ | | 677 | */ |
678 | | | 678 | |
679 | overlap = MIN(overlap, num_lb); | | 679 | overlap = MIN(overlap, num_lb); |
680 | while (overlap && (flags != UDF_EXT_REDIRECT)) { | | 680 | while (overlap && (flags != UDF_EXT_REDIRECT)) { |
681 | switch (flags) { | | 681 | switch (flags) { |
682 | case UDF_EXT_FREE : | | 682 | case UDF_EXT_FREE : |
683 | case UDF_EXT_ALLOCATED_BUT_NOT_USED : | | 683 | case UDF_EXT_ALLOCATED_BUT_NOT_USED : |
684 | transsec = UDF_TRANS_ZERO; | | 684 | transsec = UDF_TRANS_ZERO; |
685 | translen = overlap; | | 685 | translen = overlap; |
686 | while (overlap && num_lb && translen) { | | 686 | while (overlap && num_lb && translen) { |
687 | *map++ = transsec; | | 687 | *map++ = transsec; |
688 | lb_num++; | | 688 | lb_num++; |
689 | overlap--; num_lb--; translen--; | | 689 | overlap--; num_lb--; translen--; |
690 | } | | 690 | } |
691 | break; | | 691 | break; |
692 | case UDF_EXT_ALLOCATED : | | 692 | case UDF_EXT_ALLOCATED : |
693 | t_ad.loc.lb_num = udf_rw32(lb_num); | | 693 | t_ad.loc.lb_num = udf_rw32(lb_num); |
694 | t_ad.loc.part_num = udf_rw16(vpart_num); | | 694 | t_ad.loc.part_num = udf_rw16(vpart_num); |
695 | error = udf_translate_vtop(ump, | | 695 | error = udf_translate_vtop(ump, |
696 | &t_ad, &transsec32, &translen); | | 696 | &t_ad, &transsec32, &translen); |
697 | transsec = transsec32; | | 697 | transsec = transsec32; |
698 | if (error) { | | 698 | if (error) { |
699 | UDF_UNLOCK_NODE(udf_node, 0); | | 699 | UDF_UNLOCK_NODE(udf_node, 0); |
700 | return error; | | 700 | return error; |
701 | } | | 701 | } |
702 | while (overlap && num_lb && translen) { | | 702 | while (overlap && num_lb && translen) { |
703 | *map++ = transsec; | | 703 | *map++ = transsec; |
704 | lb_num++; transsec++; | | 704 | lb_num++; transsec++; |
705 | overlap--; num_lb--; translen--; | | 705 | overlap--; num_lb--; translen--; |
706 | } | | 706 | } |
707 | break; | | 707 | break; |
708 | default: | | 708 | default: |
709 | DPRINTF(TRANSLATE, | | 709 | DPRINTF(TRANSLATE, |
710 | ("Translate file extent " | | 710 | ("Translate file extent " |
711 | "failed: bad flags %x\n", flags)); | | 711 | "failed: bad flags %x\n", flags)); |
712 | UDF_UNLOCK_NODE(udf_node, 0); | | 712 | UDF_UNLOCK_NODE(udf_node, 0); |
713 | return EINVAL; | | 713 | return EINVAL; |
714 | } | | 714 | } |
715 | } | | 715 | } |
716 | if (num_lb == 0) | | 716 | if (num_lb == 0) |
717 | break; | | 717 | break; |
718 | | | 718 | |
719 | if (flags != UDF_EXT_REDIRECT) | | 719 | if (flags != UDF_EXT_REDIRECT) |
720 | foffset = end_foffset; | | 720 | foffset = end_foffset; |
721 | slot++; | | 721 | slot++; |
722 | } | | 722 | } |
723 | UDF_UNLOCK_NODE(udf_node, 0); | | 723 | UDF_UNLOCK_NODE(udf_node, 0); |
724 | | | 724 | |
725 | return 0; | | 725 | return 0; |
726 | } | | 726 | } |
727 | | | 727 | |
728 | /* --------------------------------------------------------------------- */ | | 728 | /* --------------------------------------------------------------------- */ |
729 | | | 729 | |
730 | static int | | 730 | static int |
731 | udf_search_free_vatloc(struct udf_mount *ump, uint32_t *lbnumres) | | 731 | udf_search_free_vatloc(struct udf_mount *ump, uint32_t *lbnumres) |
732 | { | | 732 | { |
733 | uint32_t lb_size, lb_num, lb_map, udf_rw32_lbmap; | | 733 | uint32_t lb_size, lb_num, lb_map, udf_rw32_lbmap; |
734 | uint8_t *blob; | | 734 | uint8_t *blob; |
735 | int entry, chunk, found, error; | | 735 | int entry, chunk, found, error; |
736 | | | 736 | |
737 | KASSERT(ump); | | 737 | KASSERT(ump); |
738 | KASSERT(ump->logical_vol); | | 738 | KASSERT(ump->logical_vol); |
739 | | | 739 | |
740 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 740 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
741 | blob = malloc(lb_size, M_UDFTEMP, M_WAITOK); | | 741 | blob = malloc(lb_size, M_UDFTEMP, M_WAITOK); |
742 | | | 742 | |
743 | /* TODO static allocation of search chunk */ | | 743 | /* TODO static allocation of search chunk */ |
744 | | | 744 | |
745 | lb_num = MIN(ump->vat_entries, ump->vat_last_free_lb); | | 745 | lb_num = MIN(ump->vat_entries, ump->vat_last_free_lb); |
746 | found = 0; | | 746 | found = 0; |
747 | error = 0; | | 747 | error = 0; |
748 | entry = 0; | | 748 | entry = 0; |
749 | do { | | 749 | do { |
750 | chunk = MIN(lb_size, (ump->vat_entries - lb_num) * 4); | | 750 | chunk = MIN(lb_size, (ump->vat_entries - lb_num) * 4); |
751 | if (chunk <= 0) | | 751 | if (chunk <= 0) |
752 | break; | | 752 | break; |
753 | /* load in chunk */ | | 753 | /* load in chunk */ |
754 | error = udf_vat_read(ump->vat_node, blob, chunk, | | 754 | error = udf_vat_read(ump->vat_node, blob, chunk, |
755 | ump->vat_offset + lb_num * 4); | | 755 | ump->vat_offset + lb_num * 4); |
756 | | | 756 | |
757 | if (error) | | 757 | if (error) |
758 | break; | | 758 | break; |
759 | | | 759 | |
760 | /* search this chunk */ | | 760 | /* search this chunk */ |
761 | for (entry=0; entry < chunk /4; entry++, lb_num++) { | | 761 | for (entry=0; entry < chunk /4; entry++, lb_num++) { |
762 | udf_rw32_lbmap = *((uint32_t *) (blob + entry * 4)); | | 762 | udf_rw32_lbmap = *((uint32_t *) (blob + entry * 4)); |
763 | lb_map = udf_rw32(udf_rw32_lbmap); | | 763 | lb_map = udf_rw32(udf_rw32_lbmap); |
764 | if (lb_map == 0xffffffff) { | | 764 | if (lb_map == 0xffffffff) { |
765 | found = 1; | | 765 | found = 1; |
766 | break; | | 766 | break; |
767 | } | | 767 | } |
768 | } | | 768 | } |
769 | } while (!found); | | 769 | } while (!found); |
770 | if (error) { | | 770 | if (error) { |
771 | printf("udf_search_free_vatloc: error reading in vat chunk " | | 771 | printf("udf_search_free_vatloc: error reading in vat chunk " |
772 | "(lb %d, size %d)\n", lb_num, chunk); | | 772 | "(lb %d, size %d)\n", lb_num, chunk); |
773 | } | | 773 | } |
774 | | | 774 | |
775 | if (!found) { | | 775 | if (!found) { |
776 | /* extend VAT */ | | 776 | /* extend VAT */ |
777 | DPRINTF(WRITE, ("udf_search_free_vatloc: extending\n")); | | 777 | DPRINTF(WRITE, ("udf_search_free_vatloc: extending\n")); |
778 | lb_num = ump->vat_entries; | | 778 | lb_num = ump->vat_entries; |
779 | ump->vat_entries++; | | 779 | ump->vat_entries++; |
780 | } | | 780 | } |
781 | | | 781 | |
782 | /* mark entry with initialiser just in case */ | | 782 | /* mark entry with initialiser just in case */ |
783 | lb_map = udf_rw32(0xfffffffe); | | 783 | lb_map = udf_rw32(0xfffffffe); |
784 | udf_vat_write(ump->vat_node, (uint8_t *) &lb_map, 4, | | 784 | udf_vat_write(ump->vat_node, (uint8_t *) &lb_map, 4, |
785 | ump->vat_offset + lb_num *4); | | 785 | ump->vat_offset + lb_num *4); |
786 | ump->vat_last_free_lb = lb_num; | | 786 | ump->vat_last_free_lb = lb_num; |
787 | | | 787 | |
788 | free(blob, M_UDFTEMP); | | 788 | free(blob, M_UDFTEMP); |
789 | *lbnumres = lb_num; | | 789 | *lbnumres = lb_num; |
790 | return 0; | | 790 | return 0; |
791 | } | | 791 | } |
792 | | | 792 | |
793 | | | 793 | |
794 | static void | | 794 | static void |
795 | udf_bitmap_allocate(struct udf_bitmap *bitmap, int ismetadata, | | 795 | udf_bitmap_allocate(struct udf_bitmap *bitmap, int ismetadata, |
796 | uint32_t *num_lb, uint64_t *lmappos) | | 796 | uint32_t *num_lb, uint64_t *lmappos) |
797 | { | | 797 | { |
798 | uint32_t offset, lb_num, bit; | | 798 | uint32_t offset, lb_num, bit; |
799 | int32_t diff; | | 799 | int32_t diff; |
800 | uint8_t *bpos; | | 800 | uint8_t *bpos; |
801 | int pass; | | 801 | int pass; |
802 | | | 802 | |
803 | if (!ismetadata) { | | 803 | if (!ismetadata) { |
804 | /* heuristic to keep the two pointers not too close */ | | 804 | /* heuristic to keep the two pointers not too close */ |
805 | diff = bitmap->data_pos - bitmap->metadata_pos; | | 805 | diff = bitmap->data_pos - bitmap->metadata_pos; |
806 | if ((diff >= 0) && (diff < 1024)) | | 806 | if ((diff >= 0) && (diff < 1024)) |
807 | bitmap->data_pos = bitmap->metadata_pos + 1024; | | 807 | bitmap->data_pos = bitmap->metadata_pos + 1024; |
808 | } | | 808 | } |
809 | offset = ismetadata ? bitmap->metadata_pos : bitmap->data_pos; | | 809 | offset = ismetadata ? bitmap->metadata_pos : bitmap->data_pos; |
810 | offset &= ~7; | | 810 | offset &= ~7; |
811 | for (pass = 0; pass < 2; pass++) { | | 811 | for (pass = 0; pass < 2; pass++) { |
812 | if (offset >= bitmap->max_offset) | | 812 | if (offset >= bitmap->max_offset) |
813 | offset = 0; | | 813 | offset = 0; |
814 | | | 814 | |
815 | while (offset < bitmap->max_offset) { | | 815 | while (offset < bitmap->max_offset) { |
816 | if (*num_lb == 0) | | 816 | if (*num_lb == 0) |
817 | break; | | 817 | break; |
818 | | | 818 | |
819 | /* use first bit not set */ | | 819 | /* use first bit not set */ |
820 | bpos = bitmap->bits + offset/8; | | 820 | bpos = bitmap->bits + offset/8; |
821 | bit = ffs(*bpos); /* returns 0 or 1..8 */ | | 821 | bit = ffs(*bpos); /* returns 0 or 1..8 */ |
822 | if (bit == 0) { | | 822 | if (bit == 0) { |
823 | offset += 8; | | 823 | offset += 8; |
824 | continue; | | 824 | continue; |
825 | } | | 825 | } |
826 | | | 826 | |
827 | /* check for ffs overshoot */ | | 827 | /* check for ffs overshoot */ |
828 | if (offset + bit-1 >= bitmap->max_offset) { | | 828 | if (offset + bit-1 >= bitmap->max_offset) { |
829 | offset = bitmap->max_offset; | | 829 | offset = bitmap->max_offset; |
830 | break; | | 830 | break; |
831 | } | | 831 | } |
832 | | | 832 | |
833 | DPRINTF(PARANOIA, ("XXX : allocate %d, %p, bit %d\n", | | 833 | DPRINTF(PARANOIA, ("XXX : allocate %d, %p, bit %d\n", |
834 | offset + bit -1, bpos, bit-1)); | | 834 | offset + bit -1, bpos, bit-1)); |
835 | *bpos &= ~(1 << (bit-1)); | | 835 | *bpos &= ~(1 << (bit-1)); |
836 | lb_num = offset + bit-1; | | 836 | lb_num = offset + bit-1; |
837 | *lmappos++ = lb_num; | | 837 | *lmappos++ = lb_num; |
838 | *num_lb = *num_lb - 1; | | 838 | *num_lb = *num_lb - 1; |
839 | // offset = (offset & ~7); | | 839 | // offset = (offset & ~7); |
840 | } | | 840 | } |
841 | } | | 841 | } |
842 | | | 842 | |
843 | if (ismetadata) { | | 843 | if (ismetadata) { |
844 | bitmap->metadata_pos = offset; | | 844 | bitmap->metadata_pos = offset; |
845 | } else { | | 845 | } else { |
846 | bitmap->data_pos = offset; | | 846 | bitmap->data_pos = offset; |
847 | } | | 847 | } |
848 | } | | 848 | } |
849 | | | 849 | |
850 | | | 850 | |
851 | static void | | 851 | static void |
852 | udf_bitmap_free(struct udf_bitmap *bitmap, uint32_t lb_num, uint32_t num_lb) | | 852 | udf_bitmap_free(struct udf_bitmap *bitmap, uint32_t lb_num, uint32_t num_lb) |
853 | { | | 853 | { |
854 | uint32_t offset; | | 854 | uint32_t offset; |
855 | uint32_t bit, bitval; | | 855 | uint32_t bit, bitval; |
856 | uint8_t *bpos; | | 856 | uint8_t *bpos; |
857 | | | 857 | |
858 | offset = lb_num; | | 858 | offset = lb_num; |
859 | | | 859 | |
860 | /* starter bits */ | | 860 | /* starter bits */ |
861 | bpos = bitmap->bits + offset/8; | | 861 | bpos = bitmap->bits + offset/8; |
862 | bit = offset % 8; | | 862 | bit = offset % 8; |
863 | while ((bit != 0) && (num_lb > 0)) { | | 863 | while ((bit != 0) && (num_lb > 0)) { |
864 | bitval = (1 << bit); | | 864 | bitval = (1 << bit); |
865 | KASSERT((*bpos & bitval) == 0); | | 865 | KASSERT((*bpos & bitval) == 0); |
866 | DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", | | 866 | DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", |
867 | offset, bpos, bit)); | | 867 | offset, bpos, bit)); |
868 | *bpos |= bitval; | | 868 | *bpos |= bitval; |
869 | offset++; num_lb--; | | 869 | offset++; num_lb--; |
870 | bit = (bit + 1) % 8; | | 870 | bit = (bit + 1) % 8; |
871 | } | | 871 | } |
872 | if (num_lb == 0) | | 872 | if (num_lb == 0) |
873 | return; | | 873 | return; |
874 | | | 874 | |
875 | /* whole bytes */ | | 875 | /* whole bytes */ |
876 | KASSERT(bit == 0); | | 876 | KASSERT(bit == 0); |
877 | bpos = bitmap->bits + offset / 8; | | 877 | bpos = bitmap->bits + offset / 8; |
878 | while (num_lb >= 8) { | | 878 | while (num_lb >= 8) { |
879 | KASSERT((*bpos == 0)); | | 879 | KASSERT((*bpos == 0)); |
880 | DPRINTF(PARANOIA, ("XXX : free %d + 8, %p\n", offset, bpos)); | | 880 | DPRINTF(PARANOIA, ("XXX : free %d + 8, %p\n", offset, bpos)); |
881 | *bpos = 255; | | 881 | *bpos = 255; |
882 | offset += 8; num_lb -= 8; | | 882 | offset += 8; num_lb -= 8; |
883 | bpos++; | | 883 | bpos++; |
884 | } | | 884 | } |
885 | | | 885 | |
886 | /* stop bits */ | | 886 | /* stop bits */ |
887 | KASSERT(num_lb < 8); | | 887 | KASSERT(num_lb < 8); |
888 | bit = 0; | | 888 | bit = 0; |
889 | while (num_lb > 0) { | | 889 | while (num_lb > 0) { |
890 | bitval = (1 << bit); | | 890 | bitval = (1 << bit); |
891 | KASSERT((*bpos & bitval) == 0); | | 891 | KASSERT((*bpos & bitval) == 0); |
892 | DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", | | 892 | DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", |
893 | offset, bpos, bit)); | | 893 | offset, bpos, bit)); |
894 | *bpos |= bitval; | | 894 | *bpos |= bitval; |
895 | offset++; num_lb--; | | 895 | offset++; num_lb--; |
896 | bit = (bit + 1) % 8; | | 896 | bit = (bit + 1) % 8; |
897 | } | | 897 | } |
898 | } | | 898 | } |
899 | | | 899 | |
900 | | | 900 | |
901 | /* allocate a contiguous sequence of sectornumbers */ | | 901 | /* allocate a contiguous sequence of sectornumbers */ |
902 | static int | | 902 | static int |
903 | udf_allocate_space(struct udf_mount *ump, int udf_c_type, | | 903 | udf_allocate_space(struct udf_mount *ump, int udf_c_type, |
904 | uint16_t vpart_num, uint32_t num_lb, uint64_t *lmapping) | | 904 | uint16_t vpart_num, uint32_t num_lb, uint64_t *lmapping) |
905 | { | | 905 | { |
906 | struct mmc_trackinfo *alloc_track, *other_track; | | 906 | struct mmc_trackinfo *alloc_track, *other_track; |
907 | struct udf_bitmap *bitmap; | | 907 | struct udf_bitmap *bitmap; |
908 | struct part_desc *pdesc; | | 908 | struct part_desc *pdesc; |
909 | struct logvol_int_desc *lvid; | | 909 | struct logvol_int_desc *lvid; |
910 | uint64_t *lmappos; | | 910 | uint64_t *lmappos; |
911 | uint32_t ptov, lb_num, *freepos, free_lbs; | | 911 | uint32_t ptov, lb_num, *freepos, free_lbs; |
912 | int lb_size, alloc_num_lb; | | 912 | int lb_size, alloc_num_lb; |
913 | int alloc_type, error; | | 913 | int alloc_type, error; |
914 | int is_node; | | 914 | int is_node; |
915 | | | 915 | |
916 | DPRINTF(CALL, ("udf_allocate_space(ctype %d, vpart %d, num_lb %d\n", | | 916 | DPRINTF(CALL, ("udf_allocate_space(ctype %d, vpart %d, num_lb %d\n", |
917 | udf_c_type, vpart_num, num_lb)); | | 917 | udf_c_type, vpart_num, num_lb)); |
918 | mutex_enter(&ump->allocate_mutex); | | 918 | mutex_enter(&ump->allocate_mutex); |
919 | | | 919 | |
920 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 920 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
921 | KASSERT(lb_size == ump->discinfo.sector_size); | | 921 | KASSERT(lb_size == ump->discinfo.sector_size); |
922 | | | 922 | |
923 | /* XXX TODO check disc space */ | | 923 | /* XXX TODO check disc space */ |
924 | | | 924 | |
925 | alloc_type = ump->vtop_alloc[vpart_num]; | | 925 | alloc_type = ump->vtop_alloc[vpart_num]; |
926 | is_node = (udf_c_type == UDF_C_NODE); | | 926 | is_node = (udf_c_type == UDF_C_NODE); |
927 | | | 927 | |
928 | lmappos = lmapping; | | 928 | lmappos = lmapping; |
929 | error = 0; | | 929 | error = 0; |
930 | switch (alloc_type) { | | 930 | switch (alloc_type) { |
931 | case UDF_ALLOC_VAT : | | 931 | case UDF_ALLOC_VAT : |
932 | /* search empty slot in VAT file */ | | 932 | /* search empty slot in VAT file */ |
933 | KASSERT(num_lb == 1); | | 933 | KASSERT(num_lb == 1); |
934 | error = udf_search_free_vatloc(ump, &lb_num); | | 934 | error = udf_search_free_vatloc(ump, &lb_num); |
935 | if (!error) | | 935 | if (!error) |
936 | *lmappos = lb_num; | | 936 | *lmappos = lb_num; |
937 | break; | | 937 | break; |
938 | case UDF_ALLOC_SEQUENTIAL : | | 938 | case UDF_ALLOC_SEQUENTIAL : |
939 | /* sequential allocation on recordable media */ | | 939 | /* sequential allocation on recordable media */ |
940 | /* get partition backing up this vpart_num_num */ | | 940 | /* get partition backing up this vpart_num_num */ |
941 | pdesc = ump->partitions[ump->vtop[vpart_num]]; | | 941 | pdesc = ump->partitions[ump->vtop[vpart_num]]; |
942 | | | 942 | |
943 | /* calculate offset from physical base partition */ | | 943 | /* calculate offset from physical base partition */ |
944 | ptov = udf_rw32(pdesc->start_loc); | | 944 | ptov = udf_rw32(pdesc->start_loc); |
945 | | | 945 | |
946 | /* get our track descriptors */ | | 946 | /* get our track descriptors */ |
947 | if (vpart_num == ump->node_part) { | | 947 | if (vpart_num == ump->node_part) { |
948 | alloc_track = &ump->metadata_track; | | 948 | alloc_track = &ump->metadata_track; |
949 | other_track = &ump->data_track; | | 949 | other_track = &ump->data_track; |
950 | } else { | | 950 | } else { |
951 | alloc_track = &ump->data_track; | | 951 | alloc_track = &ump->data_track; |
952 | other_track = &ump->metadata_track; | | 952 | other_track = &ump->metadata_track; |
953 | } | | 953 | } |
954 | | | 954 | |
955 | /* allocate */ | | 955 | /* allocate */ |
956 | for (lb_num = 0; lb_num < num_lb; lb_num++) { | | 956 | for (lb_num = 0; lb_num < num_lb; lb_num++) { |
957 | *lmappos++ = alloc_track->next_writable - ptov; | | 957 | *lmappos++ = alloc_track->next_writable - ptov; |
958 | alloc_track->next_writable++; | | 958 | alloc_track->next_writable++; |
959 | alloc_track->free_blocks--; | | 959 | alloc_track->free_blocks--; |
960 | } | | 960 | } |
961 | | | 961 | |
962 | /* keep other track up-to-date */ | | 962 | /* keep other track up-to-date */ |
963 | if (alloc_track->tracknr == other_track->tracknr) | | 963 | if (alloc_track->tracknr == other_track->tracknr) |
964 | memcpy(other_track, alloc_track, | | 964 | memcpy(other_track, alloc_track, |
965 | sizeof(struct mmc_trackinfo)); | | 965 | sizeof(struct mmc_trackinfo)); |
966 | break; | | 966 | break; |
967 | case UDF_ALLOC_SPACEMAP : | | 967 | case UDF_ALLOC_SPACEMAP : |
968 | /* try to allocate on unallocated bits */ | | 968 | /* try to allocate on unallocated bits */ |
969 | alloc_num_lb = num_lb; | | 969 | alloc_num_lb = num_lb; |
970 | bitmap = &ump->part_unalloc_bits[vpart_num]; | | 970 | bitmap = &ump->part_unalloc_bits[vpart_num]; |
971 | udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); | | 971 | udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); |
972 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; | | 972 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; |
973 | | | 973 | |
974 | /* have we allocated all? */ | | 974 | /* have we allocated all? */ |
975 | if (alloc_num_lb) { | | 975 | if (alloc_num_lb) { |
976 | /* TODO convert freed to unalloc and try again */ | | 976 | /* TODO convert freed to unalloc and try again */ |
977 | /* free allocated piece for now */ | | 977 | /* free allocated piece for now */ |
978 | lmappos = lmapping; | | 978 | lmappos = lmapping; |
979 | for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { | | 979 | for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { |
980 | udf_bitmap_free(bitmap, *lmappos++, 1); | | 980 | udf_bitmap_free(bitmap, *lmappos++, 1); |
981 | } | | 981 | } |
982 | error = ENOSPC; | | 982 | error = ENOSPC; |
983 | } | | 983 | } |
984 | if (!error) { | | 984 | if (!error) { |
985 | /* adjust freecount */ | | 985 | /* adjust freecount */ |
986 | lvid = ump->logvol_integrity; | | 986 | lvid = ump->logvol_integrity; |
987 | freepos = &lvid->tables[0] + vpart_num; | | 987 | freepos = &lvid->tables[0] + vpart_num; |
988 | free_lbs = udf_rw32(*freepos); | | 988 | free_lbs = udf_rw32(*freepos); |
989 | *freepos = udf_rw32(free_lbs - num_lb); | | 989 | *freepos = udf_rw32(free_lbs - num_lb); |
990 | } | | 990 | } |
991 | break; | | 991 | break; |
992 | case UDF_ALLOC_METABITMAP : /* UDF 2.50, 2.60 BluRay-RE */ | | 992 | case UDF_ALLOC_METABITMAP : /* UDF 2.50, 2.60 BluRay-RE */ |
993 | /* allocate on metadata unallocated bits */ | | 993 | /* allocate on metadata unallocated bits */ |
994 | alloc_num_lb = num_lb; | | 994 | alloc_num_lb = num_lb; |
995 | bitmap = &ump->metadata_unalloc_bits; | | 995 | bitmap = &ump->metadata_unalloc_bits; |
996 | udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); | | 996 | udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); |
997 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; | | 997 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; |
998 | | | 998 | |
999 | /* have we allocated all? */ | | 999 | /* have we allocated all? */ |
1000 | if (alloc_num_lb) { | | 1000 | if (alloc_num_lb) { |
1001 | /* YIKES! TODO we need to extend the metadata partition */ | | 1001 | /* YIKES! TODO we need to extend the metadata partition */ |
1002 | /* free allocated piece for now */ | | 1002 | /* free allocated piece for now */ |
1003 | lmappos = lmapping; | | 1003 | lmappos = lmapping; |
1004 | for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { | | 1004 | for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { |
1005 | udf_bitmap_free(bitmap, *lmappos++, 1); | | 1005 | udf_bitmap_free(bitmap, *lmappos++, 1); |
1006 | } | | 1006 | } |
1007 | error = ENOSPC; | | 1007 | error = ENOSPC; |
1008 | } | | 1008 | } |
1009 | if (!error) { | | 1009 | if (!error) { |
1010 | /* adjust freecount */ | | 1010 | /* adjust freecount */ |
1011 | lvid = ump->logvol_integrity; | | 1011 | lvid = ump->logvol_integrity; |
1012 | freepos = &lvid->tables[0] + vpart_num; | | 1012 | freepos = &lvid->tables[0] + vpart_num; |
1013 | free_lbs = udf_rw32(*freepos); | | 1013 | free_lbs = udf_rw32(*freepos); |
1014 | *freepos = udf_rw32(free_lbs - num_lb); | | 1014 | *freepos = udf_rw32(free_lbs - num_lb); |
1015 | } | | 1015 | } |
1016 | break; | | 1016 | break; |
1017 | case UDF_ALLOC_METASEQUENTIAL : /* UDF 2.60 BluRay-R */ | | 1017 | case UDF_ALLOC_METASEQUENTIAL : /* UDF 2.60 BluRay-R */ |
1018 | case UDF_ALLOC_RELAXEDSEQUENTIAL : /* UDF 2.50/~meta BluRay-R */ | | 1018 | case UDF_ALLOC_RELAXEDSEQUENTIAL : /* UDF 2.50/~meta BluRay-R */ |
1019 | printf("ALERT: udf_allocate_space : allocation %d " | | 1019 | printf("ALERT: udf_allocate_space : allocation %d " |
1020 | "not implemented yet!\n", alloc_type); | | 1020 | "not implemented yet!\n", alloc_type); |
1021 | /* TODO implement, doesn't have to be contiguous */ | | 1021 | /* TODO implement, doesn't have to be contiguous */ |
1022 | error = ENOSPC; | | 1022 | error = ENOSPC; |
1023 | break; | | 1023 | break; |
1024 | } | | 1024 | } |
1025 | | | 1025 | |
1026 | #ifdef DEBUG | | 1026 | #ifdef DEBUG |
1027 | if (udf_verbose & UDF_DEBUG_ALLOC) { | | 1027 | if (udf_verbose & UDF_DEBUG_ALLOC) { |
1028 | lmappos = lmapping; | | 1028 | lmappos = lmapping; |
1029 | printf("udf_allocate_space, allocated logical lba :\n"); | | 1029 | printf("udf_allocate_space, allocated logical lba :\n"); |
1030 | for (lb_num = 0; lb_num < num_lb; lb_num++) { | | 1030 | for (lb_num = 0; lb_num < num_lb; lb_num++) { |
1031 | printf("%s %"PRIu64",", (lb_num > 0)?",":"", | | 1031 | printf("%s %"PRIu64, (lb_num > 0)?",":"", |
1032 | *lmappos++); | | 1032 | *lmappos++); |
1033 | } | | 1033 | } |
1034 | printf("\n"); | | 1034 | printf("\n"); |
1035 | } | | 1035 | } |
1036 | #endif | | 1036 | #endif |
1037 | mutex_exit(&ump->allocate_mutex); | | 1037 | mutex_exit(&ump->allocate_mutex); |
1038 | | | 1038 | |
1039 | return error; | | 1039 | return error; |
1040 | } | | 1040 | } |
1041 | | | 1041 | |
1042 | /* --------------------------------------------------------------------- */ | | 1042 | /* --------------------------------------------------------------------- */ |
1043 | | | 1043 | |
1044 | void | | 1044 | void |
1045 | udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, | | 1045 | udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, |
1046 | uint16_t vpart_num, uint32_t num_lb) | | 1046 | uint16_t vpart_num, uint32_t num_lb) |
1047 | { | | 1047 | { |
1048 | struct udf_bitmap *bitmap; | | 1048 | struct udf_bitmap *bitmap; |
1049 | struct part_desc *pdesc; | | 1049 | struct part_desc *pdesc; |
1050 | struct logvol_int_desc *lvid; | | 1050 | struct logvol_int_desc *lvid; |
1051 | uint32_t ptov, lb_map, udf_rw32_lbmap; | | 1051 | uint32_t ptov, lb_map, udf_rw32_lbmap; |
1052 | uint32_t *freepos, free_lbs; | | 1052 | uint32_t *freepos, free_lbs; |
1053 | int phys_part; | | 1053 | int phys_part; |
1054 | int error; | | 1054 | int error; |
1055 | | | 1055 | |
1056 | DPRINTF(ALLOC, ("udf_free_allocated_space: freeing virt lbnum %d " | | 1056 | DPRINTF(ALLOC, ("udf_free_allocated_space: freeing virt lbnum %d " |
1057 | "part %d + %d sect\n", lb_num, vpart_num, num_lb)); | | 1057 | "part %d + %d sect\n", lb_num, vpart_num, num_lb)); |
1058 | | | 1058 | |
1059 | /* no use freeing zero length */ | | 1059 | /* no use freeing zero length */ |
1060 | if (num_lb == 0) | | 1060 | if (num_lb == 0) |
1061 | return; | | 1061 | return; |
1062 | | | 1062 | |
1063 | mutex_enter(&ump->allocate_mutex); | | 1063 | mutex_enter(&ump->allocate_mutex); |
1064 | | | 1064 | |
1065 | /* get partition backing up this vpart_num */ | | 1065 | /* get partition backing up this vpart_num */ |
1066 | pdesc = ump->partitions[ump->vtop[vpart_num]]; | | 1066 | pdesc = ump->partitions[ump->vtop[vpart_num]]; |
1067 | | | 1067 | |
1068 | switch (ump->vtop_tp[vpart_num]) { | | 1068 | switch (ump->vtop_tp[vpart_num]) { |
1069 | case UDF_VTOP_TYPE_PHYS : | | 1069 | case UDF_VTOP_TYPE_PHYS : |
1070 | case UDF_VTOP_TYPE_SPARABLE : | | 1070 | case UDF_VTOP_TYPE_SPARABLE : |
1071 | /* free space to freed or unallocated space bitmap */ | | 1071 | /* free space to freed or unallocated space bitmap */ |
1072 | ptov = udf_rw32(pdesc->start_loc); | | 1072 | ptov = udf_rw32(pdesc->start_loc); |
1073 | phys_part = ump->vtop[vpart_num]; | | 1073 | phys_part = ump->vtop[vpart_num]; |
1074 | | | 1074 | |
1075 | /* first try freed space bitmap */ | | 1075 | /* first try freed space bitmap */ |
1076 | bitmap = &ump->part_freed_bits[phys_part]; | | 1076 | bitmap = &ump->part_freed_bits[phys_part]; |
1077 | | | 1077 | |
1078 | /* if not defined, use unallocated bitmap */ | | 1078 | /* if not defined, use unallocated bitmap */ |
1079 | if (bitmap->bits == NULL) | | 1079 | if (bitmap->bits == NULL) |
1080 | bitmap = &ump->part_unalloc_bits[phys_part]; | | 1080 | bitmap = &ump->part_unalloc_bits[phys_part]; |
1081 | | | 1081 | |
1082 | /* if no bitmaps are defined, bail out; XXX OK? */ | | 1082 | /* if no bitmaps are defined, bail out; XXX OK? */ |
1083 | if (bitmap->bits == NULL) | | 1083 | if (bitmap->bits == NULL) |
1084 | break; | | 1084 | break; |
1085 | | | 1085 | |
1086 | /* free bits if its defined */ | | 1086 | /* free bits if its defined */ |
1087 | KASSERT(bitmap->bits); | | 1087 | KASSERT(bitmap->bits); |
1088 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; | | 1088 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; |
1089 | udf_bitmap_free(bitmap, lb_num, num_lb); | | 1089 | udf_bitmap_free(bitmap, lb_num, num_lb); |
1090 | | | 1090 | |
1091 | /* adjust freecount */ | | 1091 | /* adjust freecount */ |
1092 | lvid = ump->logvol_integrity; | | 1092 | lvid = ump->logvol_integrity; |
1093 | freepos = &lvid->tables[0] + vpart_num; | | 1093 | freepos = &lvid->tables[0] + vpart_num; |
1094 | free_lbs = udf_rw32(*freepos); | | 1094 | free_lbs = udf_rw32(*freepos); |
1095 | *freepos = udf_rw32(free_lbs + num_lb); | | 1095 | *freepos = udf_rw32(free_lbs + num_lb); |
1096 | break; | | 1096 | break; |
1097 | case UDF_VTOP_TYPE_VIRT : | | 1097 | case UDF_VTOP_TYPE_VIRT : |
1098 | /* free this VAT entry */ | | 1098 | /* free this VAT entry */ |
1099 | KASSERT(num_lb == 1); | | 1099 | KASSERT(num_lb == 1); |
1100 | | | 1100 | |
1101 | lb_map = 0xffffffff; | | 1101 | lb_map = 0xffffffff; |
1102 | udf_rw32_lbmap = udf_rw32(lb_map); | | 1102 | udf_rw32_lbmap = udf_rw32(lb_map); |
1103 | error = udf_vat_write(ump->vat_node, | | 1103 | error = udf_vat_write(ump->vat_node, |
1104 | (uint8_t *) &udf_rw32_lbmap, 4, | | 1104 | (uint8_t *) &udf_rw32_lbmap, 4, |
1105 | ump->vat_offset + lb_num * 4); | | 1105 | ump->vat_offset + lb_num * 4); |
1106 | KASSERT(error == 0); | | 1106 | KASSERT(error == 0); |
1107 | ump->vat_last_free_lb = MIN(ump->vat_last_free_lb, lb_num); | | 1107 | ump->vat_last_free_lb = MIN(ump->vat_last_free_lb, lb_num); |
1108 | break; | | 1108 | break; |
1109 | case UDF_VTOP_TYPE_META : | | 1109 | case UDF_VTOP_TYPE_META : |
1110 | /* free space in the metadata bitmap */ | | 1110 | /* free space in the metadata bitmap */ |
1111 | bitmap = &ump->metadata_unalloc_bits; | | 1111 | bitmap = &ump->metadata_unalloc_bits; |
1112 | KASSERT(bitmap->bits); | | 1112 | KASSERT(bitmap->bits); |
1113 | | | 1113 | |
1114 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; | | 1114 | ump->lvclose |= UDF_WRITE_PART_BITMAPS; |
1115 | udf_bitmap_free(bitmap, lb_num, num_lb); | | 1115 | udf_bitmap_free(bitmap, lb_num, num_lb); |
1116 | | | 1116 | |
1117 | /* adjust freecount */ | | 1117 | /* adjust freecount */ |
1118 | lvid = ump->logvol_integrity; | | 1118 | lvid = ump->logvol_integrity; |
1119 | freepos = &lvid->tables[0] + vpart_num; | | 1119 | freepos = &lvid->tables[0] + vpart_num; |
1120 | free_lbs = udf_rw32(*freepos); | | 1120 | free_lbs = udf_rw32(*freepos); |
1121 | *freepos = udf_rw32(free_lbs + num_lb); | | 1121 | *freepos = udf_rw32(free_lbs + num_lb); |
1122 | break; | | 1122 | break; |
1123 | default: | | 1123 | default: |
1124 | printf("ALERT: udf_free_allocated_space : allocation %d " | | 1124 | printf("ALERT: udf_free_allocated_space : allocation %d " |
1125 | "not implemented yet!\n", ump->vtop_tp[vpart_num]); | | 1125 | "not implemented yet!\n", ump->vtop_tp[vpart_num]); |
1126 | break; | | 1126 | break; |
1127 | } | | 1127 | } |
1128 | | | 1128 | |
1129 | mutex_exit(&ump->allocate_mutex); | | 1129 | mutex_exit(&ump->allocate_mutex); |
1130 | } | | 1130 | } |
1131 | | | 1131 | |
1132 | /* --------------------------------------------------------------------- */ | | 1132 | /* --------------------------------------------------------------------- */ |
1133 | | | 1133 | |
1134 | int | | 1134 | int |
1135 | udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, | | 1135 | udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, |
1136 | uint32_t num_lb, uint16_t vpartnr, uint64_t *lmapping) | | 1136 | uint32_t num_lb, uint16_t vpartnr, uint64_t *lmapping) |
1137 | { | | 1137 | { |
1138 | /* TODO properly maintain uncomitted_lb per partition */ | | 1138 | /* TODO properly maintain uncomitted_lb per partition */ |
1139 | | | 1139 | |
1140 | /* reserve size for VAT allocated data */ | | 1140 | /* reserve size for VAT allocated data */ |
1141 | if (ump->vtop_alloc[vpartnr] == UDF_ALLOC_VAT) { | | 1141 | if (ump->vtop_alloc[vpartnr] == UDF_ALLOC_VAT) { |
1142 | mutex_enter(&ump->allocate_mutex); | | 1142 | mutex_enter(&ump->allocate_mutex); |
1143 | ump->uncomitted_lb += num_lb; | | 1143 | ump->uncomitted_lb += num_lb; |
1144 | mutex_exit(&ump->allocate_mutex); | | 1144 | mutex_exit(&ump->allocate_mutex); |
1145 | } | | 1145 | } |
1146 | | | 1146 | |
1147 | return udf_allocate_space(ump, udf_c_type, vpartnr, num_lb, lmapping); | | 1147 | return udf_allocate_space(ump, udf_c_type, vpartnr, num_lb, lmapping); |
1148 | } | | 1148 | } |
1149 | | | 1149 | |
1150 | /* --------------------------------------------------------------------- */ | | 1150 | /* --------------------------------------------------------------------- */ |
1151 | | | 1151 | |
1152 | /* | | 1152 | /* |
1153 | * Allocate a buf on disc for direct write out. The space doesn't have to be | | 1153 | * Allocate a buf on disc for direct write out. The space doesn't have to be |
1154 | * contiguous as the caller takes care of this. | | 1154 | * contiguous as the caller takes care of this. |
1155 | */ | | 1155 | */ |
1156 | | | 1156 | |
1157 | void | | 1157 | void |
1158 | udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, | | 1158 | udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, |
1159 | uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_nump) | | 1159 | uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_nump) |
1160 | { | | 1160 | { |
1161 | struct udf_node *udf_node = VTOI(buf->b_vp); | | 1161 | struct udf_node *udf_node = VTOI(buf->b_vp); |
1162 | int lb_size, blks, udf_c_type; | | 1162 | int lb_size, blks, udf_c_type; |
1163 | int vpart_num, num_lb; | | 1163 | int vpart_num, num_lb; |
1164 | int error, s; | | 1164 | int error, s; |
1165 | | | 1165 | |
1166 | /* | | 1166 | /* |
1167 | * for each sector in the buf, allocate a sector on disc and record | | 1167 | * for each sector in the buf, allocate a sector on disc and record |
1168 | * its position in the provided mapping array. | | 1168 | * its position in the provided mapping array. |
1169 | * | | 1169 | * |
1170 | * If its userdata or FIDs, record its location in its node. | | 1170 | * If its userdata or FIDs, record its location in its node. |
1171 | */ | | 1171 | */ |
1172 | | | 1172 | |
1173 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 1173 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
1174 | num_lb = (buf->b_bcount + lb_size -1) / lb_size; | | 1174 | num_lb = (buf->b_bcount + lb_size -1) / lb_size; |
1175 | blks = lb_size / DEV_BSIZE; | | 1175 | blks = lb_size / DEV_BSIZE; |
1176 | udf_c_type = buf->b_udf_c_type; | | 1176 | udf_c_type = buf->b_udf_c_type; |
1177 | | | 1177 | |
1178 | KASSERT(lb_size == ump->discinfo.sector_size); | | 1178 | KASSERT(lb_size == ump->discinfo.sector_size); |
1179 | | | 1179 | |
1180 | /* select partition to record the buffer on */ | | 1180 | /* select partition to record the buffer on */ |
1181 | vpart_num = ump->data_part; | | 1181 | vpart_num = ump->data_part; |
1182 | if (udf_c_type == UDF_C_NODE) | | 1182 | if (udf_c_type == UDF_C_NODE) |
1183 | vpart_num = ump->node_part; | | 1183 | vpart_num = ump->node_part; |
1184 | if (udf_c_type == UDF_C_FIDS) | | 1184 | if (udf_c_type == UDF_C_FIDS) |
1185 | vpart_num = ump->fids_part; | | 1185 | vpart_num = ump->fids_part; |
1186 | *vpart_nump = vpart_num; | | 1186 | *vpart_nump = vpart_num; |
1187 | | | 1187 | |
1188 | if (udf_c_type == UDF_C_NODE) { | | 1188 | if (udf_c_type == UDF_C_NODE) { |
1189 | /* if not VAT, its allready allocated */ | | 1189 | /* if not VAT, its allready allocated */ |
1190 | if (ump->vtop_alloc[ump->node_part] != UDF_ALLOC_VAT) | | 1190 | if (ump->vtop_alloc[ump->node_part] != UDF_ALLOC_VAT) |
1191 | return; | | 1191 | return; |
1192 | | | 1192 | |
1193 | /* allocate on its backing sequential partition */ | | 1193 | /* allocate on its backing sequential partition */ |
1194 | vpart_num = ump->data_part; | | 1194 | vpart_num = ump->data_part; |
1195 | } | | 1195 | } |
1196 | | | 1196 | |
1197 | /* do allocation on the selected partition */ | | 1197 | /* do allocation on the selected partition */ |
1198 | error = udf_allocate_space(ump, udf_c_type, | | 1198 | error = udf_allocate_space(ump, udf_c_type, |
1199 | vpart_num, num_lb, lmapping); | | 1199 | vpart_num, num_lb, lmapping); |
1200 | if (error) { | | 1200 | if (error) { |
1201 | /* ARGH! we've not done our accounting right! */ | | 1201 | /* ARGH! we've not done our accounting right! */ |
1202 | panic("UDF disc allocation accounting gone wrong"); | | 1202 | panic("UDF disc allocation accounting gone wrong"); |
1203 | } | | 1203 | } |
1204 | | | 1204 | |
1205 | /* commit our sector count */ | | 1205 | /* commit our sector count */ |
1206 | mutex_enter(&ump->allocate_mutex); | | 1206 | mutex_enter(&ump->allocate_mutex); |
1207 | if (num_lb > ump->uncomitted_lb) { | | 1207 | if (num_lb > ump->uncomitted_lb) { |
1208 | ump->uncomitted_lb = 0; | | 1208 | ump->uncomitted_lb = 0; |
1209 | } else { | | 1209 | } else { |
1210 | ump->uncomitted_lb -= num_lb; | | 1210 | ump->uncomitted_lb -= num_lb; |
1211 | } | | 1211 | } |
1212 | mutex_exit(&ump->allocate_mutex); | | 1212 | mutex_exit(&ump->allocate_mutex); |
1213 | | | 1213 | |
1214 | /* If its userdata or FIDs, record its allocation in its node. */ | | 1214 | /* If its userdata or FIDs, record its allocation in its node. */ |
1215 | if ((udf_c_type == UDF_C_USERDATA) || | | 1215 | if ((udf_c_type == UDF_C_USERDATA) || |
1216 | (udf_c_type == UDF_C_FIDS) || | | 1216 | (udf_c_type == UDF_C_FIDS) || |
1217 | (udf_c_type == UDF_C_METADATA_SBM)) | | 1217 | (udf_c_type == UDF_C_METADATA_SBM)) |
1218 | { | | 1218 | { |
1219 | udf_record_allocation_in_node(ump, buf, vpart_num, lmapping, | | 1219 | udf_record_allocation_in_node(ump, buf, vpart_num, lmapping, |
1220 | node_ad_cpy); | | 1220 | node_ad_cpy); |
1221 | /* decrement our outstanding bufs counter */ | | 1221 | /* decrement our outstanding bufs counter */ |
1222 | s = splbio(); | | 1222 | s = splbio(); |
1223 | udf_node->outstanding_bufs--; | | 1223 | udf_node->outstanding_bufs--; |
1224 | splx(s); | | 1224 | splx(s); |
1225 | } | | 1225 | } |
1226 | } | | 1226 | } |
1227 | | | 1227 | |
1228 | /* --------------------------------------------------------------------- */ | | 1228 | /* --------------------------------------------------------------------- */ |
1229 | | | 1229 | |
1230 | /* | | 1230 | /* |
1231 | * Try to merge a1 with the new piece a2. udf_ads_merge returns error when not | | 1231 | * Try to merge a1 with the new piece a2. udf_ads_merge returns error when not |
1232 | * possible (anymore); a2 returns the rest piece. | | 1232 | * possible (anymore); a2 returns the rest piece. |
1233 | */ | | 1233 | */ |
1234 | | | 1234 | |
1235 | static int | | 1235 | static int |
1236 | udf_ads_merge(uint32_t lb_size, struct long_ad *a1, struct long_ad *a2) | | 1236 | udf_ads_merge(uint32_t lb_size, struct long_ad *a1, struct long_ad *a2) |
1237 | { | | 1237 | { |
1238 | uint32_t max_len, merge_len; | | 1238 | uint32_t max_len, merge_len; |
1239 | uint32_t a1_len, a2_len; | | 1239 | uint32_t a1_len, a2_len; |
1240 | uint32_t a1_flags, a2_flags; | | 1240 | uint32_t a1_flags, a2_flags; |
1241 | uint32_t a1_lbnum, a2_lbnum; | | 1241 | uint32_t a1_lbnum, a2_lbnum; |
1242 | uint16_t a1_part, a2_part; | | 1242 | uint16_t a1_part, a2_part; |
1243 | | | 1243 | |
1244 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); | | 1244 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); |
1245 | | | 1245 | |
1246 | a1_flags = UDF_EXT_FLAGS(udf_rw32(a1->len)); | | 1246 | a1_flags = UDF_EXT_FLAGS(udf_rw32(a1->len)); |
1247 | a1_len = UDF_EXT_LEN(udf_rw32(a1->len)); | | 1247 | a1_len = UDF_EXT_LEN(udf_rw32(a1->len)); |
1248 | a1_lbnum = udf_rw32(a1->loc.lb_num); | | 1248 | a1_lbnum = udf_rw32(a1->loc.lb_num); |
1249 | a1_part = udf_rw16(a1->loc.part_num); | | 1249 | a1_part = udf_rw16(a1->loc.part_num); |
1250 | | | 1250 | |
1251 | a2_flags = UDF_EXT_FLAGS(udf_rw32(a2->len)); | | 1251 | a2_flags = UDF_EXT_FLAGS(udf_rw32(a2->len)); |
1252 | a2_len = UDF_EXT_LEN(udf_rw32(a2->len)); | | 1252 | a2_len = UDF_EXT_LEN(udf_rw32(a2->len)); |
1253 | a2_lbnum = udf_rw32(a2->loc.lb_num); | | 1253 | a2_lbnum = udf_rw32(a2->loc.lb_num); |
1254 | a2_part = udf_rw16(a2->loc.part_num); | | 1254 | a2_part = udf_rw16(a2->loc.part_num); |
1255 | | | 1255 | |
1256 | /* defines same space */ | | 1256 | /* defines same space */ |
1257 | if (a1_flags != a2_flags) | | 1257 | if (a1_flags != a2_flags) |
1258 | return 1; | | 1258 | return 1; |
1259 | | | 1259 | |
1260 | if (a1_flags != UDF_EXT_FREE) { | | 1260 | if (a1_flags != UDF_EXT_FREE) { |
1261 | /* the same partition */ | | 1261 | /* the same partition */ |
1262 | if (a1_part != a2_part) | | 1262 | if (a1_part != a2_part) |
1263 | return 1; | | 1263 | return 1; |
1264 | | | 1264 | |
1265 | /* a2 is successor of a1 */ | | 1265 | /* a2 is successor of a1 */ |
1266 | if (a1_lbnum * lb_size + a1_len != a2_lbnum * lb_size) | | 1266 | if (a1_lbnum * lb_size + a1_len != a2_lbnum * lb_size) |
1267 | return 1; | | 1267 | return 1; |
1268 | } | | 1268 | } |
1269 | | | 1269 | |
1270 | /* merge as most from a2 if possible */ | | 1270 | /* merge as most from a2 if possible */ |
1271 | merge_len = MIN(a2_len, max_len - a1_len); | | 1271 | merge_len = MIN(a2_len, max_len - a1_len); |
1272 | a1_len += merge_len; | | 1272 | a1_len += merge_len; |
1273 | a2_len -= merge_len; | | 1273 | a2_len -= merge_len; |
1274 | a2_lbnum += merge_len/lb_size; | | 1274 | a2_lbnum += merge_len/lb_size; |
1275 | | | 1275 | |
1276 | a1->len = udf_rw32(a1_len | a1_flags); | | 1276 | a1->len = udf_rw32(a1_len | a1_flags); |
1277 | a2->len = udf_rw32(a2_len | a2_flags); | | 1277 | a2->len = udf_rw32(a2_len | a2_flags); |
1278 | a2->loc.lb_num = udf_rw32(a2_lbnum); | | 1278 | a2->loc.lb_num = udf_rw32(a2_lbnum); |
1279 | | | 1279 | |
1280 | if (a2_len > 0) | | 1280 | if (a2_len > 0) |
1281 | return 1; | | 1281 | return 1; |
1282 | | | 1282 | |
1283 | /* there is space over to merge */ | | 1283 | /* there is space over to merge */ |
1284 | return 0; | | 1284 | return 0; |
1285 | } | | 1285 | } |
1286 | | | 1286 | |
1287 | /* --------------------------------------------------------------------- */ | | 1287 | /* --------------------------------------------------------------------- */ |
1288 | | | 1288 | |
1289 | static void | | 1289 | static void |
1290 | udf_wipe_adslots(struct udf_node *udf_node) | | 1290 | udf_wipe_adslots(struct udf_node *udf_node) |
1291 | { | | 1291 | { |
1292 | struct file_entry *fe; | | 1292 | struct file_entry *fe; |
1293 | struct extfile_entry *efe; | | 1293 | struct extfile_entry *efe; |
1294 | struct alloc_ext_entry *ext; | | 1294 | struct alloc_ext_entry *ext; |
1295 | uint64_t inflen, objsize; | | 1295 | uint64_t inflen, objsize; |
1296 | uint32_t lb_size, dscr_size, l_ea, l_ad, max_l_ad, crclen; | | 1296 | uint32_t lb_size, dscr_size, l_ea, l_ad, max_l_ad, crclen; |
1297 | uint8_t *data_pos; | | 1297 | uint8_t *data_pos; |
1298 | int extnr; | | 1298 | int extnr; |
1299 | | | 1299 | |
1300 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 1300 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
1301 | | | 1301 | |
1302 | fe = udf_node->fe; | | 1302 | fe = udf_node->fe; |
1303 | efe = udf_node->efe; | | 1303 | efe = udf_node->efe; |
1304 | if (fe) { | | 1304 | if (fe) { |
1305 | inflen = udf_rw64(fe->inf_len); | | 1305 | inflen = udf_rw64(fe->inf_len); |
1306 | objsize = inflen; | | 1306 | objsize = inflen; |
1307 | dscr_size = sizeof(struct file_entry) -1; | | 1307 | dscr_size = sizeof(struct file_entry) -1; |
1308 | l_ea = udf_rw32(fe->l_ea); | | 1308 | l_ea = udf_rw32(fe->l_ea); |
1309 | l_ad = udf_rw32(fe->l_ad); | | 1309 | l_ad = udf_rw32(fe->l_ad); |
1310 | data_pos = (uint8_t *) fe + dscr_size + l_ea; | | 1310 | data_pos = (uint8_t *) fe + dscr_size + l_ea; |
1311 | } else { | | 1311 | } else { |
1312 | inflen = udf_rw64(efe->inf_len); | | 1312 | inflen = udf_rw64(efe->inf_len); |
1313 | objsize = udf_rw64(efe->obj_size); | | 1313 | objsize = udf_rw64(efe->obj_size); |
1314 | dscr_size = sizeof(struct extfile_entry) -1; | | 1314 | dscr_size = sizeof(struct extfile_entry) -1; |
1315 | l_ea = udf_rw32(efe->l_ea); | | 1315 | l_ea = udf_rw32(efe->l_ea); |
1316 | l_ad = udf_rw32(efe->l_ad); | | 1316 | l_ad = udf_rw32(efe->l_ad); |
1317 | data_pos = (uint8_t *) efe + dscr_size + l_ea; | | 1317 | data_pos = (uint8_t *) efe + dscr_size + l_ea; |
1318 | } | | 1318 | } |
1319 | max_l_ad = lb_size - dscr_size - l_ea; | | 1319 | max_l_ad = lb_size - dscr_size - l_ea; |
1320 | | | 1320 | |
1321 | /* wipe fe/efe */ | | 1321 | /* wipe fe/efe */ |
1322 | memset(data_pos, 0, max_l_ad); | | 1322 | memset(data_pos, 0, max_l_ad); |
1323 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea; | | 1323 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea; |
1324 | if (fe) { | | 1324 | if (fe) { |
1325 | fe->l_ad = udf_rw32(0); | | 1325 | fe->l_ad = udf_rw32(0); |
1326 | fe->logblks_rec = udf_rw64(0); | | 1326 | fe->logblks_rec = udf_rw64(0); |
1327 | fe->tag.desc_crc_len = udf_rw16(crclen); | | 1327 | fe->tag.desc_crc_len = udf_rw16(crclen); |
1328 | } else { | | 1328 | } else { |
1329 | efe->l_ad = udf_rw32(0); | | 1329 | efe->l_ad = udf_rw32(0); |
1330 | efe->logblks_rec = udf_rw64(0); | | 1330 | efe->logblks_rec = udf_rw64(0); |
1331 | efe->tag.desc_crc_len = udf_rw16(crclen); | | 1331 | efe->tag.desc_crc_len = udf_rw16(crclen); |
1332 | } | | 1332 | } |
1333 | | | 1333 | |
1334 | /* wipe all allocation extent entries */ | | 1334 | /* wipe all allocation extent entries */ |
1335 | for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { | | 1335 | for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { |
1336 | ext = udf_node->ext[extnr]; | | 1336 | ext = udf_node->ext[extnr]; |
1337 | dscr_size = sizeof(struct alloc_ext_entry) -1; | | 1337 | dscr_size = sizeof(struct alloc_ext_entry) -1; |
1338 | data_pos = (uint8_t *) ext->data; | | 1338 | data_pos = (uint8_t *) ext->data; |
1339 | max_l_ad = lb_size - dscr_size; | | 1339 | max_l_ad = lb_size - dscr_size; |
1340 | memset(data_pos, 0, max_l_ad); | | 1340 | memset(data_pos, 0, max_l_ad); |
1341 | ext->l_ad = udf_rw32(0); | | 1341 | ext->l_ad = udf_rw32(0); |
1342 | | | 1342 | |
1343 | crclen = dscr_size - UDF_DESC_TAG_LENGTH; | | 1343 | crclen = dscr_size - UDF_DESC_TAG_LENGTH; |
1344 | ext->tag.desc_crc_len = udf_rw16(crclen); | | 1344 | ext->tag.desc_crc_len = udf_rw16(crclen); |
1345 | } | | 1345 | } |
1346 | udf_node->i_flags |= IN_NODE_REBUILD; | | 1346 | udf_node->i_flags |= IN_NODE_REBUILD; |
1347 | } | | 1347 | } |
1348 | | | 1348 | |
1349 | /* --------------------------------------------------------------------- */ | | 1349 | /* --------------------------------------------------------------------- */ |
1350 | | | 1350 | |
1351 | void | | 1351 | void |
1352 | udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb, | | 1352 | udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb, |
1353 | int *eof) { | | 1353 | int *eof) { |
1354 | struct file_entry *fe; | | 1354 | struct file_entry *fe; |
1355 | struct extfile_entry *efe; | | 1355 | struct extfile_entry *efe; |
1356 | struct alloc_ext_entry *ext; | | 1356 | struct alloc_ext_entry *ext; |
1357 | struct icb_tag *icbtag; | | 1357 | struct icb_tag *icbtag; |
1358 | struct short_ad *short_ad; | | 1358 | struct short_ad *short_ad; |
1359 | struct long_ad *long_ad, l_icb; | | 1359 | struct long_ad *long_ad, l_icb; |
1360 | uint32_t offset; | | 1360 | uint32_t offset; |
1361 | uint32_t lb_size, dscr_size, l_ea, l_ad, flags; | | 1361 | uint32_t lb_size, dscr_size, l_ea, l_ad, flags; |
1362 | uint8_t *data_pos; | | 1362 | uint8_t *data_pos; |
1363 | int icbflags, addr_type, adlen, extnr; | | 1363 | int icbflags, addr_type, adlen, extnr; |
1364 | | | 1364 | |
1365 | /* determine what descriptor we are in */ | | 1365 | /* determine what descriptor we are in */ |
1366 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 1366 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
1367 | | | 1367 | |
1368 | fe = udf_node->fe; | | 1368 | fe = udf_node->fe; |
1369 | efe = udf_node->efe; | | 1369 | efe = udf_node->efe; |
1370 | if (fe) { | | 1370 | if (fe) { |
1371 | icbtag = &fe->icbtag; | | 1371 | icbtag = &fe->icbtag; |
1372 | dscr_size = sizeof(struct file_entry) -1; | | 1372 | dscr_size = sizeof(struct file_entry) -1; |
1373 | l_ea = udf_rw32(fe->l_ea); | | 1373 | l_ea = udf_rw32(fe->l_ea); |
1374 | l_ad = udf_rw32(fe->l_ad); | | 1374 | l_ad = udf_rw32(fe->l_ad); |
1375 | data_pos = (uint8_t *) fe + dscr_size + l_ea; | | 1375 | data_pos = (uint8_t *) fe + dscr_size + l_ea; |
1376 | } else { | | 1376 | } else { |
1377 | icbtag = &efe->icbtag; | | 1377 | icbtag = &efe->icbtag; |
1378 | dscr_size = sizeof(struct extfile_entry) -1; | | 1378 | dscr_size = sizeof(struct extfile_entry) -1; |
1379 | l_ea = udf_rw32(efe->l_ea); | | 1379 | l_ea = udf_rw32(efe->l_ea); |
1380 | l_ad = udf_rw32(efe->l_ad); | | 1380 | l_ad = udf_rw32(efe->l_ad); |
1381 | data_pos = (uint8_t *) efe + dscr_size + l_ea; | | 1381 | data_pos = (uint8_t *) efe + dscr_size + l_ea; |
1382 | } | | 1382 | } |
1383 | | | 1383 | |
1384 | icbflags = udf_rw16(icbtag->flags); | | 1384 | icbflags = udf_rw16(icbtag->flags); |
1385 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 1385 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
1386 | | | 1386 | |
1387 | /* just in case we're called on an intern, its EOF */ | | 1387 | /* just in case we're called on an intern, its EOF */ |
1388 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 1388 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
1389 | memset(icb, 0, sizeof(struct long_ad)); | | 1389 | memset(icb, 0, sizeof(struct long_ad)); |
1390 | *eof = 1; | | 1390 | *eof = 1; |
1391 | return; | | 1391 | return; |
1392 | } | | 1392 | } |
1393 | | | 1393 | |
1394 | adlen = 0; | | 1394 | adlen = 0; |
1395 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1395 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1396 | adlen = sizeof(struct short_ad); | | 1396 | adlen = sizeof(struct short_ad); |
1397 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1397 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1398 | adlen = sizeof(struct long_ad); | | 1398 | adlen = sizeof(struct long_ad); |
1399 | } | | 1399 | } |
1400 | | | 1400 | |
1401 | /* if offset too big, we go to the allocation extensions */ | | 1401 | /* if offset too big, we go to the allocation extensions */ |
1402 | offset = slot * adlen; | | 1402 | offset = slot * adlen; |
1403 | extnr = -1; | | 1403 | extnr = -1; |
1404 | while (offset >= l_ad) { | | 1404 | while (offset >= l_ad) { |
1405 | /* check if our last entry is a redirect */ | | 1405 | /* check if our last entry is a redirect */ |
1406 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1406 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1407 | short_ad = (struct short_ad *) (data_pos + l_ad-adlen); | | 1407 | short_ad = (struct short_ad *) (data_pos + l_ad-adlen); |
1408 | l_icb.len = short_ad->len; | | 1408 | l_icb.len = short_ad->len; |
1409 | l_icb.loc.part_num = udf_node->loc.loc.part_num; | | 1409 | l_icb.loc.part_num = udf_node->loc.loc.part_num; |
1410 | l_icb.loc.lb_num = short_ad->lb_num; | | 1410 | l_icb.loc.lb_num = short_ad->lb_num; |
1411 | } else { | | 1411 | } else { |
1412 | KASSERT(addr_type == UDF_ICB_LONG_ALLOC); | | 1412 | KASSERT(addr_type == UDF_ICB_LONG_ALLOC); |
1413 | long_ad = (struct long_ad *) (data_pos + l_ad-adlen); | | 1413 | long_ad = (struct long_ad *) (data_pos + l_ad-adlen); |
1414 | l_icb = *long_ad; | | 1414 | l_icb = *long_ad; |
1415 | } | | 1415 | } |
1416 | flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); | | 1416 | flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); |
1417 | if (flags != UDF_EXT_REDIRECT) { | | 1417 | if (flags != UDF_EXT_REDIRECT) { |
1418 | l_ad = 0; /* force EOF */ | | 1418 | l_ad = 0; /* force EOF */ |
1419 | break; | | 1419 | break; |
1420 | } | | 1420 | } |
1421 | | | 1421 | |
1422 | /* advance to next extent */ | | 1422 | /* advance to next extent */ |
1423 | extnr++; | | 1423 | extnr++; |
1424 | if (extnr >= udf_node->num_extensions) { | | 1424 | if (extnr >= udf_node->num_extensions) { |
1425 | l_ad = 0; /* force EOF */ | | 1425 | l_ad = 0; /* force EOF */ |
1426 | break; | | 1426 | break; |
1427 | } | | 1427 | } |
1428 | offset = offset - l_ad; | | 1428 | offset = offset - l_ad; |
1429 | ext = udf_node->ext[extnr]; | | 1429 | ext = udf_node->ext[extnr]; |
1430 | dscr_size = sizeof(struct alloc_ext_entry) -1; | | 1430 | dscr_size = sizeof(struct alloc_ext_entry) -1; |
1431 | l_ad = udf_rw32(ext->l_ad); | | 1431 | l_ad = udf_rw32(ext->l_ad); |
1432 | data_pos = (uint8_t *) ext + dscr_size; | | 1432 | data_pos = (uint8_t *) ext + dscr_size; |
1433 | } | | 1433 | } |
1434 | | | 1434 | |
1435 | /* XXX l_ad == 0 should be enough to check */ | | 1435 | /* XXX l_ad == 0 should be enough to check */ |
1436 | *eof = (offset >= l_ad) || (l_ad == 0); | | 1436 | *eof = (offset >= l_ad) || (l_ad == 0); |
1437 | if (*eof) { | | 1437 | if (*eof) { |
1438 | DPRINTF(PARANOIDADWLK, ("returning EOF, extnr %d, offset %d, " | | 1438 | DPRINTF(PARANOIDADWLK, ("returning EOF, extnr %d, offset %d, " |
1439 | "l_ad %d\n", extnr, offset, l_ad)); | | 1439 | "l_ad %d\n", extnr, offset, l_ad)); |
1440 | memset(icb, 0, sizeof(struct long_ad)); | | 1440 | memset(icb, 0, sizeof(struct long_ad)); |
1441 | return; | | 1441 | return; |
1442 | } | | 1442 | } |
1443 | | | 1443 | |
1444 | /* get the element */ | | 1444 | /* get the element */ |
1445 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1445 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1446 | short_ad = (struct short_ad *) (data_pos + offset); | | 1446 | short_ad = (struct short_ad *) (data_pos + offset); |
1447 | icb->len = short_ad->len; | | 1447 | icb->len = short_ad->len; |
1448 | icb->loc.part_num = udf_node->loc.loc.part_num; | | 1448 | icb->loc.part_num = udf_node->loc.loc.part_num; |
1449 | icb->loc.lb_num = short_ad->lb_num; | | 1449 | icb->loc.lb_num = short_ad->lb_num; |
1450 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1450 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1451 | long_ad = (struct long_ad *) (data_pos + offset); | | 1451 | long_ad = (struct long_ad *) (data_pos + offset); |
1452 | *icb = *long_ad; | | 1452 | *icb = *long_ad; |
1453 | } | | 1453 | } |
1454 | DPRINTF(PARANOIDADWLK, ("returning element : v %d, lb %d, len %d, " | | 1454 | DPRINTF(PARANOIDADWLK, ("returning element : v %d, lb %d, len %d, " |
1455 | "flags %d\n", icb->loc.part_num, icb->loc.lb_num, | | 1455 | "flags %d\n", icb->loc.part_num, icb->loc.lb_num, |
1456 | UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); | | 1456 | UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); |
1457 | } | | 1457 | } |
1458 | | | 1458 | |
1459 | /* --------------------------------------------------------------------- */ | | 1459 | /* --------------------------------------------------------------------- */ |
1460 | | | 1460 | |
1461 | int | | 1461 | int |
1462 | udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { | | 1462 | udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { |
1463 | struct udf_mount *ump = udf_node->ump; | | 1463 | struct udf_mount *ump = udf_node->ump; |
1464 | union dscrptr *dscr, *extdscr; | | 1464 | union dscrptr *dscr, *extdscr; |
1465 | struct file_entry *fe; | | 1465 | struct file_entry *fe; |
1466 | struct extfile_entry *efe; | | 1466 | struct extfile_entry *efe; |
1467 | struct alloc_ext_entry *ext; | | 1467 | struct alloc_ext_entry *ext; |
1468 | struct icb_tag *icbtag; | | 1468 | struct icb_tag *icbtag; |
1469 | struct short_ad *short_ad; | | 1469 | struct short_ad *short_ad; |
1470 | struct long_ad *long_ad, o_icb, l_icb; | | 1470 | struct long_ad *long_ad, o_icb, l_icb; |
1471 | uint64_t logblks_rec, *logblks_rec_p; | | 1471 | uint64_t logblks_rec, *logblks_rec_p; |
1472 | uint64_t lmapping; | | 1472 | uint64_t lmapping; |
1473 | uint32_t offset, rest, len, lb_num; | | 1473 | uint32_t offset, rest, len, lb_num; |
1474 | uint32_t lb_size, dscr_size, l_ea, l_ad, *l_ad_p, max_l_ad, crclen; | | 1474 | uint32_t lb_size, dscr_size, l_ea, l_ad, *l_ad_p, max_l_ad, crclen; |
1475 | uint32_t flags; | | 1475 | uint32_t flags; |
1476 | uint16_t vpart_num; | | 1476 | uint16_t vpart_num; |
1477 | uint8_t *data_pos; | | 1477 | uint8_t *data_pos; |
1478 | int icbflags, addr_type, adlen, extnr; | | 1478 | int icbflags, addr_type, adlen, extnr; |
1479 | int error; | | 1479 | int error; |
1480 | | | 1480 | |
1481 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 1481 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
1482 | vpart_num = udf_rw16(udf_node->loc.loc.part_num); | | 1482 | vpart_num = udf_rw16(udf_node->loc.loc.part_num); |
1483 | | | 1483 | |
1484 | /* determine what descriptor we are in */ | | 1484 | /* determine what descriptor we are in */ |
1485 | fe = udf_node->fe; | | 1485 | fe = udf_node->fe; |
1486 | efe = udf_node->efe; | | 1486 | efe = udf_node->efe; |
1487 | if (fe) { | | 1487 | if (fe) { |
1488 | icbtag = &fe->icbtag; | | 1488 | icbtag = &fe->icbtag; |
1489 | dscr = (union dscrptr *) fe; | | 1489 | dscr = (union dscrptr *) fe; |
1490 | dscr_size = sizeof(struct file_entry) -1; | | 1490 | dscr_size = sizeof(struct file_entry) -1; |
1491 | | | 1491 | |
1492 | l_ea = udf_rw32(fe->l_ea); | | 1492 | l_ea = udf_rw32(fe->l_ea); |
1493 | l_ad_p = &fe->l_ad; | | 1493 | l_ad_p = &fe->l_ad; |
1494 | logblks_rec_p = &fe->logblks_rec; | | 1494 | logblks_rec_p = &fe->logblks_rec; |
1495 | } else { | | 1495 | } else { |
1496 | icbtag = &efe->icbtag; | | 1496 | icbtag = &efe->icbtag; |
1497 | dscr = (union dscrptr *) efe; | | 1497 | dscr = (union dscrptr *) efe; |
1498 | dscr_size = sizeof(struct extfile_entry) -1; | | 1498 | dscr_size = sizeof(struct extfile_entry) -1; |
1499 | | | 1499 | |
1500 | l_ea = udf_rw32(efe->l_ea); | | 1500 | l_ea = udf_rw32(efe->l_ea); |
1501 | l_ad_p = &efe->l_ad; | | 1501 | l_ad_p = &efe->l_ad; |
1502 | logblks_rec_p = &efe->logblks_rec; | | 1502 | logblks_rec_p = &efe->logblks_rec; |
1503 | } | | 1503 | } |
1504 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; | | 1504 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; |
1505 | max_l_ad = lb_size - dscr_size - l_ea; | | 1505 | max_l_ad = lb_size - dscr_size - l_ea; |
1506 | | | 1506 | |
1507 | icbflags = udf_rw16(icbtag->flags); | | 1507 | icbflags = udf_rw16(icbtag->flags); |
1508 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 1508 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
1509 | | | 1509 | |
1510 | /* just in case we're called on an intern, its EOF */ | | 1510 | /* just in case we're called on an intern, its EOF */ |
1511 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 1511 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
1512 | panic("udf_append_adslot on UDF_ICB_INTERN_ALLOC\n"); | | 1512 | panic("udf_append_adslot on UDF_ICB_INTERN_ALLOC\n"); |
1513 | } | | 1513 | } |
1514 | | | 1514 | |
1515 | adlen = 0; | | 1515 | adlen = 0; |
1516 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1516 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1517 | adlen = sizeof(struct short_ad); | | 1517 | adlen = sizeof(struct short_ad); |
1518 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1518 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1519 | adlen = sizeof(struct long_ad); | | 1519 | adlen = sizeof(struct long_ad); |
1520 | } | | 1520 | } |
1521 | | | 1521 | |
1522 | /* clean up given long_ad since it can be a synthesized one */ | | 1522 | /* clean up given long_ad since it can be a synthesized one */ |
1523 | flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); | | 1523 | flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); |
1524 | if (flags == UDF_EXT_FREE) { | | 1524 | if (flags == UDF_EXT_FREE) { |
1525 | icb->loc.part_num = udf_rw16(0); | | 1525 | icb->loc.part_num = udf_rw16(0); |
1526 | icb->loc.lb_num = udf_rw32(0); | | 1526 | icb->loc.lb_num = udf_rw32(0); |
1527 | } | | 1527 | } |
1528 | | | 1528 | |
1529 | /* if offset too big, we go to the allocation extensions */ | | 1529 | /* if offset too big, we go to the allocation extensions */ |
1530 | l_ad = udf_rw32(*l_ad_p); | | 1530 | l_ad = udf_rw32(*l_ad_p); |
1531 | offset = (*slot) * adlen; | | 1531 | offset = (*slot) * adlen; |
1532 | extnr = -1; | | 1532 | extnr = -1; |
1533 | while (offset >= l_ad) { | | 1533 | while (offset >= l_ad) { |
1534 | /* check if our last entry is a redirect */ | | 1534 | /* check if our last entry is a redirect */ |
1535 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1535 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1536 | short_ad = (struct short_ad *) (data_pos + l_ad-adlen); | | 1536 | short_ad = (struct short_ad *) (data_pos + l_ad-adlen); |
1537 | l_icb.len = short_ad->len; | | 1537 | l_icb.len = short_ad->len; |
1538 | l_icb.loc.part_num = udf_node->loc.loc.part_num; | | 1538 | l_icb.loc.part_num = udf_node->loc.loc.part_num; |
1539 | l_icb.loc.lb_num = short_ad->lb_num; | | 1539 | l_icb.loc.lb_num = short_ad->lb_num; |
1540 | } else { | | 1540 | } else { |
1541 | KASSERT(addr_type == UDF_ICB_LONG_ALLOC); | | 1541 | KASSERT(addr_type == UDF_ICB_LONG_ALLOC); |
1542 | long_ad = (struct long_ad *) (data_pos + l_ad-adlen); | | 1542 | long_ad = (struct long_ad *) (data_pos + l_ad-adlen); |
1543 | l_icb = *long_ad; | | 1543 | l_icb = *long_ad; |
1544 | } | | 1544 | } |
1545 | flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); | | 1545 | flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); |
1546 | if (flags != UDF_EXT_REDIRECT) { | | 1546 | if (flags != UDF_EXT_REDIRECT) { |
1547 | /* only one past the last one is adressable */ | | 1547 | /* only one past the last one is adressable */ |
1548 | break; | | 1548 | break; |
1549 | } | | 1549 | } |
1550 | | | 1550 | |
1551 | /* advance to next extent */ | | 1551 | /* advance to next extent */ |
1552 | extnr++; | | 1552 | extnr++; |
1553 | KASSERT(extnr < udf_node->num_extensions); | | 1553 | KASSERT(extnr < udf_node->num_extensions); |
1554 | offset = offset - l_ad; | | 1554 | offset = offset - l_ad; |
1555 | | | 1555 | |
1556 | ext = udf_node->ext[extnr]; | | 1556 | ext = udf_node->ext[extnr]; |
1557 | dscr = (union dscrptr *) ext; | | 1557 | dscr = (union dscrptr *) ext; |
1558 | dscr_size = sizeof(struct alloc_ext_entry) -1; | | 1558 | dscr_size = sizeof(struct alloc_ext_entry) -1; |
1559 | max_l_ad = lb_size - dscr_size; | | 1559 | max_l_ad = lb_size - dscr_size; |
1560 | l_ad_p = &ext->l_ad; | | 1560 | l_ad_p = &ext->l_ad; |
1561 | l_ad = udf_rw32(*l_ad_p); | | 1561 | l_ad = udf_rw32(*l_ad_p); |
1562 | data_pos = (uint8_t *) ext + dscr_size; | | 1562 | data_pos = (uint8_t *) ext + dscr_size; |
1563 | } | | 1563 | } |
1564 | DPRINTF(PARANOIDADWLK, ("append, ext %d, offset %d, l_ad %d\n", | | 1564 | DPRINTF(PARANOIDADWLK, ("append, ext %d, offset %d, l_ad %d\n", |
1565 | extnr, offset, udf_rw32(*l_ad_p))); | | 1565 | extnr, offset, udf_rw32(*l_ad_p))); |
1566 | KASSERT(l_ad == udf_rw32(*l_ad_p)); | | 1566 | KASSERT(l_ad == udf_rw32(*l_ad_p)); |
1567 | | | 1567 | |
1568 | /* offset is offset within the current (E)FE/AED */ | | 1568 | /* offset is offset within the current (E)FE/AED */ |
1569 | l_ad = udf_rw32(*l_ad_p); | | 1569 | l_ad = udf_rw32(*l_ad_p); |
1570 | crclen = udf_rw16(dscr->tag.desc_crc_len); | | 1570 | crclen = udf_rw16(dscr->tag.desc_crc_len); |
1571 | logblks_rec = udf_rw64(*logblks_rec_p); | | 1571 | logblks_rec = udf_rw64(*logblks_rec_p); |
1572 | | | 1572 | |
1573 | /* overwriting old piece? */ | | 1573 | /* overwriting old piece? */ |
1574 | if (offset < l_ad) { | | 1574 | if (offset < l_ad) { |
1575 | /* overwrite entry; compensate for the old element */ | | 1575 | /* overwrite entry; compensate for the old element */ |
1576 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1576 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1577 | short_ad = (struct short_ad *) (data_pos + offset); | | 1577 | short_ad = (struct short_ad *) (data_pos + offset); |
1578 | o_icb.len = short_ad->len; | | 1578 | o_icb.len = short_ad->len; |
1579 | o_icb.loc.part_num = udf_rw16(0); /* ignore */ | | 1579 | o_icb.loc.part_num = udf_rw16(0); /* ignore */ |
1580 | o_icb.loc.lb_num = short_ad->lb_num; | | 1580 | o_icb.loc.lb_num = short_ad->lb_num; |
1581 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1581 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1582 | long_ad = (struct long_ad *) (data_pos + offset); | | 1582 | long_ad = (struct long_ad *) (data_pos + offset); |
1583 | o_icb = *long_ad; | | 1583 | o_icb = *long_ad; |
1584 | } else { | | 1584 | } else { |
1585 | panic("Invalid address type in udf_append_adslot\n"); | | 1585 | panic("Invalid address type in udf_append_adslot\n"); |
1586 | } | | 1586 | } |
1587 | | | 1587 | |
1588 | len = udf_rw32(o_icb.len); | | 1588 | len = udf_rw32(o_icb.len); |
1589 | if (UDF_EXT_FLAGS(len) == UDF_EXT_ALLOCATED) { | | 1589 | if (UDF_EXT_FLAGS(len) == UDF_EXT_ALLOCATED) { |
1590 | /* adjust counts */ | | 1590 | /* adjust counts */ |
1591 | len = UDF_EXT_LEN(len); | | 1591 | len = UDF_EXT_LEN(len); |
1592 | logblks_rec -= (len + lb_size -1) / lb_size; | | 1592 | logblks_rec -= (len + lb_size -1) / lb_size; |
1593 | } | | 1593 | } |
1594 | } | | 1594 | } |
1595 | | | 1595 | |
1596 | /* check if we're not appending a redirection */ | | 1596 | /* check if we're not appending a redirection */ |
1597 | flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); | | 1597 | flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); |
1598 | KASSERT(flags != UDF_EXT_REDIRECT); | | 1598 | KASSERT(flags != UDF_EXT_REDIRECT); |
1599 | | | 1599 | |
1600 | /* round down available space */ | | 1600 | /* round down available space */ |
1601 | rest = adlen * ((max_l_ad - offset) / adlen); | | 1601 | rest = adlen * ((max_l_ad - offset) / adlen); |
1602 | if (rest <= adlen) { | | 1602 | if (rest <= adlen) { |
1603 | /* have to append aed, see if we already have a spare one */ | | 1603 | /* have to append aed, see if we already have a spare one */ |
1604 | extnr++; | | 1604 | extnr++; |
1605 | ext = udf_node->ext[extnr]; | | 1605 | ext = udf_node->ext[extnr]; |
1606 | l_icb = udf_node->ext_loc[extnr]; | | 1606 | l_icb = udf_node->ext_loc[extnr]; |
1607 | if (ext == NULL) { | | 1607 | if (ext == NULL) { |
1608 | DPRINTF(ALLOC,("adding allocation extent %d\n", extnr)); | | 1608 | DPRINTF(ALLOC,("adding allocation extent %d\n", extnr)); |
1609 | | | 1609 | |
1610 | error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, | | 1610 | error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, |
1611 | vpart_num, &lmapping); | | 1611 | vpart_num, &lmapping); |
1612 | lb_num = lmapping; | | 1612 | lb_num = lmapping; |
1613 | if (error) | | 1613 | if (error) |
1614 | return error; | | 1614 | return error; |
1615 | | | 1615 | |
1616 | /* initialise pointer to location */ | | 1616 | /* initialise pointer to location */ |
1617 | memset(&l_icb, 0, sizeof(struct long_ad)); | | 1617 | memset(&l_icb, 0, sizeof(struct long_ad)); |
1618 | l_icb.len = udf_rw32(lb_size | UDF_EXT_REDIRECT); | | 1618 | l_icb.len = udf_rw32(lb_size | UDF_EXT_REDIRECT); |
1619 | l_icb.loc.lb_num = udf_rw32(lb_num); | | 1619 | l_icb.loc.lb_num = udf_rw32(lb_num); |
1620 | l_icb.loc.part_num = udf_rw16(vpart_num); | | 1620 | l_icb.loc.part_num = udf_rw16(vpart_num); |
1621 | | | 1621 | |
1622 | /* create new aed descriptor */ | | 1622 | /* create new aed descriptor */ |
1623 | udf_create_logvol_dscr(ump, udf_node, &l_icb, &extdscr); | | 1623 | udf_create_logvol_dscr(ump, udf_node, &l_icb, &extdscr); |
1624 | ext = &extdscr->aee; | | 1624 | ext = &extdscr->aee; |
1625 | | | 1625 | |
1626 | udf_inittag(ump, &ext->tag, TAGID_ALLOCEXTENT, lb_num); | | 1626 | udf_inittag(ump, &ext->tag, TAGID_ALLOCEXTENT, lb_num); |
1627 | dscr_size = sizeof(struct alloc_ext_entry) -1; | | 1627 | dscr_size = sizeof(struct alloc_ext_entry) -1; |
1628 | max_l_ad = lb_size - dscr_size; | | 1628 | max_l_ad = lb_size - dscr_size; |
1629 | memset(ext->data, 0, max_l_ad); | | 1629 | memset(ext->data, 0, max_l_ad); |
1630 | ext->l_ad = udf_rw32(0); | | 1630 | ext->l_ad = udf_rw32(0); |
1631 | ext->tag.desc_crc_len = | | 1631 | ext->tag.desc_crc_len = |
1632 | udf_rw16(dscr_size - UDF_DESC_TAG_LENGTH); | | 1632 | udf_rw16(dscr_size - UDF_DESC_TAG_LENGTH); |
1633 | | | 1633 | |
1634 | /* declare aed */ | | 1634 | /* declare aed */ |
1635 | udf_node->num_extensions++; | | 1635 | udf_node->num_extensions++; |
1636 | udf_node->ext_loc[extnr] = l_icb; | | 1636 | udf_node->ext_loc[extnr] = l_icb; |
1637 | udf_node->ext[extnr] = ext; | | 1637 | udf_node->ext[extnr] = ext; |
1638 | } | | 1638 | } |
1639 | /* add redirect and adjust l_ad and crclen for old descr */ | | 1639 | /* add redirect and adjust l_ad and crclen for old descr */ |
1640 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1640 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1641 | short_ad = (struct short_ad *) (data_pos + offset); | | 1641 | short_ad = (struct short_ad *) (data_pos + offset); |
1642 | short_ad->len = l_icb.len; | | 1642 | short_ad->len = l_icb.len; |
1643 | short_ad->lb_num = l_icb.loc.lb_num; | | 1643 | short_ad->lb_num = l_icb.loc.lb_num; |
1644 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1644 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1645 | long_ad = (struct long_ad *) (data_pos + offset); | | 1645 | long_ad = (struct long_ad *) (data_pos + offset); |
1646 | *long_ad = l_icb; | | 1646 | *long_ad = l_icb; |
1647 | } | | 1647 | } |
1648 | l_ad += adlen; | | 1648 | l_ad += adlen; |
1649 | crclen += adlen; | | 1649 | crclen += adlen; |
1650 | dscr->tag.desc_crc_len = udf_rw16(crclen); | | 1650 | dscr->tag.desc_crc_len = udf_rw16(crclen); |
1651 | *l_ad_p = udf_rw32(l_ad); | | 1651 | *l_ad_p = udf_rw32(l_ad); |
1652 | | | 1652 | |
1653 | /* advance to the new extension */ | | 1653 | /* advance to the new extension */ |
1654 | KASSERT(ext != NULL); | | 1654 | KASSERT(ext != NULL); |
1655 | dscr = (union dscrptr *) ext; | | 1655 | dscr = (union dscrptr *) ext; |
1656 | dscr_size = sizeof(struct alloc_ext_entry) -1; | | 1656 | dscr_size = sizeof(struct alloc_ext_entry) -1; |
1657 | max_l_ad = lb_size - dscr_size; | | 1657 | max_l_ad = lb_size - dscr_size; |
1658 | data_pos = (uint8_t *) dscr + dscr_size; | | 1658 | data_pos = (uint8_t *) dscr + dscr_size; |
1659 | | | 1659 | |
1660 | l_ad_p = &ext->l_ad; | | 1660 | l_ad_p = &ext->l_ad; |
1661 | l_ad = udf_rw32(*l_ad_p); | | 1661 | l_ad = udf_rw32(*l_ad_p); |
1662 | crclen = udf_rw16(dscr->tag.desc_crc_len); | | 1662 | crclen = udf_rw16(dscr->tag.desc_crc_len); |
1663 | offset = 0; | | 1663 | offset = 0; |
1664 | | | 1664 | |
1665 | /* adjust callees slot count for link insert */ | | 1665 | /* adjust callees slot count for link insert */ |
1666 | *slot += 1; | | 1666 | *slot += 1; |
1667 | } | | 1667 | } |
1668 | | | 1668 | |
1669 | /* write out the element */ | | 1669 | /* write out the element */ |
1670 | DPRINTF(PARANOIDADWLK, ("adding element : %p : v %d, lb %d, " | | 1670 | DPRINTF(PARANOIDADWLK, ("adding element : %p : v %d, lb %d, " |
1671 | "len %d, flags %d\n", data_pos + offset, | | 1671 | "len %d, flags %d\n", data_pos + offset, |
1672 | icb->loc.part_num, icb->loc.lb_num, | | 1672 | icb->loc.part_num, icb->loc.lb_num, |
1673 | UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); | | 1673 | UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); |
1674 | if (addr_type == UDF_ICB_SHORT_ALLOC) { | | 1674 | if (addr_type == UDF_ICB_SHORT_ALLOC) { |
1675 | short_ad = (struct short_ad *) (data_pos + offset); | | 1675 | short_ad = (struct short_ad *) (data_pos + offset); |
1676 | short_ad->len = icb->len; | | 1676 | short_ad->len = icb->len; |
1677 | short_ad->lb_num = icb->loc.lb_num; | | 1677 | short_ad->lb_num = icb->loc.lb_num; |
1678 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { | | 1678 | } else if (addr_type == UDF_ICB_LONG_ALLOC) { |
1679 | long_ad = (struct long_ad *) (data_pos + offset); | | 1679 | long_ad = (struct long_ad *) (data_pos + offset); |
1680 | *long_ad = *icb; | | 1680 | *long_ad = *icb; |
1681 | } | | 1681 | } |
1682 | | | 1682 | |
1683 | /* adjust logblks recorded count */ | | 1683 | /* adjust logblks recorded count */ |
1684 | len = udf_rw32(icb->len); | | 1684 | len = udf_rw32(icb->len); |
1685 | flags = UDF_EXT_FLAGS(len); | | 1685 | flags = UDF_EXT_FLAGS(len); |
1686 | if (flags == UDF_EXT_ALLOCATED) | | 1686 | if (flags == UDF_EXT_ALLOCATED) |
1687 | logblks_rec += (UDF_EXT_LEN(len) + lb_size -1) / lb_size; | | 1687 | logblks_rec += (UDF_EXT_LEN(len) + lb_size -1) / lb_size; |
1688 | *logblks_rec_p = udf_rw64(logblks_rec); | | 1688 | *logblks_rec_p = udf_rw64(logblks_rec); |
1689 | | | 1689 | |
1690 | /* adjust l_ad and crclen when needed */ | | 1690 | /* adjust l_ad and crclen when needed */ |
1691 | if (offset >= l_ad) { | | 1691 | if (offset >= l_ad) { |
1692 | l_ad += adlen; | | 1692 | l_ad += adlen; |
1693 | crclen += adlen; | | 1693 | crclen += adlen; |
1694 | dscr->tag.desc_crc_len = udf_rw16(crclen); | | 1694 | dscr->tag.desc_crc_len = udf_rw16(crclen); |
1695 | *l_ad_p = udf_rw32(l_ad); | | 1695 | *l_ad_p = udf_rw32(l_ad); |
1696 | } | | 1696 | } |
1697 | | | 1697 | |
1698 | return 0; | | 1698 | return 0; |
1699 | } | | 1699 | } |
1700 | | | 1700 | |
1701 | /* --------------------------------------------------------------------- */ | | 1701 | /* --------------------------------------------------------------------- */ |
1702 | | | 1702 | |
1703 | static void | | 1703 | static void |
1704 | udf_count_alloc_exts(struct udf_node *udf_node) | | 1704 | udf_count_alloc_exts(struct udf_node *udf_node) |
1705 | { | | 1705 | { |
1706 | struct long_ad s_ad; | | 1706 | struct long_ad s_ad; |
1707 | uint32_t lb_num, len, flags; | | 1707 | uint32_t lb_num, len, flags; |
1708 | uint16_t vpart_num; | | 1708 | uint16_t vpart_num; |
1709 | int slot, eof; | | 1709 | int slot, eof; |
1710 | int num_extents, extnr; | | 1710 | int num_extents, extnr; |
1711 | int lb_size; | | 1711 | int lb_size; |
1712 | | | 1712 | |
1713 | if (udf_node->num_extensions == 0) | | 1713 | if (udf_node->num_extensions == 0) |
1714 | return; | | 1714 | return; |
1715 | | | 1715 | |
1716 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 1716 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
1717 | /* count number of allocation extents in use */ | | 1717 | /* count number of allocation extents in use */ |
1718 | num_extents = 0; | | 1718 | num_extents = 0; |
1719 | slot = 0; | | 1719 | slot = 0; |
1720 | for (;;) { | | 1720 | for (;;) { |
1721 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 1721 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
1722 | if (eof) | | 1722 | if (eof) |
1723 | break; | | 1723 | break; |
1724 | len = udf_rw32(s_ad.len); | | 1724 | len = udf_rw32(s_ad.len); |
1725 | flags = UDF_EXT_FLAGS(len); | | 1725 | flags = UDF_EXT_FLAGS(len); |
1726 | | | 1726 | |
1727 | if (flags == UDF_EXT_REDIRECT) | | 1727 | if (flags == UDF_EXT_REDIRECT) |
1728 | num_extents++; | | 1728 | num_extents++; |
1729 | | | 1729 | |
1730 | slot++; | | 1730 | slot++; |
1731 | } | | 1731 | } |
1732 | | | 1732 | |
1733 | DPRINTF(ALLOC, ("udf_count_alloc_ext counted %d live extents\n", | | 1733 | DPRINTF(ALLOC, ("udf_count_alloc_ext counted %d live extents\n", |
1734 | num_extents)); | | 1734 | num_extents)); |
1735 | | | 1735 | |
1736 | /* XXX choice: we could delay freeing them on node writeout */ | | 1736 | /* XXX choice: we could delay freeing them on node writeout */ |
1737 | /* free excess entries */ | | 1737 | /* free excess entries */ |
1738 | extnr = num_extents; | | 1738 | extnr = num_extents; |
1739 | for (;extnr < udf_node->num_extensions; extnr++) { | | 1739 | for (;extnr < udf_node->num_extensions; extnr++) { |
1740 | DPRINTF(ALLOC, ("freeing alloc ext %d\n", extnr)); | | 1740 | DPRINTF(ALLOC, ("freeing alloc ext %d\n", extnr)); |
1741 | /* free dscriptor */ | | 1741 | /* free dscriptor */ |
1742 | s_ad = udf_node->ext_loc[extnr]; | | 1742 | s_ad = udf_node->ext_loc[extnr]; |
1743 | udf_free_logvol_dscr(udf_node->ump, &s_ad, | | 1743 | udf_free_logvol_dscr(udf_node->ump, &s_ad, |
1744 | udf_node->ext[extnr]); | | 1744 | udf_node->ext[extnr]); |
1745 | udf_node->ext[extnr] = NULL; | | 1745 | udf_node->ext[extnr] = NULL; |
1746 | | | 1746 | |
1747 | /* free disc space */ | | 1747 | /* free disc space */ |
1748 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 1748 | lb_num = udf_rw32(s_ad.loc.lb_num); |
1749 | vpart_num = udf_rw16(s_ad.loc.part_num); | | 1749 | vpart_num = udf_rw16(s_ad.loc.part_num); |
1750 | udf_free_allocated_space(udf_node->ump, lb_num, vpart_num, 1); | | 1750 | udf_free_allocated_space(udf_node->ump, lb_num, vpart_num, 1); |
1751 | | | 1751 | |
1752 | memset(&udf_node->ext_loc[extnr], 0, sizeof(struct long_ad)); | | 1752 | memset(&udf_node->ext_loc[extnr], 0, sizeof(struct long_ad)); |
1753 | } | | 1753 | } |
1754 | | | 1754 | |
1755 | /* set our new number of allocation extents */ | | 1755 | /* set our new number of allocation extents */ |
1756 | udf_node->num_extensions = num_extents; | | 1756 | udf_node->num_extensions = num_extents; |
1757 | } | | 1757 | } |
1758 | | | 1758 | |
1759 | | | 1759 | |
1760 | /* --------------------------------------------------------------------- */ | | 1760 | /* --------------------------------------------------------------------- */ |
1761 | | | 1761 | |
1762 | /* | | 1762 | /* |
1763 | * Adjust the node's allocation descriptors to reflect the new mapping; do | | 1763 | * Adjust the node's allocation descriptors to reflect the new mapping; do |
1764 | * take note that we might glue to existing allocation descriptors. | | 1764 | * take note that we might glue to existing allocation descriptors. |
1765 | * | | 1765 | * |
1766 | * XXX Note there can only be one allocation being recorded/mount; maybe | | 1766 | * XXX Note there can only be one allocation being recorded/mount; maybe |
1767 | * explicit allocation in shedule thread? | | 1767 | * explicit allocation in shedule thread? |
1768 | */ | | 1768 | */ |
1769 | | | 1769 | |
1770 | static void | | 1770 | static void |
1771 | udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf, | | 1771 | udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf, |
1772 | uint16_t vpart_num, uint64_t *mapping, struct long_ad *node_ad_cpy) | | 1772 | uint16_t vpart_num, uint64_t *mapping, struct long_ad *node_ad_cpy) |
1773 | { | | 1773 | { |
1774 | struct vnode *vp = buf->b_vp; | | 1774 | struct vnode *vp = buf->b_vp; |
1775 | struct udf_node *udf_node = VTOI(vp); | | 1775 | struct udf_node *udf_node = VTOI(vp); |
1776 | struct file_entry *fe; | | 1776 | struct file_entry *fe; |
1777 | struct extfile_entry *efe; | | 1777 | struct extfile_entry *efe; |
1778 | struct icb_tag *icbtag; | | 1778 | struct icb_tag *icbtag; |
1779 | struct long_ad s_ad, c_ad; | | 1779 | struct long_ad s_ad, c_ad; |
1780 | uint64_t inflen, from, till; | | 1780 | uint64_t inflen, from, till; |
1781 | uint64_t foffset, end_foffset, restart_foffset; | | 1781 | uint64_t foffset, end_foffset, restart_foffset; |
1782 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; | | 1782 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; |
1783 | uint32_t num_lb, len, flags, lb_num; | | 1783 | uint32_t num_lb, len, flags, lb_num; |
1784 | uint32_t run_start; | | 1784 | uint32_t run_start; |
1785 | uint32_t slot_offset, replace_len, replace; | | 1785 | uint32_t slot_offset, replace_len, replace; |
1786 | int addr_type, icbflags; | | 1786 | int addr_type, icbflags; |
1787 | // int udf_c_type = buf->b_udf_c_type; | | 1787 | // int udf_c_type = buf->b_udf_c_type; |
1788 | int lb_size, run_length, eof; | | 1788 | int lb_size, run_length, eof; |
1789 | int slot, cpy_slot, cpy_slots, restart_slot; | | 1789 | int slot, cpy_slot, cpy_slots, restart_slot; |
1790 | int error; | | 1790 | int error; |
1791 | | | 1791 | |
1792 | DPRINTF(ALLOC, ("udf_record_allocation_in_node\n")); | | 1792 | DPRINTF(ALLOC, ("udf_record_allocation_in_node\n")); |
1793 | | | 1793 | |
1794 | #if 0 | | 1794 | #if 0 |
1795 | /* XXX disable sanity check for now */ | | 1795 | /* XXX disable sanity check for now */ |
1796 | /* sanity check ... should be panic ? */ | | 1796 | /* sanity check ... should be panic ? */ |
1797 | if ((udf_c_type != UDF_C_USERDATA) && (udf_c_type != UDF_C_FIDS)) | | 1797 | if ((udf_c_type != UDF_C_USERDATA) && (udf_c_type != UDF_C_FIDS)) |
1798 | return; | | 1798 | return; |
1799 | #endif | | 1799 | #endif |
1800 | | | 1800 | |
1801 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); | | 1801 | lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); |
1802 | | | 1802 | |
1803 | /* do the job */ | | 1803 | /* do the job */ |
1804 | UDF_LOCK_NODE(udf_node, 0); /* XXX can deadlock ? */ | | 1804 | UDF_LOCK_NODE(udf_node, 0); /* XXX can deadlock ? */ |
1805 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); | | 1805 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); |
1806 | | | 1806 | |
1807 | fe = udf_node->fe; | | 1807 | fe = udf_node->fe; |
1808 | efe = udf_node->efe; | | 1808 | efe = udf_node->efe; |
1809 | if (fe) { | | 1809 | if (fe) { |
1810 | icbtag = &fe->icbtag; | | 1810 | icbtag = &fe->icbtag; |
1811 | inflen = udf_rw64(fe->inf_len); | | 1811 | inflen = udf_rw64(fe->inf_len); |
1812 | } else { | | 1812 | } else { |
1813 | icbtag = &efe->icbtag; | | 1813 | icbtag = &efe->icbtag; |
1814 | inflen = udf_rw64(efe->inf_len); | | 1814 | inflen = udf_rw64(efe->inf_len); |
1815 | } | | 1815 | } |
1816 | | | 1816 | |
1817 | /* do check if `till' is not past file information length */ | | 1817 | /* do check if `till' is not past file information length */ |
1818 | from = buf->b_lblkno * lb_size; | | 1818 | from = buf->b_lblkno * lb_size; |
1819 | till = MIN(inflen, from + buf->b_resid); | | 1819 | till = MIN(inflen, from + buf->b_resid); |
1820 | | | 1820 | |
1821 | num_lb = (till - from + lb_size -1) / lb_size; | | 1821 | num_lb = (till - from + lb_size -1) / lb_size; |
1822 | | | 1822 | |
1823 | DPRINTF(ALLOC, ("record allocation from %"PRIu64" + %d\n", from, buf->b_bcount)); | | 1823 | DPRINTF(ALLOC, ("record allocation from %"PRIu64" + %d\n", from, buf->b_bcount)); |
1824 | | | 1824 | |
1825 | icbflags = udf_rw16(icbtag->flags); | | 1825 | icbflags = udf_rw16(icbtag->flags); |
1826 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 1826 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
1827 | | | 1827 | |
1828 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 1828 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
1829 | /* nothing to do */ | | 1829 | /* nothing to do */ |
1830 | /* XXX clean up rest of node? just in case? */ | | 1830 | /* XXX clean up rest of node? just in case? */ |
1831 | UDF_UNLOCK_NODE(udf_node, 0); | | 1831 | UDF_UNLOCK_NODE(udf_node, 0); |
1832 | return; | | 1832 | return; |
1833 | } | | 1833 | } |
1834 | | | 1834 | |
1835 | slot = 0; | | 1835 | slot = 0; |
1836 | cpy_slot = 0; | | 1836 | cpy_slot = 0; |
1837 | foffset = 0; | | 1837 | foffset = 0; |
1838 | | | 1838 | |
1839 | /* 1) copy till first overlap piece to the rewrite buffer */ | | 1839 | /* 1) copy till first overlap piece to the rewrite buffer */ |
1840 | for (;;) { | | 1840 | for (;;) { |
1841 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 1841 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
1842 | if (eof) { | | 1842 | if (eof) { |
1843 | DPRINTF(WRITE, | | 1843 | DPRINTF(WRITE, |
1844 | ("Record allocation in node " | | 1844 | ("Record allocation in node " |
1845 | "failed: encountered EOF\n")); | | 1845 | "failed: encountered EOF\n")); |
1846 | UDF_UNLOCK_NODE(udf_node, 0); | | 1846 | UDF_UNLOCK_NODE(udf_node, 0); |
1847 | buf->b_error = EINVAL; | | 1847 | buf->b_error = EINVAL; |
1848 | return; | | 1848 | return; |
1849 | } | | 1849 | } |
1850 | len = udf_rw32(s_ad.len); | | 1850 | len = udf_rw32(s_ad.len); |
1851 | flags = UDF_EXT_FLAGS(len); | | 1851 | flags = UDF_EXT_FLAGS(len); |
1852 | len = UDF_EXT_LEN(len); | | 1852 | len = UDF_EXT_LEN(len); |
1853 | | | 1853 | |
1854 | if (flags == UDF_EXT_REDIRECT) { | | 1854 | if (flags == UDF_EXT_REDIRECT) { |
1855 | slot++; | | 1855 | slot++; |
1856 | continue; | | 1856 | continue; |
1857 | } | | 1857 | } |
1858 | | | 1858 | |
1859 | end_foffset = foffset + len; | | 1859 | end_foffset = foffset + len; |
1860 | if (end_foffset > from) | | 1860 | if (end_foffset > from) |
1861 | break; /* found */ | | 1861 | break; /* found */ |
1862 | | | 1862 | |
1863 | node_ad_cpy[cpy_slot++] = s_ad; | | 1863 | node_ad_cpy[cpy_slot++] = s_ad; |
1864 | | | 1864 | |
1865 | DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " | | 1865 | DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " |
1866 | "-> stack\n", | | 1866 | "-> stack\n", |
1867 | udf_rw16(s_ad.loc.part_num), | | 1867 | udf_rw16(s_ad.loc.part_num), |
1868 | udf_rw32(s_ad.loc.lb_num), | | 1868 | udf_rw32(s_ad.loc.lb_num), |
1869 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 1869 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
1870 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 1870 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
1871 | | | 1871 | |
1872 | foffset = end_foffset; | | 1872 | foffset = end_foffset; |
1873 | slot++; | | 1873 | slot++; |
1874 | } | | 1874 | } |
1875 | restart_slot = slot; | | 1875 | restart_slot = slot; |
1876 | restart_foffset = foffset; | | 1876 | restart_foffset = foffset; |
1877 | | | 1877 | |
1878 | /* 2) trunc overlapping slot at overlap and copy it */ | | 1878 | /* 2) trunc overlapping slot at overlap and copy it */ |
1879 | slot_offset = from - foffset; | | 1879 | slot_offset = from - foffset; |
1880 | if (slot_offset > 0) { | | 1880 | if (slot_offset > 0) { |
1881 | DPRINTF(ALLOC, ("\tslot_offset = %d, flags = %d (%d)\n", | | 1881 | DPRINTF(ALLOC, ("\tslot_offset = %d, flags = %d (%d)\n", |
1882 | slot_offset, flags >> 30, flags)); | | 1882 | slot_offset, flags >> 30, flags)); |
1883 | | | 1883 | |
1884 | s_ad.len = udf_rw32(slot_offset | flags); | | 1884 | s_ad.len = udf_rw32(slot_offset | flags); |
1885 | node_ad_cpy[cpy_slot++] = s_ad; | | 1885 | node_ad_cpy[cpy_slot++] = s_ad; |
1886 | | | 1886 | |
1887 | DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " | | 1887 | DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " |
1888 | "-> stack\n", | | 1888 | "-> stack\n", |
1889 | udf_rw16(s_ad.loc.part_num), | | 1889 | udf_rw16(s_ad.loc.part_num), |
1890 | udf_rw32(s_ad.loc.lb_num), | | 1890 | udf_rw32(s_ad.loc.lb_num), |
1891 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 1891 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
1892 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 1892 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
1893 | } | | 1893 | } |
1894 | foffset += slot_offset; | | 1894 | foffset += slot_offset; |
1895 | | | 1895 | |
1896 | /* 3) insert new mappings */ | | 1896 | /* 3) insert new mappings */ |
1897 | memset(&s_ad, 0, sizeof(struct long_ad)); | | 1897 | memset(&s_ad, 0, sizeof(struct long_ad)); |
1898 | lb_num = 0; | | 1898 | lb_num = 0; |
1899 | for (lb_num = 0; lb_num < num_lb; lb_num++) { | | 1899 | for (lb_num = 0; lb_num < num_lb; lb_num++) { |
1900 | run_start = mapping[lb_num]; | | 1900 | run_start = mapping[lb_num]; |
1901 | run_length = 1; | | 1901 | run_length = 1; |
1902 | while (lb_num < num_lb-1) { | | 1902 | while (lb_num < num_lb-1) { |
1903 | if (mapping[lb_num+1] != mapping[lb_num]+1) | | 1903 | if (mapping[lb_num+1] != mapping[lb_num]+1) |
1904 | if (mapping[lb_num+1] != mapping[lb_num]) | | 1904 | if (mapping[lb_num+1] != mapping[lb_num]) |
1905 | break; | | 1905 | break; |
1906 | run_length++; | | 1906 | run_length++; |
1907 | lb_num++; | | 1907 | lb_num++; |
1908 | } | | 1908 | } |
1909 | /* insert slot for this mapping */ | | 1909 | /* insert slot for this mapping */ |
1910 | len = run_length * lb_size; | | 1910 | len = run_length * lb_size; |
1911 | | | 1911 | |
1912 | /* bounds checking */ | | 1912 | /* bounds checking */ |
1913 | if (foffset + len > till) | | 1913 | if (foffset + len > till) |
1914 | len = till - foffset; | | 1914 | len = till - foffset; |
1915 | KASSERT(foffset + len <= inflen); | | 1915 | KASSERT(foffset + len <= inflen); |
1916 | | | 1916 | |
1917 | s_ad.len = udf_rw32(len | UDF_EXT_ALLOCATED); | | 1917 | s_ad.len = udf_rw32(len | UDF_EXT_ALLOCATED); |
1918 | s_ad.loc.part_num = udf_rw16(vpart_num); | | 1918 | s_ad.loc.part_num = udf_rw16(vpart_num); |
1919 | s_ad.loc.lb_num = udf_rw32(run_start); | | 1919 | s_ad.loc.lb_num = udf_rw32(run_start); |
1920 | | | 1920 | |
1921 | foffset += len; | | 1921 | foffset += len; |
1922 | | | 1922 | |
1923 | /* paranoia */ | | 1923 | /* paranoia */ |
1924 | if (len == 0) { | | 1924 | if (len == 0) { |
1925 | DPRINTF(WRITE, | | 1925 | DPRINTF(WRITE, |
1926 | ("Record allocation in node " | | 1926 | ("Record allocation in node " |
1927 | "failed: insert failed\n")); | | 1927 | "failed: insert failed\n")); |
1928 | UDF_UNLOCK_NODE(udf_node, 0); | | 1928 | UDF_UNLOCK_NODE(udf_node, 0); |
1929 | buf->b_error = EINVAL; | | 1929 | buf->b_error = EINVAL; |
1930 | return; | | 1930 | return; |
1931 | } | | 1931 | } |
1932 | node_ad_cpy[cpy_slot++] = s_ad; | | 1932 | node_ad_cpy[cpy_slot++] = s_ad; |
1933 | | | 1933 | |
1934 | DPRINTF(ALLOC, ("\t3: insert new mapping vp %d lb %d, len %d, " | | 1934 | DPRINTF(ALLOC, ("\t3: insert new mapping vp %d lb %d, len %d, " |
1935 | "flags %d -> stack\n", | | 1935 | "flags %d -> stack\n", |
1936 | udf_rw16(s_ad.loc.part_num), udf_rw32(s_ad.loc.lb_num), | | 1936 | udf_rw16(s_ad.loc.part_num), udf_rw32(s_ad.loc.lb_num), |
1937 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 1937 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
1938 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 1938 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
1939 | } | | 1939 | } |
1940 | | | 1940 | |
1941 | /* 4) pop replaced length */ | | 1941 | /* 4) pop replaced length */ |
1942 | slot = restart_slot; | | 1942 | slot = restart_slot; |
1943 | foffset = restart_foffset; | | 1943 | foffset = restart_foffset; |
1944 | | | 1944 | |
1945 | replace_len = till - foffset; /* total amount of bytes to pop */ | | 1945 | replace_len = till - foffset; /* total amount of bytes to pop */ |
1946 | slot_offset = from - foffset; /* offset in first encounted slot */ | | 1946 | slot_offset = from - foffset; /* offset in first encounted slot */ |
1947 | KASSERT((slot_offset % lb_size) == 0); | | 1947 | KASSERT((slot_offset % lb_size) == 0); |
1948 | | | 1948 | |
1949 | for (;;) { | | 1949 | for (;;) { |
1950 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 1950 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
1951 | if (eof) | | 1951 | if (eof) |
1952 | break; | | 1952 | break; |
1953 | | | 1953 | |
1954 | len = udf_rw32(s_ad.len); | | 1954 | len = udf_rw32(s_ad.len); |
1955 | flags = UDF_EXT_FLAGS(len); | | 1955 | flags = UDF_EXT_FLAGS(len); |
1956 | len = UDF_EXT_LEN(len); | | 1956 | len = UDF_EXT_LEN(len); |
1957 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 1957 | lb_num = udf_rw32(s_ad.loc.lb_num); |
1958 | | | 1958 | |
1959 | if (flags == UDF_EXT_REDIRECT) { | | 1959 | if (flags == UDF_EXT_REDIRECT) { |
1960 | slot++; | | 1960 | slot++; |
1961 | continue; | | 1961 | continue; |
1962 | } | | 1962 | } |
1963 | | | 1963 | |
1964 | DPRINTF(ALLOC, ("\t4i: got slot %d, slot_offset %d, " | | 1964 | DPRINTF(ALLOC, ("\t4i: got slot %d, slot_offset %d, " |
1965 | "replace_len %d, " | | 1965 | "replace_len %d, " |
1966 | "vp %d, lb %d, len %d, flags %d\n", | | 1966 | "vp %d, lb %d, len %d, flags %d\n", |
1967 | slot, slot_offset, replace_len, | | 1967 | slot, slot_offset, replace_len, |
1968 | udf_rw16(s_ad.loc.part_num), | | 1968 | udf_rw16(s_ad.loc.part_num), |
1969 | udf_rw32(s_ad.loc.lb_num), | | 1969 | udf_rw32(s_ad.loc.lb_num), |
1970 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 1970 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
1971 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 1971 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
1972 | | | 1972 | |
1973 | /* adjust for slot offset */ | | 1973 | /* adjust for slot offset */ |
1974 | if (slot_offset) { | | 1974 | if (slot_offset) { |
1975 | DPRINTF(ALLOC, ("\t4s: skipping %d\n", slot_offset)); | | 1975 | DPRINTF(ALLOC, ("\t4s: skipping %d\n", slot_offset)); |
1976 | lb_num += slot_offset / lb_size; | | 1976 | lb_num += slot_offset / lb_size; |
1977 | len -= slot_offset; | | 1977 | len -= slot_offset; |
1978 | foffset += slot_offset; | | 1978 | foffset += slot_offset; |
1979 | replace_len -= slot_offset; | | 1979 | replace_len -= slot_offset; |
1980 | | | 1980 | |
1981 | /* mark adjusted */ | | 1981 | /* mark adjusted */ |
1982 | slot_offset = 0; | | 1982 | slot_offset = 0; |
1983 | } | | 1983 | } |
1984 | | | 1984 | |
1985 | /* advance for (the rest of) this slot */ | | 1985 | /* advance for (the rest of) this slot */ |
1986 | replace = MIN(len, replace_len); | | 1986 | replace = MIN(len, replace_len); |
1987 | DPRINTF(ALLOC, ("\t4d: replacing %d\n", replace)); | | 1987 | DPRINTF(ALLOC, ("\t4d: replacing %d\n", replace)); |
1988 | | | 1988 | |
1989 | /* advance for this slot */ | | 1989 | /* advance for this slot */ |
1990 | if (replace) { | | 1990 | if (replace) { |
1991 | /* note: dont round DOWN on num_lb since we then | | 1991 | /* note: dont round DOWN on num_lb since we then |
1992 | * forget the last partial one */ | | 1992 | * forget the last partial one */ |
1993 | num_lb = (replace + lb_size - 1) / lb_size; | | 1993 | num_lb = (replace + lb_size - 1) / lb_size; |
1994 | if (flags != UDF_EXT_FREE) { | | 1994 | if (flags != UDF_EXT_FREE) { |
1995 | udf_free_allocated_space(ump, lb_num, | | 1995 | udf_free_allocated_space(ump, lb_num, |
1996 | udf_rw16(s_ad.loc.part_num), num_lb); | | 1996 | udf_rw16(s_ad.loc.part_num), num_lb); |
1997 | } | | 1997 | } |
1998 | lb_num += num_lb; | | 1998 | lb_num += num_lb; |
1999 | len -= replace; | | 1999 | len -= replace; |
2000 | foffset += replace; | | 2000 | foffset += replace; |
2001 | replace_len -= replace; | | 2001 | replace_len -= replace; |
2002 | } | | 2002 | } |
2003 | | | 2003 | |
2004 | /* do we have a slot tail ? */ | | 2004 | /* do we have a slot tail ? */ |
2005 | if (len) { | | 2005 | if (len) { |
2006 | KASSERT(foffset % lb_size == 0); | | 2006 | KASSERT(foffset % lb_size == 0); |
2007 | | | 2007 | |
2008 | /* we arrived at our point, push remainder */ | | 2008 | /* we arrived at our point, push remainder */ |
2009 | s_ad.len = udf_rw32(len | flags); | | 2009 | s_ad.len = udf_rw32(len | flags); |
2010 | s_ad.loc.lb_num = udf_rw32(lb_num); | | 2010 | s_ad.loc.lb_num = udf_rw32(lb_num); |
2011 | if (flags == UDF_EXT_FREE) | | 2011 | if (flags == UDF_EXT_FREE) |
2012 | s_ad.loc.lb_num = udf_rw32(0); | | 2012 | s_ad.loc.lb_num = udf_rw32(0); |
2013 | node_ad_cpy[cpy_slot++] = s_ad; | | 2013 | node_ad_cpy[cpy_slot++] = s_ad; |
2014 | foffset += len; | | 2014 | foffset += len; |
2015 | slot++; | | 2015 | slot++; |
2016 | | | 2016 | |
2017 | DPRINTF(ALLOC, ("\t4: vp %d, lb %d, len %d, flags %d " | | 2017 | DPRINTF(ALLOC, ("\t4: vp %d, lb %d, len %d, flags %d " |
2018 | "-> stack\n", | | 2018 | "-> stack\n", |
2019 | udf_rw16(s_ad.loc.part_num), | | 2019 | udf_rw16(s_ad.loc.part_num), |
2020 | udf_rw32(s_ad.loc.lb_num), | | 2020 | udf_rw32(s_ad.loc.lb_num), |
2021 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2021 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2022 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2022 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2023 | break; | | 2023 | break; |
2024 | } | | 2024 | } |
2025 | | | 2025 | |
2026 | slot++; | | 2026 | slot++; |
2027 | } | | 2027 | } |
2028 | | | 2028 | |
2029 | /* 5) copy remainder */ | | 2029 | /* 5) copy remainder */ |
2030 | for (;;) { | | 2030 | for (;;) { |
2031 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 2031 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
2032 | if (eof) | | 2032 | if (eof) |
2033 | break; | | 2033 | break; |
2034 | | | 2034 | |
2035 | len = udf_rw32(s_ad.len); | | 2035 | len = udf_rw32(s_ad.len); |
2036 | flags = UDF_EXT_FLAGS(len); | | 2036 | flags = UDF_EXT_FLAGS(len); |
2037 | len = UDF_EXT_LEN(len); | | 2037 | len = UDF_EXT_LEN(len); |
2038 | | | 2038 | |
2039 | if (flags == UDF_EXT_REDIRECT) { | | 2039 | if (flags == UDF_EXT_REDIRECT) { |
2040 | slot++; | | 2040 | slot++; |
2041 | continue; | | 2041 | continue; |
2042 | } | | 2042 | } |
2043 | | | 2043 | |
2044 | node_ad_cpy[cpy_slot++] = s_ad; | | 2044 | node_ad_cpy[cpy_slot++] = s_ad; |
2045 | | | 2045 | |
2046 | DPRINTF(ALLOC, ("\t5: insert new mapping " | | 2046 | DPRINTF(ALLOC, ("\t5: insert new mapping " |
2047 | "vp %d lb %d, len %d, flags %d " | | 2047 | "vp %d lb %d, len %d, flags %d " |
2048 | "-> stack\n", | | 2048 | "-> stack\n", |
2049 | udf_rw16(s_ad.loc.part_num), | | 2049 | udf_rw16(s_ad.loc.part_num), |
2050 | udf_rw32(s_ad.loc.lb_num), | | 2050 | udf_rw32(s_ad.loc.lb_num), |
2051 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2051 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2052 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2052 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2053 | | | 2053 | |
2054 | slot++; | | 2054 | slot++; |
2055 | } | | 2055 | } |
2056 | | | 2056 | |
2057 | /* 6) reset node descriptors */ | | 2057 | /* 6) reset node descriptors */ |
2058 | udf_wipe_adslots(udf_node); | | 2058 | udf_wipe_adslots(udf_node); |
2059 | | | 2059 | |
2060 | /* 7) copy back extents; merge when possible. Recounting on the fly */ | | 2060 | /* 7) copy back extents; merge when possible. Recounting on the fly */ |
2061 | cpy_slots = cpy_slot; | | 2061 | cpy_slots = cpy_slot; |
2062 | | | 2062 | |
2063 | c_ad = node_ad_cpy[0]; | | 2063 | c_ad = node_ad_cpy[0]; |
2064 | slot = 0; | | 2064 | slot = 0; |
2065 | DPRINTF(ALLOC, ("\t7s: stack -> got mapping vp %d " | | 2065 | DPRINTF(ALLOC, ("\t7s: stack -> got mapping vp %d " |
2066 | "lb %d, len %d, flags %d\n", | | 2066 | "lb %d, len %d, flags %d\n", |
2067 | udf_rw16(c_ad.loc.part_num), | | 2067 | udf_rw16(c_ad.loc.part_num), |
2068 | udf_rw32(c_ad.loc.lb_num), | | 2068 | udf_rw32(c_ad.loc.lb_num), |
2069 | UDF_EXT_LEN(udf_rw32(c_ad.len)), | | 2069 | UDF_EXT_LEN(udf_rw32(c_ad.len)), |
2070 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); | | 2070 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); |
2071 | | | 2071 | |
2072 | for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { | | 2072 | for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { |
2073 | s_ad = node_ad_cpy[cpy_slot]; | | 2073 | s_ad = node_ad_cpy[cpy_slot]; |
2074 | | | 2074 | |
2075 | DPRINTF(ALLOC, ("\t7i: stack -> got mapping vp %d " | | 2075 | DPRINTF(ALLOC, ("\t7i: stack -> got mapping vp %d " |
2076 | "lb %d, len %d, flags %d\n", | | 2076 | "lb %d, len %d, flags %d\n", |
2077 | udf_rw16(s_ad.loc.part_num), | | 2077 | udf_rw16(s_ad.loc.part_num), |
2078 | udf_rw32(s_ad.loc.lb_num), | | 2078 | udf_rw32(s_ad.loc.lb_num), |
2079 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2079 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2080 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2080 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2081 | | | 2081 | |
2082 | /* see if we can merge */ | | 2082 | /* see if we can merge */ |
2083 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { | | 2083 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { |
2084 | /* not mergable (anymore) */ | | 2084 | /* not mergable (anymore) */ |
2085 | DPRINTF(ALLOC, ("\t7: appending vp %d lb %d, " | | 2085 | DPRINTF(ALLOC, ("\t7: appending vp %d lb %d, " |
2086 | "len %d, flags %d\n", | | 2086 | "len %d, flags %d\n", |
2087 | udf_rw16(c_ad.loc.part_num), | | 2087 | udf_rw16(c_ad.loc.part_num), |
2088 | udf_rw32(c_ad.loc.lb_num), | | 2088 | udf_rw32(c_ad.loc.lb_num), |
2089 | UDF_EXT_LEN(udf_rw32(c_ad.len)), | | 2089 | UDF_EXT_LEN(udf_rw32(c_ad.len)), |
2090 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); | | 2090 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); |
2091 | | | 2091 | |
2092 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2092 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2093 | if (error) { | | 2093 | if (error) { |
2094 | buf->b_error = error; | | 2094 | buf->b_error = error; |
2095 | goto out; | | 2095 | goto out; |
2096 | } | | 2096 | } |
2097 | c_ad = s_ad; | | 2097 | c_ad = s_ad; |
2098 | slot++; | | 2098 | slot++; |
2099 | } | | 2099 | } |
2100 | } | | 2100 | } |
2101 | | | 2101 | |
2102 | /* 8) push rest slot (if any) */ | | 2102 | /* 8) push rest slot (if any) */ |
2103 | if (UDF_EXT_LEN(c_ad.len) > 0) { | | 2103 | if (UDF_EXT_LEN(c_ad.len) > 0) { |
2104 | DPRINTF(ALLOC, ("\t8: last append vp %d lb %d, " | | 2104 | DPRINTF(ALLOC, ("\t8: last append vp %d lb %d, " |
2105 | "len %d, flags %d\n", | | 2105 | "len %d, flags %d\n", |
2106 | udf_rw16(c_ad.loc.part_num), | | 2106 | udf_rw16(c_ad.loc.part_num), |
2107 | udf_rw32(c_ad.loc.lb_num), | | 2107 | udf_rw32(c_ad.loc.lb_num), |
2108 | UDF_EXT_LEN(udf_rw32(c_ad.len)), | | 2108 | UDF_EXT_LEN(udf_rw32(c_ad.len)), |
2109 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); | | 2109 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); |
2110 | | | 2110 | |
2111 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2111 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2112 | if (error) { | | 2112 | if (error) { |
2113 | buf->b_error = error; | | 2113 | buf->b_error = error; |
2114 | goto out; | | 2114 | goto out; |
2115 | } | | 2115 | } |
2116 | } | | 2116 | } |
2117 | | | 2117 | |
2118 | out: | | 2118 | out: |
2119 | udf_count_alloc_exts(udf_node); | | 2119 | udf_count_alloc_exts(udf_node); |
2120 | | | 2120 | |
2121 | /* the node's descriptors should now be sane */ | | 2121 | /* the node's descriptors should now be sane */ |
2122 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2122 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2123 | UDF_UNLOCK_NODE(udf_node, 0); | | 2123 | UDF_UNLOCK_NODE(udf_node, 0); |
2124 | | | 2124 | |
2125 | KASSERT(orig_inflen == new_inflen); | | 2125 | KASSERT(orig_inflen == new_inflen); |
2126 | KASSERT(new_lbrec >= orig_lbrec); | | 2126 | KASSERT(new_lbrec >= orig_lbrec); |
2127 | | | 2127 | |
2128 | return; | | 2128 | return; |
2129 | } | | 2129 | } |
2130 | | | 2130 | |
2131 | /* --------------------------------------------------------------------- */ | | 2131 | /* --------------------------------------------------------------------- */ |
2132 | | | 2132 | |
2133 | int | | 2133 | int |
2134 | udf_grow_node(struct udf_node *udf_node, uint64_t new_size) | | 2134 | udf_grow_node(struct udf_node *udf_node, uint64_t new_size) |
2135 | { | | 2135 | { |
2136 | union dscrptr *dscr; | | 2136 | union dscrptr *dscr; |
2137 | struct vnode *vp = udf_node->vnode; | | 2137 | struct vnode *vp = udf_node->vnode; |
2138 | struct udf_mount *ump = udf_node->ump; | | 2138 | struct udf_mount *ump = udf_node->ump; |
2139 | struct file_entry *fe; | | 2139 | struct file_entry *fe; |
2140 | struct extfile_entry *efe; | | 2140 | struct extfile_entry *efe; |
2141 | struct icb_tag *icbtag; | | 2141 | struct icb_tag *icbtag; |
2142 | struct long_ad c_ad, s_ad; | | 2142 | struct long_ad c_ad, s_ad; |
2143 | uint64_t size_diff, old_size, inflen, objsize, chunk, append_len; | | 2143 | uint64_t size_diff, old_size, inflen, objsize, chunk, append_len; |
2144 | uint64_t foffset, end_foffset; | | 2144 | uint64_t foffset, end_foffset; |
2145 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; | | 2145 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; |
2146 | uint32_t lb_size, dscr_size, crclen, lastblock_grow; | | 2146 | uint32_t lb_size, dscr_size, crclen, lastblock_grow; |
2147 | uint32_t icbflags, len, flags, max_len; | | 2147 | uint32_t icbflags, len, flags, max_len; |
2148 | uint32_t max_l_ad, l_ad, l_ea; | | 2148 | uint32_t max_l_ad, l_ad, l_ea; |
2149 | uint16_t my_part, dst_part; | | 2149 | uint16_t my_part, dst_part; |
2150 | uint8_t *data_pos, *evacuated_data; | | 2150 | uint8_t *data_pos, *evacuated_data; |
2151 | int addr_type; | | 2151 | int addr_type; |
2152 | int slot, cpy_slot; | | 2152 | int slot, cpy_slot; |
2153 | int isdir, eof, error; | | 2153 | int isdir, eof, error; |
2154 | | | 2154 | |
2155 | DPRINTF(ALLOC, ("udf_grow_node\n")); | | 2155 | DPRINTF(ALLOC, ("udf_grow_node\n")); |
2156 | | | 2156 | |
2157 | UDF_LOCK_NODE(udf_node, 0); | | 2157 | UDF_LOCK_NODE(udf_node, 0); |
2158 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); | | 2158 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); |
2159 | | | 2159 | |
2160 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 2160 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
2161 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); | | 2161 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); |
2162 | | | 2162 | |
2163 | fe = udf_node->fe; | | 2163 | fe = udf_node->fe; |
2164 | efe = udf_node->efe; | | 2164 | efe = udf_node->efe; |
2165 | if (fe) { | | 2165 | if (fe) { |
2166 | dscr = (union dscrptr *) fe; | | 2166 | dscr = (union dscrptr *) fe; |
2167 | icbtag = &fe->icbtag; | | 2167 | icbtag = &fe->icbtag; |
2168 | inflen = udf_rw64(fe->inf_len); | | 2168 | inflen = udf_rw64(fe->inf_len); |
2169 | objsize = inflen; | | 2169 | objsize = inflen; |
2170 | dscr_size = sizeof(struct file_entry) -1; | | 2170 | dscr_size = sizeof(struct file_entry) -1; |
2171 | l_ea = udf_rw32(fe->l_ea); | | 2171 | l_ea = udf_rw32(fe->l_ea); |
2172 | l_ad = udf_rw32(fe->l_ad); | | 2172 | l_ad = udf_rw32(fe->l_ad); |
2173 | } else { | | 2173 | } else { |
2174 | dscr = (union dscrptr *) efe; | | 2174 | dscr = (union dscrptr *) efe; |
2175 | icbtag = &efe->icbtag; | | 2175 | icbtag = &efe->icbtag; |
2176 | inflen = udf_rw64(efe->inf_len); | | 2176 | inflen = udf_rw64(efe->inf_len); |
2177 | objsize = udf_rw64(efe->obj_size); | | 2177 | objsize = udf_rw64(efe->obj_size); |
2178 | dscr_size = sizeof(struct extfile_entry) -1; | | 2178 | dscr_size = sizeof(struct extfile_entry) -1; |
2179 | l_ea = udf_rw32(efe->l_ea); | | 2179 | l_ea = udf_rw32(efe->l_ea); |
2180 | l_ad = udf_rw32(efe->l_ad); | | 2180 | l_ad = udf_rw32(efe->l_ad); |
2181 | } | | 2181 | } |
2182 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; | | 2182 | data_pos = (uint8_t *) dscr + dscr_size + l_ea; |
2183 | max_l_ad = lb_size - dscr_size - l_ea; | | 2183 | max_l_ad = lb_size - dscr_size - l_ea; |
2184 | | | 2184 | |
2185 | icbflags = udf_rw16(icbtag->flags); | | 2185 | icbflags = udf_rw16(icbtag->flags); |
2186 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 2186 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
2187 | | | 2187 | |
2188 | old_size = inflen; | | 2188 | old_size = inflen; |
2189 | size_diff = new_size - old_size; | | 2189 | size_diff = new_size - old_size; |
2190 | | | 2190 | |
2191 | DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); | | 2191 | DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); |
2192 | | | 2192 | |
2193 | evacuated_data = NULL; | | 2193 | evacuated_data = NULL; |
2194 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 2194 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
2195 | if (l_ad + size_diff <= max_l_ad) { | | 2195 | if (l_ad + size_diff <= max_l_ad) { |
2196 | /* only reflect size change directly in the node */ | | 2196 | /* only reflect size change directly in the node */ |
2197 | inflen += size_diff; | | 2197 | inflen += size_diff; |
2198 | objsize += size_diff; | | 2198 | objsize += size_diff; |
2199 | l_ad += size_diff; | | 2199 | l_ad += size_diff; |
2200 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; | | 2200 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; |
2201 | if (fe) { | | 2201 | if (fe) { |
2202 | fe->inf_len = udf_rw64(inflen); | | 2202 | fe->inf_len = udf_rw64(inflen); |
2203 | fe->l_ad = udf_rw32(l_ad); | | 2203 | fe->l_ad = udf_rw32(l_ad); |
2204 | fe->tag.desc_crc_len = udf_rw16(crclen); | | 2204 | fe->tag.desc_crc_len = udf_rw16(crclen); |
2205 | } else { | | 2205 | } else { |
2206 | efe->inf_len = udf_rw64(inflen); | | 2206 | efe->inf_len = udf_rw64(inflen); |
2207 | efe->obj_size = udf_rw64(objsize); | | 2207 | efe->obj_size = udf_rw64(objsize); |
2208 | efe->l_ad = udf_rw32(l_ad); | | 2208 | efe->l_ad = udf_rw32(l_ad); |
2209 | efe->tag.desc_crc_len = udf_rw16(crclen); | | 2209 | efe->tag.desc_crc_len = udf_rw16(crclen); |
2210 | } | | 2210 | } |
2211 | error = 0; | | 2211 | error = 0; |
2212 | | | 2212 | |
2213 | /* set new size for uvm */ | | 2213 | /* set new size for uvm */ |
2214 | uvm_vnp_setsize(vp, old_size); | | 2214 | uvm_vnp_setsize(vp, old_size); |
2215 | uvm_vnp_setwritesize(vp, new_size); | | 2215 | uvm_vnp_setwritesize(vp, new_size); |
2216 | | | 2216 | |
2217 | #if 0 | | 2217 | #if 0 |
2218 | /* zero append space in buffer */ | | 2218 | /* zero append space in buffer */ |
2219 | uvm_vnp_zerorange(vp, old_size, new_size - old_size); | | 2219 | uvm_vnp_zerorange(vp, old_size, new_size - old_size); |
2220 | #endif | | 2220 | #endif |
2221 | | | 2221 | |
2222 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2222 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2223 | | | 2223 | |
2224 | /* unlock */ | | 2224 | /* unlock */ |
2225 | UDF_UNLOCK_NODE(udf_node, 0); | | 2225 | UDF_UNLOCK_NODE(udf_node, 0); |
2226 | | | 2226 | |
2227 | KASSERT(new_inflen == orig_inflen + size_diff); | | 2227 | KASSERT(new_inflen == orig_inflen + size_diff); |
2228 | KASSERT(new_lbrec == orig_lbrec); | | 2228 | KASSERT(new_lbrec == orig_lbrec); |
2229 | KASSERT(new_lbrec == 0); | | 2229 | KASSERT(new_lbrec == 0); |
2230 | return 0; | | 2230 | return 0; |
2231 | } | | 2231 | } |
2232 | | | 2232 | |
2233 | DPRINTF(ALLOC, ("\tCONVERT from internal\n")); | | 2233 | DPRINTF(ALLOC, ("\tCONVERT from internal\n")); |
2234 | | | 2234 | |
2235 | if (old_size > 0) { | | 2235 | if (old_size > 0) { |
2236 | /* allocate some space and copy in the stuff to keep */ | | 2236 | /* allocate some space and copy in the stuff to keep */ |
2237 | evacuated_data = malloc(lb_size, M_UDFTEMP, M_WAITOK); | | 2237 | evacuated_data = malloc(lb_size, M_UDFTEMP, M_WAITOK); |
2238 | memset(evacuated_data, 0, lb_size); | | 2238 | memset(evacuated_data, 0, lb_size); |
2239 | | | 2239 | |
2240 | /* node is locked, so safe to exit mutex */ | | 2240 | /* node is locked, so safe to exit mutex */ |
2241 | UDF_UNLOCK_NODE(udf_node, 0); | | 2241 | UDF_UNLOCK_NODE(udf_node, 0); |
2242 | | | 2242 | |
2243 | /* read in using the `normal' vn_rdwr() */ | | 2243 | /* read in using the `normal' vn_rdwr() */ |
2244 | error = vn_rdwr(UIO_READ, udf_node->vnode, | | 2244 | error = vn_rdwr(UIO_READ, udf_node->vnode, |
2245 | evacuated_data, old_size, 0, | | 2245 | evacuated_data, old_size, 0, |
2246 | UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, | | 2246 | UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, |
2247 | FSCRED, NULL, NULL); | | 2247 | FSCRED, NULL, NULL); |
2248 | | | 2248 | |
2249 | /* enter again */ | | 2249 | /* enter again */ |
2250 | UDF_LOCK_NODE(udf_node, 0); | | 2250 | UDF_LOCK_NODE(udf_node, 0); |
2251 | } | | 2251 | } |
2252 | | | 2252 | |
2253 | /* convert to a normal alloc and select type */ | | 2253 | /* convert to a normal alloc and select type */ |
2254 | isdir = (vp->v_type == VDIR); | | 2254 | isdir = (vp->v_type == VDIR); |
2255 | my_part = udf_rw16(udf_node->loc.loc.part_num); | | 2255 | my_part = udf_rw16(udf_node->loc.loc.part_num); |
2256 | dst_part = isdir? ump->fids_part : ump->data_part; | | 2256 | dst_part = isdir ? ump->fids_part : ump->data_part; |
2257 | addr_type = UDF_ICB_SHORT_ALLOC; | | 2257 | addr_type = UDF_ICB_SHORT_ALLOC; |
2258 | if (dst_part != my_part) | | 2258 | if (dst_part != my_part) |
2259 | addr_type = UDF_ICB_LONG_ALLOC; | | 2259 | addr_type = UDF_ICB_LONG_ALLOC; |
2260 | | | 2260 | |
2261 | icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 2261 | icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
2262 | icbflags |= addr_type; | | 2262 | icbflags |= addr_type; |
2263 | icbtag->flags = udf_rw16(icbflags); | | 2263 | icbtag->flags = udf_rw16(icbflags); |
2264 | | | 2264 | |
2265 | /* wipe old descriptor space */ | | 2265 | /* wipe old descriptor space */ |
2266 | udf_wipe_adslots(udf_node); | | 2266 | udf_wipe_adslots(udf_node); |
2267 | | | 2267 | |
2268 | memset(&c_ad, 0, sizeof(struct long_ad)); | | 2268 | memset(&c_ad, 0, sizeof(struct long_ad)); |
2269 | c_ad.len = udf_rw32(old_size | UDF_EXT_FREE); | | 2269 | c_ad.len = udf_rw32(old_size | UDF_EXT_FREE); |
2270 | c_ad.loc.part_num = udf_rw16(0); /* not relevant */ | | 2270 | c_ad.loc.part_num = udf_rw16(0); /* not relevant */ |
2271 | c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ | | 2271 | c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ |
2272 | | | 2272 | |
2273 | slot = 0; | | 2273 | slot = 0; |
2274 | } else { | | 2274 | } else { |
2275 | /* goto the last entry (if any) */ | | 2275 | /* goto the last entry (if any) */ |
2276 | slot = 0; | | 2276 | slot = 0; |
2277 | cpy_slot = 0; | | 2277 | cpy_slot = 0; |
2278 | foffset = 0; | | 2278 | foffset = 0; |
2279 | memset(&c_ad, 0, sizeof(struct long_ad)); | | 2279 | memset(&c_ad, 0, sizeof(struct long_ad)); |
2280 | for (;;) { | | 2280 | for (;;) { |
2281 | udf_get_adslot(udf_node, slot, &c_ad, &eof); | | 2281 | udf_get_adslot(udf_node, slot, &c_ad, &eof); |
2282 | if (eof) | | 2282 | if (eof) |
2283 | break; | | 2283 | break; |
2284 | | | 2284 | |
2285 | len = udf_rw32(c_ad.len); | | 2285 | len = udf_rw32(c_ad.len); |
2286 | flags = UDF_EXT_FLAGS(len); | | 2286 | flags = UDF_EXT_FLAGS(len); |
2287 | len = UDF_EXT_LEN(len); | | 2287 | len = UDF_EXT_LEN(len); |
2288 | | | 2288 | |
2289 | end_foffset = foffset + len; | | 2289 | end_foffset = foffset + len; |
2290 | if (flags != UDF_EXT_REDIRECT) | | 2290 | if (flags != UDF_EXT_REDIRECT) |
2291 | foffset = end_foffset; | | 2291 | foffset = end_foffset; |
2292 | | | 2292 | |
2293 | slot++; | | 2293 | slot++; |
2294 | } | | 2294 | } |
2295 | /* at end of adslots */ | | 2295 | /* at end of adslots */ |
2296 | | | 2296 | |
2297 | /* special case if the old size was zero, then there is no last slot */ | | 2297 | /* special case if the old size was zero, then there is no last slot */ |
2298 | if (old_size == 0) { | | 2298 | if (old_size == 0) { |
2299 | c_ad.len = udf_rw32(0 | UDF_EXT_FREE); | | 2299 | c_ad.len = udf_rw32(0 | UDF_EXT_FREE); |
2300 | c_ad.loc.part_num = udf_rw16(0); /* not relevant */ | | 2300 | c_ad.loc.part_num = udf_rw16(0); /* not relevant */ |
2301 | c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ | | 2301 | c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ |
2302 | } else { | | 2302 | } else { |
2303 | /* refetch last slot */ | | 2303 | /* refetch last slot */ |
2304 | slot--; | | 2304 | slot--; |
2305 | udf_get_adslot(udf_node, slot, &c_ad, &eof); | | 2305 | udf_get_adslot(udf_node, slot, &c_ad, &eof); |
2306 | } | | 2306 | } |
2307 | } | | 2307 | } |
2308 | | | 2308 | |
2309 | /* | | 2309 | /* |
2310 | * If the length of the last slot is not a multiple of lb_size, adjust | | 2310 | * If the length of the last slot is not a multiple of lb_size, adjust |
2311 | * length so that it is; don't forget to adjust `append_len'! relevant for | | 2311 | * length so that it is; don't forget to adjust `append_len'! relevant for |
2312 | * extending existing files | | 2312 | * extending existing files |
2313 | */ | | 2313 | */ |
2314 | len = udf_rw32(c_ad.len); | | 2314 | len = udf_rw32(c_ad.len); |
2315 | flags = UDF_EXT_FLAGS(len); | | 2315 | flags = UDF_EXT_FLAGS(len); |
2316 | len = UDF_EXT_LEN(len); | | 2316 | len = UDF_EXT_LEN(len); |
2317 | | | 2317 | |
2318 | lastblock_grow = 0; | | 2318 | lastblock_grow = 0; |
2319 | if (len % lb_size > 0) { | | 2319 | if (len % lb_size > 0) { |
2320 | lastblock_grow = lb_size - (len % lb_size); | | 2320 | lastblock_grow = lb_size - (len % lb_size); |
2321 | lastblock_grow = MIN(size_diff, lastblock_grow); | | 2321 | lastblock_grow = MIN(size_diff, lastblock_grow); |
2322 | len += lastblock_grow; | | 2322 | len += lastblock_grow; |
2323 | c_ad.len = udf_rw32(len | flags); | | 2323 | c_ad.len = udf_rw32(len | flags); |
2324 | | | 2324 | |
2325 | /* TODO zero appened space in buffer! */ | | 2325 | /* TODO zero appened space in buffer! */ |
2326 | /* using uvm_vnp_zerorange(vp, old_size, new_size - old_size); ? */ | | 2326 | /* using uvm_vnp_zerorange(vp, old_size, new_size - old_size); ? */ |
2327 | } | | 2327 | } |
2328 | memset(&s_ad, 0, sizeof(struct long_ad)); | | 2328 | memset(&s_ad, 0, sizeof(struct long_ad)); |
2329 | | | 2329 | |
2330 | /* size_diff can be bigger than allowed, so grow in chunks */ | | 2330 | /* size_diff can be bigger than allowed, so grow in chunks */ |
2331 | append_len = size_diff - lastblock_grow; | | 2331 | append_len = size_diff - lastblock_grow; |
2332 | while (append_len > 0) { | | 2332 | while (append_len > 0) { |
2333 | chunk = MIN(append_len, max_len); | | 2333 | chunk = MIN(append_len, max_len); |
2334 | s_ad.len = udf_rw32(chunk | UDF_EXT_FREE); | | 2334 | s_ad.len = udf_rw32(chunk | UDF_EXT_FREE); |
2335 | s_ad.loc.part_num = udf_rw16(0); | | 2335 | s_ad.loc.part_num = udf_rw16(0); |
2336 | s_ad.loc.lb_num = udf_rw32(0); | | 2336 | s_ad.loc.lb_num = udf_rw32(0); |
2337 | | | 2337 | |
2338 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { | | 2338 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { |
2339 | /* not mergable (anymore) */ | | 2339 | /* not mergable (anymore) */ |
2340 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2340 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2341 | if (error) | | 2341 | if (error) |
2342 | goto errorout; | | 2342 | goto errorout; |
2343 | slot++; | | 2343 | slot++; |
2344 | c_ad = s_ad; | | 2344 | c_ad = s_ad; |
2345 | memset(&s_ad, 0, sizeof(struct long_ad)); | | 2345 | memset(&s_ad, 0, sizeof(struct long_ad)); |
2346 | } | | 2346 | } |
2347 | append_len -= chunk; | | 2347 | append_len -= chunk; |
2348 | } | | 2348 | } |
2349 | | | 2349 | |
2350 | /* if there is a rest piece in the accumulator, append it */ | | 2350 | /* if there is a rest piece in the accumulator, append it */ |
2351 | if (UDF_EXT_LEN(udf_rw32(c_ad.len)) > 0) { | | 2351 | if (UDF_EXT_LEN(udf_rw32(c_ad.len)) > 0) { |
2352 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2352 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2353 | if (error) | | 2353 | if (error) |
2354 | goto errorout; | | 2354 | goto errorout; |
2355 | slot++; | | 2355 | slot++; |
2356 | } | | 2356 | } |
2357 | | | 2357 | |
2358 | /* if there is a rest piece that didn't fit, append it */ | | 2358 | /* if there is a rest piece that didn't fit, append it */ |
2359 | if (UDF_EXT_LEN(udf_rw32(s_ad.len)) > 0) { | | 2359 | if (UDF_EXT_LEN(udf_rw32(s_ad.len)) > 0) { |
2360 | error = udf_append_adslot(udf_node, &slot, &s_ad); | | 2360 | error = udf_append_adslot(udf_node, &slot, &s_ad); |
2361 | if (error) | | 2361 | if (error) |
2362 | goto errorout; | | 2362 | goto errorout; |
2363 | slot++; | | 2363 | slot++; |
2364 | } | | 2364 | } |
2365 | | | 2365 | |
2366 | inflen += size_diff; | | 2366 | inflen += size_diff; |
2367 | objsize += size_diff; | | 2367 | objsize += size_diff; |
2368 | if (fe) { | | 2368 | if (fe) { |
2369 | fe->inf_len = udf_rw64(inflen); | | 2369 | fe->inf_len = udf_rw64(inflen); |
2370 | } else { | | 2370 | } else { |
2371 | efe->inf_len = udf_rw64(inflen); | | 2371 | efe->inf_len = udf_rw64(inflen); |
2372 | efe->obj_size = udf_rw64(objsize); | | 2372 | efe->obj_size = udf_rw64(objsize); |
2373 | } | | 2373 | } |
2374 | error = 0; | | 2374 | error = 0; |
2375 | | | 2375 | |
2376 | if (evacuated_data) { | | 2376 | if (evacuated_data) { |
2377 | /* set new write size for uvm */ | | 2377 | /* set new write size for uvm */ |
2378 | uvm_vnp_setwritesize(vp, old_size); | | 2378 | uvm_vnp_setwritesize(vp, old_size); |
2379 | | | 2379 | |
2380 | /* write out evacuated data */ | | 2380 | /* write out evacuated data */ |
2381 | error = vn_rdwr(UIO_WRITE, udf_node->vnode, | | 2381 | error = vn_rdwr(UIO_WRITE, udf_node->vnode, |
2382 | evacuated_data, old_size, 0, | | 2382 | evacuated_data, old_size, 0, |
2383 | UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, | | 2383 | UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, |
2384 | FSCRED, NULL, NULL); | | 2384 | FSCRED, NULL, NULL); |
2385 | uvm_vnp_setsize(vp, old_size); | | 2385 | uvm_vnp_setsize(vp, old_size); |
2386 | } | | 2386 | } |
2387 | | | 2387 | |
2388 | errorout: | | 2388 | errorout: |
2389 | if (evacuated_data) | | 2389 | if (evacuated_data) |
2390 | free(evacuated_data, M_UDFTEMP); | | 2390 | free(evacuated_data, M_UDFTEMP); |
2391 | | | 2391 | |
2392 | udf_count_alloc_exts(udf_node); | | 2392 | udf_count_alloc_exts(udf_node); |
2393 | | | 2393 | |
2394 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2394 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2395 | UDF_UNLOCK_NODE(udf_node, 0); | | 2395 | UDF_UNLOCK_NODE(udf_node, 0); |
2396 | | | 2396 | |
2397 | KASSERT(new_inflen == orig_inflen + size_diff); | | 2397 | KASSERT(new_inflen == orig_inflen + size_diff); |
2398 | KASSERT(new_lbrec == orig_lbrec); | | 2398 | KASSERT(new_lbrec == orig_lbrec); |
2399 | | | 2399 | |
2400 | return error; | | 2400 | return error; |
2401 | } | | 2401 | } |
2402 | | | 2402 | |
2403 | /* --------------------------------------------------------------------- */ | | 2403 | /* --------------------------------------------------------------------- */ |
2404 | | | 2404 | |
2405 | int | | 2405 | int |
2406 | udf_shrink_node(struct udf_node *udf_node, uint64_t new_size) | | 2406 | udf_shrink_node(struct udf_node *udf_node, uint64_t new_size) |
2407 | { | | 2407 | { |
2408 | struct vnode *vp = udf_node->vnode; | | 2408 | struct vnode *vp = udf_node->vnode; |
2409 | struct udf_mount *ump = udf_node->ump; | | 2409 | struct udf_mount *ump = udf_node->ump; |
2410 | struct file_entry *fe; | | 2410 | struct file_entry *fe; |
2411 | struct extfile_entry *efe; | | 2411 | struct extfile_entry *efe; |
2412 | struct icb_tag *icbtag; | | 2412 | struct icb_tag *icbtag; |
2413 | struct long_ad c_ad, s_ad, *node_ad_cpy; | | 2413 | struct long_ad c_ad, s_ad, *node_ad_cpy; |
2414 | uint64_t size_diff, old_size, inflen, objsize; | | 2414 | uint64_t size_diff, old_size, inflen, objsize; |
2415 | uint64_t foffset, end_foffset; | | 2415 | uint64_t foffset, end_foffset; |
2416 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; | | 2416 | uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; |
2417 | uint32_t lb_size, dscr_size, crclen; | | 2417 | uint32_t lb_size, dscr_size, crclen; |
2418 | uint32_t slot_offset; | | 2418 | uint32_t slot_offset; |
2419 | uint32_t len, flags, max_len; | | 2419 | uint32_t len, flags, max_len; |
2420 | uint32_t num_lb, lb_num; | | 2420 | uint32_t num_lb, lb_num; |
2421 | uint32_t max_l_ad, l_ad, l_ea; | | 2421 | uint32_t max_l_ad, l_ad, l_ea; |
2422 | uint16_t vpart_num; | | 2422 | uint16_t vpart_num; |
2423 | uint8_t *data_pos; | | 2423 | uint8_t *data_pos; |
2424 | int icbflags, addr_type; | | 2424 | int icbflags, addr_type; |
2425 | int slot, cpy_slot, cpy_slots; | | 2425 | int slot, cpy_slot, cpy_slots; |
2426 | int eof, error; | | 2426 | int eof, error; |
2427 | | | 2427 | |
2428 | DPRINTF(ALLOC, ("udf_shrink_node\n")); | | 2428 | DPRINTF(ALLOC, ("udf_shrink_node\n")); |
2429 | | | 2429 | |
2430 | UDF_LOCK_NODE(udf_node, 0); | | 2430 | UDF_LOCK_NODE(udf_node, 0); |
2431 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); | | 2431 | udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); |
2432 | | | 2432 | |
2433 | lb_size = udf_rw32(ump->logical_vol->lb_size); | | 2433 | lb_size = udf_rw32(ump->logical_vol->lb_size); |
2434 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); | | 2434 | max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); |
2435 | | | 2435 | |
2436 | /* do the work */ | | 2436 | /* do the work */ |
2437 | fe = udf_node->fe; | | 2437 | fe = udf_node->fe; |
2438 | efe = udf_node->efe; | | 2438 | efe = udf_node->efe; |
2439 | if (fe) { | | 2439 | if (fe) { |
2440 | icbtag = &fe->icbtag; | | 2440 | icbtag = &fe->icbtag; |
2441 | inflen = udf_rw64(fe->inf_len); | | 2441 | inflen = udf_rw64(fe->inf_len); |
2442 | objsize = inflen; | | 2442 | objsize = inflen; |
2443 | dscr_size = sizeof(struct file_entry) -1; | | 2443 | dscr_size = sizeof(struct file_entry) -1; |
2444 | l_ea = udf_rw32(fe->l_ea); | | 2444 | l_ea = udf_rw32(fe->l_ea); |
2445 | l_ad = udf_rw32(fe->l_ad); | | 2445 | l_ad = udf_rw32(fe->l_ad); |
2446 | data_pos = (uint8_t *) fe + dscr_size + l_ea; | | 2446 | data_pos = (uint8_t *) fe + dscr_size + l_ea; |
2447 | } else { | | 2447 | } else { |
2448 | icbtag = &efe->icbtag; | | 2448 | icbtag = &efe->icbtag; |
2449 | inflen = udf_rw64(efe->inf_len); | | 2449 | inflen = udf_rw64(efe->inf_len); |
2450 | objsize = udf_rw64(efe->obj_size); | | 2450 | objsize = udf_rw64(efe->obj_size); |
2451 | dscr_size = sizeof(struct extfile_entry) -1; | | 2451 | dscr_size = sizeof(struct extfile_entry) -1; |
2452 | l_ea = udf_rw32(efe->l_ea); | | 2452 | l_ea = udf_rw32(efe->l_ea); |
2453 | l_ad = udf_rw32(efe->l_ad); | | 2453 | l_ad = udf_rw32(efe->l_ad); |
2454 | data_pos = (uint8_t *) efe + dscr_size + l_ea; | | 2454 | data_pos = (uint8_t *) efe + dscr_size + l_ea; |
2455 | } | | 2455 | } |
2456 | max_l_ad = lb_size - dscr_size - l_ea; | | 2456 | max_l_ad = lb_size - dscr_size - l_ea; |
2457 | | | 2457 | |
2458 | icbflags = udf_rw16(icbtag->flags); | | 2458 | icbflags = udf_rw16(icbtag->flags); |
2459 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 2459 | addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
2460 | | | 2460 | |
2461 | old_size = inflen; | | 2461 | old_size = inflen; |
2462 | size_diff = old_size - new_size; | | 2462 | size_diff = old_size - new_size; |
2463 | | | 2463 | |
2464 | DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); | | 2464 | DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); |
2465 | | | 2465 | |
2466 | /* shrink the node to its new size */ | | 2466 | /* shrink the node to its new size */ |
2467 | if (addr_type == UDF_ICB_INTERN_ALLOC) { | | 2467 | if (addr_type == UDF_ICB_INTERN_ALLOC) { |
2468 | /* only reflect size change directly in the node */ | | 2468 | /* only reflect size change directly in the node */ |
2469 | KASSERT(new_size <= max_l_ad); | | 2469 | KASSERT(new_size <= max_l_ad); |
2470 | inflen -= size_diff; | | 2470 | inflen -= size_diff; |
2471 | objsize -= size_diff; | | 2471 | objsize -= size_diff; |
2472 | l_ad -= size_diff; | | 2472 | l_ad -= size_diff; |
2473 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; | | 2473 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; |
2474 | if (fe) { | | 2474 | if (fe) { |
2475 | fe->inf_len = udf_rw64(inflen); | | 2475 | fe->inf_len = udf_rw64(inflen); |
2476 | fe->l_ad = udf_rw32(l_ad); | | 2476 | fe->l_ad = udf_rw32(l_ad); |
2477 | fe->tag.desc_crc_len = udf_rw16(crclen); | | 2477 | fe->tag.desc_crc_len = udf_rw16(crclen); |
2478 | } else { | | 2478 | } else { |
2479 | efe->inf_len = udf_rw64(inflen); | | 2479 | efe->inf_len = udf_rw64(inflen); |
2480 | efe->obj_size = udf_rw64(objsize); | | 2480 | efe->obj_size = udf_rw64(objsize); |
2481 | efe->l_ad = udf_rw32(l_ad); | | 2481 | efe->l_ad = udf_rw32(l_ad); |
2482 | efe->tag.desc_crc_len = udf_rw16(crclen); | | 2482 | efe->tag.desc_crc_len = udf_rw16(crclen); |
2483 | } | | 2483 | } |
2484 | error = 0; | | 2484 | error = 0; |
2485 | | | 2485 | |
2486 | /* clear the space in the descriptor */ | | 2486 | /* clear the space in the descriptor */ |
2487 | KASSERT(old_size > new_size); | | 2487 | KASSERT(old_size > new_size); |
2488 | memset(data_pos + new_size, 0, old_size - new_size); | | 2488 | memset(data_pos + new_size, 0, old_size - new_size); |
2489 | | | 2489 | |
2490 | /* TODO zero appened space in buffer! */ | | 2490 | /* TODO zero appened space in buffer! */ |
2491 | /* using uvm_vnp_zerorange(vp, old_size, old_size - new_size); ? */ | | 2491 | /* using uvm_vnp_zerorange(vp, old_size, old_size - new_size); ? */ |
2492 | | | 2492 | |
2493 | /* set new size for uvm */ | | 2493 | /* set new size for uvm */ |
2494 | uvm_vnp_setsize(vp, new_size); | | 2494 | uvm_vnp_setsize(vp, new_size); |
2495 | | | 2495 | |
2496 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2496 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2497 | UDF_UNLOCK_NODE(udf_node, 0); | | 2497 | UDF_UNLOCK_NODE(udf_node, 0); |
2498 | | | 2498 | |
2499 | KASSERT(new_inflen == orig_inflen - size_diff); | | 2499 | KASSERT(new_inflen == orig_inflen - size_diff); |
2500 | KASSERT(new_lbrec == orig_lbrec); | | 2500 | KASSERT(new_lbrec == orig_lbrec); |
2501 | KASSERT(new_lbrec == 0); | | 2501 | KASSERT(new_lbrec == 0); |
2502 | | | 2502 | |
2503 | return 0; | | 2503 | return 0; |
2504 | } | | 2504 | } |
2505 | | | 2505 | |
2506 | /* setup node cleanup extents copy space */ | | 2506 | /* setup node cleanup extents copy space */ |
2507 | node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS, | | 2507 | node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS, |
2508 | M_UDFMNT, M_WAITOK); | | 2508 | M_UDFMNT, M_WAITOK); |
2509 | memset(node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS); | | 2509 | memset(node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS); |
2510 | | | 2510 | |
2511 | /* | | 2511 | /* |
2512 | * Shrink the node by releasing the allocations and truncate the last | | 2512 | * Shrink the node by releasing the allocations and truncate the last |
2513 | * allocation to the new size. If the new size fits into the | | 2513 | * allocation to the new size. If the new size fits into the |
2514 | * allocation descriptor itself, transform it into an | | 2514 | * allocation descriptor itself, transform it into an |
2515 | * UDF_ICB_INTERN_ALLOC. | | 2515 | * UDF_ICB_INTERN_ALLOC. |
2516 | */ | | 2516 | */ |
2517 | slot = 0; | | 2517 | slot = 0; |
2518 | cpy_slot = 0; | | 2518 | cpy_slot = 0; |
2519 | foffset = 0; | | 2519 | foffset = 0; |
2520 | | | 2520 | |
2521 | /* 1) copy till first overlap piece to the rewrite buffer */ | | 2521 | /* 1) copy till first overlap piece to the rewrite buffer */ |
2522 | for (;;) { | | 2522 | for (;;) { |
2523 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 2523 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
2524 | if (eof) { | | 2524 | if (eof) { |
2525 | DPRINTF(WRITE, | | 2525 | DPRINTF(WRITE, |
2526 | ("Shrink node failed: " | | 2526 | ("Shrink node failed: " |
2527 | "encountered EOF\n")); | | 2527 | "encountered EOF\n")); |
2528 | error = EINVAL; | | 2528 | error = EINVAL; |
2529 | goto errorout; /* panic? */ | | 2529 | goto errorout; /* panic? */ |
2530 | } | | 2530 | } |
2531 | len = udf_rw32(s_ad.len); | | 2531 | len = udf_rw32(s_ad.len); |
2532 | flags = UDF_EXT_FLAGS(len); | | 2532 | flags = UDF_EXT_FLAGS(len); |
2533 | len = UDF_EXT_LEN(len); | | 2533 | len = UDF_EXT_LEN(len); |
2534 | | | 2534 | |
2535 | if (flags == UDF_EXT_REDIRECT) { | | 2535 | if (flags == UDF_EXT_REDIRECT) { |
2536 | slot++; | | 2536 | slot++; |
2537 | continue; | | 2537 | continue; |
2538 | } | | 2538 | } |
2539 | | | 2539 | |
2540 | end_foffset = foffset + len; | | 2540 | end_foffset = foffset + len; |
2541 | if (end_foffset > new_size) | | 2541 | if (end_foffset > new_size) |
2542 | break; /* found */ | | 2542 | break; /* found */ |
2543 | | | 2543 | |
2544 | node_ad_cpy[cpy_slot++] = s_ad; | | 2544 | node_ad_cpy[cpy_slot++] = s_ad; |
2545 | | | 2545 | |
2546 | DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " | | 2546 | DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " |
2547 | "-> stack\n", | | 2547 | "-> stack\n", |
2548 | udf_rw16(s_ad.loc.part_num), | | 2548 | udf_rw16(s_ad.loc.part_num), |
2549 | udf_rw32(s_ad.loc.lb_num), | | 2549 | udf_rw32(s_ad.loc.lb_num), |
2550 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2550 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2551 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2551 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2552 | | | 2552 | |
2553 | foffset = end_foffset; | | 2553 | foffset = end_foffset; |
2554 | slot++; | | 2554 | slot++; |
2555 | } | | 2555 | } |
2556 | slot_offset = new_size - foffset; | | 2556 | slot_offset = new_size - foffset; |
2557 | | | 2557 | |
2558 | /* 2) trunc overlapping slot at overlap and copy it */ | | 2558 | /* 2) trunc overlapping slot at overlap and copy it */ |
2559 | if (slot_offset > 0) { | | 2559 | if (slot_offset > 0) { |
2560 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 2560 | lb_num = udf_rw32(s_ad.loc.lb_num); |
2561 | vpart_num = udf_rw16(s_ad.loc.part_num); | | 2561 | vpart_num = udf_rw16(s_ad.loc.part_num); |
2562 | | | 2562 | |
2563 | if (flags == UDF_EXT_ALLOCATED) { | | 2563 | if (flags == UDF_EXT_ALLOCATED) { |
2564 | /* note: round DOWN on num_lb */ | | 2564 | /* note: round DOWN on num_lb */ |
2565 | lb_num += (slot_offset + lb_size -1) / lb_size; | | 2565 | lb_num += (slot_offset + lb_size -1) / lb_size; |
2566 | num_lb = (len - slot_offset) / lb_size; | | 2566 | num_lb = (len - slot_offset) / lb_size; |
2567 | | | 2567 | |
2568 | udf_free_allocated_space(ump, lb_num, vpart_num, num_lb); | | 2568 | udf_free_allocated_space(ump, lb_num, vpart_num, num_lb); |
2569 | } | | 2569 | } |
2570 | | | 2570 | |
2571 | s_ad.len = udf_rw32(slot_offset | flags); | | 2571 | s_ad.len = udf_rw32(slot_offset | flags); |
2572 | node_ad_cpy[cpy_slot++] = s_ad; | | 2572 | node_ad_cpy[cpy_slot++] = s_ad; |
2573 | slot++; | | 2573 | slot++; |
2574 | | | 2574 | |
2575 | DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " | | 2575 | DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " |
2576 | "-> stack\n", | | 2576 | "-> stack\n", |
2577 | udf_rw16(s_ad.loc.part_num), | | 2577 | udf_rw16(s_ad.loc.part_num), |
2578 | udf_rw32(s_ad.loc.lb_num), | | 2578 | udf_rw32(s_ad.loc.lb_num), |
2579 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2579 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2580 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2580 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2581 | } | | 2581 | } |
2582 | | | 2582 | |
2583 | /* 3) delete remainder */ | | 2583 | /* 3) delete remainder */ |
2584 | for (;;) { | | 2584 | for (;;) { |
2585 | udf_get_adslot(udf_node, slot, &s_ad, &eof); | | 2585 | udf_get_adslot(udf_node, slot, &s_ad, &eof); |
2586 | if (eof) | | 2586 | if (eof) |
2587 | break; | | 2587 | break; |
2588 | | | 2588 | |
2589 | len = udf_rw32(s_ad.len); | | 2589 | len = udf_rw32(s_ad.len); |
2590 | flags = UDF_EXT_FLAGS(len); | | 2590 | flags = UDF_EXT_FLAGS(len); |
2591 | len = UDF_EXT_LEN(len); | | 2591 | len = UDF_EXT_LEN(len); |
2592 | | | 2592 | |
2593 | if (flags == UDF_EXT_REDIRECT) { | | 2593 | if (flags == UDF_EXT_REDIRECT) { |
2594 | slot++; | | 2594 | slot++; |
2595 | continue; | | 2595 | continue; |
2596 | } | | 2596 | } |
2597 | | | 2597 | |
2598 | DPRINTF(ALLOC, ("\t3: delete remainder " | | 2598 | DPRINTF(ALLOC, ("\t3: delete remainder " |
2599 | "vp %d lb %d, len %d, flags %d\n", | | 2599 | "vp %d lb %d, len %d, flags %d\n", |
2600 | udf_rw16(s_ad.loc.part_num), | | 2600 | udf_rw16(s_ad.loc.part_num), |
2601 | udf_rw32(s_ad.loc.lb_num), | | 2601 | udf_rw32(s_ad.loc.lb_num), |
2602 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2602 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2603 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2603 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2604 | | | 2604 | |
2605 | if (flags == UDF_EXT_ALLOCATED) { | | 2605 | if (flags == UDF_EXT_ALLOCATED) { |
2606 | lb_num = udf_rw32(s_ad.loc.lb_num); | | 2606 | lb_num = udf_rw32(s_ad.loc.lb_num); |
2607 | vpart_num = udf_rw16(s_ad.loc.part_num); | | 2607 | vpart_num = udf_rw16(s_ad.loc.part_num); |
2608 | num_lb = (len + lb_size - 1) / lb_size; | | 2608 | num_lb = (len + lb_size - 1) / lb_size; |
2609 | | | 2609 | |
2610 | udf_free_allocated_space(ump, lb_num, vpart_num, | | 2610 | udf_free_allocated_space(ump, lb_num, vpart_num, |
2611 | num_lb); | | 2611 | num_lb); |
2612 | } | | 2612 | } |
2613 | | | 2613 | |
2614 | slot++; | | 2614 | slot++; |
2615 | } | | 2615 | } |
2616 | | | 2616 | |
2617 | /* 4) if it will fit into the descriptor then convert */ | | 2617 | /* 4) if it will fit into the descriptor then convert */ |
2618 | if (new_size < max_l_ad) { | | 2618 | if (new_size < max_l_ad) { |
2619 | /* | | 2619 | /* |
2620 | * resque/evacuate old piece by reading it in, and convert it | | 2620 | * resque/evacuate old piece by reading it in, and convert it |
2621 | * to internal alloc. | | 2621 | * to internal alloc. |
2622 | */ | | 2622 | */ |
2623 | if (new_size == 0) { | | 2623 | if (new_size == 0) { |
2624 | /* XXX/TODO only for zero sizing now */ | | 2624 | /* XXX/TODO only for zero sizing now */ |
2625 | udf_wipe_adslots(udf_node); | | 2625 | udf_wipe_adslots(udf_node); |
2626 | | | 2626 | |
2627 | icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; | | 2627 | icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; |
2628 | icbflags |= UDF_ICB_INTERN_ALLOC; | | 2628 | icbflags |= UDF_ICB_INTERN_ALLOC; |
2629 | icbtag->flags = udf_rw16(icbflags); | | 2629 | icbtag->flags = udf_rw16(icbflags); |
2630 | | | 2630 | |
2631 | inflen -= size_diff; KASSERT(inflen == 0); | | 2631 | inflen -= size_diff; KASSERT(inflen == 0); |
2632 | objsize -= size_diff; | | 2632 | objsize -= size_diff; |
2633 | l_ad = new_size; | | 2633 | l_ad = new_size; |
2634 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; | | 2634 | crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; |
2635 | if (fe) { | | 2635 | if (fe) { |
2636 | fe->inf_len = udf_rw64(inflen); | | 2636 | fe->inf_len = udf_rw64(inflen); |
2637 | fe->l_ad = udf_rw32(l_ad); | | 2637 | fe->l_ad = udf_rw32(l_ad); |
2638 | fe->tag.desc_crc_len = udf_rw16(crclen); | | 2638 | fe->tag.desc_crc_len = udf_rw16(crclen); |
2639 | } else { | | 2639 | } else { |
2640 | efe->inf_len = udf_rw64(inflen); | | 2640 | efe->inf_len = udf_rw64(inflen); |
2641 | efe->obj_size = udf_rw64(objsize); | | 2641 | efe->obj_size = udf_rw64(objsize); |
2642 | efe->l_ad = udf_rw32(l_ad); | | 2642 | efe->l_ad = udf_rw32(l_ad); |
2643 | efe->tag.desc_crc_len = udf_rw16(crclen); | | 2643 | efe->tag.desc_crc_len = udf_rw16(crclen); |
2644 | } | | 2644 | } |
2645 | /* eventually copy in evacuated piece */ | | 2645 | /* eventually copy in evacuated piece */ |
2646 | /* set new size for uvm */ | | 2646 | /* set new size for uvm */ |
2647 | uvm_vnp_setsize(vp, new_size); | | 2647 | uvm_vnp_setsize(vp, new_size); |
2648 | | | 2648 | |
2649 | free(node_ad_cpy, M_UDFMNT); | | 2649 | free(node_ad_cpy, M_UDFMNT); |
2650 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2650 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2651 | | | 2651 | |
2652 | UDF_UNLOCK_NODE(udf_node, 0); | | 2652 | UDF_UNLOCK_NODE(udf_node, 0); |
2653 | | | 2653 | |
2654 | KASSERT(new_inflen == orig_inflen - size_diff); | | 2654 | KASSERT(new_inflen == orig_inflen - size_diff); |
2655 | KASSERT(new_inflen == 0); | | 2655 | KASSERT(new_inflen == 0); |
2656 | KASSERT(new_lbrec == 0); | | 2656 | KASSERT(new_lbrec == 0); |
2657 | | | 2657 | |
2658 | return 0; | | 2658 | return 0; |
2659 | } | | 2659 | } |
2660 | | | 2660 | |
2661 | printf("UDF_SHRINK_NODE: could convert to internal alloc!\n"); | | 2661 | printf("UDF_SHRINK_NODE: could convert to internal alloc!\n"); |
2662 | } | | 2662 | } |
2663 | | | 2663 | |
2664 | /* 5) reset node descriptors */ | | 2664 | /* 5) reset node descriptors */ |
2665 | udf_wipe_adslots(udf_node); | | 2665 | udf_wipe_adslots(udf_node); |
2666 | | | 2666 | |
2667 | /* 6) copy back extents; merge when possible. Recounting on the fly */ | | 2667 | /* 6) copy back extents; merge when possible. Recounting on the fly */ |
2668 | cpy_slots = cpy_slot; | | 2668 | cpy_slots = cpy_slot; |
2669 | | | 2669 | |
2670 | c_ad = node_ad_cpy[0]; | | 2670 | c_ad = node_ad_cpy[0]; |
2671 | slot = 0; | | 2671 | slot = 0; |
2672 | for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { | | 2672 | for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { |
2673 | s_ad = node_ad_cpy[cpy_slot]; | | 2673 | s_ad = node_ad_cpy[cpy_slot]; |
2674 | | | 2674 | |
2675 | DPRINTF(ALLOC, ("\t6: stack -> got mapping vp %d " | | 2675 | DPRINTF(ALLOC, ("\t6: stack -> got mapping vp %d " |
2676 | "lb %d, len %d, flags %d\n", | | 2676 | "lb %d, len %d, flags %d\n", |
2677 | udf_rw16(s_ad.loc.part_num), | | 2677 | udf_rw16(s_ad.loc.part_num), |
2678 | udf_rw32(s_ad.loc.lb_num), | | 2678 | udf_rw32(s_ad.loc.lb_num), |
2679 | UDF_EXT_LEN(udf_rw32(s_ad.len)), | | 2679 | UDF_EXT_LEN(udf_rw32(s_ad.len)), |
2680 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); | | 2680 | UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); |
2681 | | | 2681 | |
2682 | /* see if we can merge */ | | 2682 | /* see if we can merge */ |
2683 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { | | 2683 | if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { |
2684 | /* not mergable (anymore) */ | | 2684 | /* not mergable (anymore) */ |
2685 | DPRINTF(ALLOC, ("\t6: appending vp %d lb %d, " | | 2685 | DPRINTF(ALLOC, ("\t6: appending vp %d lb %d, " |
2686 | "len %d, flags %d\n", | | 2686 | "len %d, flags %d\n", |
2687 | udf_rw16(c_ad.loc.part_num), | | 2687 | udf_rw16(c_ad.loc.part_num), |
2688 | udf_rw32(c_ad.loc.lb_num), | | 2688 | udf_rw32(c_ad.loc.lb_num), |
2689 | UDF_EXT_LEN(udf_rw32(c_ad.len)), | | 2689 | UDF_EXT_LEN(udf_rw32(c_ad.len)), |
2690 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); | | 2690 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); |
2691 | | | 2691 | |
2692 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2692 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2693 | if (error) | | 2693 | if (error) |
2694 | goto errorout; /* panic? */ | | 2694 | goto errorout; /* panic? */ |
2695 | c_ad = s_ad; | | 2695 | c_ad = s_ad; |
2696 | slot++; | | 2696 | slot++; |
2697 | } | | 2697 | } |
2698 | } | | 2698 | } |
2699 | | | 2699 | |
2700 | /* 7) push rest slot (if any) */ | | 2700 | /* 7) push rest slot (if any) */ |
2701 | if (UDF_EXT_LEN(c_ad.len) > 0) { | | 2701 | if (UDF_EXT_LEN(c_ad.len) > 0) { |
2702 | DPRINTF(ALLOC, ("\t7: last append vp %d lb %d, " | | 2702 | DPRINTF(ALLOC, ("\t7: last append vp %d lb %d, " |
2703 | "len %d, flags %d\n", | | 2703 | "len %d, flags %d\n", |
2704 | udf_rw16(c_ad.loc.part_num), | | 2704 | udf_rw16(c_ad.loc.part_num), |
2705 | udf_rw32(c_ad.loc.lb_num), | | 2705 | udf_rw32(c_ad.loc.lb_num), |
2706 | UDF_EXT_LEN(udf_rw32(c_ad.len)), | | 2706 | UDF_EXT_LEN(udf_rw32(c_ad.len)), |
2707 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); | | 2707 | UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); |
2708 | | | 2708 | |
2709 | error = udf_append_adslot(udf_node, &slot, &c_ad); | | 2709 | error = udf_append_adslot(udf_node, &slot, &c_ad); |
2710 | if (error) | | 2710 | if (error) |
2711 | goto errorout; /* panic? */ | | 2711 | goto errorout; /* panic? */ |
2712 | ; | | 2712 | ; |
2713 | } | | 2713 | } |
2714 | | | 2714 | |
2715 | inflen -= size_diff; | | 2715 | inflen -= size_diff; |
2716 | objsize -= size_diff; | | 2716 | objsize -= size_diff; |
2717 | if (fe) { | | 2717 | if (fe) { |
2718 | fe->inf_len = udf_rw64(inflen); | | 2718 | fe->inf_len = udf_rw64(inflen); |
2719 | } else { | | 2719 | } else { |
2720 | efe->inf_len = udf_rw64(inflen); | | 2720 | efe->inf_len = udf_rw64(inflen); |
2721 | efe->obj_size = udf_rw64(objsize); | | 2721 | efe->obj_size = udf_rw64(objsize); |
2722 | } | | 2722 | } |
2723 | error = 0; | | 2723 | error = 0; |
2724 | | | 2724 | |
2725 | /* set new size for uvm */ | | 2725 | /* set new size for uvm */ |
2726 | uvm_vnp_setsize(vp, new_size); | | 2726 | uvm_vnp_setsize(vp, new_size); |
2727 | | | 2727 | |
2728 | errorout: | | 2728 | errorout: |
2729 | free(node_ad_cpy, M_UDFMNT); | | 2729 | free(node_ad_cpy, M_UDFMNT); |
2730 | | | 2730 | |
2731 | udf_count_alloc_exts(udf_node); | | 2731 | udf_count_alloc_exts(udf_node); |
2732 | | | 2732 | |
2733 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); | | 2733 | udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); |
2734 | UDF_UNLOCK_NODE(udf_node, 0); | | 2734 | UDF_UNLOCK_NODE(udf_node, 0); |
2735 | | | 2735 | |
2736 | KASSERT(new_inflen == orig_inflen - size_diff); | | 2736 | KASSERT(new_inflen == orig_inflen - size_diff); |
2737 | | | 2737 | |
2738 | return error; | | 2738 | return error; |
2739 | } | | 2739 | } |
2740 | | | 2740 | |