aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-11-23 08:37:51 -0500
committerChristoph Hellwig <hch@lst.de>2010-11-23 08:37:51 -0500
commit358f26d52680cb150907302d4334359de7dd2d59 (patch)
tree9348f861b49d5dd51049e31971cc09ab151388bc /fs/hfsplus
parent52399b171dfaea02b6944cd6feba49b624147126 (diff)
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')
-rw-r--r--fs/hfsplus/hfsplus_fs.h17
-rw-r--r--fs/hfsplus/part_tbl.c124
2 files changed, 71 insertions, 70 deletions
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 276ddb0fd0fd..0d8532d96694 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -401,23 +401,6 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode)
401 return list_entry(inode, struct hfsplus_inode_info, vfs_inode); 401 return list_entry(inode, struct hfsplus_inode_info, vfs_inode);
402} 402}
403 403
404#define sb_bread512(sb, sec, data) ({ \
405 struct buffer_head *__bh; \
406 sector_t __block; \
407 loff_t __start; \
408 int __offset; \
409 \
410 __start = (loff_t)(sec) << HFSPLUS_SECTOR_SHIFT;\
411 __block = __start >> (sb)->s_blocksize_bits; \
412 __offset = __start & ((sb)->s_blocksize - 1); \
413 __bh = sb_bread((sb), __block); \
414 if (likely(__bh != NULL)) \
415 data = (void *)(__bh->b_data + __offset);\
416 else \
417 data = NULL; \
418 __bh; \
419})
420
421/* time macros */ 404/* time macros */
422#define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) 405#define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U)
423#define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U)) 406#define __hfsp_ut2mt(t) (cpu_to_be32(t + 2082844800U))
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 @@
13 * 13 *
14 */ 14 */
15 15
16#include <linux/slab.h>
16#include "hfsplus_fs.h" 17#include "hfsplus_fs.h"
17 18
18/* offsets to various blocks */ 19/* offsets to various blocks */
@@ -65,70 +66,87 @@ struct old_pmap {
65 } pdEntry[42]; 66 } pdEntry[42];
66} __packed; 67} __packed;
67 68
69static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
70 sector_t *part_start, sector_t *part_size)
71{
72 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
73 int i;
74
75 for (i = 0; i < 42; i++) {
76 struct old_pmap_entry *p = &pm->pdEntry[i];
77
78 if (p->pdStart && p->pdSize &&
79 p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
80 (sbi->part < 0 || sbi->part == i)) {
81 *part_start += be32_to_cpu(p->pdStart);
82 *part_size = be32_to_cpu(p->pdSize);
83 return 0;
84 }
85 }
86
87 return -ENOENT;
88}
89
90static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
91 sector_t *part_start, sector_t *part_size)
92{
93 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
94 int size = be32_to_cpu(pm->pmMapBlkCnt);
95 int res;
96 int i = 0;
97
98 do {
99 if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
100 (sbi->part < 0 || sbi->part == i)) {
101 *part_start += be32_to_cpu(pm->pmPyPartStart);
102 *part_size = be32_to_cpu(pm->pmPartBlkCnt);
103 return 0;
104 }
105
106 if (++i >= size)
107 return -ENOENT;
108
109 res = hfsplus_submit_bio(sb->s_bdev,
110 *part_start + HFS_PMAP_BLK + i,
111 pm, READ);
112 if (res)
113 return res;
114 } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
115
116 return -ENOENT;
117}
118
68/* 119/*
69 * hfs_part_find() 120 * Parse the partition map looking for the start and length of a
70 * 121 * HFS/HFS+ partition.
71 * Parse the partition map looking for the
72 * start and length of the 'part'th HFS partition.
73 */ 122 */
74int hfs_part_find(struct super_block *sb, 123int hfs_part_find(struct super_block *sb,
75 sector_t *part_start, sector_t *part_size) 124 sector_t *part_start, sector_t *part_size)
76{ 125{
77 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 126 void *data;
78 struct buffer_head *bh; 127 int res;
79 __be16 *data; 128
80 int i, size, res; 129 data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
130 if (!data)
131 return -ENOMEM;
81 132
82 res = -ENOENT; 133 res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
83 bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data); 134 data, READ);
84 if (!bh) 135 if (res)
85 return -EIO; 136 return res;
86 137
87 switch (be16_to_cpu(*data)) { 138 switch (be16_to_cpu(*((__be16 *)data))) {
88 case HFS_OLD_PMAP_MAGIC: 139 case HFS_OLD_PMAP_MAGIC:
89 { 140 res = hfs_parse_old_pmap(sb, data, part_start, part_size);
90 struct old_pmap *pm;
91 struct old_pmap_entry *p;
92
93 pm = (struct old_pmap *)bh->b_data;
94 p = pm->pdEntry;
95 size = 42;
96 for (i = 0; i < size; p++, i++) {
97 if (p->pdStart && p->pdSize &&
98 p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
99 (sbi->part < 0 || sbi->part == i)) {
100 *part_start += be32_to_cpu(p->pdStart);
101 *part_size = be32_to_cpu(p->pdSize);
102 res = 0;
103 }
104 }
105 break; 141 break;
106 }
107 case HFS_NEW_PMAP_MAGIC: 142 case HFS_NEW_PMAP_MAGIC:
108 { 143 res = hfs_parse_new_pmap(sb, data, part_start, part_size);
109 struct new_pmap *pm; 144 break;
110 145 default:
111 pm = (struct new_pmap *)bh->b_data; 146 res = -ENOENT;
112 size = be32_to_cpu(pm->pmMapBlkCnt);
113 for (i = 0; i < size;) {
114 if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
115 (sbi->part < 0 || sbi->part == i)) {
116 *part_start += be32_to_cpu(pm->pmPyPartStart);
117 *part_size = be32_to_cpu(pm->pmPartBlkCnt);
118 res = 0;
119 break;
120 }
121 brelse(bh);
122 bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
123 if (!bh)
124 return -EIO;
125 if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
126 break;
127 }
128 break; 147 break;
129 }
130 } 148 }
131 brelse(bh);
132 149
150 kfree(data);
133 return res; 151 return res;
134} 152}