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