rendered paste bodyIndex: 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 */