diff --git a/NEWS b/NEWS
index 8768e192e400bb7609513f30c3534dd15ece2c81..a34d1983229f55ec0331e461f764d9366f24dbcf 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,45 @@ News
 ====
 
 
+Version 2.5.1
+-------------
+
+*(Released Fri, 11 May 2012)*
+
+A small bugfix release.
+
+The main issues solved are on the topic of compatibility with newer LVM
+releases:
+
+- fixed parsing of ``lv_attr`` field
+- adapted to new ``vgreduce --removemissing`` behaviour where sometimes
+  the ``--force`` flag is needed
+
+Also on the topic of compatibility, ``tools/lvmstrap`` has been changed
+to accept kernel 3.x too (was hardcoded to 2.6.*).
+
+A regression present in 2.5.0 that broke handling (in the gnt-* scripts)
+of hook results and that also made display of other errors suboptimal
+was fixed; the code behaves now like 2.4 and earlier.
+
+Another change in 2.5, the cleanup of the OS scripts environment, is too
+aggressive: it removed even the ``PATH`` variable, which requires the OS
+scripts to *always* need to export it. Since this is a bit too strict,
+we now export a minimal PATH, the same that we export for hooks.
+
+The fix for issue 201 (Preserve bridge MTU in KVM ifup script) was
+integrated into this release.
+
+Finally, a few other miscellaneous changes were done (no new features,
+just small improvements):
+
+- Fix ``gnt-group --help`` display
+- Fix hardcoded Xen kernel path
+- Fix grow-disk handling of invalid units
+- Update synopsis for ``gnt-cluster repair-disk-sizes``
+- Accept both PUT and POST in noded (makes future upgrade to 2.6 easier)
+
+
 Version 2.5.0
 -------------
 
diff --git a/configure.ac b/configure.ac
index 12d5aa094ce9ca5abda5214013271abc7862654d..a2d67b6fd051512ab90e3ea44cbbf059bf67c9c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 # Configure script for Ganeti
 m4_define([gnt_version_major], [2])
 m4_define([gnt_version_minor], [5])
-m4_define([gnt_version_revision], [0])
+m4_define([gnt_version_revision], [1])
 m4_define([gnt_version_suffix], [])
 m4_define([gnt_version_full],
           m4_format([%d.%d.%d%s],
diff --git a/doc/install.rst b/doc/install.rst
index d899abda427b7d03bd17d8d5538b6318391aed16..54a76ab9861b5d400171a5a13a8ae35b45ed6664 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -341,6 +341,26 @@ outside of ganeti. The vif scripts will only add /32 routes to your
 instances, through their interface, in the table you specified (under
 KVM, and in the main table under Xen).
 
+.. admonition:: Bridging issues with certain kernels
+
+    Some kernel versions (e.g. 2.6.32) have an issue where the bridge
+    will automatically change its ``MAC`` address to the lower-numbered
+    slave on port addition and removal. This means that, depending on
+    the ``MAC`` address of the actual NIC on the node and the addresses
+    of the instances, it could be that starting, stopping or migrating
+    instances will lead to timeouts due to the address of the bridge
+    (and thus node itself) changing.
+
+    To prevent this, it's enough to set the bridge manually to a
+    specific ``MAC`` address, which will disable this automatic address
+    change. In Debian, this can be done as follows in the bridge
+    configuration snippet::
+
+      up ip link set addr $(cat /sys/class/net/$IFACE/address) dev $IFACE
+
+    which will "set" the bridge address to the initial one, disallowing
+    changes.
+
 .. admonition:: Bridging under Debian
 
    The recommended way to configure the Xen bridge is to edit your
@@ -357,6 +377,8 @@ KVM, and in the main table under Xen).
         bridge_ports eth0
         bridge_stp off
         bridge_fd 0
+        # example for setting manually the bridge address to the eth0 NIC
+        up ip link set addr $(cat /sys/class/net/eth0/address) dev $IFACE
 
 The following commands need to be executed on the local console:
 
diff --git a/lib/backend.py b/lib/backend.py
index 2fa571364f70c19a700f9d30e22f08071a83efb7..40ce7e7348bb4e01e43ae4065f155a5147d44c59 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -78,7 +78,7 @@ _IES_PID_FILE = "pid"
 _IES_CA_FILE = "ca"
 
 #: Valid LVS output line regex
-_LVSLINE_REGEX = re.compile("^ *([^|]+)\|([^|]+)\|([0-9.]+)\|([^|]{6})\|?$")
+_LVSLINE_REGEX = re.compile("^ *([^|]+)\|([^|]+)\|([0-9.]+)\|([^|]{6,})\|?$")
 
 
 class RPCFail(Exception):
@@ -2253,6 +2253,11 @@ def OSCoreEnv(os_name, inst_os, os_params, debug=0):
   for pname, pvalue in os_params.items():
     result["OSP_%s" % pname.upper()] = pvalue
 
+  # Set a default path otherwise programs called by OS scripts (or
+  # even hooks called from OS scripts) might break, and we don't want
+  # to have each script require setting a PATH variable
+  result["PATH"] = constants.HOOKS_PATH
+
   return result
 
 
diff --git a/lib/client/gnt_group.py b/lib/client/gnt_group.py
index 199b9276d57d381a983cf13efbf3dfc4292531ff..903f569e4ba4c38029e65146bba564c801a3464e 100644
--- a/lib/client/gnt_group.py
+++ b/lib/client/gnt_group.py
@@ -244,15 +244,15 @@ commands = {
     "Evacuate all instances within a group"),
   "list-tags": (
     ListTags, ARGS_ONE_GROUP, [],
-    "<instance_name>", "List the tags of the given instance"),
+    "<group_name>", "List the tags of the given group"),
   "add-tags": (
     AddTags, [ArgGroup(min=1, max=1), ArgUnknown()],
     [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
-    "<instance_name> tag...", "Add tags to the given instance"),
+    "<group_name> tag...", "Add tags to the given group"),
   "remove-tags": (
     RemoveTags, [ArgGroup(min=1, max=1), ArgUnknown()],
     [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
-    "<instance_name> tag...", "Remove tags from given instance"),
+    "<group_name> tag...", "Remove tags from the given group"),
   }
 
 
diff --git a/lib/client/gnt_instance.py b/lib/client/gnt_instance.py
index 5ecf16f0839e35836f2de444a981eae065d98b58..9d9d7eca6528108c107dedee722cb8ee1dc58c71 100644
--- a/lib/client/gnt_instance.py
+++ b/lib/client/gnt_instance.py
@@ -640,7 +640,11 @@ def GrowDisk(opts, args):
   except (TypeError, ValueError), err:
     raise errors.OpPrereqError("Invalid disk index: %s" % str(err),
                                errors.ECODE_INVAL)
-  amount = utils.ParseUnit(args[2])
+  try:
+    amount = utils.ParseUnit(args[2])
+  except errors.UnitParseError:
+    raise errors.OpPrereqError("Can't parse the given amount '%s'" % args[2],
+                               errors.ECODE_INVAL)
   op = opcodes.OpInstanceGrowDisk(instance_name=instance,
                                   disk=disk, amount=amount,
                                   wait_for_sync=opts.wait_for_sync)
diff --git a/lib/constants.py b/lib/constants.py
index f401781955dc61783e82a233cd642d3286a4c41a..884759f968efae889ea61d9ae7c9cb4aea10753a 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -1324,7 +1324,7 @@ HVC_DEFAULTS = {
     HV_USE_BOOTLOADER: False,
     HV_BOOTLOADER_PATH: XEN_BOOTLOADER,
     HV_BOOTLOADER_ARGS: "",
-    HV_KERNEL_PATH: "/boot/vmlinuz-2.6-xenU",
+    HV_KERNEL_PATH: XEN_KERNEL,
     HV_INITRD_PATH: "",
     HV_ROOT_PATH: "/dev/sda1",
     HV_KERNEL_ARGS: "ro",
diff --git a/lib/errors.py b/lib/errors.py
index 7319cd9f13c7fb03661050424d761c102b943004..91c862aa9551fb6bf755fb5a04ebdc4dac15f71a 100644
--- a/lib/errors.py
+++ b/lib/errors.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -488,4 +488,5 @@ def MaybeRaise(result):
   error = GetEncodedError(result)
   if error:
     (errcls, args) = error
-    raise errcls(args)
+    # pylint: disable=W0142
+    raise errcls(*args)
diff --git a/test/ganeti.errors_unittest.py b/test/ganeti.errors_unittest.py
index ec25912c60da75ed8a74396c14a4d6fbd0f52fc8..f10f661c7ae0b03822da571311d079947a101f07 100755
--- a/test/ganeti.errors_unittest.py
+++ b/test/ganeti.errors_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2010 Google Inc.
+# Copyright (C) 2010, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -53,14 +53,25 @@ class TestErrors(testutils.GanetiTestCase):
                            ("GenericError", (True, 100, "foo", ["x", "y"])))
 
   def testMaybeRaise(self):
+    testvals = [None, 1, 2, 3, "Hello World", (1, ), (1, 2, 3),
+                ("NoErrorClassName", []), ("NoErrorClassName", None),
+                ("GenericError", [1, 2, 3], None), ("GenericError", 1)]
     # These shouldn't raise
-    for i in [None, 1, 2, 3, "Hello World", (1, ), (1, 2, 3),
-              ("NoErrorClassName", []), ("NoErrorClassName", None),
-              ("GenericError", [1, 2, 3], None), ("GenericError", 1)]:
+    for i in testvals:
       errors.MaybeRaise(i)
 
     self.assertRaises(errors.GenericError, errors.MaybeRaise,
                       ("GenericError", ["Hello"]))
+    # Check error encoding
+    for i in testvals:
+      src = errors.GenericError(i)
+      try:
+        errors.MaybeRaise(errors.EncodeException(src))
+      except errors.GenericError, dst:
+        self.assertEqual(src.args, dst.args)
+        self.assertEqual(src.__class__, dst.__class__)
+      else:
+        self.fail("Exception %s not raised" % repr(src))
 
   def testGetEncodedError(self):
     self.assertEqualValues(errors.GetEncodedError(["GenericError",
diff --git a/tools/lvmstrap b/tools/lvmstrap
index eb87cd2325b919d3c0c8f7a02be0048803bb53b9..3d1affd312f85ea164e6d1dca9f5bf010ecc2fd4 100755
--- a/tools/lvmstrap
+++ b/tools/lvmstrap
@@ -272,9 +272,9 @@ def CheckPrereq():
     raise PrereqError("This tool only runs on Linux"
                       " (detected OS: %s)." % osname)
 
-  if not release.startswith("2.6."):
+  if not (release.startswith("2.6.") or release.startswith("3.")):
     raise PrereqError("Wrong major kernel version (detected %s, needs"
-                      " 2.6.*)" % release)
+                      " 2.6.* or 3.*)" % release)
 
   if not os.path.ismount("/sys"):
     raise PrereqError("Can't find a filesystem mounted at /sys."