<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<link rel="alternate" type="text/html" href="https://emergent.unpythonic.net/"/>

<title>Jeff Epler's blog</title>
<modified>2016-03-01T02:56:18Z</modified>
<tagline>Photos, electronics, cnc, and more</tagline>
<author><name>Jeff Epler</name><email>jepler@unpythonic.net</email></author>
<entry>
<title>Literal copying of GPL code into ZFS on Linux</title>
<issued>2016-03-01T02:56:18Z</issued>
<modified>2016-03-01T02:56:18Z</modified>
<id>https://emergent.unpythonic.net/01456800978</id>
<link rel="alternate" type="text/html" href="https://emergent.unpythonic.net/01456800978"/>
<content type="text/html" mode="escaped">

Recently, Canonical has announced that they plan to ship zfsonlinux in compiled form from their &amp;quot;main&amp;quot; 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 &amp;quot;contrib&amp;quot; section rather than &amp;quot;main&amp;quot;);
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)

&lt;p&gt;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 &amp;quot;a work based on [the Linux kernel]&amp;quot;.
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.

&lt;p&gt;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.

&lt;p&gt;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?

&lt;p&gt;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 &amp;quot;RangeCheck&amp;quot; function (out of how many million lines in the JRE?) has been determined not to be &lt;a href=&quot;https://en.wikipedia.org/wiki/De_minimis#Copyright&quot;&gt;&lt;em&gt;de minimis&lt;/em&gt;&lt;/a&gt;, though in a new trial Google will assert a fair use defense regarding that copying.

&lt;p&gt;(note: some popular RSS readers do not show the color coding of insertions and deletions)

&lt;p&gt;&lt;hr&gt;

            &lt;style&gt;
            .wdiff { white-space: pre-wrap; font-family: mono; }
            .wdiff-same { color: black; }
            .wdiff-insert { color: #3f3; text-decoration: underline; }
            .wdiff-delete { color: #888; text-decoration: line-through; }
            &lt;/style&gt;&lt;div style=&quot;color:#888&quot;&gt;Snippet A: &lt;span&gt; linux at commit 5f99f4e79abc64ed9d93a4b0158b21c64ff7f478&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color:#3f3&quot;&gt;Snippet B: &lt;span&gt; zfsonlinux at commit 0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color:#000&quot;&gt;Common text&lt;/span&gt;&lt;/div&gt;&lt;br&gt;&lt;pre class=&quot;wdiff&quot;&gt;&lt;span class=&quot;wdiff-same&quot;&gt;static inline bool&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;dir_emit(struct dir_context *ctx,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
                           &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;const char *name, int namelen,&lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;
                           u64&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;
    uint64_t&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; ino, unsigned type)
{
       return ctx-&amp;gt;actor(ctx&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;-&amp;gt;dirent&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;, name, namelen, ctx-&amp;gt;pos, ino, type) == 0;
}&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;static inline bool&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;dir_emit_dot(struct file *file, struct dir_context *ctx)
{
       return ctx-&amp;gt;actor(ctx&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;-&amp;gt;dirent&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;, &amp;quot;.&amp;quot;, 1, ctx-&amp;gt;pos,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
                         &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;file-&amp;gt;f_path.dentry-&amp;gt;d_inode-&amp;gt;i_ino, DT_DIR) == 0;
}&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;static inline bool&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;dir_emit_dotdot(struct file *file, struct dir_context *ctx)
{
       return ctx-&amp;gt;actor(ctx&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;-&amp;gt;dirent&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;, &amp;quot;..&amp;quot;, 2, ctx-&amp;gt;pos,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
                         &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;parent_ino(file-&amp;gt;f_path.dentry), DT_DIR) == 0;
}&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;static inline bool&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;dir_emit_dots(struct file *file, struct dir_context *ctx)
{
       if (ctx-&amp;gt;pos == 0) {
               if (!dir_emit_dot(file, ctx))
                       return false;
               ctx-&amp;gt;pos = 1;
       }
       if (ctx-&amp;gt;pos == 1) {
               if (!dir_emit_dotdot(file, ctx))
                       return false;
               ctx-&amp;gt;pos = 2;
       }
       return true;
}&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;hr&gt;
&lt;div style=&quot;color:#888&quot;&gt;Snippet A: &lt;span&gt; linux at c3c532061e46156e8aab1268f38d66cfb63aeb2d&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color:#3f3&quot;&gt;Snippet B: &lt;span&gt; zfsonlinux at 5547c2f1bf49802835fd6c52f15115ba344a2a8b&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color:#000&quot;&gt;Common text&lt;/span&gt;&lt;/div&gt;&lt;br&gt;&lt;pre class=&quot;wdiff&quot;&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;static inline &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;bdi_setup_and_register(struct backing_dev_info *bdi,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;char *name,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
                           &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;unsigned int cap)
{
        char tmp[32];
        int &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;;

        bdi-&amp;gt;name = name;
        bdi-&amp;gt;capabilities = cap;
        &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; = bdi_init(bdi);
        if (&lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;)
                return &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err;&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;(error);&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;

        sprintf(tmp, &amp;quot;%.28s%s&amp;quot;, name, &amp;quot;-%d&amp;quot;);
        &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; = bdi_register(bdi, NULL, tmp,&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt; &lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;atomic_long_inc_return(&amp;amp;&lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;bdi_seq&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;zfs_bdi_seq&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;));
        if (&lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;) {
                bdi_destroy(bdi);
                return &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;err;&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;(error);&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
        }

        return &lt;/span&gt;&lt;span class=&quot;wdiff-delete&quot; style=&quot;color: #888; text-decoration: line-through;&quot;&gt;0;&lt;/span&gt;&lt;span class=&quot;wdiff-insert&quot; style=&quot;color: #3f3; text-decoration: underline&quot;&gt;(error);&lt;/span&gt;&lt;span class=&quot;wdiff-same&quot;&gt;
}&lt;/span&gt;&lt;/pre&gt;
&lt;hr&gt;
</content>
</entry>
</feed>
