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