[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[linux-lvm] [PATCH] IOPv6 support for Linux 2.4.0-test13-pre4 (LVM 0.9)



Hello & Merry Christmas,

this patch (against Linux 2.4.0-test13-pre4 + my both previous patches),
implements a IOPv6 compatiblity layer for LVM 0.9.  This is done by doing
structure conversion in copy_{pv,vg,lv}_{from,to}_user routines that replace
copy_{from,to}_user calls in lvm.c.  Currently we use the old IOP
unconditionally once CONFIG_BLK_DEV_LVM_COMPAT_08 is defined - but as soon
as we get a way to make the kernel support different IOPs without recompilation
(Heinz, would you accept a patch for MIN_IOP_VERSION and MAX_IOP_VERSION or
a syscall?) this should be changed.

Besides the above structures a lot (and I mean a _lot_) structure members have
changed their type from __u32 to ulong and will break on 64bit arches, but this
seem rather a LVM bug then a version change.

Besides that I probably have overseen a few structs ;)

	Christoph

-- 
Whip me.  Beat me.  Make me maintain AIX.


diff -uNr --exclude-from=dontdiff linux-2.4.0-test13-pre4/drivers/md/Config.in linux/drivers/md/Config.in
--- linux-2.4.0-test13-pre4/drivers/md/Config.in	Sun Nov 26 17:23:18 2000
+++ linux/drivers/md/Config.in	Mon Dec 25 21:45:50 2000
@@ -17,5 +17,6 @@
 fi
 
 dep_tristate ' Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM $CONFIG_MD
+dep_mbool '   Support (only) LVM 0.8 IOP' CONFIG_BLK_DEV_LVM_COMPAT_08 $CONFIG_BLK_DEV_LVM
 
 endmenu
diff -uNr --exclude-from=dontdiff linux-2.4.0-test13-pre4/drivers/md/Makefile linux/drivers/md/Makefile
--- linux-2.4.0-test13-pre4/drivers/md/Makefile	Sat Dec 23 18:55:04 2000
+++ linux/drivers/md/Makefile	Mon Dec 25 21:46:33 2000
@@ -6,7 +6,7 @@
 
 export-objs	:= md.o xor.o
 list-multi	:= lvm-mod.o
-lvm-mod-objs	:= lvm.o lvm-snap.o
+lvm-mod-objs	:= lvm.o lvm-snap.o lvm-compat.o
 
 # Note: link order is important.  All raid personalities
 # and xor.o must come before md.o, as they each initialise 
diff -uNr --exclude-from=dontdiff linux-2.4.0-test13-pre4/drivers/md/lvm-compat.c linux/drivers/md/lvm-compat.c
--- linux-2.4.0-test13-pre4/drivers/md/lvm-compat.c	Thu Jan  1 01:00:00 1970
+++ linux/drivers/md/lvm-compat.c	Mon Dec 25 23:18:36 2000
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2000 Christoph Hellwig.
+ * All rights reserved.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/uaccess.h>
+#include <linux/lvm.h>
+
+/*
+ * LVM compatiblity for 0.8 userlevel.
+ */
+
+int
+copy_vg_from_user(vg_t * vg, void * arg)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	int error;
+
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		vg_v1_t vg_compat;
+
+		error = copy_from_user(&vg_compat, arg, sizeof(vg_v1_t));
+		if (error)
+			return (error);
+		
+		memset(vg, 0, sizeof(vg_t));
+
+		/*
+		 * vg_t hasn't changed much - just memcpy.
+		 */
+		memcpy(vg, &vg_compat, sizeof(vg_v1_t));
+		memcpy(vg->vg_uuid, vg_compat.vg_name, UUID_LEN);
+
+		return 0;
+	} else
+#endif
+		return copy_from_user(vg, arg, sizeof(vg_t));
+}
+
+
+int
+copy_lv_from_user(lv_t * lv, void * arg)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	int error;
+
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		lv_v2_t lv_compat;
+
+
+		error = copy_from_user(&lv_compat, arg, sizeof(lv_v2_t));
+		if (error)
+			return (error);
+
+		memset(lv, 0, sizeof(lv_t));
+
+		/*
+		 * We can't simply memcpy the whole struct 
+		 * because a struct member is gone.
+		 */
+		memcpy(lv->lv_name, lv_compat.lv_name, NAME_LEN);
+		memcpy(lv->vg_name, lv_compat.vg_name, NAME_LEN);
+
+		lv->lv_access =			lv_compat.lv_access;
+		lv->lv_status =			lv_compat.lv_status;
+		lv->lv_open =			lv_compat.lv_open;
+		lv->lv_dev =			lv_compat.lv_dev;
+		lv->lv_number =			lv_compat.lv_number;
+		lv->lv_mirror_copies =		lv_compat.lv_mirror_copies;
+		lv->lv_recovery =		lv_compat.lv_recovery;
+		lv->lv_schedule =		lv_compat.lv_schedule;
+		lv->lv_size =			lv_compat.lv_size;
+		lv->lv_current_pe =		lv_compat.lv_current_pe;
+		lv->lv_current_le =		lv_compat.lv_current_le;
+		lv->lv_allocated_le =		lv_compat.lv_allocated_le;
+		lv->lv_stripes =		lv_compat.lv_stripes;
+		lv->lv_stripesize =		lv_compat.lv_stripesize;
+		lv->lv_badblock =		lv_compat.lv_badblock;
+		lv->lv_allocation =		lv_compat.lv_allocation;
+		lv->lv_io_timeout =		lv_compat.lv_io_timeout;
+		lv->lv_read_ahead =		lv_compat.lv_read_ahead;
+
+		/*
+		 * We'll convert these later.
+		 */
+		lv->lv_snapshot_org = 		(struct lv_v4 *) lv_compat.lv_snapshot_org;
+		lv->lv_snapshot_prev =		(struct lv_v4 *) lv_compat.lv_snapshot_prev;
+		lv->lv_snapshot_next =		(struct lv_v4 *) lv_compat.lv_snapshot_next;
+		
+		lv->lv_block_exception =	lv_compat.lv_block_exception;
+		lv->lv_remap_ptr = 		lv_compat.lv_remap_ptr;
+		lv->lv_remap_end =		lv_compat.lv_remap_end;
+		lv->lv_chunk_size =		lv_compat.lv_chunk_size;
+		lv->lv_snapshot_minor =		lv_compat.lv_snapshot_minor;
+
+		return 0;
+	} else
+#endif
+		return copy_from_user(lv, arg, sizeof(lv_t));
+}
+
+
+
+int
+copy_pv_from_user(pv_t * pv, void * arg)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	int error;
+
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		pv_v1_t pv_compat;
+
+		error = copy_from_user(&pv_compat, arg, sizeof(pv_v1_t));
+		if (error)
+			return (error);
+		
+		memset(pv, 0, sizeof(pv_t));
+
+		/*
+		 * vg_t hasn't changed much - just memcpy.
+		 */
+		memcpy(pv, &pv_compat, sizeof(pv_v1_t));
+		memcpy(pv->pv_uuid, pv_compat.pv_name, UUID_LEN);
+
+		return 0;
+	} else
+#endif
+		return copy_from_user(pv, arg, sizeof(pv_t));
+}
+
+int
+copy_status_byindex_from_user(lv_status_byindex_req_t * req, void * arg)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	int error;
+
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		struct {
+			u_int32_t	lv_index;
+			lv_t *		lv;
+		} req_compat;
+
+		error = copy_from_user(&req_compat, arg, sizeof(req_compat));
+		if (error)
+			return (error);
+		
+		memset(req, 0, sizeof(lv_status_byindex_req_t));
+
+		/*
+		 * vg_t hasn't changed much - just memcpy.
+		 */
+		memcpy(req, &req_compat, sizeof(req_compat));
+
+		return 0;
+	} else
+#endif
+		return copy_from_user(req, arg, sizeof(lv_status_byindex_req_t));
+}
+
+int
+copy_vg_to_user(void * arg, vg_t * vg)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		vg_v1_t vg_compat;
+
+		memcpy(&vg_compat, vg, sizeof(vg_v1_t));
+		return copy_to_user(arg, &vg_compat, sizeof(vg_v1_t));
+	} else
+#endif
+		return copy_to_user(arg, vg, sizeof(vg_t));
+}
+
+
+int
+copy_lv_to_user(void * arg, lv_t * lv)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		lv_v2_t	 lv_compat;
+
+		memset(&lv_compat, 0, sizeof(lv_v2_t));
+
+		/*
+		 * We can't simply memcpy the whole struct 
+		 * because a struct member is gone.
+		 */
+		memcpy(lv_compat.lv_name, lv->lv_name, NAME_LEN);
+		memcpy(lv_compat.vg_name, lv->vg_name, NAME_LEN);
+
+		lv_compat.lv_access =		lv->lv_access;
+		lv_compat.lv_status =		lv->lv_status;
+		lv_compat.lv_open =		lv->lv_open;
+		lv_compat.lv_dev =		lv->lv_dev;
+		lv_compat.lv_number =		lv->lv_number;
+		lv_compat.lv_mirror_copies =	lv->lv_mirror_copies;
+		lv_compat.lv_recovery =		lv->lv_recovery;
+		lv_compat.lv_schedule =		lv->lv_schedule;
+		lv_compat.lv_size =		lv->lv_size;
+		lv_compat.lv_current_pe =	lv->lv_current_pe;
+		lv_compat.lv_current_le =	lv->lv_current_le;
+		lv_compat.lv_allocated_le =	lv->lv_allocated_le;
+		lv_compat.lv_stripes =		lv->lv_stripes;
+		lv_compat.lv_stripesize =	lv->lv_stripesize;
+		lv_compat.lv_badblock =		lv->lv_badblock;
+		lv_compat.lv_allocation =	lv->lv_allocation;
+		lv_compat.lv_io_timeout =	lv->lv_io_timeout;
+		lv_compat.lv_read_ahead =	lv->lv_read_ahead;
+
+		/*
+		 * These should have already been converted.
+		 */
+		lv_compat.lv_snapshot_org = 	(struct lv_v2 *) lv->lv_snapshot_org;
+		lv_compat.lv_snapshot_prev =	(struct lv_v2 *) lv->lv_snapshot_prev;
+		lv_compat.lv_snapshot_next =	(struct lv_v2 *) lv->lv_snapshot_next;
+		
+		lv_compat.lv_block_exception =	lv->lv_block_exception;
+		lv_compat.lv_remap_ptr = 	lv->lv_remap_ptr;
+		lv_compat.lv_remap_end =	lv->lv_remap_end;
+		lv_compat.lv_chunk_size =	lv->lv_chunk_size;
+		lv_compat.lv_snapshot_minor =	lv->lv_snapshot_minor;
+
+		return copy_to_user(arg, &lv_compat, sizeof(lv_v2_t));
+	} else
+#endif
+		return copy_to_user(arg, lv, sizeof(lv_t));
+}
+
+
+
+int
+copy_pv_to_user(void * arg, pv_t * pv)
+{
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+	if (LVM_DRIVER_IOP_VERSION == 6) {
+		pv_v1_t		pv_compat;
+
+		memcpy(&pv_compat, pv, sizeof(pv_v1_t));
+		return copy_to_user(arg, &pv_compat, sizeof(pv_v1_t));
+	} else
+#endif
+		return copy_from_user(pv, arg, sizeof(pv_t));
+}
diff -uNr --exclude-from=dontdiff linux-2.4.0-test13-pre4/drivers/md/lvm.c linux/drivers/md/lvm.c
--- linux-2.4.0-test13-pre4/drivers/md/lvm.c	Mon Dec 25 19:21:16 2000
+++ linux/drivers/md/lvm.c	Mon Dec 25 23:22:56 2000
@@ -260,6 +261,15 @@
 extern int lvm_snapshot_alloc_hash_table(lv_t *);
 extern void lvm_drop_snapshot(lv_t *, char *);
 
+/* external copy calls */
+extern int	copy_vg_from_user(vg_t *, void *);
+extern int	copy_lv_from_user(lv_t *, void *);
+extern int	copy_pv_from_user(pv_t *, void *);
+extern int	copy_status_byindex_from_user(lv_status_byindex_req_t *, void *);
+extern int	copy_vg_to_user(void *, vg_t *);
+extern int	copy_lv_to_user(void *, lv_t *);
+extern int	copy_pv_to_user(void *, pv_t *);
+
 #ifdef LVM_HD_NAME
 extern void (*lvm_hd_name_ptr) (char *, int);
 #endif
@@ -720,7 +730,7 @@
 	case VG_STATUS:
 		/* get volume group data (only the vg_t struct) */
 		if (vg_ptr == NULL) return -ENXIO;
-		if (copy_to_user(arg, vg_ptr, sizeof(vg_t)) != 0)
+		if (copy_vg_to_user(arg, vg_ptr) != 0)
 			return -EFAULT;
 		return 0;
 
@@ -1892,7 +1900,7 @@
 		return -ENOMEM;
 	}
 	/* get the volume group structure */
-	if (copy_from_user(vg_ptr, arg, sizeof(vg_t)) != 0) {
+	if (copy_vg_from_user(vg_ptr, arg) != 0) {
 		kfree(vg_ptr);
 		return -EFAULT;
 	}
@@ -1947,7 +1955,7 @@
 	for (l = 0; l < vg_ptr->lv_max; l++) {
 		/* user space address */
 		if ((lvp = vg_ptr->lv[l]) != NULL) {
-			if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
+			if (copy_lv_from_user(&lv, lvp) != 0) {
 				lvm_do_vg_remove(minor);
 				return -EFAULT;
 			}
@@ -1970,7 +1978,7 @@
 	   in place during first path above */
 	for (l = 0; l < ls; l++) {
 		lvp = snap_lv_ptr[l];
-		if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0) {
+		if (copy_lv_from_user(&lv, lvp) != 0) {
 			lvm_do_vg_remove(minor);
 			return -EFAULT;
 		}
@@ -2211,7 +2221,7 @@
 		       lvm_name, __LINE__);
 		return -ENOMEM;
 	}
-	if (copy_from_user(pv_ptr, pvp, sizeof(pv_t)) != 0) {
+	if (copy_pv_from_user(pv_ptr, pvp) != 0) {
 		return -EFAULT;
 	}
 	/* We don't need the PE list
@@ -2816,9 +2826,8 @@
 		if (lv_ptr != NULL &&
 		    strcmp(lv_ptr->lv_name,
 			    lv_status_byname_req.lv_name) == 0) {
-			if (copy_to_user(lv_status_byname_req.lv,
-					 lv_ptr,
-					 sizeof(lv_t)) != 0)
+			if (copy_lv_to_user(lv_status_byname_req.lv,
+					lv_ptr) != 0)
 				return -EFAULT;
 
 			if (lv.lv_current_pe != NULL) {
@@ -2847,8 +2856,7 @@
 	lv_status_byindex_req_t lv_status_byindex_req;
 
 	if (vg_ptr == NULL) return -ENXIO;
-	if (copy_from_user(&lv_status_byindex_req, arg,
-			   sizeof(lv_status_byindex_req)) != 0)
+	if (copy_status_byindex_from_user(&lv_status_byindex_req, arg) != 0)
 		return -EFAULT;
 
 	if ((lvp = lv_status_byindex_req.lv) == NULL)
@@ -2856,10 +2864,10 @@
 	if ( ( lv_ptr = vg_ptr->lv[lv_status_byindex_req.lv_index]) == NULL)
 		return -ENXIO;
 
-	if (copy_from_user(&lv, lvp, sizeof(lv_t)) != 0)
+	if (copy_lv_from_user(&lv, lvp) != 0)
 		return -EFAULT;
 
-	if (copy_to_user(lvp, lv_ptr, sizeof(lv_t)) != 0)
+	if (copy_lv_to_user(lvp, lv_ptr) != 0)
 		return -EFAULT;
 
 	if (lv.lv_current_pe != NULL) {
@@ -2892,8 +2900,7 @@
 
 	if ( l == vg_ptr->lv_max) return -ENXIO;
 
-	if (copy_to_user(lv_status_bydev_req.lv,
-			 vg_ptr->lv[l], sizeof(lv_t)) != 0)
+	if (copy_lv_to_user(lv_status_bydev_req.lv, vg_ptr->lv[l]) != 0)
 		return -EFAULT;
 
 	return 0;
@@ -2956,9 +2963,8 @@
 #ifdef LVM_GET_INODE
 			inode_sav = pv_ptr->inode;
 #endif
-			if (copy_from_user(pv_ptr,
-					   pv_change_req.pv,
-					   sizeof(pv_t)) != 0)
+			if (copy_pv_from_user(pv_ptr,
+					   pv_change_req.pv) != 0)
 				return -EFAULT;
 
 			/* We don't need the PE list
@@ -2991,9 +2997,7 @@
 		if (pv_ptr != NULL &&
 		    strcmp(pv_ptr->pv_name,
 			       pv_status_req.pv_name) == 0) {
-			if (copy_to_user(pv_status_req.pv,
-					 pv_ptr,
-				         sizeof(pv_t)) != 0)
+			if (copy_pv_to_user(pv_status_req.pv, pv_ptr) != 0)
 				return -EFAULT;
 			return 0;
 		}
diff -uNr --exclude-from=dontdiff linux-2.4.0-test13-pre4/include/linux/lvm.h linux/include/linux/lvm.h
--- linux-2.4.0-test13-pre4/include/linux/lvm.h	Mon Dec 25 19:21:15 2000
+++ linux/include/linux/lvm.h	Mon Dec 25 21:54:41 2000
@@ -67,7 +67,6 @@
 #define	_LVM_KERNEL_H_VERSION	"LVM 0.9 (13/11/2000)"
 
 #include <linux/version.h>
-#include <endian.h>
 
 /*
  * preprocessor definitions
@@ -163,7 +162,11 @@
  * user land tools/lib/liblvm.h
  *
  */
-#define	LVM_DRIVER_IOP_VERSION	        10
+#ifdef CONFIG_BLK_DEV_LVM_COMPAT_08
+# define	LVM_DRIVER_IOP_VERSION		 6
+#else
+# define	LVM_DRIVER_IOP_VERSION	        10
+#endif
 
 #define LVM_NAME        "lvm"
 #define LVM_GLOBAL	"global"
@@ -639,6 +597,54 @@
 	ulong lv_block;
 	dev_t lv_dev;
 } lv_bmap_t;
+
+
+/*
+ * Structure Logical Volume (LV) Version 2
+ */
+
+/* core */
+typedef struct lv_v2 {
+	__u8 lv_name[NAME_LEN];
+	__u8 vg_name[NAME_LEN];
+	__u32 lv_access;
+	__u32 lv_status;
+	__u32 lv_open;		/* HM */
+	kdev_t lv_dev;		/* HM */
+	__u32 lv_number;	/* HM */
+	__u32 lv_mirror_copies;	/* for future use */
+	__u32 lv_recovery;	/*       "        */
+	__u32 lv_schedule;	/*       "        */
+	__u32 lv_size;
+	pe_t *lv_current_pe;	/* HM */
+	__u32 lv_current_le;	/* for future use */
+	__u32 lv_allocated_le;
+	__u32 lv_stripes;
+	__u32 lv_stripesize;
+	__u32 lv_badblock;	/* for future use */
+	__u32 lv_allocation;
+	__u32 lv_io_timeout;	/* for future use */
+	__u32 lv_read_ahead;
+
+	/* delta to version 1 starts here */
+	struct lv_v2 *lv_snapshot_org;
+	struct lv_v2 *lv_snapshot_prev;
+	struct lv_v2 *lv_snapshot_next;
+	lv_block_exception_t *lv_block_exception;
+	__u8 __unused;
+	__u32 lv_remap_ptr;
+	__u32 lv_remap_end;
+	__u32 lv_chunk_size;
+	__u32 lv_snapshot_minor;
+#ifdef __KERNEL__
+	struct kiobuf *lv_iobuf;
+	struct semaphore lv_snapshot_sem;
+	struct list_head *lv_snapshot_hash_table;
+	ulong  lv_snapshot_hash_mask;
+#else
+	char  dummy[200];
+#endif
+} lv_v2_t;
 
 /*
  * Structure Logical Volume (LV) Version 3


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]