]> xenbits.xensource.com Git - people/dstodden/blktap-dkms.git/commitdiff
blktap-dkms: Intro.
authorDaniel Stodden <daniel.stodden@citrix.com>
Tue, 12 Jul 2011 22:16:52 +0000 (15:16 -0700)
committerDaniel Stodden <daniel.stodden@citrix.com>
Tue, 12 Jul 2011 22:20:04 +0000 (15:20 -0700)
 - Collects sources from blktap/next- trees living in some
   $(GIT_REPO).
 - Generates backport patches from the former.
 - Builds a DKMS-compatible source tree.

Signed-off-by: Daniel Stodden <daniel.stodden@citrix.com>
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
bin/backports [new file with mode: 0755]
bin/kernelbranches [new file with mode: 0755]
bin/kernelversions [new file with mode: 0755]
dkms.head.conf.in [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..1e37af9
--- /dev/null
@@ -0,0 +1,7 @@
+src/
+dkms.*.conf
+rev.mk
+.stamp-*
+*~
+*.out
+*.deb
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..38ebe00
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,150 @@
+#
+# Assemble a blktap source package with DKMS.
+#
+
+PATH           := $(CURDIR)/bin:$(PATH)
+KERN_REPO      := git://xenbits.xensource.com/people/dstodden/linux.git
+GIT            := git
+BRANCH_PREFIX  := xenbits/blktap/next-
+
+export PATH
+export GIT
+
+-include rev.mk
+
+PKG_NAME    = blktap
+PKG_VERSION = $(shell echo $(REV:v%=%) | tr - +)
+SRCDIR      = src
+DEB         = $(PKG_NAME)-dkms_$(PKG_VERSION)_all.deb
+
+BRANCH_SOURCES =               \
+       drivers/block/blktap    \
+       include/linux/blktap.h
+
+SUDO           = sudo
+DKMS           = dkms -m $(PKG_NAME) -v $(DKMS_VERSION)
+DKMS_VERSION   = $(PKG_VERSION)
+DKMS_SRCDIR    = /usr/src/$(PKG_NAME)-$(DKMS_VERSION)
+DKMS_DSCDIR    = /var/lib/dkms/$(PKG_NAME)/$(DKMS_VERSION)/dsc
+DKMS_DEBDIR    = /var/lib/dkms/$(PKG_NAME)/$(DKMS_VERSION)/deb
+DKMS_TPLDIR    = $(DKMS_SRCDIR)/$(PKG_NAME)-dkms-mkdeb
+DKMS_DEB       = $(DKMS_DEBDIR)/$(DEB)
+
+DKMS_FRAGS =                   \
+       dkms.head.conf          \
+       dkms.backports.conf     \
+       dkms.extras.conf
+
+BACKPORTDIR = $(SRCDIR)/patches/backports
+EXTRASDIR   = $(SRCDIR)/patches/extras
+
+.PHONY: checkout       \
+       backports       \
+       dkms            \
+       extras          \
+       source          \
+       install
+
+.DELETE_ON_ERROR:              \
+       rev.mk                  \
+       kernelbranches.out
+
+all: .stamp-source
+
+source: .stamp-checkout .stamp-backports .stamp-extras \
+       $(SRCDIR)/dkms.conf $(SRCDIR)/Makefile
+
+rev.mk: kernelbranches.out
+       > $@
+       (echo -n "KVER = "; head -n1 | cut -d: -f2;) < $< >> $@
+       (echo -n "REV  = "; head -n1 | cut -d: -f3;) < $< >> $@
+
+kernelbranches.out:
+       kernelbranches $(KERN_REPO) $(BRANCH_PREFIX) > $@
+
+nexti = read i 2>/dev/null < $(1) || i=0; echo $$i; echo $$((i+1)) > $(1)
+
+.stamp-checkout:
+       $(GIT) archive --remote=$(KERN_REPO) --format=tar       \
+               --prefix=$(SRCDIR)/ $(REV) $(BRANCH_SOURCES) |  \
+               tar xf -
+       touch $@
+
+.stamp-backports:
+       rm -rf dkms.backports.conf $(BACKPORTDIR)
+       mkdir -p $(BACKPORTDIR)
+       cd $(BACKPORTDIR); \
+               backports $(KERN_REPO) $(BRANCH_PREFIX) $(BRANCH_SOURCES) | \
+                       while read file pattern; do \
+                               n=$$($(call nexti,patchno)); \
+                               echo "PATCH[$$n]='backports/$$file'"; \
+                               echo "PATCH_MATCH[$$n]='$$pattern'"; \
+                       done >> $(CURDIR)/dkms.backports.conf;
+       touch $@
+
+.stamp-extras:
+       rm -rf dkms.extras.conf $(EXTRASDIR)
+       mkdir -p $(EXTRASDIR)
+       find patches/extras -name \*.diff | \
+       while read patch; do \
+               cp $$patch $(EXTRASDIR); \
+               n=$$($(call nexti,patchno)); \
+               echo "PATCH[$$n]=extras/$$(basename $$patch)"; \
+       done >> dkms.extras.conf
+       touch .stamp-$@
+
+$(SRCDIR)/Makefile:
+       > $@
+       echo 'export CONFIG_BLK_DEV_TAP = m' >> $@
+       echo 'obj-$$(CONFIG_BLK_DEV_TAP) := drivers/block/blktap/' >> $@
+       echo 'KBUILD_CPPFLAGS += -I$$(src)/include' >> $@
+
+dkms.head.conf: dkms.head.conf.in .stamp-checkout
+       sed -e's/@PKG_NAME@/$(PKG_NAME)/'       \
+           -e's/@PKG_VERSION@/$(PKG_VERSION)/' \
+       < $< > $@
+
+$(SRCDIR)/dkms.conf: .stamp-backports .stamp-extras $(DKMS_FRAGS)
+       cat $(DKMS_FRAGS) > $@
+
+install: .stamp-source sudo-dkms-install
+
+sudo-%:
+       $(SUDO) $(MAKE) $*
+
+dkms-install:
+       rm -rf $(DKMS_SRCDIR)
+       ln -s $(CURDIR)/$(SRCDIR) $(DKMS_SRCDIR)
+       $(DKMS) add
+       touch .stamp-$@
+
+dkms-build:
+       $(DKMS) build
+       touch .stamp-$@
+
+dkms-deb:
+       $(DKMS) mkdeb --source-only
+       touch .stamp-$@
+
+$(DKMS_TPLDIR):
+       mkdir -p $(DKMS_TPLDIR)
+       cp -r template/debian $(DKMS_TPLDIR)/
+
+dkms-template: $(DKMS_TPLDIR)
+
+dkms-clean:
+       [ -z "$$($(DKMS) status)" ] || $(DKMS) remove --all
+       rm -rf $(DKMS_SRCDIR)
+       rm -f .stamp-dkms-*
+
+$(DKMS_DEB): sudo-dkms-deb
+
+$(DEB):        $(DKMS_DEB)
+       cp $(DKMS_DEB) $(DEB)
+
+deb: $(DEB)
+
+clean: sudo-dkms-clean
+       rm -rf src
+       rm -f .stamp-checkout .stamp-backports .stamp-extras patchno
+       rm -f $(DKMS_FRAGS)
diff --git a/bin/backports b/bin/backports
new file mode 100755 (executable)
index 0000000..5a1a4da
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+set -x
+
+usage ()
+{
+       echo "Usage: $(basename $0) <git-repo-dir> <branch-prefix> <sources>" 1>&2
+}
+
+fail ()
+{
+       usage
+       exit 1
+}
+
+GIT_REPO=$1
+shift || fail
+
+BRANCH_PREFIX=$1
+shift || fail
+
+SOURCES="$*"
+
+#
+# Find version $BRANCH in $GIT_REPOS's
+# $REMOTE. e.g. 'xenbits'/'blktap/next'-<version>. Sed out the
+# <version> strings. Sort them numerically (!), descending.
+#
+VERSIONS=$(kernelbranches $GIT_REPO $BRANCH_PREFIX | cut -d: -f2)
+[ -n "$VERSIONS" ] || exit 1
+
+#
+# $HEAD is the most recent branch.
+# $FIRST is that oldest found supported.
+# $PREV is the sorted ]$HEAD; $FIRST] sequence
+#
+set -- $VERSIONS
+HEAD=$1
+shift
+
+while [ -n "$1" ]
+do
+       FIRST=$1
+       PREV="$PREV $1"
+       shift
+done
+
+filesize ()
+{
+       stat -c%s $1
+}
+
+#
+# Generate a stack of backports from $HEAD down to $FIRST
+#
+
+head=$HEAD
+for prev in $PREV
+do
+       patch=backport-$prev.diff
+
+       git --git-dir=$GIT_REPO \
+               diff $BRANCH_PREFIX$head $BRANCH_PREFIX$prev \
+               -- $SOURCES 2>/dev/null > $patch
+
+       if [ $? -ne 0 -o $(filesize $patch) -eq 0 ]
+       then
+               rm -f $patch
+       else
+               echo $patch $(kernelversions regex $FIRST $head)
+       fi
+       
+       head=$prev
+done
diff --git a/bin/kernelbranches b/bin/kernelbranches
new file mode 100755 (executable)
index 0000000..c4eaacc
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/bash
+#
+#set -x
+
+usage ()
+{
+       echo "Usage: $(basename $0) <git-repo-dir> <pattern>"
+}
+
+fail ()
+{
+       usage
+       exit 1
+}
+
+GIT_REPO=$1
+shift || fail
+
+BRANCH_PREFIX=$1
+shift || fail
+
+#
+# Find version $BRANCH in $GIT_REPOS's
+# $REMOTE. e.g. 'xenbits'/'blktap/next'-<version>. Sed out the
+# <version> strings. Sort them numerically (!), descending.
+#
+
+git --git-dir=$GIT_REPO branch -r |
+
+sed -ne"s, *$BRANCH_PREFIX\([0-9.]*\)$,\\1,p" |
+
+kernelversions sort rev | 
+
+while read version
+do
+       branch="$BRANCH_PREFIX$version"
+       desc=$(git --git-dir=$GIT_REPO describe $branch)
+       echo $branch:$version:$desc
+done
+
diff --git a/bin/kernelversions b/bin/kernelversions
new file mode 100755 (executable)
index 0000000..6d6c26b
--- /dev/null
@@ -0,0 +1,262 @@
+#!/usr/bin/python
+
+import re
+
+class Trie(object):
+
+    def __init__(self, parent = None, item = None):
+        self.parent   = parent
+        self.item     = None
+        self.children = {}
+
+    def insert(self, key, item):
+        if not key:
+            self.item = item
+
+        else:
+            head = key[0]
+            tail = key[1:]
+
+            child = self.children.get(head)
+
+            if child is None:
+                child = self.__class__(self)
+                self.children[head] = child
+
+            child.insert(tail, item)
+
+    def delete(self, key):
+        if not key:
+            self.item = None
+
+        else:
+
+            head = key[0]
+            tail = key[1:]
+            child = self.children.get(head)
+            if child:
+                if child.delete(tail):
+                    del self.children[head]
+
+        return not len(self.children)
+
+    def __setitem__(self, key, item):
+        self.insert(key, item)
+
+    def __delitem__(self, key):
+        self.delete(key)
+
+    def __repr__(self):
+        return "(%r, {%s})" % \
+            (self.item,
+             ", ".join(map(lambda (key, child):
+                               "'%s': %s" % (key, repr(child)),
+                           self.children.items())))
+
+    SPECIAL = "()|."
+
+    @classmethod
+    def __escape(cls, key):
+        if key in cls.SPECIAL:
+            return "\\%s" % key
+        return key
+
+    def regex(self):
+
+        children = []
+
+        for key, child in self.children.iteritems():
+            children.append(self.__escape(key) + child.regex())
+
+        if not children:
+            return ""
+
+        if len(children) == 1:
+            return str(children[0])
+
+        children.sort()
+        return "(%s)" % "|".join(children)
+
+class KernelVersion(object):
+
+    PATTERN = re.compile("^(\d+).(\d+).(\d+)(.*)$")
+
+    def __init__(self, ver, pat, sub, ext = ""):
+        self.ver = int(ver)
+        assert self.ver <= 0xFF
+
+        self.pat = int(pat)
+        assert self.pat <= 0xFF
+
+        self.sub = int(sub)
+        assert self.sub <= 0xFF
+
+        self.ext = ext
+
+    __FIRST = [2, 4, 0]
+
+    __DISCONT = { 2: { 4: ( 37, [2, 5, 0] ),
+                       5: ( 75, [2, 6, 0] ),
+                       6: ( 39, [3, 0, 0] ) },
+                  3: { 0: ( 99, [3, 1, 0] ) } }
+
+    class InvalidVersion(Exception):
+
+        def __init__(self, kv):
+            self.version = version
+
+        def __str__(self, kv):
+            raise "Nonexistent %r" % repr(self.version)
+
+    @classmethod
+    def first(cls):
+        return cls(*cls.__FIRST)
+
+    def next(self):
+        try:
+            _max, next = self.__DISCONT[self.ver][self.pat]
+        except KeyError:
+            raise self.InvalidVersion(self)
+
+        if self.sub < _max:
+            return self.__class__(self.ver, self.pat, self.sub + 1)
+
+        elif self.sub == _max:
+            return self.__class__(*next)
+
+        else:
+            raise self.InvalidVersion(self)
+
+    def __repr__(self):
+        return "%s(%r, %r, %r, %r)" % \
+            (self.__class__.__name__,
+             self.ver, self.pat, self.sub, self.ext)
+
+    def __str__(self):
+        return "%d.%d.%d%s" % \
+            (self.ver, self.pat, self.sub, self.ext)
+
+    @classmethod
+    def from_string(cls, s):
+        match = cls.PATTERN.search(s)
+        if not match:
+            raise Exception("Not a kernel version: %s" % s)
+
+        kv = cls(*match.groups())
+        assert str(kv) == s
+
+        return kv
+
+    @classmethod
+    def from_int(cls, val):
+        ver = (val >> 16) & 0xFF
+        pat = (val >>  8) & 0xFF
+        sub = (val      ) & 0xFF
+
+        kv = cls(ver, pat, sub)
+        assert int(kv) == val
+
+    def __int__(self):
+        return \
+            (self.ver << 16) + \
+            (self.pat <<  8) + \
+            (self.sub      )
+
+    def __lt__(self, other):
+        return int(self) < int(other)
+
+    def __le__(self, other):
+        return int(self) <= int(other)
+
+    def __ge__(self, other):
+        return int(self) >= int(other)
+
+    def __gt__(self, other):
+        return int(self) > int(other)
+
+class VersionRange(object):
+
+    def __init__(self, start, until):
+        self.start = start
+        self.until = until
+
+    @classmethod
+    def from_strings(cls, start, until):
+        return cls(KernelVersion.from_string(start),
+                   KernelVersion.from_string(until))
+
+    def __iter__(self):
+        kv = self.start
+
+        while kv < self.until:
+            yield kv
+            kv = kv.next()
+
+    def regex(self):
+        t = Trie()
+
+        for i in self:
+            t[str(i)] = None
+
+        return t.regex()
+
+if __name__ == '__main__':
+    from sys import argv, stdin, stderr
+    import os
+
+    prog = os.path.basename(argv[0])
+
+    def usage(ostream):
+        print >>ostream, "Usage: %s [<cmd>] [<args>]" % prog
+        print >>ostream
+        print >>ostream, "  regex <start> <until>"
+        print >>ostream, "  list  <start> <until>"
+        print >>ostream, "  sort [rev]"
+
+    def fail():
+        usage(stderr)
+        exit(1)
+
+    try:
+        cmd  = argv[1]
+    except IndexError:
+        fail()
+
+    if cmd in ('regex', 'list'):
+        try:
+            start, until = argv[2:4]
+        except ValueError:
+            fail()
+
+    if cmd == 'regex':
+        kvs = VersionRange.from_strings(start, until)
+        print "^%s([^0-9]|$)" % kvs.regex()
+
+    elif cmd == 'list':
+        kvs = VersionRange.from_strings(start, until)
+        for kv in kvs:
+            print kv
+
+    elif cmd == 'sort':
+        try:
+            rev = argv[2] == 'rev'
+        except IndexError:
+            rev = False
+
+        kvs = []
+
+        for line in stdin:
+            line = line.strip()
+            for s in line.strip().split():
+                kv = KernelVersion.from_string(s)
+                kvs.append(kv)
+
+        kvs.sort()
+        if rev:
+            kvs.reverse()
+
+        for kv in kvs:
+            print kv
+
+    else:
+        fail()
diff --git a/dkms.head.conf.in b/dkms.head.conf.in
new file mode 100644 (file)
index 0000000..d486326
--- /dev/null
@@ -0,0 +1,6 @@
+PACKAGE_NAME="@PKG_NAME@"
+PACKAGE_VERSION="@PKG_VERSION@"
+BUILT_MODULE_NAME[0]="blktap"
+BUILT_MODULE_LOCATION[0]="drivers/block/blktap"
+DEST_MODULE_LOCATION[0]="/kernel/drivers/block/blktap"
+AUTOINSTALL="yes"