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