[PATCH/RFC] allow mapping from block-device-file to sysfs entry.

From: Neil Brown
Date: Tue Aug 07 2007 - 02:07:52 EST



Suppose that in a program I have an open file descriptor for a device,
and I want to find the /sys/block information for this device.
There is currently no direct way to do this. I need to read
/sys/block/*/dev, /sys/block/*/*/dev
and match major/minor numbers with the result from fstat.

I would like a more direct mechanism.

The following patch is a proposal for such a mechanism.

It provides an 'ioctl' which returns then 'name' of the device, as
generated by bdevname. This is the same name that is used to create
entries in sysfs.
For a partition of a device, it returns 'device/partition'.

There is also a patch to 'blockdev' so you can test it.

dell:~# ./blockdev --name /dev/sda1
sda/sda1
dell:~# ./blockdev --name /dev/disk/by-uuid/f1394e26-6e0d-48bf-9fb7-1321e06efba3
sde

My particular need for this is: given a device, find out what md/dm
array it is a member of. Given this ioctl, I can then look up
/sys/block/$DEVNAME/holders
and see what is in there.

Any objection to this becoming a new ioctl? Is 'BLKGETNAME' and
adequate name?

Thanks,
NeilBrown

----------------
Subject: Allow mapping from block-device-file to sysfs entry.

New ioctl returns name provided by bdevname for non-partitions,
or "parentname/bdevname" for partitions.

Signed-off-by: Neil Brown <neilb@xxxxxxx>

### Diffstat output
./block/ioctl.c | 13 +++++++++++++
./include/linux/fs.h | 6 +++---
2 files changed, 16 insertions(+), 3 deletions(-)

diff .prev/block/ioctl.c ./block/ioctl.c
--- .prev/block/ioctl.c 2007-08-07 14:53:07.000000000 +1000
+++ ./block/ioctl.c 2007-08-07 15:38:46.000000000 +1000
@@ -223,8 +223,21 @@ int blkdev_ioctl(struct inode *inode, st
struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
int ret, n;
+ char b[BDEVNAME_SIZE*2];

switch(cmd) {
+ case BLKGETNAME:
+ memset(b, 0, sizeof(b));
+ bdevname(bdev->bd_contains, b);
+ if (bdev->bd_contains != bdev) {
+ char *e = b + strlen(b);
+ *e++ = '/';
+ bdevname(bdev, e);
+ }
+ if (copy_to_user((char __user *)arg, b, BDEVNAME_SIZE*2))
+ return -EFAULT;
+ return 0;
+
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;

diff .prev/include/linux/fs.h ./include/linux/fs.h
--- .prev/include/linux/fs.h 2007-08-07 14:51:08.000000000 +1000
+++ ./include/linux/fs.h 2007-08-07 15:38:49.000000000 +1000
@@ -223,6 +223,9 @@ extern int dir_notify_enable;
#define BLKTRACESTOP _IO(0x12,117)
#define BLKTRACETEARDOWN _IO(0x12,118)

+#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */
+#define BLKGETNAME _IOR(0x12, 119, char [BDEVNAME_SIZE*2])
+
#define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
#define FIBMAP _IO(0x00,1) /* bmap access */
#define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */
@@ -1590,9 +1593,6 @@ extern void unregister_chrdev_region(dev
extern int chrdev_open(struct inode *, struct file *);
extern void chrdev_show(struct seq_file *,off_t);

-/* fs/block_dev.c */
-#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */
-
#ifdef CONFIG_BLOCK
#define BLKDEV_MAJOR_HASH_SIZE 255
extern const char *__bdevname(dev_t, char *buffer);

--------------
--- blockdev.c.orig 2007-08-07 15:06:00.000000000 +1000
+++ blockdev.c 2007-08-07 15:39:04.000000000 +1000
@@ -29,6 +29,7 @@
#define BLKBSZGET _IOR(0x12,112,size_t)
#define BLKBSZSET _IOW(0x12,113,size_t)
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#define BLKGETNAME _IOR(0x12,119,char [64])
#endif

/* Maybe <linux/hdreg.h> could be included */
@@ -56,6 +57,7 @@
#define ARGINTG 4
#define ARGLINTG 5
#define ARGLLINTG 6
+#define ARGSTR64 7
long argval;
char *argname;
char *help;
@@ -101,6 +103,10 @@
{ "--rereadpt", "BLKRRPART", BLKRRPART, ARGNONE, 0, NULL,
N_("reread partition table") },
#endif
+#ifdef BLKGETNAME
+ { "--name", "BLKGETNAME", BLKGETNAME, ARGSTR64, 0, NULL,
+ N_("get device name") },
+#endif
};

#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
@@ -242,6 +248,7 @@
int iarg;
long larg;
long long llarg;
+ char str64arg[64];
int verbose = 0;

for (i = 1; i < d; i++) {
@@ -306,6 +313,9 @@
llarg = bdcms[j].argval;
res = ioctl(fd, bdcms[j].ioc, &llarg);
break;
+ case ARGSTR64:
+ res = ioctl(fd, bdcms[j].ioc, &str64arg);
+ break;
}
if (res == -1) {
perror(bdcms[j].iocname);
@@ -332,6 +342,13 @@
else
printf("%lld\n", llarg);
break;
+ case ARGSTR64:
+ if (verbose)
+ printf("%s: %.64s\n", _(bdcms[j].help),
+ str64arg);
+ else
+ printf("%.64s\n", str64arg);
+ break;
default:
if (verbose)
printf(_("%s succeeded.\n"), _(bdcms[j].help));
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/