About

Michael Zucchi

 B.E. (Comp. Sys. Eng.)

Tags

android (44)
beagle (63)
biographical (85)
blogz (4)
business (1)
code (59)
cooking (30)
dez (7)
dusk (30)
ffts (3)
forth (3)
free software (4)
games (32)
gloat (2)
globalisation (1)
gnu (4)
graphics (16)
gsoc (4)
hacking (425)
haiku (2)
horticulture (10)
house (23)
hsa (6)
humour (7)
imagez (28)
java (221)
java ee (3)
javafx (48)
jjmpeg (72)
junk (3)
kobo (15)
libeze (7)
linux (5)
mediaz (27)
ml (15)
nativez (8)
opencl (119)
os (17)
parallella (97)
pdfz (8)
philosophy (26)
picfx (2)
playerz (2)
politics (7)
ps3 (12)
puppybits (17)
rants (135)
readerz (8)
rez (1)
socles (36)
termz (3)
videoz (6)
wanki (3)
workshop (3)
zcl (1)
zedzone (18)
Tuesday, 29 January 2019, 09:39

Memory, IPC. Tradeoffs.

I've been playing around with a few ideas for libeze but it's not gotten anywhere particular yet. I'm getting stuck on the tradeoffs - even though they don't really matter much.

IPC - Serialisation

It started when I read a rant against serialsiation formats; this I agree with. An internal blob isn't that important but I thought i'd look at some to see if any where useful.

XDR

This is old and simple. It was written by a smart bunch from a smart company from a time when smarter decisions were being made about things like this. The biggest drawback is the big-endian nature, but I could always fudge it and just pass native-endian values and call it RDX or something.

I then had the bright idea of being able to decode structures without any additional memory - merely referencing the packet data. But this creates a couple of additional areas where it would diverge: strings would need to include their trailing nul byte to be useful, and embedded arrays might need specific alignment.

So really, it's not quite RFX anymore either. OTOH R is listed as `supporting' XDR but it's version is modified as well.

XDR is also not self describing but descriminated descriminated unions go a long way to handling versioning which is the main reason I might want such a feature.

ASN.1 BER/DER/CER/PER

There is actually some stuff I quite like about BER. It's self describing and relatively compact.

There's a lot that makes it a pain. A full implementation needs to implement a lot as it is vastly over-engineered; this means it is complex and likely to be buggy. REAL numbers are encoded in a way that needs a lot of fiddling about on either end.

It's not all wrong, but it's not too right either.

Protocol buffers

I've had the misfortune to have to deal with these for work.

The actual on-wire format isn't too bad. It's not self-describing but you can safely skip buts you don't understand. It's relatively compact. It's also a bit pointless.

The SDK is a complete pile of shit though. The Java implementation compiles gigantic code that runs fucking slow (List<Float>???). It moves all of the protocol variance decisions into the calling code so it's a messy pain to use as well: sort of negating one of the reasons to use a self-describing format in the first place.

For work I wrote my own decoder when I could - a couple of dozen lines of code. But some projects use such complex structures you end up with a gigantic library to decode it (supplied by protoc) and then a gigantic library to marshall it's output into something usable (that you write by hand).

JSON

It's just fucked. Even the same implementation can't decide how to canonically encode empty or single-element arrays, null or emptry strings, and so on.

It's not very compact and while it's realtively simple to parse it's not trivial either.

And then it's clumsy as fuck to use from any non-dynamic language. Getting fields you even know are there is a pain. Handling variances is worse.

CBOR (and half a dozen others)

Well this is just binary JSON. It fixes the end-to-end canonical encodingness and is arguably faster to parse but it's still going to be clumsy to use and not significnatly more compact except for arrays of small integers.

It also has some questionable design decisions and is already bloating with a dozen extension types - it seems like it wants to look as 'valid' as ASN.1/BER but with an even messier encoding scheme.

The whole "look we have a completely-defined 256 element jump table" is just a fucking weird thing to have in a serialisation format RFC. And nothing says simple like 256 right? What on earth is that even about?

SDXF

This is another RFC I came across along the way - not sure how as it just took me 10 minutes to re-find it.

Honestly it's a weird arsed format that looks like someone's internal stuff they decided to publish. I can't imagine anyone uses it.

I would note that with some small changes the meta-data I have can support pretty much all of these formats.

But I pretty much wasted a few hours of my life on this. After all that fucking around I would be inclined to just dump structures around if i didn't need strings! I have several desirable features which can't be covered by a single format anyway, although two would probably suffice.

e.g. here's some use cases.

Ok, maybe 3 formats. Although i'm not really interested in the 3rd at the moment.

The Local IPC case is basically a subset of XDR, aside from the aforementioned tweaks.

The rest? Plenty there but none are a great fit.

Memory

Memory allocation in C is simple enough but managing it can be a bit of a pain, hence pools.

Another issue is that a given implementation enforces certain constraints which can waste (significant) memory: for example on an amd64 platform, malloc() allocates at least 32-bytes for each allocation even if it's only a 5 byte string (this is is the minimum required to track free blocks). And every allocation also saves a size_t before the memory block so it knows how big it was when you call free: when you have many small objects of the same size this wastes a lot of memory. A more subtle problem is that memalign() must also save this size, so that if you start allocating many aligned structures you start to quickly get a holey memory.

Dealing with strings in general is a bit of a pain (and a source of many security issues) and only the GNU-sepcific obstack really provides any good support for it.

So I experimented with a few ideas.

High level internals of malloc() & free()

An implementation of this pair basically all work the same.

malloc will find a block of free memory big enough to hold the requested size plus space to hold that size. Some area of this block will be reserved for the allocation and the free block will either be reduced by the same amount, or removed (if the whole block is used).

free() will take the saved size and address and mark it as free. As part of this process it will find out if there are other free blocks immediately adjacent to this new free block and coalesce them into a single larger block if so. There are only 4 cases: isolated free, adjacent before, adjacent after, adjacent before and after.

The memory in the free block itself is used to hold the controlling structures required for the two functions. They cease to exist once the memory is allocated.

Additionally, for finding blocks there are two basic strategies:

first-fit

The free list is stored sorted by address. It is scanned from the start and the first block with enough memory to fit the request is used.

best-fit

The free list is sorted by size. It is scanned from a block which is larger-or-equal to the desired size and the first one is used.

Each has their benefits and trade-offs.

first-fit may be slower to allocate but will more effectively utilise memory - less total memory will be required. I did some basic and non-exhaustive testing that gave me this result. It can also be implemented with very simple code and the same list can be used for performing coalescing.

best-fit can be faster to allocate as you find the correct block directly. Based on my testing it requires more total memory. Additional data structures are required to implement the free() operation.

So finally, these choices any other indices arequired determine the data structures required to track and find the free blocks, and thus determine the minimum allocation size.

GNU libc malloc() uses a size_t for the block size, a double-linked list for the free list, and another size_t at the end of the free block for fast coalescing. So the minimum size of a free block (and hence the minimum allocation size) is 32 bytes on a 64-bit system 16 bytes on a 32-bit system. I think it uses best-fit.

AllocMem()/FreeMem()

The first memory allocator I knew was the one from AmigaOS via AllocMem(). This only has a single constraint in that the minimum allocation is 8 bytes. There is no fixed allocation overhead to store the allocated size as you need to also provide the size to FreeMem(). Free nodes are stored as a single-linked list.

It takes very little code to implement this and it utilises memory very well (it can't really be more utilised than 100%).

The drawback is that both allocation and deallocation are O(N) operations since both have to walk the free list. I guess 'slow' is relative as they did ok on a 7Mhz CPU with a global(!) shared memory list. But because one knew it was slow you wrote code to avoid it (SunOS also had a dreadfully slow allocator so it wasn't unique in this regard).

On memory constrainted systems I think it's still a useful technique. free() can also be accelerated somewhat by using a balanced tree by bumping up the minimum allocation.

ez-page-alloc

So the first idea I played with was a page allocator which would underly more specific algorithms. The idea would be that it would require the free size like FreeMem() and so allow pages to be allocated with no overhead and no wastage.

I didn't really get anywhere with this and then revisited it in a different way later on (ez-alloc-alloc).

ez-string-alloc

I diverted for a little while trying to work on a string allocator. It would take some number of pages as an allocation block. In this case there would be no way to free individual strings. But they wouldn't require any alignment or size overhead either.

Strings can be built a character at a time, and large strings are moved over to their own block.

Allocation can be made very fast by only searching the most recent block. Or it can be made more compact by searching all blocks. Or some trade-off in-between.

I think this could be the basis of a good no-free high performance pool allocator.

On the way I came across apr_pool and it's code is pretty ugly and I was suprised it didn't support free() of individual allocations, given how complex it is.

ez-fixed-alloc

I've written multiple memory allocators in the past and one of the easiest and most useful is an allocator for fixed-sized blocks. It was particularly important for glib container classes.

Free is trivial as you already know the size and never have to coalesce free blocks and you can just plop the memory into the head of a single-linked list.

Allocate is likewise as trivial as a single-linked list.

However you end up having to have multiple allocators for each size so you just end up with a lot of wasted space anyway.

Eh I dunno, i'm thinking about whether this one is useful at all.

ez-alloc-alloc

I had a look at an allocator that could support memalign() without wastage. And basically do-away with a need for a special page allocator.

This is basically a tree-based version of AlocMem()/FreeMem() but with a very large alignment. Because there is no size overhead all memory is used and allocating new page-aligned pages doesn't leave unfillable holes.

Performance problems with the algorithm would be mitigated by having fewer, larger allocations and leaving the internal allocations to other more specific algorithms.

Still I dunno, it's many drawbacks in this form but I like the idea. Probably some sort of external index (radix-tree) would be better and enforcing N*page sized allocations.

ez-pool-alloc

I tried to write an allocator that supported free but with the minimum overhead. I got it down to a minimum allocation size of 8 bytes (void *) with no overhead.

Basically I wrote another AllocMem()/FreeMem() but this time much closer to the original. To support the minimum allocation size of 8 bytes on a 64-bit platform the lsb of the link pointer is used to indicate whether the size is 8 bytes (no room for size) or larger (has size).

This still suffers from the same performance problems, although it can be mitigated by being used only for short-term memory or with few frees.

The Story So Far. A Big Waste Of Fucking Time.

In the end i'm not really sure I like anything I came up with.

I'll probably change the existing ezelib serialiser, and likely split the code up so that the description part is separate from the (multiple) encoding part(s). I'll probably have something XDR-like and another more compact one, maybe tagged. Each may not support all possible structures.

The memory stuff was really just fucking around; I don't remotely need any of this. But I will poke at it some more I guess. Probably a pageish allocator which manages system memory without allocation overhead (at point of allocation), then a couple of allocators which sit atop of it and can be used as pools. A general purpose one and a high-performance non-freeing one that also supports incremental string/structure creation.

The general purpose pool might just end up being very similar to malloc() but with the (rather useful) benefit of being able to be freed en-mass. I can possibly get the minimum allocation size down to 16 bytes although I will need to borrow some bits from ez-tree's ez_node to achieve this. I can possibly also get first-fit to work efficiently (order tree by size then address?). I think i'm going to have to save the size in allocations though (thus 8-byte allocation overhead): it's going to be needed a lot of the time and I can't do fast coalescing without it. If I have a particualrly fast page allocator i might be able to do something neat for small fixed-sized allocs and that would also cover the interesting memalign cases.

Ultumately they would also need valgrind instrumentation as well.

Probably back to work next week, should get away from the screen. Wheather's nice and warm but not too hot. Finally getting a few tomatoes and the sweet-corn is nearly there.

Tagged hacking, libeze.
Friday, 25 January 2019, 15:35

blogz - a personal blog engine

Time to announce the release of another new project - blogz.

Actually it's an old project, it is the software which is running the blog portion of this site. I mentioned months ago that I would get around to releasing it at some point and this is that point.

Go read the homepage for a quick summary. As usual the source has a decent README.

Tagged blogz, zedzone.
Thursday, 24 January 2019, 23:16

Well that was shit

It ended up hitting 46.6 - yep the hottest day on record - just as I left to hit the town. The town was dead. I spent most of the time drinking alone outside on the street although I used splashes of water to keep me cooler than I would have been otherwise.

Even the cockroaches were succumbing to the heat - well at least one expired while I was sitting there! So much for the nuclear apocalipse.

As a health exercise it was a complete failure and probably worse than just staying home.

At least it's supposed to cool down tomorrow for a few days although at 23:00 it's still about 35 so it's going to be a hot-arse night.

Tagged biographical.
Thursday, 24 January 2019, 15:43

Hell on Earth

Welcome to Adelaide, South Australia.

So the mercury just hit 46.6C, which would make it hottest day on record if that sticks as an official reading. Thats a prelimary number from the BOM and i'm not sure which site they use as the official Adelaide number (it was 47.7 in Kent Town). Not even 4pm yet so it might get higher although some clouds are rolling in and there's some `breeze' (more like a fan-forced oven).

Probably not the best day for it but I have to get out of the house for health reasons so time to go see what a burning city looks like first hand. Going to be a warm ride in.

Tagged biographical.
Thursday, 24 January 2019, 12:50

libeze - C utility library

This is announcing a new small project - libeze.

It is a small collection of C utilities as a static link library.

Goals:

Rather than copy the rest of it's current home page just go there and read it. There is much more in the README and source.

It's an offshoot (read: I got very distracted) of the mele music player i've been working on as well as some previous code from ezesdk.

Tagged code, hacking, libeze.
Saturday, 19 January 2019, 22:27

For the PlayerZ

Well i've been stuck in the house for various reasons so i've been doing a lot of solid work on the audio player software for the mele box.

It's not feature complete but it all works:

I'm using posix message queues for communicating between the processes with a simple C struct serialisation mechanism. I'm not using threads as yet, the player just runs as a single thread. This means it can block while reading from libavformat but it greatly simplifies the player logic.

At the moment i'm just running it on my 'workstation' so I don't know how much work - if any - will be required to get it going on the mele, or how it will handle the processes and so on. For example if the disk indexer will overload the cpu or i/o.

Anyway here is a high-level diagram of the processes and various bits that make it up. Sorry it's a bit shit, but well, openoffice draw is a fucking headache to work with.

For it to be feature complete there isn't much left. Some sort of playlist mechanism and/or other ways to navigate the files beyond disk+file-path order. Shuffle should be easy. Network streams would be nice.

With no user interface beyond 2 leds (and given they're in the same hole that just means 2 colours) it can't get too complicated without resorting to an additional service for external maniplation. But that is of course possible.

The things I want to look at are playlists and other ways to navigate the files (other than file-path order), and network streams.

Bored as Fuck

Haven't left the house for a full week at this point. I was sick for a few days but now i'm just miserable for other reasons. This stuff is keeping me well occupied but yeah it's kind of pointless. Even my knees fucking hurt.

I'm wondering whether i should just go back to work early since there's still a couple of weeks before I would otherwise. I don't think I could face it though.

I'm also a bit pissed off that I think I drowned and killed a chilli plant i've been growing for weeks just as it started to kick into gear. We had a couple of hot days and i overwatered it i think. Actually not much is growing very well this year and I can't seem to water it properly either. Too much or too little. Water is so expensive here.

Oh, I also wasted a couple of hours playing with yacy. The idea of decentralised internet services certainly appeals. But it was just slow and provided almost no relevant results to any search I tried - it just didn't work for me. Solr/Lucene just does a weighted sub-string index which isn't very sophisticated. It's also configured for some big server so running it on this little vps was difficult even after fighting with the complex configuration system.

I'm not eating much at least so maybe i can lose some of the weight I keep putting on.

Tagged hacking, linux, playerz.
Sunday, 06 January 2019, 14:08

Media Queries

I made a small change to the HTML and CSS to try to render a bit better on phones. Even though the text is all resizeable and reflowable they rendered at some massive resolution and then scaled down - making the text unredable and non-reflowable. Sigh.

Anyway, first I added:

      <meta name='viewport' content='width=device-width, initial-scale=1'>
    

But this made the text too big and interfered with the table-like layout. I tried using a width of 800 which sort of worked but wasn't very readable either.

So I added a media query and adjusted some of the main sections and the borders and so on. It's just a quick and dirty but it works better than it did. I've only tested on one phone so others may not have changed.

    /* bloody phones */
    @media (max-width: 480px) {
        div#site-menu, .tag-menu {
            float: none;
            width: 100%;
        }
        .post-footer, .post, .post-header {
            margin-right: 1em;
        }
    }
  

On the other hand i'm lucky to get one visitor per week (lots of crawlers, and plenty of hacking attempts) so who really cares eh?

Tagged zedzone.
Sunday, 30 December 2018, 08:56

Monitoring Removable USB Drives

I've been looking into writing some media player software and one function I want is to be able to detect inserted drives and do things with them.

inotify

First I looked at using inotify and just monitoring /dev. This is quite simple; you get IN_CREATE and IN_DELETE events when the directories are created or otherwise, and then you can do what is necessary.

Then came the problem of the doing bit - well you want to mount drives. You can use usbmount or udevd but at this point I was trying for an in-memory solution and I couldn't work out how to find out when they were mounted without having another script run.

libblkid & mount(2)

blkid is used by the usbmount script to determine if the device is a mountable partition; so I looked into libblkdid to do the same from code. It's a bit of a quirky api, and is poorly documented but not terribly difficult to use for what I want. The api is designed for implementing glue between kernel and scripts. The variables you get are again, pretty much undocumented as far as i can gather so it's just a process of run it and see what looks useful.

But using it isn't hard. Basically when a /dev/sd* appears I perform a probe and if it has the right variables set I call mount. I only want read-only access so that simplifies the mount options considerably.

Here's a partial prototype example of the inotify handler and mounting process. This is basically what usbmount does but it ignores any options in fstab and so forth.

static int mount_add(const char *name, blkid_probe p) {
        int idx = mount_alloc();

        if (idx >= 0) {
                int res;
                const char *type;
                size_t type_size;

                printf("checking mount %s\n", name);          
                if (blkid_probe_lookup_value(p, "TYPE", &type, &type_size) == 0) {
                        char point[(strlen("/var/run/usb-00") + 1)];

                        sprintf(point, "/var/run/usb-%02d", idx);
                        res = mkdir(point, 0777);
                        res = mount(name, point, type, MS_NOEXEC | MS_RDONLY | MS_NOSUID, NULL);
                        if (res != 0) {
                                perror("mount");
                                return -1;
                        }
                        printf("mounted: %s <- %s\n", point, name);
                        mounted[idx].name = strdup(name);
                        mounted[idx].point = strdup(point);

                        if (blkid_probe_lookup_value(p, "UUID", &type, &type_size) == 0)
                                mounted[idx].uuid = strdup(type);
                } else {
                        idx = -1;
                }
        }
        return idx;
}

static int mount_remove(const char *name) {
        int idx = mount_index(name);
        
        if (idx >= 0) {
                int res = umount2(mounted[idx].point, MNT_DETACH);
                if (res != 0)
                        perror("umount2");
                else
                        printf("unmounted: %s <- %s\n", mounted[idx].point, mounted[idx].name);

                free(mounted[idx].name);
                free(mounted[idx].point);
                free(mounted[idx].uuid);
                memset(&mounted[idx], 0, sizeof(struct mounted));
        }

        return idx;
}

static void
handle_events(int fd, int wd)
{
        char buf[4096]  __attribute__ ((aligned(__alignof__(struct inotify_event))));
        int i;
        ssize_t len;
        char *ptr;

        for (;;) {
                len = read(fd, buf, sizeof buf);
                if (len == -1 && errno != EAGAIN) {
                        perror("read");
                        exit(EXIT_FAILURE);
                }
                if (len <= 0)
                        break;

                for (ptr = buf; ptr < buf + len;) {
                        const struct inotify_event *event;
                        
                        event = (const struct inotify_event *) ptr;

                        if (event->len && strncmp(event->name, "sd", 2) == 0) {
                                char name[(event->len + 1 + strlen("/dev/"))];

                                sprintf(name, "/dev/%s", event->name);
                                
                                if (event->mask & IN_CREATE) {
                                        blkid_probe p = blkid_new_probe_from_filename(name);
                                        int rc;

                                        blkid_probe_enable_partitions(p, 0);
                                        blkid_probe_enable_superblocks(p, 1);
                                        rc = blkid_do_safeprobe(p);
                                        
                                        int idx = mount_add(name, p);
                                        if (idx >= 0) {
                                                // do something with added mount
                                        }
                                        blkid_free_probe(p);
                                }
                                if (event->mask & IN_DELETE) {
                                        int idx = mount_index(name);
                                        if (idx >= 0) {
                                                // do something with removed mount
                                        }
                                }
                        }
                        
                        ptr += sizeof(struct inotify_event) + event->len;
                }
        }
}

udevd, NETLINK_KOBJECT_UEVENT

But I was curious - just how are the dev entries created? I thought it must be udevd or something. The only articles or documentation I could find were unclear on the matter.

So first, NETLINK_KOBJECT_UEVENT, this unpleasantly named 'network' protocol is used these days to monitor kernel activities like usb hotplugging. So I took a small example and started dumping out what I got.

The documentation and examples talk about using a 'struct nmlsghdr' as the datagram payload, but this is in error. You just get the payload directly. And the payload appears to be list of NUL terminated strings; which surprise are just environment variable declarations (i'm noticing a trend here).

Anyway, here's a complete example which dumps out the messages.

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/netlink.h>
#include <unistd.h>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

int main(int argc, char **argv) {
        int s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
        struct sockaddr_nl addr = {
                .nl_family = AF_NETLINK,
                .nl_pid = getpid(),
                .nl_groups = ~0
        };
        int res;
        char data[8192];
        struct msghdr msg;
        struct iovec iov;

        bind(s, (void *)&addr, sizeof(addr));
        
        iov.iov_base = data;
        iov.iov_len = 8192;

        msg.msg_name = (void *)&(addr);
        msg.msg_namelen = sizeof(addr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        while ((res = recvmsg(s, &msg, 0)) >= 0) {
                if (strcmp(data, "libudev") != 0) {
                        unsigned char *x = data, *e = data+res;

                        while (x < e) {
                                printf(" %s\n", x);
                                x += strlen(x) + 1;
                        }
                        printf("\n");
                } else {
                        for (int i=0;i<res;i+=16) {
                                for (int j=i;j < i+16;j++)
                                        printf(j < res ? " %02x" : "   ", data[j]);
                                printf("  ");
                                for (int j=i;j < i+16;j++)
                                        putchar(j < res ? (isprint(data[j]) ? data[j] : '.') : ' ');
                                printf("\n");
                        }
                        printf("\n");
                }
        }
        
        return 0;
}

The libudev test is because udevd repackages the requests and sends them out again in some proprietary binary format for some reason which is unclear to me at this time.

And this is the output when I plug in a usb drive.

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2
 SUBSYSTEM=usb
 MAJOR=189
 MINOR=645
 DEVNAME=bus/usb/006/006
 DEVTYPE=usb_device
 PRODUCT=90c/1000/1100
 TYPE=0/0/0
 BUSNUM=006
 DEVNUM=006
 SEQNUM=7439

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0
 SUBSYSTEM=usb
 DEVTYPE=usb_interface
 PRODUCT=90c/1000/1100
 TYPE=0/0/0
 INTERFACE=8/6/80
 MODALIAS=usb:v090Cp1000d1100dc00dsc00dp00ic08isc06ip50in00
 SEQNUM=7440

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6
 SUBSYSTEM=scsi
 DEVTYPE=scsi_host
 SEQNUM=7441

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/scsi_host/host6
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/scsi_host/host6
 SUBSYSTEM=scsi_host
 SEQNUM=7442

 bind@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0
 ACTION=bind
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0
 SUBSYSTEM=usb
 DEVTYPE=usb_interface
 DRIVER=usb-storage
 PRODUCT=90c/1000/1100
 TYPE=0/0/0
 INTERFACE=8/6/80
 MODALIAS=usb:v090Cp1000d1100dc00dsc00dp00ic08isc06ip50in00
 SEQNUM=7443

 bind@/devices/pci0000:00/0000:00:10.0/usb6/6-2
 ACTION=bind
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2
 SUBSYSTEM=usb
 MAJOR=189
 MINOR=645
 DEVNAME=bus/usb/006/006
 DEVTYPE=usb_device
 DRIVER=usb
 PRODUCT=90c/1000/1100
 TYPE=0/0/0
 BUSNUM=006
 DEVNUM=006
 SEQNUM=7444

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 89 02 00 00 05 77 c5 e5 27 f8 f5 0c  (........w..'...
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 00 53 55 42 53 59 53 54 45 4d 3d 75  /6-2.SUBSYSTEM=u
 73 62 00 44 45 56 4e 41 4d 45 3d 2f 64 65 76 2f  sb.DEVNAME=/dev/
 62 75 73 2f 75 73 62 2f 30 30 36 2f 30 30 36 00  bus/usb/006/006.
 44 45 56 54 59 50 45 3d 75 73 62 5f 64 65 76 69  DEVTYPE=usb_devi
 63 65 00 50 52 4f 44 55 43 54 3d 39 30 63 2f 31  ce.PRODUCT=90c/1
 30 30 30 2f 31 31 30 30 00 54 59 50 45 3d 30 2f  000/1100.TYPE=0/
 30 2f 30 00 42 55 53 4e 55 4d 3d 30 30 36 00 44  0/0.BUSNUM=006.D
 45 56 4e 55 4d 3d 30 30 36 00 53 45 51 4e 55 4d  EVNUM=006.SEQNUM
 3d 37 34 33 39 00 4d 41 4a 4f 52 3d 31 38 39 00  =7439.MAJOR=189.
 4d 49 4e 4f 52 3d 36 34 35 00 55 53 45 43 5f 49  MINOR=645.USEC_I
 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30 35 35 39  NITIALIZED=20559
 39 39 33 30 37 35 34 35 00 49 44 5f 56 45 4e 44  99307545.ID_VEND
 4f 52 3d 53 61 6d 73 75 6e 67 00 49 44 5f 56 45  OR=Samsung.ID_VE
 4e 44 4f 52 5f 45 4e 43 3d 53 61 6d 73 75 6e 67  NDOR_ENC=Samsung
 00 49 44 5f 56 45 4e 44 4f 52 5f 49 44 3d 30 39  .ID_VENDOR_ID=09
 30 63 00 49 44 5f 4d 4f 44 45 4c 3d 46 6c 61 73  0c.ID_MODEL=Flas
 68 5f 44 72 69 76 65 5f 44 55 4f 00 49 44 5f 4d  h_Drive_DUO.ID_M
 4f 44 45 4c 5f 45 4e 43 3d 46 6c 61 73 68 5c 78  ODEL_ENC=Flash\x
 32 30 44 72 69 76 65 5c 78 32 30 44 55 4f 00 49  20Drive\x20DUO.I
 44 5f 4d 4f 44 45 4c 5f 49 44 3d 31 30 30 30 00  D_MODEL_ID=1000.
 49 44 5f 52 45 56 49 53 49 4f 4e 3d 31 31 30 30  ID_REVISION=1100
 00 49 44 5f 53 45 52 49 41 4c 3d 53 61 6d 73 75  .ID_SERIAL=Samsu
 6e 67 5f 46 6c 61 73 68 5f 44 72 69 76 65 5f 44  ng_Flash_Drive_D
 55 4f 5f 30 33 33 31 35 31 36 30 37 30 30 31 38  UO_0331516070018
 38 31 31 00 49 44 5f 53 45 52 49 41 4c 5f 53 48  811.ID_SERIAL_SH
 4f 52 54 3d 30 33 33 31 35 31 36 30 37 30 30 31  ORT=033151607001
 38 38 31 31 00 49 44 5f 42 55 53 3d 75 73 62 00  8811.ID_BUS=usb.
 49 44 5f 55 53 42 5f 49 4e 54 45 52 46 41 43 45  ID_USB_INTERFACE
 53 3d 3a 30 38 30 36 35 30 3a 00 49 44 5f 56 45  S=:080650:.ID_VE
 4e 44 4f 52 5f 46 52 4f 4d 5f 44 41 54 41 42 41  NDOR_FROM_DATABA
 53 45 3d 53 69 6c 69 63 6f 6e 20 4d 6f 74 69 6f  SE=Silicon Motio
 6e 2c 20 49 6e 63 2e 20 2d 20 54 61 69 77 61 6e  n, Inc. - Taiwan
 20 28 66 6f 72 6d 65 72 6c 79 20 46 65 69 79 61   (formerly Feiya
 20 54 65 63 68 6e 6f 6c 6f 67 79 20 43 6f 72 70   Technology Corp
 2e 29 00 49 44 5f 4d 4f 44 45 4c 5f 46 52 4f 4d  .).ID_MODEL_FROM
 5f 44 41 54 41 42 41 53 45 3d 46 6c 61 73 68 20  _DATABASE=Flash 
 44 72 69 76 65 00 44 52 49 56 45 52 3d 75 73 62  Drive.DRIVER=usb
 00                                               .               

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 8f 01 00 00 05 77 c5 e5 b1 02 47 65  (........w....Ge
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 00 53 55 42  /6-2/6-2:1.0.SUB
 53 59 53 54 45 4d 3d 75 73 62 00 44 45 56 54 59  SYSTEM=usb.DEVTY
 50 45 3d 75 73 62 5f 69 6e 74 65 72 66 61 63 65  PE=usb_interface
 00 50 52 4f 44 55 43 54 3d 39 30 63 2f 31 30 30  .PRODUCT=90c/100
 30 2f 31 31 30 30 00 54 59 50 45 3d 30 2f 30 2f  0/1100.TYPE=0/0/
 30 00 49 4e 54 45 52 46 41 43 45 3d 38 2f 36 2f  0.INTERFACE=8/6/
 38 30 00 4d 4f 44 41 4c 49 41 53 3d 75 73 62 3a  80.MODALIAS=usb:
 76 30 39 30 43 70 31 30 30 30 64 31 31 30 30 64  v090Cp1000d1100d
 63 30 30 64 73 63 30 30 64 70 30 30 69 63 30 38  c00dsc00dp00ic08
 69 73 63 30 36 69 70 35 30 69 6e 30 30 00 53 45  isc06ip50in00.SE
 51 4e 55 4d 3d 37 34 34 30 00 55 53 45 43 5f 49  QNUM=7440.USEC_I
 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30 35 35 39  NITIALIZED=20559
 39 39 33 30 39 32 38 36 00 49 44 5f 56 45 4e 44  99309286.ID_VEND
 4f 52 5f 46 52 4f 4d 5f 44 41 54 41 42 41 53 45  OR_FROM_DATABASE
 3d 53 69 6c 69 63 6f 6e 20 4d 6f 74 69 6f 6e 2c  =Silicon Motion,
 20 49 6e 63 2e 20 2d 20 54 61 69 77 61 6e 20 28   Inc. - Taiwan (
 66 6f 72 6d 65 72 6c 79 20 46 65 69 79 61 20 54  formerly Feiya T
 65 63 68 6e 6f 6c 6f 67 79 20 43 6f 72 70 2e 29  echnology Corp.)
 00 49 44 5f 4d 4f 44 45 4c 5f 46 52 4f 4d 5f 44  .ID_MODEL_FROM_D
 41 54 41 42 41 53 45 3d 46 6c 61 73 68 20 44 72  ATABASE=Flash Dr
 69 76 65 00 44 52 49 56 45 52 3d 75 73 62 2d 73  ive.DRIVER=usb-s
 74 6f 72 61 67 65 00                             torage.         

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 97 00 00 00 29 20 1a 28 a0 05 fb 58  (.......) .(...X
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 00 53 55 42 53 59 53 54 45 4d 3d 73 63 73  t6.SUBSYSTEM=scs
 69 00 44 45 56 54 59 50 45 3d 73 63 73 69 5f 68  i.DEVTYPE=scsi_h
 6f 73 74 00 53 45 51 4e 55 4d 3d 37 34 34 31 00  ost.SEQNUM=7441.
 55 53 45 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44  USEC_INITIALIZED
 3d 32 30 35 35 39 39 39 33 31 30 38 39 37 00     =2055999310897. 

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 9a 00 00 00 a0 05 fb 58 00 00 00 00  (..........X....
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 73 63 73 69 5f 68 6f 73 74 2f 68 6f 73  t6/scsi_host/hos
 74 36 00 53 55 42 53 59 53 54 45 4d 3d 73 63 73  t6.SUBSYSTEM=scs
 69 5f 68 6f 73 74 00 53 45 51 4e 55 4d 3d 37 34  i_host.SEQNUM=74
 34 32 00 55 53 45 43 5f 49 4e 49 54 49 41 4c 49  42.USEC_INITIALI
 5a 45 44 3d 32 30 35 35 39 39 39 33 31 31 38 36  ZED=205599931186
 31 00                                            1.              

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0
 SUBSYSTEM=scsi
 DEVTYPE=scsi_target
 SEQNUM=7445

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0
 SUBSYSTEM=scsi
 DEVTYPE=scsi_device
 MODALIAS=scsi:t-0x00
 SEQNUM=7446

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
 SUBSYSTEM=scsi_disk
 SEQNUM=7447

 bind@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0
 ACTION=bind
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0
 SUBSYSTEM=scsi
 DEVTYPE=scsi_device
 DRIVER=sd
 MODALIAS=scsi:t-0x00
 SEQNUM=7448

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
 SUBSYSTEM=scsi_device
 SEQNUM=7449

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg1
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg1
 SUBSYSTEM=scsi_generic
 MAJOR=21
 MINOR=1
 DEVNAME=sg1
 SEQNUM=7450

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
 SUBSYSTEM=bsg
 MAJOR=246
 MINOR=1
 DEVNAME=bsg/6:0:0:0
 SEQNUM=7451

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 a5 00 00 00 29 20 1a 28 f2 6a 9f 62  (.......) .(.j.b
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 00 53  t6/target6:0:0.S
 55 42 53 59 53 54 45 4d 3d 73 63 73 69 00 44 45  UBSYSTEM=scsi.DE
 56 54 59 50 45 3d 73 63 73 69 5f 74 61 72 67 65  VTYPE=scsi_targe
 74 00 53 45 51 4e 55 4d 3d 37 34 34 35 00 55 53  t.SEQNUM=7445.US
 45 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32  EC_INITIALIZED=2
 30 35 36 30 30 30 36 35 39 36 37 32 00           056000659672.   

 add@/devices/virtual/bdi/8:16
 ACTION=add
 DEVPATH=/devices/virtual/bdi/8:16
 SUBSYSTEM=bdi
 SEQNUM=7452

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 cc 00 00 00 29 20 1a 28 7d b5 06 b5  (.......) .(}...
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 00 53 55 42 53 59 53 54 45 4d  :0:0:0.SUBSYSTEM
 3d 73 63 73 69 00 44 45 56 54 59 50 45 3d 73 63  =scsi.DEVTYPE=sc
 73 69 5f 64 65 76 69 63 65 00 4d 4f 44 41 4c 49  si_device.MODALI
 41 53 3d 73 63 73 69 3a 74 2d 30 78 30 30 00 53  AS=scsi:t-0x00.S
 45 51 4e 55 4d 3d 37 34 34 36 00 55 53 45 43 5f  EQNUM=7446.USEC_
 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30 35 36  INITIALIZED=2056
 30 30 30 36 36 31 36 31 35 00 44 52 49 56 45 52  000661615.DRIVER
 3d 73 64 00                                      =sd.            

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 66 00 00 00 2a 18 84 a1 00 00 00 00  (...f...*.......
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 76 69 72 74 75 61 6c 2f 62 64 69 2f  ces/virtual/bdi/
 38 3a 31 36 00 53 55 42 53 59 53 54 45 4d 3d 62  8:16.SUBSYSTEM=b
 64 69 00 53 45 51 4e 55 4d 3d 37 34 35 32 00 55  di.SEQNUM=7452.U
 53 45 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44 3d  SEC_INITIALIZED=
 32 30 35 36 30 30 30 36 36 32 34 30 31 00        2056000662401.  

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 b4 00 00 00 7d b5 06 b5 00 00 00 00  (.......}.......
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 73 63 73 69 5f 64 65 76 69  :0:0:0/scsi_devi
 63 65 2f 36 3a 30 3a 30 3a 30 00 53 55 42 53 59  ce/6:0:0:0.SUBSY
 53 54 45 4d 3d 73 63 73 69 5f 64 65 76 69 63 65  STEM=scsi_device
 00 53 45 51 4e 55 4d 3d 37 34 34 39 00 55 53 45  .SEQNUM=7449.USE
 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30  C_INITIALIZED=20
 35 36 30 30 30 36 36 35 31 34 31 00              56000665141.    

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/block/sdb
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/block/sdb
 SUBSYSTEM=block
 MAJOR=8
 MINOR=16
 DEVNAME=sdb
 DEVTYPE=disk
 SEQNUM=7453

 add@/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1
 ACTION=add
 DEVPATH=/devices/pci0000:00/0000:00:10.0/usb6/6-2/6-2:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb1
 SUBSYSTEM=block
 MAJOR=8
 MINOR=17
 DEVNAME=sdb1
 DEVTYPE=partition
 PARTN=1
 SEQNUM=7454

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 b0 00 00 00 89 0e a9 0f 00 00 00 00  (...............
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 73 63 73 69 5f 64 69 73 6b  :0:0:0/scsi_disk
 2f 36 3a 30 3a 30 3a 30 00 53 55 42 53 59 53 54  /6:0:0:0.SUBSYST
 45 4d 3d 73 63 73 69 5f 64 69 73 6b 00 53 45 51  EM=scsi_disk.SEQ
 4e 55 4d 3d 37 34 34 37 00 55 53 45 43 5f 49 4e  NUM=7447.USEC_IN
 49 54 49 41 4c 49 5a 45 44 3d 32 30 35 36 30 30  ITIALIZED=205600
 30 36 36 36 30 33 30 00                          0666030.        

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 d4 00 00 00 3c e8 b1 f8 00 00 00 00  (.......<.......
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 73 63 73 69 5f 67 65 6e 65  :0:0:0/scsi_gene
 72 69 63 2f 73 67 31 00 53 55 42 53 59 53 54 45  ric/sg1.SUBSYSTE
 4d 3d 73 63 73 69 5f 67 65 6e 65 72 69 63 00 44  M=scsi_generic.D
 45 56 4e 41 4d 45 3d 2f 64 65 76 2f 73 67 31 00  EVNAME=/dev/sg1.
 53 45 51 4e 55 4d 3d 37 34 35 30 00 4d 41 4a 4f  SEQNUM=7450.MAJO
 52 3d 32 31 00 4d 49 4e 4f 52 3d 31 00 55 53 45  R=21.MINOR=1.USE
 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30  C_INITIALIZED=20
 35 36 30 30 30 36 36 36 35 39 35 00              56000666595.    

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 cf 00 00 00 0d df d8 a1 00 00 00 00  (...............
 00 00 00 00 00 00 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 62 73 67 2f 36 3a 30 3a 30  :0:0:0/bsg/6:0:0
 3a 30 00 53 55 42 53 59 53 54 45 4d 3d 62 73 67  :0.SUBSYSTEM=bsg
 00 44 45 56 4e 41 4d 45 3d 2f 64 65 76 2f 62 73  .DEVNAME=/dev/bs
 67 2f 36 3a 30 3a 30 3a 30 00 53 45 51 4e 55 4d  g/6:0:0:0.SEQNUM
 3d 37 34 35 31 00 4d 41 4a 4f 52 3d 32 34 36 00  =7451.MAJOR=246.
 4d 49 4e 4f 52 3d 31 00 55 53 45 43 5f 49 4e 49  MINOR=1.USEC_INI
 54 49 41 4c 49 5a 45 44 3d 32 30 35 36 30 30 30  TIALIZED=2056000
 36 36 37 30 34 32 00                             667042.         

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 54 03 00 00 f0 03 1d b7 7b cb c5 ee  (...T.......{...
 02 00 04 00 10 80 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 62 6c 6f 63 6b 2f 73 64 62  :0:0:0/block/sdb
 00 53 55 42 53 59 53 54 45 4d 3d 62 6c 6f 63 6b  .SUBSYSTEM=block
 00 44 45 56 4e 41 4d 45 3d 2f 64 65 76 2f 73 64  .DEVNAME=/dev/sd
 62 00 44 45 56 54 59 50 45 3d 64 69 73 6b 00 53  b.DEVTYPE=disk.S
 45 51 4e 55 4d 3d 37 34 35 33 00 55 53 45 43 5f  EQNUM=7453.USEC_
 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32 30 35 36  INITIALIZED=2056
 30 30 30 37 33 36 33 35 39 00 4d 41 4a 4f 52 3d  000736359.MAJOR=
 38 00 4d 49 4e 4f 52 3d 31 36 00 49 44 5f 56 45  8.MINOR=16.ID_VE
 4e 44 4f 52 3d 53 61 6d 73 75 6e 67 00 49 44 5f  NDOR=Samsung.ID_
 56 45 4e 44 4f 52 5f 45 4e 43 3d 53 61 6d 73 75  VENDOR_ENC=Samsu
 6e 67 5c 78 32 30 00 49 44 5f 56 45 4e 44 4f 52  ng\x20.ID_VENDOR
 5f 49 44 3d 30 39 30 63 00 49 44 5f 4d 4f 44 45  _ID=090c.ID_MODE
 4c 3d 46 6c 61 73 68 5f 44 72 69 76 65 5f 44 55  L=Flash_Drive_DU
 4f 00 49 44 5f 4d 4f 44 45 4c 5f 45 4e 43 3d 46  O.ID_MODEL_ENC=F
 6c 61 73 68 5c 78 32 30 44 72 69 76 65 5c 78 32  lash\x20Drive\x2
 30 44 55 4f 5c 78 32 30 00 49 44 5f 4d 4f 44 45  0DUO\x20.ID_MODE
 4c 5f 49 44 3d 31 30 30 30 00 49 44 5f 52 45 56  L_ID=1000.ID_REV
 49 53 49 4f 4e 3d 31 31 30 30 00 49 44 5f 53 45  ISION=1100.ID_SE
 52 49 41 4c 3d 53 61 6d 73 75 6e 67 5f 46 6c 61  RIAL=Samsung_Fla
 73 68 5f 44 72 69 76 65 5f 44 55 4f 5f 30 33 33  sh_Drive_DUO_033
 31 35 31 36 30 37 30 30 31 38 38 31 31 2d 30 3a  1516070018811-0:
 30 00 49 44 5f 53 45 52 49 41 4c 5f 53 48 4f 52  0.ID_SERIAL_SHOR
 54 3d 30 33 33 31 35 31 36 30 37 30 30 31 38 38  T=03315160700188
 31 31 00 49 44 5f 54 59 50 45 3d 64 69 73 6b 00  11.ID_TYPE=disk.
 49 44 5f 49 4e 53 54 41 4e 43 45 3d 30 3a 30 00  ID_INSTANCE=0:0.
 49 44 5f 42 55 53 3d 75 73 62 00 49 44 5f 55 53  ID_BUS=usb.ID_US
 42 5f 49 4e 54 45 52 46 41 43 45 53 3d 3a 30 38  B_INTERFACES=:08
 30 36 35 30 3a 00 49 44 5f 55 53 42 5f 49 4e 54  0650:.ID_USB_INT
 45 52 46 41 43 45 5f 4e 55 4d 3d 30 30 00 49 44  ERFACE_NUM=00.ID
 5f 55 53 42 5f 44 52 49 56 45 52 3d 75 73 62 2d  _USB_DRIVER=usb-
 73 74 6f 72 61 67 65 00 44 45 56 4c 49 4e 4b 53  storage.DEVLINKS
 3d 2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 69 64  =/dev/disk/by-id
 2f 75 73 62 2d 53 61 6d 73 75 6e 67 5f 46 6c 61  /usb-Samsung_Fla
 73 68 5f 44 72 69 76 65 5f 44 55 4f 5f 30 33 33  sh_Drive_DUO_033
 31 35 31 36 30 37 30 30 31 38 38 31 31 2d 30 3a  1516070018811-0:
 30 20 2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d 70  0 /dev/disk/by-p
 61 74 68 2f 70 63 69 2d 30 30 30 30 3a 30 30 3a  ath/pci-0000:00:
 31 30 2e 30 2d 75 73 62 2d 30 3a 32 3a 31 2e 30  10.0-usb-0:2:1.0
 2d 73 63 73 69 2d 30 3a 30 3a 30 3a 30 00 49 44  -scsi-0:0:0:0.ID
 5f 50 41 54 48 3d 70 63 69 2d 30 30 30 30 3a 30  _PATH=pci-0000:0
 30 3a 31 30 2e 30 2d 75 73 62 2d 30 3a 32 3a 31  0:10.0-usb-0:2:1
 2e 30 2d 73 63 73 69 2d 30 3a 30 3a 30 3a 30 00  .0-scsi-0:0:0:0.
 49 44 5f 50 41 54 48 5f 54 41 47 3d 70 63 69 2d  ID_PATH_TAG=pci-
 30 30 30 30 5f 30 30 5f 31 30 5f 30 2d 75 73 62  0000_00_10_0-usb
 2d 30 5f 32 5f 31 5f 30 2d 73 63 73 69 2d 30 5f  -0_2_1_0-scsi-0_
 30 5f 30 5f 30 00 49 44 5f 50 41 52 54 5f 54 41  0_0_0.ID_PART_TA
 42 4c 45 5f 54 59 50 45 3d 64 6f 73 00 54 41 47  BLE_TYPE=dos.TAG
 53 3d 3a 73 79 73 74 65 6d 64 3a 00              S=:systemd:.    

 6c 69 62 75 64 65 76 00 fe ed ca fe 28 00 00 00  libudev.....(...
 28 00 00 00 e5 04 00 00 f0 03 1d b7 cb 23 44 89  (............#D.
 02 00 04 00 10 80 00 00 41 43 54 49 4f 4e 3d 61  ........ACTION=a
 64 64 00 44 45 56 50 41 54 48 3d 2f 64 65 76 69  dd.DEVPATH=/devi
 63 65 73 2f 70 63 69 30 30 30 30 3a 30 30 2f 30  ces/pci0000:00/0
 30 30 30 3a 30 30 3a 31 30 2e 30 2f 75 73 62 36  000:00:10.0/usb6
 2f 36 2d 32 2f 36 2d 32 3a 31 2e 30 2f 68 6f 73  /6-2/6-2:1.0/hos
 74 36 2f 74 61 72 67 65 74 36 3a 30 3a 30 2f 36  t6/target6:0:0/6
 3a 30 3a 30 3a 30 2f 62 6c 6f 63 6b 2f 73 64 62  :0:0:0/block/sdb
 2f 73 64 62 31 00 53 55 42 53 59 53 54 45 4d 3d  /sdb1.SUBSYSTEM=
 62 6c 6f 63 6b 00 44 45 56 4e 41 4d 45 3d 2f 64  block.DEVNAME=/d
 65 76 2f 73 64 62 31 00 44 45 56 54 59 50 45 3d  ev/sdb1.DEVTYPE=
 70 61 72 74 69 74 69 6f 6e 00 50 41 52 54 4e 3d  partition.PARTN=
 31 00 53 45 51 4e 55 4d 3d 37 34 35 34 00 55 53  1.SEQNUM=7454.US
 45 43 5f 49 4e 49 54 49 41 4c 49 5a 45 44 3d 32  EC_INITIALIZED=2
 30 35 36 30 30 30 37 39 35 39 37 39 00 4d 41 4a  056000795979.MAJ
 4f 52 3d 38 00 4d 49 4e 4f 52 3d 31 37 00 49 44  OR=8.MINOR=17.ID
 5f 42 55 53 3d 75 73 62 00 49 44 5f 49 4e 53 54  _BUS=usb.ID_INST
 41 4e 43 45 3d 30 3a 30 00 49 44 5f 4d 4f 44 45  ANCE=0:0.ID_MODE
 4c 3d 46 6c 61 73 68 5f 44 72 69 76 65 5f 44 55  L=Flash_Drive_DU
 4f 00 49 44 5f 4d 4f 44 45 4c 5f 45 4e 43 3d 46  O.ID_MODEL_ENC=F
 6c 61 73 68 5c 78 32 30 44 72 69 76 65 5c 78 32  lash\x20Drive\x2
 30 44 55 4f 5c 78 32 30 00 49 44 5f 4d 4f 44 45  0DUO\x20.ID_MODE
 4c 5f 49 44 3d 31 30 30 30 00 49 44 5f 50 41 52  L_ID=1000.ID_PAR
 54 5f 54 41 42 4c 45 5f 54 59 50 45 3d 64 6f 73  T_TABLE_TYPE=dos
 00 49 44 5f 50 41 54 48 3d 70 63 69 2d 30 30 30  .ID_PATH=pci-000
 30 3a 30 30 3a 31 30 2e 30 2d 75 73 62 2d 30 3a  0:00:10.0-usb-0:
 32 3a 31 2e 30 2d 73 63 73 69 2d 30 3a 30 3a 30  2:1.0-scsi-0:0:0
 3a 30 00 49 44 5f 50 41 54 48 5f 54 41 47 3d 70  :0.ID_PATH_TAG=p
 63 69 2d 30 30 30 30 5f 30 30 5f 31 30 5f 30 2d  ci-0000_00_10_0-
 75 73 62 2d 30 5f 32 5f 31 5f 30 2d 73 63 73 69  usb-0_2_1_0-scsi
 2d 30 5f 30 5f 30 5f 30 00 49 44 5f 52 45 56 49  -0_0_0_0.ID_REVI
 53 49 4f 4e 3d 31 31 30 30 00 49 44 5f 53 45 52  SION=1100.ID_SER
 49 41 4c 3d 53 61 6d 73 75 6e 67 5f 46 6c 61 73  IAL=Samsung_Flas
 68 5f 44 72 69 76 65 5f 44 55 4f 5f 30 33 33 31  h_Drive_DUO_0331
 35 31 36 30 37 30 30 31 38 38 31 31 2d 30 3a 30  516070018811-0:0
 00 49 44 5f 53 45 52 49 41 4c 5f 53 48 4f 52 54  .ID_SERIAL_SHORT
 3d 30 33 33 31 35 31 36 30 37 30 30 31 38 38 31  =033151607001881
 31 00 49 44 5f 54 59 50 45 3d 64 69 73 6b 00 49  1.ID_TYPE=disk.I
 44 5f 55 53 42 5f 44 52 49 56 45 52 3d 75 73 62  D_USB_DRIVER=usb
 2d 73 74 6f 72 61 67 65 00 49 44 5f 55 53 42 5f  -storage.ID_USB_
 49 4e 54 45 52 46 41 43 45 53 3d 3a 30 38 30 36  INTERFACES=:0806
 35 30 3a 00 49 44 5f 55 53 42 5f 49 4e 54 45 52  50:.ID_USB_INTER
 46 41 43 45 5f 4e 55 4d 3d 30 30 00 49 44 5f 56  FACE_NUM=00.ID_V
 45 4e 44 4f 52 3d 53 61 6d 73 75 6e 67 00 49 44  ENDOR=Samsung.ID
 5f 56 45 4e 44 4f 52 5f 45 4e 43 3d 53 61 6d 73  _VENDOR_ENC=Sams
 75 6e 67 5c 78 32 30 00 49 44 5f 56 45 4e 44 4f  ung\x20.ID_VENDO
 52 5f 49 44 3d 30 39 30 63 00 44 45 56 4c 49 4e  R_ID=090c.DEVLIN
 4b 53 3d 2f 64 65 76 2f 64 69 73 6b 2f 62 79 2d  KS=/dev/disk/by-
 6c 61 62 65 6c 2f 53 61 6d 73 75 6e 67 5c 78 32  label/Samsung\x2
 30 55 53 42 20 2f 64 65 76 2f 64 69 73 6b 2f 62  0USB /dev/disk/b
 79 2d 70 61 74 68 2f 70 63 69 2d 30 30 30 30 3a  y-path/pci-0000:
 30 30 3a 31 30 2e 30 2d 75 73 62 2d 30 3a 32 3a  00:10.0-usb-0:2:
 31 2e 30 2d 73 63 73 69 2d 30 3a 30 3a 30 3a 30  1.0-scsi-0:0:0:0
 2d 70 61 72 74 31 20 2f 64 65 76 2f 64 69 73 6b  -part1 /dev/disk
 2f 62 79 2d 69 64 2f 75 73 62 2d 53 61 6d 73 75  /by-id/usb-Samsu
 6e 67 5f 46 6c 61 73 68 5f 44 72 69 76 65 5f 44  ng_Flash_Drive_D
 55 4f 5f 30 33 33 31 35 31 36 30 37 30 30 31 38  UO_0331516070018
 38 31 31 2d 30 3a 30 2d 70 61 72 74 31 20 2f 64  811-0:0-part1 /d
 65 76 2f 64 69 73 6b 2f 62 79 2d 75 75 69 64 2f  ev/disk/by-uuid/
 45 35 34 31 2d 43 30 44 44 00 49 44 5f 46 53 5f  E541-C0DD.ID_FS_
 4c 41 42 45 4c 3d 53 61 6d 73 75 6e 67 5f 55 53  LABEL=Samsung_US
 42 00 49 44 5f 46 53 5f 4c 41 42 45 4c 5f 45 4e  B.ID_FS_LABEL_EN
 43 3d 53 61 6d 73 75 6e 67 5c 78 32 30 55 53 42  C=Samsung\x20USB
 00 49 44 5f 46 53 5f 55 55 49 44 3d 45 35 34 31  .ID_FS_UUID=E541
 2d 43 30 44 44 00 49 44 5f 46 53 5f 55 55 49 44  -C0DD.ID_FS_UUID
 5f 45 4e 43 3d 45 35 34 31 2d 43 30 44 44 00 49  _ENC=E541-C0DD.I
 44 5f 46 53 5f 56 45 52 53 49 4f 4e 3d 46 41 54  D_FS_VERSION=FAT
 33 32 00 49 44 5f 46 53 5f 54 59 50 45 3d 76 66  32.ID_FS_TYPE=vf
 61 74 00 49 44 5f 46 53 5f 55 53 41 47 45 3d 66  at.ID_FS_USAGE=f
 69 6c 65 73 79 73 74 65 6d 00 49 44 5f 50 41 52  ilesystem.ID_PAR
 54 5f 45 4e 54 52 59 5f 53 43 48 45 4d 45 3d 64  T_ENTRY_SCHEME=d
 6f 73 00 49 44 5f 50 41 52 54 5f 45 4e 54 52 59  os.ID_PART_ENTRY
 5f 54 59 50 45 3d 30 78 63 00 49 44 5f 50 41 52  _TYPE=0xc.ID_PAR
 54 5f 45 4e 54 52 59 5f 4e 55 4d 42 45 52 3d 31  T_ENTRY_NUMBER=1
 00 49 44 5f 50 41 52 54 5f 45 4e 54 52 59 5f 4f  .ID_PART_ENTRY_O
 46 46 53 45 54 3d 36 34 00 49 44 5f 50 41 52 54  FFSET=64.ID_PART
 5f 45 4e 54 52 59 5f 53 49 5a 45 3d 31 32 35 33  _ENTRY_SIZE=1253
 30 34 37 36 38 00 49 44 5f 50 41 52 54 5f 45 4e  04768.ID_PART_EN
 54 52 59 5f 44 49 53 4b 3d 38 3a 31 36 00 54 41  TRY_DISK=8:16.TA
 47 53 3d 3a 73 79 73 74 65 6d 64 3a 00           GS=:systemd:.   

Ignoring the libudev snot there's basically a flurry of events, a short pause, and then the last couple of interesting events where the device nodes become available.

AS FAR AS I CAN GATHER ... there appears to be no documentation regarding the format or order of these kernel messages; what variables will be included and what they mean. Well there's always the kernel source but I could find nothing in [kernel-source]/Documnetation nor anywhere else.

I suppose it is relatively straightforward to just 'suck it and see' but documentation would be nice all the same.

At this point I went down a rabbit hole of trying to work out who ACTUALLY creates the /dev entries; it turns out it's the kernel. So infact udevd isn't really doing anything particularly useful on my system. Probably just as well now that the systemd developers have started 'maintaining' it.

systemd

So anyway i've done a bit of prototyping and I'm sure I can get away without needing udevd at all, systemd is thankfully not anywhere near the mele already. Then I went down another rabbit hole of finding out the current status of systemd.

It's still not good. And i'm pretty sure it never will be. With any luck IBM will pull their finger out and realise what a huge risk and waste of money the project is to their new acquisition and throw it in the bin where it belongs. But of course i'm not holding my breath, it's been designed to be unremovable and was agressively promoted and pushed onto 3rd party projects for a reason. As an aside, hopefully IBM can make jfs a first-class filesystem citizen rather than the red-headed step-child it seems to be these days.

The blog fromthecodefront has a very clear analysis of the situation. Grating narcissitic and abusive personalities aside, this is the first time i've come across any sourcode. It is not pretty. It looks exactly like the code I write when i'm developing prototypes; lots of cut and paste, poor modularisation, meaningless function names, etc. Although I usually tend to use more comments, meaningful labels, and fewer weird-arsed macros to 'save typing' (infact i almost never use macros for that anymore; inline or plain functions can usually be used). And because it's all in C, there's quite an impedence mismatch when a scripting language would be the better choice. This is not the type of code I force onto others, and certainly not any system-critical components.

The developers seem to be out of their depth and absolute arseholes when called out on it. The passive-aggressive and other psychopathic behaviours are very troublesome; I dont deal with abusers like that and neither should you. Multiple commenters say that's just ad-hominem and not important: but it is important, and these guys are not nice people.

Fortunately I usually dont have bother with systemd much anyway - I have few services and they are running already. Shutdown and/or suspsend are sometimes broken but I can always just pull the power plug. Asking for passwords on encrypted disks is also pretty shit (console output overflows the prompts); it's just something else I have to workaround.

Actually I tried using it to stop udevd so I could determine what if anything it was doing on my system: and it refused to let me turn it off or disable it (or mask it, whatever they fuck they want call it). I stopped, disabled, and masked every 'service' or 'socket' with udev in the name, no asusage. I had to chmod the systemd-udevd binary to non-executable in the end.

The only saving grace is that systemd-udevd doesn't really do anything so it can't really fuck it up. Even systemd doesn't really do much apart from run a few scripts in some order.

Where's this going

Well i'm not really sure if i'll stick to a simple monolothic music service or go the whole hog and work on a modularised multi-process (and significnalty more secure) design. Simple is nice but the other approach has some relatively interesting things to play with.

But it's all very time-consuming and too sedentry. My body is falling apart.

I need to get out of the house more; every time i get stuck into a coding project (most recently for work) I seem to rapidly stack on weight. It's related to some (medicinal) drugs once taken and now stopped and obviously some over-consumption and it's fucking pissing me off. The weight is also completely fucking up my sleep and that's pissing me off even more. I'm pissed off a lot lately!

Tagged code, hacking.
Newer Posts | Older Posts
Copyright (C) 2018 Michael Zucchi, All Rights Reserved.Powered by gcc & me!