aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nvme.c
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew.r.wilcox@intel.com>2011-05-06 08:45:47 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2011-11-04 15:53:03 -0400
commit5aff9382ddc8aac6eb0c70ffbb351652d71da69a (patch)
treec8fcc4d065e48b55f8f04d0c7eae858fff2fd1a1 /drivers/block/nvme.c
parentfd63e9ceeeae58cfe877c2d49d41c1bf7532303c (diff)
NVMe: Use an IDA to allocate minor numbers
The current approach of using the namespace ID as the minor number doesn't work when there are multiple adapters in the machine. Rather than statically partitioning the number of namespaces between adapters, dynamically allocate minor numbers to namespaces as they are detected. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Diffstat (limited to 'drivers/block/nvme.c')
-rw-r--r--drivers/block/nvme.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index b285a7e0624d..79012c53ae9c 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -24,6 +24,7 @@
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/genhd.h> 26#include <linux/genhd.h>
27#include <linux/idr.h>
27#include <linux/init.h> 28#include <linux/init.h>
28#include <linux/interrupt.h> 29#include <linux/interrupt.h>
29#include <linux/io.h> 30#include <linux/io.h>
@@ -1240,7 +1241,34 @@ static int nvme_kthread(void *data)
1240 return 0; 1241 return 0;
1241} 1242}
1242 1243
1243static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index, 1244static DEFINE_IDA(nvme_index_ida);
1245
1246static int nvme_get_ns_idx(void)
1247{
1248 int index, error;
1249
1250 do {
1251 if (!ida_pre_get(&nvme_index_ida, GFP_KERNEL))
1252 return -1;
1253
1254 spin_lock(&dev_list_lock);
1255 error = ida_get_new(&nvme_index_ida, &index);
1256 spin_unlock(&dev_list_lock);
1257 } while (error == -EAGAIN);
1258
1259 if (error)
1260 index = -1;
1261 return index;
1262}
1263
1264static void nvme_put_ns_idx(int index)
1265{
1266 spin_lock(&dev_list_lock);
1267 ida_remove(&nvme_index_ida, index);
1268 spin_unlock(&dev_list_lock);
1269}
1270
1271static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
1244 struct nvme_id_ns *id, struct nvme_lba_range_type *rt) 1272 struct nvme_id_ns *id, struct nvme_lba_range_type *rt)
1245{ 1273{
1246 struct nvme_ns *ns; 1274 struct nvme_ns *ns;
@@ -1265,19 +1293,19 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index,
1265 disk = alloc_disk(NVME_MINORS); 1293 disk = alloc_disk(NVME_MINORS);
1266 if (!disk) 1294 if (!disk)
1267 goto out_free_queue; 1295 goto out_free_queue;
1268 ns->ns_id = index; 1296 ns->ns_id = nsid;
1269 ns->disk = disk; 1297 ns->disk = disk;
1270 lbaf = id->flbas & 0xf; 1298 lbaf = id->flbas & 0xf;
1271 ns->lba_shift = id->lbaf[lbaf].ds; 1299 ns->lba_shift = id->lbaf[lbaf].ds;
1272 1300
1273 disk->major = nvme_major; 1301 disk->major = nvme_major;
1274 disk->minors = NVME_MINORS; 1302 disk->minors = NVME_MINORS;
1275 disk->first_minor = NVME_MINORS * index; 1303 disk->first_minor = NVME_MINORS * nvme_get_ns_idx();
1276 disk->fops = &nvme_fops; 1304 disk->fops = &nvme_fops;
1277 disk->private_data = ns; 1305 disk->private_data = ns;
1278 disk->queue = ns->queue; 1306 disk->queue = ns->queue;
1279 disk->driverfs_dev = &dev->pci_dev->dev; 1307 disk->driverfs_dev = &dev->pci_dev->dev;
1280 sprintf(disk->disk_name, "nvme%dn%d", dev->instance, index); 1308 sprintf(disk->disk_name, "nvme%dn%d", dev->instance, nsid);
1281 set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9)); 1309 set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9));
1282 1310
1283 return ns; 1311 return ns;
@@ -1291,7 +1319,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int index,
1291 1319
1292static void nvme_ns_free(struct nvme_ns *ns) 1320static void nvme_ns_free(struct nvme_ns *ns)
1293{ 1321{
1322 int index = ns->disk->first_minor / NVME_MINORS;
1294 put_disk(ns->disk); 1323 put_disk(ns->disk);
1324 nvme_put_ns_idx(index);
1295 blk_cleanup_queue(ns->queue); 1325 blk_cleanup_queue(ns->queue);
1296 kfree(ns); 1326 kfree(ns);
1297} 1327}