diff options
Diffstat (limited to 'freed-ora/current/f15/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch')
-rw-r--r-- | freed-ora/current/f15/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch | 315 |
1 files changed, 0 insertions, 315 deletions
diff --git a/freed-ora/current/f15/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch b/freed-ora/current/f15/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch deleted file mode 100644 index c81bf91d1..000000000 --- a/freed-ora/current/f15/hfsplus-ensure-bio-requests-are-not-smaller-than-the.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 6596528e391ad978a6a120142cba97a1d7324cb6 Mon Sep 17 00:00:00 2001 -From: Seth Forshee <seth.forshee@canonical.com> -Date: Mon, 18 Jul 2011 08:06:23 -0700 -Subject: [PATCH] hfsplus: ensure bio requests are not smaller than the - hardware sectors - -Currently all bio requests are 512 bytes, which may fail for media -whose physical sector size is larger than this. Ensure these -requests are not smaller than the block device logical block size. - -BugLink: http://bugs.launchpad.net/bugs/734883 -Signed-off-by: Seth Forshee <seth.forshee@canonical.com> -Signed-off-by: Christoph Hellwig <hch@lst.de> ---- - fs/hfsplus/hfsplus_fs.h | 16 ++++++++- - fs/hfsplus/part_tbl.c | 32 ++++++++++-------- - fs/hfsplus/super.c | 12 +++--- - fs/hfsplus/wrapper.c | 83 +++++++++++++++++++++++++++++++++++----------- - 4 files changed, 101 insertions(+), 42 deletions(-) - -diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h -index 0bebf74..81dfd1e 100644 ---- a/fs/hfsplus/hfsplus_fs.h -+++ b/fs/hfsplus/hfsplus_fs.h -@@ -13,6 +13,7 @@ - #include <linux/fs.h> - #include <linux/mutex.h> - #include <linux/buffer_head.h> -+#include <linux/blkdev.h> - #include "hfsplus_raw.h" - - #define DBG_BNODE_REFS 0x00000001 -@@ -110,7 +111,9 @@ struct hfsplus_vh; - struct hfs_btree; - - struct hfsplus_sb_info { -+ void *s_vhdr_buf; - struct hfsplus_vh *s_vhdr; -+ void *s_backup_vhdr_buf; - struct hfsplus_vh *s_backup_vhdr; - struct hfs_btree *ext_tree; - struct hfs_btree *cat_tree; -@@ -258,6 +261,15 @@ struct hfsplus_readdir_data { - struct hfsplus_cat_key key; - }; - -+/* -+ * Find minimum acceptible I/O size for an hfsplus sb. -+ */ -+static inline unsigned short hfsplus_min_io_size(struct super_block *sb) -+{ -+ return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev), -+ HFSPLUS_SECTOR_SIZE); -+} -+ - #define hfs_btree_open hfsplus_btree_open - #define hfs_btree_close hfsplus_btree_close - #define hfs_btree_write hfsplus_btree_write -@@ -436,8 +448,8 @@ int hfsplus_compare_dentry(const struct dentry *parent, - /* wrapper.c */ - int hfsplus_read_wrapper(struct super_block *); - int hfs_part_find(struct super_block *, sector_t *, sector_t *); --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw); -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw); - - /* time macros */ - #define __hfsp_mt2ut(t) (be32_to_cpu(t) - 2082844800U) -diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c -index 40ad88c..eb355d8 100644 ---- a/fs/hfsplus/part_tbl.c -+++ b/fs/hfsplus/part_tbl.c -@@ -88,11 +88,12 @@ static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, - return -ENOENT; - } - --static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, -- sector_t *part_start, sector_t *part_size) -+static int hfs_parse_new_pmap(struct super_block *sb, void *buf, -+ 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 buf_size = hfsplus_min_io_size(sb); - int res; - int i = 0; - -@@ -107,11 +108,14 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - if (++i >= size) - return -ENOENT; - -- res = hfsplus_submit_bio(sb->s_bdev, -- *part_start + HFS_PMAP_BLK + i, -- pm, READ); -- if (res) -- return res; -+ pm = (struct new_pmap *)((u8 *)pm + HFSPLUS_SECTOR_SIZE); -+ if ((u8 *)pm - (u8 *)buf >= buf_size) { -+ res = hfsplus_submit_bio(sb, -+ *part_start + HFS_PMAP_BLK + i, -+ buf, (void **)&pm, READ); -+ if (res) -+ return res; -+ } - } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); - - return -ENOENT; -@@ -124,15 +128,15 @@ static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, - int hfs_part_find(struct super_block *sb, - sector_t *part_start, sector_t *part_size) - { -- void *data; -+ void *buf, *data; - int res; - -- data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!data) -+ buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!buf) - return -ENOMEM; - -- res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, -- data, READ); -+ res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, -+ buf, &data, READ); - if (res) - goto out; - -@@ -141,13 +145,13 @@ int hfs_part_find(struct super_block *sb, - res = hfs_parse_old_pmap(sb, data, part_start, part_size); - break; - case HFS_NEW_PMAP_MAGIC: -- res = hfs_parse_new_pmap(sb, data, part_start, part_size); -+ res = hfs_parse_new_pmap(sb, buf, data, part_start, part_size); - break; - default: - res = -ENOENT; - break; - } - out: -- kfree(data); -+ kfree(buf); - return res; - } -diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c -index 84f56e1..c106ca2 100644 ---- a/fs/hfsplus/super.c -+++ b/fs/hfsplus/super.c -@@ -203,17 +203,17 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) - write_backup = 1; - } - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, WRITE_SYNC); -+ sbi->s_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error = error2; - if (!write_backup) - goto out; - -- error2 = hfsplus_submit_bio(sb->s_bdev, -+ error2 = hfsplus_submit_bio(sb, - sbi->part_start + sbi->sect_count - 2, -- sbi->s_backup_vhdr, WRITE_SYNC); -+ sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); - if (!error) - error2 = error; - out: -@@ -257,8 +257,8 @@ static void hfsplus_put_super(struct super_block *sb) - hfs_btree_close(sbi->ext_tree); - iput(sbi->alloc_file); - iput(sbi->hidden_dir); -- kfree(sbi->s_vhdr); -- kfree(sbi->s_backup_vhdr); -+ kfree(sbi->s_vhdr_buf); -+ kfree(sbi->s_backup_vhdr_buf); - unload_nls(sbi->nls); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; -diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c -index 2f933e8..10e515a 100644 ---- a/fs/hfsplus/wrapper.c -+++ b/fs/hfsplus/wrapper.c -@@ -31,25 +31,67 @@ static void hfsplus_end_io_sync(struct bio *bio, int err) - complete(bio->bi_private); - } - --int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, -- void *data, int rw) -+/* -+ * hfsplus_submit_bio - Perfrom block I/O -+ * @sb: super block of volume for I/O -+ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes -+ * @buf: buffer for I/O -+ * @data: output pointer for location of requested data -+ * @rw: direction of I/O -+ * -+ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than -+ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads -+ * @data will return a pointer to the start of the requested sector, -+ * which may not be the same location as @buf. -+ * -+ * If @sector is not aligned to the bdev logical block size it will -+ * be rounded down. For writes this means that @buf should contain data -+ * that starts at the rounded-down address. As long as the data was -+ * read using hfsplus_submit_bio() and the same buffer is used things -+ * will work correctly. -+ */ -+int hfsplus_submit_bio(struct super_block *sb, sector_t sector, -+ void *buf, void **data, int rw) - { - DECLARE_COMPLETION_ONSTACK(wait); - struct bio *bio; - int ret = 0; -+ unsigned int io_size; -+ loff_t start; -+ int offset; -+ -+ /* -+ * Align sector to hardware sector size and find offset. We -+ * assume that io_size is a power of two, which _should_ -+ * be true. -+ */ -+ io_size = hfsplus_min_io_size(sb); -+ start = (loff_t)sector << HFSPLUS_SECTOR_SHIFT; -+ offset = start & (io_size - 1); -+ sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1); - - bio = bio_alloc(GFP_NOIO, 1); - bio->bi_sector = sector; -- bio->bi_bdev = bdev; -+ bio->bi_bdev = sb->s_bdev; - bio->bi_end_io = hfsplus_end_io_sync; - bio->bi_private = &wait; - -- /* -- * We always submit one sector at a time, so bio_add_page must not fail. -- */ -- if (bio_add_page(bio, virt_to_page(data), HFSPLUS_SECTOR_SIZE, -- offset_in_page(data)) != HFSPLUS_SECTOR_SIZE) -- BUG(); -+ if (!(rw & WRITE) && data) -+ *data = (u8 *)buf + offset; -+ -+ while (io_size > 0) { -+ unsigned int page_offset = offset_in_page(buf); -+ unsigned int len = min_t(unsigned int, PAGE_SIZE - page_offset, -+ io_size); -+ -+ ret = bio_add_page(bio, virt_to_page(buf), len, page_offset); -+ if (ret != len) { -+ ret = -EIO; -+ goto out; -+ } -+ io_size -= len; -+ buf = (u8 *)buf + len; -+ } - - submit_bio(rw, bio); - wait_for_completion(&wait); -@@ -57,8 +99,9 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector, - if (!bio_flagged(bio, BIO_UPTODATE)) - ret = -EIO; - -+out: - bio_put(bio); -- return ret; -+ return ret < 0 ? ret : 0; - } - - static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd) -@@ -143,17 +186,17 @@ int hfsplus_read_wrapper(struct super_block *sb) - goto out; - - error = -ENOMEM; -- sbi->s_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_vhdr) -+ sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_vhdr_buf) - goto out; -- sbi->s_backup_vhdr = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); -- if (!sbi->s_backup_vhdr) -+ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL); -+ if (!sbi->s_backup_vhdr_buf) - goto out_free_vhdr; - - reread: -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + HFSPLUS_VOLHEAD_SECTOR, -- sbi->s_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, -+ sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, -+ READ); - if (error) - goto out_free_backup_vhdr; - -@@ -183,9 +226,9 @@ reread: - goto reread; - } - -- error = hfsplus_submit_bio(sb->s_bdev, -- part_start + part_size - 2, -- sbi->s_backup_vhdr, READ); -+ error = hfsplus_submit_bio(sb, part_start + part_size - 2, -+ sbi->s_backup_vhdr_buf, -+ (void **)&sbi->s_backup_vhdr, READ); - if (error) - goto out_free_backup_vhdr; - --- -1.7.6 - |