| .. | .. |
|---|
| 11 | 11 | * This code is based on version 2.00 of the UDF specification, |
|---|
| 12 | 12 | * and revision 3 of the ECMA 167 standard [equivalent to ISO 13346]. |
|---|
| 13 | 13 | * http://www.osta.org/ |
|---|
| 14 | | - * http://www.ecma.ch/ |
|---|
| 15 | | - * http://www.iso.org/ |
|---|
| 14 | + * https://www.ecma.ch/ |
|---|
| 15 | + * https://www.iso.org/ |
|---|
| 16 | 16 | * |
|---|
| 17 | 17 | * COPYRIGHT |
|---|
| 18 | 18 | * This file is distributed under the terms of the GNU General Public |
|---|
| .. | .. |
|---|
| 93 | 93 | static int udf_sync_fs(struct super_block *, int); |
|---|
| 94 | 94 | static int udf_remount_fs(struct super_block *, int *, char *); |
|---|
| 95 | 95 | static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); |
|---|
| 96 | | -static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, |
|---|
| 97 | | - struct kernel_lb_addr *); |
|---|
| 98 | | -static void udf_load_fileset(struct super_block *, struct buffer_head *, |
|---|
| 99 | | - struct kernel_lb_addr *); |
|---|
| 100 | 96 | static void udf_open_lvid(struct super_block *); |
|---|
| 101 | 97 | static void udf_close_lvid(struct super_block *); |
|---|
| 102 | 98 | static unsigned int udf_count_free(struct super_block *); |
|---|
| .. | .. |
|---|
| 146 | 142 | |
|---|
| 147 | 143 | ei->i_unique = 0; |
|---|
| 148 | 144 | ei->i_lenExtents = 0; |
|---|
| 145 | + ei->i_lenStreams = 0; |
|---|
| 149 | 146 | ei->i_next_alloc_block = 0; |
|---|
| 150 | 147 | ei->i_next_alloc_goal = 0; |
|---|
| 151 | 148 | ei->i_strat4096 = 0; |
|---|
| 149 | + ei->i_streamdir = 0; |
|---|
| 150 | + ei->i_hidden = 0; |
|---|
| 152 | 151 | init_rwsem(&ei->i_data_sem); |
|---|
| 153 | 152 | ei->cached_extent.lstart = -1; |
|---|
| 154 | 153 | spin_lock_init(&ei->i_extent_cache_lock); |
|---|
| .. | .. |
|---|
| 157 | 156 | return &ei->vfs_inode; |
|---|
| 158 | 157 | } |
|---|
| 159 | 158 | |
|---|
| 160 | | -static void udf_i_callback(struct rcu_head *head) |
|---|
| 159 | +static void udf_free_in_core_inode(struct inode *inode) |
|---|
| 161 | 160 | { |
|---|
| 162 | | - struct inode *inode = container_of(head, struct inode, i_rcu); |
|---|
| 163 | 161 | kmem_cache_free(udf_inode_cachep, UDF_I(inode)); |
|---|
| 164 | | -} |
|---|
| 165 | | - |
|---|
| 166 | | -static void udf_destroy_inode(struct inode *inode) |
|---|
| 167 | | -{ |
|---|
| 168 | | - call_rcu(&inode->i_rcu, udf_i_callback); |
|---|
| 169 | 162 | } |
|---|
| 170 | 163 | |
|---|
| 171 | 164 | static void init_once(void *foo) |
|---|
| 172 | 165 | { |
|---|
| 173 | 166 | struct udf_inode_info *ei = (struct udf_inode_info *)foo; |
|---|
| 174 | 167 | |
|---|
| 175 | | - ei->i_ext.i_data = NULL; |
|---|
| 168 | + ei->i_data = NULL; |
|---|
| 176 | 169 | inode_init_once(&ei->vfs_inode); |
|---|
| 177 | 170 | } |
|---|
| 178 | 171 | |
|---|
| .. | .. |
|---|
| 202 | 195 | /* Superblock operations */ |
|---|
| 203 | 196 | static const struct super_operations udf_sb_ops = { |
|---|
| 204 | 197 | .alloc_inode = udf_alloc_inode, |
|---|
| 205 | | - .destroy_inode = udf_destroy_inode, |
|---|
| 198 | + .free_inode = udf_free_in_core_inode, |
|---|
| 206 | 199 | .write_inode = udf_write_inode, |
|---|
| 207 | 200 | .evict_inode = udf_evict_inode, |
|---|
| 208 | 201 | .put_super = udf_put_super, |
|---|
| .. | .. |
|---|
| 273 | 266 | int nr_groups = bitmap->s_nr_groups; |
|---|
| 274 | 267 | |
|---|
| 275 | 268 | for (i = 0; i < nr_groups; i++) |
|---|
| 276 | | - if (bitmap->s_block_bitmap[i]) |
|---|
| 277 | | - brelse(bitmap->s_block_bitmap[i]); |
|---|
| 269 | + brelse(bitmap->s_block_bitmap[i]); |
|---|
| 278 | 270 | |
|---|
| 279 | 271 | kvfree(bitmap); |
|---|
| 280 | 272 | } |
|---|
| .. | .. |
|---|
| 286 | 278 | |
|---|
| 287 | 279 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) |
|---|
| 288 | 280 | iput(map->s_uspace.s_table); |
|---|
| 289 | | - if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) |
|---|
| 290 | | - iput(map->s_fspace.s_table); |
|---|
| 291 | 281 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) |
|---|
| 292 | 282 | udf_sb_free_bitmap(map->s_uspace.s_bitmap); |
|---|
| 293 | | - if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) |
|---|
| 294 | | - udf_sb_free_bitmap(map->s_fspace.s_bitmap); |
|---|
| 295 | 283 | if (map->s_partition_type == UDF_SPARABLE_MAP15) |
|---|
| 296 | 284 | for (i = 0; i < 4; i++) |
|---|
| 297 | 285 | brelse(map->s_type_specific.s_sparing.s_spar_map[i]); |
|---|
| .. | .. |
|---|
| 358 | 346 | seq_printf(seq, ",lastblock=%u", sbi->s_last_block); |
|---|
| 359 | 347 | if (sbi->s_anchor != 0) |
|---|
| 360 | 348 | seq_printf(seq, ",anchor=%u", sbi->s_anchor); |
|---|
| 361 | | - if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) |
|---|
| 362 | | - seq_puts(seq, ",utf8"); |
|---|
| 363 | | - if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP) && sbi->s_nls_map) |
|---|
| 349 | + if (sbi->s_nls_map) |
|---|
| 364 | 350 | seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset); |
|---|
| 351 | + else |
|---|
| 352 | + seq_puts(seq, ",iocharset=utf8"); |
|---|
| 365 | 353 | |
|---|
| 366 | 354 | return 0; |
|---|
| 367 | 355 | } |
|---|
| .. | .. |
|---|
| 566 | 554 | /* Ignored (never implemented properly) */ |
|---|
| 567 | 555 | break; |
|---|
| 568 | 556 | case Opt_utf8: |
|---|
| 569 | | - uopt->flags |= (1 << UDF_FLAG_UTF8); |
|---|
| 557 | + if (!remount) { |
|---|
| 558 | + unload_nls(uopt->nls_map); |
|---|
| 559 | + uopt->nls_map = NULL; |
|---|
| 560 | + } |
|---|
| 570 | 561 | break; |
|---|
| 571 | 562 | case Opt_iocharset: |
|---|
| 572 | 563 | if (!remount) { |
|---|
| 573 | | - if (uopt->nls_map) |
|---|
| 574 | | - unload_nls(uopt->nls_map); |
|---|
| 564 | + unload_nls(uopt->nls_map); |
|---|
| 565 | + uopt->nls_map = NULL; |
|---|
| 566 | + } |
|---|
| 567 | + /* When nls_map is not loaded then UTF-8 is used */ |
|---|
| 568 | + if (!remount && strcmp(args[0].from, "utf8") != 0) { |
|---|
| 575 | 569 | uopt->nls_map = load_nls(args[0].from); |
|---|
| 576 | | - uopt->flags |= (1 << UDF_FLAG_NLS_MAP); |
|---|
| 570 | + if (!uopt->nls_map) { |
|---|
| 571 | + pr_err("iocharset %s not found\n", |
|---|
| 572 | + args[0].from); |
|---|
| 573 | + return 0; |
|---|
| 574 | + } |
|---|
| 577 | 575 | } |
|---|
| 578 | 576 | break; |
|---|
| 579 | 577 | case Opt_uforget: |
|---|
| .. | .. |
|---|
| 647 | 645 | return error; |
|---|
| 648 | 646 | } |
|---|
| 649 | 647 | |
|---|
| 650 | | -/* Check Volume Structure Descriptors (ECMA 167 2/9.1) */ |
|---|
| 651 | | -/* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ |
|---|
| 652 | | -static loff_t udf_check_vsd(struct super_block *sb) |
|---|
| 648 | +/* |
|---|
| 649 | + * Check VSD descriptor. Returns -1 in case we are at the end of volume |
|---|
| 650 | + * recognition area, 0 if the descriptor is valid but non-interesting, 1 if |
|---|
| 651 | + * we found one of NSR descriptors we are looking for. |
|---|
| 652 | + */ |
|---|
| 653 | +static int identify_vsd(const struct volStructDesc *vsd) |
|---|
| 654 | +{ |
|---|
| 655 | + int ret = 0; |
|---|
| 656 | + |
|---|
| 657 | + if (!memcmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) { |
|---|
| 658 | + switch (vsd->structType) { |
|---|
| 659 | + case 0: |
|---|
| 660 | + udf_debug("ISO9660 Boot Record found\n"); |
|---|
| 661 | + break; |
|---|
| 662 | + case 1: |
|---|
| 663 | + udf_debug("ISO9660 Primary Volume Descriptor found\n"); |
|---|
| 664 | + break; |
|---|
| 665 | + case 2: |
|---|
| 666 | + udf_debug("ISO9660 Supplementary Volume Descriptor found\n"); |
|---|
| 667 | + break; |
|---|
| 668 | + case 3: |
|---|
| 669 | + udf_debug("ISO9660 Volume Partition Descriptor found\n"); |
|---|
| 670 | + break; |
|---|
| 671 | + case 255: |
|---|
| 672 | + udf_debug("ISO9660 Volume Descriptor Set Terminator found\n"); |
|---|
| 673 | + break; |
|---|
| 674 | + default: |
|---|
| 675 | + udf_debug("ISO9660 VRS (%u) found\n", vsd->structType); |
|---|
| 676 | + break; |
|---|
| 677 | + } |
|---|
| 678 | + } else if (!memcmp(vsd->stdIdent, VSD_STD_ID_BEA01, VSD_STD_ID_LEN)) |
|---|
| 679 | + ; /* ret = 0 */ |
|---|
| 680 | + else if (!memcmp(vsd->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN)) |
|---|
| 681 | + ret = 1; |
|---|
| 682 | + else if (!memcmp(vsd->stdIdent, VSD_STD_ID_NSR03, VSD_STD_ID_LEN)) |
|---|
| 683 | + ret = 1; |
|---|
| 684 | + else if (!memcmp(vsd->stdIdent, VSD_STD_ID_BOOT2, VSD_STD_ID_LEN)) |
|---|
| 685 | + ; /* ret = 0 */ |
|---|
| 686 | + else if (!memcmp(vsd->stdIdent, VSD_STD_ID_CDW02, VSD_STD_ID_LEN)) |
|---|
| 687 | + ; /* ret = 0 */ |
|---|
| 688 | + else { |
|---|
| 689 | + /* TEA01 or invalid id : end of volume recognition area */ |
|---|
| 690 | + ret = -1; |
|---|
| 691 | + } |
|---|
| 692 | + |
|---|
| 693 | + return ret; |
|---|
| 694 | +} |
|---|
| 695 | + |
|---|
| 696 | +/* |
|---|
| 697 | + * Check Volume Structure Descriptors (ECMA 167 2/9.1) |
|---|
| 698 | + * We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) |
|---|
| 699 | + * @return 1 if NSR02 or NSR03 found, |
|---|
| 700 | + * -1 if first sector read error, 0 otherwise |
|---|
| 701 | + */ |
|---|
| 702 | +static int udf_check_vsd(struct super_block *sb) |
|---|
| 653 | 703 | { |
|---|
| 654 | 704 | struct volStructDesc *vsd = NULL; |
|---|
| 655 | 705 | loff_t sector = VSD_FIRST_SECTOR_OFFSET; |
|---|
| 656 | 706 | int sectorsize; |
|---|
| 657 | 707 | struct buffer_head *bh = NULL; |
|---|
| 658 | | - int nsr02 = 0; |
|---|
| 659 | | - int nsr03 = 0; |
|---|
| 708 | + int nsr = 0; |
|---|
| 660 | 709 | struct udf_sb_info *sbi; |
|---|
| 710 | + loff_t session_offset; |
|---|
| 661 | 711 | |
|---|
| 662 | 712 | sbi = UDF_SB(sb); |
|---|
| 663 | 713 | if (sb->s_blocksize < sizeof(struct volStructDesc)) |
|---|
| .. | .. |
|---|
| 665 | 715 | else |
|---|
| 666 | 716 | sectorsize = sb->s_blocksize; |
|---|
| 667 | 717 | |
|---|
| 668 | | - sector += (((loff_t)sbi->s_session) << sb->s_blocksize_bits); |
|---|
| 718 | + session_offset = (loff_t)sbi->s_session << sb->s_blocksize_bits; |
|---|
| 719 | + sector += session_offset; |
|---|
| 669 | 720 | |
|---|
| 670 | 721 | udf_debug("Starting at sector %u (%lu byte sectors)\n", |
|---|
| 671 | 722 | (unsigned int)(sector >> sb->s_blocksize_bits), |
|---|
| .. | .. |
|---|
| 680 | 731 | * activity. This actually happened with uninitialised SSD partitions |
|---|
| 681 | 732 | * (all 0xFF) before the check for the limit and all valid IDs were |
|---|
| 682 | 733 | * added */ |
|---|
| 683 | | - for (; !nsr02 && !nsr03 && sector < VSD_MAX_SECTOR_OFFSET; |
|---|
| 684 | | - sector += sectorsize) { |
|---|
| 734 | + for (; !nsr && sector < VSD_MAX_SECTOR_OFFSET; sector += sectorsize) { |
|---|
| 685 | 735 | /* Read a block */ |
|---|
| 686 | 736 | bh = udf_tread(sb, sector >> sb->s_blocksize_bits); |
|---|
| 687 | 737 | if (!bh) |
|---|
| 688 | 738 | break; |
|---|
| 689 | 739 | |
|---|
| 690 | | - /* Look for ISO descriptors */ |
|---|
| 691 | 740 | vsd = (struct volStructDesc *)(bh->b_data + |
|---|
| 692 | 741 | (sector & (sb->s_blocksize - 1))); |
|---|
| 693 | | - |
|---|
| 694 | | - if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, |
|---|
| 695 | | - VSD_STD_ID_LEN)) { |
|---|
| 696 | | - switch (vsd->structType) { |
|---|
| 697 | | - case 0: |
|---|
| 698 | | - udf_debug("ISO9660 Boot Record found\n"); |
|---|
| 699 | | - break; |
|---|
| 700 | | - case 1: |
|---|
| 701 | | - udf_debug("ISO9660 Primary Volume Descriptor found\n"); |
|---|
| 702 | | - break; |
|---|
| 703 | | - case 2: |
|---|
| 704 | | - udf_debug("ISO9660 Supplementary Volume Descriptor found\n"); |
|---|
| 705 | | - break; |
|---|
| 706 | | - case 3: |
|---|
| 707 | | - udf_debug("ISO9660 Volume Partition Descriptor found\n"); |
|---|
| 708 | | - break; |
|---|
| 709 | | - case 255: |
|---|
| 710 | | - udf_debug("ISO9660 Volume Descriptor Set Terminator found\n"); |
|---|
| 711 | | - break; |
|---|
| 712 | | - default: |
|---|
| 713 | | - udf_debug("ISO9660 VRS (%u) found\n", |
|---|
| 714 | | - vsd->structType); |
|---|
| 715 | | - break; |
|---|
| 716 | | - } |
|---|
| 717 | | - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BEA01, |
|---|
| 718 | | - VSD_STD_ID_LEN)) |
|---|
| 719 | | - ; /* nothing */ |
|---|
| 720 | | - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01, |
|---|
| 721 | | - VSD_STD_ID_LEN)) { |
|---|
| 742 | + nsr = identify_vsd(vsd); |
|---|
| 743 | + /* Found NSR or end? */ |
|---|
| 744 | + if (nsr) { |
|---|
| 722 | 745 | brelse(bh); |
|---|
| 723 | 746 | break; |
|---|
| 724 | | - } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02, |
|---|
| 725 | | - VSD_STD_ID_LEN)) |
|---|
| 726 | | - nsr02 = sector; |
|---|
| 727 | | - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03, |
|---|
| 728 | | - VSD_STD_ID_LEN)) |
|---|
| 729 | | - nsr03 = sector; |
|---|
| 730 | | - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BOOT2, |
|---|
| 731 | | - VSD_STD_ID_LEN)) |
|---|
| 732 | | - ; /* nothing */ |
|---|
| 733 | | - else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CDW02, |
|---|
| 734 | | - VSD_STD_ID_LEN)) |
|---|
| 735 | | - ; /* nothing */ |
|---|
| 736 | | - else { |
|---|
| 737 | | - /* invalid id : end of volume recognition area */ |
|---|
| 738 | | - brelse(bh); |
|---|
| 739 | | - break; |
|---|
| 747 | + } |
|---|
| 748 | + /* |
|---|
| 749 | + * Special handling for improperly formatted VRS (e.g., Win10) |
|---|
| 750 | + * where components are separated by 2048 bytes even though |
|---|
| 751 | + * sectors are 4K |
|---|
| 752 | + */ |
|---|
| 753 | + if (sb->s_blocksize == 4096) { |
|---|
| 754 | + nsr = identify_vsd(vsd + 1); |
|---|
| 755 | + /* Ignore unknown IDs... */ |
|---|
| 756 | + if (nsr < 0) |
|---|
| 757 | + nsr = 0; |
|---|
| 740 | 758 | } |
|---|
| 741 | 759 | brelse(bh); |
|---|
| 742 | 760 | } |
|---|
| 743 | 761 | |
|---|
| 744 | | - if (nsr03) |
|---|
| 745 | | - return nsr03; |
|---|
| 746 | | - else if (nsr02) |
|---|
| 747 | | - return nsr02; |
|---|
| 748 | | - else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) == |
|---|
| 749 | | - VSD_FIRST_SECTOR_OFFSET) |
|---|
| 762 | + if (nsr > 0) |
|---|
| 763 | + return 1; |
|---|
| 764 | + else if (!bh && sector - session_offset == VSD_FIRST_SECTOR_OFFSET) |
|---|
| 750 | 765 | return -1; |
|---|
| 751 | 766 | else |
|---|
| 752 | 767 | return 0; |
|---|
| 768 | +} |
|---|
| 769 | + |
|---|
| 770 | +static int udf_verify_domain_identifier(struct super_block *sb, |
|---|
| 771 | + struct regid *ident, char *dname) |
|---|
| 772 | +{ |
|---|
| 773 | + struct domainIdentSuffix *suffix; |
|---|
| 774 | + |
|---|
| 775 | + if (memcmp(ident->ident, UDF_ID_COMPLIANT, strlen(UDF_ID_COMPLIANT))) { |
|---|
| 776 | + udf_warn(sb, "Not OSTA UDF compliant %s descriptor.\n", dname); |
|---|
| 777 | + goto force_ro; |
|---|
| 778 | + } |
|---|
| 779 | + if (ident->flags & ENTITYID_FLAGS_DIRTY) { |
|---|
| 780 | + udf_warn(sb, "Possibly not OSTA UDF compliant %s descriptor.\n", |
|---|
| 781 | + dname); |
|---|
| 782 | + goto force_ro; |
|---|
| 783 | + } |
|---|
| 784 | + suffix = (struct domainIdentSuffix *)ident->identSuffix; |
|---|
| 785 | + if ((suffix->domainFlags & DOMAIN_FLAGS_HARD_WRITE_PROTECT) || |
|---|
| 786 | + (suffix->domainFlags & DOMAIN_FLAGS_SOFT_WRITE_PROTECT)) { |
|---|
| 787 | + if (!sb_rdonly(sb)) { |
|---|
| 788 | + udf_warn(sb, "Descriptor for %s marked write protected." |
|---|
| 789 | + " Forcing read only mount.\n", dname); |
|---|
| 790 | + } |
|---|
| 791 | + goto force_ro; |
|---|
| 792 | + } |
|---|
| 793 | + return 0; |
|---|
| 794 | + |
|---|
| 795 | +force_ro: |
|---|
| 796 | + if (!sb_rdonly(sb)) |
|---|
| 797 | + return -EACCES; |
|---|
| 798 | + UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT); |
|---|
| 799 | + return 0; |
|---|
| 800 | +} |
|---|
| 801 | + |
|---|
| 802 | +static int udf_load_fileset(struct super_block *sb, struct fileSetDesc *fset, |
|---|
| 803 | + struct kernel_lb_addr *root) |
|---|
| 804 | +{ |
|---|
| 805 | + int ret; |
|---|
| 806 | + |
|---|
| 807 | + ret = udf_verify_domain_identifier(sb, &fset->domainIdent, "file set"); |
|---|
| 808 | + if (ret < 0) |
|---|
| 809 | + return ret; |
|---|
| 810 | + |
|---|
| 811 | + *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation); |
|---|
| 812 | + UDF_SB(sb)->s_serial_number = le16_to_cpu(fset->descTag.tagSerialNum); |
|---|
| 813 | + |
|---|
| 814 | + udf_debug("Rootdir at block=%u, partition=%u\n", |
|---|
| 815 | + root->logicalBlockNum, root->partitionReferenceNum); |
|---|
| 816 | + return 0; |
|---|
| 753 | 817 | } |
|---|
| 754 | 818 | |
|---|
| 755 | 819 | static int udf_find_fileset(struct super_block *sb, |
|---|
| .. | .. |
|---|
| 758 | 822 | { |
|---|
| 759 | 823 | struct buffer_head *bh = NULL; |
|---|
| 760 | 824 | uint16_t ident; |
|---|
| 825 | + int ret; |
|---|
| 761 | 826 | |
|---|
| 762 | | - if (fileset->logicalBlockNum != 0xFFFFFFFF || |
|---|
| 763 | | - fileset->partitionReferenceNum != 0xFFFF) { |
|---|
| 764 | | - bh = udf_read_ptagged(sb, fileset, 0, &ident); |
|---|
| 827 | + if (fileset->logicalBlockNum == 0xFFFFFFFF && |
|---|
| 828 | + fileset->partitionReferenceNum == 0xFFFF) |
|---|
| 829 | + return -EINVAL; |
|---|
| 765 | 830 | |
|---|
| 766 | | - if (!bh) { |
|---|
| 767 | | - return 1; |
|---|
| 768 | | - } else if (ident != TAG_IDENT_FSD) { |
|---|
| 769 | | - brelse(bh); |
|---|
| 770 | | - return 1; |
|---|
| 771 | | - } |
|---|
| 772 | | - |
|---|
| 773 | | - udf_debug("Fileset at block=%u, partition=%u\n", |
|---|
| 774 | | - fileset->logicalBlockNum, |
|---|
| 775 | | - fileset->partitionReferenceNum); |
|---|
| 776 | | - |
|---|
| 777 | | - UDF_SB(sb)->s_partition = fileset->partitionReferenceNum; |
|---|
| 778 | | - udf_load_fileset(sb, bh, root); |
|---|
| 831 | + bh = udf_read_ptagged(sb, fileset, 0, &ident); |
|---|
| 832 | + if (!bh) |
|---|
| 833 | + return -EIO; |
|---|
| 834 | + if (ident != TAG_IDENT_FSD) { |
|---|
| 779 | 835 | brelse(bh); |
|---|
| 780 | | - return 0; |
|---|
| 836 | + return -EINVAL; |
|---|
| 781 | 837 | } |
|---|
| 782 | | - return 1; |
|---|
| 838 | + |
|---|
| 839 | + udf_debug("Fileset at block=%u, partition=%u\n", |
|---|
| 840 | + fileset->logicalBlockNum, fileset->partitionReferenceNum); |
|---|
| 841 | + |
|---|
| 842 | + UDF_SB(sb)->s_partition = fileset->partitionReferenceNum; |
|---|
| 843 | + ret = udf_load_fileset(sb, (struct fileSetDesc *)bh->b_data, root); |
|---|
| 844 | + brelse(bh); |
|---|
| 845 | + return ret; |
|---|
| 783 | 846 | } |
|---|
| 784 | 847 | |
|---|
| 785 | 848 | /* |
|---|
| .. | .. |
|---|
| 794 | 857 | uint8_t *outstr; |
|---|
| 795 | 858 | struct buffer_head *bh; |
|---|
| 796 | 859 | uint16_t ident; |
|---|
| 797 | | - int ret = -ENOMEM; |
|---|
| 798 | | -#ifdef UDFFS_DEBUG |
|---|
| 860 | + int ret; |
|---|
| 799 | 861 | struct timestamp *ts; |
|---|
| 800 | | -#endif |
|---|
| 801 | 862 | |
|---|
| 802 | 863 | outstr = kmalloc(128, GFP_NOFS); |
|---|
| 803 | 864 | if (!outstr) |
|---|
| .. | .. |
|---|
| 818 | 879 | |
|---|
| 819 | 880 | udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, |
|---|
| 820 | 881 | pvoldesc->recordingDateAndTime); |
|---|
| 821 | | -#ifdef UDFFS_DEBUG |
|---|
| 822 | 882 | ts = &pvoldesc->recordingDateAndTime; |
|---|
| 823 | 883 | udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n", |
|---|
| 824 | 884 | le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, |
|---|
| 825 | 885 | ts->minute, le16_to_cpu(ts->typeAndTimezone)); |
|---|
| 826 | | -#endif |
|---|
| 827 | | - |
|---|
| 828 | 886 | |
|---|
| 829 | 887 | ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32); |
|---|
| 830 | 888 | if (ret < 0) { |
|---|
| .. | .. |
|---|
| 940 | 998 | return 0; |
|---|
| 941 | 999 | } |
|---|
| 942 | 1000 | |
|---|
| 943 | | -static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, |
|---|
| 944 | | - struct kernel_lb_addr *root) |
|---|
| 945 | | -{ |
|---|
| 946 | | - struct fileSetDesc *fset; |
|---|
| 947 | | - |
|---|
| 948 | | - fset = (struct fileSetDesc *)bh->b_data; |
|---|
| 949 | | - |
|---|
| 950 | | - *root = lelb_to_cpu(fset->rootDirectoryICB.extLocation); |
|---|
| 951 | | - |
|---|
| 952 | | - UDF_SB(sb)->s_serial_number = le16_to_cpu(fset->descTag.tagSerialNum); |
|---|
| 953 | | - |
|---|
| 954 | | - udf_debug("Rootdir at block=%u, partition=%u\n", |
|---|
| 955 | | - root->logicalBlockNum, root->partitionReferenceNum); |
|---|
| 956 | | -} |
|---|
| 957 | | - |
|---|
| 958 | 1001 | int udf_compute_nr_groups(struct super_block *sb, u32 partition) |
|---|
| 959 | 1002 | { |
|---|
| 960 | 1003 | struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
|---|
| .. | .. |
|---|
| 966 | 1009 | static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) |
|---|
| 967 | 1010 | { |
|---|
| 968 | 1011 | struct udf_bitmap *bitmap; |
|---|
| 969 | | - int nr_groups; |
|---|
| 970 | | - int size; |
|---|
| 1012 | + int nr_groups = udf_compute_nr_groups(sb, index); |
|---|
| 971 | 1013 | |
|---|
| 972 | | - nr_groups = udf_compute_nr_groups(sb, index); |
|---|
| 973 | | - size = sizeof(struct udf_bitmap) + |
|---|
| 974 | | - (sizeof(struct buffer_head *) * nr_groups); |
|---|
| 975 | | - |
|---|
| 976 | | - if (size <= PAGE_SIZE) |
|---|
| 977 | | - bitmap = kzalloc(size, GFP_KERNEL); |
|---|
| 978 | | - else |
|---|
| 979 | | - bitmap = vzalloc(size); /* TODO: get rid of vzalloc */ |
|---|
| 980 | | - |
|---|
| 1014 | + bitmap = kvzalloc(struct_size(bitmap, s_block_bitmap, nr_groups), |
|---|
| 1015 | + GFP_KERNEL); |
|---|
| 981 | 1016 | if (!bitmap) |
|---|
| 982 | 1017 | return NULL; |
|---|
| 983 | 1018 | |
|---|
| .. | .. |
|---|
| 1022 | 1057 | goto force_ro; |
|---|
| 1023 | 1058 | |
|---|
| 1024 | 1059 | if (map->s_partition_type == UDF_VIRTUAL_MAP15 || |
|---|
| 1025 | | - map->s_partition_type == UDF_VIRTUAL_MAP20) |
|---|
| 1060 | + map->s_partition_type == UDF_VIRTUAL_MAP20 || |
|---|
| 1061 | + map->s_partition_type == UDF_METADATA_MAP25) |
|---|
| 1026 | 1062 | goto force_ro; |
|---|
| 1027 | 1063 | |
|---|
| 1028 | 1064 | return 0; |
|---|
| .. | .. |
|---|
| 1104 | 1140 | p_index, bitmap->s_extPosition); |
|---|
| 1105 | 1141 | } |
|---|
| 1106 | 1142 | |
|---|
| 1107 | | - if (phd->freedSpaceTable.extLength) { |
|---|
| 1108 | | - struct kernel_lb_addr loc = { |
|---|
| 1109 | | - .logicalBlockNum = le32_to_cpu( |
|---|
| 1110 | | - phd->freedSpaceTable.extPosition), |
|---|
| 1111 | | - .partitionReferenceNum = p_index, |
|---|
| 1112 | | - }; |
|---|
| 1113 | | - struct inode *inode; |
|---|
| 1114 | | - |
|---|
| 1115 | | - inode = udf_iget_special(sb, &loc); |
|---|
| 1116 | | - if (IS_ERR(inode)) { |
|---|
| 1117 | | - udf_debug("cannot load freedSpaceTable (part %d)\n", |
|---|
| 1118 | | - p_index); |
|---|
| 1119 | | - return PTR_ERR(inode); |
|---|
| 1120 | | - } |
|---|
| 1121 | | - map->s_fspace.s_table = inode; |
|---|
| 1122 | | - map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; |
|---|
| 1123 | | - udf_debug("freedSpaceTable (part %d) @ %lu\n", |
|---|
| 1124 | | - p_index, map->s_fspace.s_table->i_ino); |
|---|
| 1125 | | - } |
|---|
| 1126 | | - |
|---|
| 1127 | | - if (phd->freedSpaceBitmap.extLength) { |
|---|
| 1128 | | - struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index); |
|---|
| 1129 | | - if (!bitmap) |
|---|
| 1130 | | - return -ENOMEM; |
|---|
| 1131 | | - map->s_fspace.s_bitmap = bitmap; |
|---|
| 1132 | | - bitmap->s_extPosition = le32_to_cpu( |
|---|
| 1133 | | - phd->freedSpaceBitmap.extPosition); |
|---|
| 1134 | | - map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP; |
|---|
| 1135 | | - udf_debug("freedSpaceBitmap (part %d) @ %u\n", |
|---|
| 1136 | | - p_index, bitmap->s_extPosition); |
|---|
| 1137 | | - } |
|---|
| 1138 | 1143 | return 0; |
|---|
| 1139 | 1144 | } |
|---|
| 1140 | 1145 | |
|---|
| .. | .. |
|---|
| 1200 | 1205 | vat20 = (struct virtualAllocationTable20 *)bh->b_data; |
|---|
| 1201 | 1206 | } else { |
|---|
| 1202 | 1207 | vat20 = (struct virtualAllocationTable20 *) |
|---|
| 1203 | | - vati->i_ext.i_data; |
|---|
| 1208 | + vati->i_data; |
|---|
| 1204 | 1209 | } |
|---|
| 1205 | 1210 | |
|---|
| 1206 | 1211 | map->s_type_specific.s_virtual.s_start_offset = |
|---|
| .. | .. |
|---|
| 1269 | 1274 | * PHYSICAL partitions are already set up |
|---|
| 1270 | 1275 | */ |
|---|
| 1271 | 1276 | type1_idx = i; |
|---|
| 1272 | | -#ifdef UDFFS_DEBUG |
|---|
| 1273 | 1277 | map = NULL; /* supress 'maybe used uninitialized' warning */ |
|---|
| 1274 | | -#endif |
|---|
| 1275 | 1278 | for (i = 0; i < sbi->s_partitions; i++) { |
|---|
| 1276 | 1279 | map = &sbi->s_partmaps[i]; |
|---|
| 1277 | 1280 | |
|---|
| .. | .. |
|---|
| 1401 | 1404 | goto out_bh; |
|---|
| 1402 | 1405 | } |
|---|
| 1403 | 1406 | |
|---|
| 1407 | + ret = udf_verify_domain_identifier(sb, &lvd->domainIdent, |
|---|
| 1408 | + "logical volume"); |
|---|
| 1409 | + if (ret) |
|---|
| 1410 | + goto out_bh; |
|---|
| 1404 | 1411 | ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); |
|---|
| 1405 | 1412 | if (ret) |
|---|
| 1406 | 1413 | goto out_bh; |
|---|
| .. | .. |
|---|
| 1510 | 1517 | if (lvd->integritySeqExt.extLength) |
|---|
| 1511 | 1518 | udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt)); |
|---|
| 1512 | 1519 | ret = 0; |
|---|
| 1520 | + |
|---|
| 1521 | + if (!sbi->s_lvid_bh) { |
|---|
| 1522 | + /* We can't generate unique IDs without a valid LVID */ |
|---|
| 1523 | + if (sb_rdonly(sb)) { |
|---|
| 1524 | + UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT); |
|---|
| 1525 | + } else { |
|---|
| 1526 | + udf_warn(sb, "Damaged or missing LVID, forcing " |
|---|
| 1527 | + "readonly mount\n"); |
|---|
| 1528 | + ret = -EACCES; |
|---|
| 1529 | + } |
|---|
| 1530 | + } |
|---|
| 1513 | 1531 | out_bh: |
|---|
| 1514 | 1532 | brelse(bh); |
|---|
| 1515 | 1533 | return ret; |
|---|
| .. | .. |
|---|
| 1959 | 1977 | int silent, struct kernel_lb_addr *fileset) |
|---|
| 1960 | 1978 | { |
|---|
| 1961 | 1979 | struct udf_sb_info *sbi = UDF_SB(sb); |
|---|
| 1962 | | - loff_t nsr_off; |
|---|
| 1980 | + int nsr = 0; |
|---|
| 1963 | 1981 | int ret; |
|---|
| 1964 | 1982 | |
|---|
| 1965 | 1983 | if (!sb_set_blocksize(sb, uopt->blocksize)) { |
|---|
| .. | .. |
|---|
| 1970 | 1988 | sbi->s_last_block = uopt->lastblock; |
|---|
| 1971 | 1989 | if (!uopt->novrs) { |
|---|
| 1972 | 1990 | /* Check that it is NSR02 compliant */ |
|---|
| 1973 | | - nsr_off = udf_check_vsd(sb); |
|---|
| 1974 | | - if (!nsr_off) { |
|---|
| 1991 | + nsr = udf_check_vsd(sb); |
|---|
| 1992 | + if (!nsr) { |
|---|
| 1975 | 1993 | if (!silent) |
|---|
| 1976 | 1994 | udf_warn(sb, "No VRS found\n"); |
|---|
| 1977 | 1995 | return -EINVAL; |
|---|
| 1978 | 1996 | } |
|---|
| 1979 | | - if (nsr_off == -1) |
|---|
| 1997 | + if (nsr == -1) |
|---|
| 1980 | 1998 | udf_debug("Failed to read sector at offset %d. " |
|---|
| 1981 | 1999 | "Assuming open disc. Skipping validity " |
|---|
| 1982 | 2000 | "check\n", VSD_FIRST_SECTOR_OFFSET); |
|---|
| .. | .. |
|---|
| 1997 | 2015 | return 0; |
|---|
| 1998 | 2016 | } |
|---|
| 1999 | 2017 | |
|---|
| 2018 | +static void udf_finalize_lvid(struct logicalVolIntegrityDesc *lvid) |
|---|
| 2019 | +{ |
|---|
| 2020 | + struct timespec64 ts; |
|---|
| 2021 | + |
|---|
| 2022 | + ktime_get_real_ts64(&ts); |
|---|
| 2023 | + udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts); |
|---|
| 2024 | + lvid->descTag.descCRC = cpu_to_le16( |
|---|
| 2025 | + crc_itu_t(0, (char *)lvid + sizeof(struct tag), |
|---|
| 2026 | + le16_to_cpu(lvid->descTag.descCRCLength))); |
|---|
| 2027 | + lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
|---|
| 2028 | +} |
|---|
| 2029 | + |
|---|
| 2000 | 2030 | static void udf_open_lvid(struct super_block *sb) |
|---|
| 2001 | 2031 | { |
|---|
| 2002 | 2032 | struct udf_sb_info *sbi = UDF_SB(sb); |
|---|
| 2003 | 2033 | struct buffer_head *bh = sbi->s_lvid_bh; |
|---|
| 2004 | 2034 | struct logicalVolIntegrityDesc *lvid; |
|---|
| 2005 | 2035 | struct logicalVolIntegrityDescImpUse *lvidiu; |
|---|
| 2006 | | - struct timespec64 ts; |
|---|
| 2007 | 2036 | |
|---|
| 2008 | 2037 | if (!bh) |
|---|
| 2009 | 2038 | return; |
|---|
| .. | .. |
|---|
| 2015 | 2044 | mutex_lock(&sbi->s_alloc_mutex); |
|---|
| 2016 | 2045 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
|---|
| 2017 | 2046 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
|---|
| 2018 | | - ktime_get_real_ts64(&ts); |
|---|
| 2019 | | - udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts); |
|---|
| 2020 | 2047 | if (le32_to_cpu(lvid->integrityType) == LVID_INTEGRITY_TYPE_CLOSE) |
|---|
| 2021 | 2048 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); |
|---|
| 2022 | 2049 | else |
|---|
| 2023 | 2050 | UDF_SET_FLAG(sb, UDF_FLAG_INCONSISTENT); |
|---|
| 2024 | 2051 | |
|---|
| 2025 | | - lvid->descTag.descCRC = cpu_to_le16( |
|---|
| 2026 | | - crc_itu_t(0, (char *)lvid + sizeof(struct tag), |
|---|
| 2027 | | - le16_to_cpu(lvid->descTag.descCRCLength))); |
|---|
| 2028 | | - |
|---|
| 2029 | | - lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
|---|
| 2052 | + udf_finalize_lvid(lvid); |
|---|
| 2030 | 2053 | mark_buffer_dirty(bh); |
|---|
| 2031 | 2054 | sbi->s_lvid_dirty = 0; |
|---|
| 2032 | 2055 | mutex_unlock(&sbi->s_alloc_mutex); |
|---|
| .. | .. |
|---|
| 2040 | 2063 | struct buffer_head *bh = sbi->s_lvid_bh; |
|---|
| 2041 | 2064 | struct logicalVolIntegrityDesc *lvid; |
|---|
| 2042 | 2065 | struct logicalVolIntegrityDescImpUse *lvidiu; |
|---|
| 2043 | | - struct timespec64 ts; |
|---|
| 2044 | 2066 | |
|---|
| 2045 | 2067 | if (!bh) |
|---|
| 2046 | 2068 | return; |
|---|
| .. | .. |
|---|
| 2052 | 2074 | mutex_lock(&sbi->s_alloc_mutex); |
|---|
| 2053 | 2075 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
|---|
| 2054 | 2076 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
|---|
| 2055 | | - ktime_get_real_ts64(&ts); |
|---|
| 2056 | | - udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts); |
|---|
| 2057 | 2077 | if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev)) |
|---|
| 2058 | 2078 | lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION); |
|---|
| 2059 | 2079 | if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev)) |
|---|
| .. | .. |
|---|
| 2063 | 2083 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_INCONSISTENT)) |
|---|
| 2064 | 2084 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); |
|---|
| 2065 | 2085 | |
|---|
| 2066 | | - lvid->descTag.descCRC = cpu_to_le16( |
|---|
| 2067 | | - crc_itu_t(0, (char *)lvid + sizeof(struct tag), |
|---|
| 2068 | | - le16_to_cpu(lvid->descTag.descCRCLength))); |
|---|
| 2069 | | - |
|---|
| 2070 | | - lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
|---|
| 2071 | 2086 | /* |
|---|
| 2072 | 2087 | * We set buffer uptodate unconditionally here to avoid spurious |
|---|
| 2073 | 2088 | * warnings from mark_buffer_dirty() when previous EIO has marked |
|---|
| 2074 | 2089 | * the buffer as !uptodate |
|---|
| 2075 | 2090 | */ |
|---|
| 2076 | 2091 | set_buffer_uptodate(bh); |
|---|
| 2092 | + udf_finalize_lvid(lvid); |
|---|
| 2077 | 2093 | mark_buffer_dirty(bh); |
|---|
| 2078 | 2094 | sbi->s_lvid_dirty = 0; |
|---|
| 2079 | 2095 | mutex_unlock(&sbi->s_alloc_mutex); |
|---|
| .. | .. |
|---|
| 2102 | 2118 | if (!(++uniqueID & 0xFFFFFFFF)) |
|---|
| 2103 | 2119 | uniqueID += 16; |
|---|
| 2104 | 2120 | lvhd->uniqueID = cpu_to_le64(uniqueID); |
|---|
| 2121 | + udf_updated_lvid(sb); |
|---|
| 2105 | 2122 | mutex_unlock(&sbi->s_alloc_mutex); |
|---|
| 2106 | | - mark_buffer_dirty(bh); |
|---|
| 2107 | 2123 | |
|---|
| 2108 | 2124 | return ret; |
|---|
| 2109 | 2125 | } |
|---|
| .. | .. |
|---|
| 2136 | 2152 | |
|---|
| 2137 | 2153 | if (!udf_parse_options((char *)options, &uopt, false)) |
|---|
| 2138 | 2154 | goto parse_options_failure; |
|---|
| 2139 | | - |
|---|
| 2140 | | - if (uopt.flags & (1 << UDF_FLAG_UTF8) && |
|---|
| 2141 | | - uopt.flags & (1 << UDF_FLAG_NLS_MAP)) { |
|---|
| 2142 | | - udf_err(sb, "utf8 cannot be combined with iocharset\n"); |
|---|
| 2143 | | - goto parse_options_failure; |
|---|
| 2144 | | - } |
|---|
| 2145 | | - if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) { |
|---|
| 2146 | | - uopt.nls_map = load_nls_default(); |
|---|
| 2147 | | - if (!uopt.nls_map) |
|---|
| 2148 | | - uopt.flags &= ~(1 << UDF_FLAG_NLS_MAP); |
|---|
| 2149 | | - else |
|---|
| 2150 | | - udf_debug("Using default NLS map\n"); |
|---|
| 2151 | | - } |
|---|
| 2152 | | - if (!(uopt.flags & (1 << UDF_FLAG_NLS_MAP))) |
|---|
| 2153 | | - uopt.flags |= (1 << UDF_FLAG_UTF8); |
|---|
| 2154 | 2155 | |
|---|
| 2155 | 2156 | fileset.logicalBlockNum = 0xFFFFFFFF; |
|---|
| 2156 | 2157 | fileset.partitionReferenceNum = 0xFFFF; |
|---|
| .. | .. |
|---|
| 2262 | 2263 | UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT); |
|---|
| 2263 | 2264 | } |
|---|
| 2264 | 2265 | |
|---|
| 2265 | | - if (udf_find_fileset(sb, &fileset, &rootdir)) { |
|---|
| 2266 | + ret = udf_find_fileset(sb, &fileset, &rootdir); |
|---|
| 2267 | + if (ret < 0) { |
|---|
| 2266 | 2268 | udf_warn(sb, "No fileset found\n"); |
|---|
| 2267 | | - ret = -EINVAL; |
|---|
| 2268 | 2269 | goto error_out; |
|---|
| 2269 | 2270 | } |
|---|
| 2270 | 2271 | |
|---|
| .. | .. |
|---|
| 2306 | 2307 | error_out: |
|---|
| 2307 | 2308 | iput(sbi->s_vat_inode); |
|---|
| 2308 | 2309 | parse_options_failure: |
|---|
| 2309 | | - if (uopt.nls_map) |
|---|
| 2310 | | - unload_nls(uopt.nls_map); |
|---|
| 2310 | + unload_nls(uopt.nls_map); |
|---|
| 2311 | 2311 | if (lvid_open) |
|---|
| 2312 | 2312 | udf_close_lvid(sb); |
|---|
| 2313 | 2313 | brelse(sbi->s_lvid_bh); |
|---|
| .. | .. |
|---|
| 2357 | 2357 | sbi = UDF_SB(sb); |
|---|
| 2358 | 2358 | |
|---|
| 2359 | 2359 | iput(sbi->s_vat_inode); |
|---|
| 2360 | | - if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) |
|---|
| 2361 | | - unload_nls(sbi->s_nls_map); |
|---|
| 2360 | + unload_nls(sbi->s_nls_map); |
|---|
| 2362 | 2361 | if (!sb_rdonly(sb)) |
|---|
| 2363 | 2362 | udf_close_lvid(sb); |
|---|
| 2364 | 2363 | brelse(sbi->s_lvid_bh); |
|---|
| .. | .. |
|---|
| 2374 | 2373 | |
|---|
| 2375 | 2374 | mutex_lock(&sbi->s_alloc_mutex); |
|---|
| 2376 | 2375 | if (sbi->s_lvid_dirty) { |
|---|
| 2376 | + struct buffer_head *bh = sbi->s_lvid_bh; |
|---|
| 2377 | + struct logicalVolIntegrityDesc *lvid; |
|---|
| 2378 | + |
|---|
| 2379 | + lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
|---|
| 2380 | + udf_finalize_lvid(lvid); |
|---|
| 2381 | + |
|---|
| 2377 | 2382 | /* |
|---|
| 2378 | 2383 | * Blockdevice will be synced later so we don't have to submit |
|---|
| 2379 | 2384 | * the buffer for IO |
|---|
| 2380 | 2385 | */ |
|---|
| 2381 | | - mark_buffer_dirty(sbi->s_lvid_bh); |
|---|
| 2386 | + mark_buffer_dirty(bh); |
|---|
| 2382 | 2387 | sbi->s_lvid_dirty = 0; |
|---|
| 2383 | 2388 | } |
|---|
| 2384 | 2389 | mutex_unlock(&sbi->s_alloc_mutex); |
|---|
| .. | .. |
|---|
| 2399 | 2404 | buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len; |
|---|
| 2400 | 2405 | buf->f_bfree = udf_count_free(sb); |
|---|
| 2401 | 2406 | buf->f_bavail = buf->f_bfree; |
|---|
| 2407 | + /* |
|---|
| 2408 | + * Let's pretend each free block is also a free 'inode' since UDF does |
|---|
| 2409 | + * not have separate preallocated table of inodes. |
|---|
| 2410 | + */ |
|---|
| 2402 | 2411 | buf->f_files = (lvidiu != NULL ? (le32_to_cpu(lvidiu->numFiles) + |
|---|
| 2403 | 2412 | le32_to_cpu(lvidiu->numDirs)) : 0) |
|---|
| 2404 | 2413 | + buf->f_bfree; |
|---|
| 2405 | 2414 | buf->f_ffree = buf->f_bfree; |
|---|
| 2406 | 2415 | buf->f_namelen = UDF_NAME_LEN; |
|---|
| 2407 | | - buf->f_fsid.val[0] = (u32)id; |
|---|
| 2408 | | - buf->f_fsid.val[1] = (u32)(id >> 32); |
|---|
| 2416 | + buf->f_fsid = u64_to_fsid(id); |
|---|
| 2409 | 2417 | |
|---|
| 2410 | 2418 | return 0; |
|---|
| 2411 | 2419 | } |
|---|
| .. | .. |
|---|
| 2525 | 2533 | accum += udf_count_free_bitmap(sb, |
|---|
| 2526 | 2534 | map->s_uspace.s_bitmap); |
|---|
| 2527 | 2535 | } |
|---|
| 2528 | | - if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { |
|---|
| 2529 | | - accum += udf_count_free_bitmap(sb, |
|---|
| 2530 | | - map->s_fspace.s_bitmap); |
|---|
| 2531 | | - } |
|---|
| 2532 | 2536 | if (accum) |
|---|
| 2533 | 2537 | return accum; |
|---|
| 2534 | 2538 | |
|---|
| .. | .. |
|---|
| 2536 | 2540 | accum += udf_count_free_table(sb, |
|---|
| 2537 | 2541 | map->s_uspace.s_table); |
|---|
| 2538 | 2542 | } |
|---|
| 2539 | | - if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { |
|---|
| 2540 | | - accum += udf_count_free_table(sb, |
|---|
| 2541 | | - map->s_fspace.s_table); |
|---|
| 2542 | | - } |
|---|
| 2543 | | - |
|---|
| 2544 | 2543 | return accum; |
|---|
| 2545 | 2544 | } |
|---|
| 2546 | 2545 | |
|---|
| 2547 | 2546 | MODULE_AUTHOR("Ben Fennema"); |
|---|
| 2548 | 2547 | MODULE_DESCRIPTION("Universal Disk Format Filesystem"); |
|---|
| 2549 | 2548 | MODULE_LICENSE("GPL"); |
|---|
| 2549 | +MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY); |
|---|
| 2550 | 2550 | module_init(init_udf_fs) |
|---|
| 2551 | 2551 | module_exit(exit_udf_fs) |
|---|