Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

loop: support 4k physical blocksize

When generating bootable VM images certain systems (most notably
s390x) require devices with 4k blocksize. This patch implements
a new flag 'LO_FLAGS_BLOCKSIZE' which will set the physical
blocksize to that of the underlying device, and allow to change
the logical blocksize for up to the physical blocksize.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@fb.com>

authored by

Hannes Reinecke and committed by
Jens Axboe
f2c6df7d 51001b7d

+41 -6
+37 -6
drivers/block/loop.c
··· 221 221 } 222 222 223 223 static int 224 - figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit) 224 + figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit, 225 + loff_t logical_blocksize) 225 226 { 226 227 loff_t size = get_size(offset, sizelimit, lo->lo_backing_file); 227 228 sector_t x = (sector_t)size; ··· 234 233 lo->lo_offset = offset; 235 234 if (lo->lo_sizelimit != sizelimit) 236 235 lo->lo_sizelimit = sizelimit; 236 + if (lo->lo_flags & LO_FLAGS_BLOCKSIZE) { 237 + lo->lo_logical_blocksize = logical_blocksize; 238 + blk_queue_physical_block_size(lo->lo_queue, lo->lo_blocksize); 239 + blk_queue_logical_block_size(lo->lo_queue, 240 + lo->lo_logical_blocksize); 241 + } 237 242 set_capacity(lo->lo_disk, x); 238 243 bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9); 239 244 /* let user-space know about the new size */ ··· 817 810 struct file *file = lo->lo_backing_file; 818 811 struct inode *inode = file->f_mapping->host; 819 812 struct request_queue *q = lo->lo_queue; 813 + int lo_bits = 9; 820 814 821 815 /* 822 816 * We use punch hole to reclaim the free space used by the ··· 837 829 838 830 q->limits.discard_granularity = inode->i_sb->s_blocksize; 839 831 q->limits.discard_alignment = 0; 840 - blk_queue_max_discard_sectors(q, UINT_MAX >> 9); 841 - blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9); 832 + if (lo->lo_flags & LO_FLAGS_BLOCKSIZE) 833 + lo_bits = blksize_bits(lo->lo_logical_blocksize); 834 + 835 + blk_queue_max_discard_sectors(q, UINT_MAX >> lo_bits); 836 + blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> lo_bits); 842 837 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); 843 838 } 844 839 ··· 929 918 930 919 lo->use_dio = false; 931 920 lo->lo_blocksize = lo_blocksize; 921 + lo->lo_logical_blocksize = 512; 932 922 lo->lo_device = bdev; 933 923 lo->lo_flags = lo_flags; 934 924 lo->lo_backing_file = file; ··· 1095 1083 int err; 1096 1084 struct loop_func_table *xfer; 1097 1085 kuid_t uid = current_uid(); 1086 + int lo_flags = lo->lo_flags; 1098 1087 1099 1088 if (lo->lo_encrypt_key_size && 1100 1089 !uid_eq(lo->lo_key_owner, uid) && ··· 1128 1115 if (err) 1129 1116 goto exit; 1130 1117 1118 + if (info->lo_flags & LO_FLAGS_BLOCKSIZE) { 1119 + if (!(lo->lo_flags & LO_FLAGS_BLOCKSIZE)) 1120 + lo->lo_logical_blocksize = 512; 1121 + lo->lo_flags |= LO_FLAGS_BLOCKSIZE; 1122 + if (LO_INFO_BLOCKSIZE(info) != 512 && 1123 + LO_INFO_BLOCKSIZE(info) != 1024 && 1124 + LO_INFO_BLOCKSIZE(info) != 2048 && 1125 + LO_INFO_BLOCKSIZE(info) != 4096) 1126 + return -EINVAL; 1127 + if (LO_INFO_BLOCKSIZE(info) > lo->lo_blocksize) 1128 + return -EINVAL; 1129 + } 1130 + 1131 1131 if (lo->lo_offset != info->lo_offset || 1132 - lo->lo_sizelimit != info->lo_sizelimit) 1133 - if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) { 1132 + lo->lo_sizelimit != info->lo_sizelimit || 1133 + lo->lo_flags != lo_flags || 1134 + ((lo->lo_flags & LO_FLAGS_BLOCKSIZE) && 1135 + lo->lo_logical_blocksize != LO_INFO_BLOCKSIZE(info))) { 1136 + if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit, 1137 + LO_INFO_BLOCKSIZE(info))) 1134 1138 err = -EFBIG; 1135 1139 goto exit; 1136 1140 } ··· 1338 1308 if (unlikely(lo->lo_state != Lo_bound)) 1339 1309 return -ENXIO; 1340 1310 1341 - return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit); 1311 + return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit, 1312 + lo->lo_logical_blocksize); 1342 1313 } 1343 1314 1344 1315 static int loop_set_dio(struct loop_device *lo, unsigned long arg)
+1
drivers/block/loop.h
··· 49 49 struct file * lo_backing_file; 50 50 struct block_device *lo_device; 51 51 unsigned lo_blocksize; 52 + unsigned lo_logical_blocksize; 52 53 void *key_data; 53 54 54 55 gfp_t old_gfp_mask;
+3
include/uapi/linux/loop.h
··· 22 22 LO_FLAGS_AUTOCLEAR = 4, 23 23 LO_FLAGS_PARTSCAN = 8, 24 24 LO_FLAGS_DIRECT_IO = 16, 25 + LO_FLAGS_BLOCKSIZE = 32, 25 26 }; 26 27 27 28 #include <asm/posix_types.h> /* for __kernel_old_dev_t */ ··· 59 58 __u8 lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ 60 59 __u64 lo_init[2]; 61 60 }; 61 + 62 + #define LO_INFO_BLOCKSIZE(l) (l)->lo_init[0] 62 63 63 64 /* 64 65 * Loop filter types