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