From: Ben Slusky 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: _