Lines Matching +full:cache +full:- +full:op +full:- +full:block +full:- +full:size

1 // SPDX-License-Identifier: GPL-2.0
3 * Zoned block device handling
16 #include <linux/blk-mq.h>
37 * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX.
40 * Description: Centralize block layer function to convert BLK_ZONE_COND_XXX
60 if (!rq->q->disk->seq_zones_wlock) in blk_req_needs_zone_write_lock()
71 if (test_and_set_bit(zno, rq->q->disk->seq_zones_wlock)) in blk_req_zone_write_trylock()
74 WARN_ON_ONCE(rq->rq_flags & RQF_ZONE_WRITE_LOCKED); in blk_req_zone_write_trylock()
75 rq->rq_flags |= RQF_ZONE_WRITE_LOCKED; in blk_req_zone_write_trylock()
84 rq->q->disk->seq_zones_wlock))) in __blk_req_zone_write_lock()
87 WARN_ON_ONCE(rq->rq_flags & RQF_ZONE_WRITE_LOCKED); in __blk_req_zone_write_lock()
88 rq->rq_flags |= RQF_ZONE_WRITE_LOCKED; in __blk_req_zone_write_lock()
94 rq->rq_flags &= ~RQF_ZONE_WRITE_LOCKED; in __blk_req_zone_write_unlock()
95 if (rq->q->disk->seq_zones_wlock) in __blk_req_zone_write_unlock()
97 rq->q->disk->seq_zones_wlock)); in __blk_req_zone_write_unlock()
102 * bdev_nr_zones - Get number of zones
105 * Return the total number of zones of a zoned block device. For a block
114 return (bdev_nr_sectors(bdev) + zone_sectors - 1) >> in bdev_nr_zones()
120 * blkdev_report_zones - Get zones information
121 * @bdev: Target block device
141 struct gendisk *disk = bdev->bd_disk; in blkdev_report_zones()
144 if (!bdev_is_zoned(bdev) || WARN_ON_ONCE(!disk->fops->report_zones)) in blkdev_report_zones()
145 return -EOPNOTSUPP; in blkdev_report_zones()
150 return disk->fops->report_zones(disk, sector, nr_zones, cb, data); in blkdev_report_zones()
165 * For an all-zones reset, ignore conventional, empty, read-only in blk_zone_need_reset_cb()
168 switch (zone->cond) { in blk_zone_need_reset_cb()
183 struct gendisk *disk = bdev->bd_disk; in blkdev_zone_reset_all_emulated()
191 need_reset = blk_alloc_zone_bitmap(disk->queue->node, disk->nr_zones); in blkdev_zone_reset_all_emulated()
193 return -ENOMEM; in blkdev_zone_reset_all_emulated()
195 ret = disk->fops->report_zones(disk, 0, disk->nr_zones, in blkdev_zone_reset_all_emulated()
209 bio->bi_iter.bi_sector = sector; in blkdev_zone_reset_all_emulated()
235 * blkdev_zone_mgmt - Execute a zone management operation on a range of zones
236 * @bdev: Target block device
237 * @op: Operation to be performed on the zones
240 * must be zone size aligned.
250 int blkdev_zone_mgmt(struct block_device *bdev, enum req_op op, in blkdev_zone_mgmt() argument
261 return -EOPNOTSUPP; in blkdev_zone_mgmt()
264 return -EPERM; in blkdev_zone_mgmt()
266 if (!op_is_zone_mgmt(op)) in blkdev_zone_mgmt()
267 return -EOPNOTSUPP; in blkdev_zone_mgmt()
271 return -EINVAL; in blkdev_zone_mgmt()
275 return -EINVAL; in blkdev_zone_mgmt()
278 return -EINVAL; in blkdev_zone_mgmt()
286 if (op == REQ_OP_ZONE_RESET && sector == 0 && nr_sectors == capacity) { in blkdev_zone_mgmt()
293 bio = blk_next_bio(bio, bdev, 0, op | REQ_SYNC, gfp_mask); in blkdev_zone_mgmt()
294 bio->bi_iter.bi_sector = sector; in blkdev_zone_mgmt()
317 if (copy_to_user(&args->zones[idx], zone, sizeof(struct blk_zone))) in blkdev_copy_zone_to_user()
318 return -EFAULT; in blkdev_copy_zone_to_user()
335 return -EINVAL; in blkdev_report_zones_ioctl()
338 return -ENOTTY; in blkdev_report_zones_ioctl()
341 return -EFAULT; in blkdev_report_zones_ioctl()
344 return -EINVAL; in blkdev_report_zones_ioctl()
355 return -EFAULT; in blkdev_report_zones_ioctl()
364 if (zrange->sector + zrange->nr_sectors <= zrange->sector || in blkdev_truncate_zone_range()
365 zrange->sector + zrange->nr_sectors > get_capacity(bdev->bd_disk)) in blkdev_truncate_zone_range()
367 return -EINVAL; in blkdev_truncate_zone_range()
369 start = zrange->sector << SECTOR_SHIFT; in blkdev_truncate_zone_range()
370 end = ((zrange->sector + zrange->nr_sectors) << SECTOR_SHIFT) - 1; in blkdev_truncate_zone_range()
384 enum req_op op; in blkdev_zone_mgmt_ioctl() local
388 return -EINVAL; in blkdev_zone_mgmt_ioctl()
391 return -ENOTTY; in blkdev_zone_mgmt_ioctl()
394 return -EBADF; in blkdev_zone_mgmt_ioctl()
397 return -EFAULT; in blkdev_zone_mgmt_ioctl()
401 op = REQ_OP_ZONE_RESET; in blkdev_zone_mgmt_ioctl()
403 /* Invalidate the page cache, including dirty pages. */ in blkdev_zone_mgmt_ioctl()
404 filemap_invalidate_lock(bdev->bd_inode->i_mapping); in blkdev_zone_mgmt_ioctl()
410 op = REQ_OP_ZONE_OPEN; in blkdev_zone_mgmt_ioctl()
413 op = REQ_OP_ZONE_CLOSE; in blkdev_zone_mgmt_ioctl()
416 op = REQ_OP_ZONE_FINISH; in blkdev_zone_mgmt_ioctl()
419 return -ENOTTY; in blkdev_zone_mgmt_ioctl()
422 ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors, in blkdev_zone_mgmt_ioctl()
427 filemap_invalidate_unlock(bdev->bd_inode->i_mapping); in blkdev_zone_mgmt_ioctl()
434 kfree(disk->conv_zones_bitmap); in disk_free_zone_bitmaps()
435 disk->conv_zones_bitmap = NULL; in disk_free_zone_bitmaps()
436 kfree(disk->seq_zones_wlock); in disk_free_zone_bitmaps()
437 disk->seq_zones_wlock = NULL; in disk_free_zone_bitmaps()
449 * Helper function to check the validity of zones of a zoned block device.
455 struct gendisk *disk = args->disk; in blk_revalidate_zone_cb()
456 struct request_queue *q = disk->queue; in blk_revalidate_zone_cb()
458 sector_t zone_sectors = q->limits.chunk_sectors; in blk_revalidate_zone_cb()
461 if (zone->start != args->sector) { in blk_revalidate_zone_cb()
463 disk->disk_name, args->sector, zone->start); in blk_revalidate_zone_cb()
464 return -ENODEV; in blk_revalidate_zone_cb()
467 if (zone->start >= capacity || !zone->len) { in blk_revalidate_zone_cb()
469 disk->disk_name, zone->start, zone->len); in blk_revalidate_zone_cb()
470 return -ENODEV; in blk_revalidate_zone_cb()
474 * All zones must have the same size, with the exception on an eventual in blk_revalidate_zone_cb()
477 if (zone->start + zone->len < capacity) { in blk_revalidate_zone_cb()
478 if (zone->len != zone_sectors) { in blk_revalidate_zone_cb()
479 pr_warn("%s: Invalid zoned device with non constant zone size\n", in blk_revalidate_zone_cb()
480 disk->disk_name); in blk_revalidate_zone_cb()
481 return -ENODEV; in blk_revalidate_zone_cb()
483 } else if (zone->len > zone_sectors) { in blk_revalidate_zone_cb()
484 pr_warn("%s: Invalid zoned device with larger last zone size\n", in blk_revalidate_zone_cb()
485 disk->disk_name); in blk_revalidate_zone_cb()
486 return -ENODEV; in blk_revalidate_zone_cb()
490 switch (zone->type) { in blk_revalidate_zone_cb()
492 if (!args->conv_zones_bitmap) { in blk_revalidate_zone_cb()
493 args->conv_zones_bitmap = in blk_revalidate_zone_cb()
494 blk_alloc_zone_bitmap(q->node, args->nr_zones); in blk_revalidate_zone_cb()
495 if (!args->conv_zones_bitmap) in blk_revalidate_zone_cb()
496 return -ENOMEM; in blk_revalidate_zone_cb()
498 set_bit(idx, args->conv_zones_bitmap); in blk_revalidate_zone_cb()
502 if (!args->seq_zones_wlock) { in blk_revalidate_zone_cb()
503 args->seq_zones_wlock = in blk_revalidate_zone_cb()
504 blk_alloc_zone_bitmap(q->node, args->nr_zones); in blk_revalidate_zone_cb()
505 if (!args->seq_zones_wlock) in blk_revalidate_zone_cb()
506 return -ENOMEM; in blk_revalidate_zone_cb()
511 disk->disk_name, (int)zone->type, zone->start); in blk_revalidate_zone_cb()
512 return -ENODEV; in blk_revalidate_zone_cb()
515 args->sector += zone->len; in blk_revalidate_zone_cb()
520 * blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps
524 * Helper function for low-level device drivers to check and (re) allocate and
526 * be called within the disk ->revalidate method for blk-mq based drivers.
528 * device zone size (chunk_sector limit) and the max zone append limit.
530 * only need to set disk->nr_zones so that the sysfs exposed value is correct.
538 struct request_queue *q = disk->queue; in blk_revalidate_disk_zones()
539 sector_t zone_sectors = q->limits.chunk_sectors; in blk_revalidate_disk_zones()
546 return -EIO; in blk_revalidate_disk_zones()
548 return -EIO; in blk_revalidate_disk_zones()
551 return -ENODEV; in blk_revalidate_disk_zones()
554 * Checks that the device driver indicated a valid zone size and that in blk_revalidate_disk_zones()
558 pr_warn("%s: Invalid non power of two zone size (%llu)\n", in blk_revalidate_disk_zones()
559 disk->disk_name, zone_sectors); in blk_revalidate_disk_zones()
560 return -ENODEV; in blk_revalidate_disk_zones()
563 if (!q->limits.max_zone_append_sectors) { in blk_revalidate_disk_zones()
565 disk->disk_name); in blk_revalidate_disk_zones()
566 return -ENODEV; in blk_revalidate_disk_zones()
574 args.nr_zones = (capacity + zone_sectors - 1) >> ilog2(zone_sectors); in blk_revalidate_disk_zones()
576 ret = disk->fops->report_zones(disk, 0, UINT_MAX, in blk_revalidate_disk_zones()
579 pr_warn("%s: No zones reported\n", disk->disk_name); in blk_revalidate_disk_zones()
580 ret = -ENODEV; in blk_revalidate_disk_zones()
590 disk->disk_name, args.sector); in blk_revalidate_disk_zones()
591 ret = -ENODEV; in blk_revalidate_disk_zones()
601 disk->nr_zones = args.nr_zones; in blk_revalidate_disk_zones()
602 swap(disk->seq_zones_wlock, args.seq_zones_wlock); in blk_revalidate_disk_zones()
603 swap(disk->conv_zones_bitmap, args.conv_zones_bitmap); in blk_revalidate_disk_zones()
608 pr_warn("%s: failed to revalidate zones\n", disk->disk_name); in blk_revalidate_disk_zones()
621 struct request_queue *q = disk->queue; in disk_clear_zone_settings()
627 q->required_elevator_features &= ~ELEVATOR_F_ZBD_SEQ_WRITE; in disk_clear_zone_settings()
628 disk->nr_zones = 0; in disk_clear_zone_settings()
629 disk->max_open_zones = 0; in disk_clear_zone_settings()
630 disk->max_active_zones = 0; in disk_clear_zone_settings()
631 q->limits.chunk_sectors = 0; in disk_clear_zone_settings()
632 q->limits.zone_write_granularity = 0; in disk_clear_zone_settings()
633 q->limits.max_zone_append_sectors = 0; in disk_clear_zone_settings()