Jeff Epler's blog

19 March 2016, 23:35 UTC

New Desktop 2016

After many years of having an everyday laptop with a headless server, I decided I wanted an everyday desktop computer at home. The parts are on order. By my birthday I hope to have the new system up and running.

read more…

1 March 2016, 2:56 UTC

Literal copying of GPL code into ZFS on Linux

Recently, Canonical has announced that they plan to ship zfsonlinux in compiled form from their "main" repository. They rely on advice from their lawyers that the compiled form of zfs.ko, the kernel loadable module implementing zfs, is not a derivative of the linux kernel. This is important, because if zfsonlinux is a derivative of both GPL code and CDDL code, the two licenses impose incompatible requirements on the compiled form of the software, and distribution is not possible. (This is in contrast to Debian's plan to ship zfs in source form only in their next release (and also in the somewhat ghettoized "contrib" section rather than "main"); this is considered safer by many because the GPL's restrictions on code in source format are less stringent than code in object code or executable format)

There are two main ways that zfsonlinux's zfs.ko could be a derivative work of linux: First, and the option that many commenters have concentrated on, is if the act of compiling zfs also includes copyrighted portions of linux in a way that activates the GPL's restrictions because the combined work is "a work based on [the Linux kernel]". However, there is a second way that zfsonlinux could be subject to the GPL and CDDL simultaneously: if source code licensed exclusively under the GPL has been copied into the zfsonlinux source tree.

In this article, I collect some samples of code from zfsonlinux and compare those samples to code committed earlier to linux. I present the samples using a customized word diff algorithm. To reproduce my results, you will need to manually find the associated refs in linux.git and zfsonlinux/zfs.git and use your own word-diff algorithm.

I don't know whether I've found the worst of the code copying; I found the two examples given below pretty quickly, imagined that I had found just the tip of the iceberg, and then decided to write this article before looking for more. But I haven't found any more that are as clear-cut as these two examples are in my mind, while also being over ten lines long. Beginner's luck? Or did I find the 50 copied lines out of 260,000 lines in a half hour and that's the whole story?

Because I cannot speak for the authors of the code committed to linux.git which appear to be duplicated in zfsonlinux, it is impossible for me to say whether they have some private arrangement with the code authors that permit the use of the code snippets under the CDDL. If not, it's a legal question whether the amount of code copied is relevant under copyright law. In this area, I imagine caution is best; after all, in the US, Google's copying of the 9-line "RangeCheck" function (out of how many million lines in the JRE?) has been determined not to be de minimis, though in a new trial Google will assert a fair use defense regarding that copying.

(note: some popular RSS readers do not show the color coding of insertions and deletions)

Snippet A: linux at commit 5f99f4e79abc64ed9d93a4b0158b21c64ff7f478
Snippet B: zfsonlinux at commit 0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66
Common text

static inline bool dir_emit(struct dir_context *ctx,
                           const char *name, int namelen,
    uint64_t ino, unsigned type)
       return ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type) == 0;
static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
       return ctx->actor(ctx->dirent, ".", 1, ctx->pos,
                         file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0;
static inline bool dir_emit_dotdot(struct file *file, struct dir_context *ctx)
       return ctx->actor(ctx->dirent, "..", 2, ctx->pos,
                         parent_ino(file->f_path.dentry), DT_DIR) == 0;
static inline bool dir_emit_dots(struct file *file, struct dir_context *ctx)
       if (ctx->pos == 0) {
               if (!dir_emit_dot(file, ctx))
                       return false;
               ctx->pos = 1;
       if (ctx->pos == 1) {
               if (!dir_emit_dotdot(file, ctx))
                       return false;
               ctx->pos = 2;
       return true;

Snippet A: linux at c3c532061e46156e8aab1268f38d66cfb63aeb2d
Snippet B: zfsonlinux at 5547c2f1bf49802835fd6c52f15115ba344a2a8b
Common text

static inline int bdi_setup_and_register(struct backing_dev_info *bdi, char *name,
                           unsigned int cap)
        char tmp[32];
        int errerror;

        bdi->name = name;
        bdi->capabilities = cap;
        errerror = bdi_init(bdi);
        if (errerror)
                return err;(error);

        sprintf(tmp, "%.28s%s", name, "-%d");
        errerror = bdi_register(bdi, NULL, tmp, atomic_long_inc_return(&bdi_seqzfs_bdi_seq));
        if (errerror) {
                return err;(error);

        return 0;(error);


16 January 2016, 22:15 UTC

Ancho Reyes Hot Chocolate

Here's a winter-time drink that will warm you up in three ways—but it's not for kids. It is the best use I've found so far for a recent addition to my liquor cabinet, the Ancho Reyes chili liqueur. This stuff isn't killer hot like the jalapeno beers I've had (and hated), and it turns out to make an excellent addition to hot chocolate.


  • 2TBSP cocoa powder
  • 1TBSP granulated sugar (or more, to taste)
  • 1/2 cup whole milk, cold
  • 1/2 cup water, boiling
  • 2floz Ancho Reyes chili liqueur (to taste)
First, combine the cocoa powder, granulated sugar, and 2TBSP of the milk in a microwaveable mug. Whisk until the cocoa combines with the milk to form a paste. (this works best with "just the right amount" of cold milk. You'll know it when you see it. If you get too much milk, it just takes a bit more effort). Add the rest of the milk and microwave until warm. Add the Ancho Reyes and the hot water to fill your mug. Give one last whisk to combine everything, and enjoy while hot.

If you don't have a hot water kettle, you can combine the milk and water before microwaving. Don't add the liquor until after microwaving, though.

You may need to fine tune the sugar and liqueur to your own tastes, I like a less sweet and more spicy drink. Double the sugar or cut the chili liqueur in half according to your own preferences.


30 December 2015, 19:38 UTC

Coolest C Preprocessor Trick of the Year

Probably everyone knew about this but me, but here goes anyway. (hat tip: Google's ANGLE library)

By suitably defining SHADER_SOURCE, you can write your shader program as though it was just inline source in your larger C(++) program:

const char * fs = SHADER_SOURCE
            precision mediump float;
            void main()
                gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);

The definition of SHADER_SOURCE is simple:

#define SHADER_SOURCE(...) # __VA_ARGS__

This works as long as your shader is a valid sequence of preprocessor tokens. If you need to also use shader language directives like #version, you will need to write them as strings. But due to the way string catenation works, you can do

const char * fs =
    "#version 100\n"
and keep most of the inline shader source outside of strings.


2 December 2015, 23:12 UTC

Free Software, Meritocracy, and why I try to listen when 'SJWs' speak

Three quarters of a lifetime ago, I was a bullied fat kid in elementary school. Picked last for sports teams, if I bothered to even try playing with the other kids. Unaware of the rules while everyone else seemed to know innately how to play baseball, or soccer, or football, or whatever the game of the day was.

From their point of view, those athletic youths were probaby practicing a meritocracy: why would you pick the asthmatic fatty who couldn't even remember to dribble when playing basketball? I hadn't earned it. Those team captains knew the rules like they knew how to breathe. Me, I can go learn the rules on my own and lose a few pounds and then maybe I'll get picked to play.

In my teens, through BBSes and later the Internet I found communities where I was more accepted and where my computer skills gave me a measure of status. Many years later it's easy to imagine that I learned those skills effortlessly. Some of that may be an inherent aptitude, but the reality is probably that I learned much more from those around me than I realized.

Oh and did I mention that all along I was growing up in a dysfunctional household with a dad who was prone to angry verbal outbursts, something that I learned to imitate and have still not entirely managed to outgrow over twenty years after I cut him out of my life?

So anyway from the mid nineties through the present, I became a part of Hacker culture, Free Software culture, and specifically a part of the LinuxCNC project. During this time, we patted ourselves on the back because we were doing Important Work, because we were Revolutionary Thinkers who had seen the flaw in commercial software and closed development methods. I guess that only by the narrowest of margins did I avoid reading Ayn Rand and styling myself a libertarian and an objectivist.

What did I learn from my idols, people like Linus Torvalds and Eric Raymond? I learned that some people are such bad software developers that it would be better if they were run over by a bus than that they ever offer a contribution to Free Software again. And that as a result, it was their right (and mine) to verbally abuse those contributors until they stopped wasting our time.

What did I bring to LinuxCNC? An echo of childhood bullying, a habit of verbally abusing the people around me, and the idea that I was essentially born an elite hacker.

I'd like to think that I've never written anything truly vile and insulting on a Free Software mailing list or chat group, but in reality I'm sure I've crossed lines that I shouldn't have. More recently, my unmanaged irritation at "noobs" cuased me to largely shut down as a participant in the LinuxCNC community since if I took insults off the table the only course of action I knew was to remain silent and withdrawn.

And now, at age 40, I'm seriously reflecting on this for the first time. And what I see is that way into my adulthood, I'm more or less repeating playground bullying techniques against people who don't instictively configure their text editor to insert 4 spaces when they press tab, who don't know they have to "sign off" their commits or write documentation or a test or whatever road block I want to put up when they have a contribution to offer. I got to the top of something, and I haven't used that position to bring other people up with me, but to finally exercise a little power over people who are beneath me and less than me.

In short, I've been a bully and an abuser.

Why am I finally figuring this out now? I am sure it's a confluence of many things, but one of those things is how the so-called "Social Justice Warriors" (SJWs) have started to make their voices heard in our communities. Ironically, their voices have become louder for me the more that is said against them.

They say, build an inclusive community. Build everyone up, even first-timers who don't know all the scret handshakes. Don't accept that you're playing a zero-sum game where you have to tear everyone else down.

They say, show this by your conduct. Recognize that there are groups who are traditionally excluded from your community. Act in a way that not only avoids treating them unfairly, but which avoids even the appearance of treating them unfairly. Don't set up impossible barriers and pretend you would have been able to surmount them yourself.

I want to practice these ideals. I will fail a lot before I succeed, if I ever do succeed. But so many voices are now being raised, fellow people who want to succeed at this project and who will do so by lifting me up and who I have a duty to lift up in turn. Social Justice Warriors, thank you for your constructive criticism of the way I've been participating in Free Software development and generally as a person. I'm working on an updated and improved version that incorporates your feedback. Let me know what you think.


11 November 2015, 13:58 UTC

Community Builder reCAPTCHA

I had the unfortunate task of setting up a site with Joomla, Community Builder, and Kunena for

One problem with the Joomla "community" is that while the software is nominally GPL, there are lots of paid-only add-ons, sometimes for things that should be basic features.

(long treatise about Free Software and the difference between paying for software and paying for support elided so that we can just get to the good stuff)

One such basic feature is a CAPTCHA for the Community Builder new account creation process. After much searching, I found an older (2008) plugin that works with Joomla 3.4.5 and Community Builder 2.0.12 (the latest versions at the time of writing). This plugin's license is Creative Commons by-nc-nd/2.5/in, so while it is clear I can distribute the unmodified plugin, you have to use your own judgement to determine whether you are permitted to use it on any particular site.

This plugin warns that it is not compatible with the current Joomla and CB, but it works just fine. Since the license is a "no derivatives" license, I cannot provide a modified version which doesn't display this warning.

Files currently attached to this page:



4 November 2015, 15:34 UTC

HTTPS enabled thanks to Let's Encrypt

My blog should now be https enabled thanks to the fine people behind Let's Encrypt. This is good for everyone but a few people using IE on Windows XP, which I believe doesn't support a version of TLS new enough to connect.


12 October 2015, 14:03 UTC

NEJE "ROSH" 300mW laser engraver with LinuxCNC

I purchased a cheap (sub-$100) laser engraver from dxsoul. I can't in good conscience recommend this device to anyone, but I still wanted to take the time to write about my experience with it.

read more…

8 October 2015, 19:52 UTC

Turning off ads and google analytics

13 January 2015, 15:43 UTC

Maria Island

All older entries
Website Copyright © 2004-2014 Jeff Epler