1 /* $NetBSD: udf_allocation.c,v 1.18 2008/08/29 15:04:18 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.18 2008/08/29 15:04:18 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 DPRINTF(PARANOIA, ("XXX : allocate %d, %p, bit %d\n", 831 offset + bit -1, bpos, bit-1)); 832 *bpos &= ~(1 << (bit-1)); 833 lb_num = offset + bit-1; 834 *lmappos++ = lb_num; 835 *num_lb = *num_lb - 1; 836 // offset = (offset & ~7); 837 } 838 } 839 840 if (ismetadata) { 841 bitmap->metadata_pos = offset; 842 } else { 843 bitmap->data_pos = offset; 844 } 845 } 846 847 848 static void 849 udf_bitmap_free(struct udf_bitmap *bitmap, uint32_t lb_num, uint32_t num_lb) 850 { 851 uint32_t offset; 852 uint32_t bit, bitval; 853 uint8_t *bpos; 854 855 offset = lb_num; 856 857 /* starter bits */ 858 bpos = bitmap->bits + offset/8; 859 bit = offset % 8; 860 while ((bit != 0) && (num_lb > 0)) { 861 bitval = (1 << bit); 862 KASSERT((*bpos & bitval) == 0); 863 DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", 864 offset, bpos, bit)); 865 *bpos |= bitval; 866 offset++; num_lb--; 867 bit = (bit + 1) % 8; 868 } 869 if (num_lb == 0) 870 return; 871 872 /* whole bytes */ 873 KASSERT(bit == 0); 874 bpos = bitmap->bits + offset / 8; 875 while (num_lb >= 8) { 876 KASSERT((*bpos == 0)); 877 DPRINTF(PARANOIA, ("XXX : free %d + 8, %p\n", offset, bpos)); 878 *bpos = 255; 879 offset += 8; num_lb -= 8; 880 bpos++; 881 } 882 883 /* stop bits */ 884 KASSERT(num_lb < 8); 885 bit = 0; 886 while (num_lb > 0) { 887 bitval = (1 << bit); 888 KASSERT((*bpos & bitval) == 0); 889 DPRINTF(PARANOIA, ("XXX : free %d, %p, %d\n", 890 offset, bpos, bit)); 891 *bpos |= bitval; 892 offset++; num_lb--; 893 bit = (bit + 1) % 8; 894 } 895 } 896 897 898 /* allocate a contiguous sequence of sectornumbers */ 899 static int 900 udf_allocate_space(struct udf_mount *ump, int udf_c_type, 901 uint16_t vpart_num, uint32_t num_lb, uint64_t *lmapping) 902 { 903 struct mmc_trackinfo *alloc_track, *other_track; 904 struct udf_bitmap *bitmap; 905 struct part_desc *pdesc; 906 struct logvol_int_desc *lvid; 907 uint64_t *lmappos; 908 uint32_t ptov, lb_num, *freepos, free_lbs; 909 int lb_size, alloc_num_lb; 910 int alloc_type, error; 911 int is_node; 912 913 DPRINTF(CALL, ("udf_allocate_space(ctype %d, vpart %d, num_lb %d\n", 914 udf_c_type, vpart_num, num_lb)); 915 mutex_enter(&ump->allocate_mutex); 916 917 lb_size = udf_rw32(ump->logical_vol->lb_size); 918 KASSERT(lb_size == ump->discinfo.sector_size); 919 920 /* XXX TODO check disc space */ 921 922 alloc_type = ump->vtop_alloc[vpart_num]; 923 is_node = (udf_c_type == UDF_C_NODE); 924 925 lmappos = lmapping; 926 error = 0; 927 switch (alloc_type) { 928 case UDF_ALLOC_VAT : 929 /* search empty slot in VAT file */ 930 KASSERT(num_lb == 1); 931 error = udf_search_free_vatloc(ump, &lb_num); 932 if (!error) 933 *lmappos = lb_num; 934 break; 935 case UDF_ALLOC_SEQUENTIAL : 936 /* sequential allocation on recordable media */ 937 /* get partition backing up this vpart_num_num */ 938 pdesc = ump->partitions[ump->vtop[vpart_num]]; 939 940 /* calculate offset from physical base partition */ 941 ptov = udf_rw32(pdesc->start_loc); 942 943 /* get our track descriptors */ 944 if (vpart_num == ump->node_part) { 945 alloc_track = &ump->metadata_track; 946 other_track = &ump->data_track; 947 } else { 948 alloc_track = &ump->data_track; 949 other_track = &ump->metadata_track; 950 } 951 952 /* allocate */ 953 for (lb_num = 0; lb_num < num_lb; lb_num++) { 954 *lmappos++ = alloc_track->next_writable - ptov; 955 alloc_track->next_writable++; 956 alloc_track->free_blocks--; 957 } 958 959 /* keep other track up-to-date */ 960 if (alloc_track->tracknr == other_track->tracknr) 961 memcpy(other_track, alloc_track, 962 sizeof(struct mmc_trackinfo)); 963 break; 964 case UDF_ALLOC_SPACEMAP : 965 /* try to allocate on unallocated bits */ 966 alloc_num_lb = num_lb; 967 bitmap = &ump->part_unalloc_bits[vpart_num]; 968 udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); 969 ump->lvclose |= UDF_WRITE_PART_BITMAPS; 970 971 /* have we allocated all? */ 972 if (alloc_num_lb) { 973 /* TODO convert freed to unalloc and try again */ 974 /* free allocated piece for now */ 975 lmappos = lmapping; 976 for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { 977 udf_bitmap_free(bitmap, *lmappos++, 1); 978 } 979 error = ENOSPC; 980 } 981 if (!error) { 982 /* adjust freecount */ 983 lvid = ump->logvol_integrity; 984 freepos = &lvid->tables[0] + vpart_num; 985 free_lbs = udf_rw32(*freepos); 986 *freepos = udf_rw32(free_lbs - num_lb); 987 } 988 break; 989 case UDF_ALLOC_METABITMAP : /* UDF 2.50, 2.60 BluRay-RE */ 990 /* allocate on metadata unallocated bits */ 991 alloc_num_lb = num_lb; 992 bitmap = &ump->metadata_unalloc_bits; 993 udf_bitmap_allocate(bitmap, is_node, &alloc_num_lb, lmappos); 994 ump->lvclose |= UDF_WRITE_PART_BITMAPS; 995 996 /* have we allocated all? */ 997 if (alloc_num_lb) { 998 /* YIKES! TODO we need to extend the metadata partition */ 999 /* free allocated piece for now */ 1000 lmappos = lmapping; 1001 for (lb_num=0; lb_num < num_lb-alloc_num_lb; lb_num++) { 1002 udf_bitmap_free(bitmap, *lmappos++, 1); 1003 } 1004 error = ENOSPC; 1005 } 1006 if (!error) { 1007 /* adjust freecount */ 1008 lvid = ump->logvol_integrity; 1009 freepos = &lvid->tables[0] + vpart_num; 1010 free_lbs = udf_rw32(*freepos); 1011 *freepos = udf_rw32(free_lbs - num_lb); 1012 } 1013 break; 1014 case UDF_ALLOC_METASEQUENTIAL : /* UDF 2.60 BluRay-R */ 1015 case UDF_ALLOC_RELAXEDSEQUENTIAL : /* UDF 2.50/~meta BluRay-R */ 1016 printf("ALERT: udf_allocate_space : allocation %d " 1017 "not implemented yet!\n", alloc_type); 1018 /* TODO implement, doesn't have to be contiguous */ 1019 error = ENOSPC; 1020 break; 1021 } 1022 1023 #ifdef DEBUG 1024 if (udf_verbose & UDF_DEBUG_ALLOC) { 1025 lmappos = lmapping; 1026 printf("udf_allocate_space, allocated logical lba :\n"); 1027 for (lb_num = 0; lb_num < num_lb; lb_num++) { 1028 printf("%s %"PRIu64",", (lb_num > 0)?",":"", 1029 *lmappos++); 1030 } 1031 printf("\n"); 1032 } 1033 #endif 1034 mutex_exit(&ump->allocate_mutex); 1035 1036 return error; 1037 } 1038 1039 /* --------------------------------------------------------------------- */ 1040 1041 void 1042 udf_free_allocated_space(struct udf_mount *ump, uint32_t lb_num, 1043 uint16_t vpart_num, uint32_t num_lb) 1044 { 1045 struct udf_bitmap *bitmap; 1046 struct part_desc *pdesc; 1047 struct logvol_int_desc *lvid; 1048 uint32_t ptov, lb_map, udf_rw32_lbmap; 1049 uint32_t *freepos, free_lbs; 1050 int phys_part; 1051 int error; 1052 1053 DPRINTF(ALLOC, ("udf_free_allocated_space: freeing virt lbnum %d " 1054 "part %d + %d sect\n", lb_num, vpart_num, num_lb)); 1055 1056 /* no use freeing zero length */ 1057 if (num_lb == 0) 1058 return; 1059 1060 mutex_enter(&ump->allocate_mutex); 1061 1062 /* get partition backing up this vpart_num */ 1063 pdesc = ump->partitions[ump->vtop[vpart_num]]; 1064 1065 switch (ump->vtop_tp[vpart_num]) { 1066 case UDF_VTOP_TYPE_PHYS : 1067 case UDF_VTOP_TYPE_SPARABLE : 1068 /* free space to freed or unallocated space bitmap */ 1069 ptov = udf_rw32(pdesc->start_loc); 1070 phys_part = ump->vtop[vpart_num]; 1071 1072 /* first try freed space bitmap */ 1073 bitmap = &ump->part_freed_bits[phys_part]; 1074 1075 /* if not defined, use unallocated bitmap */ 1076 if (bitmap->bits == NULL) 1077 bitmap = &ump->part_unalloc_bits[phys_part]; 1078 1079 /* if no bitmaps are defined, bail out; XXX OK? */ 1080 if (bitmap->bits == NULL) 1081 break; 1082 1083 /* free bits if its defined */ 1084 KASSERT(bitmap->bits); 1085 ump->lvclose |= UDF_WRITE_PART_BITMAPS; 1086 udf_bitmap_free(bitmap, lb_num, num_lb); 1087 1088 /* adjust freecount */ 1089 lvid = ump->logvol_integrity; 1090 freepos = &lvid->tables[0] + vpart_num; 1091 free_lbs = udf_rw32(*freepos); 1092 *freepos = udf_rw32(free_lbs + num_lb); 1093 break; 1094 case UDF_VTOP_TYPE_VIRT : 1095 /* free this VAT entry */ 1096 KASSERT(num_lb == 1); 1097 1098 lb_map = 0xffffffff; 1099 udf_rw32_lbmap = udf_rw32(lb_map); 1100 error = udf_vat_write(ump->vat_node, 1101 (uint8_t *) &udf_rw32_lbmap, 4, 1102 ump->vat_offset + lb_num * 4); 1103 KASSERT(error == 0); 1104 ump->vat_last_free_lb = MIN(ump->vat_last_free_lb, lb_num); 1105 break; 1106 case UDF_VTOP_TYPE_META : 1107 /* free space in the metadata bitmap */ 1108 bitmap = &ump->metadata_unalloc_bits; 1109 KASSERT(bitmap->bits); 1110 1111 ump->lvclose |= UDF_WRITE_PART_BITMAPS; 1112 udf_bitmap_free(bitmap, lb_num, num_lb); 1113 1114 /* adjust freecount */ 1115 lvid = ump->logvol_integrity; 1116 freepos = &lvid->tables[0] + vpart_num; 1117 free_lbs = udf_rw32(*freepos); 1118 *freepos = udf_rw32(free_lbs + num_lb); 1119 break; 1120 default: 1121 printf("ALERT: udf_free_allocated_space : allocation %d " 1122 "not implemented yet!\n", ump->vtop_tp[vpart_num]); 1123 break; 1124 } 1125 1126 mutex_exit(&ump->allocate_mutex); 1127 } 1128 1129 /* --------------------------------------------------------------------- */ 1130 1131 int 1132 udf_pre_allocate_space(struct udf_mount *ump, int udf_c_type, 1133 uint32_t num_lb, uint16_t vpartnr, uint64_t *lmapping) 1134 { 1135 /* TODO properly maintain uncomitted_lb per partition */ 1136 1137 /* reserve size for VAT allocated data */ 1138 if (ump->vtop_alloc[vpartnr] == UDF_ALLOC_VAT) { 1139 mutex_enter(&ump->allocate_mutex); 1140 ump->uncomitted_lb += num_lb; 1141 mutex_exit(&ump->allocate_mutex); 1142 } 1143 1144 return udf_allocate_space(ump, udf_c_type, vpartnr, num_lb, lmapping); 1145 } 1146 1147 /* --------------------------------------------------------------------- */ 1148 1149 /* 1150 * Allocate a buf on disc for direct write out. The space doesn't have to be 1151 * contiguous as the caller takes care of this. 1152 */ 1153 1154 void 1155 udf_late_allocate_buf(struct udf_mount *ump, struct buf *buf, 1156 uint64_t *lmapping, struct long_ad *node_ad_cpy, uint16_t *vpart_nump) 1157 { 1158 struct udf_node *udf_node = VTOI(buf->b_vp); 1159 int lb_size, blks, udf_c_type; 1160 int vpart_num, num_lb; 1161 int error, s; 1162 1163 /* 1164 * for each sector in the buf, allocate a sector on disc and record 1165 * its position in the provided mapping array. 1166 * 1167 * If its userdata or FIDs, record its location in its node. 1168 */ 1169 1170 lb_size = udf_rw32(ump->logical_vol->lb_size); 1171 num_lb = (buf->b_bcount + lb_size -1) / lb_size; 1172 blks = lb_size / DEV_BSIZE; 1173 udf_c_type = buf->b_udf_c_type; 1174 1175 KASSERT(lb_size == ump->discinfo.sector_size); 1176 1177 /* select partition to record the buffer on */ 1178 vpart_num = ump->data_part; 1179 if (udf_c_type == UDF_C_NODE) 1180 vpart_num = ump->node_part; 1181 if (udf_c_type == UDF_C_FIDS) 1182 vpart_num = ump->fids_part; 1183 *vpart_nump = vpart_num; 1184 1185 if (udf_c_type == UDF_C_NODE) { 1186 /* if not VAT, its allready allocated */ 1187 if (ump->vtop_alloc[ump->node_part] != UDF_ALLOC_VAT) 1188 return; 1189 1190 /* allocate on its backing sequential partition */ 1191 vpart_num = ump->data_part; 1192 } 1193 1194 /* do allocation on the selected partition */ 1195 error = udf_allocate_space(ump, udf_c_type, 1196 vpart_num, num_lb, lmapping); 1197 if (error) { 1198 /* ARGH! we've not done our accounting right! */ 1199 panic("UDF disc allocation accounting gone wrong"); 1200 } 1201 1202 /* commit our sector count */ 1203 mutex_enter(&ump->allocate_mutex); 1204 if (num_lb > ump->uncomitted_lb) { 1205 ump->uncomitted_lb = 0; 1206 } else { 1207 ump->uncomitted_lb -= num_lb; 1208 } 1209 mutex_exit(&ump->allocate_mutex); 1210 1211 /* If its userdata or FIDs, record its allocation in its node. */ 1212 if ((udf_c_type == UDF_C_USERDATA) || 1213 (udf_c_type == UDF_C_FIDS) || 1214 (udf_c_type == UDF_C_METADATA_SBM)) 1215 { 1216 udf_record_allocation_in_node(ump, buf, vpart_num, lmapping, 1217 node_ad_cpy); 1218 /* decrement our outstanding bufs counter */ 1219 s = splbio(); 1220 udf_node->outstanding_bufs--; 1221 splx(s); 1222 } 1223 } 1224 1225 /* --------------------------------------------------------------------- */ 1226 1227 /* 1228 * Try to merge a1 with the new piece a2. udf_ads_merge returns error when not 1229 * possible (anymore); a2 returns the rest piece. 1230 */ 1231 1232 static int 1233 udf_ads_merge(uint32_t lb_size, struct long_ad *a1, struct long_ad *a2) 1234 { 1235 uint32_t max_len, merge_len; 1236 uint32_t a1_len, a2_len; 1237 uint32_t a1_flags, a2_flags; 1238 uint32_t a1_lbnum, a2_lbnum; 1239 uint16_t a1_part, a2_part; 1240 1241 max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); 1242 1243 a1_flags = UDF_EXT_FLAGS(udf_rw32(a1->len)); 1244 a1_len = UDF_EXT_LEN(udf_rw32(a1->len)); 1245 a1_lbnum = udf_rw32(a1->loc.lb_num); 1246 a1_part = udf_rw16(a1->loc.part_num); 1247 1248 a2_flags = UDF_EXT_FLAGS(udf_rw32(a2->len)); 1249 a2_len = UDF_EXT_LEN(udf_rw32(a2->len)); 1250 a2_lbnum = udf_rw32(a2->loc.lb_num); 1251 a2_part = udf_rw16(a2->loc.part_num); 1252 1253 /* defines same space */ 1254 if (a1_flags != a2_flags) 1255 return 1; 1256 1257 if (a1_flags != UDF_EXT_FREE) { 1258 /* the same partition */ 1259 if (a1_part != a2_part) 1260 return 1; 1261 1262 /* a2 is successor of a1 */ 1263 if (a1_lbnum * lb_size + a1_len != a2_lbnum * lb_size) 1264 return 1; 1265 } 1266 1267 /* merge as most from a2 if possible */ 1268 merge_len = MIN(a2_len, max_len - a1_len); 1269 a1_len += merge_len; 1270 a2_len -= merge_len; 1271 a2_lbnum += merge_len/lb_size; 1272 1273 a1->len = udf_rw32(a1_len | a1_flags); 1274 a2->len = udf_rw32(a2_len | a2_flags); 1275 a2->loc.lb_num = udf_rw32(a2_lbnum); 1276 1277 if (a2_len > 0) 1278 return 1; 1279 1280 /* there is space over to merge */ 1281 return 0; 1282 } 1283 1284 /* --------------------------------------------------------------------- */ 1285 1286 static void 1287 udf_wipe_adslots(struct udf_node *udf_node) 1288 { 1289 struct file_entry *fe; 1290 struct extfile_entry *efe; 1291 struct alloc_ext_entry *ext; 1292 uint64_t inflen, objsize; 1293 uint32_t lb_size, dscr_size, l_ea, l_ad, max_l_ad, crclen; 1294 uint8_t *data_pos; 1295 int extnr; 1296 1297 lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 1298 1299 fe = udf_node->fe; 1300 efe = udf_node->efe; 1301 if (fe) { 1302 inflen = udf_rw64(fe->inf_len); 1303 objsize = inflen; 1304 dscr_size = sizeof(struct file_entry) -1; 1305 l_ea = udf_rw32(fe->l_ea); 1306 l_ad = udf_rw32(fe->l_ad); 1307 data_pos = (uint8_t *) fe + dscr_size + l_ea; 1308 } else { 1309 inflen = udf_rw64(efe->inf_len); 1310 objsize = udf_rw64(efe->obj_size); 1311 dscr_size = sizeof(struct extfile_entry) -1; 1312 l_ea = udf_rw32(efe->l_ea); 1313 l_ad = udf_rw32(efe->l_ad); 1314 data_pos = (uint8_t *) efe + dscr_size + l_ea; 1315 } 1316 max_l_ad = lb_size - dscr_size - l_ea; 1317 1318 /* wipe fe/efe */ 1319 memset(data_pos, 0, max_l_ad); 1320 crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea; 1321 if (fe) { 1322 fe->l_ad = udf_rw32(0); 1323 fe->logblks_rec = udf_rw64(0); 1324 fe->tag.desc_crc_len = udf_rw32(crclen); 1325 } else { 1326 efe->l_ad = udf_rw32(0); 1327 efe->logblks_rec = udf_rw64(0); 1328 efe->tag.desc_crc_len = udf_rw32(crclen); 1329 } 1330 1331 /* wipe all allocation extent entries */ 1332 for (extnr = 0; extnr < udf_node->num_extensions; extnr++) { 1333 ext = udf_node->ext[extnr]; 1334 dscr_size = sizeof(struct alloc_ext_entry) -1; 1335 data_pos = (uint8_t *) ext->data; 1336 max_l_ad = lb_size - dscr_size; 1337 memset(data_pos, 0, max_l_ad); 1338 ext->l_ad = udf_rw32(0); 1339 1340 crclen = dscr_size - UDF_DESC_TAG_LENGTH; 1341 ext->tag.desc_crc_len = udf_rw32(crclen); 1342 } 1343 udf_node->i_flags |= IN_NODE_REBUILD; 1344 } 1345 1346 /* --------------------------------------------------------------------- */ 1347 1348 void 1349 udf_get_adslot(struct udf_node *udf_node, int slot, struct long_ad *icb, 1350 int *eof) { 1351 struct file_entry *fe; 1352 struct extfile_entry *efe; 1353 struct alloc_ext_entry *ext; 1354 struct icb_tag *icbtag; 1355 struct short_ad *short_ad; 1356 struct long_ad *long_ad, l_icb; 1357 uint32_t offset; 1358 uint32_t lb_size, dscr_size, l_ea, l_ad, flags; 1359 uint8_t *data_pos; 1360 int icbflags, addr_type, adlen, extnr; 1361 1362 /* determine what descriptor we are in */ 1363 lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 1364 1365 fe = udf_node->fe; 1366 efe = udf_node->efe; 1367 if (fe) { 1368 icbtag = &fe->icbtag; 1369 dscr_size = sizeof(struct file_entry) -1; 1370 l_ea = udf_rw32(fe->l_ea); 1371 l_ad = udf_rw32(fe->l_ad); 1372 data_pos = (uint8_t *) fe + dscr_size + l_ea; 1373 } else { 1374 icbtag = &efe->icbtag; 1375 dscr_size = sizeof(struct extfile_entry) -1; 1376 l_ea = udf_rw32(efe->l_ea); 1377 l_ad = udf_rw32(efe->l_ad); 1378 data_pos = (uint8_t *) efe + dscr_size + l_ea; 1379 } 1380 1381 icbflags = udf_rw16(icbtag->flags); 1382 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 1383 1384 /* just in case we're called on an intern, its EOF */ 1385 if (addr_type == UDF_ICB_INTERN_ALLOC) { 1386 memset(icb, 0, sizeof(struct long_ad)); 1387 *eof = 1; 1388 return; 1389 } 1390 1391 adlen = 0; 1392 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1393 adlen = sizeof(struct short_ad); 1394 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1395 adlen = sizeof(struct long_ad); 1396 } 1397 1398 /* if offset too big, we go to the allocation extensions */ 1399 offset = slot * adlen; 1400 extnr = -1; 1401 while (offset >= l_ad) { 1402 /* check if our last entry is a redirect */ 1403 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1404 short_ad = (struct short_ad *) (data_pos + l_ad-adlen); 1405 l_icb.len = short_ad->len; 1406 l_icb.loc.part_num = udf_node->loc.loc.part_num; 1407 l_icb.loc.lb_num = short_ad->lb_num; 1408 } else { 1409 KASSERT(addr_type == UDF_ICB_LONG_ALLOC); 1410 long_ad = (struct long_ad *) (data_pos + l_ad-adlen); 1411 l_icb = *long_ad; 1412 } 1413 flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); 1414 if (flags != UDF_EXT_REDIRECT) { 1415 l_ad = 0; /* force EOF */ 1416 break; 1417 } 1418 1419 /* advance to next extent */ 1420 extnr++; 1421 if (extnr >= udf_node->num_extensions) { 1422 l_ad = 0; /* force EOF */ 1423 break; 1424 } 1425 offset = offset - l_ad; 1426 ext = udf_node->ext[extnr]; 1427 dscr_size = sizeof(struct alloc_ext_entry) -1; 1428 l_ad = udf_rw32(ext->l_ad); 1429 data_pos = (uint8_t *) ext + dscr_size; 1430 } 1431 1432 /* XXX l_ad == 0 should be enough to check */ 1433 *eof = (offset >= l_ad) || (l_ad == 0); 1434 if (*eof) { 1435 DPRINTF(PARANOIDADWLK, ("returning EOF, extnr %d, offset %d, " 1436 "l_ad %d\n", extnr, offset, l_ad)); 1437 memset(icb, 0, sizeof(struct long_ad)); 1438 return; 1439 } 1440 1441 /* get the element */ 1442 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1443 short_ad = (struct short_ad *) (data_pos + offset); 1444 icb->len = short_ad->len; 1445 icb->loc.part_num = udf_node->loc.loc.part_num; 1446 icb->loc.lb_num = short_ad->lb_num; 1447 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1448 long_ad = (struct long_ad *) (data_pos + offset); 1449 *icb = *long_ad; 1450 } 1451 DPRINTF(PARANOIDADWLK, ("returning element : v %d, lb %d, len %d, " 1452 "flags %d\n", icb->loc.part_num, icb->loc.lb_num, 1453 UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); 1454 } 1455 1456 /* --------------------------------------------------------------------- */ 1457 1458 int 1459 udf_append_adslot(struct udf_node *udf_node, int *slot, struct long_ad *icb) { 1460 struct udf_mount *ump = udf_node->ump; 1461 union dscrptr *dscr, *extdscr; 1462 struct file_entry *fe; 1463 struct extfile_entry *efe; 1464 struct alloc_ext_entry *ext; 1465 struct icb_tag *icbtag; 1466 struct short_ad *short_ad; 1467 struct long_ad *long_ad, o_icb, l_icb; 1468 uint64_t logblks_rec, *logblks_rec_p; 1469 uint64_t lmapping; 1470 uint32_t offset, rest, len, lb_num; 1471 uint32_t lb_size, dscr_size, l_ea, l_ad, *l_ad_p, max_l_ad, crclen; 1472 uint32_t flags; 1473 uint16_t vpart_num; 1474 uint8_t *data_pos; 1475 int icbflags, addr_type, adlen, extnr; 1476 int error; 1477 1478 lb_size = udf_rw32(ump->logical_vol->lb_size); 1479 vpart_num = udf_rw16(udf_node->loc.loc.part_num); 1480 1481 /* determine what descriptor we are in */ 1482 fe = udf_node->fe; 1483 efe = udf_node->efe; 1484 if (fe) { 1485 icbtag = &fe->icbtag; 1486 dscr = (union dscrptr *) fe; 1487 dscr_size = sizeof(struct file_entry) -1; 1488 1489 l_ea = udf_rw32(fe->l_ea); 1490 l_ad_p = &fe->l_ad; 1491 logblks_rec_p = &fe->logblks_rec; 1492 } else { 1493 icbtag = &efe->icbtag; 1494 dscr = (union dscrptr *) efe; 1495 dscr_size = sizeof(struct extfile_entry) -1; 1496 1497 l_ea = udf_rw32(efe->l_ea); 1498 l_ad_p = &efe->l_ad; 1499 logblks_rec_p = &efe->logblks_rec; 1500 } 1501 data_pos = (uint8_t *) dscr + dscr_size + l_ea; 1502 max_l_ad = lb_size - dscr_size - l_ea; 1503 1504 icbflags = udf_rw16(icbtag->flags); 1505 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 1506 1507 /* just in case we're called on an intern, its EOF */ 1508 if (addr_type == UDF_ICB_INTERN_ALLOC) { 1509 panic("udf_append_adslot on UDF_ICB_INTERN_ALLOC\n"); 1510 } 1511 1512 adlen = 0; 1513 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1514 adlen = sizeof(struct short_ad); 1515 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1516 adlen = sizeof(struct long_ad); 1517 } 1518 1519 /* clean up given long_ad since it can be a synthesized one */ 1520 flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); 1521 if (flags == UDF_EXT_FREE) { 1522 icb->loc.part_num = udf_rw16(0); 1523 icb->loc.lb_num = udf_rw32(0); 1524 } 1525 1526 /* if offset too big, we go to the allocation extensions */ 1527 l_ad = udf_rw32(*l_ad_p); 1528 offset = (*slot) * adlen; 1529 extnr = -1; 1530 while (offset >= l_ad) { 1531 /* check if our last entry is a redirect */ 1532 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1533 short_ad = (struct short_ad *) (data_pos + l_ad-adlen); 1534 l_icb.len = short_ad->len; 1535 l_icb.loc.part_num = udf_node->loc.loc.part_num; 1536 l_icb.loc.lb_num = short_ad->lb_num; 1537 } else { 1538 KASSERT(addr_type == UDF_ICB_LONG_ALLOC); 1539 long_ad = (struct long_ad *) (data_pos + l_ad-adlen); 1540 l_icb = *long_ad; 1541 } 1542 flags = UDF_EXT_FLAGS(udf_rw32(l_icb.len)); 1543 if (flags != UDF_EXT_REDIRECT) { 1544 /* only one past the last one is adressable */ 1545 break; 1546 } 1547 1548 /* advance to next extent */ 1549 extnr++; 1550 KASSERT(extnr < udf_node->num_extensions); 1551 offset = offset - l_ad; 1552 1553 ext = udf_node->ext[extnr]; 1554 dscr = (union dscrptr *) ext; 1555 dscr_size = sizeof(struct alloc_ext_entry) -1; 1556 max_l_ad = lb_size - dscr_size; 1557 l_ad_p = &ext->l_ad; 1558 l_ad = udf_rw32(*l_ad_p); 1559 data_pos = (uint8_t *) ext + dscr_size; 1560 } 1561 DPRINTF(PARANOIDADWLK, ("append, ext %d, offset %d, l_ad %d\n", 1562 extnr, offset, udf_rw32(*l_ad_p))); 1563 KASSERT(l_ad == udf_rw32(*l_ad_p)); 1564 1565 /* offset is offset within the current (E)FE/AED */ 1566 l_ad = udf_rw32(*l_ad_p); 1567 crclen = udf_rw32(dscr->tag.desc_crc_len); 1568 logblks_rec = udf_rw64(*logblks_rec_p); 1569 1570 /* overwriting old piece? */ 1571 if (offset < l_ad) { 1572 /* overwrite entry; compensate for the old element */ 1573 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1574 short_ad = (struct short_ad *) (data_pos + offset); 1575 o_icb.len = short_ad->len; 1576 o_icb.loc.part_num = udf_rw16(0); /* ignore */ 1577 o_icb.loc.lb_num = short_ad->lb_num; 1578 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1579 long_ad = (struct long_ad *) (data_pos + offset); 1580 o_icb = *long_ad; 1581 } else { 1582 panic("Invalid address type in udf_append_adslot\n"); 1583 } 1584 1585 len = udf_rw32(o_icb.len); 1586 if (UDF_EXT_FLAGS(len) == UDF_EXT_ALLOCATED) { 1587 /* adjust counts */ 1588 len = UDF_EXT_LEN(len); 1589 logblks_rec -= (len + lb_size -1) / lb_size; 1590 } 1591 } 1592 1593 /* check if we're not appending a redirection */ 1594 flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); 1595 KASSERT(flags != UDF_EXT_REDIRECT); 1596 1597 /* round down available space */ 1598 rest = adlen * ((max_l_ad - offset) / adlen); 1599 if (rest <= adlen) { 1600 /* have to append aed, see if we already have a spare one */ 1601 extnr++; 1602 ext = udf_node->ext[extnr]; 1603 l_icb = udf_node->ext_loc[extnr]; 1604 if (ext == NULL) { 1605 DPRINTF(ALLOC,("adding allocation extent %d\n", extnr)); 1606 1607 error = udf_pre_allocate_space(ump, UDF_C_NODE, 1, 1608 vpart_num, &lmapping); 1609 lb_num = lmapping; 1610 if (error) 1611 return error; 1612 1613 /* initialise pointer to location */ 1614 memset(&l_icb, 0, sizeof(struct long_ad)); 1615 l_icb.len = udf_rw32(lb_size | UDF_EXT_REDIRECT); 1616 l_icb.loc.lb_num = udf_rw32(lb_num); 1617 l_icb.loc.part_num = udf_rw16(vpart_num); 1618 1619 /* create new aed descriptor */ 1620 udf_create_logvol_dscr(ump, udf_node, &l_icb, &extdscr); 1621 ext = &extdscr->aee; 1622 1623 udf_inittag(ump, &ext->tag, TAGID_ALLOCEXTENT, lb_num); 1624 dscr_size = sizeof(struct alloc_ext_entry) -1; 1625 max_l_ad = lb_size - dscr_size; 1626 memset(ext->data, 0, max_l_ad); 1627 ext->l_ad = udf_rw32(0); 1628 ext->tag.desc_crc_len = 1629 udf_rw32(dscr_size - UDF_DESC_TAG_LENGTH); 1630 1631 /* declare aed */ 1632 udf_node->num_extensions++; 1633 udf_node->ext_loc[extnr] = l_icb; 1634 udf_node->ext[extnr] = ext; 1635 } 1636 /* add redirect and adjust l_ad and crclen for old descr */ 1637 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1638 short_ad = (struct short_ad *) (data_pos + offset); 1639 short_ad->len = l_icb.len; 1640 short_ad->lb_num = l_icb.loc.lb_num; 1641 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1642 long_ad = (struct long_ad *) (data_pos + offset); 1643 *long_ad = l_icb; 1644 } 1645 l_ad += adlen; 1646 crclen += adlen; 1647 dscr->tag.desc_crc_len = udf_rw32(crclen); 1648 *l_ad_p = udf_rw32(l_ad); 1649 1650 /* advance to the new extension */ 1651 KASSERT(ext != NULL); 1652 dscr = (union dscrptr *) ext; 1653 dscr_size = sizeof(struct alloc_ext_entry) -1; 1654 max_l_ad = lb_size - dscr_size; 1655 data_pos = (uint8_t *) dscr + dscr_size; 1656 1657 l_ad_p = &ext->l_ad; 1658 l_ad = udf_rw32(*l_ad_p); 1659 crclen = udf_rw32(dscr->tag.desc_crc_len); 1660 offset = 0; 1661 1662 /* adjust callees slot count for link insert */ 1663 *slot += 1; 1664 } 1665 1666 /* write out the element */ 1667 DPRINTF(PARANOIDADWLK, ("adding element : %p : v %d, lb %d, " 1668 "len %d, flags %d\n", data_pos + offset, 1669 icb->loc.part_num, icb->loc.lb_num, 1670 UDF_EXT_LEN(icb->len), UDF_EXT_FLAGS(icb->len))); 1671 if (addr_type == UDF_ICB_SHORT_ALLOC) { 1672 short_ad = (struct short_ad *) (data_pos + offset); 1673 short_ad->len = icb->len; 1674 short_ad->lb_num = icb->loc.lb_num; 1675 } else if (addr_type == UDF_ICB_LONG_ALLOC) { 1676 long_ad = (struct long_ad *) (data_pos + offset); 1677 *long_ad = *icb; 1678 } 1679 1680 /* adjust logblks recorded count */ 1681 flags = UDF_EXT_FLAGS(udf_rw32(icb->len)); 1682 if (flags == UDF_EXT_ALLOCATED) 1683 logblks_rec += (UDF_EXT_LEN(icb->len) + lb_size -1) / lb_size; 1684 *logblks_rec_p = udf_rw64(logblks_rec); 1685 1686 /* adjust l_ad and crclen when needed */ 1687 if (offset >= l_ad) { 1688 l_ad += adlen; 1689 crclen += adlen; 1690 dscr->tag.desc_crc_len = udf_rw32(crclen); 1691 *l_ad_p = udf_rw32(l_ad); 1692 } 1693 1694 return 0; 1695 } 1696 1697 /* --------------------------------------------------------------------- */ 1698 1699 static void 1700 udf_count_alloc_exts(struct udf_node *udf_node) 1701 { 1702 struct long_ad s_ad; 1703 uint32_t lb_num, len, flags; 1704 uint16_t vpart_num; 1705 int slot, eof; 1706 int num_extents, extnr; 1707 int lb_size; 1708 1709 if (udf_node->num_extensions == 0) 1710 return; 1711 1712 lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 1713 /* count number of allocation extents in use */ 1714 num_extents = 0; 1715 slot = 0; 1716 for (;;) { 1717 udf_get_adslot(udf_node, slot, &s_ad, &eof); 1718 if (eof) 1719 break; 1720 len = udf_rw32(s_ad.len); 1721 flags = UDF_EXT_FLAGS(len); 1722 1723 if (flags == UDF_EXT_REDIRECT) 1724 num_extents++; 1725 1726 slot++; 1727 } 1728 1729 DPRINTF(ALLOC, ("udf_count_alloc_ext counted %d live extents\n", 1730 num_extents)); 1731 1732 /* XXX choice: we could delay freeing them on node writeout */ 1733 /* free excess entries */ 1734 extnr = num_extents; 1735 for (;extnr < udf_node->num_extensions; extnr++) { 1736 DPRINTF(ALLOC, ("freeing alloc ext %d\n", extnr)); 1737 /* free dscriptor */ 1738 s_ad = udf_node->ext_loc[extnr]; 1739 udf_free_logvol_dscr(udf_node->ump, &s_ad, 1740 udf_node->ext[extnr]); 1741 udf_node->ext[extnr] = NULL; 1742 1743 /* free disc space */ 1744 lb_num = udf_rw32(s_ad.loc.lb_num); 1745 vpart_num = udf_rw16(s_ad.loc.part_num); 1746 udf_free_allocated_space(udf_node->ump, lb_num, vpart_num, 1); 1747 1748 memset(&udf_node->ext_loc[extnr], 0, sizeof(struct long_ad)); 1749 } 1750 1751 /* set our new number of allocation extents */ 1752 udf_node->num_extensions = num_extents; 1753 } 1754 1755 1756 /* --------------------------------------------------------------------- */ 1757 1758 /* 1759 * Adjust the node's allocation descriptors to reflect the new mapping; do 1760 * take note that we might glue to existing allocation descriptors. 1761 * 1762 * XXX Note there can only be one allocation being recorded/mount; maybe 1763 * explicit allocation in shedule thread? 1764 */ 1765 1766 static void 1767 udf_record_allocation_in_node(struct udf_mount *ump, struct buf *buf, 1768 uint16_t vpart_num, uint64_t *mapping, struct long_ad *node_ad_cpy) 1769 { 1770 struct vnode *vp = buf->b_vp; 1771 struct udf_node *udf_node = VTOI(vp); 1772 struct file_entry *fe; 1773 struct extfile_entry *efe; 1774 struct icb_tag *icbtag; 1775 struct long_ad s_ad, c_ad; 1776 uint64_t inflen, from, till; 1777 uint64_t foffset, end_foffset, restart_foffset; 1778 uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; 1779 uint32_t num_lb, len, flags, lb_num; 1780 uint32_t run_start; 1781 uint32_t slot_offset, replace_len, replace; 1782 int addr_type, icbflags; 1783 // int udf_c_type = buf->b_udf_c_type; 1784 int lb_size, run_length, eof; 1785 int slot, cpy_slot, cpy_slots, restart_slot; 1786 int error; 1787 1788 DPRINTF(ALLOC, ("udf_record_allocation_in_node\n")); 1789 1790 #if 0 1791 /* XXX disable sanity check for now */ 1792 /* sanity check ... should be panic ? */ 1793 if ((udf_c_type != UDF_C_USERDATA) && (udf_c_type != UDF_C_FIDS)) 1794 return; 1795 #endif 1796 1797 lb_size = udf_rw32(udf_node->ump->logical_vol->lb_size); 1798 1799 /* do the job */ 1800 UDF_LOCK_NODE(udf_node, 0); /* XXX can deadlock ? */ 1801 udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); 1802 1803 fe = udf_node->fe; 1804 efe = udf_node->efe; 1805 if (fe) { 1806 icbtag = &fe->icbtag; 1807 inflen = udf_rw64(fe->inf_len); 1808 } else { 1809 icbtag = &efe->icbtag; 1810 inflen = udf_rw64(efe->inf_len); 1811 } 1812 1813 /* do check if `till' is not past file information length */ 1814 from = buf->b_lblkno * lb_size; 1815 till = MIN(inflen, from + buf->b_resid); 1816 1817 num_lb = (till - from + lb_size -1) / lb_size; 1818 1819 DPRINTF(ALLOC, ("record allocation from %"PRIu64" + %d\n", from, buf->b_bcount)); 1820 1821 icbflags = udf_rw16(icbtag->flags); 1822 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 1823 1824 if (addr_type == UDF_ICB_INTERN_ALLOC) { 1825 /* nothing to do */ 1826 /* XXX clean up rest of node? just in case? */ 1827 UDF_UNLOCK_NODE(udf_node, 0); 1828 return; 1829 } 1830 1831 slot = 0; 1832 cpy_slot = 0; 1833 foffset = 0; 1834 1835 /* 1) copy till first overlap piece to the rewrite buffer */ 1836 for (;;) { 1837 udf_get_adslot(udf_node, slot, &s_ad, &eof); 1838 if (eof) { 1839 DPRINTF(WRITE, 1840 ("Record allocation in node " 1841 "failed: encountered EOF\n")); 1842 UDF_UNLOCK_NODE(udf_node, 0); 1843 buf->b_error = EINVAL; 1844 return; 1845 } 1846 len = udf_rw32(s_ad.len); 1847 flags = UDF_EXT_FLAGS(len); 1848 len = UDF_EXT_LEN(len); 1849 1850 if (flags == UDF_EXT_REDIRECT) { 1851 slot++; 1852 continue; 1853 } 1854 1855 end_foffset = foffset + len; 1856 if (end_foffset > from) 1857 break; /* found */ 1858 1859 node_ad_cpy[cpy_slot++] = s_ad; 1860 1861 DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " 1862 "-> stack\n", 1863 udf_rw16(s_ad.loc.part_num), 1864 udf_rw32(s_ad.loc.lb_num), 1865 UDF_EXT_LEN(udf_rw32(s_ad.len)), 1866 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 1867 1868 foffset = end_foffset; 1869 slot++; 1870 } 1871 restart_slot = slot; 1872 restart_foffset = foffset; 1873 1874 /* 2) trunc overlapping slot at overlap and copy it */ 1875 slot_offset = from - foffset; 1876 if (slot_offset > 0) { 1877 DPRINTF(ALLOC, ("\tslot_offset = %d, flags = %d (%d)\n", 1878 slot_offset, flags >> 30, flags)); 1879 1880 s_ad.len = udf_rw32(slot_offset | flags); 1881 node_ad_cpy[cpy_slot++] = s_ad; 1882 1883 DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " 1884 "-> stack\n", 1885 udf_rw16(s_ad.loc.part_num), 1886 udf_rw32(s_ad.loc.lb_num), 1887 UDF_EXT_LEN(udf_rw32(s_ad.len)), 1888 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 1889 } 1890 foffset += slot_offset; 1891 1892 /* 3) insert new mappings */ 1893 memset(&s_ad, 0, sizeof(struct long_ad)); 1894 lb_num = 0; 1895 for (lb_num = 0; lb_num < num_lb; lb_num++) { 1896 run_start = mapping[lb_num]; 1897 run_length = 1; 1898 while (lb_num < num_lb-1) { 1899 if (mapping[lb_num+1] != mapping[lb_num]+1) 1900 if (mapping[lb_num+1] != mapping[lb_num]) 1901 break; 1902 run_length++; 1903 lb_num++; 1904 } 1905 /* insert slot for this mapping */ 1906 len = run_length * lb_size; 1907 1908 /* bounds checking */ 1909 if (foffset + len > till) 1910 len = till - foffset; 1911 KASSERT(foffset + len <= inflen); 1912 1913 s_ad.len = udf_rw32(len | UDF_EXT_ALLOCATED); 1914 s_ad.loc.part_num = udf_rw16(vpart_num); 1915 s_ad.loc.lb_num = udf_rw32(run_start); 1916 1917 foffset += len; 1918 1919 /* paranoia */ 1920 if (len == 0) { 1921 DPRINTF(WRITE, 1922 ("Record allocation in node " 1923 "failed: insert failed\n")); 1924 UDF_UNLOCK_NODE(udf_node, 0); 1925 buf->b_error = EINVAL; 1926 return; 1927 } 1928 node_ad_cpy[cpy_slot++] = s_ad; 1929 1930 DPRINTF(ALLOC, ("\t3: insert new mapping vp %d lb %d, len %d, " 1931 "flags %d -> stack\n", 1932 udf_rw16(s_ad.loc.part_num), udf_rw32(s_ad.loc.lb_num), 1933 UDF_EXT_LEN(udf_rw32(s_ad.len)), 1934 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 1935 } 1936 1937 /* 4) pop replaced length */ 1938 slot = restart_slot; 1939 foffset = restart_foffset; 1940 1941 replace_len = till - foffset; /* total amount of bytes to pop */ 1942 slot_offset = from - foffset; /* offset in first encounted slot */ 1943 KASSERT((slot_offset % lb_size) == 0); 1944 1945 for (;;) { 1946 udf_get_adslot(udf_node, slot, &s_ad, &eof); 1947 if (eof) 1948 break; 1949 1950 len = udf_rw32(s_ad.len); 1951 flags = UDF_EXT_FLAGS(len); 1952 len = UDF_EXT_LEN(len); 1953 lb_num = udf_rw32(s_ad.loc.lb_num); 1954 1955 if (flags == UDF_EXT_REDIRECT) { 1956 slot++; 1957 continue; 1958 } 1959 1960 DPRINTF(ALLOC, ("\t4i: got slot %d, slot_offset %d, " 1961 "replace_len %d, " 1962 "vp %d, lb %d, len %d, flags %d\n", 1963 slot, slot_offset, replace_len, 1964 udf_rw16(s_ad.loc.part_num), 1965 udf_rw32(s_ad.loc.lb_num), 1966 UDF_EXT_LEN(udf_rw32(s_ad.len)), 1967 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 1968 1969 /* adjust for slot offset */ 1970 if (slot_offset) { 1971 DPRINTF(ALLOC, ("\t4s: skipping %d\n", slot_offset)); 1972 lb_num += slot_offset / lb_size; 1973 len -= slot_offset; 1974 foffset += slot_offset; 1975 replace_len -= slot_offset; 1976 1977 /* mark adjusted */ 1978 slot_offset = 0; 1979 } 1980 1981 /* advance for (the rest of) this slot */ 1982 replace = MIN(len, replace_len); 1983 DPRINTF(ALLOC, ("\t4d: replacing %d\n", replace)); 1984 1985 /* advance for this slot */ 1986 if (replace) { 1987 /* note: dont round DOWN on num_lb since we then 1988 * forget the last partial one */ 1989 num_lb = (replace + lb_size - 1) / lb_size; 1990 if (flags != UDF_EXT_FREE) { 1991 udf_free_allocated_space(ump, lb_num, 1992 udf_rw16(s_ad.loc.part_num), num_lb); 1993 } 1994 lb_num += num_lb; 1995 len -= replace; 1996 foffset += replace; 1997 replace_len -= replace; 1998 } 1999 2000 /* do we have a slot tail ? */ 2001 if (len) { 2002 KASSERT(foffset % lb_size == 0); 2003 2004 /* we arrived at our point, push remainder */ 2005 s_ad.len = udf_rw32(len | flags); 2006 s_ad.loc.lb_num = udf_rw32(lb_num); 2007 if (flags == UDF_EXT_FREE) 2008 s_ad.loc.lb_num = udf_rw32(0); 2009 node_ad_cpy[cpy_slot++] = s_ad; 2010 foffset += len; 2011 slot++; 2012 2013 DPRINTF(ALLOC, ("\t4: vp %d, lb %d, len %d, flags %d " 2014 "-> stack\n", 2015 udf_rw16(s_ad.loc.part_num), 2016 udf_rw32(s_ad.loc.lb_num), 2017 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2018 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2019 break; 2020 } 2021 2022 slot++; 2023 } 2024 2025 /* 5) copy remainder */ 2026 for (;;) { 2027 udf_get_adslot(udf_node, slot, &s_ad, &eof); 2028 if (eof) 2029 break; 2030 2031 len = udf_rw32(s_ad.len); 2032 flags = UDF_EXT_FLAGS(len); 2033 len = UDF_EXT_LEN(len); 2034 2035 if (flags == UDF_EXT_REDIRECT) { 2036 slot++; 2037 continue; 2038 } 2039 2040 node_ad_cpy[cpy_slot++] = s_ad; 2041 2042 DPRINTF(ALLOC, ("\t5: insert new mapping " 2043 "vp %d lb %d, len %d, flags %d " 2044 "-> stack\n", 2045 udf_rw16(s_ad.loc.part_num), 2046 udf_rw32(s_ad.loc.lb_num), 2047 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2048 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2049 2050 slot++; 2051 } 2052 2053 /* 6) reset node descriptors */ 2054 udf_wipe_adslots(udf_node); 2055 2056 /* 7) copy back extents; merge when possible. Recounting on the fly */ 2057 cpy_slots = cpy_slot; 2058 2059 c_ad = node_ad_cpy[0]; 2060 slot = 0; 2061 DPRINTF(ALLOC, ("\t7s: stack -> got mapping vp %d " 2062 "lb %d, len %d, flags %d\n", 2063 udf_rw16(c_ad.loc.part_num), 2064 udf_rw32(c_ad.loc.lb_num), 2065 UDF_EXT_LEN(udf_rw32(c_ad.len)), 2066 UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); 2067 2068 for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { 2069 s_ad = node_ad_cpy[cpy_slot]; 2070 2071 DPRINTF(ALLOC, ("\t7i: stack -> got mapping vp %d " 2072 "lb %d, len %d, flags %d\n", 2073 udf_rw16(s_ad.loc.part_num), 2074 udf_rw32(s_ad.loc.lb_num), 2075 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2076 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2077 2078 /* see if we can merge */ 2079 if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { 2080 /* not mergable (anymore) */ 2081 DPRINTF(ALLOC, ("\t7: appending vp %d lb %d, " 2082 "len %d, flags %d\n", 2083 udf_rw16(c_ad.loc.part_num), 2084 udf_rw32(c_ad.loc.lb_num), 2085 UDF_EXT_LEN(udf_rw32(c_ad.len)), 2086 UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); 2087 2088 error = udf_append_adslot(udf_node, &slot, &c_ad); 2089 if (error) { 2090 buf->b_error = error; 2091 goto out; 2092 } 2093 c_ad = s_ad; 2094 slot++; 2095 } 2096 } 2097 2098 /* 8) push rest slot (if any) */ 2099 if (UDF_EXT_LEN(c_ad.len) > 0) { 2100 DPRINTF(ALLOC, ("\t8: last append vp %d lb %d, " 2101 "len %d, flags %d\n", 2102 udf_rw16(c_ad.loc.part_num), 2103 udf_rw32(c_ad.loc.lb_num), 2104 UDF_EXT_LEN(udf_rw32(c_ad.len)), 2105 UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); 2106 2107 error = udf_append_adslot(udf_node, &slot, &c_ad); 2108 if (error) { 2109 buf->b_error = error; 2110 goto out; 2111 } 2112 } 2113 2114 out: 2115 udf_count_alloc_exts(udf_node); 2116 2117 /* the node's descriptors should now be sane */ 2118 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2119 UDF_UNLOCK_NODE(udf_node, 0); 2120 2121 KASSERT(orig_inflen == new_inflen); 2122 KASSERT(new_lbrec >= orig_lbrec); 2123 2124 return; 2125 } 2126 2127 /* --------------------------------------------------------------------- */ 2128 2129 int 2130 udf_grow_node(struct udf_node *udf_node, uint64_t new_size) 2131 { 2132 union dscrptr *dscr; 2133 struct vnode *vp = udf_node->vnode; 2134 struct udf_mount *ump = udf_node->ump; 2135 struct file_entry *fe; 2136 struct extfile_entry *efe; 2137 struct icb_tag *icbtag; 2138 struct long_ad c_ad, s_ad; 2139 uint64_t size_diff, old_size, inflen, objsize, chunk, append_len; 2140 uint64_t foffset, end_foffset; 2141 uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; 2142 uint32_t lb_size, dscr_size, crclen, lastblock_grow; 2143 uint32_t icbflags, len, flags, max_len; 2144 uint32_t max_l_ad, l_ad, l_ea; 2145 uint16_t my_part, dst_part; 2146 uint8_t *data_pos, *evacuated_data; 2147 int addr_type; 2148 int slot, cpy_slot; 2149 int isdir, eof, error; 2150 2151 DPRINTF(ALLOC, ("udf_grow_node\n")); 2152 2153 UDF_LOCK_NODE(udf_node, 0); 2154 udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); 2155 2156 lb_size = udf_rw32(ump->logical_vol->lb_size); 2157 max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); 2158 2159 fe = udf_node->fe; 2160 efe = udf_node->efe; 2161 if (fe) { 2162 dscr = (union dscrptr *) fe; 2163 icbtag = &fe->icbtag; 2164 inflen = udf_rw64(fe->inf_len); 2165 objsize = inflen; 2166 dscr_size = sizeof(struct file_entry) -1; 2167 l_ea = udf_rw32(fe->l_ea); 2168 l_ad = udf_rw32(fe->l_ad); 2169 } else { 2170 dscr = (union dscrptr *) efe; 2171 icbtag = &efe->icbtag; 2172 inflen = udf_rw64(efe->inf_len); 2173 objsize = udf_rw64(efe->obj_size); 2174 dscr_size = sizeof(struct extfile_entry) -1; 2175 l_ea = udf_rw32(efe->l_ea); 2176 l_ad = udf_rw32(efe->l_ad); 2177 } 2178 data_pos = (uint8_t *) dscr + dscr_size + l_ea; 2179 max_l_ad = lb_size - dscr_size - l_ea; 2180 2181 icbflags = udf_rw16(icbtag->flags); 2182 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2183 2184 old_size = inflen; 2185 size_diff = new_size - old_size; 2186 2187 DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); 2188 2189 evacuated_data = NULL; 2190 if (addr_type == UDF_ICB_INTERN_ALLOC) { 2191 if (l_ad + size_diff <= max_l_ad) { 2192 /* only reflect size change directly in the node */ 2193 inflen += size_diff; 2194 objsize += size_diff; 2195 l_ad += size_diff; 2196 crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; 2197 if (fe) { 2198 fe->inf_len = udf_rw64(inflen); 2199 fe->l_ad = udf_rw32(l_ad); 2200 fe->tag.desc_crc_len = udf_rw32(crclen); 2201 } else { 2202 efe->inf_len = udf_rw64(inflen); 2203 efe->obj_size = udf_rw64(objsize); 2204 efe->l_ad = udf_rw32(l_ad); 2205 efe->tag.desc_crc_len = udf_rw32(crclen); 2206 } 2207 error = 0; 2208 2209 /* set new size for uvm */ 2210 uvm_vnp_setsize(vp, old_size); 2211 uvm_vnp_setwritesize(vp, new_size); 2212 2213 #if 0 2214 /* zero append space in buffer */ 2215 uvm_vnp_zerorange(vp, old_size, new_size - old_size); 2216 #endif 2217 2218 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2219 2220 /* unlock */ 2221 UDF_UNLOCK_NODE(udf_node, 0); 2222 2223 KASSERT(new_inflen == orig_inflen + size_diff); 2224 KASSERT(new_lbrec == orig_lbrec); 2225 KASSERT(new_lbrec == 0); 2226 return 0; 2227 } 2228 2229 DPRINTF(ALLOC, ("\tCONVERT from internal\n")); 2230 2231 if (old_size > 0) { 2232 /* allocate some space and copy in the stuff to keep */ 2233 evacuated_data = malloc(lb_size, M_UDFTEMP, M_WAITOK); 2234 memset(evacuated_data, 0, lb_size); 2235 2236 /* node is locked, so safe to exit mutex */ 2237 UDF_UNLOCK_NODE(udf_node, 0); 2238 2239 /* read in using the `normal' vn_rdwr() */ 2240 error = vn_rdwr(UIO_READ, udf_node->vnode, 2241 evacuated_data, old_size, 0, 2242 UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 2243 FSCRED, NULL, NULL); 2244 2245 /* enter again */ 2246 UDF_LOCK_NODE(udf_node, 0); 2247 } 2248 2249 /* convert to a normal alloc and select type */ 2250 isdir = (vp->v_type == VDIR); 2251 my_part = udf_rw16(udf_node->loc.loc.part_num); 2252 dst_part = isdir? ump->fids_part : ump->data_part; 2253 addr_type = UDF_ICB_SHORT_ALLOC; 2254 if (dst_part != my_part) 2255 addr_type = UDF_ICB_LONG_ALLOC; 2256 2257 icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2258 icbflags |= addr_type; 2259 icbtag->flags = udf_rw16(icbflags); 2260 2261 /* wipe old descriptor space */ 2262 udf_wipe_adslots(udf_node); 2263 2264 memset(&c_ad, 0, sizeof(struct long_ad)); 2265 c_ad.len = udf_rw32(old_size | UDF_EXT_FREE); 2266 c_ad.loc.part_num = udf_rw16(0); /* not relevant */ 2267 c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ 2268 2269 slot = 0; 2270 } else { 2271 /* goto the last entry (if any) */ 2272 slot = 0; 2273 cpy_slot = 0; 2274 foffset = 0; 2275 memset(&c_ad, 0, sizeof(struct long_ad)); 2276 for (;;) { 2277 udf_get_adslot(udf_node, slot, &c_ad, &eof); 2278 if (eof) 2279 break; 2280 2281 len = udf_rw32(c_ad.len); 2282 flags = UDF_EXT_FLAGS(len); 2283 len = UDF_EXT_LEN(len); 2284 2285 end_foffset = foffset + len; 2286 if (flags != UDF_EXT_REDIRECT) 2287 foffset = end_foffset; 2288 2289 slot++; 2290 } 2291 /* at end of adslots */ 2292 2293 /* special case if the old size was zero, then there is no last slot */ 2294 if (old_size == 0) { 2295 c_ad.len = udf_rw32(0 | UDF_EXT_FREE); 2296 c_ad.loc.part_num = udf_rw16(0); /* not relevant */ 2297 c_ad.loc.lb_num = udf_rw32(0); /* not relevant */ 2298 } else { 2299 /* refetch last slot */ 2300 slot--; 2301 udf_get_adslot(udf_node, slot, &c_ad, &eof); 2302 } 2303 } 2304 2305 /* 2306 * If the length of the last slot is not a multiple of lb_size, adjust 2307 * length so that it is; don't forget to adjust `append_len'! relevant for 2308 * extending existing files 2309 */ 2310 len = udf_rw32(c_ad.len); 2311 flags = UDF_EXT_FLAGS(len); 2312 len = UDF_EXT_LEN(len); 2313 2314 lastblock_grow = 0; 2315 if (len % lb_size > 0) { 2316 lastblock_grow = lb_size - (len % lb_size); 2317 lastblock_grow = MIN(size_diff, lastblock_grow); 2318 len += lastblock_grow; 2319 c_ad.len = udf_rw32(len | flags); 2320 2321 /* TODO zero appened space in buffer! */ 2322 /* using uvm_vnp_zerorange(vp, old_size, new_size - old_size); ? */ 2323 } 2324 memset(&s_ad, 0, sizeof(struct long_ad)); 2325 2326 /* size_diff can be bigger than allowed, so grow in chunks */ 2327 append_len = size_diff - lastblock_grow; 2328 while (append_len > 0) { 2329 chunk = MIN(append_len, max_len); 2330 s_ad.len = udf_rw32(chunk | UDF_EXT_FREE); 2331 s_ad.loc.part_num = udf_rw16(0); 2332 s_ad.loc.lb_num = udf_rw32(0); 2333 2334 if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { 2335 /* not mergable (anymore) */ 2336 error = udf_append_adslot(udf_node, &slot, &c_ad); 2337 if (error) 2338 goto errorout; 2339 slot++; 2340 c_ad = s_ad; 2341 memset(&s_ad, 0, sizeof(struct long_ad)); 2342 } 2343 append_len -= chunk; 2344 } 2345 2346 /* if there is a rest piece in the accumulator, append it */ 2347 if (UDF_EXT_LEN(udf_rw32(c_ad.len)) > 0) { 2348 error = udf_append_adslot(udf_node, &slot, &c_ad); 2349 if (error) 2350 goto errorout; 2351 slot++; 2352 } 2353 2354 /* if there is a rest piece that didn't fit, append it */ 2355 if (UDF_EXT_LEN(udf_rw32(s_ad.len)) > 0) { 2356 error = udf_append_adslot(udf_node, &slot, &s_ad); 2357 if (error) 2358 goto errorout; 2359 slot++; 2360 } 2361 2362 inflen += size_diff; 2363 objsize += size_diff; 2364 if (fe) { 2365 fe->inf_len = udf_rw64(inflen); 2366 } else { 2367 efe->inf_len = udf_rw64(inflen); 2368 efe->obj_size = udf_rw64(objsize); 2369 } 2370 error = 0; 2371 2372 if (evacuated_data) { 2373 /* set new write size for uvm */ 2374 uvm_vnp_setwritesize(vp, old_size); 2375 2376 /* write out evacuated data */ 2377 error = vn_rdwr(UIO_WRITE, udf_node->vnode, 2378 evacuated_data, old_size, 0, 2379 UIO_SYSSPACE, IO_ALTSEMANTICS | IO_NODELOCKED, 2380 FSCRED, NULL, NULL); 2381 uvm_vnp_setsize(vp, old_size); 2382 } 2383 2384 errorout: 2385 if (evacuated_data) 2386 free(evacuated_data, M_UDFTEMP); 2387 2388 udf_count_alloc_exts(udf_node); 2389 2390 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2391 UDF_UNLOCK_NODE(udf_node, 0); 2392 2393 KASSERT(new_inflen == orig_inflen + size_diff); 2394 KASSERT(new_lbrec == orig_lbrec); 2395 2396 return error; 2397 } 2398 2399 /* --------------------------------------------------------------------- */ 2400 2401 int 2402 udf_shrink_node(struct udf_node *udf_node, uint64_t new_size) 2403 { 2404 struct vnode *vp = udf_node->vnode; 2405 struct udf_mount *ump = udf_node->ump; 2406 struct file_entry *fe; 2407 struct extfile_entry *efe; 2408 struct icb_tag *icbtag; 2409 struct long_ad c_ad, s_ad, *node_ad_cpy; 2410 uint64_t size_diff, old_size, inflen, objsize; 2411 uint64_t foffset, end_foffset; 2412 uint64_t orig_inflen, orig_lbrec, new_inflen, new_lbrec; 2413 uint32_t lb_size, dscr_size, crclen; 2414 uint32_t slot_offset; 2415 uint32_t len, flags, max_len; 2416 uint32_t num_lb, lb_num; 2417 uint32_t max_l_ad, l_ad, l_ea; 2418 uint16_t vpart_num; 2419 uint8_t *data_pos; 2420 int icbflags, addr_type; 2421 int slot, cpy_slot, cpy_slots; 2422 int eof, error; 2423 2424 DPRINTF(ALLOC, ("udf_shrink_node\n")); 2425 2426 UDF_LOCK_NODE(udf_node, 0); 2427 udf_node_sanity_check(udf_node, &orig_inflen, &orig_lbrec); 2428 2429 lb_size = udf_rw32(ump->logical_vol->lb_size); 2430 max_len = ((UDF_EXT_MAXLEN / lb_size) * lb_size); 2431 2432 /* do the work */ 2433 fe = udf_node->fe; 2434 efe = udf_node->efe; 2435 if (fe) { 2436 icbtag = &fe->icbtag; 2437 inflen = udf_rw64(fe->inf_len); 2438 objsize = inflen; 2439 dscr_size = sizeof(struct file_entry) -1; 2440 l_ea = udf_rw32(fe->l_ea); 2441 l_ad = udf_rw32(fe->l_ad); 2442 data_pos = (uint8_t *) fe + dscr_size + l_ea; 2443 } else { 2444 icbtag = &efe->icbtag; 2445 inflen = udf_rw64(efe->inf_len); 2446 objsize = udf_rw64(efe->obj_size); 2447 dscr_size = sizeof(struct extfile_entry) -1; 2448 l_ea = udf_rw32(efe->l_ea); 2449 l_ad = udf_rw32(efe->l_ad); 2450 data_pos = (uint8_t *) efe + dscr_size + l_ea; 2451 } 2452 max_l_ad = lb_size - dscr_size - l_ea; 2453 2454 icbflags = udf_rw16(icbtag->flags); 2455 addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2456 2457 old_size = inflen; 2458 size_diff = old_size - new_size; 2459 2460 DPRINTF(ALLOC, ("\tfrom %"PRIu64" to %"PRIu64"\n", old_size, new_size)); 2461 2462 /* shrink the node to its new size */ 2463 if (addr_type == UDF_ICB_INTERN_ALLOC) { 2464 /* only reflect size change directly in the node */ 2465 KASSERT(new_size <= max_l_ad); 2466 inflen -= size_diff; 2467 objsize -= size_diff; 2468 l_ad -= size_diff; 2469 crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; 2470 if (fe) { 2471 fe->inf_len = udf_rw64(inflen); 2472 fe->l_ad = udf_rw32(l_ad); 2473 fe->tag.desc_crc_len = udf_rw32(crclen); 2474 } else { 2475 efe->inf_len = udf_rw64(inflen); 2476 efe->obj_size = udf_rw64(objsize); 2477 efe->l_ad = udf_rw32(l_ad); 2478 efe->tag.desc_crc_len = udf_rw32(crclen); 2479 } 2480 error = 0; 2481 2482 /* clear the space in the descriptor */ 2483 KASSERT(old_size > new_size); 2484 memset(data_pos + new_size, 0, old_size - new_size); 2485 2486 /* TODO zero appened space in buffer! */ 2487 /* using uvm_vnp_zerorange(vp, old_size, old_size - new_size); ? */ 2488 2489 /* set new size for uvm */ 2490 uvm_vnp_setsize(vp, new_size); 2491 2492 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2493 UDF_UNLOCK_NODE(udf_node, 0); 2494 2495 KASSERT(new_inflen == orig_inflen - size_diff); 2496 KASSERT(new_lbrec == orig_lbrec); 2497 KASSERT(new_lbrec == 0); 2498 2499 return 0; 2500 } 2501 2502 /* setup node cleanup extents copy space */ 2503 node_ad_cpy = malloc(lb_size * UDF_MAX_ALLOC_EXTENTS, 2504 M_UDFMNT, M_WAITOK); 2505 memset(node_ad_cpy, 0, lb_size * UDF_MAX_ALLOC_EXTENTS); 2506 2507 /* 2508 * Shrink the node by releasing the allocations and truncate the last 2509 * allocation to the new size. If the new size fits into the 2510 * allocation descriptor itself, transform it into an 2511 * UDF_ICB_INTERN_ALLOC. 2512 */ 2513 slot = 0; 2514 cpy_slot = 0; 2515 foffset = 0; 2516 2517 /* 1) copy till first overlap piece to the rewrite buffer */ 2518 for (;;) { 2519 udf_get_adslot(udf_node, slot, &s_ad, &eof); 2520 if (eof) { 2521 DPRINTF(WRITE, 2522 ("Shrink node failed: " 2523 "encountered EOF\n")); 2524 error = EINVAL; 2525 goto errorout; /* panic? */ 2526 } 2527 len = udf_rw32(s_ad.len); 2528 flags = UDF_EXT_FLAGS(len); 2529 len = UDF_EXT_LEN(len); 2530 2531 if (flags == UDF_EXT_REDIRECT) { 2532 slot++; 2533 continue; 2534 } 2535 2536 end_foffset = foffset + len; 2537 if (end_foffset > new_size) 2538 break; /* found */ 2539 2540 node_ad_cpy[cpy_slot++] = s_ad; 2541 2542 DPRINTF(ALLOC, ("\t1: vp %d, lb %d, len %d, flags %d " 2543 "-> stack\n", 2544 udf_rw16(s_ad.loc.part_num), 2545 udf_rw32(s_ad.loc.lb_num), 2546 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2547 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2548 2549 foffset = end_foffset; 2550 slot++; 2551 } 2552 slot_offset = new_size - foffset; 2553 2554 /* 2) trunc overlapping slot at overlap and copy it */ 2555 if (slot_offset > 0) { 2556 lb_num = udf_rw32(s_ad.loc.lb_num); 2557 vpart_num = udf_rw16(s_ad.loc.part_num); 2558 2559 if (flags == UDF_EXT_ALLOCATED) { 2560 /* note: round DOWN on num_lb */ 2561 lb_num += (slot_offset + lb_size -1) / lb_size; 2562 num_lb = (len - slot_offset) / lb_size; 2563 2564 udf_free_allocated_space(ump, lb_num, vpart_num, num_lb); 2565 } 2566 2567 s_ad.len = udf_rw32(slot_offset | flags); 2568 node_ad_cpy[cpy_slot++] = s_ad; 2569 slot++; 2570 2571 DPRINTF(ALLOC, ("\t2: vp %d, lb %d, len %d, flags %d " 2572 "-> stack\n", 2573 udf_rw16(s_ad.loc.part_num), 2574 udf_rw32(s_ad.loc.lb_num), 2575 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2576 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2577 } 2578 2579 /* 3) delete remainder */ 2580 for (;;) { 2581 udf_get_adslot(udf_node, slot, &s_ad, &eof); 2582 if (eof) 2583 break; 2584 2585 len = udf_rw32(s_ad.len); 2586 flags = UDF_EXT_FLAGS(len); 2587 len = UDF_EXT_LEN(len); 2588 2589 if (flags == UDF_EXT_REDIRECT) { 2590 slot++; 2591 continue; 2592 } 2593 2594 DPRINTF(ALLOC, ("\t3: delete remainder " 2595 "vp %d lb %d, len %d, flags %d\n", 2596 udf_rw16(s_ad.loc.part_num), 2597 udf_rw32(s_ad.loc.lb_num), 2598 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2599 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2600 2601 if (flags == UDF_EXT_ALLOCATED) { 2602 lb_num = udf_rw32(s_ad.loc.lb_num); 2603 vpart_num = udf_rw16(s_ad.loc.part_num); 2604 num_lb = (len + lb_size - 1) / lb_size; 2605 2606 udf_free_allocated_space(ump, lb_num, vpart_num, 2607 num_lb); 2608 } 2609 2610 slot++; 2611 } 2612 2613 /* 4) if it will fit into the descriptor then convert */ 2614 if (new_size < max_l_ad) { 2615 /* 2616 * resque/evacuate old piece by reading it in, and convert it 2617 * to internal alloc. 2618 */ 2619 if (new_size == 0) { 2620 /* XXX/TODO only for zero sizing now */ 2621 udf_wipe_adslots(udf_node); 2622 2623 icbflags &= ~UDF_ICB_TAG_FLAGS_ALLOC_MASK; 2624 icbflags |= UDF_ICB_INTERN_ALLOC; 2625 icbtag->flags = udf_rw16(icbflags); 2626 2627 inflen -= size_diff; KASSERT(inflen == 0); 2628 objsize -= size_diff; 2629 l_ad = new_size; 2630 crclen = dscr_size - UDF_DESC_TAG_LENGTH + l_ea + l_ad; 2631 if (fe) { 2632 fe->inf_len = udf_rw64(inflen); 2633 fe->l_ad = udf_rw32(l_ad); 2634 fe->tag.desc_crc_len = udf_rw32(crclen); 2635 } else { 2636 efe->inf_len = udf_rw64(inflen); 2637 efe->obj_size = udf_rw64(objsize); 2638 efe->l_ad = udf_rw32(l_ad); 2639 efe->tag.desc_crc_len = udf_rw32(crclen); 2640 } 2641 /* eventually copy in evacuated piece */ 2642 /* set new size for uvm */ 2643 uvm_vnp_setsize(vp, new_size); 2644 2645 free(node_ad_cpy, M_UDFMNT); 2646 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2647 2648 UDF_UNLOCK_NODE(udf_node, 0); 2649 2650 KASSERT(new_inflen == orig_inflen - size_diff); 2651 KASSERT(new_inflen == 0); 2652 KASSERT(new_lbrec == 0); 2653 2654 return 0; 2655 } 2656 2657 printf("UDF_SHRINK_NODE: could convert to internal alloc!\n"); 2658 } 2659 2660 /* 5) reset node descriptors */ 2661 udf_wipe_adslots(udf_node); 2662 2663 /* 6) copy back extents; merge when possible. Recounting on the fly */ 2664 cpy_slots = cpy_slot; 2665 2666 c_ad = node_ad_cpy[0]; 2667 slot = 0; 2668 for (cpy_slot = 1; cpy_slot < cpy_slots; cpy_slot++) { 2669 s_ad = node_ad_cpy[cpy_slot]; 2670 2671 DPRINTF(ALLOC, ("\t6: stack -> got mapping vp %d " 2672 "lb %d, len %d, flags %d\n", 2673 udf_rw16(s_ad.loc.part_num), 2674 udf_rw32(s_ad.loc.lb_num), 2675 UDF_EXT_LEN(udf_rw32(s_ad.len)), 2676 UDF_EXT_FLAGS(udf_rw32(s_ad.len)) >> 30)); 2677 2678 /* see if we can merge */ 2679 if (udf_ads_merge(lb_size, &c_ad, &s_ad)) { 2680 /* not mergable (anymore) */ 2681 DPRINTF(ALLOC, ("\t6: appending vp %d lb %d, " 2682 "len %d, flags %d\n", 2683 udf_rw16(c_ad.loc.part_num), 2684 udf_rw32(c_ad.loc.lb_num), 2685 UDF_EXT_LEN(udf_rw32(c_ad.len)), 2686 UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); 2687 2688 error = udf_append_adslot(udf_node, &slot, &c_ad); 2689 if (error) 2690 goto errorout; /* panic? */ 2691 c_ad = s_ad; 2692 slot++; 2693 } 2694 } 2695 2696 /* 7) push rest slot (if any) */ 2697 if (UDF_EXT_LEN(c_ad.len) > 0) { 2698 DPRINTF(ALLOC, ("\t7: last append vp %d lb %d, " 2699 "len %d, flags %d\n", 2700 udf_rw16(c_ad.loc.part_num), 2701 udf_rw32(c_ad.loc.lb_num), 2702 UDF_EXT_LEN(udf_rw32(c_ad.len)), 2703 UDF_EXT_FLAGS(udf_rw32(c_ad.len)) >> 30)); 2704 2705 error = udf_append_adslot(udf_node, &slot, &c_ad); 2706 if (error) 2707 goto errorout; /* panic? */ 2708 ; 2709 } 2710 2711 inflen -= size_diff; 2712 objsize -= size_diff; 2713 if (fe) { 2714 fe->inf_len = udf_rw64(inflen); 2715 } else { 2716 efe->inf_len = udf_rw64(inflen); 2717 efe->obj_size = udf_rw64(objsize); 2718 } 2719 error = 0; 2720 2721 /* set new size for uvm */ 2722 uvm_vnp_setsize(vp, new_size); 2723 2724 errorout: 2725 free(node_ad_cpy, M_UDFMNT); 2726 2727 udf_count_alloc_exts(udf_node); 2728 2729 udf_node_sanity_check(udf_node, &new_inflen, &new_lbrec); 2730 UDF_UNLOCK_NODE(udf_node, 0); 2731 2732 KASSERT(new_inflen == orig_inflen - size_diff); 2733 2734 return error; 2735 } 2736 2737