Message ID | 20220516133921.126925-4-p.raghav@samsung.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v4,01/13] block: make blkdev_nr_zones and blk_queue_zone_no generic for npo2 zsze | expand |
On 2022/05/16 15:39, Pankaj Raghav wrote: > Remove the condition which disallows non-power_of_2 zone size ZNS drive > to be updated and use generic method to calculate number of zones > instead of relying on log and shift based calculation on zone size. > > The power_of_2 calculation has been replaced directly with generic > calculation without special handling. Both modified functions are not > used in hot paths, they are only used during initialization & > revalidation of the ZNS device. > > Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> > Reviewed by: Adam Manzanares <a.manzanares@samsung.com> > Signed-off-by: Pankaj Raghav <p.raghav@samsung.com> > --- > drivers/nvme/host/zns.c | 24 +++++++++++++++--------- > 1 file changed, 15 insertions(+), 9 deletions(-) > > diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c > index 9f81beb4d..65d2aa68a 100644 > --- a/drivers/nvme/host/zns.c > +++ b/drivers/nvme/host/zns.c > @@ -101,13 +101,6 @@ int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf) > } > > ns->zsze = nvme_lba_to_sect(ns, le64_to_cpu(id->lbafe[lbaf].zsze)); > - if (!is_power_of_2(ns->zsze)) { > - dev_warn(ns->ctrl->device, > - "invalid zone size:%llu for namespace:%u\n", > - ns->zsze, ns->head->ns_id); > - status = -ENODEV; > - goto free_data; > - } > > blk_queue_set_zoned(ns->disk, BLK_ZONED_HM); > blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q); > @@ -128,8 +121,13 @@ static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns, > const size_t min_bufsize = sizeof(struct nvme_zone_report) + > sizeof(struct nvme_zone_descriptor); > > + /* > + * Division is used to calculate nr_zones with no special handling > + * for power of 2 zone sizes as this function is not invoked in a > + * hot path > + */ Comment not very useful. > nr_zones = min_t(unsigned int, nr_zones, > - get_capacity(ns->disk) >> ilog2(ns->zsze)); > + div64_u64(get_capacity(ns->disk), ns->zsze)); > > bufsize = sizeof(struct nvme_zone_report) + > nr_zones * sizeof(struct nvme_zone_descriptor); > @@ -182,6 +180,7 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector, > int ret, zone_idx = 0; > unsigned int nz, i; > size_t buflen; > + u64 remainder = 0; > > if (ns->head->ids.csi != NVME_CSI_ZNS) > return -EINVAL; > @@ -197,7 +196,14 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector, > c.zmr.zrasf = NVME_ZRASF_ZONE_REPORT_ALL; > c.zmr.pr = NVME_REPORT_ZONE_PARTIAL; > > - sector &= ~(ns->zsze - 1); > + /* > + * rounddown the sector value to the nearest zone size. roundown macro > + * provided in math.h will not work for 32 bit architectures. > + * Division is used here with no special handling for power of 2 > + * zone sizes as this function is not invoked in a hot path > + */ Please simplify this to: /* Round down the sector value to the nearest zone start */ > + div64_u64_rem(sector, ns->zsze, &remainder); > + sector -= remainder; > while (zone_idx < nr_zones && sector < get_capacity(ns->disk)) { > memset(report, 0, buflen); >
diff --git a/drivers/nvme/host/zns.c b/drivers/nvme/host/zns.c index 9f81beb4d..65d2aa68a 100644 --- a/drivers/nvme/host/zns.c +++ b/drivers/nvme/host/zns.c @@ -101,13 +101,6 @@ int nvme_update_zone_info(struct nvme_ns *ns, unsigned lbaf) } ns->zsze = nvme_lba_to_sect(ns, le64_to_cpu(id->lbafe[lbaf].zsze)); - if (!is_power_of_2(ns->zsze)) { - dev_warn(ns->ctrl->device, - "invalid zone size:%llu for namespace:%u\n", - ns->zsze, ns->head->ns_id); - status = -ENODEV; - goto free_data; - } blk_queue_set_zoned(ns->disk, BLK_ZONED_HM); blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q); @@ -128,8 +121,13 @@ static void *nvme_zns_alloc_report_buffer(struct nvme_ns *ns, const size_t min_bufsize = sizeof(struct nvme_zone_report) + sizeof(struct nvme_zone_descriptor); + /* + * Division is used to calculate nr_zones with no special handling + * for power of 2 zone sizes as this function is not invoked in a + * hot path + */ nr_zones = min_t(unsigned int, nr_zones, - get_capacity(ns->disk) >> ilog2(ns->zsze)); + div64_u64(get_capacity(ns->disk), ns->zsze)); bufsize = sizeof(struct nvme_zone_report) + nr_zones * sizeof(struct nvme_zone_descriptor); @@ -182,6 +180,7 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector, int ret, zone_idx = 0; unsigned int nz, i; size_t buflen; + u64 remainder = 0; if (ns->head->ids.csi != NVME_CSI_ZNS) return -EINVAL; @@ -197,7 +196,14 @@ int nvme_ns_report_zones(struct nvme_ns *ns, sector_t sector, c.zmr.zrasf = NVME_ZRASF_ZONE_REPORT_ALL; c.zmr.pr = NVME_REPORT_ZONE_PARTIAL; - sector &= ~(ns->zsze - 1); + /* + * rounddown the sector value to the nearest zone size. roundown macro + * provided in math.h will not work for 32 bit architectures. + * Division is used here with no special handling for power of 2 + * zone sizes as this function is not invoked in a hot path + */ + div64_u64_rem(sector, ns->zsze, &remainder); + sector -= remainder; while (zone_idx < nr_zones && sector < get_capacity(ns->disk)) { memset(report, 0, buflen);