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/17 22:08:56
@@ -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#
@@ -256,12 +255,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 +350,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 +405,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/06/17 18:51:32
@@ -96,6 +96,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/06/17 21:26:35
@@ -277,6 +277,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 +289,18 @@
 		 "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;
-
+	    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 +327,20 @@
 	    }
 	}
     }
+
+    if (c == 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;
 }
 
 /*
@@ -351,16 +366,24 @@
  * cell name -> cell_entry *
  */
 
+static cell_entry *
+get_hash_by_name (const char *cellname)
+{
+    cell_entry key;
+
+    key.name = cellname;
+    return (cell_entry *)hashtabsearch (cellnamehtab, &key);
+}
+
 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 +441,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 +456,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 +676,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
