diff options
-rw-r--r-- | drivers/block/nvme-core.c | 29 | ||||
-rw-r--r-- | include/linux/nvme.h | 1 |
2 files changed, 21 insertions, 9 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 6f04771f1019..b02ae3d759d7 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -1943,6 +1943,18 @@ 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_ns(struct kref *kref) | ||
1947 | { | ||
1948 | struct nvme_ns *ns = container_of(kref, struct nvme_ns, kref); | ||
1949 | |||
1950 | spin_lock(&dev_list_lock); | ||
1951 | ns->disk->private_data = NULL; | ||
1952 | spin_unlock(&dev_list_lock); | ||
1953 | |||
1954 | put_disk(ns->disk); | ||
1955 | kfree(ns); | ||
1956 | } | ||
1957 | |||
1946 | static int nvme_open(struct block_device *bdev, fmode_t mode) | 1958 | static int nvme_open(struct block_device *bdev, fmode_t mode) |
1947 | { | 1959 | { |
1948 | int ret = 0; | 1960 | int ret = 0; |
@@ -1952,21 +1964,25 @@ static int nvme_open(struct block_device *bdev, fmode_t mode) | |||
1952 | ns = bdev->bd_disk->private_data; | 1964 | ns = bdev->bd_disk->private_data; |
1953 | if (!ns) | 1965 | if (!ns) |
1954 | ret = -ENXIO; | 1966 | ret = -ENXIO; |
1955 | else if (!kref_get_unless_zero(&ns->dev->kref)) | 1967 | else if (!kref_get_unless_zero(&ns->kref)) |
1956 | ret = -ENXIO; | 1968 | ret = -ENXIO; |
1969 | else if (!kref_get_unless_zero(&ns->dev->kref)) { | ||
1970 | kref_put(&ns->kref, nvme_free_ns); | ||
1971 | ret = -ENXIO; | ||
1972 | } | ||
1957 | spin_unlock(&dev_list_lock); | 1973 | spin_unlock(&dev_list_lock); |
1958 | 1974 | ||
1959 | return ret; | 1975 | return ret; |
1960 | } | 1976 | } |
1961 | 1977 | ||
1962 | static void nvme_free_dev(struct kref *kref); | 1978 | static void nvme_free_dev(struct kref *kref); |
1963 | |||
1964 | static void nvme_release(struct gendisk *disk, fmode_t mode) | 1979 | static void nvme_release(struct gendisk *disk, fmode_t mode) |
1965 | { | 1980 | { |
1966 | struct nvme_ns *ns = disk->private_data; | 1981 | struct nvme_ns *ns = disk->private_data; |
1967 | struct nvme_dev *dev = ns->dev; | 1982 | struct nvme_dev *dev = ns->dev; |
1968 | 1983 | ||
1969 | kref_put(&dev->kref, nvme_free_dev); | 1984 | kref_put(&dev->kref, nvme_free_dev); |
1985 | kref_put(&ns->kref, nvme_free_ns); | ||
1970 | } | 1986 | } |
1971 | 1987 | ||
1972 | static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo) | 1988 | static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo) |
@@ -2126,6 +2142,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid) | |||
2126 | if (!disk) | 2142 | if (!disk) |
2127 | goto out_free_queue; | 2143 | goto out_free_queue; |
2128 | 2144 | ||
2145 | kref_init(&ns->kref); | ||
2129 | ns->ns_id = nsid; | 2146 | ns->ns_id = nsid; |
2130 | ns->disk = disk; | 2147 | ns->disk = disk; |
2131 | ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */ | 2148 | ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */ |
@@ -2360,13 +2377,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) | |||
2360 | static void nvme_free_namespace(struct nvme_ns *ns) | 2377 | static void nvme_free_namespace(struct nvme_ns *ns) |
2361 | { | 2378 | { |
2362 | list_del(&ns->list); | 2379 | list_del(&ns->list); |
2363 | 2380 | kref_put(&ns->kref, nvme_free_ns); | |
2364 | spin_lock(&dev_list_lock); | ||
2365 | ns->disk->private_data = NULL; | ||
2366 | spin_unlock(&dev_list_lock); | ||
2367 | |||
2368 | put_disk(ns->disk); | ||
2369 | kfree(ns); | ||
2370 | } | 2381 | } |
2371 | 2382 | ||
2372 | static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) | 2383 | static int ns_cmp(void *priv, struct list_head *a, struct list_head *b) |
diff --git a/include/linux/nvme.h b/include/linux/nvme.h index b5812c395351..992b9c118678 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h | |||
@@ -135,6 +135,7 @@ struct nvme_ns { | |||
135 | struct nvme_dev *dev; | 135 | struct nvme_dev *dev; |
136 | struct request_queue *queue; | 136 | struct request_queue *queue; |
137 | struct gendisk *disk; | 137 | struct gendisk *disk; |
138 | struct kref kref; | ||
138 | 139 | ||
139 | unsigned ns_id; | 140 | unsigned ns_id; |
140 | int lba_shift; | 141 | int lba_shift; |