hfsplus: use raw bio access for partition tables
authorChristoph Hellwig <hch@tuxera.com>
Tue, 23 Nov 2010 13:37:51 +0000 (14:37 +0100)
committerChristoph Hellwig <hch@lst.de>
Tue, 23 Nov 2010 13:37:51 +0000 (14:37 +0100)
Switch the hfsplus partition table reding for cdroms to use our bio
helpers.  Again we don't rely on any caching in the buffer_heads, and
this gets rid of the last buffer_head use in hfsplus.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/part_tbl.c

index 276ddb0..0d8532d 100644 (file)
@@ -401,23 +401,6 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
        return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
 }
 
-#define sb_bread512(sb, sec, data) ({                  \
-       struct buffer_head *__bh;                       \
-       sector_t __block;                               \
-       loff_t __start;                                 \
-       int __offset;                                   \
-                                                       \
-       __start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\
-       __block = __start >> (sb)->s_blocksize_bits;    \
-       __offset = __start & ((sb)->s_blocksize - 1);   \
-       __bh = sb_bread((sb), __block);                 \
-       if (likely(__bh != NULL))                       \
-               data = (void *)(__bh->b_data + __offset);\
-       else                                            \
-               data = NULL;                            \
-       __bh;                                           \
-})
-
 /* time macros */
 #define __hfsp_mt2ut(t)                (be32_to_cpu(t) - 2082844800U)
 #define __hfsp_ut2mt(t)                (cpu_to_be32(t + 2082844800U))
index 208b16c..5891822 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/slab.h>
 #include "hfsplus_fs.h"
 
 /* offsets to various blocks */
@@ -65,70 +66,87 @@ struct old_pmap {
        }       pdEntry[42];
 } __packed;
 
+static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
+               sector_t *part_start, sector_t *part_size)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       int i;
+
+       for (i = 0; i < 42; i++) {
+               struct old_pmap_entry *p = &pm->pdEntry[i];
+
+               if (p->pdStart && p->pdSize &&
+                   p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
+                   (sbi->part < 0 || sbi->part == i)) {
+                       *part_start += be32_to_cpu(p->pdStart);
+                       *part_size = be32_to_cpu(p->pdSize);
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+
+static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
+               sector_t *part_start, sector_t *part_size)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       int size = be32_to_cpu(pm->pmMapBlkCnt);
+       int res;
+       int i = 0;
+
+       do {
+               if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
+                   (sbi->part < 0 || sbi->part == i)) {
+                       *part_start += be32_to_cpu(pm->pmPyPartStart);
+                       *part_size = be32_to_cpu(pm->pmPartBlkCnt);
+                       return 0;
+               }
+
+               if (++i >= size)
+                       return -ENOENT;
+
+               res = hfsplus_submit_bio(sb->s_bdev,
+                                        *part_start + HFS_PMAP_BLK + i,
+                                        pm, READ);
+               if (res)
+                       return res;
+       } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
+
+       return -ENOENT;
+}
+
 /*
- * hfs_part_find()
- *
- * Parse the partition map looking for the
- * start and length of the 'part'th HFS partition.
+ * Parse the partition map looking for the start and length of a
+ * HFS/HFS+ partition.
  */
 int hfs_part_find(struct super_block *sb,
-                 sector_t *part_start, sector_t *part_size)
+               sector_t *part_start, sector_t *part_size)
 {
-       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
-       struct buffer_head *bh;
-       __be16 *data;
-       int i, size, res;
+       void *data;
+       int res;
+
+       data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
-       res = -ENOENT;
-       bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
-       if (!bh)
-               return -EIO;
+       res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
+                                data, READ);
+       if (res)
+               return res;
 
-       switch (be16_to_cpu(*data)) {
+       switch (be16_to_cpu(*((__be16 *)data))) {
        case HFS_OLD_PMAP_MAGIC:
-         {
-               struct old_pmap *pm;
-               struct old_pmap_entry *p;
-
-               pm = (struct old_pmap *)bh->b_data;
-               p = pm->pdEntry;
-               size = 42;
-               for (i = 0; i < size; p++, i++) {
-                       if (p->pdStart && p->pdSize &&
-                           p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
-                           (sbi->part < 0 || sbi->part == i)) {
-                               *part_start += be32_to_cpu(p->pdStart);
-                               *part_size = be32_to_cpu(p->pdSize);
-                               res = 0;
-                       }
-               }
+               res = hfs_parse_old_pmap(sb, data, part_start, part_size);
                break;
-         }
        case HFS_NEW_PMAP_MAGIC:
-         {
-               struct new_pmap *pm;
-
-               pm = (struct new_pmap *)bh->b_data;
-               size = be32_to_cpu(pm->pmMapBlkCnt);
-               for (i = 0; i < size;) {
-                       if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
-                           (sbi->part < 0 || sbi->part == i)) {
-                               *part_start += be32_to_cpu(pm->pmPyPartStart);
-                               *part_size = be32_to_cpu(pm->pmPartBlkCnt);
-                               res = 0;
-                               break;
-                       }
-                       brelse(bh);
-                       bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
-                       if (!bh)
-                               return -EIO;
-                       if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
-                               break;
-               }
+               res = hfs_parse_new_pmap(sb, data, part_start, part_size);
+               break;
+       default:
+               res = -ENOENT;
                break;
-         }
        }
-       brelse(bh);
 
+       kfree(data);
        return res;
 }