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