Index: arlad/Makefile.in
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/Makefile.in,v
retrieving revision 1.83.2.3
diff -u -r1.83.2.3 Makefile.in
--- arlad/Makefile.in	2001/05/28 23:22:46	1.83.2.3
+++ arlad/Makefile.in	2001/07/02 03:43:20
@@ -87,6 +87,7 @@
 		arla-cli.c			\
 		arladeb.c			\
 		arladebu.c			\
+		cellcache.c			\
 		cmcb.c				\
 		conn.c				\
 		cred.c				\
@@ -109,6 +110,7 @@
 		afs_dir.h			\
 		arla_local.h			\
 		arladeb.h			\
+		cellcache.h			\
 		cmcb.h				\
 		conn.h				\
 		cred.h				\
@@ -132,6 +134,7 @@
 		arla.o				\
 		arladeb.o			\
 		arladebu.o			\
+		cellcache.o			\
 		cmcb.o				\
 		conn.o				\
 		cred.o				\
Index: arlad/arla.c
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/arla.c,v
retrieving revision 1.135.2.1
diff -u -r1.135.2.1 arla.c
--- arlad/arla.c	2001/04/30 00:00:34	1.135.2.1
+++ arlad/arla.c	2001/07/02 20:30:35
@@ -61,6 +61,7 @@
     fcache_store_state ();
     volcache_store_state ();
     cm_store_state ();
+    cellcache_store_state ();
 }
 
 struct conf_param {
@@ -202,7 +203,7 @@
 int cpu_usage;
 int version_flag;
 int help_flag;
-int recover = 0;
+int recover = 1;
 int dynroot_enable = 0;
 int cm_consistency = 0;
 
@@ -344,7 +345,10 @@
     arla_warnx (ADEBINIT, "conn_init numconns = %u", numconns);
     conn_init (numconns);
     arla_warnx (ADEBINIT, "cellcache");
-    cell_init (0, arla_log_method);
+    if (cell_init_malloc (0, arla_log_method) >= 0){
+      cellcache_init ();
+      cell_init_fill ();
+    }
     arla_warnx (ADEBINIT, "fprio");
     fprio_init(fpriofile);
     arla_warnx (ADEBINIT, "volcache numvols = %u", numvols);
Index: arlad/arla_local.h
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/arla_local.h,v
retrieving revision 1.61.2.1
diff -u -r1.61.2.1 arla_local.h
--- arlad/arla_local.h	2001/04/30 00:00:54	1.61.2.1
+++ arlad/arla_local.h	2001/07/02 03:42:11
@@ -122,6 +122,7 @@
 #include "ports.h"
 #include "conn.h"
 #include "fcache.h"
+#include "cellcache.h"
 #include "inter.h"
 #include "cred.h"
 #include "adir.h"
Index: arlad/cellcache.c
===================================================================
RCS file: cellcache.c
diff -N cellcache.c
--- /dev/null	Tue May  5 22:32:27 1998
+++ cellcache.c	Mon Jul  2 22:27:27 2001
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include "arla_local.h"
+
+RCSID("$Id: $") ;
+
+static int
+cache_store_state(int fd, cell_entry *ce){
+    int len;
+    char *linefeed="\n";
+    int error;
+
+    len=strlen(ce->name);
+    error = write(fd, ce->name, len);
+    if (error < 0)
+	return errno;
+    if (error != len)
+	return ENOSPC;
+    error = write(fd, linefeed, 1);
+    if (error < 0)
+	return errno;
+    if (error != 1)
+	return ENOSPC;
+    return 0;
+}
+
+int
+cellcache_store_state(){
+    int32_t cellnum;
+    cell_entry *ce;
+    int fd;
+    int bignumber = 10000;
+    int error;
+
+    fd = open ("cellcache.new", O_WRONLY | O_CREAT | O_TRUNC, 0666);
+    if (fd < 0)
+	return errno;
+    /* Cells start at 1 to some big number */
+    for (cellnum = 1; cellnum < bignumber; cellnum++){
+	ce = cell_get_by_id(cellnum);
+	if (ce == NULL)
+	    break;
+	if ((error = cache_store_state(fd, ce)) != 0){
+	    close(fd);
+	    unlink("cellcache.new");
+	    return error;
+	}
+    }
+    assert(cellnum < bignumber);
+    close(fd);
+    if (rename ("cellcache.new", "cellcache"))
+	return errno;
+    return 0;
+}
+
+static int
+cellcache_recover_state(){
+  FILE *f;
+  char s[1024];
+
+  f = fopen ("cellcache", "r");
+  if (f == NULL)
+    return errno;
+  while (fgets(s, 1024, f)) {
+    if (isspace(s[strlen(s) - 1]))
+      s[strlen(s) - 1] = 0;
+    cell_new(s);
+  }
+  fclose(f);
+  return 0;
+}
+
+void
+cellcache_init(){
+  if (recover)
+    cellcache_recover_state();
+}
Index: arlad/cellcache.h
===================================================================
RCS file: cellcache.h
diff -N cellcache.h
--- /dev/null	Tue May  5 22:32:27 1998
+++ cellcache.h	Mon Jul  2 20:39:40 2001
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * The interface for the cell-cache.
+ */
+
+/* $Id: $ */
+
+#ifndef _CELLCACHE_H_
+#define _CELLCACHE_H_
+
+#include <fcntl.h>
+
+int
+cellcache_store_state (void);
+void
+cellcache_init(void);
+
+#endif /* _CELLCACHE_H_ */
Index: arlad/dynroot.c
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/dynroot.c,v
retrieving revision 1.13.2.2
diff -u -r1.13.2.2 dynroot.c
--- arlad/dynroot.c	2001/05/28 15:19:20	1.13.2.2
+++ arlad/dynroot.c	2001/06/23 08:57:38
@@ -53,7 +53,6 @@
 
 static int32_t dynrootcell = 0;			/* this is the dynroocell */
 static Bool dynroot_enable  = 0;		/* is dynroot enabled ? */
-static unsigned long last_celldb_version = 0;	/* last version of celldb */
 
 /*
  * Magic glue wrt afsvnode#
@@ -81,6 +80,10 @@
 {
     struct create_entry *entry = (struct create_entry *) arg;
     int ret;
+    
+    /* dynroot itself should not be visible as an entry in /afs */
+    if (cell->id == DYNROOT_CELLID)
+	return 0;
 
     if (!cell_dynroot(cell))
 	return 0;
@@ -256,12 +259,16 @@
     int ret, fd, rootnode;
     size_t len;
     fbuf dir;
+    static unsigned long last_celldb_version = 0;	/* last version of celldb */
+    unsigned long l;
 
     rootnode = entry->fid.fid.Vnode == DYNROOT_ROOTDIR ? 1 : 0;
 
+    l = last_celldb_version;
+    last_celldb_version = cell_get_version();
     if (entry->flags.attrp &&
 	entry->flags.datap &&
-	(!rootnode || last_celldb_version == cell_get_version()))
+	(!rootnode || last_celldb_version == l))
 	return 0;
 
     fd = fcache_open_file (entry, O_RDWR);
@@ -347,6 +354,24 @@
 }
 
 /*
+ * returns TRUE if `entry' is _the_ top dynroot entry (/afs)
+ */
+
+Bool
+dynroot_is_top_dynrootp (FCacheEntry *entry)
+{
+    assert (entry);
+
+    if (dynroot_enable &&
+	entry->fid.Cell == dynrootcell &&
+	entry->fid.fid.Volume == DYNROOT_ROOTVOLUME &&
+	entry->fid.fid.Vnode == DYNROOT_ROOTDIR)
+	return TRUE;
+
+    return FALSE;
+}
+
+/*
  * Return what status the dynroot is in.
  */
 
@@ -384,4 +409,26 @@
 int32_t dynroot_volumeid (void)
 {
     return DYNROOT_ROOTVOLUME;
+}
+
+/*
+ * Create an entry for a new cell in the root dynamically
+ * on the fly
+ */
+
+int
+dynroot_create_entry_dynamically (const char *cellname,
+				  FCacheEntry *entry, 
+				  CredCacheEntry *ce)
+{
+    if (cell_add_dynroot(cellname))
+	return ENOENT;
+
+    dynroot_get_node(entry, ce);
+    break_callback(entry);
+    /* Turn some of the flags recently set in dynroot_get_node off again */
+    entry->tokens &= ~(XFS_DATA_R|XFS_DATA_W);
+    entry->flags.datap = FALSE;
+
+    return 0;
 }
Index: arlad/dynroot.h
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/dynroot.h,v
retrieving revision 1.2.2.1
diff -u -r1.2.2.1 dynroot.h
--- arlad/dynroot.h	2001/05/28 15:19:20	1.2.2.1
+++ arlad/dynroot.h	2001/06/17 18:34:17
@@ -37,6 +37,10 @@
 
 #define DYNROOT_DEFAULT 0
 
+int dynroot_create_entry_dynamically (const char *cellname, 
+				      FCacheEntry *cacheentry, 
+				      CredCacheEntry *ce);
+
 int dynroot_fetch_vldbN (nvldbentry *entry);
 
 Bool dynroot_isvolumep (int cell, const char *volume);
@@ -47,6 +51,8 @@
 
 Bool dynroot_is_dynrootp (FCacheEntry *entry);
 
+Bool dynroot_is_top_dynrootp (FCacheEntry *entry);
+
 Bool dynroot_enablep (void);
 
 Bool dynroot_setenable (Bool enable);
@@ -54,3 +60,4 @@
 int32_t dynroot_cellid (void);
 
 int32_t dynroot_volumeid (void);
+
Index: arlad/inter.c
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/inter.c,v
retrieving revision 1.110.2.3
diff -u -r1.110.2.3 inter.c
--- arlad/inter.c	2001/06/05 01:27:05	1.110.2.3
+++ arlad/inter.c	2001/06/17 18:41:49
@@ -599,6 +599,12 @@
      }
 
      error = adir_lookup (entry, name, res);
+     if (error == ENOENT && dynroot_is_top_dynrootp (entry)) {
+	 arla_warnx(ADEBCM, "cm_lookup(): Creating dynamic entry for %s", name);
+	 error = dynroot_create_entry_dynamically(name, entry, *ce);
+	 if (!error)
+	     error = adir_lookup (entry, name, res);
+     }
      if (error) {
 	 fcache_release(entry);
 	 ret.res   = -1;
Index: arlad/volcache.c
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/arlad/volcache.c,v
retrieving revision 1.95.2.4
diff -u -r1.95.2.4 volcache.c
--- arlad/volcache.c	2001/03/04 05:11:19	1.95.2.4
+++ arlad/volcache.c	2001/06/17 17:28:29
@@ -588,7 +588,11 @@
 		    "Cannot find any db servers in cell %d(%s) while "
 		    "getting data for volume `%s'",
 		    cell, cell_num2name(cell), name);
-	assert (cell_is_sanep (cell));
+	/* haba: cellnums cached in xfs */
+	/* Instead of asserting on cell existence, try to recycle */
+	/* the entry and let that code assert if that is not possible */
+	recycle_entry(e);
+	/* assert (cell_is_sanep (cell)); */
 	return ENOENT;
     }
 
Index: lib/ko/ko.h
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/lib/ko/ko.h,v
retrieving revision 1.27.2.2
diff -u -r1.27.2.2 ko.h
--- lib/ko/ko.h	2001/05/06 22:40:49	1.27.2.2
+++ lib/ko/ko.h	2001/07/02 19:37:44
@@ -67,11 +67,14 @@
     time_t timeout;		/* timeout of address */
 } cell_db_entry;
 
+/*
+ * Flags used in cell_entry
+ */
+
 enum { SUID_CELL 	= 0x1,	/* if this is a suid cell */
        DYNROOT_CELL	= 0x2	/* cell should show up in dynroot */
 };
 
-
 typedef struct {
     int32_t id;			/* Cell-ID */
     const char *name;		/* Domain-style name */
@@ -83,7 +86,16 @@
     time_t timeout;		/* when this entry expire */
 } cell_entry;
 
+/*
+ * The magic cell id for the dynroot cell
+ * (normal cells are numbered from 1)
+ */
+
+#define DYNROOT_CELLID 0
+
 void	      cell_init (int cellcachesize, Log_method *log);
+int	      cell_init_malloc (int cellcachesize, Log_method *log);
+void	      cell_init_fill (void);
 
 const cell_db_entry *cell_dbservers_by_id (int32_t cell, int *);
 
@@ -96,6 +108,7 @@
 cell_entry    *cell_get_by_id (int32_t cell);
 cell_entry    *cell_new (const char *name);
 cell_entry    *cell_new_dynamic (const char *name);
+int            cell_add_dynroot(const char *cellname);
 Bool	       cell_dynroot (const cell_entry *c);
 Bool           cell_issuid (const cell_entry *c);
 Bool           cell_issuid_by_num (int32_t cell);
Index: lib/ko/kocell.c
===================================================================
RCS file: /afs/stacken.kth.se/src/SourceRepository/arla/lib/ko/kocell.c,v
retrieving revision 1.47.2.2
diff -u -r1.47.2.2 kocell.c
--- lib/ko/kocell.c	2001/05/06 22:40:50	1.47.2.2
+++ lib/ko/kocell.c	2001/07/02 20:12:55
@@ -160,7 +160,8 @@
 
      len = strcspn (line, " \t#");
      line[len] = '\0';
-     c = cell_new (line);
+     if ((c = cell_get_by_name(line)) == NULL)
+       c = cell_new (line);
      if (c == NULL)
 	 err (1, "malloc failed");
 
@@ -263,6 +264,19 @@
 }
 
 /*
+ * cell name -> cell_entry * (hashtable only)
+ */
+
+static cell_entry *
+get_hash_by_name (const char *cellname)
+{
+    cell_entry key;
+
+    key.name = cellname;
+    return (cell_entry *)hashtabsearch (cellnamehtab, &key);
+}
+
+/*
  * try to lookup `cell' in DNS
  * if c == NULL, a new cell will be allocated
  */
@@ -277,6 +291,8 @@
     int lowest_ttl;
     int i;
     struct timeval tv;
+    char *answerdomain = NULL;
+    int ret = 0;
 
     memset (dbservers, 0, sizeof(dbservers));
     gettimeofday(&tv, NULL);
@@ -287,13 +303,19 @@
 		 "dns_lookup_cell: failed to resolve cell %s", cell);
 	return 1;
     }
-    if (c == NULL)
-	c = cell_new_dynamic (cell);
 
     for(rr = r->head; rr;rr=rr->next){
 	if(rr->type == T_AFSDB) {
 	    struct mx_record *mx = (struct mx_record*)rr->u.data;
-
+	    assert(rr->domain); /* rr filled in as expected? */
+	    if (answerdomain == NULL)
+	      answerdomain = rr->domain;
+	    if (ret == 0 && strcmp(cell, rr->domain) != 0) {
+		log_log (cell_log, CDEBDNS, 
+			 "dns_lookup_cell: asked for %s got back domain %s", 
+			 cell, rr->domain);
+		ret = 1;
+	    }
 	    if (mx->preference != 1) {
 		break;
 	    }
@@ -320,12 +342,20 @@
 	    }
 	}
     }
+
+    if (c == NULL && answerdomain != NULL) {
+	if ((c = get_hash_by_name (answerdomain)) == NULL)
+	    c = cell_new_dynamic (answerdomain);
+    }
     dns_free_data(r);
+    if (c == NULL)
+	return 1;
 
     /* catch the hosts that didn't fit in additional rr */
-    c->timeout = lowest_ttl + tv.tv_sec;
+    if (c->timeout != 0)
+	c->timeout = lowest_ttl + tv.tv_sec;
     updatehosts (c, dbnum, dbservers);
-    return 0;
+    return ret;
 }
 
 /*
@@ -347,20 +377,20 @@
     updatehosts (c, c->ndbservers, c->dbservers);
 }
 
+
 /*
- * cell name -> cell_entry *
+ * cell name -> cell_entry * (hashtable or dns_lookup)
  */
 
 cell_entry *
 cell_get_by_name (const char *cellname)
 {
-    cell_entry key, *data;
+    cell_entry *data;
 
-    key.name = cellname;
-    data = (cell_entry *)hashtabsearch (cellnamehtab, &key);
+    data = get_hash_by_name(cellname);
     if (data == NULL) {
 	dns_lookup_cell (cellname, NULL);
-	data = (cell_entry *)hashtabsearch (cellnamehtab, &key);
+	data = get_hash_by_name(cellname);
     }
     if (data)
 	update_cell (data);
@@ -418,6 +448,7 @@
     hashtabadd (cellnumhtab, c);
     c->timeout      = 0;
     celldb_version++;
+    log_log (cell_log, CDEBERR, "Inserted cell %s with id %d", name, c->id);
     return c;
 }
 
@@ -432,6 +463,9 @@
     FILE *f;
 
     c = cell_new (name);
+
+    return c; /* haba does not believe in changing CellServDB on the fly */
+
     if (c == NULL)
 	return NULL;
     c->expl = "dynamically added cell";
@@ -649,24 +683,35 @@
 {
     return parse_simple_file (filename, addsuidcell);
 }
-
 /*
- *
+ *   Just as cell_add_dynroot but ignores return
  */
 
 static void
 add_dynroot(const char *cellname)
 {
+    if (cell_add_dynroot(cellname))
+	dynrootdb_in_use = 1;
+}
+
+/*
+ *   Adds cell to cell cache and sets its dynroot flag.
+ *   returns NULL on error, otherwise cell_entry struct.
+ */
+
+int
+cell_add_dynroot(const char *cellname)
+{
     cell_entry *e; 
 
     e = cell_get_by_name (cellname);
-    if (e == NULL) {
+    if (cell_get_by_name (cellname) == NULL) {
 	log_log (cell_log, CDEBWARN,
 		 "dynroot: cell %s doesn't exist in the db\n", cellname);
-    } else {
+	return -1;
+    } else
 	e->flags |= DYNROOT_CELL;
-	dynrootdb_in_use = 1;
-    }
+    return 0;
 }
 
 static int
@@ -682,16 +727,20 @@
 static int cell_inited = 0;
 
 void
-cell_init (int cellcachesize, Log_method *log)
+cell_init(int cellcachesize, Log_method *log)
 {
-    char *env;
-    int ret;
+  if (cell_init_malloc (cellcachesize, log) >= 0)
+    cell_init_fill();
+}
 
+int
+cell_init_malloc (int cellcachesize, Log_method *log)
+{
     assert (log);
 
     if (cell_inited) {
 	log_log (cell_log, CDEBWARN, "cell_init: Already initlized");
-	return;
+	return -1;
     }
     cell_inited = 1;
 
@@ -712,6 +761,14 @@
     cellnumhtab  = hashtabnew (cellcachesize, cellnumcmp,  cellnumhash);
     if (cellnumhtab == NULL)
 	errx (1, "cell_init: hashtabnew failed");
+    return 1;
+}
+
+void
+cell_init_fill()
+{
+    char *env;
+    int ret;
 
     env = getenv ("AFSCELL");
     if (env != NULL) {
@@ -1102,7 +1159,7 @@
 	free (c);
 	return errno;
     }
-    c->id         = 0; /* XXX */
+    c->id         = DYNROOT_CELLID;
     c->expl       = "The special dynroot cell";
     c->ndbservers = 0;
     c->dbservers  = NULL;
