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