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