* [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
@ 2007-08-07 6:07 Neil Brown
2007-08-07 6:37 ` Arjan van de Ven
0 siblings, 1 reply; 6+ messages in thread
From: Neil Brown @ 2007-08-07 6:07 UTC (permalink / raw)
To: linux-kernel
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@suse.de>
### 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));
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
2007-08-07 6:07 [PATCH/RFC] allow mapping from block-device-file to sysfs entry Neil Brown
@ 2007-08-07 6:37 ` Arjan van de Ven
2007-08-07 7:13 ` Neil Brown
0 siblings, 1 reply; 6+ messages in thread
From: Arjan van de Ven @ 2007-08-07 6:37 UTC (permalink / raw)
To: Neil Brown; +Cc: linux-kernel
On Tue, 2007-08-07 at 16:07 +1000, Neil Brown wrote:
> 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'.
how about returning the entire path relative to the start of sysfs? That
way, if things move or something you're tolerant against that....
(I'd not be against making this a generic IOCTL for every device, a
SYSFSLOCATION kind of ioctl... it's by no means block specific...)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
2007-08-07 6:37 ` Arjan van de Ven
@ 2007-08-07 7:13 ` Neil Brown
2007-08-07 7:41 ` Kay Sievers
0 siblings, 1 reply; 6+ messages in thread
From: Neil Brown @ 2007-08-07 7:13 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: linux-kernel
On Monday August 6, arjan@infradead.org wrote:
> On Tue, 2007-08-07 at 16:07 +1000, Neil Brown wrote:
> > 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'.
>
>
> how about returning the entire path relative to the start of sysfs? That
> way, if things move or something you're tolerant against that....
That makes a lot of sense.
So it would return "block/sda/sda1" now, but one day that might change
to "class/block/sda/sda1" or some-such.
>
> (I'd not be against making this a generic IOCTL for every device, a
> SYSFSLOCATION kind of ioctl... it's by no means block specific...)
>
That too seems very sensible. Only it's harder to choose a 'generic'
ioctl request number than to choose a block-specific one :-)
We would also need a somewhat longer buffer. The longest
/sys/**/dev
path on my test machine is
/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1/usb_endpoint/usbdev2.2_ep82/dev
So at least 80 chars. Probably 256 would do....
#define SYSFSLOCATION _IOR(0, 0xff, char[256])
??
Thanks,
NeilBrown
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
2007-08-07 7:13 ` Neil Brown
@ 2007-08-07 7:41 ` Kay Sievers
2007-08-09 6:50 ` Neil Brown
0 siblings, 1 reply; 6+ messages in thread
From: Kay Sievers @ 2007-08-07 7:41 UTC (permalink / raw)
To: Neil Brown; +Cc: Arjan van de Ven, linux-kernel
On 8/7/07, Neil Brown <neilb@suse.de> wrote:
> On Monday August 6, arjan@infradead.org wrote:
> > On Tue, 2007-08-07 at 16:07 +1000, Neil Brown wrote:
> > > 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.
$ udevinfo --query=path --name=sda
/block/sda
> > > 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'.
> >
> >
> > how about returning the entire path relative to the start of sysfs? That
> > way, if things move or something you're tolerant against that....
>
> That makes a lot of sense.
> So it would return "block/sda/sda1" now,
Every devpath always starts with a '/' in the kernel, its kind of
weird, but we should not introduce a new variation of it. :)
> but one day that might change
> to "class/block/sda/sda1" or some-such.
It will start with /devices/..., like:
/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sda/sda1
> > (I'd not be against making this a generic IOCTL for every device, a
> > SYSFSLOCATION kind of ioctl... it's by no means block specific...)
> >
>
> That too seems very sensible. Only it's harder to choose a 'generic'
> ioctl request number than to choose a block-specific one :-)
>
> We would also need a somewhat longer buffer. The longest
> /sys/**/dev
> path on my test machine is
> /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.1/usb_endpoint/usbdev2.2_ep82/dev
>
> So at least 80 chars. Probably 256 would do....
They can be definitely longer than than 256, probably not longer than
512 today, but you can't be sure about that.
Thanks,
Kay
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
2007-08-07 7:41 ` Kay Sievers
@ 2007-08-09 6:50 ` Neil Brown
2007-08-09 9:54 ` Kay Sievers
0 siblings, 1 reply; 6+ messages in thread
From: Neil Brown @ 2007-08-09 6:50 UTC (permalink / raw)
To: Kay Sievers; +Cc: Arjan van de Ven, linux-kernel
On Tuesday August 7, kay.sievers@vrfy.org wrote:
> On 8/7/07, Neil Brown <neilb@suse.de> wrote:
> > On Monday August 6, arjan@infradead.org wrote:
> > > On Tue, 2007-08-07 at 16:07 +1000, Neil Brown wrote:
> > > > 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.
>
> $ udevinfo --query=path --name=sda
> /block/sda
If I interpret the result of 'strace' properly, this looks at
/dev/.udev/names/sda
and prints the result after decoding '\x2f' as '/'.
I want to go from an open file descriptor, or at least an entry in
/dev.
And I don't think I want to depend on udev if I can avoid it....
> >
> > That makes a lot of sense.
> > So it would return "block/sda/sda1" now,
>
> Every devpath always starts with a '/' in the kernel, its kind of
> weird, but we should not introduce a new variation of it. :)
Fair comment. So
/block/sda/sda1
now, and whatever later.
>
> They can be definitely longer than than 256, probably not longer than
> 512 today, but you can't be sure about that.
I guess we go for PATH_MAX then?
Any idea how to get a sysfs path in a generic way?
I tried:
struct inode *inode = filp->f_path.dentry->d_inode;
struct kobject *ko = NULL;
char *path = NULL;
if (S_ISBLK(inode->i_mode) &&
inode->i_bdev &&
inode->i_bdev->bd_disk)
ko = &inode->i_bdev->bd_disk->kobj;
if (S_ISCHR(inode->i_mode) &&
inode->i_cdev)
ko = &inode->i_cdev->kobj;
if (ko)
path = kobject_get_path(ko, GFP_KERNEL);
For /dev/sda, it returns /block/sda which is good.
For /dev/sda1 it still returns /block/sda which is not good.
For /dev/null it returns /mem which doesn't even exist in sysfs
For /dev/tty it doesn't return anything.
I'm tempted to just implement it for block devices and let someone
else worry about char devices.
Thanks,
NeilBrown
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH/RFC] allow mapping from block-device-file to sysfs entry.
2007-08-09 6:50 ` Neil Brown
@ 2007-08-09 9:54 ` Kay Sievers
0 siblings, 0 replies; 6+ messages in thread
From: Kay Sievers @ 2007-08-09 9:54 UTC (permalink / raw)
To: Neil Brown; +Cc: Arjan van de Ven, linux-kernel
On Thu, 2007-08-09 at 16:50 +1000, Neil Brown wrote:
> On Tuesday August 7, kay.sievers@vrfy.org wrote:
> > On 8/7/07, Neil Brown <neilb@suse.de> wrote:
> > > On Monday August 6, arjan@infradead.org wrote:
> > > > On Tue, 2007-08-07 at 16:07 +1000, Neil Brown wrote:
> > > > > 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.
> >
> > $ udevinfo --query=path --name=sda
> > /block/sda
>
> If I interpret the result of 'strace' properly, this looks at
> /dev/.udev/names/sda
> and prints the result after decoding '\x2f' as '/'.
> I want to go from an open file descriptor, or at least an entry in
> /dev.
Right, it maintains two indices, one from the devpath to the /dev-name,
and one from the /dev-name to the devpath.
> And I don't think I want to depend on udev if I can avoid it....
>
> > >
> > > That makes a lot of sense.
> > > So it would return "block/sda/sda1" now,
> >
> > Every devpath always starts with a '/' in the kernel, its kind of
> > weird, but we should not introduce a new variation of it. :)
>
> Fair comment. So
> /block/sda/sda1
> now, and whatever later.
Right.
> > They can be definitely longer than than 256, probably not longer than
> > 512 today, but you can't be sure about that.
>
> I guess we go for PATH_MAX then?
Maybe, yes.
> Any idea how to get a sysfs path in a generic way?
No, no idea.
> I tried:
> struct inode *inode = filp->f_path.dentry->d_inode;
> struct kobject *ko = NULL;
> char *path = NULL;
> if (S_ISBLK(inode->i_mode) &&
> inode->i_bdev &&
> inode->i_bdev->bd_disk)
> ko = &inode->i_bdev->bd_disk->kobj;
> if (S_ISCHR(inode->i_mode) &&
> inode->i_cdev)
> ko = &inode->i_cdev->kobj;
> if (ko)
> path = kobject_get_path(ko, GFP_KERNEL);
>
>
> For /dev/sda, it returns /block/sda which is good.
> For /dev/sda1 it still returns /block/sda which is not good.
You have to explicitely handle partitions by looking at the minor
number. They are not registered in the kobj_map.
> For /dev/null it returns /mem which doesn't even exist in sysfs
In the kobj_map is only the minor _range_ of the subsystem, which is
able to resolve the minor to the object.
> For /dev/tty it doesn't return anything.
Same here.
> I'm tempted to just implement it for block devices and let someone
> else worry about char devices.
We probably want to extend kobj_map with something where _every_ device
is registered, not only the "handler" for a region of devices.
Today, when you open a device, the "driver" gets called and it looks up
the device by traversing over a list of known devices, or some using idr
internally for this. In /proc/devices are the registered "handlers", you
can't get more than this. The "mem" entry there, is what you are looking
up, but which device (devpath) it is, is hidden inside the mem class.
Seems block devices are special here, and register every genhd directly
and make them accessible the way you try to do it. Not sure if that will
work for all block devices in all cases though.
Would be nice if generic kernel code (the kobj_map) could just return a
pointer back to the kobject for _every_ major/minor combination, instead
of only the pointer into the subsystem (which registered a range). Today
every subsystem implements its own way of doing the lookup for the
object the minor number belongs to. That would be the right place to
solve this problem. :)
Kay
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-08-09 9:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-07 6:07 [PATCH/RFC] allow mapping from block-device-file to sysfs entry Neil Brown
2007-08-07 6:37 ` Arjan van de Ven
2007-08-07 7:13 ` Neil Brown
2007-08-07 7:41 ` Kay Sievers
2007-08-09 6:50 ` Neil Brown
2007-08-09 9:54 ` Kay Sievers
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.