1 /* 2 * Zoned block device handling 3 * 4 * Copyright (c) 2015, Hannes Reinecke 5 * Copyright (c) 2015, SUSE Linux GmbH 6 * 7 * Copyright (c) 2016, Damien Le Moal 8 * Copyright (c) 2016, Western Digital 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/rbtree.h> 14 #include <linux/blkdev.h> 15 16 static inline sector_t blk_zone_start(struct request_queue *q, 17 sector_t sector) 18 { 19 sector_t zone_mask = blk_queue_zone_sectors(q) - 1; 20 21 return sector & ~zone_mask; 22 } 23 24 /* 25 * Check that a zone report belongs to the partition. 26 * If yes, fix its start sector and write pointer, copy it in the 27 * zone information array and return true. Return false otherwise. 28 */ 29 static bool blkdev_report_zone(struct block_device *bdev, 30 struct blk_zone *rep, 31 struct blk_zone *zone) 32 { 33 sector_t offset = get_start_sect(bdev); 34 35 if (rep->start < offset) 36 return false; 37 38 rep->start -= offset; 39 if (rep->start + rep->len > bdev->bd_part->nr_sects) 40 return false; 41 42 if (rep->type == BLK_ZONE_TYPE_CONVENTIONAL) 43 rep->wp = rep->start + rep->len; 44 else 45 rep->wp -= offset; 46 memcpy(zone, rep, sizeof(struct blk_zone)); 47 48 return true; 49 } 50 51 /** 52 * blkdev_report_zones - Get zones information 53 * @bdev: Target block device 54 * @sector: Sector from which to report zones 55 * @zones: Array of zone structures where to return the zones information 56 * @nr_zones: Number of zone structures in the zone array 57 * @gfp_mask: Memory allocation flags (for bio_alloc) 58 * 59 * Description: 60 * Get zone information starting from the zone containing @sector. 61 * The number of zone information reported may be less than the number 62 * requested by @nr_zones. The number of zones actually reported is 63 * returned in @nr_zones. 64 */ 65 int blkdev_report_zones(struct block_device *bdev, 66 sector_t sector, 67 struct blk_zone *zones, 68 unsigned int *nr_zones, 69 gfp_t gfp_mask) 70 { 71 struct request_queue *q = bdev_get_queue(bdev); 72 struct blk_zone_report_hdr *hdr; 73 unsigned int nrz = *nr_zones; 74 struct page *page; 75 unsigned int nr_rep; 76 size_t rep_bytes; 77 unsigned int nr_pages; 78 struct bio *bio; 79 struct bio_vec *bv; 80 unsigned int i, n, nz; 81 unsigned int ofst; 82 void *addr; 83 int ret; 84 85 if (!q) 86 return -ENXIO; 87 88 if (!blk_queue_is_zoned(q)) 89 return -EOPNOTSUPP; 90 91 if (!nrz) 92 return 0; 93 94 if (sector > bdev->bd_part->nr_sects) { 95 *nr_zones = 0; 96 return 0; 97 } 98 99 /* 100 * The zone report has a header. So make room for it in the 101 * payload. Also make sure that the report fits in a single BIO 102 * that will not be split down the stack. 103 */ 104 rep_bytes = sizeof(struct blk_zone_report_hdr) + 105 sizeof(struct blk_zone) * nrz; 106 rep_bytes = (rep_bytes + PAGE_SIZE - 1) & PAGE_MASK; 107 if (rep_bytes > (queue_max_sectors(q) << 9)) 108 rep_bytes = queue_max_sectors(q) << 9; 109 110 nr_pages = min_t(unsigned int, BIO_MAX_PAGES, 111 rep_bytes >> PAGE_SHIFT); 112 nr_pages = min_t(unsigned int, nr_pages, 113 queue_max_segments(q)); 114 115 bio = bio_alloc(gfp_mask, nr_pages); 116 if (!bio) 117 return -ENOMEM; 118 119 bio->bi_bdev = bdev; 120 bio->bi_iter.bi_sector = blk_zone_start(q, sector); 121 bio_set_op_attrs(bio, REQ_OP_ZONE_REPORT, 0); 122 123 for (i = 0; i < nr_pages; i++) { 124 page = alloc_page(gfp_mask); 125 if (!page) { 126 ret = -ENOMEM; 127 goto out; 128 } 129 if (!bio_add_page(bio, page, PAGE_SIZE, 0)) { 130 __free_page(page); 131 break; 132 } 133 } 134 135 if (i == 0) 136 ret = -ENOMEM; 137 else 138 ret = submit_bio_wait(bio); 139 if (ret) 140 goto out; 141 142 /* 143 * Process the report result: skip the header and go through the 144 * reported zones to fixup and fixup the zone information for 145 * partitions. At the same time, return the zone information into 146 * the zone array. 147 */ 148 n = 0; 149 nz = 0; 150 nr_rep = 0; 151 bio_for_each_segment_all(bv, bio, i) { 152 153 if (!bv->bv_page) 154 break; 155 156 addr = kmap_atomic(bv->bv_page); 157 158 /* Get header in the first page */ 159 ofst = 0; 160 if (!nr_rep) { 161 hdr = (struct blk_zone_report_hdr *) addr; 162 nr_rep = hdr->nr_zones; 163 ofst = sizeof(struct blk_zone_report_hdr); 164 } 165 166 /* Fixup and report zones */ 167 while (ofst < bv->bv_len && 168 n < nr_rep && nz < nrz) { 169 if (blkdev_report_zone(bdev, addr + ofst, &zones[nz])) 170 nz++; 171 ofst += sizeof(struct blk_zone); 172 n++; 173 } 174 175 kunmap_atomic(addr); 176 177 if (n >= nr_rep || nz >= nrz) 178 break; 179 180 } 181 182 *nr_zones = nz; 183 out: 184 bio_for_each_segment_all(bv, bio, i) 185 __free_page(bv->bv_page); 186 bio_put(bio); 187 188 return ret; 189 } 190 EXPORT_SYMBOL_GPL(blkdev_report_zones); 191 192 /** 193 * blkdev_reset_zones - Reset zones write pointer 194 * @bdev: Target block device 195 * @sector: Start sector of the first zone to reset 196 * @nr_sectors: Number of sectors, at least the length of one zone 197 * @gfp_mask: Memory allocation flags (for bio_alloc) 198 * 199 * Description: 200 * Reset the write pointer of the zones contained in the range 201 * @sector..@sector+@nr_sectors. Specifying the entire disk sector range 202 * is valid, but the specified range should not contain conventional zones. 203 */ 204 int blkdev_reset_zones(struct block_device *bdev, 205 sector_t sector, sector_t nr_sectors, 206 gfp_t gfp_mask) 207 { 208 struct request_queue *q = bdev_get_queue(bdev); 209 sector_t zone_sectors; 210 sector_t end_sector = sector + nr_sectors; 211 struct bio *bio; 212 int ret; 213 214 if (!q) 215 return -ENXIO; 216 217 if (!blk_queue_is_zoned(q)) 218 return -EOPNOTSUPP; 219 220 if (end_sector > bdev->bd_part->nr_sects) 221 /* Out of range */ 222 return -EINVAL; 223 224 /* Check alignment (handle eventual smaller last zone) */ 225 zone_sectors = blk_queue_zone_sectors(q); 226 if (sector & (zone_sectors - 1)) 227 return -EINVAL; 228 229 if ((nr_sectors & (zone_sectors - 1)) && 230 end_sector != bdev->bd_part->nr_sects) 231 return -EINVAL; 232 233 while (sector < end_sector) { 234 235 bio = bio_alloc(gfp_mask, 0); 236 bio->bi_iter.bi_sector = sector; 237 bio->bi_bdev = bdev; 238 bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0); 239 240 ret = submit_bio_wait(bio); 241 bio_put(bio); 242 243 if (ret) 244 return ret; 245 246 sector += zone_sectors; 247 248 /* This may take a while, so be nice to others */ 249 cond_resched(); 250 251 } 252 253 return 0; 254 } 255 EXPORT_SYMBOL_GPL(blkdev_reset_zones); 256 257 /** 258 * BLKREPORTZONE ioctl processing. 259 * Called from blkdev_ioctl. 260 */ 261 int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, 262 unsigned int cmd, unsigned long arg) 263 { 264 void __user *argp = (void __user *)arg; 265 struct request_queue *q; 266 struct blk_zone_report rep; 267 struct blk_zone *zones; 268 int ret; 269 270 if (!argp) 271 return -EINVAL; 272 273 q = bdev_get_queue(bdev); 274 if (!q) 275 return -ENXIO; 276 277 if (!blk_queue_is_zoned(q)) 278 return -ENOTTY; 279 280 if (!capable(CAP_SYS_ADMIN)) 281 return -EACCES; 282 283 if (copy_from_user(&rep, argp, sizeof(struct blk_zone_report))) 284 return -EFAULT; 285 286 if (!rep.nr_zones) 287 return -EINVAL; 288 289 zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL); 290 if (!zones) 291 return -ENOMEM; 292 293 ret = blkdev_report_zones(bdev, rep.sector, 294 zones, &rep.nr_zones, 295 GFP_KERNEL); 296 if (ret) 297 goto out; 298 299 if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) { 300 ret = -EFAULT; 301 goto out; 302 } 303 304 if (rep.nr_zones) { 305 if (copy_to_user(argp + sizeof(struct blk_zone_report), zones, 306 sizeof(struct blk_zone) * rep.nr_zones)) 307 ret = -EFAULT; 308 } 309 310 out: 311 kfree(zones); 312 313 return ret; 314 } 315 316 /** 317 * BLKRESETZONE ioctl processing. 318 * Called from blkdev_ioctl. 319 */ 320 int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode, 321 unsigned int cmd, unsigned long arg) 322 { 323 void __user *argp = (void __user *)arg; 324 struct request_queue *q; 325 struct blk_zone_range zrange; 326 327 if (!argp) 328 return -EINVAL; 329 330 q = bdev_get_queue(bdev); 331 if (!q) 332 return -ENXIO; 333 334 if (!blk_queue_is_zoned(q)) 335 return -ENOTTY; 336 337 if (!capable(CAP_SYS_ADMIN)) 338 return -EACCES; 339 340 if (!(mode & FMODE_WRITE)) 341 return -EBADF; 342 343 if (copy_from_user(&zrange, argp, sizeof(struct blk_zone_range))) 344 return -EFAULT; 345 346 return blkdev_reset_zones(bdev, zrange.sector, zrange.nr_sectors, 347 GFP_KERNEL); 348 } 349