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