All pastes #1394416 Raw Edit

Something

public text v1 · immutable
#1394416 ·published 2009-04-16 22:32 UTC
rendered paste body
Index: src/afs/afs_pioctl.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_pioctl.c,v
retrieving revision 1.110.2.34
diff -u -r1.110.2.34 afs_pioctl.c
--- src/afs/afs_pioctl.c	18 Mar 2009 13:41:35 -0000	1.110.2.34
+++ src/afs/afs_pioctl.c	16 Apr 2009 22:30:04 -0000
@@ -119,6 +119,11 @@
 DECL_PIOCTL(PNFSNukeCreds);
 DECL_PIOCTL(PNewUuid);
 DECL_PIOCTL(PPrecache); 
+/* 
+ * Patch for Google Summer of Code - implementing a random server
+ * rank
+ */
+DECL_PIOCTL(PSetSPrefsRand);
 #if defined(AFS_CACHE_BYPASS)
 DECL_PIOCTL(PSetCachingThreshold);
 DECL_PIOCTL(PSetCachingBlkSize);
@@ -221,6 +226,7 @@
 	PResidencyCmd,		/* 67 -- MR-AFS: generic commnd interface */
 	PBogus,			/* 68 -- arla: fetch stats */
 	PGetVnodeXStatus2,	/* 69 - get caller access and some vcache status */
+	PSetSPrefsRand,		/* 70 - Randomize the server preference list */
 };
 
 static pioctlFunction CpioctlSw[] = {
@@ -3484,6 +3490,128 @@
     return 0;
 }
 
+
+static void *
+ReSortCells_cbRand(struct cell *cell, void *arg)
+{
+    afs_int32 *p = (afs_int32 *) arg;
+    afs_int32 *l = p + 1;
+    int i, s = p[0];
+
+    for (i = 0; i < s; i++) {
+	if (l[i] == cell->cellNum) {
+	    ObtainWriteLock(&cell->lock, 690);
+	    afs_SortServersRand(cell->cellHosts, MAXCELLHOSTS);
+	    ReleaseWriteLock(&cell->lock);
+	}
+    }
+
+    return NULL;
+}
+
+static void
+ReSortCellsRand(int s, afs_int32 * l, int vlonly)
+{
+    int i;
+    struct volume *j;
+    register int k;
+
+    if (vlonly) {
+	afs_int32 *p;
+	p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
+	p[0] = s;
+	memcpy(p + 1, l, s * sizeof(afs_int32));
+	afs_TraverseCells(&ReSortCells_cbRand, p);
+	afs_osi_Free(p, sizeof(afs_int32) * (s + 1));
+	return;
+    }
+
+    ObtainReadLock(&afs_xvolume);
+    for (i = 0; i < NVOLS; i++) {
+	for (j = afs_volumes[i]; j; j = j->next) {
+	    for (k = 0; k < s; k++)
+		if (j->cell == l[k]) {
+		    ObtainWriteLock(&j->lock, 233);
+		    afs_SortServersRand(j->serverHost, MAXHOSTS);
+		    ReleaseWriteLock(&j->lock);
+		    break;
+		}
+	}
+    }
+    ReleaseReadLock(&afs_xvolume);
+}
+
+static int
+afs_setsprefsrand(struct spref *sp, unsigned int num, unsigned int vlonly)
+{
+    struct srvAddr *sa;
+    int i, j, k, matches, touchedSize;
+    struct server *srvr = NULL;
+    afs_int32 touched[34];
+    int isfs;
+
+    touchedSize = 0;
+    for (k = 0; k < num; sp++, k++) {
+	if (debugsetsp) {
+	    printf("sp host=%x, rank=%d\n", sp->host.s_addr, sp->rank);
+	}
+	matches = 0;
+	ObtainReadLock(&afs_xserver);
+
+	i = SHash(sp->host.s_addr);
+	for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
+	    if (sa->sa_ip == sp->host.s_addr) {
+		srvr = sa->server;
+		isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
+		    || (sa->sa_portal == AFS_FSPORT);
+		if ((!vlonly && isfs) || (vlonly && !isfs)) {
+		    matches++;
+		    break;
+		}
+	    }
+	}
+
+	if (sa && matches) {	/* found one! */
+	    if (debugsetsp) {
+		printf("sa ip=%x, ip_rank=%d\n", sa->sa_ip, sa->sa_iprank);
+	    }
+	    sa->sa_iprank = sp->rank + afs_randomMod15();
+	    afs_SortOneServer(sa->server);
+
+	    if (srvr->cell) {
+		/* if we don't know yet what cell it's in, this is moot */
+		for (j = touchedSize - 1;
+		     j >= 0 && touched[j] != srvr->cell->cellNum; j--)
+		    /* is it in our list of touched cells ?  */ ;
+		if (j < 0) {	/* no, it's not */
+		    touched[touchedSize++] = srvr->cell->cellNum;
+		    if (touchedSize >= 32) {	/* watch for ovrflow */
+			ReleaseReadLock(&afs_xserver);
+			ReSortCellsRand(touchedSize, touched, vlonly);
+			touchedSize = 0;
+			ObtainReadLock(&afs_xserver);
+		    }
+		}
+	    }
+	}
+
+	ReleaseReadLock(&afs_xserver);
+	/* if we didn't find one, start to create one. */
+	/* Note that it doesn't have a cell yet...     */
+	if (!matches) {
+	    afs_uint32 temp = sp->host.s_addr;
+	    srvr =
+		afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
+			      WRITE_LOCK, (afsUUID *) 0, 0);
+	    srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
+	    afs_PutServer(srvr, WRITE_LOCK);
+	}
+    }				/* for all cited preferences */
+
+    ReSortCellsRand(touchedSize, touched, vlonly);
+    return 0;
+}
+
 /*!
  * VIOC_SETPREFS (46) - Set server ranks
  *
@@ -3548,6 +3676,120 @@
     return 0;
 }
 
+/*
+ * VIOC_SETSPREFSRAND (70) - Set server ranks randomly
+ *
+ * \param[in] ain	the server preferences to be set
+ * \param[out] aout	not in use
+ *
+ * \retval EIO		Error if the afs daemon hasn't started yet
+ * \retval EACCES	Error if the user doesn't have super-user credentials
+ *
+ * \post set the server preferences, calling a function
+ *
+ * \notes this may only be performed by the local root user.
+ */
+
+DECL_PIOCTL(PSetSPrefsRand)
+{
+    struct sprefrequest *spin;	/* input */
+    struct setspref *sp;	/* input for randomization */
+    struct sprefinfo *spout;	/* output */
+    struct spref *srvout;	/* one output component */
+    int i, j;			/* counters for hash table traversal */
+    struct server *srvr;	/* one of CM's server structs */
+    struct srvAddr *sa;
+    int vlonly;			/* just return vlservers ? */
+    int isfs;
+    struct server *servers[NSERVERS];
+
+    AFS_STATCNT(PGetSPrefs);
+    if (!afs_resourceinit_flag)	/* afs daemons haven't started yet */
+	return EIO;		/* Inappropriate ioctl for device */
+
+
+    if (ainSize < sizeof(struct sprefrequest_33)) {
+	return ENOENT;
+    } else {
+	spin = ((struct sprefrequest *)ain);
+    }
+
+    if (ainSize > sizeof(struct sprefrequest_33)) {
+	vlonly = (spin->flags & DBservers);
+    } else
+	vlonly = 0;
+
+    /* struct sprefinfo includes 1 server struct...  that size gets added
+     * in during the loop that follows.
+     */
+    *aoutSize = sizeof(struct sprefinfo) - sizeof(struct spref);
+    spout = (struct sprefinfo *)aout;
+    spout->next_offset = spin->offset;
+    spout->num_servers = 0;
+    srvout = spout->servers;
+
+    /* sp = (struct setspref *)ain;
+    afs_setsprefsrand(&(sp->servers[0]), sp->num_servers,
+		  (sp->flags & DBservers)); JUMP */
+
+/***********************************************************************
+ * I EITHER NEED TO CALL afs_SortServers() FROM WITHIN THIS FUNCTION
+ * OR I NEED TO USE THE HASH TABLE TO GET A RESORTED LIST
+ * FOR afs_SortServer() I'LL NEED TO GO FROM HASH TABLE TO AN ARRAY OF 
+ * struct server*. afs_SortServer() WILL ALSO ENTAIL PUTTING SORTED LIST
+ * INTO *aout
+ ************************************************************************/
+
+    ObtainReadLock(&afs_xserver);
+    for (i = 0, j = 0; j < NSERVERS; j++) {	/* sift through hash table */
+	for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
+	    if (spin->offset > (unsigned short)i) {
+		continue;	/* catch up to where we left off */
+	    }
+	    spout->next_offset++;
+
+	    srvr = sa->server;
+	    servers[j] = sa->server;
+/*	    isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
+		|| (sa->sa_portal == AFS_FSPORT);
+
+	    if ((vlonly && isfs) || (!vlonly && !isfs)) {
+		/* only report ranks for vl servers NEEDS END COMMENT
+		continue;
+	    }
+
+	    srvout->host.s_addr = sa->sa_ip;
+	    srvout->rank = sa->sa_iprank;
+	    *aoutSize += sizeof(struct spref);
+	    spout->num_servers++;
+	    srvout++;
+
+	    if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
+		ReleaseReadLock(&afs_xserver);	/* no more room! NEEDS END COMMENT
+		return 0;
+	    }*/
+	}
+    }
+
+   if(!afs_SortServersRand(servers, NSERVERS))
+	return ENOENT;
+
+   for(j = 0; j < NSERVERS; j++) {	
+	srvout->host.s_addr = servers[j]->addr->sa_ip; /*sa->sa_ip;*/
+	srvout->rank = servers[j]->addr->sa_iprank; /*a->sa_iprank;*/
+ 	*aoutSize += sizeof(struct spref);
+	spout->num_servers++;
+	srvout++;
+    }
+    ReleaseReadLock(&afs_xserver);
+
+    spout->next_offset = 0;	/* start over from the beginning next time*/
+
+    return 0;
+}
+
+
+
 /* 
  * VIOC_GETSPREFS (43) - Get server ranks
  *
Index: src/afs/afs_server.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_server.c,v
retrieving revision 1.43.4.11
diff -u -r1.43.4.11 afs_server.c
--- src/afs/afs_server.c	18 Mar 2009 13:41:35 -0000	1.43.4.11
+++ src/afs/afs_server.c	16 Apr 2009 22:30:27 -0000
@@ -940,6 +940,50 @@
     }
 }				/*afs_SortServers */
 
+/*
+ * For Summer of Code Patch, should make the server rank random
+ */
+void
+afs_SortServersRand(struct server *aservers[], int count)
+{
+    struct server *ts, *index;
+    int i, j, low, k, l;
+
+    AFS_STATCNT(afs_SortServers);
+    for (i = 0; i < count; i++) {
+	if (!aservers[i])
+	    break;
+	aservers[i]->addr->sa_iprank = afs_randomMod15();
+
+	for (low = i, j = i + 1; j <= count; j++) {
+	    if ((!aservers[j]) || (!aservers[j]->addr))
+		break;
+	    if ((!aservers[low]) || (!aservers[low]->addr))
+		break;
+	    if (aservers[j]->addr->sa_iprank < aservers[low]->addr->sa_iprank) {
+		low = j;
+	    }
+	}
+	if (low != i) {
+	    ts = aservers[i];
+	    aservers[i] = aservers[low];
+	    aservers[low] = ts;
+	}
+    }
+
+    for (k=1; k < count; k++)
+    {
+	index = aservers[k];
+	l = k;
+	while ((l > 0) && (aservers[l-1]->addr->sa_iprank > index->addr->sa_iprank))
+	{
+		aservers[l] = aservers[l-1];
+		l = l - 1;
+	}
+	aservers[l] = index;
+    }
+}				/*afs_SortServers */
+
 /* afs_SetServerPrefs is rather system-dependent.  It pokes around in kernel
    data structures to determine what the local IP addresses and subnet masks 
    are in order to choose which server(s) are on the local subnet.
Index: src/venus/fs.c
===================================================================
RCS file: /cvs/openafs/src/venus/fs.c,v
retrieving revision 1.30.2.21
diff -u -r1.30.2.21 fs.c
--- src/venus/fs.c	16 Mar 2009 13:24:37 -0000	1.30.2.21
+++ src/venus/fs.c	16 Apr 2009 22:30:40 -0000
@@ -3213,6 +3213,78 @@
 }
 
 static int
+GetPrefCmdRand(struct cmd_syndesc *as, void *arock)
+{
+    afs_int32 code;
+    struct cmd_item *ti;
+    char *name, tbuffer[20];
+    afs_int32 addr;
+    FILE *outfd;
+    int resolve;
+    int vlservers = 0;
+    struct ViceIoctl blob;
+    struct sprefrequest *in;
+    struct sprefinfo *out;
+    int i;
+
+    ti = as->parms[0].items;	/* -file */
+    if (ti) {
+	if (debug)
+	    fprintf(stderr, "opening file %s\n", ti->data);
+	if (!(outfd = freopen(ti->data, "w", stdout))) {
+	    perror(ti->data);
+	    return 1;
+	}
+    }
+
+    ti = as->parms[1].items;	/* -numeric */
+    resolve = !(ti);
+    ti = as->parms[2].items;	/* -vlservers */
+    vlservers |= (ti ? DBservers : 0);
+    /*  ti = as->parms[3].items;   -cell */
+
+    in = (struct sprefrequest *)space;
+    in->offset = 0;
+
+    do {
+	blob.in_size = sizeof(struct sprefrequest);
+	blob.in = (char *)in;
+	blob.out = space;
+	blob.out_size = MAXSIZE;
+
+	in->num_servers =
+	    (MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref);
+	in->flags = vlservers;
+
+	code = pioctl(0, VIOC_GETSPREFSRAND, &blob, 1); /* VIOC_GETSPREFSRAND */
+	if (code) {
+	    perror("randomserverprefs pioctl");
+	    return 1;
+	}
+
+	out = (struct sprefinfo *)blob.out;
+
+	for (i = 0; i < out->num_servers; i++) {
+	    if (resolve) {
+		name = hostutil_GetNameByINet(out->servers[i].server.s_addr);
+	    } else {
+		addr = ntohl(out->servers[i].server.s_addr);
+		sprintf(tbuffer, "%d.%d.%d.%d", (addr >> 24) & 0xff,
+			(addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
+		name = tbuffer;
+	    }
+	    printf("%-50s %5u\n", name, out->servers[i].rank);
+	}
+
+	in->offset = out->next_offset;
+    } while (out->next_offset > 0);
+
+    return 0;
+}
+
+
+
+static int
 StoreBehindCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code = 0;
@@ -3507,6 +3579,16 @@
 /*    cmd_AddParm(ts, "-cell", CMD_FLAG, CMD_OPTIONAL, "cellname"); */
     cmd_CreateAlias(ts, "gp");
 
+    ts = cmd_CreateSyntax("randomserverprefs", GetPrefCmdRand, NULL,
+			  "get server ranks");
+    cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL,
+		"output to named file");
+    cmd_AddParm(ts, "-numeric", CMD_FLAG, CMD_OPTIONAL, "addresses only");
+    cmd_AddParm(ts, "-vlservers", CMD_FLAG, CMD_OPTIONAL, "VL servers");
+/*    cmd_AddParm(ts, "-cell", CMD_FLAG, CMD_OPTIONAL, "cellname"); */
+    cmd_CreateAlias(ts, "gp");
+
+
     ts = cmd_CreateSyntax("setacl", SetACLCmd, NULL, "set access control list");
     cmd_AddParm(ts, "-dir", CMD_LIST, 0, "directory");
     cmd_AddParm(ts, "-acl", CMD_LIST, 0, "access list entries");
Index: src/config/venus.h
===================================================================
RCS file: /cvs/openafs/src/config/venus.h,v
retrieving revision 1.12.2.8
diff -u -r1.12.2.8 venus.h
--- src/config/venus.h	20 Jan 2009 03:32:38 -0000	1.12.2.8
+++ src/config/venus.h	16 Apr 2009 22:32:05 -0000
@@ -159,6 +159,7 @@
 #define VIOCGETVCXSTATUS	_VICEIOCTL(41)
 #define VIOC_SETSPREFS33  	_VICEIOCTL(42)	/* Set server ranks */
 #define VIOC_GETSPREFS  	_VICEIOCTL(43)	/* Get server ranks */
+#define VIOC_GETSPREFSRAND	_VICEIOCTL(70)	/* randomize server ranks */
 #define VIOC_GAG    	        _VICEIOCTL(44)	/* silence CM */
 #define VIOC_TWIDDLE    	_VICEIOCTL(45)	/* adjust RX knobs */
 #define VIOC_SETSPREFS  	_VICEIOCTL(46)	/* Set server ranks */