Russ Allbery: Review: Blue Remembered Earth
| Series: | Poseidon's Children #1 |
| Publisher: | Ace |
| Copyright: | January 2012 |
| Printing: | June 2012 |
| ISBN: | 0-441-02071-2 |
| Format: | Hardcover |
| Pages: | 505 |
| Series: | Poseidon's Children #1 |
| Publisher: | Ace |
| Copyright: | January 2012 |
| Printing: | June 2012 |
| ISBN: | 0-441-02071-2 |
| Format: | Hardcover |
| Pages: | 505 |
For those with fond memories of the very successful DebConf13...
This photo is actually from a few years ago, but the white stuff has started to appear in some parts of the country. Maybe someone local will even be able to sneak down there and draw the Debian swirl in the snow.
It has become a tradition, that I'm going into Dolomites each October with friends using Pentax. This year the weather looked more like a winter than autumn, but still it was nice opportunity to take some mountain pictures.
We've started near Passo Rolle:
Filed under: English Photography Travelling 3 comments Flattr this!
We ve been trying to build Mono on MIPS in Debian for a long time. Just under a decade, in fact. Mono 0.29.99.20040114-3 was the first attempt, back when the Mono source was 10 meg, not today s ~80.
It never worked though. Not once. At the end of 2004, 10 upstream versions later, we gave up, and turned off mipsel as a target architecture in the package.
When I became a Debian Developer in 2009, one of the first things I did was try again with Mono on various previously unsupported architectures, by running a build on the Debian porterboxes. Supposedly MIPS support was there, as evidenced by all the MIPS-related files in the source tree. But I d try it, and it d fail, and upstream would say works for me . I repeat the process every major release or so, to see what s changed.
The breakthrough
Spurred by the removal of two bitrotted architectures (IA64 and SPARC), I decided to try again, this time investigating more deeply into the reason for the failures, with the help of upstream developer Alex R nne Petersen. A couple of hours of IRC-driven gdb and test program disassembly later, a seemingly innocent comment flagged something in my brain:
09-07-2013 15:10:11 < alexrp!~zor@baldr.rfw.name: TIL that mul and mult are not the same thing on mips
Why is this notable? Well, MIPS processors lack a whole bunch of instructions which are commonly used in assembler. MUL is one of them it s valid MIPS assembler, which is expanded to MULT/MFLO when compiling. Call it a macro, or a mnemonic, or shorthand the preferred term is pseudoinstructions . So what s the issue?
09-07-2013 15:18:27 > directhex: mono isn't trying to use a mul instruction, right? i mean, that instruction doesn't exist as far as the cpu is concerned, it's a macro the compiler does things with
See where this is headed?
09-07-2013 15:23:59 > directhex: mini/mini-mips.c:#define USE_MUL 1 /* use mul instead of mult/mflo for multiply */
Argh.
See, the thing about MIPS pseudoinstructions is they may be real instructions on a given CPU implementation. Strictly speaking MUL isn t a standard instruction, but a given CPU might have it anyway, to make multiplication a little faster (by using only one instruction, not two, for multiplication). In this case, the Debian MIPS infrastructure is based around ICT Loongson-2E processors which don t have that extension but the upstream Mono developers were building and testing on an extended CPU, never seeing the issue themselves.
Flipping that define to 0 (and amending the instruction length setting in another file) fixed the build. Mono was running on MIPS for me for the first time ever.
Digging through the history in git showed just how annoying this implementation quirk was. USE_MUL was added in late 2008 replacing a previously used #if 1 . The mult/mflo version of the code existed in the Mono source since the first time the full MIPS port was committed in 2006, but we never saw it.
The breakage
So, with that patched to work, I added mipsel to the Experimental build of Mono which still failed. The runtime would build fine, but the class library build would fail at random times, with random meaningless stack traces. Unrepeatable. Some kind of race condition. The build would eventually succeed if I hammered make a few times, but that s no good for the Debian build daemons. Back to square one
except I had an epiphany yesterday. I have heard more than once that Loongson processors are missing a few instructions. What if one of those was being hit, intermittently? I started doing a search in places that might need to work around that kind of issue, and found this. A patch to binutils in 2009, replacing one no-op instruction with another, when /usr/bin/as is fed the -mfix-loongson2f-nop flag.
Turns out NOP is another pseudoinstruction on MIPS. Well, more of an alias. The opcode 0 000000 is Shift Left Logical with 0 registers and 0 data, which is a no-op. But on all but the latest generation of Loongson-2F chips, that opcode can, under heavy load, fail causing inconsistent state in the CPU registers. The flag to as replaces sll 0,0,0 with or $at,$at,0 , which is also a no-op instruction, but doesn t trigger the failure on Loongson-2F chips (and 2E chips, although that s not stated in the documentation).
As long as ALL your programs get fed through as , you don t have a problem, since it uses the replacement opcode but what if you use a JITter to generate your own opcodes? Oh fuck, it couldn t be
diff --git a/mono/arch/mips/mips-codegen.h b/mono/arch/mips/mips-codegen.h
index dc4df7d..1dbd1c6 100644
--- a/mono/arch/mips/mips-codegen.h
+++ b/mono/arch/mips/mips-codegen.h
@@ -334,7 +334,7 @@ enum
/* misc and coprocessor ops */
#define mips_move(c,dest,src) mips_addu(c,dest,src,mips_zero)
#define mips_dmove(c,dest,src) mips_daddu(c,dest,src,mips_zero)
-#define mips_nop(c) mips_sll(c,0,0,0)
+#define mips_nop(c) mips_or(c,mips_at,mips_at,0)
#define mips_break(c,code) mips_emit32(c, ((code)<<6) 13)
#define mips_mfhi(c,dest) mips_format_r(c,0,0,0,dest,0,16)
#define mips_mflo(c,dest) mips_format_r(c,0,0,0,dest,0,18)
Oh yes it could! Mono was using sll 0,0,0 (the recommended no-op instruction from the MIPS instruction reference manual), causing failures in my tests, because Debian s build and test infrastructure just happens to use defective silicon. And, again, upstream were unable to reproduce a problem because they use better silicon than we do.
So what now?
Well, last night I uploaded mono_3.2.3+dfsg-3, which includes the above patch to force the replacement no-op instruction. It test built fine on the porterbox, and it should (when the damn experimental buildd gets around to it), just work.
Finally.
After just under a decade, Mono packages will be available on MIPS in Debian.
And after all this time, all we had to change was 4 lines to work around 7 year old Chinese knock-off processors.
The edit
So, things are finally built.
It turns out that despite everything, the replacement NOP opcode is not enough.
If you re-read the post to the binutils list, pay close attention to:
In theory this is still not enough to fully eliminate possible hangs, but the possiblity is extremely low now and hard to be hit in real code.
It s a filthy lie. It s easy to hit the issue in real code: just do a from-source build of the whole Mono class library. With the replacement instruction it builds .NET 2.0, 3.0, 3.5, 4.0, and most of 4.5, before dying in the same way as before an improvement on failing early in the 2.0 build, but not enough.
Thankfully, 2 out of the 5 Debian mipsel build servers are not Loongson 2 they re 11 year old Broadcom SWARM developer boards. Not fast but also not broken. Luck smiled on me, and caused my build to go to one of these Broadcom machines. As a result
(experimental_mipsel-dchroot)directhex@eder:~$ mono --version head -1
Mono JIT compiler version 3.2.3 (Debian 3.2.3+dfsg-3)
It s been a long time coming.
Snitch is the first DSL I ve written in Hy. It may be the first Hy DSL ever, but I have nothing to prove that.
Since I ve had a bit of time while the hard-working Alioth maintainers hack on getting vasks alive, I wrote Snitch (and set up the Debian view to be shown on fraked.debian.net - more to come!)
Snitch's DSL looks like:
(rules "personal" (rule "pault.ag" pingable httpable) (rule "lucifer.pault.ag" pingable httpable))Which expands out to quite a few lines that query the server s status using Snitch s informants, and insert the result into MongoDB. More to come!
After running a QNAP TS-459 Pro+ for the last 3 or 4 years at home, my monitoring was alerting me about memory warnings cause I upgraded my SqueezeBox Server to the latest nightly version. So I looked into how to upgrade the shipped Adata SU3S1333B1G9-B.
It seems that the KVR1333D3S8S9/2G should work, so I ordered one. After plugin it in, it revealed that the module wasn't working while it worked for others. After digging around, it seems essentially that the modul has a 8-chip design. Indeed, my modul just has only 8 memory chips, but the design is a 16 chip. So I thought it would be a nice try to order the one from amazon that worked for others.
And like expected it's not the same module but has the same Kingston Part Number.
As you can see, the 16 chip design module has printed '9905428-189.A00lf' on and the 8 chip design '9931712-009.A00G'. It's something like in the Wireless LAN USB dongle business where they sell totally different hardware with the same Part Number but different Revisions.
I also ordered a Samsung M471B5773DH0-CH9 cause that's also a 8 chip design.
To make it short, both 8 chips design modules worked like a charm, the M471B5773DH0-CH9 and the KVR1333D3S8S9/2G (9931712-009.A00G). - Please avoid the Adolf one from Kingston! ;)
| Series: | Elemental Logic #3 |
| Publisher: | Small Beer Press |
| Copyright: | 2007 |
| ISBN: | 1-931520-23-2 |
| Format: | Trade paperback |
| Pages: | 332 |
Changes:
freetype (2.5.0.1-0.1) UNRELEASED; urgency=low
.
* Non-maintainer upload.
* Now make it "multiple upstream source" style instead of "tar-in-tar".
New style makes it easier to check source code with search engine like
sources.debian.net.
* use "3.0 (quilt)" in debian/source/format
- merge debian/patches-freetype and patches-ft2demos to debian/patches
- drop patches since merged to upstream
+ savannah-bug-37907.patch
+ savannah-bug-37906.patch
+ savannah-bug-37905.patch
+ savannah-bug-35847.patch
+ savannah-bug-35833.patch
+ ft2demos-2.1.7-no-rpath.patch (cannot be applied)
- refresh patches
+ fix compiler warning in compiler_hardening_fixes.patch
* simplify debian/rules and separate some thing to debian/* files
- don't install GPLv2.TXT (not GPL.TXT)
* debian/control
- add "Build-Depends: libpng12-dev libpng-dev"
* update debian/libfreetype6.symbols
$ dget http://www.mithril-linux.org/~henrich/debian/package/temp/freetype_2.5.0.1-0.1.dsc
$ wget http://www.mithril-linux.org/~henrich/debian/package/temp/libfreetype6_2.5.0.1-0.1_amd64.deb
Today I ll be working out how to properly configure DNSSEC on a BIND9 installation, I ll also make sure to give you all the needed instructions to properly verify if a specific domain is being correctly covered by DNSSEC itself. In addition to that a few more details will be provided about adding the relevant SSHFP s entries on your DNS zone files to be able to automatically verify the authenticity of your domain when connecting to it with SSH avoiding any possible MITM attack.
First of all, let s create the Zone Signing Key (ZSK) which is the key that will be responsible to sign any other record on the zone file which is not a DNSKEY record itself:
dnssec-keygen -a RSASHA1 -b 1024 -n ZONE gnome.org
32:bind97-9.7.0-17.P2.el5_9.2.x86_64 : The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server Repo : rhel-x86_64-server-5 Matched from: Filename : /usr/sbin/dnssec-keygen
32:bind-9.8.2-0.17.rc1.el6.3.x86_64 : The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server Repo : rhel-x86_64-server-6 Matched from: Filename : /usr/sbin/dnssec-keygen
dnssec-keygen -a RSASHA1 -b 2048 -n ZONE -f KSK gnome.org
cat Kgnome.org*.key >> gnome.org
$INCLUDE /srv/dnssec-keys/Kgnome.org+005+12345.key $INCLUDE /srv/dnssec-keys/Kgnome.org+005+67890.key
dnssec-signzone -K /path/to/your/dnssec/keys -e +3024000 -N INCREMENT gnome.org
#!/bin/sh SIGNZONE="/usr/sbin/dnssec-signzone" DNSSEC_KEYS="/srv/dnssec-keys" NAMEDCHROOT="/var/named/chroot" ZONEFILES="gnome.org" cd $NAMEDCHROOT for ZONE in $ZONEFILES; do $SIGNZONE -K $DNSSEC_KEYS -e +3024000 -f $ZONE.signed -N INCREMENT $ZONE done /sbin/service named reload
zone "gnome.org" file "gnome.org.signed"; ;
;; ANSWER SECTION: gnome.org. 888 IN DNSKEY 257 3 5 AwEAAbRD7AymDFuKc2iXta7HXZMleMkUMwjOZTsn4f75ZUp0of8TJdlU DtFtqifEBnFcGJU5r+ZVvkBKQ0qDTTjayL54Nz56XGGoIBj6XxbG8Es+ VbZCg0RsetDk5EsxLst0egrvOXga27jbsJ+7Me3D5Xp1bkBnQMrXEXQ9 C43QfO2KUWJVljo1Bii3fTfnHSLRUsbRn8Puz+orK71qxs3G9mgGR6rm n91brkpfmHKr3S9Rbxq8iDRWDPiCaWkI7qfASdFk4TLV0gSVlA3OxyW9 TCkPZStZ5r/WRW2jhUY/kjHERQd4qX5dHAuYrjJSV99P6FfCFXoJ3ty5 s3fl1RZaTo8=
dig . DNSKEY grep -Ev '^($ ;)' > root.keys dig +sigchase +trusted-key=./root.keys gnome.org. A cat -n
105 ;; WE HAVE MATERIAL, WE NOW DO VALIDATION 106 ;; VERIFYING DS RRset for org. with DNSKEY:59085: success 107 ;; OK We found DNSKEY (or more) to validate the RRset 108 ;; Ok, find a Trusted Key in the DNSKEY RRset: 19036 109 ;; VERIFYING DNSKEY RRset for . with DNSKEY:19036: success 110 111 ;; Ok this DNSKEY is a Trusted Key, DNSSEC validation is ok: SUCCESS
ssh-keygen -r $(hostname --fqdn) -f /etc/ssh/ssh_host_rsa_key.pub
ssh -oVerifyHostKeyDNS=yes -v subdomain.gnome.org
VerifyHostKeyDNS=yes
debug1: Server host key: RSA 00:39:fd:1a:a4:2c:6b:28:b8:2e:95:31:c2:90:72:03 debug1: found 1 secure fingerprints in DNS debug1: matching host key fingerprint found in DNS debug1: ssh_rsa_verify: signature correct
Last week was the
OpenStack Design Summit Icehouse
in Hong-Kong where we, OpenStack developers, discussed and designed the new
OpenStack release (Icehouse) that is coming up.
The week has been wonderful. It was my second OpenStack design summit, and I
loved it. Bumping into various people I've never met so far and worked with
online was a real pleasure. As it was to meet again with fellow OpenStack
developers! The event organisation was great, as were the parties. :-)
On the last day, I had the chance to present a talk with Eoghan Glynn and
Nick Barcet how we built the auto-scaling feature in Heat, implementing the
"alarming" feature needed in Ceilometer.
In Haskell, lists are ubiquitous. In real-world Haskell, monads are ubiquitous. So it should be an easy task to fill a list with values obtained in a monad, i.e. a list of n random numbers (in the Rand monad), or getting some input from the user, and storing it in a list, until the user chooses to finish the input.
The task
For now, assume a function getInput :: IO Int; we want to run it 10000 and then have the list of the values returned. Sounds simple and straight forward, but it is actually really hard to get the run-time behaviour that we naively and optimistically expect.
The expectation
In an imperative setting, we would have a simple counting loop. In the loop, we run getInput, allocate a new cell for the linked list, and append it to the list. Clearly, this
accumAppend :: Int -> IO [Int]
accumAppend n = go n []
where
go 0 l = return l
go n l = do x <- getInput; go (n-1) (l++[x])
To check the space usage of this, I pass -Kn to the GHC runtime and see what limit is just enough to let this program calculate accumAppend 10000 and fully evaluate the resulting list. It turns out that we need 328336 bytes of stack space.
So what about the second requirement; that the list is fully evaluated? Experienced Haskellers see it immediatelly: The accumulator is not used in the loop, so each iteration adds a thunk around the previous value, that would add the next entry to the end. Only when the list is actually used, these are run, each traversing the whole list, causing quadratic cost. We can verify this using ghc-vis:
accumAppendSeq :: Int -> IO [Int]
accumAppendSeq n = go n []
where
go 0 l = return l
go n l = do x <- getInput ; go (n-1) $!! (l++[x])
As the accumulator gets fully evaluated before being passed to the next invocation of go, the result will not contain thunks. But note that this has also fixed the stack consumption: The code now runs the smallest setting for -K, 8 bytes. This works as both go and deepseq are tail-recursive.
But this is still not the solution we are looking for, as the quadradic cost caused by using ++ is still there.
Attempt 3: The accumulator (reversed)
Since we know that l++[x] is expensive, but x:l is cheap, we can simply use this to update the accumulator. This has the slightly annoying consequence that the entries of the list are in the reverse order, but we can fix that in the base case:
accumReverse :: Int -> IO [Int]
accumReverse n = go n []
where
go 0 l = return (reverse l)
go n l = do x <- getInput ; go (n-1) (x:l)
And indeed, we get noticably faster code that still runs in 8 bytes of stack. Unfortunately, we still don t construct the final list directly.
Attempt 4: Naive recursion
Maybe we can do without an accumulator. The most naive such code would be
listRecurse :: Int -> IO [Int]
listRecurse n = go n
where
go 0 = return []
go n = do x <- getInput; r <- go (n-1); return (x:r)
and I d expect that most experienced Haskellers would write that code (if they are asked not to use a library function). And indeed, this code does create the final list directly. But it requires a large stack or 164616 bytes. The reason is that this is no longer tail recursive: After calling go again we need to take the result and prepend x
Attempt 5: library functions
Maybe we should simply not worry about the implementation, and use library functions? Clearly, the authors of such libraries have found the best solution. So how does
listReplicateM :: Int -> IO [Int] listReplicateM n = Control.Monad.replicateM n getInputfare? Unfortunately, not better than the naive recursion. In fact, the stack space requirement is the same 164616 bytes. The same holds when using special libraries for generating and consuming list, e.g. the Streams module from the vector package:
listStreams :: Int -> IO [Int] listStreams n = MStream.toList $ MStream.replicateM n getInputAttempt 6: Difference lists It is time to dig deeper into our box of tricks. What if we have lists with constant time Snoc (a.k.a. appending a new element)? Then Attempt 3 would not require reversing the list. Such lists are provided by difference lists; there are libraries for that, but we can simply implement them using lambdas:
accumDList :: Int -> IO [Int]
accumDList n = go n id
where
go 0 l = return (l [])
go n l = do x <- getInput; go (n-1) (l . (x:))
Indeed, no stack is required (8 bytes are enough). But we are cheating here: We are still not constructing the final list, but rather we combine functions that append elements to lists. So when accumDList returns, what we have in memory, is a thunk and sequence of partial function applications in the wrong order, and evaluating the thunk does basically the same thing as reverse in Attempt 3. It might be a bit faster, is still not satisfying enough:
listUnsafeInterleave :: Int -> IO [Int]
listUnsafeInterleave n = do l <- go n; return $!! l
where
go 0 = return []
go n = do x <- getInput
r <- unsafeInterleaveIO (go (n-1))
return (x:r)
The stack consumption is 8 bytes. It is worth noting that the all to deepseq (in $!!) will actually drive the evaluation of go. Also, it guarantees that the unsafe effects of unsafeInterleaveIO are confined to the execution of listUnsafeInterleave, i.e. are actually safe.
Run time statistics
I ran criterion over the functions (generating lists of length 1000), and found these results:

here's the list of RC bugs I've worked on during the last week.
One week ago, a thread in opam-devel mailing list started about the possibility to create binary snapshot to distribute OPAM packages. Distributing binary packages with everything already compiled is pretty useful when you want to make sure that everyone has the same version of packages installed and you don't want to spend time configuring all the computer of your colleague.
As a matter of fact I was also interested to see that happening. I have several computers where I want to install a set of packages and I want to snapshot OPAM archives when I am ready for an upgrade. I have tested for a long time another source distribution: GODI. I even wrote a puppet module to drive it. This was a fun experience, but as with any source only distribution, there are some drawbacks. Especially even if it is fully automated, you get a lot of errors and timeout when trying to build automatically from source.
This is how opam2debian has started. I wanted a replacement for puppet-godi that takes advantage of OPAM and the possibility to distribute my set of packages everywhere quickly.
The goals of this project are:
$ opam2debian create --build --name opam2debian-test2 --compiler 4.01.0 \ ocamlfind fileutils ocaml-data-notation ocaml-expect ounit \ ocamlmod ocamlify oasis yojson sexplib extlib pcre-ocaml \ calendar ocaml-inifiles ocamlnet ocurl gettext inotify ocaml-sqlexpr \ ocamlrss ocaml-xdg-basedirGetting the package list right can be tricky because the process will stop at the first error -- and if it is because the last package fails to build it can be long. I have implemented a --keep-build-dir in case you want to tune the package list live. The program will build everything and it can takes quite a while. At the end you get a file opam2debian-test2_20131105_amd64.deb which has a reasonable size of 232MB. That is big, but it looks like the biggest directory is $OPAMROOT/4.01.0/build, I am not sure if I can remove it but we may save some space here (the build directory represents 50% of the package size). Then you can just do a standard Debian installation:
$ sudo dpkg -i opam2debian-test2_20131105_amd64.debAnd you can use it:
$ eval $(opam config env --root /opt/opam2debian/opam2debian-test2/) $ which ocamlfind /opt/opam2debian/opam2debian-test2/4.01.0/bin/ocamlfind $ ocamlfind list [...] stdlib (version: [distributed with Ocaml]) str (version: [distributed with Ocaml]) threads (version: [distributed with Ocaml]) threads.posix (version: [internal]) threads.vm (version: [internal]) type_conv (version: 109.41.00) unidiff (version: 0.0.2) unix (version: [distributed with Ocaml]) userconf (version: 0.3.1) xdg-basedir (version: 0.0.3) xmlm (version: 1.1.1) yojson (version: 1.1.5)A nice thing to note, is that it is a standard OPAM install. You can install, update and upgrade OPAM from there, as root. However, I would recommend not to do it, and just rebuild a newer Debian package to upgrade. Install You will need the opam and proot Debian package available in Debian jessie and sid. You will also need various OCaml libraries (cmdliner, calendar, fileutils and jingoo). Download the opam2debian tarball on the forge, build and install it. The project is hosted on github. Open issues On the initial list of goals of the project. Not everything is completed. I have still several open issues. In particular 4. (create snapshot of OPAM repository) was blocked by a bug in opam-mk-repo, that prevents snapshots (see my pull-request to solve it). Another issues is about licenses of the included files. I should list them all and I need to figure out a way to extract every licences. Submit bugs directly to github.
config interface 'loopback'
option ifname 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'
config globals 'globals'
option ula_prefix 'fdbf:4c12:3fed::/48'
config interface 'lan'
option ifname 'eth0'
option type 'bridge'
option proto 'dhcp'
option ipaddr '192.168.1.1'
option netmask '255.255.255.0'
option hostname 'tl-mr3040'
option ip6assign '60'
config interface 'mesh'
option ifname 'adhoc0'
option mtu '1528'
option proto 'batadv'
option mesh 'bat0'
/etc/config/wireless
config wifi-device 'radio0'
option type 'mac80211'
option channel '11'
option hwmode '11ng'
option path 'platform/ar933x_wmac'
option htmode 'HT20'
list ht_capab 'SHORT-GI-20'
list ht_capab 'SHORT-GI-40'
list ht_capab 'RX-STBC1'
list ht_capab 'DSSS_CCK-40'
option disabled '0'
config wifi-iface 'wmesh'
option device 'radio0'
option ifname 'adhoc0'
option network 'mesh'
option encryption 'none'
option mode 'adhoc'
option bssid '02:BA:00:00:00:01'
option ssid 'meshfx@hackeriet'
/etc/config/batman-adv
config 'mesh' 'bat0'
option interfaces 'adhoc0'
option 'aggregated_ogms'
option 'ap_isolation'
option 'bonding'
option 'fragmentation'
option 'gw_bandwidth'
option 'gw_mode'
option 'gw_sel_class'
option 'log_level'
option 'orig_interval'
option 'vis_mode'
option 'bridge_loop_avoidance'
option 'distributed_arp_table'
option 'network_coding'
option 'hop_penalty'
# yet another batX instance
# config 'mesh' 'bat5'
# option 'interfaces' 'second_mesh'
The mesh node is now operational. I have yet to test its range,
but I hope it is good. I have not yet tested the TP-Link 3600 box
still wrapped up in plastic.
(This is a reproduction of the mail sent to -announce for the planet readers)
Aloha, hackers,
As some of you notice from the slamn default background in wheezy, (BTW;Next.