diff options
author | Keith Busch <keith.busch@intel.com> | 2015-10-02 12:37:28 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-10-09 12:40:36 -0400 |
commit | 5105aa555c1c681ae281ea0d6108efd0a5d8a5e8 (patch) | |
tree | 632da12e8be617c320b4b2857b31e38213a07dbf | |
parent | 188c3568f814fea965947ed24739987ba9c5a87e (diff) |
NVMe: Namespace removal simplifications
This liberates namespace removal from the device, allowing gendisk
references to be closed independent of the nvme controller reference
count.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/nvme-core.c | 42 |
1 files changed, 10 insertions, 32 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index b02ae3d759d7..904b54fcbbcd 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -1943,6 +1943,7 @@ static int nvme_compat_ioctl(struct block_device *bdev, fmode_t mode, | |||
1943 | #define nvme_compat_ioctl NULL | 1943 | #define nvme_compat_ioctl NULL |
1944 | #endif | 1944 | #endif |
1945 | 1945 | ||
1946 | static void nvme_free_dev(struct kref *kref); | ||
1946 | static void nvme_free_ns(struct kref *kref) | 1947 | static void nvme_free_ns(struct kref *kref) |
1947 | { | 1948 | { |
1948 | struct nvme_ns *ns = container_of(kref, struct nvme_ns, kref); | 1949 | struct nvme_ns *ns = container_of(kref, struct nvme_ns, kref); |
@@ -1951,6 +1952,7 @@ static void nvme_free_ns(struct kref *kref) | |||
1951 | ns->disk->private_data = NULL; | 1952 | ns->disk->private_data = NULL; |
1952 | spin_unlock(&dev_list_lock); | 1953 | spin_unlock(&dev_list_lock); |
1953 | 1954 | ||
1955 | kref_put(&ns->dev->kref, nvme_free_dev); | ||
1954 | put_disk(ns->disk); | 1956 | put_disk(ns->disk); |
1955 | kfree(ns); | 1957 | kfree(ns); |
1956 | } | 1958 | } |
@@ -1966,22 +1968,14 @@ static int nvme_open(struct block_device *bdev, fmode_t mode) | |||
1966 | ret = -ENXIO; | 1968 | ret = -ENXIO; |
1967 | else if (!kref_get_unless_zero(&ns->kref)) | 1969 | else if (!kref_get_unless_zero(&ns->kref)) |
1968 | ret = -ENXIO; | 1970 | ret = -ENXIO; |
1969 | else if (!kref_get_unless_zero(&ns->dev->kref)) { | ||
1970 | kref_put(&ns->kref, nvme_free_ns); | ||
1971 | ret = -ENXIO; | ||
1972 | } | ||
1973 | spin_unlock(&dev_list_lock); | 1971 | spin_unlock(&dev_list_lock); |
1974 | 1972 | ||
1975 | return ret; | 1973 | return ret; |
1976 | } | 1974 | } |
1977 | 1975 | ||
1978 | static void nvme_free_dev(struct kref *kref); | ||
1979 | static void nvme_release(struct gendisk *disk, fmode_t mode) | 1976 | static void nvme_release(struct gendisk *disk, fmode_t mode) |
1980 | { | 1977 | { |
1981 | struct nvme_ns *ns = disk->private_data; | 1978 | struct nvme_ns *ns = disk->private_data; |
1982 | struct nvme_dev *dev = ns->dev; | ||
1983 | |||
1984 | kref_put(&dev->kref, nvme_free_dev); | ||
1985 | kref_put(&ns->kref, nvme_free_ns); | 1979 | kref_put(&ns->kref, nvme_free_ns); |
1986 | } | 1980 | } |
1987 | 1981 | ||
@@ -2179,6 +2173,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) | |||
2179 | if (nvme_revalidate_disk(ns->disk)) | 2173 | if (nvme_revalidate_disk(ns->disk)) |
2180 | goto out_free_disk; | 2174 | goto out_free_disk; |
2181 | 2175 | ||
2176 | kref_get(&dev->kref); | ||
2182 | add_disk(ns->disk); | 2177 | add_disk(ns->disk); |
2183 | if (ns->ms) { | 2178 | if (ns->ms) { |
2184 | struct block_device *bd = bdget_disk(ns->disk, 0); | 2179 | struct block_device *bd = bdget_disk(ns->disk, 0); |
@@ -2374,12 +2369,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) | |||
2374 | return result; | 2369 | return result; |
2375 | } | 2370 | } |
2376 | 2371 | ||
2377 | static void nvme_free_namespace(struct nvme_ns *ns) | ||
2378 | { | ||
2379 | list_del(&ns->list); | ||
2380 | kref_put(&ns->kref, nvme_free_ns); | ||
2381 | } | ||
2382 | |||
2383 | static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) | 2372 | static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) |
2384 | { | 2373 | { |
2385 | struct nvme_ns *nsa = container_of(a, struct nvme_ns, list); | 2374 | struct nvme_ns *nsa = container_of(a, struct nvme_ns, list); |
@@ -2421,7 +2410,9 @@ static void nvme_ns_remove(struct nvme_ns *ns) | |||
2421 | if (kill || !blk_queue_dying(ns->queue)) { | 2410 | if (kill || !blk_queue_dying(ns->queue)) { |
2422 | blk_mq_abort_requeue_list(ns->queue); | 2411 | blk_mq_abort_requeue_list(ns->queue); |
2423 | blk_cleanup_queue(ns->queue); | 2412 | blk_cleanup_queue(ns->queue); |
2424 | } | 2413 | } |
2414 | list_del_init(&ns->list); | ||
2415 | kref_put(&ns->kref, nvme_free_ns); | ||
2425 | } | 2416 | } |
2426 | 2417 | ||
2427 | static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn) | 2418 | static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn) |
@@ -2432,18 +2423,14 @@ static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn) | |||
2432 | for (i = 1; i <= nn; i++) { | 2423 | for (i = 1; i <= nn; i++) { |
2433 | ns = nvme_find_ns(dev, i); | 2424 | ns = nvme_find_ns(dev, i); |
2434 | if (ns) { | 2425 | if (ns) { |
2435 | if (revalidate_disk(ns->disk)) { | 2426 | if (revalidate_disk(ns->disk)) |
2436 | nvme_ns_remove(ns); | 2427 | nvme_ns_remove(ns); |
2437 | nvme_free_namespace(ns); | ||
2438 | } | ||
2439 | } else | 2428 | } else |
2440 | nvme_alloc_ns(dev, i); | 2429 | nvme_alloc_ns(dev, i); |
2441 | } | 2430 | } |
2442 | list_for_each_entry_safe(ns, next, &dev->namespaces, list) { | 2431 | list_for_each_entry_safe(ns, next, &dev->namespaces, list) { |
2443 | if (ns->ns_id > nn) { | 2432 | if (ns->ns_id > nn) |
2444 | nvme_ns_remove(ns); | 2433 | nvme_ns_remove(ns); |
2445 | nvme_free_namespace(ns); | ||
2446 | } | ||
2447 | } | 2434 | } |
2448 | list_sort(NULL, &dev->namespaces, ns_cmp); | 2435 | list_sort(NULL, &dev->namespaces, ns_cmp); |
2449 | } | 2436 | } |
@@ -2833,9 +2820,9 @@ static void nvme_dev_shutdown(struct nvme_dev *dev) | |||
2833 | 2820 | ||
2834 | static void nvme_dev_remove(struct nvme_dev *dev) | 2821 | static void nvme_dev_remove(struct nvme_dev *dev) |
2835 | { | 2822 | { |
2836 | struct nvme_ns *ns; | 2823 | struct nvme_ns *ns, *next; |
2837 | 2824 | ||
2838 | list_for_each_entry(ns, &dev->namespaces, list) | 2825 | list_for_each_entry_safe(ns, next, &dev->namespaces, list) |
2839 | nvme_ns_remove(ns); | 2826 | nvme_ns_remove(ns); |
2840 | } | 2827 | } |
2841 | 2828 | ||
@@ -2891,21 +2878,12 @@ static void nvme_release_instance(struct nvme_dev *dev) | |||
2891 | spin_unlock(&dev_list_lock); | 2878 | spin_unlock(&dev_list_lock); |
2892 | } | 2879 | } |
2893 | 2880 | ||
2894 | static void nvme_free_namespaces(struct nvme_dev *dev) | ||
2895 | { | ||
2896 | struct nvme_ns *ns, *next; | ||
2897 | |||
2898 | list_for_each_entry_safe(ns, next, &dev->namespaces, list) | ||
2899 | nvme_free_namespace(ns); | ||
2900 | } | ||
2901 | |||
2902 | static void nvme_free_dev(struct kref *kref) | 2881 | static void nvme_free_dev(struct kref *kref) |
2903 | { | 2882 | { |
2904 | struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); | 2883 | struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); |
2905 | 2884 | ||
2906 | put_device(dev->dev); | 2885 | put_device(dev->dev); |
2907 | put_device(dev->device); | 2886 | put_device(dev->device); |
2908 | nvme_free_namespaces(dev); | ||
2909 | nvme_release_instance(dev); | 2887 | nvme_release_instance(dev); |
2910 | if (dev->tagset.tags) | 2888 | if (dev->tagset.tags) |
2911 | blk_mq_free_tag_set(&dev->tagset); | 2889 | blk_mq_free_tag_set(&dev->tagset); |