Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify
[pandora-kernel.git] / fs / isofs / inode.c
index 60c2b94..bfdeb82 100644 (file)
@@ -543,6 +543,34 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
        return vol_desc_start;
 }
 
+/*
+ * Check if root directory is empty (has less than 3 files).
+ *
+ * Used to detect broken CDs where ISO root directory is empty but Joliet root
+ * directory is OK. If such CD has Rock Ridge extensions, they will be disabled
+ * (and Joliet used instead) or else no files would be visible.
+ */
+static bool rootdir_empty(struct super_block *sb, unsigned long block)
+{
+       int offset = 0, files = 0, de_len;
+       struct iso_directory_record *de;
+       struct buffer_head *bh;
+
+       bh = sb_bread(sb, block);
+       if (!bh)
+               return true;
+       while (files < 3) {
+               de = (struct iso_directory_record *) (bh->b_data + offset);
+               de_len = *(unsigned char *) de;
+               if (de_len == 0)
+                       break;
+               files++;
+               offset += de_len;
+       }
+       brelse(bh);
+       return files < 3;
+}
+
 /*
  * Initialize the superblock and read the root inode.
  *
@@ -842,6 +870,18 @@ root_found:
        if (IS_ERR(inode))
                goto out_no_root;
 
+       /*
+        * Fix for broken CDs with Rock Ridge and empty ISO root directory but
+        * correct Joliet root directory.
+        */
+       if (sbi->s_rock == 1 && joliet_level &&
+                               rootdir_empty(s, sbi->s_firstdatazone)) {
+               printk(KERN_NOTICE
+                       "ISOFS: primary root directory is empty. "
+                       "Disabling Rock Ridge and switching to Joliet.");
+               sbi->s_rock = 0;
+       }
+
        /*
         * If this disk has both Rock Ridge and Joliet on it, then we
         * want to use Rock Ridge by default.  This can be overridden
@@ -1467,17 +1507,16 @@ struct inode *isofs_iget(struct super_block *sb,
        return inode;
 }
 
-static int isofs_get_sb(struct file_system_type *fs_type,
-       int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+static struct dentry *isofs_mount(struct file_system_type *fs_type,
+       int flags, const char *dev_name, void *data)
 {
-       return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
-                               mnt);
+       return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
 
 static struct file_system_type iso9660_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "iso9660",
-       .get_sb         = isofs_get_sb,
+       .mount          = isofs_mount,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };