Merge tag 'block-5.10-2020-10-12' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / nvme / host / core.c
index 893e296..d2397cf 100644 (file)
@@ -94,21 +94,34 @@ static void nvme_put_subsystem(struct nvme_subsystem *subsys);
 static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,
                                           unsigned nsid);
 
+static void nvme_update_bdev_size(struct gendisk *disk)
+{
+       struct block_device *bdev = bdget_disk(disk, 0);
+
+       if (bdev) {
+               bd_set_nr_sectors(bdev, get_capacity(disk));
+               bdput(bdev);
+       }
+}
+
+/*
+ * Prepare a queue for teardown.
+ *
+ * This must forcibly unquiesce queues to avoid blocking dispatch, and only set
+ * the capacity to 0 after that to avoid blocking dispatchers that may be
+ * holding bd_butex.  This will end buffered writers dirtying pages that can't
+ * be synced.
+ */
 static void nvme_set_queue_dying(struct nvme_ns *ns)
 {
-       /*
-        * Revalidating a dead namespace sets capacity to 0. This will end
-        * buffered writers dirtying pages that can't be synced.
-        */
        if (test_and_set_bit(NVME_NS_DEAD, &ns->flags))
                return;
+
        blk_set_queue_dying(ns->queue);
-       /* Forcibly unquiesce queues to avoid blocking dispatch */
        blk_mq_unquiesce_queue(ns->queue);
-       /*
-        * Revalidate after unblocking dispatchers that may be holding bd_butex
-        */
-       revalidate_disk(ns->disk);
+
+       set_capacity(ns->disk, 0);
+       nvme_update_bdev_size(ns->disk);
 }
 
 static void nvme_queue_scan(struct nvme_ctrl *ctrl)
@@ -2134,7 +2147,8 @@ static int __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
                nvme_update_disk_info(ns->head->disk, ns, id);
                blk_stack_limits(&ns->head->disk->queue->limits,
                                 &ns->queue->limits, 0);
-               nvme_mpath_update_disk_size(ns->head->disk);
+               blk_queue_update_readahead(ns->head->disk->queue);
+               nvme_update_bdev_size(ns->head->disk);
        }
 #endif
        return 0;
@@ -2339,7 +2353,6 @@ static const struct block_device_operations nvme_fops = {
        .open           = nvme_open,
        .release        = nvme_release,
        .getgeo         = nvme_getgeo,
-       .revalidate_disk= nvme_revalidate_disk,
        .report_zones   = nvme_report_zones,
        .pr_ops         = &nvme_pr_ops,
 };
@@ -3929,8 +3942,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
                goto out_free_ns;
 
        if (ctrl->opts && ctrl->opts->data_digest)
-               ns->queue->backing_dev_info->capabilities
-                       |= BDI_CAP_STABLE_WRITES;
+               blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, ns->queue);
 
        blk_queue_flag_set(QUEUE_FLAG_NONROT, ns->queue);
        if (ctrl->ops->flags & NVME_F_PCI_P2PDMA)
@@ -4056,14 +4068,19 @@ static void nvme_ns_remove_by_nsid(struct nvme_ctrl *ctrl, u32 nsid)
 static void nvme_validate_ns(struct nvme_ctrl *ctrl, unsigned nsid)
 {
        struct nvme_ns *ns;
+       int ret;
 
        ns = nvme_find_get_ns(ctrl, nsid);
-       if (ns) {
-               if (revalidate_disk(ns->disk))
-                       nvme_ns_remove(ns);
-               nvme_put_ns(ns);
-       } else
+       if (!ns) {
                nvme_alloc_ns(ctrl, nsid);
+               return;
+       }
+
+       ret = nvme_revalidate_disk(ns->disk);
+       revalidate_disk_size(ns->disk, ret == 0);
+       if (ret)
+               nvme_ns_remove(ns);
+       nvme_put_ns(ns);
 }
 
 static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,