[lvm-devel] [PATCH] lvm: don't set snapshot cow device read only

Mikulas Patocka mpatocka at redhat.com
Tue Feb 5 18:05:29 UTC 2013


Hi

This is the patch for the bug in lvm that it creates read-only 
snapshot-cow device and then lets the kernel driver to write to the 
device.

BTW. I'd like to ask - what does this "vg->status & LVM_WRITE" flag mean 
and how is it controlled? It is supposed to mean that the volume group is 
read-only or read-write, but I don't know how is it set (there is no 
read-only flag in vgchange or vgconvert) and what exactly does it cause.

Mikulas

---

lvm: don't set snapshot cow device read only

lvm has a bug: when creating snapshot with "--permission r", the
underlying -cow device is set read-only. Kernel than tries to write to
this read-only device when creating metadata header and when processing
writes to the origin. The kernel doesn't check writes to read-only
device originating from kernelspace, thus this bug becomes unnoticed.
However, if we modify the kernel to not allow write bios to read-only
devices, this bug shows up.

This patch fixes lvm so that the underlying -cow device is always
read-write.

Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>

---
 lib/activate/activate.c    |    2 +-
 lib/activate/dev_manager.c |    9 ++++++---
 lib/activate/dev_manager.h |    3 ++-
 3 files changed, 9 insertions(+), 5 deletions(-)

Index: LVM2.2.02.98/lib/activate/dev_manager.c
===================================================================
--- LVM2.2.02.98.orig/lib/activate/dev_manager.c	2013-02-04 19:53:38.000000000 +0100
+++ LVM2.2.02.98/lib/activate/dev_manager.c	2013-02-05 16:01:58.000000000 +0100
@@ -61,9 +61,12 @@ struct lv_layer {
 
 static const char _thin_layer[] = "tpool";
 
-int read_only_lv(struct logical_volume *lv, struct lv_activate_opts *laopts)
+int read_only_lv(struct logical_volume *lv, struct lv_activate_opts *laopts,
+		 const char *layer)
 {
-	return (laopts->read_only || !(lv->vg->status & LVM_WRITE) || !(lv->status & LVM_WRITE));
+	if (!(lv->vg->status & LVM_WRITE)) return 1;
+	if (layer && !strcmp(layer, "cow")) return 0;
+	return laopts->read_only || !(lv->status & LVM_WRITE);
 }
 
 /*
@@ -1968,7 +1971,7 @@ static int _add_new_lv_to_dtree(struct d
 	if (!(dnode = dm_tree_add_new_dev_with_udev_flags(dtree, name, dlid,
 					     layer ? UINT32_C(0) : (uint32_t) lv->major,
 					     layer ? UINT32_C(0) : (uint32_t) lv->minor,
-					     read_only_lv(lv, laopts),
+					     read_only_lv(lv, laopts, layer),
 					     ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
 					     lvlayer,
 					     _get_udev_flags(dm, lv, layer))))
Index: LVM2.2.02.98/lib/activate/activate.c
===================================================================
--- LVM2.2.02.98.orig/lib/activate/activate.c	2013-02-05 01:14:34.000000000 +0100
+++ LVM2.2.02.98/lib/activate/activate.c	2013-02-05 01:15:06.000000000 +0100
@@ -1857,7 +1857,7 @@ static int _lv_activate(struct cmd_conte
 	 * Nothing to do?
 	 */
 	if (info.exists && !info.suspended && info.live_table &&
-	    (info.read_only == read_only_lv(lv, laopts))) {
+	    (info.read_only == read_only_lv(lv, laopts, NULL))) {
 		r = 1;
 		goto out;
 	}
Index: LVM2.2.02.98/lib/activate/dev_manager.h
===================================================================
--- LVM2.2.02.98.orig/lib/activate/dev_manager.h	2013-02-05 01:14:20.000000000 +0100
+++ LVM2.2.02.98/lib/activate/dev_manager.h	2013-02-05 01:14:29.000000000 +0100
@@ -26,7 +26,8 @@ struct dev_manager;
 struct dm_info;
 struct device;
 
-int read_only_lv(struct logical_volume *lv, struct lv_activate_opts *laopts);
+int read_only_lv(struct logical_volume *lv, struct lv_activate_opts *laopts,
+		 const char *layer);
 
 /*
  * Constructor and destructor.




More information about the lvm-devel mailing list