From asaddi@kalahari.flup.org  Thu Oct  3 02:35:13 2002
Return-Path: <asaddi@kalahari.flup.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 7D20C37B401
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  3 Oct 2002 02:35:13 -0700 (PDT)
Received: from kalahari.flup.org (kalahari.flup.org [198.78.66.13])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 26E4343E6A
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  3 Oct 2002 02:35:13 -0700 (PDT)
	(envelope-from asaddi@kalahari.flup.org)
Received: by kalahari.flup.org (Postfix, from userid 1001)
	id 4EAAF15A49; Thu,  3 Oct 2002 02:35:11 -0700 (PDT)
Message-Id: <20021003093511.4EAAF15A49@kalahari.flup.org>
Date: Thu,  3 Oct 2002 02:35:11 -0700 (PDT)
From: Allan Saddi <allan@saddi.com>
Reply-To: Allan Saddi <allan@saddi.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: vinum: 'readpol prefer' option broken [patch included]
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         43623
>Category:       kern
>Synopsis:       vinum: 'readpol prefer' option broken [patch included]
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    grog
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 03 02:40:04 PDT 2002
>Closed-Date:    Mon Jun 02 22:04:03 PDT 2003
>Last-Modified:  Mon Jun 02 22:04:03 PDT 2003
>Originator:     Allan Saddi
>Release:        FreeBSD 4.6.2-RELEASE-p2 i386
>Organization:
Saddi Enterprises
>Environment:
System: FreeBSD tranquility.caelum.net 4.6.2-RELEASE-p2 FreeBSD 4.6.2-RELEASE-p2 #0: Thu Sep 26 11:42:50 PDT 2002 root@tranquility.caelum.net:/usr/obj/usr/src/sys/TRANQUILITY i386


	<machine, os, target, libraries (multiple lines)>
>Description:
Volumes consisting of multiple plexes can be configured to prefer a
specific plex for reading using the 'readpol prefer <plexname>' option.
I found that this option is broken in 4.6.2 (and after viewing the
CVS history, -current and -stable as well). I identified a few
problems:

  1. Inconsistent initialization of plex->plexno.
  2. plex->plexno is wrong when defining an already referenced plex.
  3. The config dump/print code incorrectly assume that
     vol->preferred_plex is an index into the global plex array.
     It's an index into the volume's plex array.

I corrected the problems in the following patch and 'readpol prefer'
now seems to work.

>How-To-Repeat:
Attempt to configure a volume using the 'readpol prefer <plexname>'
option. The vinum lv command will show the volume as having the wrong
number of plexes and/or it will include the wrong plex. Issuing
vinum dumpconfig will show a configuration that is different than
what you expect. vinum printconfig core dumps.

>Fix:
Also available at http://www.saddi.com/allan/tmp/vinum-readpol.diff

--- sys/dev/vinum/vinumconfig.c.orig	Sat Feb  2 16:43:35 2002
+++ sys/dev/vinum/vinumconfig.c	Sun Sep 29 03:37:51 2002
@@ -568,6 +568,7 @@
     /* initialize some things */
     sd = &SD[sdno];					    /* point to it */
     bzero(sd, sizeof(struct sd));			    /* initialize */
+    sd->sdno = sdno;					    /* point back to config */
     sd->flags |= VF_NEWBORN;				    /* newly born subdisk */
     sd->plexno = -1;					    /* no plex */
     sd->sectors = -1;					    /* no space */
@@ -760,6 +761,7 @@
     /* Found a plex.  Give it an sd structure */
     plex = &PLEX[plexno];				    /* this one is ours */
     bzero(plex, sizeof(struct plex));			    /* polish it up */
+    plex->plexno = plexno;				    /* point back to config */
     plex->sdnos = (int *) Malloc(sizeof(int) * INITIAL_SUBDISKS_IN_PLEX); /* allocate sd table */
     CHECKALLOC(plex->sdnos, "vinum: Can't allocate plex subdisk table");
     bzero(plex->sdnos, (sizeof(int) * INITIAL_SUBDISKS_IN_PLEX)); /* do we need this? */
@@ -1074,7 +1076,9 @@
 			struct plex *plex;		    /* for tidying up dangling references */
 
 			*sd = SD[namedsdno];		    /* copy from the referenced one */
+			sd->sdno = sdno;		    /* point back to config */
 			SD[namedsdno].state = sd_unallocated; /* and deallocate the referenced one */
+			SD[namedsdno].name[0] = '\0';	    /* make sure no one finds it */
 			plex = &PLEX[sd->plexno];	    /* now take a look at our plex */
 			for (i = 0; i < plex->subdisks; i++) { /* look for the pointer */
 			    if (plex->sdnos[i] == namedsdno) /* pointing to the old subdisk */
@@ -1251,7 +1255,6 @@
     current_plex = -1;					    /* forget the previous plex */
     plexno = get_empty_plex();				    /* allocate a plex */
     plex = &PLEX[plexno];				    /* and point to it */
-    plex->plexno = plexno;				    /* and back to the config */
 
     for (parameter = 1; parameter < tokens; parameter++) {  /* look at the other tokens */
 	switch (get_keyword(token[parameter], &keyword_set)) {
@@ -1273,7 +1276,9 @@
 			struct volume *vol;		    /* for tidying up dangling references */
 
 			*plex = PLEX[namedplexno];	    /* get the info */
+			plex->plexno = plexno;		    /* point back to config */
 			PLEX[namedplexno].state = plex_unallocated; /* and deallocate the other one */
+			PLEX[namedplexno].name[0] = '\0';   /* make sure no one finds it */
 			vol = &VOL[plex->volno];	    /* point to the volume */
 			for (i = 0; i < MAXPLEX; i++) {	    /* for each plex */
 			    if (vol->plex[i] == namedplexno)
@@ -1468,19 +1473,22 @@
 
 	    case kw_prefer:
 		{
-		    int myplexno;			    /* index of this plex */
+		    int plexno;				    /* index of this plex */
+		    int myplexno;			    /* and index if it's already ours */
 
-		    myplexno = find_plex(token[++parameter], 1); /* find a plex */
-		    if (myplexno < 0)			    /* couldn't */
+		    plexno = find_plex(token[++parameter], 1); /* find a plex */
+		    if (plexno < 0)			    /* couldn't */
 			break;				    /* we've already had an error message */
-		    myplexno = my_plex(volno, myplexno);    /* does it already belong to us? */
+		    myplexno = my_plex(volno, plexno);      /* does it already belong to us? */
 		    if (myplexno > 0)			    /* yes */
 			vol->preferred_plex = myplexno;	    /* just note the index */
 		    else if (++vol->plexes > 8)		    /* another entry */
 			throw_rude_remark(EINVAL, "Too many plexes");
 		    else {				    /* space for the new plex */
-			vol->plex[vol->plexes - 1] = myplexno; /* add it to our list */
+			vol->plex[vol->plexes - 1] = plexno; /* add it to our list */
 			vol->preferred_plex = vol->plexes - 1; /* and note the index */
+			PLEX[plexno].state = plex_referenced; /* we know something about it */
+			PLEX[plexno].volno = volno;	    /* and this volume references it */
 		    }
 		}
 		break;
--- sys/dev/vinum/vinumio.c.orig	Thu May  2 01:43:44 2002
+++ sys/dev/vinum/vinumio.c	Sun Sep 29 02:02:29 2002
@@ -490,7 +490,7 @@
 		snprintf(s,
 		    configend - s,
 		    " readpol prefer %s",
-		    vinum_conf.plex[vol->preferred_plex].name);
+		    vinum_conf.plex[vol->plex[vol->preferred_plex]].name);
 	    while (*s)
 		s++;					    /* find the end */
 	    s = sappend("\n", s);
--- sbin/vinum/list.c.orig	Sun May 27 22:58:04 2001
+++ sbin/vinum/list.c	Sun Sep 29 03:53:46 2002
@@ -1095,13 +1095,14 @@
     for (i = 0; i < vinum_conf.volumes_allocated; i++) {
 	get_volume_info(&vol, i);
 	if (vol.state != volume_unallocated) {
-	    if (vol.preferred_plex >= 0)		    /* preferences, */
+	    if (vol.preferred_plex >= 0) {		    /* preferences, */
+		get_plex_info(&plex, vol.plex[vol.preferred_plex]);
 		fprintf(of,
 		    "%svolume %s readpol prefer %s\n",
 		    comment,
 		    vol.name,
-		    vinum_conf.plex[vol.preferred_plex].name);
-	    else					    /* default round-robin */
+		    plex.name);
+	    } else					    /* default round-robin */
 		fprintf(of, "%svolume %s\n", comment, vol.name);
 	}
     }
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->grog 
Responsible-Changed-By: schweikh 
Responsible-Changed-When: Thu Oct 10 10:26:07 PDT 2002 
Responsible-Changed-Why:  
Over to maintainer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43623 
State-Changed-From-To: open->closed 
State-Changed-By: grog 
State-Changed-When: Mon Jun 2 21:59:25 PDT 2003 
State-Changed-Why:  
Problem fixed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=43623 
>Unformatted:

Greg Lehey, 3 June 2003

The problem with readpol is the simplistic configuration format: at
the time the volume is being defined, the preferred plex may not
exist.  Since the reference internally is by plex number, not name,
this means that there is no way to remember the preference.  In
particular, this applied to the on-disk configuration.  I have now
solved this issue in a different way: instead of telling the volume
the name of the preferred plex, the plex can have an optional keyword
"preferred".  If it's part of a volume, it then becomes the preferred
plex of that volume.

PR closed.
