diff options
Diffstat (limited to 'fs/isofs/inode.c')
-rw-r--r-- | fs/isofs/inode.c | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 5a44811b5027..bfdeb82a53be 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/nls.h> | 18 | #include <linux/nls.h> |
19 | #include <linux/ctype.h> | 19 | #include <linux/ctype.h> |
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/statfs.h> | 20 | #include <linux/statfs.h> |
22 | #include <linux/cdrom.h> | 21 | #include <linux/cdrom.h> |
23 | #include <linux/parser.h> | 22 | #include <linux/parser.h> |
@@ -44,11 +43,7 @@ static void isofs_put_super(struct super_block *sb) | |||
44 | struct isofs_sb_info *sbi = ISOFS_SB(sb); | 43 | struct isofs_sb_info *sbi = ISOFS_SB(sb); |
45 | 44 | ||
46 | #ifdef CONFIG_JOLIET | 45 | #ifdef CONFIG_JOLIET |
47 | lock_kernel(); | ||
48 | |||
49 | unload_nls(sbi->s_nls_iocharset); | 46 | unload_nls(sbi->s_nls_iocharset); |
50 | |||
51 | unlock_kernel(); | ||
52 | #endif | 47 | #endif |
53 | 48 | ||
54 | kfree(sbi); | 49 | kfree(sbi); |
@@ -549,6 +544,34 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session) | |||
549 | } | 544 | } |
550 | 545 | ||
551 | /* | 546 | /* |
547 | * Check if root directory is empty (has less than 3 files). | ||
548 | * | ||
549 | * Used to detect broken CDs where ISO root directory is empty but Joliet root | ||
550 | * directory is OK. If such CD has Rock Ridge extensions, they will be disabled | ||
551 | * (and Joliet used instead) or else no files would be visible. | ||
552 | */ | ||
553 | static bool rootdir_empty(struct super_block *sb, unsigned long block) | ||
554 | { | ||
555 | int offset = 0, files = 0, de_len; | ||
556 | struct iso_directory_record *de; | ||
557 | struct buffer_head *bh; | ||
558 | |||
559 | bh = sb_bread(sb, block); | ||
560 | if (!bh) | ||
561 | return true; | ||
562 | while (files < 3) { | ||
563 | de = (struct iso_directory_record *) (bh->b_data + offset); | ||
564 | de_len = *(unsigned char *) de; | ||
565 | if (de_len == 0) | ||
566 | break; | ||
567 | files++; | ||
568 | offset += de_len; | ||
569 | } | ||
570 | brelse(bh); | ||
571 | return files < 3; | ||
572 | } | ||
573 | |||
574 | /* | ||
552 | * Initialize the superblock and read the root inode. | 575 | * Initialize the superblock and read the root inode. |
553 | * | 576 | * |
554 | * Note: a check_disk_change() has been done immediately prior | 577 | * Note: a check_disk_change() has been done immediately prior |
@@ -823,6 +846,7 @@ root_found: | |||
823 | sbi->s_utf8 = opt.utf8; | 846 | sbi->s_utf8 = opt.utf8; |
824 | sbi->s_nocompress = opt.nocompress; | 847 | sbi->s_nocompress = opt.nocompress; |
825 | sbi->s_overriderockperm = opt.overriderockperm; | 848 | sbi->s_overriderockperm = opt.overriderockperm; |
849 | mutex_init(&sbi->s_mutex); | ||
826 | /* | 850 | /* |
827 | * It would be incredibly stupid to allow people to mark every file | 851 | * It would be incredibly stupid to allow people to mark every file |
828 | * on the disk as suid, so we merely allow them to set the default | 852 | * on the disk as suid, so we merely allow them to set the default |
@@ -847,6 +871,18 @@ root_found: | |||
847 | goto out_no_root; | 871 | goto out_no_root; |
848 | 872 | ||
849 | /* | 873 | /* |
874 | * Fix for broken CDs with Rock Ridge and empty ISO root directory but | ||
875 | * correct Joliet root directory. | ||
876 | */ | ||
877 | if (sbi->s_rock == 1 && joliet_level && | ||
878 | rootdir_empty(s, sbi->s_firstdatazone)) { | ||
879 | printk(KERN_NOTICE | ||
880 | "ISOFS: primary root directory is empty. " | ||
881 | "Disabling Rock Ridge and switching to Joliet."); | ||
882 | sbi->s_rock = 0; | ||
883 | } | ||
884 | |||
885 | /* | ||
850 | * If this disk has both Rock Ridge and Joliet on it, then we | 886 | * If this disk has both Rock Ridge and Joliet on it, then we |
851 | * want to use Rock Ridge by default. This can be overridden | 887 | * want to use Rock Ridge by default. This can be overridden |
852 | * by using the norock mount option. There is still one other | 888 | * by using the norock mount option. There is still one other |
@@ -966,27 +1002,23 @@ static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) | |||
966 | * or getblk() if they are not. Returns the number of blocks inserted | 1002 | * or getblk() if they are not. Returns the number of blocks inserted |
967 | * (-ve == error.) | 1003 | * (-ve == error.) |
968 | */ | 1004 | */ |
969 | int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | 1005 | int isofs_get_blocks(struct inode *inode, sector_t iblock, |
970 | struct buffer_head **bh, unsigned long nblocks) | 1006 | struct buffer_head **bh, unsigned long nblocks) |
971 | { | 1007 | { |
972 | unsigned long b_off; | 1008 | unsigned long b_off = iblock; |
973 | unsigned offset, sect_size; | 1009 | unsigned offset, sect_size; |
974 | unsigned int firstext; | 1010 | unsigned int firstext; |
975 | unsigned long nextblk, nextoff; | 1011 | unsigned long nextblk, nextoff; |
976 | long iblock = (long)iblock_s; | ||
977 | int section, rv, error; | 1012 | int section, rv, error; |
978 | struct iso_inode_info *ei = ISOFS_I(inode); | 1013 | struct iso_inode_info *ei = ISOFS_I(inode); |
979 | 1014 | ||
980 | lock_kernel(); | ||
981 | |||
982 | error = -EIO; | 1015 | error = -EIO; |
983 | rv = 0; | 1016 | rv = 0; |
984 | if (iblock < 0 || iblock != iblock_s) { | 1017 | if (iblock != b_off) { |
985 | printk(KERN_DEBUG "%s: block number too large\n", __func__); | 1018 | printk(KERN_DEBUG "%s: block number too large\n", __func__); |
986 | goto abort; | 1019 | goto abort; |
987 | } | 1020 | } |
988 | 1021 | ||
989 | b_off = iblock; | ||
990 | 1022 | ||
991 | offset = 0; | 1023 | offset = 0; |
992 | firstext = ei->i_first_extent; | 1024 | firstext = ei->i_first_extent; |
@@ -1004,8 +1036,9 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
1004 | * I/O errors. | 1036 | * I/O errors. |
1005 | */ | 1037 | */ |
1006 | if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) { | 1038 | if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) { |
1007 | printk(KERN_DEBUG "%s: block >= EOF (%ld, %ld)\n", | 1039 | printk(KERN_DEBUG "%s: block >= EOF (%lu, %llu)\n", |
1008 | __func__, iblock, (unsigned long) inode->i_size); | 1040 | __func__, b_off, |
1041 | (unsigned long long)inode->i_size); | ||
1009 | goto abort; | 1042 | goto abort; |
1010 | } | 1043 | } |
1011 | 1044 | ||
@@ -1031,9 +1064,9 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
1031 | if (++section > 100) { | 1064 | if (++section > 100) { |
1032 | printk(KERN_DEBUG "%s: More than 100 file sections ?!?" | 1065 | printk(KERN_DEBUG "%s: More than 100 file sections ?!?" |
1033 | " aborting...\n", __func__); | 1066 | " aborting...\n", __func__); |
1034 | printk(KERN_DEBUG "%s: block=%ld firstext=%u sect_size=%u " | 1067 | printk(KERN_DEBUG "%s: block=%lu firstext=%u sect_size=%u " |
1035 | "nextblk=%lu nextoff=%lu\n", __func__, | 1068 | "nextblk=%lu nextoff=%lu\n", __func__, |
1036 | iblock, firstext, (unsigned) sect_size, | 1069 | b_off, firstext, (unsigned) sect_size, |
1037 | nextblk, nextoff); | 1070 | nextblk, nextoff); |
1038 | goto abort; | 1071 | goto abort; |
1039 | } | 1072 | } |
@@ -1054,7 +1087,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
1054 | 1087 | ||
1055 | error = 0; | 1088 | error = 0; |
1056 | abort: | 1089 | abort: |
1057 | unlock_kernel(); | ||
1058 | return rv != 0 ? rv : error; | 1090 | return rv != 0 ? rv : error; |
1059 | } | 1091 | } |
1060 | 1092 | ||
@@ -1475,17 +1507,16 @@ struct inode *isofs_iget(struct super_block *sb, | |||
1475 | return inode; | 1507 | return inode; |
1476 | } | 1508 | } |
1477 | 1509 | ||
1478 | static int isofs_get_sb(struct file_system_type *fs_type, | 1510 | static struct dentry *isofs_mount(struct file_system_type *fs_type, |
1479 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 1511 | int flags, const char *dev_name, void *data) |
1480 | { | 1512 | { |
1481 | return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, | 1513 | return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super); |
1482 | mnt); | ||
1483 | } | 1514 | } |
1484 | 1515 | ||
1485 | static struct file_system_type iso9660_fs_type = { | 1516 | static struct file_system_type iso9660_fs_type = { |
1486 | .owner = THIS_MODULE, | 1517 | .owner = THIS_MODULE, |
1487 | .name = "iso9660", | 1518 | .name = "iso9660", |
1488 | .get_sb = isofs_get_sb, | 1519 | .mount = isofs_mount, |
1489 | .kill_sb = kill_block_super, | 1520 | .kill_sb = kill_block_super, |
1490 | .fs_flags = FS_REQUIRES_DEV, | 1521 | .fs_flags = FS_REQUIRES_DEV, |
1491 | }; | 1522 | }; |