Merge tag 'for-5.8-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
[linux-2.6-microblaze.git] / block / blk-zoned.c
index f87956e..23831fa 100644 (file)
@@ -82,6 +82,20 @@ bool blk_req_needs_zone_write_lock(struct request *rq)
 }
 EXPORT_SYMBOL_GPL(blk_req_needs_zone_write_lock);
 
+bool blk_req_zone_write_trylock(struct request *rq)
+{
+       unsigned int zno = blk_rq_zone_no(rq);
+
+       if (test_and_set_bit(zno, rq->q->seq_zones_wlock))
+               return false;
+
+       WARN_ON_ONCE(rq->rq_flags & RQF_ZONE_WRITE_LOCKED);
+       rq->rq_flags |= RQF_ZONE_WRITE_LOCKED;
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(blk_req_zone_write_trylock);
+
 void __blk_req_zone_write_lock(struct request *rq)
 {
        if (WARN_ON_ONCE(test_and_set_bit(blk_rq_zone_no(rq),
@@ -457,14 +471,19 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
 /**
  * blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps
  * @disk:      Target disk
+ * @update_driver_data:        Callback to update driver data on the frozen disk
  *
  * Helper function for low-level device drivers to (re) allocate and initialize
  * a disk request queue zone bitmaps. This functions should normally be called
  * within the disk ->revalidate method for blk-mq based drivers.  For BIO based
  * drivers only q->nr_zones needs to be updated so that the sysfs exposed value
  * is correct.
+ * If the @update_driver_data callback function is not NULL, the callback is
+ * executed with the device request queue frozen after all zones have been
+ * checked.
  */
-int blk_revalidate_disk_zones(struct gendisk *disk)
+int blk_revalidate_disk_zones(struct gendisk *disk,
+                             void (*update_driver_data)(struct gendisk *disk))
 {
        struct request_queue *q = disk->queue;
        struct blk_revalidate_zone_args args = {
@@ -498,6 +517,8 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
                q->nr_zones = args.nr_zones;
                swap(q->seq_zones_wlock, args.seq_zones_wlock);
                swap(q->conv_zones_bitmap, args.conv_zones_bitmap);
+               if (update_driver_data)
+                       update_driver_data(disk);
                ret = 0;
        } else {
                pr_warn("%s: failed to revalidate zones\n", disk->disk_name);