summaryrefslogtreecommitdiff
path: root/fs/hfsplus/part_tbl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-11-23 16:37:51 +0300
committerChristoph Hellwig <hch@lst.de>2010-11-23 16:37:51 +0300
commit358f26d52680cb150907302d4334359de7dd2d59 (patch)
tree9348f861b49d5dd51049e31971cc09ab151388bc /fs/hfsplus/part_tbl.c
parent52399b171dfaea02b6944cd6feba49b624147126 (diff)
downloadlinux-358f26d52680cb150907302d4334359de7dd2d59.tar.xz
hfsplus: use raw bio access for partition tables
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>
Diffstat (limited to 'fs/hfsplus/part_tbl.c')
-rw-r--r--fs/hfsplus/part_tbl.c124
1 files changed, 71 insertions, 53 deletions
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
index 208b16c645cc..58918222a604 100644
--- a/fs/hfsplus/part_tbl.c
+++ b/fs/hfsplus/part_tbl.c
@@ -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;
}