OSDN Git Service

block: rework zone reporting
[tomoyo/tomoyo-test1.git] / drivers / md / dm-zoned-metadata.c
index feb4718..069e467 100644 (file)
@@ -1080,9 +1080,10 @@ static int dmz_load_sb(struct dmz_metadata *zmd)
 /*
  * Initialize a zone descriptor.
  */
-static int dmz_init_zone(struct dmz_metadata *zmd, struct dm_zone *zone,
-                        struct blk_zone *blkz)
+static int dmz_init_zone(struct blk_zone *blkz, unsigned int idx, void *data)
 {
+       struct dmz_metadata *zmd = data;
+       struct dm_zone *zone = &zmd->zones[idx];
        struct dmz_dev *dev = zmd->dev;
 
        /* Ignore the eventual last runt (smaller) zone */
@@ -1096,26 +1097,29 @@ static int dmz_init_zone(struct dmz_metadata *zmd, struct dm_zone *zone,
        atomic_set(&zone->refcount, 0);
        zone->chunk = DMZ_MAP_UNMAPPED;
 
-       if (blkz->type == BLK_ZONE_TYPE_CONVENTIONAL) {
+       switch (blkz->type) {
+       case BLK_ZONE_TYPE_CONVENTIONAL:
                set_bit(DMZ_RND, &zone->flags);
                zmd->nr_rnd_zones++;
-       } else if (blkz->type == BLK_ZONE_TYPE_SEQWRITE_REQ ||
-                  blkz->type == BLK_ZONE_TYPE_SEQWRITE_PREF) {
+               break;
+       case BLK_ZONE_TYPE_SEQWRITE_REQ:
+       case BLK_ZONE_TYPE_SEQWRITE_PREF:
                set_bit(DMZ_SEQ, &zone->flags);
-       } else
+               break;
+       default:
                return -ENXIO;
-
-       if (blkz->cond == BLK_ZONE_COND_OFFLINE)
-               set_bit(DMZ_OFFLINE, &zone->flags);
-       else if (blkz->cond == BLK_ZONE_COND_READONLY)
-               set_bit(DMZ_READ_ONLY, &zone->flags);
+       }
 
        if (dmz_is_rnd(zone))
                zone->wp_block = 0;
        else
                zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start);
 
-       if (!dmz_is_offline(zone) && !dmz_is_readonly(zone)) {
+       if (blkz->cond == BLK_ZONE_COND_OFFLINE)
+               set_bit(DMZ_OFFLINE, &zone->flags);
+       else if (blkz->cond == BLK_ZONE_COND_READONLY)
+               set_bit(DMZ_READ_ONLY, &zone->flags);
+       else {
                zmd->nr_useable_zones++;
                if (dmz_is_rnd(zone)) {
                        zmd->nr_rnd_zones++;
@@ -1139,23 +1143,13 @@ static void dmz_drop_zones(struct dmz_metadata *zmd)
 }
 
 /*
- * The size of a zone report in number of zones.
- * This results in 4096*64B=256KB report zones commands.
- */
-#define DMZ_REPORT_NR_ZONES    4096
-
-/*
  * Allocate and initialize zone descriptors using the zone
  * information from disk.
  */
 static int dmz_init_zones(struct dmz_metadata *zmd)
 {
        struct dmz_dev *dev = zmd->dev;
-       struct dm_zone *zone;
-       struct blk_zone *blkz;
-       unsigned int nr_blkz;
-       sector_t sector = 0;
-       int i, ret = 0;
+       int ret;
 
        /* Init */
        zmd->zone_bitmap_size = dev->zone_nr_blocks >> 3;
@@ -1169,54 +1163,38 @@ static int dmz_init_zones(struct dmz_metadata *zmd)
        dmz_dev_info(dev, "Using %zu B for zone information",
                     sizeof(struct dm_zone) * dev->nr_zones);
 
-       /* Get zone information */
-       nr_blkz = DMZ_REPORT_NR_ZONES;
-       blkz = kcalloc(nr_blkz, sizeof(struct blk_zone), GFP_KERNEL);
-       if (!blkz) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        /*
-        * Get zone information and initialize zone descriptors.
-        * At the same time, determine where the super block
-        * should be: first block of the first randomly writable
-        * zone.
+        * Get zone information and initialize zone descriptors.  At the same
+        * time, determine where the super block should be: first block of the
+        * first randomly writable zone.
         */
-       zone = zmd->zones;
-       while (sector < dev->capacity) {
-               /* Get zone information */
-               nr_blkz = DMZ_REPORT_NR_ZONES;
-               ret = blkdev_report_zones(dev->bdev, sector, blkz, &nr_blkz);
-               if (ret) {
-                       dmz_dev_err(dev, "Report zones failed %d", ret);
-                       goto out;
-               }
+       ret = blkdev_report_zones(dev->bdev, 0, BLK_ALL_ZONES, dmz_init_zone,
+                                 zmd);
+       if (ret < 0) {
+               dmz_drop_zones(zmd);
+               return ret;
+       }
 
-               if (!nr_blkz)
-                       break;
+       return 0;
+}
 
-               /* Process report */
-               for (i = 0; i < nr_blkz; i++) {
-                       ret = dmz_init_zone(zmd, zone, &blkz[i]);
-                       if (ret)
-                               goto out;
-                       sector += dev->zone_nr_sectors;
-                       zone++;
-               }
-       }
+static int dmz_update_zone_cb(struct blk_zone *blkz, unsigned int idx,
+                             void *data)
+{
+       struct dm_zone *zone = data;
 
-       /* The entire zone configuration of the disk should now be known */
-       if (sector < dev->capacity) {
-               dmz_dev_err(dev, "Failed to get correct zone information");
-               ret = -ENXIO;
-       }
-out:
-       kfree(blkz);
-       if (ret)
-               dmz_drop_zones(zmd);
+       clear_bit(DMZ_OFFLINE, &zone->flags);
+       clear_bit(DMZ_READ_ONLY, &zone->flags);
+       if (blkz->cond == BLK_ZONE_COND_OFFLINE)
+               set_bit(DMZ_OFFLINE, &zone->flags);
+       else if (blkz->cond == BLK_ZONE_COND_READONLY)
+               set_bit(DMZ_READ_ONLY, &zone->flags);
 
-       return ret;
+       if (dmz_is_seq(zone))
+               zone->wp_block = dmz_sect2blk(blkz->wp - blkz->start);
+       else
+               zone->wp_block = 0;
+       return 0;
 }
 
 /*
@@ -1224,9 +1202,7 @@ out:
  */
 static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
 {
-       unsigned int nr_blkz = 1;
        unsigned int noio_flag;
-       struct blk_zone blkz;
        int ret;
 
        /*
@@ -1236,29 +1212,18 @@ static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
         * GFP_NOIO was specified.
         */
        noio_flag = memalloc_noio_save();
-       ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone),
-                                 &blkz, &nr_blkz);
+       ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone), 1,
+                                 dmz_update_zone_cb, zone);
        memalloc_noio_restore(noio_flag);
-       if (!nr_blkz)
+
+       if (ret == 0)
                ret = -EIO;
-       if (ret) {
+       if (ret < 0) {
                dmz_dev_err(zmd->dev, "Get zone %u report failed",
                            dmz_id(zmd, zone));
                return ret;
        }
 
-       clear_bit(DMZ_OFFLINE, &zone->flags);
-       clear_bit(DMZ_READ_ONLY, &zone->flags);
-       if (blkz.cond == BLK_ZONE_COND_OFFLINE)
-               set_bit(DMZ_OFFLINE, &zone->flags);
-       else if (blkz.cond == BLK_ZONE_COND_READONLY)
-               set_bit(DMZ_READ_ONLY, &zone->flags);
-
-       if (dmz_is_seq(zone))
-               zone->wp_block = dmz_sect2blk(blkz.wp - blkz.start);
-       else
-               zone->wp_block = 0;
-
        return 0;
 }