Age | Commit message (Collapse) | Author |
|
|
|
Netlink will never get out-of-order and we just depend on it from
now on. Udevsend messages will have no effect if they contain a
sequence number (SEQNUM).
Thanks to Bastian Blank <waldi@debian.org>, for the debugging session
which identified a bug where the timeouts are not working if
inotify was not available. All the timeout handling is removed
now and this issue should be solved.
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
RUN="socket:<name>" will send the environment in the kernel uevent
format to the named destination. Using the socket instead of the program
to pass the hotplug events to the HAL daemon, cuts down the running
time of udevstart from 0.8 to 0.4 seconds on my box.
env -i ACTION=add DEVPATH=/block/hda/hda1 strace -s10000 ./udev block
sendto(3, "add@/block/hda/hda1\0
ACTION=add\0DEVPATH=/block/hda/hda1\0UDEV_LOG=3\0
ID_TYPE=disk\0ID_MODEL=HTS726060M9AT00\0ID_SERIAL=MRH401M4G6UM9B\0
ID_REVISION=MH4OA6BA\0ID_BUS=ata\0ID_PATH=pci-0000:00:1f.1-ide-0:0\0
ID_FS_USAGE=other\0ID_FS_TYPE=swap\0ID_FS_VERSION=2\0
ID_FS_UUID=9352cfef-7687-47bc-a2a3-34cf136f72e1\0
ID_FS_LABEL=ThisIsSwap\0ID_FS_LABEL_SAFE=ThisIsSwap\0
DEVNAME=/dev/hda1\0"
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
Allow to override some parameters by environment keys.
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
Controls the behavior of the running daemon. Currently only stopping and starting
of the execution queue is supported.
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
|
|
|
|
|
|
|
|
If udevsend is called from the commandline the env may be too
big to fit in our buffer and we tag the message.
|
|
If we take over the hotplug call and manage the events we don't need
to call the event fake script in dev.d/. Just set all expected values
to the new network interface name and call hotplug.d/. This way the
device renaming is completely handled inside of udev and userspace
can't get confused.
|
|
|
|
Accept event without a subsystem and pass it through udevd.
Pass empty environment while starting udevd.
|
|
|
|
This will prevent a loop, if udev sends events back into the
daemon.
|
|
|
|
Make _all_ hotplug variables available to the forked udev,
the udev callouts and the udev dev.d/ scripts. We put the
whole environment into a buffer and send it over the udevd
socket. udevd recreates *envp[] and passes it to the exec().
|
|
This makes the udev operation completely lockless by storing a
file for every node in /dev/.udevdb/* This solved the problem
with deadlocking concurrent udev processes waiting for each other
to release the file lock under heavy load.
|
|
|
|
|
|
Change to the same timeout loop we use in the rest of the code. Change
some comments and names to be more descriptive.
I'm mostly finished with the overall cleanup. I will post a new patch
for the udevd-nofork experiment, which will be much smaller now.
|
|
Seems that we never closed the opened syslog.
Here is a patch to do this in all our binaries.
|
|
selinux wants a clean fd set, so better close all open fds
|
|
The kernel will use a u64 for the sequence number, so we want the same.
|
|
On Tue, May 11, 2004 at 04:54:44PM -0700, Greg KH wrote:
> On Tue, May 11, 2004 at 01:16:41PM +0200, Kay Sievers wrote:
> > Hi,
> > the execution of udev depends on the proper fuction of udevd, the
> > serializing daemon. If we can't connect to udevd within a 20 second we
> > give up and the request to create a node is lost. Hope this never happens,
> > but a broken udevd may prevent udev from working.
> >
> > What do you think? Should we call the udev binary directly from udevsend
> > instead of discarding the event? This way we would create the node, regardless
> > of the state of udevd. It would be 20 seconds later and maybe not in the right
> > sequence order - but the node will propably be there.
> >
> > Does it sound sane? What do you think?
>
> That sounds like a good "failsafe" thing to do.
Here we go:
Add a fallback udev call to udevsend. If udevsend is unable to send the
event to udevd, we call the udev binary instead of doing nothing and exiting.
|
|
here is a patch on top of your nice improvements.
I fixed the whitespace and it hopefully fixes the stupid timestamp bug in
udevd. Some stupid OS sets the hwclock to localtime and linux changes it
to UTC while starting. If any events are pending they may be delayed by
the users time distance from UTC :) So we use the uptime seconds now.
|
|
Here we replace the various fgets() with a mmap() call for the config
file reading, due to the reported performance problems with klibc.
Thanks to Patrick's testing, it makes a very small, close to nothing
speed gain for libc users, but a 6 times speed increase for klibc users
with a 1000 line config file.
I've created a udev_lib.[hc] for this and also moved all the generic
stuff from udev.h in there and uninlined the functions.
|
|
Here I try to make the style a bit more consistant in the different
files, so that new patches just copy the 'right' one :)
Some "magic" numbers are replaced and udevtest.c is catched up with udev.
|
|
Here we truncate our input strings from the environment to our
defined limit. It's a bit theroretical but better check for it.
It cleans up some magic length definitions and removes the code
duplication in udev, udevtest and udevsend.
udevd needs to be killed after installation, cause the message size
is changed with this patch.
Should we do this with the 'make install', like we do with the '.udevdb'?
|
|
On Tue, Feb 24, 2004 at 11:50:52PM +0100, Kay Sievers wrote:
> Here is the first step towards a safer string handling.
> More will follow, but for now only the easy ones :)
>
> Thanks to all who pointed this out. strncat() isn't a nice function. We
> all should remember that the destination string is not terminated if the
> given lenght is shorter than the strlen of the source string.
>
> And shame on the various implementers of strfieldcat() I found in the
> unapplied patches on this list, it's not really better than strncpy()
> and hides the real problem.
Hmm, bk didn't checked in one file, maybe I edited it again as root.
Nevermind, here is the more complete version.
|
|
|
|
|
|
Here is a small improvement. We check for the type of message we receive
and udevsend seems not to need all the credential setup stuff, the
kernel will fill it for us.
udevd now refuses to start as non root, cause it doesn't make any sense.
|
|
Here is the badly needed client authorization for udevd.
Since we switched to abstract namespace sockets, we are unable to
control the access of the socket by file permissions.
So here we send a ancillary credential message with every datagram,
to be able to verify the uid of the sender. The sender can't fake the
credentials, cause the kernel doesn't allow it for non root users.
udevd is still working with klibc here :)
|
|
On Mon, Feb 09, 2004 at 05:41:15AM +0100, Kay Sievers wrote:
> It seems that today was just another udev-sunday for me :)
>
> Here is a working patch to compile udevd with klibc.
>
> It's sweet the static binary takes 6 kbytes and it runs
> with only 80 kbytes virtual memory.
>
> I changed a few peaces and added a siginterrupt.c file to klibc.
> We may check with hpa to get the changes upstream?
So here is the next try :)
hpa, for good reason, didn't like my changes to klibc.
He will dump signal() completely from klibc instead, so here we switch to
sigaction() and keep udevd working with klibc.
|
|
Also introduce boolean type for config file to use.
|
|
On Fri, Feb 06, 2004 at 01:08:24AM -0500, Chris Friesen wrote:
>
> Kay, you said "unless we can get rid of _all_ the threads or at least
> getting faster, I don't want to change it."
>
> Well how about we get rid of all the threads, *and* we get faster?
Yes, we are twice as fast now on my box :)
> This patch applies to current bk trees, and does the following:
>
> 1) Switch to DGRAM sockets rather than STREAM. This simplifies things
> as mentioned in the previous message.
>
> 2) Invalid sequence numbers are mapped to -1 rather than zero, since
> zero is a valid sequence number (I think). Also, this allows for real
> speed tests using scripts starting at a zero sequence number, since that
> is what the initial expected sequence number is.
>
> 3) Get rid of all threading. This is the biggie. Some highlights:
> a) timeout using setitimer() and SIGALRM
> b) async child death notification via SIGCHLD
> c) these two signal handlers do nothing but raise volatile flags,
> all the
> work is done in the main loop
> d) locking no longer required
I cleaned up the rest of the comments, the whitespace and a few names to match
the whole thing. Please recheck it. Test script is switched to work on subsystem
'test' to let udev ignore it.
|
|
It seems that the guys are no longer differ about the right size of the
socket address :)
The kernel simply takes all bytes until the specified length as the name,
so the real length should be enough.
|
|
As Chris Friesen <chris_friesen@sympatico.ca> suggested, here we switch
the unix domains socket path to abstract namespace and get rid of the
socket file in the filesystem.
Hey, this was new to me today. So here a few words:
Linux supports a abstract namespace for sockets. We don't need a
physical file on the filesystem but only a unique string magically
starting with the '\0' character.
strace with real file:
connect(3, {sa_family=AF_UNIX, path="/udev/.udevd.sock"}, 110)
strace with abstract namespace:
connect(3, {sa_family=AF_UNIX, path=@udevd}, 110)
|
|
This patch allows udevsend to be called by the user and not only by the
kernel with its SEQNUM. If no SEQNUM is given, we move the event straight
to the exec queue and don't look if something is missing.
I don't know if this is really needed, but some people seem trying to
send events trough udevd instead of calling udev directly with their
scripts and confuse the reorder logic with that.
So at least, we may remove this source of confusion and udevsend is much
much faster back than udev itself and it will also block concurrent events
for the same devpath.
|
|
|
|
> I don't mind udevd using glibc, I just want the programs that get run a
> lot of different times (udev and udevsend) to be as small as possible to
> get the best cache results. As udevd sticks around all the time, it's
> not as important. Sound sane to you?
Oh, nice. Good idea.
|
|
problem now.
|
|
name in the syslog.
|
|
> Here is a small cleanup and better Makefile integration.
> udevd and udevsender are now installed. Just switch HOTPLUG_EXEC from ROOT
> to SENDER before install and udevsend will be called.
>
> We may add the location of the socket and lock file to the config,
> if this is needed.
Same patch with a fix for the stack size setting.
|
|
On Thu, Jan 29, 2004 at 04:55:11PM +0100, Kay Sievers wrote:
> On Thu, Jan 29, 2004 at 02:56:25AM +0100, Kay Sievers wrote:
> > On Wed, Jan 28, 2004 at 10:47:36PM +0100, Kay Sievers wrote:
> > > Oh, couldn't resist to try threads.
> > > It's a multithreaded udevd that communicates through a localhost socket.
> > > The message includes a magic with the udev version, so we don't accept
> > > older udevsend's.
> > >
> > > No need for locking, cause we can't bind two sockets on the same address.
> > > The daemon tries to connect and if it fails it starts the daemon.
> > >
> > > We create a thread for every incoming connection, handle over the socket,
> > > sort the messages in the global message queue and exit the thread.
> > > Huh, that was easy with threads :)
> > >
> > > With the addition of a message we wakeup the queue manager thread and
> > > handle timeouts or move the message to the global exec list. This wakes
> > > up the exec list manager who looks if a process is already running for this
> > > device path.
> > > If yes, the exec is delayed otherwise we create a thread that execs udev.
> > > n the background. With the return of udev we free the message and wakeup
> > > the exec list manager to look if something is pending.
> > >
> > > It is just a quick shot, cause I couldn't solve the problems with fork an
> > > scheduling and I wanted to see if I'm to stupid :)
> > > But if anybody with a better idea or more experience with I/O scheduling
> > > we may go another way. The remaining problem is that klibc doesn't support
> > > threads.
> > >
> > > By now, we don't exec anything, it's just a sleep 3 for every exec,
> > > but you can see the queue management by watching syslog and do:
> > >
> > > DEVPATH=/abc ACTION=add SEQNUM=0 ./udevsend /abc
>
> Next version, switched to unix domain sockets.
Next cleaned up version. Hey, nobody wants to try it :)
Works for me, It's funny if I connect/disconnect my 4in1-usb-flash-reader
every two seconds. The 2.6 usb rocks! I can connect/diconnect a hub with 3
devices plugged in every second and don't run into any problem but a _very_
big udevd queue.
|
|
Here is the next round. We have three queues now. All incoming messages
are queued in msg_list and if nothing is missing we move it to the
running_list and exec in the background.
If the exec comes back, it removes the message from the running_list and
frees the message.
Before we exec, we check the running_list if there is a udev running on
the same device path. If yes, we move the message to the delay_list. If
the former exec comes back, we move the message to the running_list and
exec it.
The very first event is delayed now to catch possible earlier sequences,
every following event is executed without delay if no sequence is missing.
The daemon doesn't exit by itself any longer, cause we don't want to
delay every first exec.
I've put a $(PWD) for now in the Makefile for testing this beast. Only
the local binaries are executed, not the /sbin/udev. We can change it
if we are ready for real testing.
And SIGKILL can't be cought, so I removed it from the handler :)
06:58:36 sig_handler: caught signal 15
06:58:36 main: using ipc queue 0x2d548
06:58:37 message is still in the ipc queue, starting daemon...
06:58:37 work: received sequence 3, expected sequence 0
06:58:37 msg_dump_queue: sequence 3 in queue
06:58:37 set_timeout: set timeout in 1 seconds
06:58:37 main: using ipc queue 0x2d548
06:58:37 main: using ipc queue 0x2d548
06:58:37 work: received sequence 1, expected sequence 1
06:58:37 msg_dump_queue: sequence 1 in queue
06:58:37 msg_dump_queue: sequence 3 in queue
06:58:37 msg_dump: sequence 1, 'add', '/block/sda', 'block'
06:58:37 msg_exec: child [8038] created
06:58:37 running_moveto_queue: move sequence 1 [8038] to running queue '/block/sda'
06:58:37 set_timeout: set timeout in 5 seconds
06:58:37 work: received sequence 2, expected sequence 2
06:58:37 msg_dump_queue: sequence 2 in queue
06:58:37 msg_dump_queue: sequence 3 in queue
06:58:37 msg_dump: sequence 2, 'add', '/block/sdb', 'block'
06:58:37 msg_exec: child [8039] created
06:58:37 running_moveto_queue: move sequence 2 [8039] to running queue '/block/sdb'
06:58:37 msg_dump: sequence 3, 'add', '/block/sdc', 'block'
06:58:37 msg_exec: child [8040] created
06:58:37 running_moveto_queue: move sequence 3 [8040] to running queue '/block/sdc'
06:58:37 main: using ipc queue 0x2d548
06:58:37 main: using ipc queue 0x2d548
06:58:37 work: received sequence 4, expected sequence 4
06:58:37 msg_dump_queue: sequence 4 in queue
06:58:37 msg_dump: sequence 4, 'remove', '/block/sdc', 'block'
06:58:37 msg_exec: delay exec of sequence 4, [8040] already working on '/block/sdc'
06:58:37 delayed_moveto_queue: move event to delayed queue '/block/sdc'
06:58:37 msg_exec: child [8043] created
06:58:37 running_moveto_queue: move sequence 4 [8043] to running queue '/block/sdc'
06:58:37 work: received sequence 5, expected sequence 5
06:58:37 msg_dump_queue: sequence 5 in queue
06:58:37 msg_dump: sequence 5, 'remove', '/block/sdb', 'block'
06:58:37 msg_exec: delay exec of sequence 5, [8039] already working on '/block/sdb'
06:58:37 delayed_moveto_queue: move event to delayed queue '/block/sdb'
06:58:37 msg_exec: child [8044] created
06:58:37 running_moveto_queue: move sequence 5 [8044] to running queue '/block/sdb'
06:58:37 main: using ipc queue 0x2d548
06:58:37 main: using ipc queue 0x2d548
06:58:37 work: received sequence 8, expected sequence 6
06:58:37 msg_dump_queue: sequence 8 in queue
06:58:37 set_timeout: set timeout in 5 seconds
06:58:37 work: received sequence 6, expected sequence 6
06:58:37 msg_dump_queue: sequence 6 in queue
06:58:37 msg_dump_queue: sequence 8 in queue
06:58:37 msg_dump: sequence 6, 'remove', '/block/sda', 'block'
06:58:37 msg_exec: delay exec of sequence 6, [8038] already working on '/block/sda'
06:58:37 delayed_moveto_queue: move event to delayed queue '/block/sda'
06:58:37 msg_exec: child [8047] created
06:58:37 running_moveto_queue: move sequence 6 [8047] to running queue '/block/sda'
06:58:37 set_timeout: set timeout in 5 seconds
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8038
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8039
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8040
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8043
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8044
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:38 sig_handler: caught signal 17
06:58:38 sig_handler: exec finished, pid 8047
06:58:38 set_timeout: set timeout in 4 seconds
06:58:38 msg_dump_queue: sequence 8 in queue
06:58:39 main: using ipc queue 0x2d548
06:58:39 main: using ipc queue 0x2d548
06:58:39 work: received sequence 9, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:39 work: received sequence 11, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 msg_dump_queue: sequence 11 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:39 main: using ipc queue 0x2d548
06:58:39 work: received sequence 10, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 msg_dump_queue: sequence 10 in queue
06:58:39 msg_dump_queue: sequence 11 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:39 main: using ipc queue 0x2d548
06:58:39 work: received sequence 13, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 msg_dump_queue: sequence 10 in queue
06:58:39 msg_dump_queue: sequence 11 in queue
06:58:39 msg_dump_queue: sequence 13 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:39 main: using ipc queue 0x2d548
06:58:39 work: received sequence 14, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 msg_dump_queue: sequence 10 in queue
06:58:39 msg_dump_queue: sequence 11 in queue
06:58:39 msg_dump_queue: sequence 13 in queue
06:58:39 msg_dump_queue: sequence 14 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:39 main: using ipc queue 0x2d548
06:58:39 work: received sequence 15, expected sequence 7
06:58:39 msg_dump_queue: sequence 8 in queue
06:58:39 msg_dump_queue: sequence 9 in queue
06:58:39 msg_dump_queue: sequence 10 in queue
06:58:39 msg_dump_queue: sequence 11 in queue
06:58:39 msg_dump_queue: sequence 13 in queue
06:58:39 msg_dump_queue: sequence 14 in queue
06:58:39 msg_dump_queue: sequence 15 in queue
06:58:39 set_timeout: set timeout in 3 seconds
06:58:41 main: using ipc queue 0x2d548
06:58:41 work: received sequence 12, expected sequence 7
06:58:41 msg_dump_queue: sequence 8 in queue
06:58:41 msg_dump_queue: sequence 9 in queue
06:58:41 msg_dump_queue: sequence 10 in queue
06:58:41 msg_dump_queue: sequence 11 in queue
06:58:41 msg_dump_queue: sequence 12 in queue
06:58:41 msg_dump_queue: sequence 13 in queue
06:58:41 msg_dump_queue: sequence 14 in queue
06:58:41 msg_dump_queue: sequence 15 in queue
06:58:41 set_timeout: set timeout in 1 seconds
06:58:42 sig_handler: caught signal 14
06:58:42 sig_handler: event timeout reached
06:58:42 event 8, age 5 seconds, skip event 7-7
06:58:42 msg_dump: sequence 8, 'add', '/block/sdb', 'block'
06:58:42 msg_exec: child [8057] created
06:58:42 running_moveto_queue: move sequence 8 [8057] to running queue '/block/sdb'
06:58:42 msg_dump: sequence 9, 'add', '/block/sdc', 'block'
06:58:42 msg_exec: child [8058] created
06:58:42 running_moveto_queue: move sequence 9 [8058] to running queue '/block/sdc'
06:58:42 msg_dump: sequence 10, 'remove', '/block/sdc', 'block'
06:58:42 msg_exec: delay exec of sequence 10, [8058] already working on '/block/sdc'
06:58:42 delayed_moveto_queue: move event to delayed queue '/block/sdc'
06:58:42 msg_exec: child [8059] created
06:58:42 running_moveto_queue: move sequence 10 [8059] to running queue '/block/sdc'
06:58:42 msg_dump: sequence 11, 'remove', '/block/sdb', 'block'
06:58:42 msg_exec: delay exec of sequence 11, [8057] already working on '/block/sdb'
06:58:42 delayed_moveto_queue: move event to delayed queue '/block/sdb'
06:58:42 msg_exec: child [8060] created
06:58:42 running_moveto_queue: move sequence 11 [8060] to running queue '/block/sdb'
06:58:42 msg_dump: sequence 12, 'remove', '/block/sda', 'block'
06:58:42 msg_exec: child [8061] created
06:58:42 running_moveto_queue: move sequence 12 [8061] to running queue '/block/sda'
06:58:42 msg_dump: sequence 13, 'add', '/block/sda', 'block'
06:58:42 msg_exec: delay exec of sequence 13, [8061] already working on '/block/sda'
06:58:42 delayed_moveto_queue: move event to delayed queue '/block/sda'
06:58:42 msg_exec: child [8062] created
06:58:42 running_moveto_queue: move sequence 13 [8062] to running queue '/block/sda'
06:58:42 msg_dump: sequence 14, 'add', '/block/sdb', 'block'
06:58:42 msg_exec: delay exec of sequence 14, [8057] already working on '/block/sdb'
06:58:42 delayed_moveto_queue: move event to delayed queue '/block/sdb'
06:58:42 msg_exec: child [8063] created
06:58:42 running_moveto_queue: move sequence 14 [8063] to running queue '/block/sdb'
06:58:42 msg_dump: sequence 15, 'add', '/block/sdc', 'block'
06:58:42 msg_exec: delay exec of sequence 15, [8058] already working on '/block/sdc'
06:58:42 delayed_moveto_queue: move event to delayed queue '/block/sdc'
06:58:42 msg_exec: child [8064] created
06:58:42 running_moveto_queue: move sequence 15 [8064] to running queue '/block/sdc'
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8057
06:58:43 sig_handler: exec finished, pid 8058
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8059
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8060
06:58:43 sig_handler: exec finished, pid 8061
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8062
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8063
06:58:43 sig_handler: caught signal 17
06:58:43 sig_handler: exec finished, pid 8064
|
|
Trivial style cleanup, to be consistent.
And add chdir("/") to the daemon so one can umout its filesystem,
while we are running :)
|