All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Stephen M. Cameron" <scameron@beardog.cce.hp.com>
To: linux-kernel@vger.kernel.org
Cc: axboe@kernel.dk, Chayan.Biswas@sandisk.com,
	lsorense@csclub.uwaterloo.ca, Sumant.Patro@sandisk.com,
	stephenmcameron@gmail.com
Subject: [RFC PATCH] block: Add new generic block device naming interface
Date: Mon, 11 Mar 2013 14:00:30 -0500	[thread overview]
Message-ID: <20130311190030.5753.92288.stgit@beardog.cce.hp.com> (raw)

From: Stephen M. Cameron <scameron@beardog.cce.hp.com>

This is really the merest sketch of an idea, I'm not asking that
this patch be taken in its current form, just asking for feedback
on the idea, and if someone else better acquainted with the block
layer wants to take this idea and implement it in a better, proper
way, please, have at it.

Upon requesting advice from the grub developers about best practices
for naming device nodes for new block device drivers[*] to cause the
least amount of pain in grub, I was understandably greeted with the
advice to make it a SCSI driver or have a damn good reason why not.

See this thread:
https://lists.gnu.org/archive/html/grub-devel/2013-03/msg00049.html

Well, I did have what I think is a good reason, but this got me to
thinking that adding a new block device driver really shouldn't be causing
the grub guys any extra work, yet, it seems that it does.  This is because
there is no standardized naming system for block drivers as there is for
SCSI drivers -- the block device drivers kind of choose their own device
names, as does the sd driver -- but all the scsi hba drivers share the sd
driver -- so all the scsi block devices share the same device namespace,
and grub only has to know about this shared namespace.

So I cooked up a similar system for the block drivers, copied from sd
pretty much.  The idea is that instead of each new block driver manually
setting gendisk's disk_name field (though legacy drivers could still do
that) they call blk_assign_new_disk_name(struct gendisk *disk), and the
block layer hands out a name, so that all the new block drivers share
a namespace, and grub only has to learn about this one new naming
scheme, and any new block drivers can leverage that for booting support
automatically.

The scheme implemented in this patch is to name the devices /dev/bda,
/dev/bdb, /dev/bdc, etc.  in the exact same manner as the sd driver names
its devices /dev/sda, etc. (I literally copied the code from the sd
driver and tweaked it ever so slightly.)  This of course may not be the
best solution (as that ancient scheme came from what, SunOS?) but it
was the quickest to get up and running for a proof of concept.

It does occur to me that this seems like such an obvious idea that perhaps
there is a good reason why it's not done already, but if so, I don't know
what that reason is.

[*] the new driver I have in mind which triggered this question is here:
    https://github.com/HPSmartStorage/scsi-over-pcie

-- steve
---
 block/genhd.c         |   86 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/genhd.h |    1 +
 2 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index 3c001fb..9d735f6 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -569,6 +569,92 @@ exit:
 }
 
 /**
+ *	bd_format_disk_name - format disk name
+ *	@prefix: name prefix - ie. "bd" for SCSI disks
+ *	@index: index of the disk to format name for
+ *	@buf: output buffer
+ *	@buflen: length of the output buffer
+ *
+ *	block disk names starts at bda.  The 26th device is bdz and the
+ *	27th is bdaa.  The last one for two lettered suffix is bdzz
+ *	which is followed by bdaaa.
+ *
+ *	This is basically 26 base counting with one extra 'nil' entry
+ *	at the beginning from the second digit on and can be
+ *	determined using similar method as 26 base conversion with the
+ *	index shifted -1 after each digit is computed.
+ *
+ *	CONTEXT:
+ *	Don't care.
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
+ *
+ *	bd_format_disk_name is obviously cribbed from sd_format_disk_name
+ *
+ */
+static int bd_format_disk_name(char *prefix, int index, char *buf, int buflen)
+{
+	const int base = 'z' - 'a' + 1;
+	char *begin = buf + strlen(prefix);
+	char *end = buf + buflen;
+	char *p;
+	int unit;
+
+	p = end - 1;
+	*p = '\0';
+	unit = base;
+	do {
+		if (p == begin)
+			return -EINVAL;
+		*--p = 'a' + (index % unit);
+		index = (index / unit) - 1;
+	} while (index >= 0);
+
+	memmove(begin, p, end - p);
+	memcpy(buf, prefix, strlen(prefix));
+
+	return 0;
+}
+
+DEFINE_SPINLOCK(bd_index_lock);
+DEFINE_IDA(bd_index_ida);
+char *blk_assign_new_disk_name(struct gendisk *disk)
+{
+	int index, error;
+
+	do {
+		if (!ida_pre_get(&bd_index_ida, GFP_KERNEL))
+			goto out;
+
+		spin_lock(&bd_index_lock);
+		error = ida_get_new(&bd_index_ida, &index);
+		spin_unlock(&bd_index_lock);
+	} while (error == -EAGAIN);
+
+	if (error) {
+		pr_warn("blk_assign_new_disk_name: memory exhausted\n");
+		goto out;
+	}
+
+	error = bd_format_disk_name("bd", index, disk->disk_name,
+					DISK_NAME_LEN);
+	if (error) {
+		pr_warn("block disk (bd) name length exceeded.\n");
+		goto out_free_index;
+	}
+	return disk->disk_name;
+
+out_free_index:
+	spin_lock(&bd_index_lock);
+	ida_remove(&bd_index_ida, index);
+	spin_unlock(&bd_index_lock);
+out:
+	return NULL;
+}
+EXPORT_SYMBOL(blk_assign_new_disk_name);
+
+/**
  * add_disk - add partitioning information to kernel list
  * @disk: per-device partitioning information
  *
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 9f3c275..cef2169 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -602,6 +602,7 @@ extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt);
 extern void blk_free_devt(dev_t devt);
 extern dev_t blk_lookup_devt(const char *name, int partno);
 extern char *disk_name (struct gendisk *hd, int partno, char *buf);
+extern char *blk_assign_new_disk_name(struct gendisk *hd);
 
 extern int disk_expand_part_tbl(struct gendisk *disk, int target);
 extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);


             reply	other threads:[~2013-03-11 19:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-11 19:00 Stephen M. Cameron [this message]
  -- strict thread matches above, loose matches on Subject: below --
2013-03-28 16:18 [RFC PATCH] block: Add new generic block device naming interface Stephen M. Cameron
2013-04-25 20:22 Stephen M. Cameron
2013-04-25 20:40 ` Tejun Heo
2013-04-25 21:07   ` scameron
2013-04-25 21:14     ` Tejun Heo
2013-04-25 22:12       ` scameron
2013-04-26 19:03         ` Tejun Heo
2013-04-29 14:56           ` Hannes Reinecke
2013-04-29 15:17             ` Vivek Goyal
2013-04-29 16:06             ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130311190030.5753.92288.stgit@beardog.cce.hp.com \
    --to=scameron@beardog.cce.hp.com \
    --cc=Chayan.Biswas@sandisk.com \
    --cc=Sumant.Patro@sandisk.com \
    --cc=axboe@kernel.dk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lsorense@csclub.uwaterloo.ca \
    --cc=stephenmcameron@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.