1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/t_lock.h> 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/systm.h> 34 #include <sys/sysmacros.h> 35 #include <sys/resource.h> 36 #include <sys/signal.h> 37 #include <sys/cred.h> 38 #include <sys/user.h> 39 #include <sys/buf.h> 40 #include <sys/vfs.h> 41 #include <sys/stat.h> 42 #include <sys/vnode.h> 43 #include <sys/mode.h> 44 #include <sys/proc.h> 45 #include <sys/disp.h> 46 #include <sys/file.h> 47 #include <sys/fcntl.h> 48 #include <sys/flock.h> 49 #include <sys/kmem.h> 50 #include <sys/uio.h> 51 #include <sys/dnlc.h> 52 #include <sys/conf.h> 53 #include <sys/errno.h> 54 #include <sys/mman.h> 55 #include <sys/fbuf.h> 56 #include <sys/pathname.h> 57 #include <sys/debug.h> 58 #include <sys/vmsystm.h> 59 #include <sys/cmn_err.h> 60 #include <sys/dirent.h> 61 #include <sys/errno.h> 62 #include <sys/modctl.h> 63 #include <sys/statvfs.h> 64 #include <sys/mount.h> 65 #include <sys/sunddi.h> 66 #include <sys/bootconf.h> 67 68 #include <vm/hat.h> 69 #include <vm/page.h> 70 #include <vm/pvn.h> 71 #include <vm/as.h> 72 #include <vm/seg.h> 73 #include <vm/seg_map.h> 74 #include <vm/seg_kmem.h> 75 #include <vm/seg_vn.h> 76 #include <vm/rm.h> 77 #include <vm/page.h> 78 #include <sys/swap.h> 79 80 81 #include <fs/fs_subr.h> 82 83 84 #include <sys/fs/udf_volume.h> 85 #include <sys/fs/udf_inode.h> 86 87 88 int32_t ud_break_create_new_icb(struct ud_inode *, int32_t, uint32_t); 89 int32_t ud_bump_ext_count(struct ud_inode *, int32_t); 90 void ud_remove_ext_at_index(struct ud_inode *, int32_t); 91 int32_t ud_last_alloc_ext(struct ud_inode *, uint64_t, uint32_t, int32_t); 92 int32_t ud_create_ext(struct ud_inode *, int32_t, uint32_t, 93 int32_t, uint64_t, uint64_t *); 94 int32_t ud_zero_it(struct ud_inode *, uint32_t, uint32_t); 95 96 #define ALLOC_SPACE 0x01 97 #define NEW_EXT 0x02 98 99 #define MEXT_BITS 30 100 101 int32_t 102 ud_bmap_has_holes(struct ud_inode *ip) 103 { 104 int32_t i, error = 0; 105 struct icb_ext *iext; 106 107 ud_printf("ud_bmap_has_holes\n"); 108 109 ASSERT(RW_LOCK_HELD(&ip->i_contents)); 110 111 /* ICB_FLAG_ONE_AD is always continuos */ 112 if (ip->i_desc_type != ICB_FLAG_ONE_AD) { 113 if ((error = ud_read_icb_till_off(ip, ip->i_size)) == 0) { 114 for (i = 0; i < ip->i_ext_used; i++) { 115 iext = &ip->i_ext[i]; 116 if (iext->ib_flags == IB_UN_RE_AL) { 117 error = 1; 118 break; 119 } 120 } 121 } 122 } 123 124 return (error); 125 } 126 127 int32_t 128 ud_bmap_read(struct ud_inode *ip, u_offset_t off, daddr_t *bnp, int32_t *lenp) 129 { 130 struct icb_ext *iext; 131 daddr_t bno; 132 int32_t lbmask, i, l2b, l2d, error = 0, count; 133 uint32_t length, block, dummy; 134 135 ud_printf("ud_bmap_read\n"); 136 137 ASSERT(RW_LOCK_HELD(&ip->i_contents)); 138 139 lbmask = ip->i_udf->udf_lbmask; 140 l2b = ip->i_udf->udf_l2b_shift; 141 l2d = ip->i_udf->udf_l2d_shift; 142 143 if ((error = ud_read_icb_till_off(ip, ip->i_size)) == 0) { 144 for (i = 0; i < ip->i_ext_used; i++) { 145 iext = &ip->i_ext[i]; 146 if ((iext->ib_offset <= off) && 147 (off < (iext->ib_offset + iext->ib_count))) { 148 length = ((iext->ib_offset + 149 iext->ib_count - off) + 150 lbmask) & ~lbmask; 151 if (iext->ib_flags == IB_UN_RE_AL) { 152 *bnp = UDF_HOLE; 153 *lenp = length; 154 break; 155 } 156 157 block = iext->ib_block + 158 ((off - iext->ib_offset) >> l2b); 159 count = length >> l2b; 160 161 bno = ud_xlate_to_daddr(ip->i_udf, 162 iext->ib_prn, block, count, &dummy); 163 ASSERT(dummy != 0); 164 ASSERT(dummy <= count); 165 *bnp = bno << l2d; 166 *lenp = dummy << l2b; 167 168 break; 169 } 170 } 171 if (i == ip->i_ext_used) { 172 error = EINVAL; 173 } 174 } 175 176 return (error); 177 } 178 179 180 /* 181 * Extent allocation in the inode 182 * Initially when the inode is allocated we 183 * will allocate EXT_PER_MALLOC extents and once these 184 * are used we allocate another 10 and copy 185 * the old extents and start using the others 186 */ 187 #define BASE(count) ((count) & ~lbmask) 188 #define CEIL(count) (((count) + lbmask) & ~lbmask) 189 190 #define PBASE(count) ((count) & PAGEMASK) 191 #define PCEIL(count) (((count) + PAGEOFFSET) & PAGEMASK) 192 193 194 /* ARGSUSED3 */ 195 int32_t 196 ud_bmap_write(struct ud_inode *ip, 197 u_offset_t off, int32_t size, int32_t alloc_only, struct cred *cr) 198 { 199 int32_t error = 0, i, isdir, issync; 200 struct udf_vfs *udf_vfsp; 201 struct icb_ext *iext, *pext; 202 uint32_t blkno, sz; 203 u_offset_t isize; 204 uint32_t acount, prox; 205 int32_t blkcount, next; 206 int32_t lbmask, l2b; 207 uint64_t end_req, end_ext, mext_sz, icb_offset, count; 208 int32_t dtype_changed = 0, memory_allocated = 0; 209 struct fbuf *fbp = NULL; 210 211 212 ud_printf("ud_bmap_write\n"); 213 214 ASSERT(RW_WRITE_HELD(&ip->i_contents)); 215 216 udf_vfsp = ip->i_udf; 217 lbmask = udf_vfsp->udf_lbmask; 218 l2b = udf_vfsp->udf_l2b_shift; 219 mext_sz = (1 << MEXT_BITS) - PAGESIZE; 220 221 if (lblkno(udf_vfsp, off) < 0) { 222 return (EFBIG); 223 } 224 225 issync = ((ip->i_flag & ISYNC) != 0); 226 227 isdir = (ip->i_type == VDIR); 228 if (isdir || issync) { 229 alloc_only = 0; /* make sure */ 230 } 231 232 end_req = BASE(off) + size; 233 if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 234 if (end_req < ip->i_max_emb) { 235 goto out; 236 } 237 238 if (ip->i_size != 0) { 239 error = fbread(ITOV(ip), 0, ip->i_size, S_OTHER, &fbp); 240 if (error != 0) { 241 goto out; 242 } 243 } else { 244 fbp = NULL; 245 } 246 /* 247 * Change the desc_type 248 */ 249 ip->i_desc_type = ICB_FLAG_SHORT_AD; 250 dtype_changed = 1; 251 252 one_ad_no_i_ext: 253 ASSERT(ip->i_ext == NULL); 254 ASSERT(ip->i_astrat == STRAT_TYPE4); 255 256 ip->i_ext_used = 0; 257 ip->i_cur_max_ext = ip->i_max_emb / sizeof (struct short_ad); 258 ip->i_cur_max_ext --; 259 if (end_req > mext_sz) { 260 next = end_req / mext_sz; 261 } else { 262 next = 1; 263 } 264 ip->i_ext_count = 265 ((next / EXT_PER_MALLOC) + 1) * EXT_PER_MALLOC; 266 iext = ip->i_ext = (struct icb_ext *)kmem_zalloc( 267 ip->i_ext_count * sizeof (struct icb_ext), KM_SLEEP); 268 memory_allocated = 1; 269 270 /* There will be atleast EXT_PER_MALLOC icb_ext's allocated */ 271 272 one_ad_i_ext: 273 icb_offset = 0; 274 count = end_req; 275 276 /* Can we create a HOLE */ 277 278 if ((PCEIL(ip->i_size) < PBASE(off)) && 279 ((PBASE(off) - PCEIL(ip->i_size)) >= PAGESIZE)) { 280 281 if (ip->i_size != 0) { 282 283 /* 284 * Allocate one block for 285 * old data.(cannot be more than one page) 286 */ 287 288 count = PAGESIZE; 289 if (error = ud_create_ext(ip, ip->i_ext_used, 290 ALLOC_SPACE | NEW_EXT, alloc_only, 291 icb_offset, &count)) { 292 goto embedded_error; 293 } 294 icb_offset = PAGESIZE; 295 } 296 297 /* 298 * Allocate a hole from PCEIL(ip->i_size) to PBASE(off) 299 */ 300 301 count = PBASE(off) - PCEIL(ip->i_size); 302 (void) ud_create_ext(ip, ip->i_ext_used, NEW_EXT, 303 alloc_only, icb_offset, &count); 304 icb_offset = PBASE(off); 305 306 /* 307 * Allocate the rest of the space PBASE(off) to end_req 308 */ 309 count = end_req - PBASE(off); 310 } else { 311 /* 312 * If no hole can be created then allocate 313 * space till the end of the request 314 */ 315 count = end_req; 316 } 317 318 319 320 if (error = ud_create_ext(ip, ip->i_ext_used, 321 ALLOC_SPACE | NEW_EXT, 322 alloc_only, icb_offset, &count)) { 323 embedded_error: 324 /* 325 * Something error 326 * most probable file system is full 327 * we know that the file came in as a embedded file. 328 * undo what ever we did in this block of code 329 */ 330 if (dtype_changed) { 331 ip->i_desc_type = ICB_FLAG_ONE_AD; 332 } 333 for (i = 0; i < ip->i_ext_used; i++) { 334 iext = &ip->i_ext[i]; 335 if (iext->ib_flags != IB_UN_RE_AL) { 336 ud_free_space(ip->i_udf->udf_vfs, 337 iext->ib_prn, iext->ib_block, 338 (iext->ib_count + lbmask) >> 339 l2b); 340 } 341 } 342 if (memory_allocated) { 343 kmem_free(ip->i_ext, 344 ip->i_ext_count * 345 sizeof (struct icb_ext)); 346 ip->i_ext = NULL; 347 ip->i_ext_count = ip->i_ext_used = 0; 348 } 349 } 350 351 if (fbp != NULL) { 352 fbrelse(fbp, S_WRITE); 353 } 354 355 return (error); 356 } else { 357 358 /* 359 * Type 4 directories being created 360 */ 361 if (ip->i_ext == NULL) { 362 goto one_ad_no_i_ext; 363 } 364 365 /* 366 * Read the entire icb's to memory 367 */ 368 if (ud_read_icb_till_off(ip, ip->i_size) != 0) { 369 error = EINVAL; 370 goto out; 371 } 372 373 isize = CEIL(ip->i_size); 374 375 if (end_req > isize) { 376 377 /* 378 * The new file size is greater 379 * than the old size 380 */ 381 382 if (ip->i_ext == NULL) { 383 goto one_ad_no_i_ext; 384 } else if (ip->i_ext_used == 0) { 385 goto one_ad_i_ext; 386 } 387 388 error = ud_last_alloc_ext(ip, off, size, alloc_only); 389 390 return (error); 391 } else { 392 393 /* 394 * File growing the new size will be less than 395 * iext->ib_offset + CEIL(iext->ib_count) 396 */ 397 398 iext = &ip->i_ext[ip->i_ext_used - 1]; 399 400 if (end_req > (iext->ib_offset + iext->ib_count)) { 401 402 iext->ib_count = end_req - iext->ib_offset; 403 404 if (iext->ib_flags != IB_UN_RE_AL) { 405 error = 0; 406 goto out; 407 } 408 } 409 } 410 } 411 412 /* By this point the end of last extent is >= BASE(off) + size */ 413 414 ASSERT(ip->i_ext); 415 416 /* 417 * Figure out the icb_ext that has offset "off" 418 */ 419 for (i = 0; i < ip->i_ext_used; i++) { 420 iext = &ip->i_ext[i]; 421 if ((iext->ib_offset <= off) && 422 ((iext->ib_offset + iext->ib_count) > off)) { 423 break; 424 } 425 } 426 427 /* 428 * iext will have offset "off" 429 */ 430 431 432 do { 433 iext = &ip->i_ext[i]; 434 435 if ((iext->ib_flags & IB_UN_RE_AL) == 0) { 436 437 /* 438 * Already allocated do nothing 439 */ 440 441 i++; 442 } else { 443 444 /* 445 * We are in a hole. 446 * allocate the required space 447 * while trying to create smaller holes 448 */ 449 450 if ((PBASE(off) > PBASE(iext->ib_offset)) && 451 ((PBASE(off) - PBASE(iext->ib_offset)) >= 452 PAGESIZE)) { 453 454 /* 455 * Allocate space from begining of 456 * old hole to the begining of new hole 457 * We want all holes created by us 458 * to be MMUPAGE Aligned 459 */ 460 461 if (PBASE(iext->ib_offset) != 462 BASE(iext->ib_offset)) { 463 if ((error = ud_break_create_new_icb( 464 ip, i, BASE(iext->ib_offset) - 465 PBASE(iext->ib_offset))) != 0) { 466 return (error); 467 } 468 goto alloc_cur_ext; 469 } 470 471 /* 472 * Create the new hole 473 */ 474 475 if ((error = ud_break_create_new_icb(ip, i, 476 PBASE(off) - iext->ib_offset)) != 0) { 477 return (error); 478 } 479 iext = &ip->i_ext[i]; 480 i++; 481 continue; 482 } 483 484 end_ext = iext->ib_offset + iext->ib_count; 485 486 if ((PBASE(end_ext) > PCEIL(end_req)) && 487 ((PBASE(end_ext) - PCEIL(end_req)) >= 488 PAGESIZE)) { 489 /* 490 * We can create a hole 491 * from PCEIL(end_req) - BASE(end_ext) 492 */ 493 if ((error = ud_break_create_new_icb(ip, i, 494 PCEIL(end_req) - iext->ib_offset)) != 0) { 495 return (error); 496 } 497 } 498 499 500 alloc_cur_ext: 501 /* 502 * Allocate the current extent 503 */ 504 505 506 /* 507 * If the previous extent 508 * is allocated then try to allocate 509 * adjascent to the previous extent 510 */ 511 prox = 0; 512 if (i != 0) { 513 pext = &ip->i_ext[i - 1]; 514 if (pext->ib_flags != IB_UN_RE_AL) { 515 prox = pext->ib_block + 516 (CEIL(pext->ib_count) >> l2b); 517 } 518 } 519 520 iext = &ip->i_ext[i]; 521 blkcount = CEIL(iext->ib_count) >> l2b; 522 523 if ((error = ud_alloc_space(ip->i_vfs, 524 ip->i_icb_prn, prox, blkcount, 525 &blkno, &sz, 1, 0)) != 0) { 526 return (error); 527 } 528 ip->i_lbr += sz; 529 if (sz == 0) { 530 return (ENOSPC); 531 } 532 533 if (alloc_only == 0) { 534 error = ud_zero_it(ip, blkno, sz); 535 } 536 537 acount = sz << l2b; 538 if ((prox == blkno) && 539 ((pext->ib_count + acount) < mext_sz)) { 540 541 /* 542 * We are able to allocate adjascent to 543 * the previous extent. Increment the 544 * previous extent count if the size 545 * of the extent is not greater than 546 * max extent size 547 */ 548 549 pext = &ip->i_ext[i - 1]; 550 pext->ib_count += acount; 551 552 if (sz == blkcount) { 553 /* 554 * and get rid of the current 555 * extent since we have 556 * allocated all of its size 557 * and incremented the 558 * previous extents count 559 */ 560 ud_remove_ext_at_index(ip, i); 561 } else { 562 /* 563 * reduce the count of the 564 * current extent by the amount 565 * allocated in the last extent 566 */ 567 ASSERT(acount < iext->ib_count); 568 iext->ib_count -= acount; 569 iext->ib_offset += acount; 570 } 571 } else { 572 if (sz < blkcount) { 573 if ((error = ud_break_create_new_icb( 574 ip, i, sz << l2b)) != 0) { 575 return (error); 576 } 577 } 578 iext = &ip->i_ext[i]; 579 count -= CEIL(iext->ib_count); 580 iext->ib_prn = ip->i_icb_prn; 581 iext->ib_block = blkno; 582 iext->ib_flags &= ~IB_UN_RE_AL; 583 /* 584 * iext->ib_flags |= IB_UN_REC; 585 */ 586 i++; 587 continue; 588 } 589 } 590 } while ((iext->ib_offset + iext->ib_count) < end_req); 591 592 out: 593 return (error); 594 } 595 596 597 /* 598 * increase i_con/i_ext arrays and set new elements 599 * using long or short allocation descriptors 600 */ 601 static void 602 ud_common_ad(struct ud_inode *ip, struct buf *bp) 603 { 604 int32_t ndesc, count, lbmask; 605 uint32_t length; 606 struct alloc_ext_desc *aed; 607 struct icb_ext *iext, *con; 608 u_offset_t offset; 609 long_ad_t *lad; 610 short_ad_t *sad; 611 int islong; 612 void *addr; 613 614 addr = bp->b_un.b_addr + sizeof (struct alloc_ext_desc); 615 aed = (struct alloc_ext_desc *)bp->b_un.b_addr; 616 length = SWAP_32(aed->aed_len_aed); 617 if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 618 islong = 1; 619 lad = addr; 620 ndesc = length / sizeof (*lad); 621 } else if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 622 islong = 0; 623 sad = addr; 624 ndesc = length / sizeof (*sad); 625 } else 626 return; 627 628 /* 629 * realloc i_ext array 630 */ 631 count = (((ip->i_ext_used + ndesc) / EXT_PER_MALLOC) + 1) * 632 EXT_PER_MALLOC; 633 addr = kmem_zalloc(count * sizeof (struct icb_ext), KM_SLEEP); 634 bcopy(ip->i_ext, addr, ip->i_ext_used * sizeof (struct icb_ext)); 635 kmem_free(ip->i_ext, ip->i_ext_count * sizeof (struct icb_ext)); 636 ip->i_ext = addr; 637 ip->i_ext_count = count; 638 639 /* 640 * scan descriptors 641 */ 642 lbmask = ip->i_udf->udf_lbmask; 643 iext = &ip->i_ext[ip->i_ext_used - 1]; 644 offset = iext->ib_offset + iext->ib_count; 645 iext++; 646 while (ndesc--) { 647 if (islong) 648 length = SWAP_32(lad->lad_ext_len); 649 else 650 length = SWAP_32(sad->sad_ext_len); 651 652 if ((length & 0x3FFFFFFF) == 0) 653 break; 654 else if (((length >> 30) & IB_MASK) == IB_CON) { 655 if (ip->i_con_used == ip->i_con_count) { 656 struct icb_ext *old; 657 int32_t old_count; 658 659 old = ip->i_con; 660 old_count = ip->i_con_count * 661 sizeof (struct icb_ext); 662 ip->i_con_count += EXT_PER_MALLOC; 663 ip->i_con = kmem_zalloc(ip->i_con_count * 664 sizeof (struct icb_ext), KM_SLEEP); 665 666 if (old) { 667 bcopy(old, ip->i_con, old_count); 668 kmem_free(old, old_count); 669 } 670 } 671 con = &ip->i_con[ip->i_con_used]; 672 if (islong) { 673 con->ib_prn = SWAP_16(lad->lad_ext_prn); 674 con->ib_block = SWAP_32(lad->lad_ext_loc); 675 } else { 676 con->ib_prn = ip->i_icb_prn; 677 con->ib_block = SWAP_32(sad->sad_ext_loc); 678 } 679 con->ib_count = length & 0x3FFFFFFF; 680 con->ib_flags = (length >> 30) & IB_MASK; 681 ip->i_con_used++; 682 break; 683 } 684 685 if (islong) { 686 iext->ib_prn = SWAP_16(lad->lad_ext_prn); 687 iext->ib_block = SWAP_32(lad->lad_ext_loc); 688 lad++; 689 } else { 690 iext->ib_prn = 0; 691 iext->ib_block = SWAP_32(sad->sad_ext_loc); 692 sad++; 693 } 694 iext->ib_count = length & 0x3FFFFFFF; 695 iext->ib_offset = offset; 696 iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 697 iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 698 offset += (iext->ib_count + lbmask) & (~lbmask); 699 iext->ib_flags = (length >> 30) & IB_MASK; 700 ip->i_ext_used++; 701 iext++; 702 } 703 } 704 705 706 static int32_t 707 ud_read_next_cont(struct ud_inode *ip) 708 { 709 uint32_t dummy, error = 0; 710 struct alloc_ext_desc *aed; 711 struct icb_ext *cont; 712 struct buf *bp; 713 daddr_t bno; 714 715 cont = &ip->i_con[ip->i_con_read]; 716 ASSERT(cont->ib_count > 0); 717 718 bno = ud_xlate_to_daddr(ip->i_udf, cont->ib_prn, cont->ib_block, 719 1, &dummy); 720 bp = ud_bread(ip->i_dev, bno << ip->i_udf->udf_l2d_shift, 721 cont->ib_count); 722 if (bp->b_flags & B_ERROR) 723 error = bp->b_error; 724 else { 725 aed = (struct alloc_ext_desc *)bp->b_un.b_addr; 726 if (ud_verify_tag_and_desc(&aed->aed_tag, UD_ALLOC_EXT_DESC, 727 cont->ib_block, 1, cont->ib_count)) 728 error = EINVAL; 729 } 730 731 if (error == 0) 732 ud_common_ad(ip, bp); 733 734 brelse(bp); 735 return (error); 736 } 737 738 739 int32_t 740 ud_read_icb_till_off(struct ud_inode *ip, u_offset_t offset) 741 { 742 int32_t error = 0; 743 struct icb_ext *iext; 744 745 ud_printf("ud_read_icb_till_off\n"); 746 747 if (ip->i_desc_type == ICB_FLAG_ONE_AD) 748 return (0); 749 else if ((ip->i_astrat != STRAT_TYPE4) && 750 (ip->i_astrat != STRAT_TYPE4096)) 751 return (EINVAL); 752 else if (ip->i_ext_used == 0) 753 return ((ip->i_size == 0) ? 0 : EINVAL); 754 755 /* 756 * supported allocation strategies are 757 * STRAT_TYPE4 and STRAT_TYPE4096 758 */ 759 760 mutex_enter(&ip->i_con_lock); 761 iext = &ip->i_ext[ip->i_ext_used - 1]; 762 while ((iext->ib_offset + iext->ib_count) < offset) { 763 if (ip->i_con_used == ip->i_con_read) { 764 error = EINVAL; 765 break; 766 } 767 if (error = ud_read_next_cont(ip)) 768 break; 769 ip->i_con_read++; 770 iext = &ip->i_ext[ip->i_ext_used - 1]; 771 } 772 mutex_exit(&ip->i_con_lock); 773 774 return (error); 775 } 776 777 778 /* 779 * Assumption is the off is beyond ip->i_size 780 * And we will have atleast one ext used 781 */ 782 int32_t 783 ud_last_alloc_ext(struct ud_inode *ip, uint64_t off, 784 uint32_t size, int32_t alloc_only) 785 { 786 struct icb_ext *iext; 787 struct udf_vfs *udf_vfsp; 788 int32_t lbsize, lbmask; 789 uint64_t end_req, end_count, icb_offset; 790 uint64_t count; 791 int32_t error = 0; 792 793 794 udf_vfsp = ip->i_udf; 795 lbsize = udf_vfsp->udf_lbsize; 796 lbmask = udf_vfsp->udf_lbmask; 797 798 end_req = BASE(off) + size; 799 800 801 /* 802 * If we are here it means the file 803 * is growing beyond the end of the 804 * current block. So round up the 805 * last extent 806 */ 807 808 iext = &ip->i_ext[ip->i_ext_used - 1]; 809 iext->ib_count = CEIL(iext->ib_count); 810 811 /* 812 * Figure out if we can create 813 * a hole here 814 */ 815 816 817 end_count = iext->ib_offset + iext->ib_count; 818 819 if ((PCEIL(end_count) < PBASE(off)) && 820 ((PBASE(off) - PCEIL(end_count)) >= PAGESIZE)) { 821 822 count = PCEIL(end_count) - CEIL(end_count); 823 if (count >= lbsize) { 824 825 /* 826 * There is space between the begining 827 * of the hole to be created and 828 * end of the last offset 829 * Allocate blocks for it 830 */ 831 832 iext = &ip->i_ext[ip->i_ext_used - 1]; 833 icb_offset = iext->ib_offset + CEIL(iext->ib_count); 834 835 if (iext->ib_flags == IB_UN_RE_AL) { 836 837 /* 838 * Previous extent is a unallocated 839 * extent. Create a new allocated 840 * extent 841 */ 842 843 error = ud_create_ext(ip, ip->i_ext_used, 844 ALLOC_SPACE | NEW_EXT, 845 alloc_only, icb_offset, &count); 846 847 } else { 848 849 /* 850 * Last extent is allocated 851 * try to allocate adjascent to the 852 * last extent 853 */ 854 855 error = ud_create_ext(ip, ip->i_ext_used - 1, 856 ALLOC_SPACE, alloc_only, 857 icb_offset, &count); 858 } 859 860 if (error != 0) { 861 return (error); 862 } 863 } 864 865 iext = &ip->i_ext[ip->i_ext_used - 1]; 866 end_count = iext->ib_offset + iext->ib_count; 867 count = PBASE(off) - PCEIL(end_count); 868 icb_offset = PCEIL(end_count); 869 870 if (iext->ib_flags == IB_UN_RE_AL) { 871 872 /* 873 * The last extent is unallocated 874 * Just bump the extent count 875 */ 876 (void) ud_create_ext(ip, ip->i_ext_used - 1, 877 0, alloc_only, icb_offset, &count); 878 } else { 879 880 /* 881 * Last extent is allocated 882 * round up the size of the extent to 883 * lbsize and allocate a new unallocated extent 884 */ 885 iext->ib_count = CEIL(iext->ib_count); 886 (void) ud_create_ext(ip, ip->i_ext_used, 887 NEW_EXT, alloc_only, icb_offset, &count); 888 } 889 890 icb_offset = PBASE(off); 891 } else { 892 893 /* 894 * We cannot create any hole inbetween 895 * the last extent and the off so 896 * round up the count in the last extent 897 */ 898 899 iext = &ip->i_ext[ip->i_ext_used - 1]; 900 iext->ib_count = CEIL(iext->ib_count); 901 902 } 903 904 905 iext = &ip->i_ext[ip->i_ext_used - 1]; 906 count = end_req - (iext->ib_offset + iext->ib_count); 907 icb_offset = iext->ib_offset + CEIL(iext->ib_count); 908 909 if (iext->ib_flags == IB_UN_RE_AL) { 910 911 /* 912 * Last extent was a unallocated extent 913 * create a new extent 914 */ 915 916 error = ud_create_ext(ip, ip->i_ext_used, 917 ALLOC_SPACE | NEW_EXT, alloc_only, icb_offset, &count); 918 } else { 919 920 /* 921 * Last extent was an allocated extent 922 * try to allocate adjascent to the old blocks 923 */ 924 925 error = ud_create_ext(ip, ip->i_ext_used - 1, 926 ALLOC_SPACE, alloc_only, icb_offset, &count); 927 } 928 929 return (error); 930 } 931 932 /* 933 * Break up the icb_ext at index 934 * into two icb_ext, 935 * one at index ib_count "count" and 936 * the other at index+1 with ib_count = old_ib_count - count 937 */ 938 int32_t 939 ud_break_create_new_icb(struct ud_inode *ip, 940 int32_t index, uint32_t count) 941 { 942 int32_t i, error; 943 struct icb_ext *iext, *next; 944 945 946 ud_printf("ud_break_create_new_icb\n"); 947 iext = &ip->i_ext[index]; 948 949 ASSERT(count < iext->ib_count); 950 951 if ((error = ud_bump_ext_count(ip, KM_SLEEP)) != 0) { 952 return (error); 953 } 954 955 for (i = ip->i_ext_used; i > index; i--) { 956 ip->i_ext[i] = ip->i_ext[i - 1]; 957 } 958 959 next = &ip->i_ext[index + 1]; 960 iext = &ip->i_ext[index]; 961 962 iext->ib_count = count; 963 next->ib_count -= count; 964 next->ib_offset = iext->ib_offset + iext->ib_count; 965 if (iext->ib_flags != IB_UN_RE_AL) { 966 next->ib_block = iext->ib_block + 967 iext->ib_count >> ip->i_udf->udf_l2b_shift; 968 } 969 ip->i_ext_used++; 970 return (0); 971 } 972 973 void 974 ud_remove_ext_at_index(struct ud_inode *ip, int32_t index) 975 { 976 int32_t i; 977 978 ASSERT(index <= ip->i_ext_used); 979 980 for (i = index; i < ip->i_ext_used; i++) { 981 if ((i + 1) < ip->i_ext_count) { 982 ip->i_ext[i] = ip->i_ext[i + 1]; 983 } else { 984 bzero(&ip->i_ext[i], sizeof (struct icb_ext)); 985 } 986 } 987 ip->i_ext_used --; 988 } 989 990 int32_t 991 ud_bump_ext_count(struct ud_inode *ip, int32_t sleep_flag) 992 { 993 int32_t error = 0; 994 struct icb_ext *iext; 995 uint32_t old_count, elen; 996 997 ASSERT(ip); 998 ASSERT(sleep_flag == KM_SLEEP); 999 1000 ud_printf("ud_bump_ext_count\n"); 1001 1002 if (ip->i_ext_used >= ip->i_ext_count) { 1003 1004 old_count = sizeof (struct icb_ext) * ip->i_ext_count; 1005 ip->i_ext_count += EXT_PER_MALLOC; 1006 iext = kmem_zalloc(sizeof (struct icb_ext) * 1007 ip->i_ext_count, sleep_flag); 1008 bcopy(ip->i_ext, iext, old_count); 1009 kmem_free(ip->i_ext, old_count); 1010 ip->i_ext = iext; 1011 } 1012 1013 if (ip->i_ext_used >= ip->i_cur_max_ext) { 1014 int32_t prox; 1015 struct icb_ext *icon; 1016 uint32_t blkno, sz; 1017 int32_t lbmask, l2b; 1018 1019 lbmask = ip->i_udf->udf_lbmask; 1020 l2b = ip->i_udf->udf_l2b_shift; 1021 1022 if ((error = ud_read_icb_till_off(ip, ip->i_size)) != 0) { 1023 return (error); 1024 } 1025 1026 /* 1027 * If there are any old cont extents 1028 * allocate the new one ajscant to the old one 1029 */ 1030 if (ip->i_con_used != 0) { 1031 icon = &ip->i_con[ip->i_con_used - 1]; 1032 prox = icon->ib_block + (CEIL(icon->ib_count) >> l2b); 1033 } else { 1034 prox = 0; 1035 } 1036 1037 /* 1038 * Allocate space 1039 */ 1040 if ((error = ud_alloc_space(ip->i_vfs, ip->i_icb_prn, 1041 prox, 1, &blkno, &sz, 0, 0)) != 0) { 1042 return (error); 1043 } 1044 if (sz == 0) { 1045 return (ENOSPC); 1046 } 1047 1048 sz <<= l2b; 1049 1050 if (ip->i_con_used == ip->i_con_count) { 1051 struct icb_ext *old; 1052 int32_t old_count; 1053 1054 old = ip->i_con; 1055 old_count = ip->i_con_count * 1056 sizeof (struct icb_ext); 1057 ip->i_con_count += EXT_PER_MALLOC; 1058 ip->i_con = kmem_zalloc(ip->i_con_count * 1059 sizeof (struct icb_ext), KM_SLEEP); 1060 if (old != 0) { 1061 bcopy(old, ip->i_con, old_count); 1062 kmem_free(old, old_count); 1063 } 1064 } 1065 icon = &ip->i_con[ip->i_con_used++]; 1066 icon->ib_flags = IB_CON; 1067 icon->ib_prn = ip->i_icb_prn; 1068 icon->ib_block = blkno; 1069 icon->ib_count = sz; 1070 icon->ib_offset = 0; 1071 icon->ib_marker1 = (uint32_t)0xAAAAAAAA; 1072 icon->ib_marker2 = (uint32_t)0xBBBBBBBB; 1073 1074 /* 1075 * Bump the i_cur_max_ext according to 1076 * the space allocated 1077 */ 1078 if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 1079 elen = sizeof (struct short_ad); 1080 } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 1081 elen = sizeof (struct long_ad); 1082 } else { 1083 return (ENOSPC); 1084 } 1085 sz = sz - (sizeof (struct alloc_ext_desc) + elen); 1086 ip->i_cur_max_ext += sz / elen; 1087 } 1088 return (error); 1089 } 1090 1091 int32_t 1092 ud_create_ext(struct ud_inode *ip, int32_t index, uint32_t flags, 1093 int32_t alloc_only, uint64_t offset, uint64_t *count) 1094 { 1095 struct icb_ext *iext, *pext; 1096 struct udf_vfs *udf_vfsp; 1097 int32_t error = 0, blkcount, acount; 1098 uint32_t blkno, sz, prox, mext_sz; 1099 int32_t lbmask, l2b; 1100 1101 if (*count == 0) { 1102 return (0); 1103 } 1104 1105 begin: 1106 udf_vfsp = ip->i_udf; 1107 lbmask = udf_vfsp->udf_lbmask; 1108 l2b = udf_vfsp->udf_l2b_shift; 1109 mext_sz = (1 << MEXT_BITS) - PAGESIZE; 1110 1111 if ((error = ud_bump_ext_count(ip, KM_SLEEP)) != 0) { 1112 return (error); 1113 } 1114 1115 iext = &ip->i_ext[index]; 1116 if (flags & ALLOC_SPACE) { 1117 if ((flags & NEW_EXT) || 1118 (ip->i_ext_count == 0)) { 1119 1120 iext->ib_flags = 0; 1121 iext->ib_prn = ip->i_icb_prn; 1122 if (*count > mext_sz) { 1123 blkcount = mext_sz >> l2b; 1124 } else { 1125 blkcount = CEIL(*count) >> l2b; 1126 } 1127 if ((error = ud_alloc_space(ip->i_vfs, 1128 ip->i_icb_prn, 0, blkcount, 1129 &blkno, &sz, 1, 0)) != 0) { 1130 return (error); 1131 } 1132 if (sz == 0) { 1133 return (ENOSPC); 1134 } 1135 ip->i_lbr += sz; 1136 iext->ib_block = blkno; 1137 acount = sz << l2b; 1138 if ((sz << l2b) > *count) { 1139 iext->ib_count = *count; 1140 *count = 0; 1141 } else { 1142 iext->ib_count = sz << l2b; 1143 *count -= iext->ib_count; 1144 } 1145 iext->ib_offset = offset; 1146 if (ip->i_ext_used <= index) 1147 ip->i_ext_used ++; 1148 } else { 1149 if ((iext->ib_count + *count) > mext_sz) { 1150 blkcount = (mext_sz - iext->ib_count) >> l2b; 1151 } else { 1152 blkcount = CEIL(*count) >> l2b; 1153 } 1154 if (blkcount == 0) { 1155 flags |= NEW_EXT; 1156 index++; 1157 goto begin; 1158 } 1159 prox = iext->ib_block + (CEIL(iext->ib_count) >> l2b); 1160 if ((error = ud_alloc_space(ip->i_vfs, 1161 ip->i_icb_prn, prox, blkcount, 1162 &blkno, &sz, 1, 0)) != 0) { 1163 return (error); 1164 } 1165 if (sz == 0) { 1166 return (ENOSPC); 1167 } 1168 acount = sz << l2b; 1169 if (acount > *count) { 1170 acount = *count; 1171 *count = 0; 1172 } else { 1173 *count -= acount; 1174 } 1175 ip->i_lbr += sz; 1176 if (prox == blkno) { 1177 iext->ib_count += acount; 1178 } else { 1179 if ((error = ud_bump_ext_count(ip, KM_SLEEP)) 1180 != 0) { 1181 return (error); 1182 } 1183 pext = &ip->i_ext[index]; 1184 iext = &ip->i_ext[index + 1]; 1185 iext->ib_flags = 0; 1186 iext->ib_prn = ip->i_icb_prn; 1187 iext->ib_block = blkno; 1188 iext->ib_offset = 1189 pext->ib_offset + pext->ib_count; 1190 iext->ib_count = acount; 1191 /* 1192 * Increment the index, since we have used 1193 * the extent at [index+1] above. 1194 */ 1195 index++; 1196 if (ip->i_ext_used <= index) 1197 ip->i_ext_used ++; 1198 } 1199 } 1200 if (alloc_only == 0) { 1201 error = ud_zero_it(ip, blkno, sz); 1202 } 1203 if (*count) { 1204 offset = iext->ib_offset + CEIL(iext->ib_count); 1205 flags |= NEW_EXT; 1206 index++; 1207 goto begin; 1208 } 1209 } else { 1210 if (flags & NEW_EXT) { 1211 iext->ib_flags = IB_UN_RE_AL; 1212 iext->ib_prn = 0; 1213 iext->ib_block = 0; 1214 if (*count > mext_sz) { 1215 iext->ib_count = mext_sz; 1216 *count -= iext->ib_count; 1217 } else { 1218 iext->ib_count = *count; 1219 *count = 0; 1220 } 1221 iext->ib_offset = offset; 1222 if (ip->i_ext_used <= index) 1223 ip->i_ext_used ++; 1224 } else { 1225 ASSERT(iext->ib_flags == IB_UN_RE_AL); 1226 if ((iext->ib_count + *count) > mext_sz) { 1227 acount = mext_sz - iext->ib_count; 1228 iext->ib_count += acount; 1229 *count -= acount; 1230 } else { 1231 iext->ib_count += *count; 1232 *count = 0; 1233 } 1234 } 1235 if (*count != 0) { 1236 offset = iext->ib_offset + CEIL(iext->ib_count); 1237 flags |= NEW_EXT; 1238 index++; 1239 goto begin; 1240 } 1241 } 1242 iext->ib_marker1 = (uint32_t)0xAAAAAAAA; 1243 iext->ib_marker2 = (uint32_t)0xBBBBBBBB; 1244 return (error); 1245 } 1246 1247 #undef CEIL 1248 #undef BASE 1249 1250 int32_t 1251 ud_zero_it(struct ud_inode *ip, uint32_t start_block, uint32_t block_count) 1252 { 1253 struct udf_vfs *udf_vfsp; 1254 uint32_t bno, dummy; 1255 int32_t error; 1256 struct buf *bp; 1257 1258 /* 1259 * Donot use bio routines 1260 * since the buffer can sit 1261 * long enough in cache for the space 1262 * to be allocated/freed and 1263 * then allocated 1264 */ 1265 udf_vfsp = ip->i_udf; 1266 bno = ud_xlate_to_daddr(udf_vfsp, 1267 ip->i_icb_prn, start_block, block_count, &dummy); 1268 1269 dummy = block_count << udf_vfsp->udf_l2b_shift; 1270 bp = (struct buf *)kmem_zalloc(biosize(), KM_SLEEP); 1271 sema_init(&bp->b_sem, 0, NULL, SEMA_DEFAULT, NULL); 1272 sema_init(&bp->b_io, 0, NULL, SEMA_DEFAULT, NULL); 1273 1274 bp->b_flags = B_WRITE | B_BUSY; 1275 bp->b_edev = ip->i_dev; 1276 bp->b_dev = cmpdev(ip->i_dev); 1277 bp->b_blkno = bno << udf_vfsp->udf_l2d_shift; 1278 bp->b_bcount = dummy; 1279 bp->b_un.b_addr = kmem_zalloc(bp->b_bcount, KM_SLEEP); 1280 bp->b_file = ip->i_vnode; 1281 bp->b_offset = -1; 1282 1283 (void) bdev_strategy(bp); 1284 if (error = biowait(bp)) { 1285 cmn_err(CE_WARN, "error in write\n"); 1286 } 1287 1288 kmem_free(bp->b_un.b_addr, dummy); 1289 sema_destroy(&bp->b_io); 1290 sema_destroy(&bp->b_sem); 1291 kmem_free((caddr_t)bp, biosize()); 1292 1293 return (error); 1294 } 1295