* Re: [PATCH] udevadm-info: Don't access sysfs 'resource<N>' files
From: Myron Stowe @ 2013-03-19 16:57 UTC (permalink / raw)
To: Alex Williamson
Cc: Bjørn Mork, Greg KH, Kay Sievers, Myron Stowe, linux-hotplug,
linux-pci, yuxiangl, yxlraid, linux-kernel
In-Reply-To: <1363633176.24132.401.camel@bling.home>
On Mon, 2013-03-18 at 12:59 -0600, Alex Williamson wrote:
> On Mon, 2013-03-18 at 19:25 +0100, Bjørn Mork wrote:
> > Alex Williamson <alex.williamson@redhat.com> wrote:
> >
> > >On Mon, 2013-03-18 at 18:20 +0100, Bjørn Mork wrote:
> > >> Alex Williamson <alex.williamson@redhat.com> writes:
> > >>
> > >> > At least for KVM the kernel fix is the addition of the vfio driver
> > >which
> > >> > gives us a non-sysfs way to do this. If this problem was found a
> > >few
> > >> > years later and we were ready to make the switch I'd support just
> > >> > removing these resource files. In the meantime we have userspace
> > >that
> > >> > depends on this interface, so I'm open to suggestions how to fix
> > >it.
> > >>
> > >> I am puzzled by a couple of things in this discussion:
> > >>
> > >> 1) do you seriously mean that a userspace application (any, not just
> > >> udevadm or qemu or whatever) should be able to read and write
> > >these
> > >> registers while the device is owned by a driver? How is that ever
> > >> going to work?
> > >
> > >The expectation is that the user doesn't mess with the device through
> > >pci-sysfs while it's running. This is really no different than config
> > >space or MMIO space in that respect.
> >
> > But it is. That's the problem. As a user I expect to be able to run
> > e.g "grep . /sys/devices/whatever/*" with no ill effects. This holds
> > for config space or MMIO space. It does not for any reset-on-read
> > register.
>
> As a non-admin user you can
>
> > > You can use setpci to break your
> > >PCI card while it's used by the driver today. The difference is that
> > >MMIO spaces side-step the issue by only allowing mmap and config space
> > >is known not to have read side-effects.
> >
> > Yes. And that is why there is no problem exporting those. This
> > difference is fundamental.
>
> So how do we side-step the problem with I/O port registers? If we
> remove them then KVM needs to run with iopl which is a pretty serious
> security hole should QEMU be exploited. We could activate the resource
> files only when the device is bound to pci-assign, but that only limits
> the scope and might break UIO drivers. We could modify the file to have
> an enable sequence, but we can't do this without breaking current
> userspace. As I mentioned, the VFIO driver is intended to replace KVM's
> use of these files, but we're not ready to rip it out, perhaps not even
> ready to declare it deprecated.
>
> > >> 2) is it really so that a device can be so fundamentally screwed up
> > >by
> > >> reading some registers, that a later driver probe cannot properly
> > >> reinitialize it?
> > >
> > >Never underestimate how broken hardware can be,
> >
> > True :)
> >
> > > though in this case
> > >reading a device register seems to be causing a system hang/reset.
> >
> > I understand that it does so if the ahci driver is bound to the device
> > while reading the registers, but does it also hang the system with no
> > bound driver? How does it do that? By killing the bus?
>
> I don't know, Myron?
Yes - the system hangs when BAR1's (and likely BAR3's) I/O port space is
read.
Here are the details that I've been able to put together from the two
linux-pci threads and various online sources -
From Robert Hancock - "... BAR5 is the MMIO region used by the AHCI
driver. BARs 0-4 are the legacy SFF-compatible ATA ports. Nothing
should be messing with those IO ports while AHCI is enabled. ..." This
likely explains why the system boots and runs fine as long as the
'udevadm ...' command is *not* ran (i.e. the driver never accesses the
I/O port BARs).
Using a SATA controller I have access to as an example for the details
(Note: I do not have access to a system with the Marvell 9125 device):
00:1f.2 SATA controller: Intel Corporation 5 Series/3400 Series Chipset 6 port SATA AHCI Controller (rev 06) (prog-if 01 [AHCI 1.0])
Subsystem: Lenovo Device 2168
Region 0: I/O ports at 1860 [size=8]
Region 1: I/O ports at 1814 [size=4]
Region 2: I/O ports at 1818 [size=8]
Region 3: I/O ports at 1810 [size=4]
Region 4: I/O ports at 1840 [size2]
Region 5: Memory at f2827000 (32-bit, non-prefetchable) [size=2K]
I/O port registers [1][2]:
Primary IDE controller [0x1860-0x1867; 0x1814-0x1817]
BAR0 Base address for the command block registers for ATA Channel X
0x1860 (Read/Write): Data Register
0x1861 (Read): Error Register
0x1861 (Write): Features Register
0x1862 (Read/Write): Sector Count Register
0x1863 (Read/Write): LBA Low Register
0x1864 (Read/Write): LBA Mid Register
0x1865 (Read/Write): LBA High Register
0x1866 (Read/Write): Drive/Head Register
0x1867 (Read): Status Register
0x1867 (Write): Command Register
BAR1* Base address for the control register for ATA Channel X
0x1814 Reserved
0x1815 Reserved
0x1816 (Read): Alternate Status Register
0x1816 (Write): Device Control Register
0x1817 Reserved
* The base must be Dword aligned; a PCI requirement. The Device Control
and Alternate Status Registers are at ofset 0x2 from this base.
[1] www.t13.org/documents/UploadedDocuments/project/d1510r1-Host-Adapter.pdf
[2] lateblt.tripod.com/atapi.htm
From Xiangliang - executing 'udevadm ...' causes a 32-bit I/O port read
to BAR1's region. This is shown by the BE (Byte Enable) value of
0x1111. So apparently reads to this region that include any of reserved
Bytes causes "the chip will go bad."
So, only a Byte access at offset 2 is successful. I have not been able
to get any more details as to the exact cause of the hang. I would have
thought that the PCI transaction would have just timed out, or errored
out, or something but apparently the platform ends up hanging.
It appears that this device did not implement the reserved registers
such that they would return 0 on reads or something more similarly sane.
Since BARs 2 and 3 are not 0, indicating the device only supports one
channel, I expect the same issue will occur when accessing BAR3. Again,
I do not have access to a system with this device to test with.
>
> > >> I would have thought that the solution to all this was to return
> > >-EINVAL
> > >> on any attemt to read or write these files while a driver is bound to
> > >> the device. If userspace is going to use the API, then the
> > >application
> > >> better unbind any driver first.
> > >>
> > >> Or? Am I missing something here?
> > >
> > >That doesn't really solve anything though. Let's pretend the resource
> > >files only work while the device is bound to pci-stub. Now what
> > >happens
> > >when you run this udevadm command as admin while it's in use by the
> > >userspace driver? All we've done is limit the scope of the problem.
> >
> > Assuming that the system hangs without driver help and that this
> > brokenness is widespread. I don't think any of those assumptions hold.
> > Do they?
>
> I thought it was true that for this device a system hang happened
> regardless of the host driver, but haven't seen the original bug report.
> As for widespread, this is the first I've heard of problems in the 2.5+
> years that we've supported these I/O port resource files. The rest is
> probably just FUD about random userspace apps trolling through device
> registers.
>
> > >> > If we want to blacklist this specific device, that's fine, but as
> > >others
> > >> > have pointed out it's really a class problem. Perhaps we report 1
> > >byte
> > >> > extra for the file length where EOF-1 is an enable byte? Is there
> > >> > anything else in file ops that we could use to make it slightly
> > >more
> > >> > complicated than open(), read() to access the device? Thanks,
> > >>
> > >> If there really are devices which cannot handle reading at all, and
> > >> cannot be reset to a sane state by later driver initialization, then
> > >a
> > >> blacklist could be added for those devices. This should not be a
> > >common
> > >> problem.
> > >
> > >Yes, if these are dead registers, let's blacklist and move along. I
> > >suspect though that these registers probably work fine if you access
> > >them according to the device programming model, so blacklisting just
> > >prevents full use through something like KVM device assignment.
> >
> > Well, if the device is that broken then I think it will require the
> > kernel to police the device programming. I don't see how you can leave
> > a bomb like that because it might be useful in a rare and very
> > theoretical case.
> >
> > Easier to just blacklist it...
>
> Easier, yes. But it likely just kicks the problem down the road until
> the next device. Thanks,
>
> Alex
>
>
^ permalink raw reply
* Re: [PATCH] udevadm-info: Don't access sysfs 'resource<N>' files
From: Myron Stowe @ 2013-03-19 17:06 UTC (permalink / raw)
To: Alex Williamson
Cc: Bjørn Mork, Greg KH, Kay Sievers, Myron Stowe, linux-hotplug,
linux-pci, yuxiangl, yxlraid, linux-kernel
In-Reply-To: <1363712270.2399.62.camel@zim.stowe>
On Tue, 2013-03-19 at 10:57 -0600, Myron Stowe wrote:
> On Mon, 2013-03-18 at 12:59 -0600, Alex Williamson wrote:
> > On Mon, 2013-03-18 at 19:25 +0100, Bjørn Mork wrote:
> > > Alex Williamson <alex.williamson@redhat.com> wrote:
> > >
> > > >On Mon, 2013-03-18 at 18:20 +0100, Bjørn Mork wrote:
> > > >> Alex Williamson <alex.williamson@redhat.com> writes:
> > > >>
> > > >> > At least for KVM the kernel fix is the addition of the vfio driver
> > > >which
> > > >> > gives us a non-sysfs way to do this. If this problem was found a
> > > >few
> > > >> > years later and we were ready to make the switch I'd support just
> > > >> > removing these resource files. In the meantime we have userspace
> > > >that
> > > >> > depends on this interface, so I'm open to suggestions how to fix
> > > >it.
> > > >>
> > > >> I am puzzled by a couple of things in this discussion:
> > > >>
> > > >> 1) do you seriously mean that a userspace application (any, not just
> > > >> udevadm or qemu or whatever) should be able to read and write
> > > >these
> > > >> registers while the device is owned by a driver? How is that ever
> > > >> going to work?
> > > >
> > > >The expectation is that the user doesn't mess with the device through
> > > >pci-sysfs while it's running. This is really no different than config
> > > >space or MMIO space in that respect.
> > >
> > > But it is. That's the problem. As a user I expect to be able to run
> > > e.g "grep . /sys/devices/whatever/*" with no ill effects. This holds
> > > for config space or MMIO space. It does not for any reset-on-read
> > > register.
> >
> > As a non-admin user you can
> >
> > > > You can use setpci to break your
> > > >PCI card while it's used by the driver today. The difference is that
> > > >MMIO spaces side-step the issue by only allowing mmap and config space
> > > >is known not to have read side-effects.
> > >
> > > Yes. And that is why there is no problem exporting those. This
> > > difference is fundamental.
> >
> > So how do we side-step the problem with I/O port registers? If we
> > remove them then KVM needs to run with iopl which is a pretty serious
> > security hole should QEMU be exploited. We could activate the resource
> > files only when the device is bound to pci-assign, but that only limits
> > the scope and might break UIO drivers. We could modify the file to have
> > an enable sequence, but we can't do this without breaking current
> > userspace. As I mentioned, the VFIO driver is intended to replace KVM's
> > use of these files, but we're not ready to rip it out, perhaps not even
> > ready to declare it deprecated.
> >
> > > >> 2) is it really so that a device can be so fundamentally screwed up
> > > >by
> > > >> reading some registers, that a later driver probe cannot properly
> > > >> reinitialize it?
> > > >
> > > >Never underestimate how broken hardware can be,
> > >
> > > True :)
> > >
> > > > though in this case
> > > >reading a device register seems to be causing a system hang/reset.
> > >
> > > I understand that it does so if the ahci driver is bound to the device
> > > while reading the registers, but does it also hang the system with no
> > > bound driver? How does it do that? By killing the bus?
> >
> > I don't know, Myron?
>
> Yes - the system hangs when BAR1's (and likely BAR3's) I/O port space is
> read.
Sorry - that wasn't very explicit. Just accessing BAR1's region as
udevadm does is enough to hang the system - even when no driver is
bound.
>
> Here are the details that I've been able to put together from the two
> linux-pci threads and various online sources -
>
>
> From Robert Hancock - "... BAR5 is the MMIO region used by the AHCI
> driver. BARs 0-4 are the legacy SFF-compatible ATA ports. Nothing
> should be messing with those IO ports while AHCI is enabled. ..." This
> likely explains why the system boots and runs fine as long as the
> 'udevadm ...' command is *not* ran (i.e. the driver never accesses the
> I/O port BARs).
>
> Using a SATA controller I have access to as an example for the details
> (Note: I do not have access to a system with the Marvell 9125 device):
> 00:1f.2 SATA controller: Intel Corporation 5 Series/3400 Series Chipset 6 port SATA AHCI Controller (rev 06) (prog-if 01 [AHCI 1.0])
> Subsystem: Lenovo Device 2168
> Region 0: I/O ports at 1860 [size=8]
> Region 1: I/O ports at 1814 [size=4]
> Region 2: I/O ports at 1818 [size=8]
> Region 3: I/O ports at 1810 [size=4]
> Region 4: I/O ports at 1840 [size2]
> Region 5: Memory at f2827000 (32-bit, non-prefetchable) [size=2K]
>
> I/O port registers [1][2]:
> Primary IDE controller [0x1860-0x1867; 0x1814-0x1817]
> BAR0 Base address for the command block registers for ATA Channel X
> 0x1860 (Read/Write): Data Register
> 0x1861 (Read): Error Register
> 0x1861 (Write): Features Register
> 0x1862 (Read/Write): Sector Count Register
> 0x1863 (Read/Write): LBA Low Register
> 0x1864 (Read/Write): LBA Mid Register
> 0x1865 (Read/Write): LBA High Register
> 0x1866 (Read/Write): Drive/Head Register
> 0x1867 (Read): Status Register
> 0x1867 (Write): Command Register
> BAR1* Base address for the control register for ATA Channel X
> 0x1814 Reserved
> 0x1815 Reserved
> 0x1816 (Read): Alternate Status Register
> 0x1816 (Write): Device Control Register
> 0x1817 Reserved
>
> * The base must be Dword aligned; a PCI requirement. The Device Control
> and Alternate Status Registers are at ofset 0x2 from this base.
>
> [1] www.t13.org/documents/UploadedDocuments/project/d1510r1-Host-Adapter.pdf
> [2] lateblt.tripod.com/atapi.htm
>
> From Xiangliang - executing 'udevadm ...' causes a 32-bit I/O port read
> to BAR1's region. This is shown by the BE (Byte Enable) value of
> 0x1111. So apparently reads to this region that include any of reserved
> Bytes causes "the chip will go bad."
>
> So, only a Byte access at offset 2 is successful. I have not been able
> to get any more details as to the exact cause of the hang. I would have
> thought that the PCI transaction would have just timed out, or errored
> out, or something but apparently the platform ends up hanging.
>
> It appears that this device did not implement the reserved registers
> such that they would return 0 on reads or something more similarly sane.
>
> Since BARs 2 and 3 are not 0, indicating the device only supports one
> channel, I expect the same issue will occur when accessing BAR3. Again,
> I do not have access to a system with this device to test with.
>
> >
> > > >> I would have thought that the solution to all this was to return
> > > >-EINVAL
> > > >> on any attemt to read or write these files while a driver is bound to
> > > >> the device. If userspace is going to use the API, then the
> > > >application
> > > >> better unbind any driver first.
> > > >>
> > > >> Or? Am I missing something here?
> > > >
> > > >That doesn't really solve anything though. Let's pretend the resource
> > > >files only work while the device is bound to pci-stub. Now what
> > > >happens
> > > >when you run this udevadm command as admin while it's in use by the
> > > >userspace driver? All we've done is limit the scope of the problem.
> > >
> > > Assuming that the system hangs without driver help and that this
> > > brokenness is widespread. I don't think any of those assumptions hold.
> > > Do they?
> >
> > I thought it was true that for this device a system hang happened
> > regardless of the host driver, but haven't seen the original bug report.
> > As for widespread, this is the first I've heard of problems in the 2.5+
> > years that we've supported these I/O port resource files. The rest is
> > probably just FUD about random userspace apps trolling through device
> > registers.
> >
> > > >> > If we want to blacklist this specific device, that's fine, but as
> > > >others
> > > >> > have pointed out it's really a class problem. Perhaps we report 1
> > > >byte
> > > >> > extra for the file length where EOF-1 is an enable byte? Is there
> > > >> > anything else in file ops that we could use to make it slightly
> > > >more
> > > >> > complicated than open(), read() to access the device? Thanks,
> > > >>
> > > >> If there really are devices which cannot handle reading at all, and
> > > >> cannot be reset to a sane state by later driver initialization, then
> > > >a
> > > >> blacklist could be added for those devices. This should not be a
> > > >common
> > > >> problem.
> > > >
> > > >Yes, if these are dead registers, let's blacklist and move along. I
> > > >suspect though that these registers probably work fine if you access
> > > >them according to the device programming model, so blacklisting just
> > > >prevents full use through something like KVM device assignment.
> > >
> > > Well, if the device is that broken then I think it will require the
> > > kernel to police the device programming. I don't see how you can leave
> > > a bomb like that because it might be useful in a rare and very
> > > theoretical case.
> > >
> > > Easier to just blacklist it...
> >
> > Easier, yes. But it likely just kicks the problem down the road until
> > the next device. Thanks,
> >
> > Alex
> >
> >
>
>
^ permalink raw reply
* Dell Latitude E6530 keymap
From: Stephen Gildea @ 2013-03-24 23:21 UTC (permalink / raw)
To: linux-hotplug
I have a Dell Latitude E6530 laptop
(system vendor "Dell Inc.", product name "Latitude E6530").
A few of the keys are mapped incorrectly:
Fn+F5, Touchpad Toggle
----------------------
Fn+F5 is labeled on my keyboard with a "touchpad" icon, and in
udev 198, the line in /lib/udev/keymaps/dell for it is this:
0x9E f21 #touchpad toggle
Since we know it is "touchpad toggle" (and I confirm it is), and there
is a key name for that, how about changing this line to read thusly:
0x9E touchpad_toggle # Fn+F5
In the same "dell" file, 0xD9 is mapped the same ("f21 # touchpad toggle");
perhaps it also should be changed to send a real touchpad_toggle?
Fn+F8, LCD/CRT Switch
---------------------
Fn+F8 is labeled on my keyboard with an "LCD/CRT" icon.
It sends two keycodes: Left_Win (aka "leftmeta"), then "p".
Can we get it to appear as a single "switchvideomode" key?
(If this is outside udev's domain, where should I look?)
Fn+End, Prnt Scrn
-----------------
The SysRq (Fn+Home) and Prnt Scrn (Fn+End) keys both send the same
scan code, 0xB7, which is mapped to "sysrq". How can I get Prnt Scrn
to send something unique?
< Stephen
^ permalink raw reply
* Re: Dell Latitude E6530 keymap
From: Dmitry Torokhov @ 2013-03-26 0:46 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <20580.1364167284@owl>
On Sunday, March 24, 2013 04:21:24 PM Stephen Gildea wrote:
> I have a Dell Latitude E6530 laptop
> (system vendor "Dell Inc.", product name "Latitude E6530").
> A few of the keys are mapped incorrectly:
>
> Fn+F5, Touchpad Toggle
> ----------------------
>
> Fn+F5 is labeled on my keyboard with a "touchpad" icon, and in
> udev 198, the line in /lib/udev/keymaps/dell for it is this:
>
> 0x9E f21 #touchpad toggle
>
> Since we know it is "touchpad toggle" (and I confirm it is), and there
> is a key name for that, how about changing this line to read thusly:
>
> 0x9E touchpad_toggle # Fn+F5
>
> In the same "dell" file, 0xD9 is mapped the same ("f21 # touchpad toggle");
> perhaps it also should be changed to send a real touchpad_toggle?
Unfortunately X can't deal with keycodes above 255 :(
--
Dmitry
^ permalink raw reply
* device properties and change events
From: Keith Pine @ 2013-03-27 4:47 UTC (permalink / raw)
To: linux-hotplug
I'm using udev-147 in CentOS 6.3.
I have two rules that import properties into the udev db. I'll use a
simplified example.
IMPORT{program}="program1 %k"
ACTION="add", IMPORT{program}="program2 %N"
program1 exports MY_FOO, and program2 exports MY_BAR. I've noticed that
when a change event is triggered, MY_BAR is no longer available in the
udev database. So it appears change events clear the existing environment.
The work done in program2 is relatively expensive so I'd rather only run
it when the device is first added.
It looks like I can re-import MY_BAR if I use IMPORT{db} in a separate
rule:
IMPORT{program}="program1 %k"
ACTION="add", IMPORT{program}="program2 %N"
ACTION="change", IMPORT{db}="MY_BAR"
Is this the correct approach? Or is there another way to persist the
properties that were imported during add, besides re-importing program2?
Also, is it possible to determine *what* causes a change event to occur?
With 'udevadm monitor' I can see change events being triggered whenever my
application exits (for the devices it has opened), and would like to
determine why. I was hoping udev could give me a hint.
-Keith
^ permalink raw reply
* Re: device properties and change events
From: Greg KH @ 2013-03-28 22:58 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <F391FB4F21BEC943926789308B8035905C5C8FD8@LAX-EX-MB3.datadirect.datadirectnet.com>
On Wed, Mar 27, 2013 at 04:47:39AM +0000, Keith Pine wrote:
> I'm using udev-147 in CentOS 6.3.
My sympathies :)
> I have two rules that import properties into the udev db. I'll use a
> simplified example.
>
> IMPORT{program}="program1 %k"
> ACTION="add", IMPORT{program}="program2 %N"
>
> program1 exports MY_FOO, and program2 exports MY_BAR. I've noticed that
> when a change event is triggered, MY_BAR is no longer available in the
> udev database. So it appears change events clear the existing environment.
What is triggering a change event? What type of device? What driver?
> The work done in program2 is relatively expensive so I'd rather only run
> it when the device is first added.
>
> It looks like I can re-import MY_BAR if I use IMPORT{db} in a separate
> rule:
>
> IMPORT{program}="program1 %k"
> ACTION="add", IMPORT{program}="program2 %N"
> ACTION="change", IMPORT{db}="MY_BAR"
>
>
> Is this the correct approach? Or is there another way to persist the
> properties that were imported during add, besides re-importing program2?
I think that is correct. When a device "changes", all of it's
attributes are thrown away as they obviously changed (the kernel told us
so.)
> Also, is it possible to determine *what* causes a change event to occur?
What type of device is this?
> With 'udevadm monitor' I can see change events being triggered whenever my
> application exits (for the devices it has opened), and would like to
> determine why. I was hoping udev could give me a hint.
Your kernel driver should tell you why, what driver is it?
thanks,
greg k-h
^ permalink raw reply
* RE: device properties and change events
From: Keith Pine @ 2013-03-29 1:26 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <F391FB4F21BEC943926789308B8035905C5C8FD8@LAX-EX-MB3.datadirect.datadirectnet.com>
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBHcmVnIEtIIFttYWlsdG86Z3Jl
Z2toQGxpbnV4Zm91bmRhdGlvbi5vcmddDQo+IFNlbnQ6IFRodXJzZGF5LCBNYXJjaCAyOCwgMjAx
MyAzOjU5IFBNDQo+IFRvOiBLZWl0aCBQaW5lDQo+IENjOiBsaW51eC1ob3RwbHVnQHZnZXIua2Vy
bmVsLm9yZw0KPiBTdWJqZWN0OiBSZTogZGV2aWNlIHByb3BlcnRpZXMgYW5kIGNoYW5nZSBldmVu
dHMNCg0KLi4uDQoNCj4gSSB0aGluayB0aGF0IGlzIGNvcnJlY3QuICBXaGVuIGEgZGV2aWNlICJj
aGFuZ2VzIiwgYWxsIG9mIGl0J3MNCj4gYXR0cmlidXRlcyBhcmUgdGhyb3duIGF3YXkgYXMgdGhl
eSBvYnZpb3VzbHkgY2hhbmdlZCAodGhlIGtlcm5lbCB0b2xkIHVzDQo+IHNvLikNCg0KT2ssIHRo
YXQgbWFrZXMgc2Vuc2UuDQoNCj4gPiBXaXRoICd1ZGV2YWRtIG1vbml0b3InIEkgY2FuIHNlZSBj
aGFuZ2UgZXZlbnRzIGJlaW5nIHRyaWdnZXJlZCB3aGVuZXZlcg0KPiBteQ0KPiA+IGFwcGxpY2F0
aW9uIGV4aXRzIChmb3IgdGhlIGRldmljZXMgaXQgaGFzIG9wZW5lZCksIGFuZCB3b3VsZCBsaWtl
IHRvDQo+ID4gZGV0ZXJtaW5lIHdoeS4gSSB3YXMgaG9waW5nIHVkZXYgY291bGQgZ2l2ZSBtZSBh
IGhpbnQuDQo+IA0KPiBZb3VyIGtlcm5lbCBkcml2ZXIgc2hvdWxkIHRlbGwgeW91IHdoeSwgd2hh
dCBkcml2ZXIgaXMgaXQ/DQoNClNDU0kgYmxvY2sgZGV2aWNlIChzZCkuIFlvdXIgcXVlc3Rpb25z
IGdvdCBtZSBsb29raW5nIGFnYWluLCBzbyBJIGRpZCBhIHF1aWNrIHRlc3Qgd2hpY2ggc2hvd2Vk
IHRoYXQgdGhlIGFjdCBvZiBjbG9zaW5nIGEgZmlsZSBkZXNjcmlwdG9yIG9wZW5lZCBvbiB0aGUg
YmxvY2sgZGV2aWNlIHdpdGggd3JpdGUgYWNjZXNzIGlzIGVub3VnaCB0byB0cmlnZ2VyIHRoZSBj
aGFuZ2UgZXZlbnQgKHJlYWQtb25seSBhY2Nlc3MgZG9lcyBub3QgY2F1c2UgYSBjaGFuZ2UgZXZl
bnQpLiBJIGxvb2tlZCBhdCBzY3NpIGRlYnVnIGxvZ3MsIGV0Yy4sIGFuZCBmaW5hbGx5IGNoZWNr
ZWQgR29vZ2xlLCB3aGVyZSBJIHdhcyByZW1pbmRlZCBhYm91dCB0aGUgd2F0Y2ggb3B0aW9uLiBT
dXJlIGVub3VnaCwgdGhlIDYwLXBlcnNpc3RlbnQtc3RvcmFnZS5ydWxlcyBmaWxlIGVuYWJsZXMg
d2F0Y2ggZm9yIHNkIGRldmljZXMuIElmIEkgc2V0IG5vd2F0Y2ggaW4gbXkgY3VzdG9tIHVkZXYg
cnVsZXMgdGhlIGNoYW5nZSBldmVudHMgbm8gbG9uZ2VyIHRyaWdnZXI7IG15c3Rlcnkgc29sdmVk
Lg0KDQpJIGd1ZXNzIG5vdyBJIG5lZWQgdG8gY29uc2lkZXIgd2hldGhlciBvciBub3QgSSBldmVu
IHdhbnQgd2F0Y2ggZW5hYmxlZCBmb3IgbXkgYmxvY2sgZGV2aWNlcy4gVGhlcmUncyBubyBmaWxl
c3lzdGVtIGFuZCBteSBhcHBsaWNhdGlvbiB3aWxsIHR5cGljYWxseSBiZSB0aGUgb3duZXIgYW5k
IG9ubHkgdXNlciwgc28gSSdtIG5vdCBzdXJlIHRoZSBvcHRpb24gaXMgdXNlZnVsLiBBcmUgeW91
IGF3YXJlIG9mIGFueSBvdGhlciBraW5kIG9mIGV2ZW50cyB0aGF0IGNvdWxkIGNhdXNlIGEgY2hh
bmdlIGV2ZW50IG9uIGEgYmxvY2sgZGV2aWNlPw0KDQpUaGFua3MsDQpLZWl0aA0K
^ permalink raw reply
* [ANNOUNCE] kmod 13
From: Lucas De Marchi @ 2013-04-09 22:57 UTC (permalink / raw)
To: linux-modules; +Cc: LKML, linux-hotplug, Rusty Russell
ftp://ftp.kernel.org/pub/linux/utils/kernel/kmod/kmod-13.tar.xz
ftp://ftp.kernel.org/pub/linux/utils/kernel/kmod/kmod-13.tar.sign
New release of kmod 13, after some time accumulating bug fixes and new
features. This release got a bit delayed due to my marriage,
vacations, changing job and some new features getting into the kernel.
What else could happen at the same time? :-)
The most notable new features are the support for finit_module()
syscall and for signed modules. For finit_module() we try to be nice
with older kernels and we fallback to init_module() if the new one is
not available. The older syscall is also used in case the module is
compressed.
There are also bug fixes and other minor new features. Check the NEWS
file. Thanks to everyone involved in this release. Shortlog is below.
Cheers,
Lucas De Marchi
---
Andrey Mazo (2):
depmod: --symbol-prefix actually requires an argument
depmod: fix builtin symbols resolution when the prefix symbol is set
Cristian Rodríguez (1):
libkmod: Use secure_getenv if available
Josh Boyer (1):
rmmod: Teach rmmod about builtin modules
Kees Cook (3):
libkmod: add finit_module logic
testsuite: handle finit_module
libkmod: fix address argument to mmap calls
Lucas De Marchi (13):
man: fix lib dir in which we look for config
gitignore: ignore files generated by Automake's testsuite
Update copyright notices
libkmod-util: Add missing include file
testsuite: Exit with success on signal if test has expected_fail=true
testsuite: Add test to check if modprobe explodes on bogus config
modprobe: Fix assertion on --show-depends with bogus config file
libkmod: Add missing definitions
libkmod: Move finit_module() definition to missing.h
testsuite: Wrap syscall() to get calls to finit_module()
testsuite: Fix checking __sysno
build-sys: Always enable parallel tests
kmod 13
Michal Marek (4):
libkmod-module: Add helper for building the module info list
libkmod-module: Do not free the list in kmod_module_info_append
libkmod: Return module signature information in kmod_module_get_info()
testsuite: Add modinfo test for module signatures
^ permalink raw reply
* [PATCH] [WIP]tools: add devname2tmpfile
From: Tom Gundersen @ 2013-04-11 15:47 UTC (permalink / raw)
To: linux-hotplug
This tool reads modules.devname from the current kernel directory and writes the information
out in the tmpfiles format so that systemd-tmpfiles can use this to create the required device
nodes before systemd-udevd is started on boot.
This makes sure nothing but kmod reads the private files under
/usr/lib/modules/.
Cc: <linux-hotplug@vger.kernel.org>
Cc: <systemd-devel@lists.freedesktop.org>
---
Makefile.am | 3 +-
tools/devname2tmpfile.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++
tools/kmod.c | 1 +
tools/kmod.h | 1 +
4 files changed, 130 insertions(+), 1 deletion(-)
create mode 100644 tools/devname2tmpfile.c
diff --git a/Makefile.am b/Makefile.am
index 9feaf96..50cd380 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -109,7 +109,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
tools/rmmod.c tools/insmod.c \
tools/modinfo.c tools/modprobe.c \
- tools/depmod.c tools/log.h tools/log.c
+ tools/depmod.c tools/log.h tools/log.c \
+ tools/devname2tmpfile.c
tools_kmod_LDADD = libkmod/libkmod-util.la \
libkmod/libkmod.la
diff --git a/tools/devname2tmpfile.c b/tools/devname2tmpfile.c
new file mode 100644
index 0000000..05a2b4e
--- /dev/null
+++ b/tools/devname2tmpfile.c
@@ -0,0 +1,126 @@
+/*
+ * kmod-devname2tmpfile - write devnames of current kernel in tmpfiles.d format
+ *
+ * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2011-2013 ProFUSION embedded systems
+ * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "libkmod.h"
+
+#include "kmod.h"
+
+static int do_devname2tmpfile(int argc, char *argv[])
+{
+ struct kmod_ctx *ctx;
+ struct utsname kernel;
+ const char *null_config = NULL;
+ char modules[PATH_MAX];
+ char buf[4096];
+ FILE *f, *out;
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: %s\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx = NULL) {
+ fputs("Error: kmod_new() failed!\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ if (uname(&kernel) < 0) {
+ fputs("Error: uname failed!\n", stderr);
+ return EXIT_FAILURE;
+ }
+ snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
+ f = fopen(modules, "re");
+ if (f = NULL) {
+ fprintf(stderr, "Error: could not open %s/modules.devname!\n", kernel.release);
+ return EXIT_FAILURE;
+ }
+
+ if (mkdir("/run/tmpfiles.d/", 755) != 0 && errno != EEXIST) {
+ fputs("Error: /run/tmpfiles.d does not exist and could not be created!\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ out = fopen("/run/tmpfiles.d/kmod.conf", "we");
+ if (out = NULL) {
+ fputs("Error: could not create /run/tmpfiles.d/kmod.conf!\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *s;
+ const char *modname;
+ const char *devname;
+ const char *devno;
+ int maj, min;
+ char type;
+
+ if (buf[0] = '#')
+ continue;
+
+ modname = buf;
+ s = strchr(modname, ' ');
+ if (s = NULL)
+ continue;
+ s[0] = '\0';
+
+ devname = &s[1];
+ s = strchr(devname, ' ');
+ if (s = NULL)
+ continue;
+ s[0] = '\0';
+
+ devno = &s[1];
+ s = strchr(devno, ' ');
+ if (s = NULL)
+ s = strchr(devno, '\n');
+ if (s != NULL)
+ s[0] = '\0';
+ if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
+ continue;
+
+ if (type != 'c' && type != 'b')
+ continue;
+
+ fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
+ }
+
+ fclose(f);
+ kmod_unref(ctx);
+
+ return EXIT_SUCCESS;
+}
+
+const struct kmod_cmd kmod_cmd_devname2tmpfile = {
+ .name = "devname2tmpfile",
+ .cmd = do_devname2tmpfile,
+ .help = "write devnames of current kernel in tmpfiles.d format",
+};
diff --git a/tools/kmod.c b/tools/kmod.c
index ebb8875..ff6518c 100644
--- a/tools/kmod.c
+++ b/tools/kmod.c
@@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
static const struct kmod_cmd *kmod_cmds[] = {
&kmod_cmd_help,
&kmod_cmd_list,
+ &kmod_cmd_devname2tmpfile,
};
static const struct kmod_cmd *kmod_compat_cmds[] = {
diff --git a/tools/kmod.h b/tools/kmod.h
index 80fa4c2..6410ed5 100644
--- a/tools/kmod.h
+++ b/tools/kmod.h
@@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
extern const struct kmod_cmd kmod_cmd_compat_depmod;
extern const struct kmod_cmd kmod_cmd_list;
+extern const struct kmod_cmd kmod_cmd_devname2tmpfile;
#include "log.h"
--
1.8.2.1
^ permalink raw reply related
* [PATCH] [RFC] udevd: let tmpfiles create all static nodes
From: Tom Gundersen @ 2013-04-11 15:48 UTC (permalink / raw)
To: linux-hotplug
systemd-tmpfiles has had support for creation of static nodes for some time (to
replace copying nodes from /lib/udev/). Make sure these nodes are created before
udev is started.
Also, drop support for creating static nodes based on modules.devname from
systemd-udevd. This allows it to run witohut CAP_MKNOD, moreover we no longer
need to parse /usr/lib/modules/*/modules.devname.
As a replacement for udevd's functionality, we let kmod generate a tmpfiles.d
fragment based on the correct modules.devname file (see separate patch). We
might want to split the kmod call out into its own unit file and ship that with
kmod instead.
Note: one functional change is that we no longer update the creation time on
already existing device nodes. Is this important? If so, should tmpfiles learn to
do that?
Cc: <linux-modules@vger.kernel.org>
Cc: <linux-hotplug@vger.kernel.org>
---
Makefile.am | 5 +++
TODO | 4 --
src/udev/udevd.c | 72 -----------------------------------
units/systemd-static-nodes.service.in | 17 +++++++++
units/systemd-udevd.service.in | 5 +--
5 files changed, 24 insertions(+), 79 deletions(-)
create mode 100644 units/systemd-static-nodes.service.in
diff --git a/Makefile.am b/Makefile.am
index ec81f53..3c6adcb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -427,6 +427,7 @@ nodist_systemunit_DATA = \
units/systemd-kexec.service \
units/systemd-fsck@.service \
units/systemd-fsck-root.service \
+ units/systemd-static-nodes.service \
units/systemd-udevd.service \
units/systemd-udev-trigger.service \
units/systemd-udev-settle.service \
@@ -468,6 +469,7 @@ EXTRA_DIST += \
units/systemd-fsck@.service.in \
units/systemd-fsck-root.service.in \
units/user@.service.in \
+ units/systemd-static-nodes.service \
units/systemd-udevd.service \
units/systemd-udev-trigger.service \
units/systemd-udev-settle.service \
@@ -1925,11 +1927,13 @@ CLEANFILES += \
src/udev/udev.pc
EXTRA_DIST += \
+ units/systemd-static-nodes.service.in \
units/systemd-udevd.service.in \
units/systemd-udev-trigger.service.in \
units/systemd-udev-settle.service.in
CLEANFILES += \
+ units/systemd-static-nodes.service \
units/systemd-udevd.service \
units/systemd-udev-trigger.service \
units/systemd-udev-settle.service
@@ -1938,6 +1942,7 @@ SOCKETS_TARGET_WANTS += \
systemd-udevd-control.socket \
systemd-udevd-kernel.socket
SYSINIT_TARGET_WANTS += \
+ systemd-static-nodes.service \
systemd-udevd.service \
systemd-udev-trigger.service
diff --git a/TODO b/TODO
index 369fb78..d70732d 100644
--- a/TODO
+++ b/TODO
@@ -51,10 +51,6 @@ Features:
so that the coredump is properly written to the user's own journal
file.
-* move /usr/lib/modules/$(uname -r)/modules.devname parsing from udevd to
- kmod static-nodes
- call kmod as an early service, and drop CAP_MKNOD from udevd.service
-
* systemd-delta needs to be made aware of *.d/*.conf drop-in files for
units.
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 2d9093d..642ca43 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -812,77 +812,6 @@ static void handle_signal(struct udev *udev, int signo)
}
}
-static void static_dev_create_from_modules(struct udev *udev)
-{
- struct utsname kernel;
- char modules[UTIL_PATH_SIZE];
- char buf[4096];
- FILE *f;
-
- if (uname(&kernel) < 0) {
- log_error("uname failed: %m");
- return;
- }
-
- strscpyl(modules, sizeof(modules), ROOTPREFIX "/lib/modules/", kernel.release, "/modules.devname", NULL);
- f = fopen(modules, "re");
- if (f = NULL)
- return;
-
- while (fgets(buf, sizeof(buf), f) != NULL) {
- char *s;
- const char *modname;
- const char *devname;
- const char *devno;
- int maj, min;
- char type;
- mode_t mode;
- char filename[UTIL_PATH_SIZE];
-
- if (buf[0] = '#')
- continue;
-
- modname = buf;
- s = strchr(modname, ' ');
- if (s = NULL)
- continue;
- s[0] = '\0';
-
- devname = &s[1];
- s = strchr(devname, ' ');
- if (s = NULL)
- continue;
- s[0] = '\0';
-
- devno = &s[1];
- s = strchr(devno, ' ');
- if (s = NULL)
- s = strchr(devno, '\n');
- if (s != NULL)
- s[0] = '\0';
- if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
- continue;
-
- mode = 0600;
- if (type = 'c')
- mode |= S_IFCHR;
- else if (type = 'b')
- mode |= S_IFBLK;
- else
- continue;
-
- strscpyl(filename, sizeof(filename), "/dev/", devname, NULL);
- mkdir_parents_label(filename, 0755);
- label_context_set(filename, mode);
- log_debug("mknod '%s' %c%u:%u\n", filename, type, maj, min);
- if (mknod(filename, mode, makedev(maj, min)) < 0 && errno = EEXIST)
- utimensat(AT_FDCWD, filename, NULL, 0);
- label_context_clear();
- }
-
- fclose(f);
-}
-
static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink)
{
int ctrl = -1, netlink = -1;
@@ -1067,7 +996,6 @@ int main(int argc, char *argv[])
mkdir("/run/udev", 0755);
dev_setup(NULL);
- static_dev_create_from_modules(udev);
/* before opening new files, make sure std{in,out,err} fds are in a sane state */
if (daemonize) {
diff --git a/units/systemd-static-nodes.service.in b/units/systemd-static-nodes.service.in
new file mode 100644
index 0000000..8178c43
--- /dev/null
+++ b/units/systemd-static-nodes.service.in
@@ -0,0 +1,17 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Create static device nodes in /dev
+DefaultDependencies=no
+Before=sysinit.target local-fs-pre.target
+ConditionCapabilityÊP_MKNOD
+
+[Service]
+Type=oneshot
+ExecStart=@rootbindir@/kmod devname2tmpfile
+ExecStart=@rootbindir@/systemd-tmpfiles --prefix=/dev --create
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
index ddef423..c0dc4f2 100644
--- a/units/systemd-udevd.service.in
+++ b/units/systemd-udevd.service.in
@@ -9,10 +9,9 @@
Description=udev Kernel Device Manager
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
-Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket
-After=systemd-udevd-control.socket systemd-udevd-kernel.socket
+Wants=systemd-static-nodes.service systemd-udevd-control.socket systemd-udevd-kernel.socket
+After=systemd-static-nodes.service systemd-udevd-control.socket systemd-udevd-kernel.socket
Before=sysinit.target local-fs-pre.target
-ConditionCapabilityÊP_MKNOD
[Service]
Type=notify
--
1.8.2.1
^ permalink raw reply related
* Disabling device
From: Štefan Sakalík @ 2013-04-11 16:16 UTC (permalink / raw)
To: linux-hotplug
Hello,
I want to tell udev in RHEL6 _not_ to create a hard drive device in
/dev/ identified by (for example) serial number. I see two problems:
1. AFAIK it is not possible to disable device creation in udev/rules.d/
2. It is not possible to identify device by serial number in udev. When
I run: udevadm info -a -p $(udevadm info -q path -n /dev/sdak)
, it does not show me serial or other identifying information.
I need to get rid of this device because I'm sharing one disk array
between two servers and both of them see all devices in the array.
I want to make sure the two servers are not accessing the drives
simultaneously.
-Stefan
^ permalink raw reply
* Re: Disabling device
From: Greg KH @ 2013-04-11 16:46 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <5166E1C8.60105@gmail.com>
On Thu, Apr 11, 2013 at 06:16:08PM +0200, Štefan Sakalík wrote:
> Hello,
> I want to tell udev in RHEL6 _not_ to create a hard drive device in
> /dev/ identified by (for example) serial number. I see two problems:
> 1. AFAIK it is not possible to disable device creation in udev/rules.d/
> 2. It is not possible to identify device by serial number in udev.
> When I run: udevadm info -a -p $(udevadm info -q path -n /dev/sdak)
> , it does not show me serial or other identifying information.
As you are using RHEL6, why not ask for support for this type of
situation from Red Hat? You are paying for the support, might as well
use it :)
Good luck,
greg k-h
^ permalink raw reply
* Re: [PATCH] [WIP]tools: add devname2tmpfile
From: Dave Reisner @ 2013-04-11 18:21 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1365695275-30856-1-git-send-email-teg@jklm.no>
On Thu, Apr 11, 2013 at 05:47:55PM +0200, Tom Gundersen wrote:
> This tool reads modules.devname from the current kernel directory and writes the information
> out in the tmpfiles format so that systemd-tmpfiles can use this to create the required device
> nodes before systemd-udevd is started on boot.
I'm a little confused as to why this should live in kmod if the output
is only useful to systemd. Rather, I would have suspected that this
would be part of src/core/kmod-setup.c in systemd. modules.devname is
easily parseable and requires no knowledge of what kmod does internally.
In fact, your code initializes a kmod context but then never uses it for
anything.
I've left some comments for you regardless of where this ends up
living...
> This makes sure nothing but kmod reads the private files under
> /usr/lib/modules/.
The code says otherwise -- it reads from /lib/modules/...
> Cc: <linux-hotplug@vger.kernel.org>
> Cc: <systemd-devel@lists.freedesktop.org>
> ---
> Makefile.am | 3 +-
> tools/devname2tmpfile.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++
> tools/kmod.c | 1 +
> tools/kmod.h | 1 +
> 4 files changed, 130 insertions(+), 1 deletion(-)
> create mode 100644 tools/devname2tmpfile.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 9feaf96..50cd380 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -109,7 +109,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
> tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
> tools/rmmod.c tools/insmod.c \
> tools/modinfo.c tools/modprobe.c \
> - tools/depmod.c tools/log.h tools/log.c
> + tools/depmod.c tools/log.h tools/log.c \
> + tools/devname2tmpfile.c
> tools_kmod_LDADD = libkmod/libkmod-util.la \
> libkmod/libkmod.la
>
> diff --git a/tools/devname2tmpfile.c b/tools/devname2tmpfile.c
> new file mode 100644
> index 0000000..05a2b4e
> --- /dev/null
> +++ b/tools/devname2tmpfile.c
> @@ -0,0 +1,126 @@
> +/*
> + * kmod-devname2tmpfile - write devnames of current kernel in tmpfiles.d format
> + *
> + * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
> + * Copyright (C) 2011-2013 ProFUSION embedded systems
> + * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stddef.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <limits.h>
> +#include <sys/utsname.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include "libkmod.h"
> +
> +#include "kmod.h"
> +
> +static int do_devname2tmpfile(int argc, char *argv[])
> +{
> + struct kmod_ctx *ctx;
> + struct utsname kernel;
> + const char *null_config = NULL;
> + char modules[PATH_MAX];
> + char buf[4096];
> + FILE *f, *out;
> +
> + if (argc != 1) {
> + fprintf(stderr, "Usage: %s\n", argv[0]);
> + return EXIT_FAILURE;
> + }
> +
> + ctx = kmod_new(NULL, &null_config);
As mentioned above, this is never actually used, but it seems the only
thing it could be potentially used for is logging, rather than writing
directly to a stream.
> + if (ctx = NULL) {
> + fputs("Error: kmod_new() failed!\n", stderr);
> + return EXIT_FAILURE;
> + }
> +
> + if (uname(&kernel) < 0) {
> + fputs("Error: uname failed!\n", stderr);
> + return EXIT_FAILURE;
> + }
> + snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
> + f = fopen(modules, "re");
> + if (f = NULL) {
> + fprintf(stderr, "Error: could not open %s/modules.devname!\n", kernel.release);
Full path here instead of just a trailing fragment?
> + return EXIT_FAILURE;
I disagree that this should be an error or a failure.
> + }
> +
> + if (mkdir("/run/tmpfiles.d/", 755) != 0 && errno != EEXIST) {
> + fputs("Error: /run/tmpfiles.d does not exist and could not be created!\n", stderr);
> + return EXIT_FAILURE;
> + }
> +
> + out = fopen("/run/tmpfiles.d/kmod.conf", "we");
> + if (out = NULL) {
> + fputs("Error: could not create /run/tmpfiles.d/kmod.conf!\n", stderr);
> + return EXIT_FAILURE;
> + }
You appear to have some inconsistent whitespace above here in the
fprintf and fputs calls. There's more below which I haven't pointed out.
> +
> + while (fgets(buf, sizeof(buf), f) != NULL) {
> + char *s;
> + const char *modname;
> + const char *devname;
> + const char *devno;
> + int maj, min;
You declare these as int (signed), but then treat them as unsigned (%u)
in sscanf and fprintf.
> + char type;
> +
> + if (buf[0] = '#')
> + continue;
> +
> + modname = buf;
> + s = strchr(modname, ' ');
> + if (s = NULL)
> + continue;
> + s[0] = '\0';
> +
> + devname = &s[1];
> + s = strchr(devname, ' ');
> + if (s = NULL)
> + continue;
> + s[0] = '\0';
> +
> + devno = &s[1];
> + s = strchr(devno, ' ');
> + if (s = NULL)
> + s = strchr(devno, '\n');
> + if (s != NULL)
> + s[0] = '\0';
> + if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
> + continue;
This whole section is unnecessarily verbose. This should be a well
formed file where non-comment data matches the format string "%ms %ms
%c%u:%u". You can simply do your validation on that (i.e. sscanf
returns exactly 5). Note that %ms will allocate memory for the data, so
you need to free it after printing it below. Alternatively, just use
adequately sized stack allocated char[] with %s.
> +
> + if (type != 'c' && type != 'b')
> + continue;
I think this is worth logging about given that depmod currently never
writes anything but 'b' or 'c' here. I suspect this won't be changing
any time soon...
> + fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
> + }
> +
> + fclose(f);
> + kmod_unref(ctx);
> +
> + return EXIT_SUCCESS;
> +}
> +
> +const struct kmod_cmd kmod_cmd_devname2tmpfile = {
> + .name = "devname2tmpfile",
> + .cmd = do_devname2tmpfile,
> + .help = "write devnames of current kernel in tmpfiles.d format",
> +};
> diff --git a/tools/kmod.c b/tools/kmod.c
> index ebb8875..ff6518c 100644
> --- a/tools/kmod.c
> +++ b/tools/kmod.c
> @@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
> static const struct kmod_cmd *kmod_cmds[] = {
> &kmod_cmd_help,
> &kmod_cmd_list,
> + &kmod_cmd_devname2tmpfile,
> };
>
> static const struct kmod_cmd *kmod_compat_cmds[] = {
> diff --git a/tools/kmod.h b/tools/kmod.h
> index 80fa4c2..6410ed5 100644
> --- a/tools/kmod.h
> +++ b/tools/kmod.h
> @@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
> extern const struct kmod_cmd kmod_cmd_compat_depmod;
>
> extern const struct kmod_cmd kmod_cmd_list;
> +extern const struct kmod_cmd kmod_cmd_devname2tmpfile;
>
> #include "log.h"
> --
> 1.8.2.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-modules" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2] tools: add static-nodes tool
From: Tom Gundersen @ 2013-04-13 0:15 UTC (permalink / raw)
To: linux-hotplug
This tool reads modules.devname from the current kernel directory and outputs
the information.
For now only the tmpfiles.d(5) format is supported, but more could easily be
added in the future if there is a need.
When booting with systemd, the new tool is called at boot to instruct
systemd-tmpfiles to create the necessary static modules before starting
systemd-udevd.
This means nothing but kmod needs to reads the private files under /lib/modules/.
Cc: <linux-hotplug@vger.kernel.org>
Cc: <systemd-devel@lists.freedesktop.org>
---
v2: adressed concerns raised by Dave, and made the tool a bit more generic so
more output formats may be added in the future as suggested by Lucas. Also
included the systemd unit file to hook this up with systemd.
Makefile.am | 20 ++++-
configure.ac | 8 ++
tools/kmod-static-nodes.service.in | 16 ++++
tools/kmod.c | 1 +
tools/kmod.h | 1 +
tools/static-nodes.c | 163 +++++++++++++++++++++++++++++++++++++
6 files changed, 207 insertions(+), 2 deletions(-)
create mode 100644 tools/kmod-static-nodes.service.in
create mode 100644 tools/static-nodes.c
diff --git a/Makefile.am b/Makefile.am
index 9feaf96..333e861 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,9 @@ SED_PROCESS = \
%.pc: %.pc.in Makefile
$(SED_PROCESS)
+%.service: %.service.in Makefile
+ $(SED_PROCESS)
+
LIBKMOD_CURRENT=4
LIBKMOD_REVISION=2
LIBKMOD_AGE=2
@@ -88,6 +91,17 @@ pkgconfig_DATA = libkmod/libkmod.pc
EXTRA_DIST += libkmod/libkmod.pc.in
CLEANFILES += libkmod/libkmod.pc
+if HAVE_SYSTEMD
+systemdsystemunit_DATA = tools/kmod-static-nodes.service
+EXTRA_DIST += tools/kmod-static-nodes.service.in
+CLEANFILES += tools/kmod-static-nodes.service
+
+install-data-hook:
+ $(MKDIR_P) $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants
+ ln -sf ../kmod-static-nodes.service \
+ $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants/kmod-static-nodes.service
+endif
+
install-exec-hook:
if test "$(libdir)" != "$(rootlibdir)"; then \
$(MKDIR_P) $(DESTDIR)$(rootlibdir) && \
@@ -109,7 +123,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
tools/rmmod.c tools/insmod.c \
tools/modinfo.c tools/modprobe.c \
- tools/depmod.c tools/log.h tools/log.c
+ tools/depmod.c tools/log.h tools/log.c \
+ tools/static-nodes.c
tools_kmod_LDADD = libkmod/libkmod-util.la \
libkmod/libkmod.la
@@ -211,7 +226,8 @@ testsuite-distclean:
DISTCLEAN_LOCAL_HOOKS += testsuite-distclean
EXTRA_DIST += testsuite/rootfs-pristine
-DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib
+DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib \
+ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
diff --git a/configure.ac b/configure.ac
index 566b317..af5ed52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,13 @@ AS_IF([test "x$with_zlib" != "xno"], [
AC_MSG_NOTICE([zlib support not requested])
])
+AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != xno; then
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
#####################################################################
# --enable-
@@ -200,6 +207,7 @@ AC_MSG_RESULT([
compiler: ${CC}
cflags: ${with_cflags} ${CFLAGS}
ldflags: ${with_ldflags} ${LDFLAGS}
+ systemdsystemunitdir: ${with_systemdsystemunitdir}
tools: ${enable_tools}
logging: ${enable_logging}
diff --git a/tools/kmod-static-nodes.service.in b/tools/kmod-static-nodes.service.in
new file mode 100644
index 0000000..be8482e
--- /dev/null
+++ b/tools/kmod-static-nodes.service.in
@@ -0,0 +1,16 @@
+# This file is part of kmod.
+#
+# kmod is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Create list of static nodes to be created in /dev
+DefaultDependencies=no
+Before=sysinit.target systemd-static-nodes.service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/mkdir -p /run/tmpfiles.d
+ExecStart=@prefix@/bin/kmod static-nodes tmpfiles --output=/run/tmpfiles.d/kmod.conf
diff --git a/tools/kmod.c b/tools/kmod.c
index ebb8875..347bb7d 100644
--- a/tools/kmod.c
+++ b/tools/kmod.c
@@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
static const struct kmod_cmd *kmod_cmds[] = {
&kmod_cmd_help,
&kmod_cmd_list,
+ &kmod_cmd_static_nodes,
};
static const struct kmod_cmd *kmod_compat_cmds[] = {
diff --git a/tools/kmod.h b/tools/kmod.h
index 80fa4c2..68a646a 100644
--- a/tools/kmod.h
+++ b/tools/kmod.h
@@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
extern const struct kmod_cmd kmod_cmd_compat_depmod;
extern const struct kmod_cmd kmod_cmd_list;
+extern const struct kmod_cmd kmod_cmd_static_nodes;
#include "log.h"
diff --git a/tools/static-nodes.c b/tools/static-nodes.c
new file mode 100644
index 0000000..a79fc3d
--- /dev/null
+++ b/tools/static-nodes.c
@@ -0,0 +1,163 @@
+/*
+ * kmod-static-nodes - manage modules.devname
+ *
+ * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2011-2013 ProFUSION embedded systems
+ * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "libkmod-util.h"
+
+#include "kmod.h"
+
+static const char cmdopts_s[] = "o:h";
+static const struct option cmdopts[] = {
+ { "output", required_argument, 0, 'o'},
+ { "help", no_argument, 0, 'h'},
+ { },
+};
+
+static void help(void)
+{
+ printf("Usage:\n"
+ "\t%s static-nodes format [options]\n"
+ "\n"
+ "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
+ "\n"
+ "Options:\n"
+ "\t-o, --output=FILE write output to file\n"
+ "\t-h, --help show this help\n"
+ "\n"
+ "Formats:\n"
+ " tmpfiles the tmpfiles.d(5) used by systemd-tmpfiles.\n",
+ program_invocation_short_name);
+}
+
+static int write_tmpfile(FILE *in, FILE *out) {
+ char buf[4096];
+ int ret = EXIT_SUCCESS;
+
+ while (fgets(buf, sizeof(buf), in) != NULL) {
+ char devname[PATH_MAX];
+ char type;
+ unsigned int maj, min;
+ int matches;
+
+ if (buf[0] = '#')
+ continue;
+
+ matches = sscanf(buf, "%*s %s %c%u:%u", devname, &type, &maj, &min);
+ if (matches != 4 || (type != 'c' && type != 'b')) {
+ fprintf(stderr, "Error: invalid devname entry: %s", buf);
+ ret = EXIT_FAILURE;
+ continue;
+ }
+
+ fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
+ }
+
+ return ret;
+}
+
+static int do_static_nodes(int argc, char *argv[])
+{
+ struct utsname kernel;
+ char modules[PATH_MAX];
+ FILE *in = NULL, *out = stdout;
+ int ret = EXIT_SUCCESS;
+
+ for (;;) {
+ int c, idx = 0;
+
+ c = getopt_long(argc - 1, argv + 1, cmdopts_s, cmdopts, &idx);
+ if (c = -1) {
+ break;
+ }
+ switch (c) {
+ case 'o':
+ out = fopen(optarg, "we");
+ if (out = NULL) {
+ fprintf(stderr, "Error: could not create %s!\n", optarg);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ break;
+ case 'h':
+ help();
+ goto finish;
+ case '?':
+ ret = EXIT_FAILURE;
+ goto finish;
+ default:
+ fprintf(stderr, "Unexpected commandline option '%c'.\n", c);
+ help();
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ }
+
+ if (argc < 2) {
+ help();
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+
+ if (!streq(argv[1], "tmpfiles")) {
+ fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
+ help();
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+
+ if (uname(&kernel) < 0) {
+ fputs("Error: uname failed!\n", stderr);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
+ in = fopen(modules, "re");
+ if (in = NULL && errno != ENOENT) {
+ fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname!\n", kernel.release);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+
+ ret = write_tmpfile(in, out);
+
+finish:
+ if (in)
+ fclose(in);
+ if (out)
+ fclose(out);
+ return ret;
+}
+
+const struct kmod_cmd kmod_cmd_static_nodes = {
+ .name = "static-nodes",
+ .cmd = do_static_nodes,
+ .help = "outputs the static-node information of the currently running kernel",
+};
--
1.8.2.1
^ permalink raw reply related
* Re: [PATCH v2] tools: add static-nodes tool
From: Lucas De Marchi @ 2013-04-15 23:20 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1365812145-3859-1-git-send-email-teg@jklm.no>
Hi Tom,
On Fri, Apr 12, 2013 at 9:15 PM, Tom Gundersen <teg@jklm.no> wrote:
> This tool reads modules.devname from the current kernel directory and outputs
> the information.
>
> For now only the tmpfiles.d(5) format is supported, but more could easily be
> added in the future if there is a need.
>
> When booting with systemd, the new tool is called at boot to instruct
> systemd-tmpfiles to create the necessary static modules before starting
> systemd-udevd.
>
> This means nothing but kmod needs to reads the private files under /lib/modules/.
For me this would be the main goal of this patch or anything similar to this.
>
> Cc: <linux-hotplug@vger.kernel.org>
> Cc: <systemd-devel@lists.freedesktop.org>
> ---
>
> v2: adressed concerns raised by Dave, and made the tool a bit more generic so
> more output formats may be added in the future as suggested by Lucas. Also
> included the systemd unit file to hook this up with systemd.
>
> Makefile.am | 20 ++++-
> configure.ac | 8 ++
> tools/kmod-static-nodes.service.in | 16 ++++
> tools/kmod.c | 1 +
> tools/kmod.h | 1 +
> tools/static-nodes.c | 163 +++++++++++++++++++++++++++++++++++++
> 6 files changed, 207 insertions(+), 2 deletions(-)
> create mode 100644 tools/kmod-static-nodes.service.in
> create mode 100644 tools/static-nodes.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 9feaf96..333e861 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -36,6 +36,9 @@ SED_PROCESS = \
> %.pc: %.pc.in Makefile
> $(SED_PROCESS)
>
> +%.service: %.service.in Makefile
> + $(SED_PROCESS)
> +
> LIBKMOD_CURRENT=4
> LIBKMOD_REVISION=2
> LIBKMOD_AGE=2
> @@ -88,6 +91,17 @@ pkgconfig_DATA = libkmod/libkmod.pc
> EXTRA_DIST += libkmod/libkmod.pc.in
> CLEANFILES += libkmod/libkmod.pc
>
> +if HAVE_SYSTEMD
> +systemdsystemunit_DATA = tools/kmod-static-nodes.service
> +EXTRA_DIST += tools/kmod-static-nodes.service.in
> +CLEANFILES += tools/kmod-static-nodes.service
> +
> +install-data-hook:
> + $(MKDIR_P) $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants
> + ln -sf ../kmod-static-nodes.service \
> + $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants/kmod-static-nodes.service
> +endif
> +
> install-exec-hook:
> if test "$(libdir)" != "$(rootlibdir)"; then \
> $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \
> @@ -109,7 +123,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
> tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
> tools/rmmod.c tools/insmod.c \
> tools/modinfo.c tools/modprobe.c \
> - tools/depmod.c tools/log.h tools/log.c
> + tools/depmod.c tools/log.h tools/log.c \
> + tools/static-nodes.c
> tools_kmod_LDADD = libkmod/libkmod-util.la \
> libkmod/libkmod.la
>
> @@ -211,7 +226,8 @@ testsuite-distclean:
> DISTCLEAN_LOCAL_HOOKS += testsuite-distclean
> EXTRA_DIST += testsuite/rootfs-pristine
>
> -DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib
> +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib \
> + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
>
> distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
>
> diff --git a/configure.ac b/configure.ac
> index 566b317..af5ed52 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -76,6 +76,13 @@ AS_IF([test "x$with_zlib" != "xno"], [
> AC_MSG_NOTICE([zlib support not requested])
> ])
>
> +AC_ARG_WITH([systemdsystemunitdir],
> + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
> + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
> +if test "x$with_systemdsystemunitdir" != xno; then
> + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
> +fi
> +AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
>
> #####################################################################
> # --enable-
> @@ -200,6 +207,7 @@ AC_MSG_RESULT([
> compiler: ${CC}
> cflags: ${with_cflags} ${CFLAGS}
> ldflags: ${with_ldflags} ${LDFLAGS}
> + systemdsystemunitdir: ${with_systemdsystemunitdir}
>
> tools: ${enable_tools}
> logging: ${enable_logging}
> diff --git a/tools/kmod-static-nodes.service.in b/tools/kmod-static-nodes.service.in
> new file mode 100644
> index 0000000..be8482e
> --- /dev/null
> +++ b/tools/kmod-static-nodes.service.in
I'm not sure we want the service file to live in kmod repository.
Maybe we could let this in systemd and in kmod we only add the support
to create this type of information?
> @@ -0,0 +1,16 @@
> +# This file is part of kmod.
> +#
> +# kmod is free software; you can redistribute it and/or modify it
> +# under the terms of the GNU Lesser General Public License as published by
> +# the Free Software Foundation; either version 2.1 of the License, or
> +# (at your option) any later version.
> +
> +[Unit]
> +Description=Create list of static nodes to be created in /dev
> +DefaultDependencies=no
> +Before=sysinit.target systemd-static-nodes.service
> +
> +[Service]
> +Type=oneshot
> +ExecStart=/bin/mkdir -p /run/tmpfiles.d
> +ExecStart=@prefix@/bin/kmod static-nodes tmpfiles --output=/run/tmpfiles.d/kmod.conf
The syntax is a bit cumbersome too, but since we still don't have any
command (except from the test-only "list") I think we could let this
as is and change later, before a new release.
IMO it should be kmod static-nodes --format=...
It's ok to implement only the tmpfiles output, though the default
should be an human readable format, just like git commands are.
> diff --git a/tools/kmod.c b/tools/kmod.c
> index ebb8875..347bb7d 100644
> --- a/tools/kmod.c
> +++ b/tools/kmod.c
> @@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
> static const struct kmod_cmd *kmod_cmds[] = {
> &kmod_cmd_help,
> &kmod_cmd_list,
> + &kmod_cmd_static_nodes,
> };
>
> static const struct kmod_cmd *kmod_compat_cmds[] = {
> diff --git a/tools/kmod.h b/tools/kmod.h
> index 80fa4c2..68a646a 100644
> --- a/tools/kmod.h
> +++ b/tools/kmod.h
> @@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
> extern const struct kmod_cmd kmod_cmd_compat_depmod;
>
> extern const struct kmod_cmd kmod_cmd_list;
> +extern const struct kmod_cmd kmod_cmd_static_nodes;
>
> #include "log.h"
> diff --git a/tools/static-nodes.c b/tools/static-nodes.c
> new file mode 100644
> index 0000000..a79fc3d
> --- /dev/null
> +++ b/tools/static-nodes.c
> @@ -0,0 +1,163 @@
> +/*
> + * kmod-static-nodes - manage modules.devname
> + *
> + * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
> + * Copyright (C) 2011-2013 ProFUSION embedded systems
> + * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stddef.h>
> +#include <getopt.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <limits.h>
> +#include <sys/utsname.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include "libkmod-util.h"
> +
> +#include "kmod.h"
> +
> +static const char cmdopts_s[] = "o:h";
> +static const struct option cmdopts[] = {
> + { "output", required_argument, 0, 'o'},
> + { "help", no_argument, 0, 'h'},
> + { },
> +};
> +
> +static void help(void)
> +{
> + printf("Usage:\n"
> + "\t%s static-nodes format [options]\n"
> + "\n"
> + "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
> + "\n"
> + "Options:\n"
> + "\t-o, --output=FILE write output to file\n"
> + "\t-h, --help show this help\n"
> + "\n"
> + "Formats:\n"
> + " tmpfiles the tmpfiles.d(5) used by systemd-tmpfiles.\n",
> + program_invocation_short_name);
> +}
> +
> +static int write_tmpfile(FILE *in, FILE *out) {
> + char buf[4096];
> + int ret = EXIT_SUCCESS;
> +
> + while (fgets(buf, sizeof(buf), in) != NULL) {
> + char devname[PATH_MAX];
> + char type;
> + unsigned int maj, min;
> + int matches;
> +
> + if (buf[0] = '#')
> + continue;
> +
> + matches = sscanf(buf, "%*s %s %c%u:%u", devname, &type, &maj, &min);
> + if (matches != 4 || (type != 'c' && type != 'b')) {
> + fprintf(stderr, "Error: invalid devname entry: %s", buf);
> + ret = EXIT_FAILURE;
> + continue;
> + }
> +
> + fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
> + }
> +
> + return ret;
> +}
> +
> +static int do_static_nodes(int argc, char *argv[])
> +{
> + struct utsname kernel;
> + char modules[PATH_MAX];
> + FILE *in = NULL, *out = stdout;
> + int ret = EXIT_SUCCESS;
> +
> + for (;;) {
> + int c, idx = 0;
> +
> + c = getopt_long(argc - 1, argv + 1, cmdopts_s, cmdopts, &idx);
> + if (c = -1) {
> + break;
> + }
> + switch (c) {
> + case 'o':
> + out = fopen(optarg, "we");
> + if (out = NULL) {
> + fprintf(stderr, "Error: could not create %s!\n", optarg);
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> + break;
> + case 'h':
> + help();
> + goto finish;
> + case '?':
> + ret = EXIT_FAILURE;
> + goto finish;
> + default:
> + fprintf(stderr, "Unexpected commandline option '%c'.\n", c);
> + help();
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> + }
> +
> + if (argc < 2) {
> + help();
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> +
> + if (!streq(argv[1], "tmpfiles")) {
> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
> + help();
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> +
> + if (uname(&kernel) < 0) {
> + fputs("Error: uname failed!\n", stderr);
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> + snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
> + in = fopen(modules, "re");
> + if (in = NULL && errno != ENOENT) {
> + fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname!\n", kernel.release);
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> +
> + ret = write_tmpfile(in, out);
> +
> +finish:
> + if (in)
> + fclose(in);
> + if (out)
> + fclose(out);
> + return ret;
> +}
> +
> +const struct kmod_cmd kmod_cmd_static_nodes = {
> + .name = "static-nodes",
> + .cmd = do_static_nodes,
> + .help = "outputs the static-node information of the currently running kernel",
> +};
> --
Lucas De Marchi
^ permalink raw reply
* Re: [PATCH v2] tools: add static-nodes tool
From: Tom Gundersen @ 2013-04-16 13:10 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1365812145-3859-1-git-send-email-teg@jklm.no>
On Tue, Apr 16, 2013 at 1:20 AM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> Hi Tom,
Hi Lucas,
Thanks for your review!
> On Fri, Apr 12, 2013 at 9:15 PM, Tom Gundersen <teg@jklm.no> wrote:
>> This tool reads modules.devname from the current kernel directory and outputs
>> the information.
>>
>> For now only the tmpfiles.d(5) format is supported, but more could easily be
>> added in the future if there is a need.
>>
>> When booting with systemd, the new tool is called at boot to instruct
>> systemd-tmpfiles to create the necessary static modules before starting
>> systemd-udevd.
>>
>> This means nothing but kmod needs to reads the private files under /lib/modules/.
>
> For me this would be the main goal of this patch or anything similar to this.
Yeah, I agree.
>> Cc: <linux-hotplug@vger.kernel.org>
>> Cc: <systemd-devel@lists.freedesktop.org>
>> ---
>>
>> v2: adressed concerns raised by Dave, and made the tool a bit more generic so
>> more output formats may be added in the future as suggested by Lucas. Also
>> included the systemd unit file to hook this up with systemd.
>>
>> Makefile.am | 20 ++++-
>> configure.ac | 8 ++
>> tools/kmod-static-nodes.service.in | 16 ++++
>> tools/kmod.c | 1 +
>> tools/kmod.h | 1 +
>> tools/static-nodes.c | 163 +++++++++++++++++++++++++++++++++++++
>> 6 files changed, 207 insertions(+), 2 deletions(-)
>> create mode 100644 tools/kmod-static-nodes.service.in
>> create mode 100644 tools/static-nodes.c
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 9feaf96..333e861 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -36,6 +36,9 @@ SED_PROCESS = \
>> %.pc: %.pc.in Makefile
>> $(SED_PROCESS)
>>
>> +%.service: %.service.in Makefile
>> + $(SED_PROCESS)
>> +
>> LIBKMOD_CURRENT=4
>> LIBKMOD_REVISION=2
>> LIBKMOD_AGE=2
>> @@ -88,6 +91,17 @@ pkgconfig_DATA = libkmod/libkmod.pc
>> EXTRA_DIST += libkmod/libkmod.pc.in
>> CLEANFILES += libkmod/libkmod.pc
>>
>> +if HAVE_SYSTEMD
>> +systemdsystemunit_DATA = tools/kmod-static-nodes.service
>> +EXTRA_DIST += tools/kmod-static-nodes.service.in
>> +CLEANFILES += tools/kmod-static-nodes.service
>> +
>> +install-data-hook:
>> + $(MKDIR_P) $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants
>> + ln -sf ../kmod-static-nodes.service \
>> + $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants/kmod-static-nodes.service
>> +endif
>> +
>> install-exec-hook:
>> if test "$(libdir)" != "$(rootlibdir)"; then \
>> $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \
>> @@ -109,7 +123,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
>> tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
>> tools/rmmod.c tools/insmod.c \
>> tools/modinfo.c tools/modprobe.c \
>> - tools/depmod.c tools/log.h tools/log.c
>> + tools/depmod.c tools/log.h tools/log.c \
>> + tools/static-nodes.c
>> tools_kmod_LDADD = libkmod/libkmod-util.la \
>> libkmod/libkmod.la
>>
>> @@ -211,7 +226,8 @@ testsuite-distclean:
>> DISTCLEAN_LOCAL_HOOKS += testsuite-distclean
>> EXTRA_DIST += testsuite/rootfs-pristine
>>
>> -DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib
>> +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib \
>> + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
>>
>> distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
>>
>> diff --git a/configure.ac b/configure.ac
>> index 566b317..af5ed52 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -76,6 +76,13 @@ AS_IF([test "x$with_zlib" != "xno"], [
>> AC_MSG_NOTICE([zlib support not requested])
>> ])
>>
>> +AC_ARG_WITH([systemdsystemunitdir],
>> + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
>> + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
>> +if test "x$with_systemdsystemunitdir" != xno; then
>> + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
>> +fi
>> +AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
>>
>> #####################################################################
>> # --enable-
>> @@ -200,6 +207,7 @@ AC_MSG_RESULT([
>> compiler: ${CC}
>> cflags: ${with_cflags} ${CFLAGS}
>> ldflags: ${with_ldflags} ${LDFLAGS}
>> + systemdsystemunitdir: ${with_systemdsystemunitdir}
>>
>> tools: ${enable_tools}
>> logging: ${enable_logging}
>> diff --git a/tools/kmod-static-nodes.service.in b/tools/kmod-static-nodes.service.in
>> new file mode 100644
>> index 0000000..be8482e
>> --- /dev/null
>> +++ b/tools/kmod-static-nodes.service.in
>
> I'm not sure we want the service file to live in kmod repository.
> Maybe we could let this in systemd and in kmod we only add the support
> to create this type of information?
I don't really mind. For now I'll drop it, and we can agree on where
to put it later.
>> @@ -0,0 +1,16 @@
>> +# This file is part of kmod.
>> +#
>> +# kmod is free software; you can redistribute it and/or modify it
>> +# under the terms of the GNU Lesser General Public License as published by
>> +# the Free Software Foundation; either version 2.1 of the License, or
>> +# (at your option) any later version.
>> +
>> +[Unit]
>> +Description=Create list of static nodes to be created in /dev
>> +DefaultDependencies=no
>> +Before=sysinit.target systemd-static-nodes.service
>> +
>> +[Service]
>> +Type=oneshot
>> +ExecStart=/bin/mkdir -p /run/tmpfiles.d
>> +ExecStart=@prefix@/bin/kmod static-nodes tmpfiles --output=/run/tmpfiles.d/kmod.conf
>
> The syntax is a bit cumbersome too, but since we still don't have any
> command (except from the test-only "list") I think we could let this
> as is and change later, before a new release.
>
> IMO it should be kmod static-nodes --format=...
>
> It's ok to implement only the tmpfiles output, though the default
> should be an human readable format, just like git commands are.
Thanks for the suggestions, makes sense. I resent with these changes.
>> diff --git a/tools/kmod.c b/tools/kmod.c
>> index ebb8875..347bb7d 100644
>> --- a/tools/kmod.c
>> +++ b/tools/kmod.c
>> @@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
>> static const struct kmod_cmd *kmod_cmds[] = {
>> &kmod_cmd_help,
>> &kmod_cmd_list,
>> + &kmod_cmd_static_nodes,
>> };
>>
>> static const struct kmod_cmd *kmod_compat_cmds[] = {
>> diff --git a/tools/kmod.h b/tools/kmod.h
>> index 80fa4c2..68a646a 100644
>> --- a/tools/kmod.h
>> +++ b/tools/kmod.h
>> @@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
>> extern const struct kmod_cmd kmod_cmd_compat_depmod;
>>
>> extern const struct kmod_cmd kmod_cmd_list;
>> +extern const struct kmod_cmd kmod_cmd_static_nodes;
>>
>> #include "log.h"
>> diff --git a/tools/static-nodes.c b/tools/static-nodes.c
>> new file mode 100644
>> index 0000000..a79fc3d
>> --- /dev/null
>> +++ b/tools/static-nodes.c
>> @@ -0,0 +1,163 @@
>> +/*
>> + * kmod-static-nodes - manage modules.devname
>> + *
>> + * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
>> + * Copyright (C) 2011-2013 ProFUSION embedded systems
>> + * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <stddef.h>
>> +#include <getopt.h>
>> +#include <errno.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <limits.h>
>> +#include <sys/utsname.h>
>> +#include <sys/stat.h>
>> +#include <sys/types.h>
>> +#include "libkmod-util.h"
>> +
>> +#include "kmod.h"
>> +
>> +static const char cmdopts_s[] = "o:h";
>> +static const struct option cmdopts[] = {
>> + { "output", required_argument, 0, 'o'},
>> + { "help", no_argument, 0, 'h'},
>> + { },
>> +};
>> +
>> +static void help(void)
>> +{
>> + printf("Usage:\n"
>> + "\t%s static-nodes format [options]\n"
>> + "\n"
>> + "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
>> + "\n"
>> + "Options:\n"
>> + "\t-o, --output=FILE write output to file\n"
>> + "\t-h, --help show this help\n"
>> + "\n"
>> + "Formats:\n"
>> + " tmpfiles the tmpfiles.d(5) used by systemd-tmpfiles.\n",
>> + program_invocation_short_name);
>> +}
>> +
>> +static int write_tmpfile(FILE *in, FILE *out) {
>> + char buf[4096];
>> + int ret = EXIT_SUCCESS;
>> +
>> + while (fgets(buf, sizeof(buf), in) != NULL) {
>> + char devname[PATH_MAX];
>> + char type;
>> + unsigned int maj, min;
>> + int matches;
>> +
>> + if (buf[0] = '#')
>> + continue;
>> +
>> + matches = sscanf(buf, "%*s %s %c%u:%u", devname, &type, &maj, &min);
>> + if (matches != 4 || (type != 'c' && type != 'b')) {
>> + fprintf(stderr, "Error: invalid devname entry: %s", buf);
>> + ret = EXIT_FAILURE;
>> + continue;
>> + }
>> +
>> + fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int do_static_nodes(int argc, char *argv[])
>> +{
>> + struct utsname kernel;
>> + char modules[PATH_MAX];
>> + FILE *in = NULL, *out = stdout;
>> + int ret = EXIT_SUCCESS;
>> +
>> + for (;;) {
>> + int c, idx = 0;
>> +
>> + c = getopt_long(argc - 1, argv + 1, cmdopts_s, cmdopts, &idx);
>> + if (c = -1) {
>> + break;
>> + }
>> + switch (c) {
>> + case 'o':
>> + out = fopen(optarg, "we");
>> + if (out = NULL) {
>> + fprintf(stderr, "Error: could not create %s!\n", optarg);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + break;
>> + case 'h':
>> + help();
>> + goto finish;
>> + case '?':
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + default:
>> + fprintf(stderr, "Unexpected commandline option '%c'.\n", c);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + }
>> +
>> + if (argc < 2) {
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + if (!streq(argv[1], "tmpfiles")) {
>> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + if (uname(&kernel) < 0) {
>> + fputs("Error: uname failed!\n", stderr);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
>> + in = fopen(modules, "re");
>> + if (in = NULL && errno != ENOENT) {
>> + fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname!\n", kernel.release);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + ret = write_tmpfile(in, out);
>> +
>> +finish:
>> + if (in)
>> + fclose(in);
>> + if (out)
>> + fclose(out);
>> + return ret;
>> +}
>> +
>> +const struct kmod_cmd kmod_cmd_static_nodes = {
>> + .name = "static-nodes",
>> + .cmd = do_static_nodes,
>> + .help = "outputs the static-node information of the currently running kernel",
>> +};
>> --
>
>
> Lucas De Marchi
^ permalink raw reply
* [PATCH v3] tools: add static-nodes tool
From: Tom Gundersen @ 2013-04-16 13:12 UTC (permalink / raw)
To: linux-hotplug
This tool reads modules.devname from the current kernel directory and outputs
the information. By default in a human-readable format, and optionally in
machine-readable formats.
For now only the tmpfiles.d(5) format is supported, but more could easily be
added in the future if there is a need.
This means nothing but kmod needs to reads the private files under
/lib/modules/. In particular systemd-udevd can stop reading modules.devname.
Cc: <linux-hotplug@vger.kernel.org>
Cc: <systemd-devel@lists.freedesktop.org>tools: static-nodes
---
v3: dropped the systemd integration for now, we can decide on that separately
added human-readable format and use this by default
added a --format= switch to get the tmpfiles format
Makefile.am | 3 +-
tools/kmod.c | 1 +
tools/kmod.h | 1 +
tools/static-nodes.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 180 insertions(+), 1 deletion(-)
create mode 100644 tools/static-nodes.c
diff --git a/Makefile.am b/Makefile.am
index fe4c769..b1bfd59 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -110,7 +110,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
tools/rmmod.c tools/insmod.c \
tools/modinfo.c tools/modprobe.c \
- tools/depmod.c tools/log.h tools/log.c
+ tools/depmod.c tools/log.h tools/log.c \
+ tools/static-nodes.c
tools_kmod_LDADD = libkmod/libkmod-util.la \
libkmod/libkmod.la
diff --git a/tools/kmod.c b/tools/kmod.c
index ebb8875..347bb7d 100644
--- a/tools/kmod.c
+++ b/tools/kmod.c
@@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
static const struct kmod_cmd *kmod_cmds[] = {
&kmod_cmd_help,
&kmod_cmd_list,
+ &kmod_cmd_static_nodes,
};
static const struct kmod_cmd *kmod_compat_cmds[] = {
diff --git a/tools/kmod.h b/tools/kmod.h
index 80fa4c2..68a646a 100644
--- a/tools/kmod.h
+++ b/tools/kmod.h
@@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
extern const struct kmod_cmd kmod_cmd_compat_depmod;
extern const struct kmod_cmd kmod_cmd_list;
+extern const struct kmod_cmd kmod_cmd_static_nodes;
#include "log.h"
diff --git a/tools/static-nodes.c b/tools/static-nodes.c
new file mode 100644
index 0000000..3d0582a
--- /dev/null
+++ b/tools/static-nodes.c
@@ -0,0 +1,176 @@
+/*
+ * kmod-static-nodes - manage modules.devname
+ *
+ * Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
+ * Copyright (C) 2011-2013 ProFUSION embedded systems
+ * Copyright (C) 2013 Tom Gundersen <teg@jklm.no>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "libkmod-util.h"
+
+#include "kmod.h"
+
+static const char cmdopts_s[] = "o:f:h";
+static const struct option cmdopts[] = {
+ { "output", required_argument, 0, 'o'},
+ { "format", required_argument, 0, 'f'},
+ { "help", no_argument, 0, 'h'},
+ { },
+};
+
+static void help(void)
+{
+ printf("Usage:\n"
+ "\t%s static-nodes [options]\n"
+ "\n"
+ "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
+ "\n"
+ "Options:\n"
+ "\t-f, --format=FORMAT use a machine-readable format\n"
+ "\t-o, --output=FILE write output to file\n"
+ "\t-h, --help show this help\n"
+ "\n"
+ "Formats:\n"
+ " tmpfiles the tmpfiles.d(5) format used by systemd-tmpfiles.\n",
+ program_invocation_short_name);
+}
+
+static void write_human(FILE *out, char module[], char devname[], char type, unsigned int maj, unsigned int min)
+{
+ fprintf(out,
+ "Module: %s\n"
+ "\tDevice node: /dev/%s\n"
+ "\t\tType: %s device\n"
+ "\t\tMajor: %u\n"
+ "\t\tMinor: %u\n",
+ module, devname, (type = 'c') ? "character" : "block", maj, min);
+ return;
+}
+
+static void write_tmpfile(FILE *out, char devname[], char type, unsigned int maj, unsigned int min)
+{
+ fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
+ return;
+}
+
+static int do_static_nodes(int argc, char *argv[])
+{
+ struct utsname kernel;
+ char modules[PATH_MAX];
+ FILE *in = NULL, *out = stdout;
+ bool human_readable = 1;
+ char buf[4096];
+ int ret = EXIT_SUCCESS;
+
+ for (;;) {
+ int c, idx = 0;
+
+ c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
+ if (c = -1) {
+ break;
+ }
+ switch (c) {
+ case 'o':
+ out = fopen(optarg, "we");
+ if (out = NULL) {
+ fprintf(stderr, "Error: could not create %s!\n", optarg);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ break;
+ case 'f':
+ if (!streq(optarg, "tmpfiles")) {
+ fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
+ help();
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ human_readable = 0;
+ break;
+ case 'h':
+ help();
+ goto finish;
+ case '?':
+ ret = EXIT_FAILURE;
+ goto finish;
+ default:
+ fprintf(stderr, "Unexpected commandline option '%c'.\n", c);
+ help();
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ }
+
+ if (uname(&kernel) < 0) {
+ fputs("Error: uname failed!\n", stderr);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+ snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
+ in = fopen(modules, "re");
+ if (in = NULL && errno != ENOENT) {
+ fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname!\n", kernel.release);
+ ret = EXIT_FAILURE;
+ goto finish;
+ }
+
+ while (fgets(buf, sizeof(buf), in) != NULL) {
+ char module[PATH_MAX];
+ char devname[PATH_MAX];
+ char type;
+ unsigned int maj, min;
+ int matches;
+
+ if (buf[0] = '#')
+ continue;
+
+ matches = sscanf(buf, "%s %s %c%u:%u", module, devname, &type, &maj, &min);
+ if (matches != 5 || (type != 'c' && type != 'b')) {
+ fprintf(stderr, "Error: invalid devname entry: %s", buf);
+ ret = EXIT_FAILURE;
+ continue;
+ }
+
+ if (human_readable)
+ write_human(out, module, devname, type, maj, min);
+ else
+ write_tmpfile(out, devname, type, maj, min);
+ }
+
+finish:
+ if (in)
+ fclose(in);
+ if (out)
+ fclose(out);
+ return ret;
+}
+
+const struct kmod_cmd kmod_cmd_static_nodes = {
+ .name = "static-nodes",
+ .cmd = do_static_nodes,
+ .help = "outputs the static-node information of the currently running kernel",
+};
--
1.8.2.1
^ permalink raw reply related
* Re: [PATCH v3] tools: add static-nodes tool
From: Thomas Bächler @ 2013-04-16 13:49 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1366117954-9272-1-git-send-email-teg@jklm.no>
[-- Attachment #1: Type: text/plain, Size: 1971 bytes --]
Am 16.04.2013 15:12, schrieb Tom Gundersen:
> +static void write_human(FILE *out, char module[], char devname[], char type, unsigned int maj, unsigned int min)
[...]
> +static void write_tmpfile(FILE *out, char devname[], char type, unsigned int maj, unsigned int min)
[...]
> +static int do_static_nodes(int argc, char *argv[])
> +{
> + struct utsname kernel;
> + char modules[PATH_MAX];
> + FILE *in = NULL, *out = stdout;
> + bool human_readable = 1;
This code emphasizes that there is actually only one format available
and needs to be changed again when another one is added. Why not
void (*write_output)((FILE *, char[], char[], char, unsigned int,
unsigned int) = write_human;
? Then ...
> + case 'f':
> + if (!streq(optarg, "tmpfiles")) {
> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
> + help();
> + ret = EXIT_FAILURE;
> + goto finish;
> + }
> + human_readable = 0;
> + break;
case 'f':
if (streq(optarg, "tmpfiles")) {
write_output = write_tmpfiles;
}
else {
fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
[...]
}
break;
And in the end:
> + if (human_readable)
> + write_human(out, module, devname, type, maj, min);
> + else
> + write_tmpfile(out, devname, type, maj, min);
write_output(out, module, devname, type, maj, min);
Maybe even add an array with output name and function pointer pairs, so
that we could get a list of available formats using --format=?. For
consistency, --format=human should also work. Just seems nicer to me, in
case someone actually plans to extend this later.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]
^ permalink raw reply
* Re: [PATCH v3] tools: add static-nodes tool
From: Lucas De Marchi @ 2013-04-16 18:51 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1366117954-9272-1-git-send-email-teg@jklm.no>
On Tue, Apr 16, 2013 at 10:49 AM, Thomas Bächler <thomas@archlinux.org> wrote:
> Am 16.04.2013 15:12, schrieb Tom Gundersen:
>> +static void write_human(FILE *out, char module[], char devname[], char type, unsigned int maj, unsigned int min)
>
> [...]
>
>> +static void write_tmpfile(FILE *out, char devname[], char type, unsigned int maj, unsigned int min)
>
> [...]
>
>> +static int do_static_nodes(int argc, char *argv[])
>> +{
>> + struct utsname kernel;
>> + char modules[PATH_MAX];
>> + FILE *in = NULL, *out = stdout;
>> + bool human_readable = 1;
>
> This code emphasizes that there is actually only one format available
> and needs to be changed again when another one is added. Why not
>
> void (*write_output)((FILE *, char[], char[], char, unsigned int,
> unsigned int) = write_human;
>
> ? Then ...
>
>> + case 'f':
>> + if (!streq(optarg, "tmpfiles")) {
>> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + human_readable = 0;
>> + break;
>
> case 'f':
> if (streq(optarg, "tmpfiles")) {
> write_output = write_tmpfiles;
> }
> else {
> fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
> [...]
> }
> break;
>
> And in the end:
>
>> + if (human_readable)
>> + write_human(out, module, devname, type, maj, min);
>> + else
>> + write_tmpfile(out, devname, type, maj, min);
>
> write_output(out, module, devname, type, maj, min);
>
> Maybe even add an array with output name and function pointer pairs, so
> that we could get a list of available formats using --format=?. For
> consistency, --format=human should also work. Just seems nicer to me, in
> case someone actually plans to extend this later.
>
Agree. Otherwise looks good.
Kay, what's your opinion regarding this command? Is this sufficient to
drop CAP_MKNOD from udev?
Lucas De Marchi
^ permalink raw reply
* Re: [PATCH v3] tools: add static-nodes tool
From: Kay Sievers @ 2013-04-16 19:08 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1366117954-9272-1-git-send-email-teg@jklm.no>
On Tue, Apr 16, 2013 at 8:51 PM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> Kay, what's your opinion regarding this command? Is this sufficient to
> drop CAP_MKNOD from udev?
Sounds all good to me.
Kay
^ permalink raw reply
* Re: [PATCH v3] tools: add static-nodes tool
From: Tom Gundersen @ 2013-04-16 20:32 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <1366117954-9272-1-git-send-email-teg@jklm.no>
On Tue, Apr 16, 2013 at 3:49 PM, Thomas Bächler <thomas@archlinux.org> wrote:
> Am 16.04.2013 15:12, schrieb Tom Gundersen:
>> +static void write_human(FILE *out, char module[], char devname[], char type, unsigned int maj, unsigned int min)
>
> [...]
>
>> +static void write_tmpfile(FILE *out, char devname[], char type, unsigned int maj, unsigned int min)
>
> [...]
>
>> +static int do_static_nodes(int argc, char *argv[])
>> +{
>> + struct utsname kernel;
>> + char modules[PATH_MAX];
>> + FILE *in = NULL, *out = stdout;
>> + bool human_readable = 1;
>
> This code emphasizes that there is actually only one format available
> and needs to be changed again when another one is added. Why not
>
> void (*write_output)((FILE *, char[], char[], char, unsigned int,
> unsigned int) = write_human;
>
> ? Then ...
>
>> + case 'f':
>> + if (!streq(optarg, "tmpfiles")) {
>> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + human_readable = 0;
>> + break;
>
> case 'f':
> if (streq(optarg, "tmpfiles")) {
> write_output = write_tmpfiles;
> }
> else {
> fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
> [...]
> }
> break;
>
> And in the end:
>
>> + if (human_readable)
>> + write_human(out, module, devname, type, maj, min);
>> + else
>> + write_tmpfile(out, devname, type, maj, min);
>
> write_output(out, module, devname, type, maj, min);
>
> Maybe even add an array with output name and function pointer pairs, so
> that we could get a list of available formats using --format=?. For
> consistency, --format=human should also work. Just seems nicer to me, in
> case someone actually plans to extend this later.
Thanks for the suggestions Thomas. I implemented most of them, so now
it should be a lot simpler to extend this in the future.
The only thing I skipped was the --format=? idea, as this info is
already in the help output, and I'm not sure how useful it is to
parse. That said, it could easily be added follow-up patch if there is
a need for it.
-t
^ permalink raw reply
* Lenovo IdeaPad S206
From: Steve White @ 2013-04-26 8:46 UTC (permalink / raw)
To: linux-hotplug
[-- Attachment #1: Type: text/plain, Size: 2003 bytes --]
Hi,
My new Lenovo IdeaPad S206 has a special button ("OneKey recovery system"
button) that I wanted to re-map to a sleep button. I did this, and it
works well. There is also a QS key, that one could profitably re-map.
Along the way realized that the generic IdeaPad mappings of the Ubuntu 12.10
distro are largely incompatible with the keys on this computer.
So I set out to remedy that.
I'm not sure I'm following best practices though. In particular, should
existing IdeaPad rules be restricted, or should the mappings be overridden?
I have some evidence that the mappings here should also work for the S200,
but I'm pretty sure they *aren't* appropriate for the S205.
________________________________
$ cat /sys/class/dmi/id/sys_vendor
LENOVO
$ cat /sys/class/dmi/id/product_name
2638
$ cat /sys/class/dmi/id/product_version
Lenovo IdeaPad S206
________________________________
The OneKey button on this machine is perfect for a sleep button:
it is easily accessible, but impossible to press accidentally.
To simply re-map the OneKey button, I first observed:
A 0x10 press-release pair is emitted if the button is given a substantial
press, and released. After about 3 sec of continuous pressing,
a 0x11 press-release pair is emitted.
I put a rule like this under "keyboard_modulecheck":
________________________________
ENV{DMI_VENDOR}=="LENOVO*", KERNELS=="input*", ATTRS{name}=="Ideapad extra buttons", ATTR{[dmi/id]product_version}=="*S206|*S200", RUN+="keymap $name 0x10 sleep 0x11 hibernate"
________________________________
For the other keys, I have made a keymap file, which at least gets the proper
mappings going. I'm not sure if I really improved anything. See attached.
For one thing, some of the keys don't seem to make scan codes on any device
(the camera key on the F9 key.) Some seem to work regardless of how I map
them -- I guess that means they're going straight to hardware and the
system just reads the hardware state.
I'll be glad to hear what you think!
[-- Attachment #2: udev-db.txt.gz --]
[-- Type: application/x-gunzip, Size: 14526 bytes --]
[-- Attachment #3: lenovo-ideapad-s206 --]
[-- Type: text/plain, Size: 615 bytes --]
# key codes on Lenovo IdeaPad S206, and presumably the S200
0x81 reserved # disable lenovo-ideapad mapping
0xB9 reserved # disable lenovo-ideapad mapping
0xBA reserved # disable lenovo-ideapad mapping
0xF1 f6 # on F6 touchpad toggle (disabled)
0x83 rfkill # on F7 handled in module-lenovo-ideapad-s206
0xCE micmute # on F8
#???? camera # on F9 can't find this in udev
0xDB switchvideomode # on F10
0xF0 display_off # on F11
0xCC brightnessdown # on F12
0xD4 brightnessup # on ins
0x82 unknown # QS key
^ permalink raw reply
* Re: Lenovo IdeaPad S206
From: Steve White @ 2013-04-27 16:15 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <20130426084624.GA28942@iota>
[-- Attachment #1: Type: text/plain, Size: 946 bytes --]
Hi,
In the previous post, I had confused the "win" key with the "switch video"
key. This is corrected now. See attached.
I still have several questions:
switch video
------------
The key meant to switch video (mod F10) produces two scan codes.
In man showkey, there are some remarks, but I don't know what they mean.
$ keymap -i /input/event4
scan code: 0xDB
scan code: 0x19
(both scancodes emitted together only once on press,
nothing on longer hold, nothing on release)
$ showkey -s
0x19 on press
0x99 on release
** What does this mean, and how are such results to be used with udev rules?
camera off-on
-------------
I can't see that this key (mod F9) generates anything on any device,
although it does in fact seem to kill the USB-based camera.
** Any ideas?
kill key
----------
The kill key (mod F4) very effectively kills any terminal it's running
in, so I have yet to determine what scan codes it generates.
** Any ideas?
[-- Attachment #2: lenovo-ideapad-s206 --]
[-- Type: text/plain, Size: 683 bytes --]
# key codes on Lenovo IdeaPad S206, and presumably the S200
0x81 reserved # disable lenovo-ideapad mapping
0xB9 reserved # disable lenovo-ideapad mapping
0xBA reserved # disable lenovo-ideapad mapping
0xF1 f6 # mod F6 touchpad toggle (disabled)
0x83 rfkill # mod F7 handled in module-lenovo-ideapad-s206
0xCE micmute # mod F8
#???? camera # mod F9 can't find this in udev
#???? switchvideomode # mod F10 emits multiple scancodes?
0xF0 display_off # mod F11
0xCC brightnessdown # mod F12
0xD4 brightnessup # mod ins
0xDB menu # win key
0x82 unknown # QS key
^ permalink raw reply
* Inhibiting plug and play
From: Phillip Susi @ 2013-06-18 17:45 UTC (permalink / raw)
To: linux-hotplug
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Various tools, but most notably partitioners, manipulate disks in such
a way that they need to prevent the rest of the system from racing
with them while they are in the middle of manipulating the disk.
Presently this is done with a hodge podge of hacks that involve
running some script or executable to temporarily hold off on some
aspects ( typically only auto mounting ) of plug and play processing.
Which one depends on whether you are running hal, udisks, udisks2, or
systemd.
There really needs to be a proper way at a lower level, either udev,
or maybe in the kernel, to inhibit processing events until the tool
changing the device has finished completely. The question is, should
this be in the kernel, or in udev, and what should the interface be?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQEcBAEBAgAGBQJRwJylAAoJEJrBOlT6nu75TlAH/1Eso89Jta4AFn/ynYZUWwVD
xS1Nm8ZbRHQizBFmv5rq5Yunr6XUcUQlux9EeG81QwgJ2mgOAk3XE2ldzOp0lUei
cqQYsrdWKHXz8ZXpNG1Jsgw77EUyrs39Z6NmNC+X1AcFbzxRXplGMTJfRSWtW3bw
Ngi8MCjKZOx/qNzUcyZnR3tdAF0veLHWtr7j5XvgO+/iomnAxIOcYiSCv1OeDMdX
SCx8bULT4/LaRWzbcmpzmh1irMsXavrOwuPzIGBTdMKhByyxnwxiOdIyhOs1OJda
059zK7CxMNidD37ON9hMyMtYz5BeCzZmPJdJ6Ef4G7ZrH++xiI4cGvgVOClP6vI=Ym1b
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: Inhibiting plug and play
From: Greg KH @ 2013-06-18 17:55 UTC (permalink / raw)
To: linux-hotplug
In-Reply-To: <51C09CA5.6020902@ubuntu.com>
On Tue, Jun 18, 2013 at 01:45:09PM -0400, Phillip Susi wrote:
> Various tools, but most notably partitioners, manipulate disks in such
> a way that they need to prevent the rest of the system from racing
> with them while they are in the middle of manipulating the disk.
> Presently this is done with a hodge podge of hacks that involve
> running some script or executable to temporarily hold off on some
> aspects ( typically only auto mounting ) of plug and play processing.
> Which one depends on whether you are running hal, udisks, udisks2, or
> systemd.
>
> There really needs to be a proper way at a lower level, either udev,
> or maybe in the kernel, to inhibit processing events until the tool
> changing the device has finished completely. The question is, should
> this be in the kernel, or in udev, and what should the interface be?
What events are you wishing to inhibit? And who is in control of them?
thanks,
greg k-h
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox