| .. | .. |
|---|
| 45 | 45 | |
|---|
| 46 | 46 | #define EXTENT_MERGE_SIZE 5 |
|---|
| 47 | 47 | |
|---|
| 48 | +#define FE_MAPPED_PERMS (FE_PERM_U_READ | FE_PERM_U_WRITE | FE_PERM_U_EXEC | \ |
|---|
| 49 | + FE_PERM_G_READ | FE_PERM_G_WRITE | FE_PERM_G_EXEC | \ |
|---|
| 50 | + FE_PERM_O_READ | FE_PERM_O_WRITE | FE_PERM_O_EXEC) |
|---|
| 51 | + |
|---|
| 52 | +#define FE_DELETE_PERMS (FE_PERM_U_DELETE | FE_PERM_G_DELETE | \ |
|---|
| 53 | + FE_PERM_O_DELETE) |
|---|
| 54 | + |
|---|
| 48 | 55 | static umode_t udf_convert_permissions(struct fileEntry *); |
|---|
| 49 | 56 | static int udf_update_inode(struct inode *, int); |
|---|
| 50 | 57 | static int udf_sync_inode(struct inode *inode); |
|---|
| 51 | 58 | static int udf_alloc_i_data(struct inode *inode, size_t size); |
|---|
| 52 | 59 | static sector_t inode_getblk(struct inode *, sector_t, int *, int *); |
|---|
| 53 | | -static int8_t udf_insert_aext(struct inode *, struct extent_position, |
|---|
| 54 | | - struct kernel_lb_addr, uint32_t); |
|---|
| 60 | +static int udf_insert_aext(struct inode *, struct extent_position, |
|---|
| 61 | + struct kernel_lb_addr, uint32_t); |
|---|
| 55 | 62 | static void udf_split_extents(struct inode *, int *, int, udf_pblk_t, |
|---|
| 56 | 63 | struct kernel_long_ad *, int *); |
|---|
| 57 | 64 | static void udf_prealloc_extents(struct inode *, int, int, |
|---|
| 58 | 65 | struct kernel_long_ad *, int *); |
|---|
| 59 | 66 | static void udf_merge_extents(struct inode *, struct kernel_long_ad *, int *); |
|---|
| 60 | | -static void udf_update_extents(struct inode *, struct kernel_long_ad *, int, |
|---|
| 61 | | - int, struct extent_position *); |
|---|
| 67 | +static int udf_update_extents(struct inode *, struct kernel_long_ad *, int, |
|---|
| 68 | + int, struct extent_position *); |
|---|
| 62 | 69 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); |
|---|
| 63 | 70 | |
|---|
| 64 | 71 | static void __udf_clear_extent_cache(struct inode *inode) |
|---|
| .. | .. |
|---|
| 150 | 157 | truncate_inode_pages_final(&inode->i_data); |
|---|
| 151 | 158 | invalidate_inode_buffers(inode); |
|---|
| 152 | 159 | clear_inode(inode); |
|---|
| 153 | | - kfree(iinfo->i_ext.i_data); |
|---|
| 154 | | - iinfo->i_ext.i_data = NULL; |
|---|
| 160 | + kfree(iinfo->i_data); |
|---|
| 161 | + iinfo->i_data = NULL; |
|---|
| 155 | 162 | udf_clear_extent_cache(inode); |
|---|
| 156 | 163 | if (want_delete) { |
|---|
| 157 | 164 | udf_free_inode(inode); |
|---|
| .. | .. |
|---|
| 191 | 198 | return mpage_readpage(page, udf_get_block); |
|---|
| 192 | 199 | } |
|---|
| 193 | 200 | |
|---|
| 194 | | -static int udf_readpages(struct file *file, struct address_space *mapping, |
|---|
| 195 | | - struct list_head *pages, unsigned nr_pages) |
|---|
| 201 | +static void udf_readahead(struct readahead_control *rac) |
|---|
| 196 | 202 | { |
|---|
| 197 | | - return mpage_readpages(mapping, pages, nr_pages, udf_get_block); |
|---|
| 203 | + mpage_readahead(rac, udf_get_block); |
|---|
| 198 | 204 | } |
|---|
| 199 | 205 | |
|---|
| 200 | 206 | static int udf_write_begin(struct file *file, struct address_space *mapping, |
|---|
| .. | .. |
|---|
| 230 | 236 | |
|---|
| 231 | 237 | const struct address_space_operations udf_aops = { |
|---|
| 232 | 238 | .readpage = udf_readpage, |
|---|
| 233 | | - .readpages = udf_readpages, |
|---|
| 239 | + .readahead = udf_readahead, |
|---|
| 234 | 240 | .writepage = udf_writepage, |
|---|
| 235 | 241 | .writepages = udf_writepages, |
|---|
| 236 | 242 | .write_begin = udf_write_begin, |
|---|
| .. | .. |
|---|
| 278 | 284 | kaddr = kmap_atomic(page); |
|---|
| 279 | 285 | memset(kaddr + iinfo->i_lenAlloc, 0x00, |
|---|
| 280 | 286 | PAGE_SIZE - iinfo->i_lenAlloc); |
|---|
| 281 | | - memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, |
|---|
| 287 | + memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, |
|---|
| 282 | 288 | iinfo->i_lenAlloc); |
|---|
| 283 | 289 | flush_dcache_page(page); |
|---|
| 284 | 290 | SetPageUptodate(page); |
|---|
| 285 | 291 | kunmap_atomic(kaddr); |
|---|
| 286 | 292 | } |
|---|
| 287 | 293 | down_write(&iinfo->i_data_sem); |
|---|
| 288 | | - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, |
|---|
| 294 | + memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00, |
|---|
| 289 | 295 | iinfo->i_lenAlloc); |
|---|
| 290 | 296 | iinfo->i_lenAlloc = 0; |
|---|
| 291 | 297 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) |
|---|
| .. | .. |
|---|
| 303 | 309 | lock_page(page); |
|---|
| 304 | 310 | down_write(&iinfo->i_data_sem); |
|---|
| 305 | 311 | kaddr = kmap_atomic(page); |
|---|
| 306 | | - memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, |
|---|
| 307 | | - inode->i_size); |
|---|
| 312 | + memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, inode->i_size); |
|---|
| 308 | 313 | kunmap_atomic(kaddr); |
|---|
| 309 | 314 | unlock_page(page); |
|---|
| 310 | 315 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; |
|---|
| .. | .. |
|---|
| 392 | 397 | } |
|---|
| 393 | 398 | mark_buffer_dirty_inode(dbh, inode); |
|---|
| 394 | 399 | |
|---|
| 395 | | - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0, |
|---|
| 396 | | - iinfo->i_lenAlloc); |
|---|
| 400 | + memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc); |
|---|
| 397 | 401 | iinfo->i_lenAlloc = 0; |
|---|
| 398 | 402 | eloc.logicalBlockNum = *block; |
|---|
| 399 | 403 | eloc.partitionReferenceNum = |
|---|
| .. | .. |
|---|
| 434 | 438 | iinfo->i_next_alloc_goal++; |
|---|
| 435 | 439 | } |
|---|
| 436 | 440 | |
|---|
| 441 | + /* |
|---|
| 442 | + * Block beyond EOF and prealloc extents? Just discard preallocation |
|---|
| 443 | + * as it is not useful and complicates things. |
|---|
| 444 | + */ |
|---|
| 445 | + if (((loff_t)block) << inode->i_blkbits >= iinfo->i_lenExtents) |
|---|
| 446 | + udf_discard_prealloc(inode); |
|---|
| 437 | 447 | udf_clear_extent_cache(inode); |
|---|
| 438 | 448 | phys = inode_getblk(inode, block, &err, &new); |
|---|
| 439 | 449 | if (!phys) |
|---|
| .. | .. |
|---|
| 483 | 493 | uint32_t add; |
|---|
| 484 | 494 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); |
|---|
| 485 | 495 | struct super_block *sb = inode->i_sb; |
|---|
| 486 | | - struct kernel_lb_addr prealloc_loc = {}; |
|---|
| 487 | | - uint32_t prealloc_len = 0; |
|---|
| 488 | 496 | struct udf_inode_info *iinfo; |
|---|
| 489 | 497 | int err; |
|---|
| 490 | 498 | |
|---|
| .. | .. |
|---|
| 505 | 513 | ~(sb->s_blocksize - 1); |
|---|
| 506 | 514 | } |
|---|
| 507 | 515 | |
|---|
| 508 | | - /* Last extent are just preallocated blocks? */ |
|---|
| 509 | | - if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == |
|---|
| 510 | | - EXT_NOT_RECORDED_ALLOCATED) { |
|---|
| 511 | | - /* Save the extent so that we can reattach it to the end */ |
|---|
| 512 | | - prealloc_loc = last_ext->extLocation; |
|---|
| 513 | | - prealloc_len = last_ext->extLength; |
|---|
| 514 | | - /* Mark the extent as a hole */ |
|---|
| 515 | | - last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
|---|
| 516 | | - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); |
|---|
| 517 | | - last_ext->extLocation.logicalBlockNum = 0; |
|---|
| 518 | | - last_ext->extLocation.partitionReferenceNum = 0; |
|---|
| 519 | | - } |
|---|
| 520 | | - |
|---|
| 521 | 516 | /* Can we merge with the previous extent? */ |
|---|
| 522 | 517 | if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == |
|---|
| 523 | 518 | EXT_NOT_RECORDED_NOT_ALLOCATED) { |
|---|
| .. | .. |
|---|
| 530 | 525 | } |
|---|
| 531 | 526 | |
|---|
| 532 | 527 | if (fake) { |
|---|
| 533 | | - udf_add_aext(inode, last_pos, &last_ext->extLocation, |
|---|
| 534 | | - last_ext->extLength, 1); |
|---|
| 528 | + err = udf_add_aext(inode, last_pos, &last_ext->extLocation, |
|---|
| 529 | + last_ext->extLength, 1); |
|---|
| 530 | + if (err < 0) |
|---|
| 531 | + goto out_err; |
|---|
| 535 | 532 | count++; |
|---|
| 536 | 533 | } else { |
|---|
| 537 | 534 | struct kernel_lb_addr tmploc; |
|---|
| .. | .. |
|---|
| 545 | 542 | * more extents, we may need to enter possible following |
|---|
| 546 | 543 | * empty indirect extent. |
|---|
| 547 | 544 | */ |
|---|
| 548 | | - if (new_block_bytes || prealloc_len) |
|---|
| 545 | + if (new_block_bytes) |
|---|
| 549 | 546 | udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); |
|---|
| 550 | 547 | } |
|---|
| 551 | 548 | |
|---|
| .. | .. |
|---|
| 565 | 562 | err = udf_add_aext(inode, last_pos, &last_ext->extLocation, |
|---|
| 566 | 563 | last_ext->extLength, 1); |
|---|
| 567 | 564 | if (err) |
|---|
| 568 | | - return err; |
|---|
| 565 | + goto out_err; |
|---|
| 569 | 566 | count++; |
|---|
| 570 | 567 | } |
|---|
| 571 | 568 | if (new_block_bytes) { |
|---|
| .. | .. |
|---|
| 574 | 571 | err = udf_add_aext(inode, last_pos, &last_ext->extLocation, |
|---|
| 575 | 572 | last_ext->extLength, 1); |
|---|
| 576 | 573 | if (err) |
|---|
| 577 | | - return err; |
|---|
| 574 | + goto out_err; |
|---|
| 578 | 575 | count++; |
|---|
| 579 | 576 | } |
|---|
| 580 | 577 | |
|---|
| 581 | 578 | out: |
|---|
| 582 | | - /* Do we have some preallocated blocks saved? */ |
|---|
| 583 | | - if (prealloc_len) { |
|---|
| 584 | | - err = udf_add_aext(inode, last_pos, &prealloc_loc, |
|---|
| 585 | | - prealloc_len, 1); |
|---|
| 586 | | - if (err) |
|---|
| 587 | | - return err; |
|---|
| 588 | | - last_ext->extLocation = prealloc_loc; |
|---|
| 589 | | - last_ext->extLength = prealloc_len; |
|---|
| 590 | | - count++; |
|---|
| 591 | | - } |
|---|
| 592 | | - |
|---|
| 593 | 579 | /* last_pos should point to the last written extent... */ |
|---|
| 594 | 580 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
|---|
| 595 | 581 | last_pos->offset -= sizeof(struct short_ad); |
|---|
| .. | .. |
|---|
| 599 | 585 | return -EIO; |
|---|
| 600 | 586 | |
|---|
| 601 | 587 | return count; |
|---|
| 588 | +out_err: |
|---|
| 589 | + /* Remove extents we've created so far */ |
|---|
| 590 | + udf_clear_extent_cache(inode); |
|---|
| 591 | + udf_truncate_extents(inode); |
|---|
| 592 | + return err; |
|---|
| 602 | 593 | } |
|---|
| 603 | 594 | |
|---|
| 604 | 595 | /* Extend the final block of the file to final_block_len bytes */ |
|---|
| 605 | 596 | static void udf_do_extend_final_block(struct inode *inode, |
|---|
| 606 | 597 | struct extent_position *last_pos, |
|---|
| 607 | 598 | struct kernel_long_ad *last_ext, |
|---|
| 608 | | - uint32_t final_block_len) |
|---|
| 599 | + uint32_t new_elen) |
|---|
| 609 | 600 | { |
|---|
| 610 | | - struct super_block *sb = inode->i_sb; |
|---|
| 611 | 601 | uint32_t added_bytes; |
|---|
| 612 | 602 | |
|---|
| 613 | | - added_bytes = final_block_len - |
|---|
| 614 | | - (last_ext->extLength & (sb->s_blocksize - 1)); |
|---|
| 603 | + /* |
|---|
| 604 | + * Extent already large enough? It may be already rounded up to block |
|---|
| 605 | + * size... |
|---|
| 606 | + */ |
|---|
| 607 | + if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) |
|---|
| 608 | + return; |
|---|
| 609 | + added_bytes = new_elen - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); |
|---|
| 615 | 610 | last_ext->extLength += added_bytes; |
|---|
| 616 | 611 | UDF_I(inode)->i_lenExtents += added_bytes; |
|---|
| 617 | 612 | |
|---|
| .. | .. |
|---|
| 628 | 623 | int8_t etype; |
|---|
| 629 | 624 | struct super_block *sb = inode->i_sb; |
|---|
| 630 | 625 | sector_t first_block = newsize >> sb->s_blocksize_bits, offset; |
|---|
| 631 | | - unsigned long partial_final_block; |
|---|
| 626 | + loff_t new_elen; |
|---|
| 632 | 627 | int adsize; |
|---|
| 633 | 628 | struct udf_inode_info *iinfo = UDF_I(inode); |
|---|
| 634 | 629 | struct kernel_long_ad extent; |
|---|
| 635 | 630 | int err = 0; |
|---|
| 636 | | - int within_final_block; |
|---|
| 631 | + bool within_last_ext; |
|---|
| 637 | 632 | |
|---|
| 638 | 633 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
|---|
| 639 | 634 | adsize = sizeof(struct short_ad); |
|---|
| .. | .. |
|---|
| 642 | 637 | else |
|---|
| 643 | 638 | BUG(); |
|---|
| 644 | 639 | |
|---|
| 640 | + /* |
|---|
| 641 | + * When creating hole in file, just don't bother with preserving |
|---|
| 642 | + * preallocation. It likely won't be very useful anyway. |
|---|
| 643 | + */ |
|---|
| 644 | + udf_discard_prealloc(inode); |
|---|
| 645 | + |
|---|
| 645 | 646 | etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); |
|---|
| 646 | | - within_final_block = (etype != -1); |
|---|
| 647 | + within_last_ext = (etype != -1); |
|---|
| 648 | + /* We don't expect extents past EOF... */ |
|---|
| 649 | + WARN_ON_ONCE(within_last_ext && |
|---|
| 650 | + elen > ((loff_t)offset + 1) << inode->i_blkbits); |
|---|
| 647 | 651 | |
|---|
| 648 | 652 | if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || |
|---|
| 649 | 653 | (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { |
|---|
| .. | .. |
|---|
| 659 | 663 | extent.extLength |= etype << 30; |
|---|
| 660 | 664 | } |
|---|
| 661 | 665 | |
|---|
| 662 | | - partial_final_block = newsize & (sb->s_blocksize - 1); |
|---|
| 666 | + new_elen = ((loff_t)offset << inode->i_blkbits) | |
|---|
| 667 | + (newsize & (sb->s_blocksize - 1)); |
|---|
| 663 | 668 | |
|---|
| 664 | 669 | /* File has extent covering the new size (could happen when extending |
|---|
| 665 | 670 | * inside a block)? |
|---|
| 666 | 671 | */ |
|---|
| 667 | | - if (within_final_block) { |
|---|
| 672 | + if (within_last_ext) { |
|---|
| 668 | 673 | /* Extending file within the last file block */ |
|---|
| 669 | | - udf_do_extend_final_block(inode, &epos, &extent, |
|---|
| 670 | | - partial_final_block); |
|---|
| 674 | + udf_do_extend_final_block(inode, &epos, &extent, new_elen); |
|---|
| 671 | 675 | } else { |
|---|
| 672 | | - loff_t add = ((loff_t)offset << sb->s_blocksize_bits) | |
|---|
| 673 | | - partial_final_block; |
|---|
| 674 | | - err = udf_do_extend_file(inode, &epos, &extent, add); |
|---|
| 676 | + err = udf_do_extend_file(inode, &epos, &extent, new_elen); |
|---|
| 675 | 677 | } |
|---|
| 676 | 678 | |
|---|
| 677 | 679 | if (err < 0) |
|---|
| .. | .. |
|---|
| 693 | 695 | struct kernel_lb_addr eloc, tmpeloc; |
|---|
| 694 | 696 | int c = 1; |
|---|
| 695 | 697 | loff_t lbcount = 0, b_off = 0; |
|---|
| 696 | | - udf_pblk_t newblocknum, newblock; |
|---|
| 698 | + udf_pblk_t newblocknum, newblock = 0; |
|---|
| 697 | 699 | sector_t offset = 0; |
|---|
| 698 | 700 | int8_t etype; |
|---|
| 699 | 701 | struct udf_inode_info *iinfo = UDF_I(inode); |
|---|
| .. | .. |
|---|
| 772 | 774 | goto out_free; |
|---|
| 773 | 775 | } |
|---|
| 774 | 776 | |
|---|
| 775 | | - /* Are we beyond EOF? */ |
|---|
| 777 | + /* Are we beyond EOF and preallocated extent? */ |
|---|
| 776 | 778 | if (etype == -1) { |
|---|
| 777 | 779 | int ret; |
|---|
| 778 | 780 | loff_t hole_len; |
|---|
| 781 | + |
|---|
| 779 | 782 | isBeyondEOF = true; |
|---|
| 780 | 783 | if (count) { |
|---|
| 781 | 784 | if (c) |
|---|
| .. | .. |
|---|
| 795 | 798 | ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len); |
|---|
| 796 | 799 | if (ret < 0) { |
|---|
| 797 | 800 | *err = ret; |
|---|
| 798 | | - newblock = 0; |
|---|
| 799 | 801 | goto out_free; |
|---|
| 800 | 802 | } |
|---|
| 801 | 803 | c = 0; |
|---|
| 802 | 804 | offset = 0; |
|---|
| 803 | 805 | count += ret; |
|---|
| 804 | | - /* We are not covered by a preallocated extent? */ |
|---|
| 805 | | - if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != |
|---|
| 806 | | - EXT_NOT_RECORDED_ALLOCATED) { |
|---|
| 807 | | - /* Is there any real extent? - otherwise we overwrite |
|---|
| 808 | | - * the fake one... */ |
|---|
| 809 | | - if (count) |
|---|
| 810 | | - c = !c; |
|---|
| 811 | | - laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
|---|
| 812 | | - inode->i_sb->s_blocksize; |
|---|
| 813 | | - memset(&laarr[c].extLocation, 0x00, |
|---|
| 814 | | - sizeof(struct kernel_lb_addr)); |
|---|
| 815 | | - count++; |
|---|
| 816 | | - } |
|---|
| 806 | + /* |
|---|
| 807 | + * Is there any real extent? - otherwise we overwrite the fake |
|---|
| 808 | + * one... |
|---|
| 809 | + */ |
|---|
| 810 | + if (count) |
|---|
| 811 | + c = !c; |
|---|
| 812 | + laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
|---|
| 813 | + inode->i_sb->s_blocksize; |
|---|
| 814 | + memset(&laarr[c].extLocation, 0x00, |
|---|
| 815 | + sizeof(struct kernel_lb_addr)); |
|---|
| 816 | + count++; |
|---|
| 817 | 817 | endnum = c + 1; |
|---|
| 818 | 818 | lastblock = 1; |
|---|
| 819 | 819 | } else { |
|---|
| .. | .. |
|---|
| 860 | 860 | goal, err); |
|---|
| 861 | 861 | if (!newblocknum) { |
|---|
| 862 | 862 | *err = -ENOSPC; |
|---|
| 863 | | - newblock = 0; |
|---|
| 864 | 863 | goto out_free; |
|---|
| 865 | 864 | } |
|---|
| 866 | 865 | if (isBeyondEOF) |
|---|
| .. | .. |
|---|
| 886 | 885 | /* write back the new extents, inserting new extents if the new number |
|---|
| 887 | 886 | * of extents is greater than the old number, and deleting extents if |
|---|
| 888 | 887 | * the new number of extents is less than the old number */ |
|---|
| 889 | | - udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); |
|---|
| 888 | + *err = udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); |
|---|
| 889 | + if (*err < 0) |
|---|
| 890 | + goto out_free; |
|---|
| 890 | 891 | |
|---|
| 891 | 892 | newblock = udf_get_pblock(inode->i_sb, newblocknum, |
|---|
| 892 | 893 | iinfo->i_location.partitionReferenceNum, 0); |
|---|
| .. | .. |
|---|
| 1090 | 1091 | blocksize - 1) >> blocksize_bits)))) { |
|---|
| 1091 | 1092 | |
|---|
| 1092 | 1093 | if (((li->extLength & UDF_EXTENT_LENGTH_MASK) + |
|---|
| 1093 | | - (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + |
|---|
| 1094 | | - blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) { |
|---|
| 1095 | | - lip1->extLength = (lip1->extLength - |
|---|
| 1096 | | - (li->extLength & |
|---|
| 1097 | | - UDF_EXTENT_LENGTH_MASK) + |
|---|
| 1098 | | - UDF_EXTENT_LENGTH_MASK) & |
|---|
| 1099 | | - ~(blocksize - 1); |
|---|
| 1100 | | - li->extLength = (li->extLength & |
|---|
| 1101 | | - UDF_EXTENT_FLAG_MASK) + |
|---|
| 1102 | | - (UDF_EXTENT_LENGTH_MASK + 1) - |
|---|
| 1103 | | - blocksize; |
|---|
| 1104 | | - lip1->extLocation.logicalBlockNum = |
|---|
| 1105 | | - li->extLocation.logicalBlockNum + |
|---|
| 1106 | | - ((li->extLength & |
|---|
| 1107 | | - UDF_EXTENT_LENGTH_MASK) >> |
|---|
| 1108 | | - blocksize_bits); |
|---|
| 1109 | | - } else { |
|---|
| 1094 | + (lip1->extLength & UDF_EXTENT_LENGTH_MASK) + |
|---|
| 1095 | + blocksize - 1) <= UDF_EXTENT_LENGTH_MASK) { |
|---|
| 1110 | 1096 | li->extLength = lip1->extLength + |
|---|
| 1111 | 1097 | (((li->extLength & |
|---|
| 1112 | 1098 | UDF_EXTENT_LENGTH_MASK) + |
|---|
| .. | .. |
|---|
| 1169 | 1155 | } |
|---|
| 1170 | 1156 | } |
|---|
| 1171 | 1157 | |
|---|
| 1172 | | -static void udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr, |
|---|
| 1173 | | - int startnum, int endnum, |
|---|
| 1174 | | - struct extent_position *epos) |
|---|
| 1158 | +static int udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr, |
|---|
| 1159 | + int startnum, int endnum, |
|---|
| 1160 | + struct extent_position *epos) |
|---|
| 1175 | 1161 | { |
|---|
| 1176 | 1162 | int start = 0, i; |
|---|
| 1177 | 1163 | struct kernel_lb_addr tmploc; |
|---|
| 1178 | 1164 | uint32_t tmplen; |
|---|
| 1165 | + int err; |
|---|
| 1179 | 1166 | |
|---|
| 1180 | 1167 | if (startnum > endnum) { |
|---|
| 1181 | 1168 | for (i = 0; i < (startnum - endnum); i++) |
|---|
| 1182 | 1169 | udf_delete_aext(inode, *epos); |
|---|
| 1183 | 1170 | } else if (startnum < endnum) { |
|---|
| 1184 | 1171 | for (i = 0; i < (endnum - startnum); i++) { |
|---|
| 1185 | | - udf_insert_aext(inode, *epos, laarr[i].extLocation, |
|---|
| 1186 | | - laarr[i].extLength); |
|---|
| 1172 | + err = udf_insert_aext(inode, *epos, |
|---|
| 1173 | + laarr[i].extLocation, |
|---|
| 1174 | + laarr[i].extLength); |
|---|
| 1175 | + /* |
|---|
| 1176 | + * If we fail here, we are likely corrupting the extent |
|---|
| 1177 | + * list and leaking blocks. At least stop early to |
|---|
| 1178 | + * limit the damage. |
|---|
| 1179 | + */ |
|---|
| 1180 | + if (err < 0) |
|---|
| 1181 | + return err; |
|---|
| 1187 | 1182 | udf_next_aext(inode, epos, &laarr[i].extLocation, |
|---|
| 1188 | 1183 | &laarr[i].extLength, 1); |
|---|
| 1189 | 1184 | start++; |
|---|
| .. | .. |
|---|
| 1195 | 1190 | udf_write_aext(inode, epos, &laarr[i].extLocation, |
|---|
| 1196 | 1191 | laarr[i].extLength, 1); |
|---|
| 1197 | 1192 | } |
|---|
| 1193 | + return 0; |
|---|
| 1198 | 1194 | } |
|---|
| 1199 | 1195 | |
|---|
| 1200 | 1196 | struct buffer_head *udf_bread(struct inode *inode, udf_pblk_t block, |
|---|
| .. | .. |
|---|
| 1259 | 1255 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { |
|---|
| 1260 | 1256 | down_write(&iinfo->i_data_sem); |
|---|
| 1261 | 1257 | udf_clear_extent_cache(inode); |
|---|
| 1262 | | - memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, |
|---|
| 1258 | + memset(iinfo->i_data + iinfo->i_lenEAttr + newsize, |
|---|
| 1263 | 1259 | 0x00, bsize - newsize - |
|---|
| 1264 | 1260 | udf_file_entry_alloc_offset(inode)); |
|---|
| 1265 | 1261 | iinfo->i_lenAlloc = newsize; |
|---|
| .. | .. |
|---|
| 1274 | 1270 | truncate_setsize(inode, newsize); |
|---|
| 1275 | 1271 | down_write(&iinfo->i_data_sem); |
|---|
| 1276 | 1272 | udf_clear_extent_cache(inode); |
|---|
| 1277 | | - udf_truncate_extents(inode); |
|---|
| 1273 | + err = udf_truncate_extents(inode); |
|---|
| 1278 | 1274 | up_write(&iinfo->i_data_sem); |
|---|
| 1275 | + if (err) |
|---|
| 1276 | + return err; |
|---|
| 1279 | 1277 | } |
|---|
| 1280 | 1278 | update_time: |
|---|
| 1281 | 1279 | inode->i_mtime = inode->i_ctime = current_time(inode); |
|---|
| .. | .. |
|---|
| 1395 | 1393 | ret = -EIO; |
|---|
| 1396 | 1394 | goto out; |
|---|
| 1397 | 1395 | } |
|---|
| 1396 | + iinfo->i_hidden = hidden_inode; |
|---|
| 1398 | 1397 | iinfo->i_unique = 0; |
|---|
| 1399 | 1398 | iinfo->i_lenEAttr = 0; |
|---|
| 1400 | 1399 | iinfo->i_lenExtents = 0; |
|---|
| .. | .. |
|---|
| 1408 | 1407 | sizeof(struct extendedFileEntry)); |
|---|
| 1409 | 1408 | if (ret) |
|---|
| 1410 | 1409 | goto out; |
|---|
| 1411 | | - memcpy(iinfo->i_ext.i_data, |
|---|
| 1410 | + memcpy(iinfo->i_data, |
|---|
| 1412 | 1411 | bh->b_data + sizeof(struct extendedFileEntry), |
|---|
| 1413 | 1412 | bs - sizeof(struct extendedFileEntry)); |
|---|
| 1414 | 1413 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { |
|---|
| .. | .. |
|---|
| 1417 | 1416 | ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry)); |
|---|
| 1418 | 1417 | if (ret) |
|---|
| 1419 | 1418 | goto out; |
|---|
| 1420 | | - memcpy(iinfo->i_ext.i_data, |
|---|
| 1419 | + memcpy(iinfo->i_data, |
|---|
| 1421 | 1420 | bh->b_data + sizeof(struct fileEntry), |
|---|
| 1422 | 1421 | bs - sizeof(struct fileEntry)); |
|---|
| 1423 | 1422 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { |
|---|
| .. | .. |
|---|
| 1430 | 1429 | sizeof(struct unallocSpaceEntry)); |
|---|
| 1431 | 1430 | if (ret) |
|---|
| 1432 | 1431 | goto out; |
|---|
| 1433 | | - memcpy(iinfo->i_ext.i_data, |
|---|
| 1432 | + memcpy(iinfo->i_data, |
|---|
| 1434 | 1433 | bh->b_data + sizeof(struct unallocSpaceEntry), |
|---|
| 1435 | 1434 | bs - sizeof(struct unallocSpaceEntry)); |
|---|
| 1436 | 1435 | return 0; |
|---|
| .. | .. |
|---|
| 1461 | 1460 | else |
|---|
| 1462 | 1461 | inode->i_mode = udf_convert_permissions(fe); |
|---|
| 1463 | 1462 | inode->i_mode &= ~sbi->s_umask; |
|---|
| 1463 | + iinfo->i_extraPerms = le32_to_cpu(fe->permissions) & ~FE_MAPPED_PERMS; |
|---|
| 1464 | + |
|---|
| 1464 | 1465 | read_unlock(&sbi->s_cred_lock); |
|---|
| 1465 | 1466 | |
|---|
| 1466 | 1467 | link_count = le16_to_cpu(fe->fileLinkCount); |
|---|
| .. | .. |
|---|
| 1488 | 1489 | iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); |
|---|
| 1489 | 1490 | iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); |
|---|
| 1490 | 1491 | iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); |
|---|
| 1492 | + iinfo->i_streamdir = 0; |
|---|
| 1493 | + iinfo->i_lenStreams = 0; |
|---|
| 1491 | 1494 | } else { |
|---|
| 1492 | 1495 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << |
|---|
| 1493 | 1496 | (inode->i_sb->s_blocksize_bits - 9); |
|---|
| .. | .. |
|---|
| 1501 | 1504 | iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); |
|---|
| 1502 | 1505 | iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); |
|---|
| 1503 | 1506 | iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); |
|---|
| 1507 | + |
|---|
| 1508 | + /* Named streams */ |
|---|
| 1509 | + iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0); |
|---|
| 1510 | + iinfo->i_locStreamdir = |
|---|
| 1511 | + lelb_to_cpu(efe->streamDirectoryICB.extLocation); |
|---|
| 1512 | + iinfo->i_lenStreams = le64_to_cpu(efe->objectSize); |
|---|
| 1513 | + if (iinfo->i_lenStreams >= inode->i_size) |
|---|
| 1514 | + iinfo->i_lenStreams -= inode->i_size; |
|---|
| 1515 | + else |
|---|
| 1516 | + iinfo->i_lenStreams = 0; |
|---|
| 1504 | 1517 | } |
|---|
| 1505 | 1518 | inode->i_generation = iinfo->i_unique; |
|---|
| 1506 | 1519 | |
|---|
| .. | .. |
|---|
| 1597 | 1610 | static int udf_alloc_i_data(struct inode *inode, size_t size) |
|---|
| 1598 | 1611 | { |
|---|
| 1599 | 1612 | struct udf_inode_info *iinfo = UDF_I(inode); |
|---|
| 1600 | | - iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL); |
|---|
| 1601 | | - if (!iinfo->i_ext.i_data) |
|---|
| 1613 | + iinfo->i_data = kmalloc(size, GFP_KERNEL); |
|---|
| 1614 | + if (!iinfo->i_data) |
|---|
| 1602 | 1615 | return -ENOMEM; |
|---|
| 1603 | 1616 | return 0; |
|---|
| 1604 | 1617 | } |
|---|
| .. | .. |
|---|
| 1620 | 1633 | ((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0); |
|---|
| 1621 | 1634 | |
|---|
| 1622 | 1635 | return mode; |
|---|
| 1636 | +} |
|---|
| 1637 | + |
|---|
| 1638 | +void udf_update_extra_perms(struct inode *inode, umode_t mode) |
|---|
| 1639 | +{ |
|---|
| 1640 | + struct udf_inode_info *iinfo = UDF_I(inode); |
|---|
| 1641 | + |
|---|
| 1642 | + /* |
|---|
| 1643 | + * UDF 2.01 sec. 3.3.3.3 Note 2: |
|---|
| 1644 | + * In Unix, delete permission tracks write |
|---|
| 1645 | + */ |
|---|
| 1646 | + iinfo->i_extraPerms &= ~FE_DELETE_PERMS; |
|---|
| 1647 | + if (mode & 0200) |
|---|
| 1648 | + iinfo->i_extraPerms |= FE_PERM_U_DELETE; |
|---|
| 1649 | + if (mode & 0020) |
|---|
| 1650 | + iinfo->i_extraPerms |= FE_PERM_G_DELETE; |
|---|
| 1651 | + if (mode & 0002) |
|---|
| 1652 | + iinfo->i_extraPerms |= FE_PERM_O_DELETE; |
|---|
| 1623 | 1653 | } |
|---|
| 1624 | 1654 | |
|---|
| 1625 | 1655 | int udf_write_inode(struct inode *inode, struct writeback_control *wbc) |
|---|
| .. | .. |
|---|
| 1672 | 1702 | |
|---|
| 1673 | 1703 | use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); |
|---|
| 1674 | 1704 | memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), |
|---|
| 1675 | | - iinfo->i_ext.i_data, inode->i_sb->s_blocksize - |
|---|
| 1705 | + iinfo->i_data, inode->i_sb->s_blocksize - |
|---|
| 1676 | 1706 | sizeof(struct unallocSpaceEntry)); |
|---|
| 1677 | 1707 | use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); |
|---|
| 1678 | 1708 | crclen = sizeof(struct unallocSpaceEntry); |
|---|
| .. | .. |
|---|
| 1694 | 1724 | ((inode->i_mode & 0070) << 2) | |
|---|
| 1695 | 1725 | ((inode->i_mode & 0700) << 4); |
|---|
| 1696 | 1726 | |
|---|
| 1697 | | - udfperms |= (le32_to_cpu(fe->permissions) & |
|---|
| 1698 | | - (FE_PERM_O_DELETE | FE_PERM_O_CHATTR | |
|---|
| 1699 | | - FE_PERM_G_DELETE | FE_PERM_G_CHATTR | |
|---|
| 1700 | | - FE_PERM_U_DELETE | FE_PERM_U_CHATTR)); |
|---|
| 1727 | + udfperms |= iinfo->i_extraPerms; |
|---|
| 1701 | 1728 | fe->permissions = cpu_to_le32(udfperms); |
|---|
| 1702 | 1729 | |
|---|
| 1703 | 1730 | if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0) |
|---|
| 1704 | 1731 | fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); |
|---|
| 1705 | | - else |
|---|
| 1706 | | - fe->fileLinkCount = cpu_to_le16(inode->i_nlink); |
|---|
| 1732 | + else { |
|---|
| 1733 | + if (iinfo->i_hidden) |
|---|
| 1734 | + fe->fileLinkCount = cpu_to_le16(0); |
|---|
| 1735 | + else |
|---|
| 1736 | + fe->fileLinkCount = cpu_to_le16(inode->i_nlink); |
|---|
| 1737 | + } |
|---|
| 1707 | 1738 | |
|---|
| 1708 | 1739 | fe->informationLength = cpu_to_le64(inode->i_size); |
|---|
| 1709 | 1740 | |
|---|
| .. | .. |
|---|
| 1741 | 1772 | |
|---|
| 1742 | 1773 | if (iinfo->i_efe == 0) { |
|---|
| 1743 | 1774 | memcpy(bh->b_data + sizeof(struct fileEntry), |
|---|
| 1744 | | - iinfo->i_ext.i_data, |
|---|
| 1775 | + iinfo->i_data, |
|---|
| 1745 | 1776 | inode->i_sb->s_blocksize - sizeof(struct fileEntry)); |
|---|
| 1746 | 1777 | fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); |
|---|
| 1747 | 1778 | |
|---|
| .. | .. |
|---|
| 1760 | 1791 | crclen = sizeof(struct fileEntry); |
|---|
| 1761 | 1792 | } else { |
|---|
| 1762 | 1793 | memcpy(bh->b_data + sizeof(struct extendedFileEntry), |
|---|
| 1763 | | - iinfo->i_ext.i_data, |
|---|
| 1794 | + iinfo->i_data, |
|---|
| 1764 | 1795 | inode->i_sb->s_blocksize - |
|---|
| 1765 | 1796 | sizeof(struct extendedFileEntry)); |
|---|
| 1766 | | - efe->objectSize = cpu_to_le64(inode->i_size); |
|---|
| 1797 | + efe->objectSize = |
|---|
| 1798 | + cpu_to_le64(inode->i_size + iinfo->i_lenStreams); |
|---|
| 1767 | 1799 | efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); |
|---|
| 1800 | + |
|---|
| 1801 | + if (iinfo->i_streamdir) { |
|---|
| 1802 | + struct long_ad *icb_lad = &efe->streamDirectoryICB; |
|---|
| 1803 | + |
|---|
| 1804 | + icb_lad->extLocation = |
|---|
| 1805 | + cpu_to_lelb(iinfo->i_locStreamdir); |
|---|
| 1806 | + icb_lad->extLength = |
|---|
| 1807 | + cpu_to_le32(inode->i_sb->s_blocksize); |
|---|
| 1808 | + } |
|---|
| 1768 | 1809 | |
|---|
| 1769 | 1810 | udf_adjust_time(iinfo, inode->i_atime); |
|---|
| 1770 | 1811 | udf_adjust_time(iinfo, inode->i_mtime); |
|---|
| .. | .. |
|---|
| 1864 | 1905 | if (!inode) |
|---|
| 1865 | 1906 | return ERR_PTR(-ENOMEM); |
|---|
| 1866 | 1907 | |
|---|
| 1867 | | - if (!(inode->i_state & I_NEW)) |
|---|
| 1908 | + if (!(inode->i_state & I_NEW)) { |
|---|
| 1909 | + if (UDF_I(inode)->i_hidden != hidden_inode) { |
|---|
| 1910 | + iput(inode); |
|---|
| 1911 | + return ERR_PTR(-EFSCORRUPTED); |
|---|
| 1912 | + } |
|---|
| 1868 | 1913 | return inode; |
|---|
| 1914 | + } |
|---|
| 1869 | 1915 | |
|---|
| 1870 | 1916 | memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); |
|---|
| 1871 | 1917 | err = udf_read_inode(inode, hidden_inode); |
|---|
| .. | .. |
|---|
| 1939 | 1985 | |
|---|
| 1940 | 1986 | __udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1); |
|---|
| 1941 | 1987 | udf_write_aext(inode, epos, &nepos.block, |
|---|
| 1942 | | - sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0); |
|---|
| 1988 | + sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0); |
|---|
| 1943 | 1989 | } else { |
|---|
| 1944 | 1990 | __udf_add_aext(inode, epos, &nepos.block, |
|---|
| 1945 | | - sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0); |
|---|
| 1991 | + sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0); |
|---|
| 1946 | 1992 | } |
|---|
| 1947 | 1993 | |
|---|
| 1948 | 1994 | brelse(epos->bh); |
|---|
| .. | .. |
|---|
| 2046 | 2092 | struct udf_inode_info *iinfo = UDF_I(inode); |
|---|
| 2047 | 2093 | |
|---|
| 2048 | 2094 | if (!epos->bh) |
|---|
| 2049 | | - ptr = iinfo->i_ext.i_data + epos->offset - |
|---|
| 2095 | + ptr = iinfo->i_data + epos->offset - |
|---|
| 2050 | 2096 | udf_file_entry_alloc_offset(inode) + |
|---|
| 2051 | 2097 | iinfo->i_lenEAttr; |
|---|
| 2052 | 2098 | else |
|---|
| .. | .. |
|---|
| 2101 | 2147 | unsigned int indirections = 0; |
|---|
| 2102 | 2148 | |
|---|
| 2103 | 2149 | while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == |
|---|
| 2104 | | - (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { |
|---|
| 2150 | + (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) { |
|---|
| 2105 | 2151 | udf_pblk_t block; |
|---|
| 2106 | 2152 | |
|---|
| 2107 | 2153 | if (++indirections > UDF_MAX_INDIR_EXTS) { |
|---|
| .. | .. |
|---|
| 2138 | 2184 | if (!epos->bh) { |
|---|
| 2139 | 2185 | if (!epos->offset) |
|---|
| 2140 | 2186 | epos->offset = udf_file_entry_alloc_offset(inode); |
|---|
| 2141 | | - ptr = iinfo->i_ext.i_data + epos->offset - |
|---|
| 2187 | + ptr = iinfo->i_data + epos->offset - |
|---|
| 2142 | 2188 | udf_file_entry_alloc_offset(inode) + |
|---|
| 2143 | 2189 | iinfo->i_lenEAttr; |
|---|
| 2144 | 2190 | alen = udf_file_entry_alloc_offset(inode) + |
|---|
| .. | .. |
|---|
| 2179 | 2225 | return etype; |
|---|
| 2180 | 2226 | } |
|---|
| 2181 | 2227 | |
|---|
| 2182 | | -static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, |
|---|
| 2183 | | - struct kernel_lb_addr neloc, uint32_t nelen) |
|---|
| 2228 | +static int udf_insert_aext(struct inode *inode, struct extent_position epos, |
|---|
| 2229 | + struct kernel_lb_addr neloc, uint32_t nelen) |
|---|
| 2184 | 2230 | { |
|---|
| 2185 | 2231 | struct kernel_lb_addr oeloc; |
|---|
| 2186 | 2232 | uint32_t oelen; |
|---|
| 2187 | 2233 | int8_t etype; |
|---|
| 2234 | + int err; |
|---|
| 2188 | 2235 | |
|---|
| 2189 | 2236 | if (epos.bh) |
|---|
| 2190 | 2237 | get_bh(epos.bh); |
|---|
| .. | .. |
|---|
| 2194 | 2241 | neloc = oeloc; |
|---|
| 2195 | 2242 | nelen = (etype << 30) | oelen; |
|---|
| 2196 | 2243 | } |
|---|
| 2197 | | - udf_add_aext(inode, &epos, &neloc, nelen, 1); |
|---|
| 2244 | + err = udf_add_aext(inode, &epos, &neloc, nelen, 1); |
|---|
| 2198 | 2245 | brelse(epos.bh); |
|---|
| 2199 | 2246 | |
|---|
| 2200 | | - return (nelen >> 30); |
|---|
| 2247 | + return err; |
|---|
| 2201 | 2248 | } |
|---|
| 2202 | 2249 | |
|---|
| 2203 | 2250 | int8_t udf_delete_aext(struct inode *inode, struct extent_position epos) |
|---|