From: Ben Slusky <sluskyb@paranoiacs.org>

We need to set the hardsect_size of the loop device to that of the real
device.

The loop device advertises a block size of 1024 even when configured over a
cdrom.

When burning a ext2 on a cd, and mounting it directly, I get:

	blocksize=2048;

when I losetup /dev/loop0 /dev/cdrom, and then try to mount, I get:

blocksize=1024; and then misaligned transfer; this results in not being able
to read the superblock.

The loop device should be changed to export the same blocksize of the
underlying device



---

 drivers/block/loop.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)

diff -puN drivers/block/loop.c~loop-fix-hardsect drivers/block/loop.c
--- 25/drivers/block/loop.c~loop-fix-hardsect	2004-01-07 21:18:52.000000000 -0800
+++ 25-akpm/drivers/block/loop.c	2004-01-07 21:20:52.000000000 -0800
@@ -676,7 +676,6 @@ static int loop_set_fd(struct loop_devic
 	if (!file)
 		goto out;
 
-	error = -EINVAL;
 	inode = file->f_dentry->d_inode;
 
 	if (!(file->f_mode & FMODE_WRITE))
@@ -686,7 +685,7 @@ static int loop_set_fd(struct loop_devic
 		lo_device = inode->i_bdev;
 		if (lo_device == bdev) {
 			error = -EBUSY;
-			goto out;
+			goto out_putf;
 		}
 		lo_blocksize = block_size(lo_device);
 		if (bdev_read_only(lo_device))
@@ -697,6 +696,7 @@ static int loop_set_fd(struct loop_devic
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
 		 */
+		error = -EINVAL;
 		if (!inode->i_fop->sendfile)
 			goto out_putf;
 
@@ -709,8 +709,6 @@ static int loop_set_fd(struct loop_devic
 	} else
 		goto out_putf;
 
-	get_file(file);
-
 	if (!(lo_file->f_mode & FMODE_WRITE))
 		lo_flags |= LO_FLAGS_READ_ONLY;
 
@@ -725,15 +723,12 @@ static int loop_set_fd(struct loop_devic
 	lo->lo_sizelimit = 0;
 	if (figure_loop_size(lo)) {
 		error = -EFBIG;
-		fput(file);
 		goto out_putf;
 	}
 	lo->old_gfp_mask = mapping_gfp_mask(inode->i_mapping);
 	mapping_set_gfp_mask(inode->i_mapping,
 			     lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
 
-	set_blocksize(bdev, lo_blocksize);
-
 	lo->lo_bio = lo->lo_biotail = NULL;
 
 	/*
@@ -752,15 +747,18 @@ static int loop_set_fd(struct loop_devic
 		blk_queue_max_sectors(lo->lo_queue, q->max_sectors);
 		blk_queue_max_phys_segments(lo->lo_queue,q->max_phys_segments);
 		blk_queue_max_hw_segments(lo->lo_queue, q->max_hw_segments);
+		blk_queue_hardsect_size(lo->lo_queue, queue_hardsect_size(q));
 		blk_queue_max_segment_size(lo->lo_queue, q->max_segment_size);
 		blk_queue_segment_boundary(lo->lo_queue, q->seg_boundary_mask);
 		blk_queue_merge_bvec(lo->lo_queue, q->merge_bvec_fn);
 	}
 
+	error = set_blocksize(bdev, lo_blocksize);
+	if (error)
+		goto out_putf;
+
 	kernel_thread(loop_thread, lo, CLONE_KERNEL);
 	down(&lo->lo_sem);
-
-	fput(file);
 	return 0;
 
  out_putf:

_