[systemd-devel] libudev: subdirectories in sysfs (what does "available" mean?)

Anne Mulhern amulhern at redhat.com
Tue Nov 24 09:37:46 PST 2015


----- Original Message -----
> From: "Greg KH" <gregkh at linuxfoundation.org>
> To: "Anne Mulhern" <amulhern at redhat.com>
> Cc: "David Herrmann" <dh.herrmann at gmail.com>, "systemd" <systemd-devel at lists.freedesktop.org>
> Sent: Tuesday, November 24, 2015 11:42:21 AM
> Subject: Re: [systemd-devel] libudev: subdirectories in sysfs (what does "available" mean?)
> 
> On Tue, Nov 24, 2015 at 10:37:08AM -0500, Anne Mulhern wrote:
> > 
> > 
> > 
> > 
> > ----- Original Message -----
> > > From: "David Herrmann" <dh.herrmann at gmail.com>
> > > To: "Anne Mulhern" <amulhern at redhat.com>
> > > Cc: "systemd" <systemd-devel at lists.freedesktop.org>
> > > Sent: Tuesday, November 24, 2015 10:15:05 AM
> > > Subject: Re: [systemd-devel] libudev: subdirectories in sysfs (what does
> > > "available" mean?)
> > > 
> > > Hi
> > > 
> > > On Tue, Nov 24, 2015 at 3:54 PM, Anne Mulhern <amulhern at redhat.com>
> > > wrote:
> > > >> From: "David Herrmann" <dh.herrmann at gmail.com>
> > > >> On Tue, Nov 17, 2015 at 11:57 PM, Anne Mulhern <amulhern at redhat.com>
> > > >> wrote:
> > > >> >> From: "David Herrmann" <dh.herrmann at gmail.com>
> > > >> >> On Mon, Nov 16, 2015 at 5:35 PM, Anne Mulhern <amulhern at redhat.com>
> > > >> >> wrote:
> > > >> >> > libudev has some cooperating procedures that return the keys for
> > > >> >> > a
> > > >> >> > bunch
> > > >> >> > of
> > > >> >> > sysfs attributes for a given device.
> > > >> >> >
> > > >> >> > These attributes all correspond to files that are stored in the
> > > >> >> > sysfs
> > > >> >> > device directory.
> > > >> >> >
> > > >> >> > In the same directory there are sometimes subdirectories, that
> > > >> >> > themselves
> > > >> >> > contain files
> > > >> >> > with information about their corresponding attribute. The dm
> > > >> >> > directory
> > > >> >> > is
> > > >> >> > one obvious
> > > >> >> > example.
> > > >> >> >
> > > >> >> > Are their any plans for libudev to add an ability to get the
> > > >> >> > values
> > > >> >> > from
> > > >> >> > these subdirectories
> > > >> >> > as some kind of attributes?
> > > >> >> >
> > > >> >> > If no, why?
> > > >> >>
> > > >> >> sd_device_get_sysattr_value(device, "foo/bar/baz", &value);
> > > >> >>
> > > >> >> This should work fine (or its udev_device_* equivalent).
> > > >> >>
> > > >> >> Btw., I recommend just using readdir(), open(), read(), and
> > > >> >> write().
> > > >> >> sysfs is a filesystem, no reason to wrap all those commands.
> > > >> >
> > > >> > Thanks, I'm asking this more as the pyudev maintainer than as
> > > >> > someone
> > > >> > who actually wants these values.
> > > >> >
> > > >> > The funny thing is, I recently found out that the list obtained by
> > > >> > udev_device_get_sysattr_list_entry () and friends contains so
> > > >> > called "available" keys, but when those get passed to
> > > >> > udev_device_get_sysattr_value () the result might be NULL.
> > > >> > That makes sense in the sense that they might represent files
> > > >> > that are unreadable.
> > > >> >
> > > >> > Now I find out that I can make up keys not in the results of
> > > >> > udev_device_get_sysattr_list_entry () and pass those to
> > > >> > udev_device_get_sysattr_value() and get a non-null result.
> > > >> >
> > > >> > So, what does "available" mean? Do these sysattr_list_entry()
> > > >> > methods give any useful information?
> > > >>
> > > >> "available" probably means attributes which are direct descendants of
> > > >> the device. That is, sysattr_list_entry() only lists such direct
> > > >> descendants, while sysattr_value() allows you to query anything (you
> > > >> probably can even pass "foo/../../bar/baz").
> > > >>
> > > >> Thanks
> > > >> David
> > > >>
> > > >
> > > > I think it's yet more complicated than that. For example,
> > > > 'dm' (for device mapper) is not in the list of available
> > > > attributes, but 'dm/name' is certainly an attribute that
> > > > can be read by sysattr_value().
> > > 
> > > 'dm' is not an attribute, so it will never be listed as available
> > > attribute. Directories are never treated as attributes.
> > > 
> > > Thanks
> > > David
> > > 
> > 
> > But "bdi" is listed as an attribute, and is a directory.
> 
> Can you provide a "full" path here that you are looking at (or the
> output of 'tree' or 'find' on the device), so that I can try to figure
> this out?
> 
> Odds are, dm is doing something "odd"...
> 
> thanks,
> 
> greg k-h
> 

It's a bit bare, let me know if you'ld like me to add a few options.

[mulhern-journal at megadeth pyudev]$ find /sys/devices/virtual/block/dm-32
/sys/devices/virtual/block/dm-32
/sys/devices/virtual/block/dm-32/dm
/sys/devices/virtual/block/dm-32/dm/name
/sys/devices/virtual/block/dm-32/dm/uuid
/sys/devices/virtual/block/dm-32/dm/rq_based_seq_io_merge_deadline
/sys/devices/virtual/block/dm-32/dm/use_blk_mq
/sys/devices/virtual/block/dm-32/dm/suspended
/sys/devices/virtual/block/dm-32/ro
/sys/devices/virtual/block/dm-32/bdi
/sys/devices/virtual/block/dm-32/dev
/sys/devices/virtual/block/dm-32/size
/sys/devices/virtual/block/dm-32/stat
/sys/devices/virtual/block/dm-32/power
/sys/devices/virtual/block/dm-32/power/control
/sys/devices/virtual/block/dm-32/power/runtime_active_time
/sys/devices/virtual/block/dm-32/power/autosuspend_delay_ms
/sys/devices/virtual/block/dm-32/power/runtime_status
/sys/devices/virtual/block/dm-32/power/runtime_suspended_time
/sys/devices/virtual/block/dm-32/range
/sys/devices/virtual/block/dm-32/queue
/sys/devices/virtual/block/dm-32/queue/nomerges
/sys/devices/virtual/block/dm-32/queue/logical_block_size
/sys/devices/virtual/block/dm-32/queue/rq_affinity
/sys/devices/virtual/block/dm-32/queue/discard_zeroes_data
/sys/devices/virtual/block/dm-32/queue/max_segments
/sys/devices/virtual/block/dm-32/queue/unpriv_sgio
/sys/devices/virtual/block/dm-32/queue/max_segment_size
/sys/devices/virtual/block/dm-32/queue/rotational
/sys/devices/virtual/block/dm-32/queue/scheduler
/sys/devices/virtual/block/dm-32/queue/read_ahead_kb
/sys/devices/virtual/block/dm-32/queue/max_hw_sectors_kb
/sys/devices/virtual/block/dm-32/queue/discard_granularity
/sys/devices/virtual/block/dm-32/queue/discard_max_bytes
/sys/devices/virtual/block/dm-32/queue/write_same_max_bytes
/sys/devices/virtual/block/dm-32/queue/max_integrity_segments
/sys/devices/virtual/block/dm-32/queue/max_sectors_kb
/sys/devices/virtual/block/dm-32/queue/physical_block_size
/sys/devices/virtual/block/dm-32/queue/add_random
/sys/devices/virtual/block/dm-32/queue/nr_requests
/sys/devices/virtual/block/dm-32/queue/minimum_io_size
/sys/devices/virtual/block/dm-32/queue/hw_sector_size
/sys/devices/virtual/block/dm-32/queue/optimal_io_size
/sys/devices/virtual/block/dm-32/queue/iostats
/sys/devices/virtual/block/dm-32/trace
/sys/devices/virtual/block/dm-32/trace/pid
/sys/devices/virtual/block/dm-32/trace/end_lba
/sys/devices/virtual/block/dm-32/trace/enable
/sys/devices/virtual/block/dm-32/trace/act_mask
/sys/devices/virtual/block/dm-32/trace/start_lba
/sys/devices/virtual/block/dm-32/discard_alignment
/sys/devices/virtual/block/dm-32/subsystem
/sys/devices/virtual/block/dm-32/ext_range
/sys/devices/virtual/block/dm-32/slaves
/sys/devices/virtual/block/dm-32/slaves/dm-27
/sys/devices/virtual/block/dm-32/slaves/dm-31
/sys/devices/virtual/block/dm-32/uevent
/sys/devices/virtual/block/dm-32/alignment_offset
/sys/devices/virtual/block/dm-32/holders
/sys/devices/virtual/block/dm-32/holders/dm-33
/sys/devices/virtual/block/dm-32/holders/dm-34
/sys/devices/virtual/block/dm-32/inflight
/sys/devices/virtual/block/dm-32/removable
/sys/devices/virtual/block/dm-32/capability

I just noticed that a fact that holds true for the particular device I'm
poking at is that "directory appears in the list of attributes"
is equivalent to "directory is actually a soft link to an actual directory".

Here's a little reproducer:

#include <stdio.h>
#include <libudev.h>

int main() {
    int res;
    struct udev * context;
    struct udev_enumerate * enumerator;
    struct udev_device * device;
    struct udev_list_entry * entry;
    struct udev_list_entry * other_entry;
    struct udev_list_entry * start;
    char const * name;
    char const * value;
    context = udev_new();
    char const * const syspath = "/sys/devices/virtual/block/dm-32";

    device = udev_device_new_from_syspath(context, syspath);

    printf("get_sysattr_list_entry for %s \n", syspath);
    entry = udev_device_get_sysattr_list_entry(device);
    while (entry) {
        name = udev_list_entry_get_name(entry);
        value = udev_list_entry_get_value(entry);
        printf("%s: %s\n", name, value);
        entry = udev_list_entry_get_next(entry);
    }
    printf("\n");

    return 0;
}

and its output:

[mulhern-journal at megadeth pyudev]$ ./a.out
get_sysattr_list_entry for /sys/devices/virtual/block/dm-32 
ro: (null)
bdi: (null)
dev: (null)
size: (null)
stat: (null)
range: (null)
discard_alignment: (null)
subsystem: (null)
ext_range: (null)
uevent: (null)
alignment_offset: (null)
inflight: (null)
removable: (null)
capability: (null)

Thanks,

- mulhern


More information about the systemd-devel mailing list