Subject: afs/fs/afs volume.h,1.4,1.5 volume.c,1.7,1.8 vnode.h,1.4,1.5 vnode.c,1.6,1.7 vlocation.c,1.8,1.9 vlclient.h,1.4,1.5 vlclient.c,1.6,1.7 super.h,1.2,1.3 super.c,1.8,1.9 server.c,1.3,1.4 mntpt.c,1.6,1.7 main.c,1.11,1.12 kafstimod.c,1.6,1.7 internal.h,1.14,1.15 inode.c,1.10,1.11 file.c,1.7,1.8 dir.c,1.9,1.10 cmservice.c,1.6,1.7 cell.h,1.4,1.5 cell.c,1.8,1.9 callback.c,1.3,1.4 Makefile,1.11,1.12

From: [email-masked]
Date: Fri, 04 Jul 2003 16:26:34 +0100

Update of /home/cvs/afs/fs/afs
In directory phoenix.infradead.org:/tmp/cvs-serv10566/fs/afs

Modified Files:
	volume.h volume.c vnode.h vnode.c vlocation.c vlclient.h 
	vlclient.c super.h super.c server.c mntpt.c main.c kafstimod.c 
	internal.h inode.c file.c dir.c cmservice.c cell.h cell.c 
	callback.c Makefile 
Log Message:
done some cleaning up
moved a little towards hch-compliance (CodingStyle)
added automount/expiry (requires kernel patch)
made cache index match functions request update/delete if necessary

Index: volume.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/volume.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- volume.h	6 Jun 2003 08:33:37 -0000	1.4
+++ volume.h	4 Jul 2003 15:26:31 -0000	1.5
@@ -87,13 +87,16 @@
 	unsigned short		valid;		/* T if valid */
 };
 
-extern int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_vlocation);
+extern int afs_vlocation_lookup(struct afs_cell *cell,
+				const char *name,
+				unsigned namesz,
+				struct afs_vlocation **_vlocation);
 
 #define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
 
-extern void __afs_put_vlocation(afs_vlocation_t *vlocation);
-extern void afs_put_vlocation(afs_vlocation_t *vlocation);
-extern void afs_vlocation_do_timeout(afs_vlocation_t *vlocation);
+extern void __afs_put_vlocation(struct afs_vlocation *vlocation);
+extern void afs_put_vlocation(struct afs_vlocation *vlocation);
+extern void afs_vlocation_do_timeout(struct afs_vlocation *vlocation);
 
 /*****************************************************************************/
 /*
@@ -114,14 +117,19 @@
 	struct rw_semaphore	server_sem;	/* lock for accessing current server */
 };
 
-extern int afs_volume_lookup(char *name, int ro, afs_volume_t **_volume);
+extern int afs_volume_lookup(const char *name,
+			     struct afs_cell *cell,
+			     int rwpath,
+			     struct afs_volume **_volume);
 
 #define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0)
 
-extern void afs_put_volume(afs_volume_t *volume);
+extern void afs_put_volume(struct afs_volume *volume);
 
-extern int afs_volume_pick_fileserver(afs_volume_t *volume, afs_server_t **_server);
+extern int afs_volume_pick_fileserver(struct afs_volume *volume, struct afs_server **_server);
 
-extern int afs_volume_release_fileserver(afs_volume_t *volume, afs_server_t *server, int result);
+extern int afs_volume_release_fileserver(struct afs_volume *volume,
+					 struct afs_server *server,
+					 int result);
 
 #endif /* _LINUX_AFS_VOLUME_H */

Index: volume.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/volume.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- volume.c	9 Jun 2003 13:52:04 -0000	1.7
+++ volume.c	4 Jul 2003 15:26:31 -0000	1.8
@@ -56,19 +56,19 @@
  * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W if not available
  * - Rule 3: If parent volume is R/W, then only mount R/W volume unless explicitly told otherwise
  */
-int afs_volume_lookup(char *name, int rwparent, afs_volume_t **_volume)
+int afs_volume_lookup(const char *name, struct afs_cell *cell, int rwpath,
+		      afs_volume_t **_volume)
 {
-	afs_vlocation_t *vlocation = NULL;
+	struct afs_vlocation *vlocation = NULL;
+	struct afs_volume *volume = NULL;
 	afs_voltype_t type;
-	afs_volume_t *volume = NULL;
-	afs_cell_t *cell = NULL;
-	char *cellname, *volname, *suffix;
+	const char *cellname, *volname, *suffix;
 	char srvtmask;
-	int force, ret, loop;
+	int force, ret, loop, cellnamesz, volnamesz;
 
-	_enter(",%s,",name);
+	_enter("%s,,%d,", name, rwpath);
 
-	if (!name || (name[0]!='%' && name[0]!='#') || !name[1]) {
+	if (!name || (name[0] != '%' && name[0] != '#') || !name[1]) {
 		printk("kAFS: unparsable volume name\n");
 		return -EINVAL;
 	}
@@ -77,24 +77,22 @@
 	force = 0;
 	type = AFSVL_ROVOL;
 
-	if (rwparent || name[0]=='%') {
+	if (rwpath || name[0] == '%') {
 		type = AFSVL_RWVOL;
 		force = 1;
 	}
 
-	suffix = strrchr(name,'.');
+	suffix = strrchr(name, '.');
 	if (suffix) {
-		if (strcmp(suffix,".readonly")==0) {
+		if (strcmp(suffix, ".readonly") == 0) {
 			type = AFSVL_ROVOL;
 			force = 1;
 		}
-		else if (strcmp(suffix,".backup")==0) {
+		else if (strcmp(suffix, ".backup") == 0) {
 			type = AFSVL_BACKVOL;
 			force = 1;
 		}
-		else if (suffix[1]==0) {
-			*suffix = 0;
-			suffix = NULL;
+		else if (suffix[1] == 0) {
 		}
 		else {
 			suffix = NULL;
@@ -103,38 +101,45 @@
 
 	/* split the cell and volume names */
 	name++;
-	volname = strchr(name,':');
+	volname = strchr(name, ':');
 	if (volname) {
-		*volname++ = 0;
 		cellname = name;
+		cellnamesz = volname - name;
 	}
 	else {
 		volname = name;
 		cellname = NULL;
+		cellnamesz = 0;
 	}
 
-	_debug("CELL:%s VOLUME:%s SUFFIX:%s TYPE:%d%s",
-	       cellname,volname,suffix?:"-",type,force?" FORCE":"");
+	volnamesz = suffix ? suffix - volname : strlen(volname);
 
-	/* lookup the cell record */
-	ret = afs_cell_lookup(cellname,&cell);
-	if (ret<0)
-		printk("kAFS: unable to lookup cell '%s'\n",cellname?:"");
+	_debug("CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
+	       cellnamesz, cellnamesz, cellname ?: "", cell,
+	       volnamesz, volnamesz, volname, suffix ?: "-",
+	       type,
+	       force ? " FORCE" : "");
 
-	if (cellname) volname[-1] = ':';
-	if (ret<0)
-		goto error;
+	/* lookup the cell record */
+	if (cellname || !cell) {
+		ret = afs_cell_lookup(cellname, cellnamesz, &cell);
+		if (ret<0) {
+			printk("kAFS: unable to lookup cell '%s'\n", cellname ?: "");
+			goto error;
+		}
+	}
+	else {
+		afs_get_cell(cell);
+	}
 
 	/* lookup the volume location record */
-	if (suffix) *suffix = 0;
-	ret = afs_vlocation_lookup(cell,volname,&vlocation);
-	if (suffix) *suffix = '.';
-	if (ret<0)
+	ret = afs_vlocation_lookup(cell, volname, volnamesz, &vlocation);
+	if (ret < 0)
 		goto error;
 
 	/* make the final decision on the type we want */
 	ret = -ENOMEDIUM;
-	if (force && !(vlocation->vldb.vidmask & (1<<type)))
+	if (force && !(vlocation->vldb.vidmask & (1 << type)))
 		goto error;
 
 	srvtmask = 0;
@@ -142,7 +147,7 @@
 		srvtmask |= vlocation->vldb.srvtmask[loop];
 
 	if (force) {
-		if (!(srvtmask & (1 <<type)))
+		if (!(srvtmask & (1 << type)))
 			goto error;
 	}
 	else if (srvtmask & AFS_VOL_VTM_RO) {
@@ -169,12 +174,12 @@
 	_debug("creating new volume record");
 
 	ret = -ENOMEM;
-	volume = kmalloc(sizeof(afs_volume_t),GFP_KERNEL);
+	volume = kmalloc(sizeof(afs_volume_t), GFP_KERNEL);
 	if (!volume)
 		goto error_up;
 
-	memset(volume,0,sizeof(afs_volume_t));
-	atomic_set(&volume->usage,1);
+	memset(volume, 0, sizeof(afs_volume_t));
+	atomic_set(&volume->usage, 1);
 	volume->type		= type;
 	volume->type_force	= force;
 	volume->cell		= cell;
@@ -207,7 +212,7 @@
 	vlocation->vols[type] = volume;
 
  success:
-	_debug("kAFS selected %s volume %08x",afs_voltypes[volume->type],volume->vid);
+	_debug("kAFS selected %s volume %08x", afs_voltypes[volume->type], volume->vid);
 	*_volume = volume;
 	ret = 0;
 
@@ -215,18 +220,17 @@
  error_up:
 	up_write(&cell->vl_sem);
  error:
-	if (vlocation)	afs_put_vlocation(vlocation);
-	if (cell)	afs_put_cell(cell);
+	afs_put_vlocation(vlocation);
+	afs_put_cell(cell);
 
-	_leave(" = %d (%p)",ret,volume);
+	_leave(" = %d (%p)", ret, volume);
 	return ret;
 
  error_discard:
 	up_write(&cell->vl_sem);
 
 	for (loop=volume->nservers-1; loop>=0; loop--)
-		if (volume->servers[loop])
-			afs_put_server(volume->servers[loop]);
+		afs_put_server(volume->servers[loop]);
 
 	kfree(volume);
 	goto error;
@@ -241,6 +245,9 @@
 	afs_vlocation_t *vlocation;
 	int loop;
 
+	if (!volume)
+		return;
+
 	_enter("%p",volume);
 
 	vlocation = volume->vlocation;
@@ -267,8 +274,7 @@
 	afs_put_vlocation(vlocation);
 
 	for (loop=volume->nservers-1; loop>=0; loop--)
-		if (volume->servers[loop])
-			afs_put_server(volume->servers[loop]);
+		afs_put_server(volume->servers[loop]);
 
 	kfree(volume);

Index: vnode.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/vnode.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- vnode.h	6 Jun 2003 08:33:37 -0000	1.4
+++ vnode.h	4 Jul 2003 15:26:31 -0000	1.5
@@ -27,7 +27,9 @@
  */
 struct afs_cache_vnode
 {
-	afs_vnodeid_t		vnode;		/* vnode ID */
+	afs_vnodeid_t		vnode_id;	/* vnode ID */
+	unsigned		vnode_unique;	/* vnode ID uniquifier */
+	afs_dataversion_t	data_version;	/* data version */
 };
 
 extern struct cachefs_index_def afs_vnode_cache_index_def;

Index: vnode.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/vnode.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- vnode.c	10 Jun 2003 17:49:49 -0000	1.6
+++ vnode.c	4 Jul 2003 15:26:31 -0000	1.7
@@ -72,8 +72,7 @@
 
 	spin_unlock(&vnode->lock);
 
-	if (oldserver)
-		afs_put_server(oldserver);
+	afs_put_server(oldserver);
 
 	_leave("");
 } /* end afs_vnode_cb_timed_out() */
@@ -137,8 +136,7 @@
 
 	wake_up_all(&vnode->update_waitq);
 
-	if (oldserver)
-		afs_put_server(oldserver);
+	afs_put_server(oldserver);
 
 	_leave("");
 
@@ -337,8 +335,12 @@
 
 	_enter("");
 
-	if (vnode->fid.vnode == cvnode->vnode)
-		return CACHEFS_MATCH_SUCCESS;
+	if (vnode->fid.vnode != cvnode->vnode_id)
+		return CACHEFS_MATCH_FAILED;
+
+	if (vnode->fid.unique != cvnode->vnode_unique ||
+	    vnode->status.version != cvnode->data_version)
+		return CACHEFS_MATCH_SUCCESS_DELETE;
 
 	return CACHEFS_MATCH_FAILED;
 } /* end afs_vnode_cache_match() */
@@ -354,6 +356,8 @@
 
 	_enter("");
 
-	cvnode->vnode = vnode->fid.vnode;
+	cvnode->vnode_id	= vnode->fid.vnode;
+	cvnode->vnode_unique	= vnode->fid.unique;
+	cvnode->data_version	= vnode->status.version;
 
 } /* end afs_vnode_cache_update() */

Index: vlocation.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/vlocation.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- vlocation.c	9 Jun 2003 13:52:04 -0000	1.8
+++ vlocation.c	4 Jul 2003 15:26:31 -0000	1.9
@@ -75,21 +75,23 @@
  */
 static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation,
 					   const char *name,
+					   unsigned namesz,
 					   struct afs_cache_vlocation *vldb)
 {
 	afs_server_t *server = NULL;
 	afs_cell_t *cell = vlocation->cell;
 	int count, ret;
 
-	_enter("%s,%s,",cell->name,name);
+	_enter("%s,%*.*s,%u", cell->name, namesz, namesz, name, namesz);
 
 	ret = -ENOMEDIUM;
 	for (count=cell->vl_naddrs; count>0; count--) {
 		_debug("CellServ[%hu]: %08x",
-		       cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr);
+		       cell->vl_curr_svix,
+		       cell->vl_addrs[cell->vl_curr_svix].s_addr);
 
 		/* try and create a server */
-		ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server);
+		ret = afs_server_lookup(cell, &cell->vl_addrs[cell->vl_curr_svix], &server);
 		switch (ret) {
 		case 0:
 			break;
@@ -101,7 +103,7 @@
 		}
 
 		/* attempt to access the VL server */
-		ret = afs_rxvl_get_entry_by_name(server,name,vldb);
+		ret = afs_rxvl_get_entry_by_name(server, name, namesz, vldb);
 		switch (ret) {
 		case 0:
 			afs_put_server(server);
@@ -118,7 +120,7 @@
 			}
 			up_write(&server->sem);
 			afs_put_server(server);
-			if (ret==-ENOMEM || ret==-ENONET)
+			if (ret == -ENOMEM || ret == -ENONET)
 				goto out;
 			goto rotate;
 		case -ENOMEDIUM:
@@ -157,15 +159,16 @@
 	afs_cell_t *cell = vlocation->cell;
 	int count, ret;
 
-	_enter("%s,%x,%d,",cell->name,volid,voltype);
+	_enter("%s,%x,%d,", cell->name, volid, voltype);
 
 	ret = -ENOMEDIUM;
 	for (count=cell->vl_naddrs; count>0; count--) {
 		_debug("CellServ[%hu]: %08x",
-		       cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr);
+		       cell->vl_curr_svix,
+		       cell->vl_addrs[cell->vl_curr_svix].s_addr);
 
 		/* try and create a server */
-		ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server);
+		ret = afs_server_lookup(cell, &cell->vl_addrs[cell->vl_curr_svix], &server);
 		switch (ret) {
 		case 0:
 			break;
@@ -177,7 +180,7 @@
 		}
 
 		/* attempt to access the VL server */
-		ret = afs_rxvl_get_entry_by_id(server,volid,voltype,vldb);
+		ret = afs_rxvl_get_entry_by_id(server, volid, voltype, vldb);
 		switch (ret) {
 		case 0:
 			afs_put_server(server);
@@ -194,7 +197,7 @@
 			}
 			up_write(&server->sem);
 			afs_put_server(server);
-			if (ret==-ENOMEM || ret==-ENONET)
+			if (ret == -ENOMEM || ret == -ENONET)
 				goto out;
 			goto rotate;
 		case -ENOMEDIUM:
@@ -227,7 +230,8 @@
  * - lookup in the local cache if not able to find on the VL server
  * - insert/update in the local cache if did get a VL response
  */
-int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_vlocation)
+int afs_vlocation_lookup(afs_cell_t *cell, const char *name, unsigned namesz,
+			 afs_vlocation_t **_vlocation)
 {
 	struct afs_cache_vlocation vldb;
 	struct list_head *_p;
@@ -236,48 +240,56 @@
 	afs_volid_t vid;
 	int active = 0, ret;
 
-	_enter(",%s,%s,",cell->name,name);
+	_enter("{%s},%*.*s,%u,", cell->name, namesz, namesz, name, namesz);
 
-	if (strlen(name)>sizeof(vlocation->vldb.name)) {
+	if (namesz > sizeof(vlocation->vldb.name)) {
 		_leave(" = -ENAMETOOLONG");
 		return -ENAMETOOLONG;
 	}
 
 	/* search the cell's active list first */
-	list_for_each(_p,&cell->vl_list) {
-		vlocation = list_entry(_p,afs_vlocation_t,link);
-		if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0)
+	list_for_each(_p, &cell->vl_list) {
+		vlocation = list_entry(_p, afs_vlocation_t, link);
+		if (namesz < sizeof(vlocation->vldb.name) &&
+		    vlocation->vldb.name[namesz] != '\0')
+			continue;
+
+		if (memcmp(vlocation->vldb.name, name, namesz) == 0)
 			goto found_in_memory;
 	}
 
 	/* search the cell's graveyard list second */
 	spin_lock(&cell->vl_gylock);
-	list_for_each(_p,&cell->vl_graveyard) {
-		vlocation = list_entry(_p,afs_vlocation_t,link);
-		if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0)
+	list_for_each(_p, &cell->vl_graveyard) {
+		vlocation = list_entry(_p, afs_vlocation_t, link);
+		if (namesz < sizeof(vlocation->vldb.name) &&
+		    vlocation->vldb.name[namesz] != '\0')
+			continue;
+
+		if (memcmp(vlocation->vldb.name, name, namesz) == 0)
 			goto found_in_graveyard;
 	}
 	spin_unlock(&cell->vl_gylock);
 
 	/* not in the cell's in-memory lists - create a new record */
-	vlocation = kmalloc(sizeof(afs_vlocation_t),GFP_KERNEL);
+	vlocation = kmalloc(sizeof(afs_vlocation_t), GFP_KERNEL);
 	if (!vlocation)
 		return -ENOMEM;
 
-	memset(vlocation,0,sizeof(afs_vlocation_t));
-	atomic_set(&vlocation->usage,1);
+	memset(vlocation, 0, sizeof(afs_vlocation_t));
+	atomic_set(&vlocation->usage, 1);
 	INIT_LIST_HEAD(&vlocation->link);
 	rwlock_init(&vlocation->lock);
-	strncpy(vlocation->vldb.name,name,sizeof(vlocation->vldb.name));
+	memcpy(vlocation->vldb.name, name, namesz);
 
-	afs_timer_init(&vlocation->timeout,&afs_vlocation_timer_ops);
-	afs_timer_init(&vlocation->upd_timer,&afs_vlocation_update_timer_ops);
-	afs_async_op_init(&vlocation->upd_op,&afs_vlocation_update_op_ops);
+	afs_timer_init(&vlocation->timeout, &afs_vlocation_timer_ops);
+	afs_timer_init(&vlocation->upd_timer, &afs_vlocation_update_timer_ops);
+	afs_async_op_init(&vlocation->upd_op, &afs_vlocation_update_op_ops);
 
 	afs_get_cell(cell);
 	vlocation->cell = cell;
 
-	list_add_tail(&vlocation->link,&cell->vl_list);
+	list_add_tail(&vlocation->link, &cell->vl_list);
 
 	/* we want to store it in the cache, plus it might already be encached */
 	cachefs_acquire_cookie(cell->cache,
@@ -289,9 +301,10 @@
 		goto found_in_cache;
 
 	/* try to look up an unknown volume in the cell VL databases by name */
-	ret = afs_vlocation_access_vl_by_name(vlocation,name,&vldb);
+	ret = afs_vlocation_access_vl_by_name(vlocation, name, namesz, &vldb);
 	if (ret<0) {
-		printk("kAFS: failed to locate '%s' in cell '%s'\n",name,cell->name);
+		printk("kAFS: failed to locate '%*.*s' in cell '%s'\n",
+		       namesz, namesz, name, cell->name);
 		goto error;
 	}
 
@@ -302,7 +315,7 @@
 	_debug("found in graveyard");
 	atomic_inc(&vlocation->usage);
 	list_del(&vlocation->link);
-	list_add_tail(&vlocation->link,&cell->vl_list);
+	list_add_tail(&vlocation->link, &cell->vl_list);
 	spin_unlock(&cell->vl_gylock);
 
 	afs_kafstimod_del_timer(&vlocation->timeout);
@@ -323,13 +336,13 @@
 	_debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
 	       vlocation->vldb.name,
 	       vlocation->vldb.vidmask,
-	       ntohl(vlocation->vldb.servers[0].s_addr),vlocation->vldb.srvtmask[0],
-	       ntohl(vlocation->vldb.servers[1].s_addr),vlocation->vldb.srvtmask[1],
-	       ntohl(vlocation->vldb.servers[2].s_addr),vlocation->vldb.srvtmask[2]
+	       ntohl(vlocation->vldb.servers[0].s_addr), vlocation->vldb.srvtmask[0],
+	       ntohl(vlocation->vldb.servers[1].s_addr), vlocation->vldb.srvtmask[1],
+	       ntohl(vlocation->vldb.servers[2].s_addr), vlocation->vldb.srvtmask[2]
 	       );
 
 	_debug("Vids: %08x %08x %08x",
-	       vlocation->vldb.vid[0],vlocation->vldb.vid[1],vlocation->vldb.vid[2]);
+	       vlocation->vldb.vid[0], vlocation->vldb.vid[1], vlocation->vldb.vid[2]);
 
 	if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) {
 		vid = vlocation->vldb.vid[0];
@@ -349,12 +362,12 @@
 		voltype = 0;
 	}
 
-	ret = afs_vlocation_access_vl_by_id(vlocation,vid,voltype,&vldb);
+	ret = afs_vlocation_access_vl_by_id(vlocation, vid, voltype, &vldb);
 	switch (ret) {
 		/* net error */
 	default:
-		printk("kAFS: failed to volume '%s' (%x) up in '%s': %d\n",
-		       name,vid,cell->name,ret);
+		printk("kAFS: failed to volume '%*.*s' (%x) up in '%s': %d\n",
+		       namesz, namesz, name, vid, cell->name, ret);
 		goto error;
 
 		/* pulled from local cache into memory */
@@ -363,27 +376,30 @@
 
 		/* uh oh... looks like the volume got deleted */
 	case -ENOMEDIUM:
-		printk("kAFS: volume '%s' (%x) does not exist '%s'\n",name,vid,cell->name);
+		printk("kAFS: volume '%*.*s' (%x) does not exist '%s'\n",
+		       namesz, namesz, name, vid, cell->name);
 
 		/* TODO: make existing record unavailable */
 		goto error;
 	}
 
  found_on_vlserver:
-	_debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
-	       name,
+	_debug("Done VL Lookup: %*.*s %02x { %08x(%x) %08x(%x) %08x(%x) }",
+	       namesz, namesz, name,
 	       vldb.vidmask,
-	       ntohl(vldb.servers[0].s_addr),vldb.srvtmask[0],
-	       ntohl(vldb.servers[1].s_addr),vldb.srvtmask[1],
-	       ntohl(vldb.servers[2].s_addr),vldb.srvtmask[2]
+	       ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
+	       ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
+	       ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
 	       );
 
-	_debug("Vids: %08x %08x %08x",vldb.vid[0],vldb.vid[1],vldb.vid[2]);
+	_debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]);
 
-	if (strncmp(vldb.name,name,sizeof(vlocation->vldb.name))!=0)
-		printk("kAFS: name of volume '%s' changed to '%s' on server\n",name,vldb.name);
+	if ((namesz < sizeof(vlocation->vldb.name) && vlocation->vldb.name[namesz] != '\0') ||
+	    memcmp(vldb.name, name, namesz) != 0)
+		printk("kAFS: name of volume '%*.*s' changed to '%s' on server\n",
+		       namesz, namesz, name, vldb.name);
 
-	memcpy(&vlocation->vldb,&vldb,sizeof(vlocation->vldb));
+	memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
 
 #if 0
 	/* add volume entry to local cache */
@@ -392,7 +408,7 @@
 		goto error;
 #endif
 
-	afs_kafstimod_add_timer(&vlocation->upd_timer,10*HZ);
+	afs_kafstimod_add_timer(&vlocation->upd_timer, 10*HZ);
 
 	*_vlocation = vlocation;
 	_leave(" = 0 (%p)",vlocation);
@@ -405,7 +421,7 @@
 		}
 		else {
 			list_del(&vlocation->link);
-			cachefs_relinquish_cookie(vlocation->cache,0);
+			cachefs_relinquish_cookie(vlocation->cache, 0);
 			afs_put_cell(vlocation->cell);
 			kfree(vlocation);
 		}
@@ -420,12 +436,17 @@
  * finish using a volume location record
  * - caller must have cell->vol_sem write-locked
  */
-void __afs_put_vlocation(afs_vlocation_t *vlocation)
+void __afs_put_vlocation(struct afs_vlocation *vlocation)
 {
-	afs_cell_t *cell = vlocation->cell;
+	struct afs_cell *cell;
+
+	if (!vlocation)
+		return;
 
 	_enter("%s",vlocation->vldb.name);
 
+	cell = vlocation->cell;
+
 	/* sanity check */
 	if (atomic_read(&vlocation->usage)<=0)
 		BUG();
@@ -459,11 +480,13 @@
  */
 void afs_put_vlocation(afs_vlocation_t *vlocation)
 {
-	afs_cell_t *cell = vlocation->cell;
+	if (vlocation) {
+		struct afs_cell *cell = vlocation->cell;
 
-	down_write(&cell->vl_sem);
-	__afs_put_vlocation(vlocation);
-	up_write(&cell->vl_sem);
+		down_write(&cell->vl_sem);
+		__afs_put_vlocation(vlocation);
+		up_write(&cell->vl_sem);
+	}
 } /* end afs_put_vlocation() */
 
 /*****************************************************************************/
@@ -575,10 +598,8 @@
 		printk("kAFS: Abandoning VL update '%s': %d\n",vlocation->vldb.name,ret);
 
 	/* discard the server record */
-	if (vlocation->upd_op.server) {
-		afs_put_server(vlocation->upd_op.server);
-		vlocation->upd_op.server = NULL;
-	}
+	afs_put_server(vlocation->upd_op.server);
+	vlocation->upd_op.server = NULL;
 
 	spin_lock(&afs_vlocation_update_lock);
 	afs_vlocation_update = NULL;
@@ -766,11 +787,9 @@
  try_next:
 	vlocation->upd_busy_cnt = 0;
 
-	if (vlocation->upd_op.server) {
-		/* discard the server record */
-		afs_put_server(vlocation->upd_op.server);
-		vlocation->upd_op.server = NULL;
-	}
+	/* discard the server record */
+	afs_put_server(vlocation->upd_op.server);
+	vlocation->upd_op.server = NULL;
 
 	tmp = vlocation->cell->vl_naddrs;
 	if (tmp==0)
@@ -832,20 +851,36 @@
  * match a VLDB record stored in the cache
  * - may also load target from entry
  */
-static cachefs_match_val_t afs_vlocation_cache_match(void *target, const void *entry)
+static cachefs_match_val_t afs_vlocation_cache_match(void *target,
+						     const void *entry)
 {
 	const struct afs_cache_vlocation *vldb = entry;
 	struct afs_vlocation *vlocation = target;
 
 	_enter("");
 
-	if (strncmp(vlocation->vldb.name,vldb->name,sizeof(vldb->name))==0) {
-		if (!vlocation->valid || vlocation->vldb.rtime == vldb->rtime) {
+	if (strncmp(vlocation->vldb.name,
+		    vldb->name,
+		    sizeof(vldb->name)) == 0) {
+		if (!vlocation->valid ||
+		    vlocation->vldb.rtime == vldb->rtime) {
 			struct_cpy(&vlocation->vldb,vldb);
 			vlocation->valid = 1;
+			return CACHEFS_MATCH_SUCCESS;
 		}
+		/* need to update cache if cached info differs */
+		else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) {
+			/* delete if VIDs for this name differ */
+			if (memcmp(&vlocation->vldb.vid,
+				   &vldb->vid,
+				   sizeof(vldb->vid)) != 0)
+				return CACHEFS_MATCH_SUCCESS_DELETE;
 
-		return CACHEFS_MATCH_SUCCESS;
+			return CACHEFS_MATCH_SUCCESS_UPDATE;
+		}
+		else {
+			return CACHEFS_MATCH_SUCCESS;
+		}
 	}
 
 	return CACHEFS_MATCH_FAILED;

Index: vlclient.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/vlclient.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- vlclient.h	6 Jun 2003 08:33:37 -0000	1.4
+++ vlclient.h	4 Jul 2003 15:26:31 -0000	1.5
@@ -77,6 +77,7 @@
 /* look up a volume location database entry by name */
 extern int afs_rxvl_get_entry_by_name(afs_server_t *server,
 				      const char *volname,
+				      unsigned volnamesz,
 				      struct afs_cache_vlocation *entry);
 
 /* look up a volume location database entry by ID */

Index: vlclient.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/vlclient.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- vlclient.c	6 Jun 2003 08:33:37 -0000	1.6
+++ vlclient.c	4 Jul 2003 15:26:31 -0000	1.7
@@ -176,7 +176,7 @@
 /*
  * look up a volume location database entry by name
  */
-int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
+int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname, unsigned volnamesz,
 			       struct afs_cache_vlocation *entry)
 {
 	DECLARE_WAITQUEUE(myself,current);
@@ -189,29 +189,29 @@
 	int ret, loop;
 	u32 *bp, param[2], zero;
 
-	_enter(",%s,",volname);
+	_enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);
 
-	memset(entry,0,sizeof(*entry));
+	memset(entry, 0, sizeof(*entry));
 
 	/* get hold of the vlserver connection */
-	ret = afs_server_get_vlconn(server,&conn);
+	ret = afs_server_get_vlconn(server, &conn);
 	if (ret<0)
 		goto out;
 
 	/* create a call through that connection */
-	ret = rxrpc_create_call(conn,NULL,NULL,afs_rxvl_aemap,&call);
-	if (ret<0) {
-		printk("kAFS: Unable to create call: %d\n",ret);
+	ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call);
+	if (ret < 0) {
+		printk("kAFS: Unable to create call: %d\n", ret);
 		goto out_put_conn;
 	}
 	call->app_opcode = VLGETENTRYBYNAME;
 
 	/* we want to get event notifications from the call */
-	add_wait_queue(&call->waitq,&myself);
+	add_wait_queue(&call->waitq, &myself);
 
 	/* marshall the parameters */
-	piov[1].iov_len = strlen(volname);
-	piov[1].iov_base = (char*)volname;
+	piov[1].iov_len = volnamesz;
+	piov[1].iov_base = (char*) volname;
 
 	zero = 0;
 	piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
@@ -224,16 +224,16 @@
 	piov[0].iov_base = param;
 
 	/* send the parameters to the server */
-	ret = rxrpc_call_write_data(call,3,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
+	ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 0, &sent);
 	if (ret<0)
 		goto abort;
 
 	/* wait for the reply to completely arrive */
-	bp = rxrpc_call_alloc_scratch(call,384);
+	bp = rxrpc_call_alloc_scratch(call, 384);
 
-	ret = rxrpc_call_read_data(call,bp,384,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
-	if (ret<0) {
-		if (ret==-ECONNABORTED) {
+	ret = rxrpc_call_read_data(call, bp, 384, RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
+	if (ret < 0) {
+		if (ret == -ECONNABORTED) {
 			ret = call->app_errno;
 			goto out_unwait;
 		}
@@ -281,12 +281,12 @@
 
  out_unwait:
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&call->waitq,&myself);
+	remove_wait_queue(&call->waitq, &myself);
 	rxrpc_put_call(call);
  out_put_conn:
 	rxrpc_put_connection(conn);
  out:
-	_leave(" = %d",ret);
+	_leave(" = %d", ret);
 	return ret;
 
  abort:

Index: super.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/super.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- super.h	14 Oct 2002 12:06:58 -0000	1.2
+++ super.h	4 Jul 2003 15:26:31 -0000	1.3
@@ -29,7 +29,7 @@
  */
 struct afs_super_info
 {
-	afs_volume_t		*volume;	/* volume record */
+	struct afs_volume	*volume;	/* volume record */
 	char			rwparent;	/* T if parent is R/W AFS volume */
 };

Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/super.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- super.c	16 Oct 2002 12:45:03 -0000	1.8
+++ super.c	4 Jul 2003 15:26:31 -0000	1.9
@@ -29,18 +29,26 @@
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
 
+struct afs_mount_params {
+	int			rwpath;
+	struct afs_cell		*default_cell;
+	struct afs_volume	*volume;
+};
+
 static inline char *strdup(const char *s)
 {
-	char *ns = kmalloc(strlen(s)+1,GFP_KERNEL);
+	char *ns = kmalloc(strlen(s) + 1, GFP_KERNEL);
 	if (ns)
-		strcpy(ns,s);
+		strcpy(ns, s);
 	return ns;
 }
 
-static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags);
+static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
+			    unsigned long flags);
 
 static struct super_block *afs_get_sb(struct file_system_type *fs_type,
-				      int flags, char *dev_name, void *data);
+				      int flags, const char *dev_name,
+				      void *data);
 
 static struct inode *afs_alloc_inode(struct super_block *sb);
 
@@ -65,6 +73,7 @@
 };
 
 static kmem_cache_t *afs_inode_cachep;
+static atomic_t afs_count_active_inodes;
 
 /*****************************************************************************/
 /*
@@ -76,14 +85,18 @@
 
 	kenter("");
 
+	afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops);
+
 	/* create ourselves an inode cache */
+	atomic_set(&afs_count_active_inodes, 0);
+
 	ret = -ENOMEM;
 	afs_inode_cachep = kmem_cache_create("afs_inode_cache",
-						sizeof(afs_vnode_t),
-						0,
-						SLAB_HWCACHE_ALIGN,
-						afs_i_init_once,
-						NULL);
+					     sizeof(afs_vnode_t),
+					     0,
+					     SLAB_HWCACHE_ALIGN,
+					     afs_i_init_once,
+					     NULL);
 	if (!afs_inode_cachep) {
 		printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n");
 		return ret;
@@ -91,9 +104,9 @@
 
 	/* now export our filesystem to lesser mortals */
 	ret = register_filesystem(&afs_fs_type);
-	if (ret<0) {
+	if (ret < 0) {
 		kmem_cache_destroy(afs_inode_cachep);
-		kleave(" = %d",ret);
+		kleave(" = %d", ret);
 		return ret;
 	}
 
@@ -107,11 +120,16 @@
  */
 void __exit afs_fs_exit(void)
 {
-	/* destroy our private inode cache */
-	kmem_cache_destroy(afs_inode_cachep);
-
 	unregister_filesystem(&afs_fs_type);
 
+	if (atomic_read(&afs_count_active_inodes) != 0) {
+		printk("kAFS: %d active inode objects still present\n",
+		       atomic_read(&afs_count_active_inodes));
+		BUG();
+	}
+
+	kmem_cache_destroy(afs_inode_cachep);
+
 } /* end afs_fs_exit() */
 
 /*****************************************************************************/
@@ -121,7 +139,7 @@
 static int want_arg(char **_value, const char *option)
 {
 	if (!_value || !*_value || !**_value) {
-		printk(KERN_NOTICE "kAFS: %s: argument missing\n",option);
+		printk(KERN_NOTICE "kAFS: %s: argument missing\n", option);
 		return 0;
 	}
 	return 1;
@@ -129,27 +147,13 @@
 
 /*****************************************************************************/
 /*
- * check that there is a value
- */
-#if 0
-static int want_value(char **_value, const char *option)
-{
-	if (!_value || !*_value || !**_value) {
-		printk(KERN_NOTICE "kAFS: %s: argument incomplete\n",option);
-		return 0;
-	}
-	return 1;
-} /* end want_value() */
-#endif
-
-/*****************************************************************************/
-/*
  * check that there's no subsequent value
  */
 static int want_no_value(char *const *_value, const char *option)
 {
 	if (*_value && **_value) {
-		printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",option,*_value);
+		printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",
+		       option, *_value);
 		return 0;
 	}
 	return 1;
@@ -157,150 +161,55 @@
 
 /*****************************************************************************/
 /*
- * extract a number from an option string value
- */
-#if 0
-static int want_number(char **_value, const char *option, unsigned long *number,
-		       unsigned long limit)
-{
-	char *value = *_value;
-
-	if (!want_value(_value,option))
-		return 0;
-
-	*number = simple_strtoul(value,_value,0);
-
-	if (value==*_value) {
-		printk(KERN_NOTICE "kAFS: %s: Invalid number: %s\n",option,value);
-		return 0;
-	}
-
-	if (*number>limit) {
-		printk(KERN_NOTICE "kAFS: %s: numeric value %lu > %lu\n",option,*number,limit);
-		return 0;
-	}
-
-	return 1;
-} /* end want_number() */
-#endif
-
-/*****************************************************************************/
-/*
- * extract a separator from an option string value
- */
-#if 0
-static int want_sep(char **_value, const char *option, char sep)
-{
-	if (!want_value(_value,option))
-		return 0;
-
-	if (*(*_value)++ != sep) {
-		printk(KERN_NOTICE "kAFS: %s: '%c' expected: %s\n",option,sep,*_value-1);
-		return 0;
-	}
-
-	return 1;
-} /* end want_number() */
-#endif
-
-/*****************************************************************************/
-/*
- * extract an IP address from an option string value
- */
-#if 0
-static int want_ipaddr(char **_value, const char *option, struct in_addr *addr)
-{
-	unsigned long number[4];
-
-	if (!want_value(_value,option))
-		return 0;
-
-	if (!want_number(_value,option,&number[0],255) ||
-	    !want_sep(_value,option,'.') ||
-	    !want_number(_value,option,&number[1],255) ||
-	    !want_sep(_value,option,'.') ||
-	    !want_number(_value,option,&number[2],255) ||
-	    !want_sep(_value,option,'.') ||
-	    !want_number(_value,option,&number[3],255))
-		return 0;
-
-	((u8*)addr)[0] = number[0];
-	((u8*)addr)[1] = number[1];
-	((u8*)addr)[2] = number[2];
-	((u8*)addr)[3] = number[3];
-
-	return 1;
-} /* end want_numeric() */
-#endif
-
-/*****************************************************************************/
-/*
  * parse the mount options
  * - this function has been shamelessly adapted from the ext3 fs which shamelessly adapted it from
  *   the msdos fs
  */
-static int afs_super_parse_options(struct afs_super_info *as, char *options, char **devname)
+static int afs_super_parse_options(struct afs_mount_params *params,
+				   char *options,
+				   const char **devname)
 {
 	char *key, *value;
 	int ret;
 
-	_enter("%s",options);
+	_enter("%s", options);
+
+	options[PAGE_SIZE - 1] = 0;
 
 	ret = 0;
-	while ((key = strsep(&options,",")))
+	while ((key = strsep(&options, ",")))
 	{
-		value = strchr(key,'=');
+		value = strchr(key, '=');
 		if (value)
 			*value++ = 0;
 
-		printk("kAFS: KEY: %s, VAL:%s\n",key,value?:"-");
+		printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-");
 
-		if (strcmp(key,"rwpath")==0) {
-			if (!want_no_value(&value,"rwpath")) return -EINVAL;
-			as->rwparent = 1;
+		if (strcmp(key, "rwpath") == 0) {
+			if (!want_no_value(&value, "rwpath"))
+				return -EINVAL;
+			params->rwpath = 1;
 			continue;
 		}
-		else if (strcmp(key,"vol")==0) {
-			if (!want_arg(&value,"vol")) return -EINVAL;
+		else if (strcmp(key, "vol") == 0) {
+			if (!want_arg(&value, "vol"))
+				return -EINVAL;
 			*devname = value;
 			continue;
 		}
-
-#if 0
-		if (strcmp(key,"servers")==0) {
-			if (!want_arg(&value,"servers")) return -EINVAL;
-
-			_debug("servers=%s",value);
-
-			for (;;) {
-				struct in_addr addr;
-
-				if (!want_ipaddr(&value,"servers",&addr))
-					return -EINVAL;
-
-				ret = afs_create_server(as->cell,&addr,&as->server);
-				if (ret<0) {
-					printk("kAFS: unable to create server: %d\n",ret);
-					return ret;
-				}
-
-				if (!*value)
-					break;
-
-				if (as->server) {
-					printk(KERN_NOTICE
-					       "kAFS: only one server can be specified\n");
-					return -EINVAL;
-				}
-
-				if (!want_sep(&value,"servers",':'))
-					return -EINVAL;
-			}
+		else if (strcmp(key, "cell") == 0) {
+			if (!want_arg(&value, "cell"))
+				return -EINVAL;
+			afs_put_cell(params->default_cell);
+			ret = afs_cell_lookup(value,
+					      strlen(value),
+					      &params->default_cell);
+			if (ret < 0)
+				return -EINVAL;
 			continue;
 		}
-#endif
 
-		printk("kAFS: Unknown mount option: '%s'\n",key);
+		printk("kAFS: Unknown mount option: '%s'\n",  key);
 		ret = -EINVAL;
 		goto error;
 	}
@@ -308,61 +217,48 @@
 	ret = 0;
 
  error:
-	_leave(" = %d",ret);
-
+	_leave(" = %d", ret);
 	return ret;
 } /* end afs_super_parse_options() */
 
 /*****************************************************************************/
 /*
+ * check a superblock to see if it's the one we're looking for
+ */
+static int afs_test_super(struct super_block *sb, void *data)
+{
+	struct afs_mount_params *params = data;
+	struct afs_super_info *as = sb->s_fs_info;
+
+	return as->volume == params->volume;
+} /* end afs_test_super() */
+
+/*****************************************************************************/
+/*
  * fill in the superblock
  */
-static int afs_fill_super(struct super_block *sb, void *_data, int silent)
+static int afs_fill_super(struct super_block *sb, void *data, int silent)
 {
+	struct afs_mount_params *params = data;
 	struct afs_super_info *as = NULL;
 	struct dentry *root = NULL;
 	struct inode *inode = NULL;
 	afs_fid_t fid;
-	void **data = _data;
-	char *options, *devname;
 	int ret;
 
-	_enter("");
-
-	if (!data) {
-		_leave(" = -EINVAL");
-		return -EINVAL;
-	}
-	devname = data[0];
-	options = data[1];
-	if (options)
-		options[PAGE_SIZE-1] = 0;
+	kenter("");
 
 	/* allocate a superblock info record */
-	as = kmalloc(sizeof(struct afs_super_info),GFP_KERNEL);
+	as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL);
 	if (!as) {
 		_leave(" = -ENOMEM");
 		return -ENOMEM;
 	}
 
-	memset(as,0,sizeof(struct afs_super_info));
-
-	/* parse the options */
-	if (options) {
-		ret = afs_super_parse_options(as,options,&devname);
-		if (ret<0)
-			goto error;
-		if (!devname) {
-			printk("kAFS: no volume name specified\n");
-			ret = -EINVAL;
-			goto error;
-		}
-	}
+	memset(as, 0, sizeof(struct afs_super_info));
 
-	/* parse the device name */
-	ret = afs_volume_lookup(devname,as->rwparent,&as->volume);
-	if (ret<0)
-		goto error;
+	afs_get_volume(params->volume);
+	as->volume = params->volume;
 
 	/* fill in the superblock */
 	sb->s_blocksize		= PAGE_CACHE_SIZE;
@@ -375,8 +271,8 @@
 	fid.vid		= as->volume->vid;
 	fid.vnode	= 1;
 	fid.unique	= 1;
-	ret = afs_iget(sb,&fid,&inode);
-	if (ret<0)
+	ret = afs_iget(sb, &fid, &inode);
+	if (ret < 0)
 		goto error;
 
 	ret = -ENOMEM;
@@ -386,19 +282,18 @@
 
 	sb->s_root = root;
 
-	_leave(" = 0");
+	kleave(" = 0");
 	return 0;
 
  error:
-	if (root) dput(root);
-	if (inode) iput(inode);
-	if (as) {
-		if (as->volume)		afs_put_volume(as->volume);
-		kfree(as);
-	}
+	dput(root);
+	iput(inode);
+	afs_put_volume(as->volume);
+	kfree(as);
+
 	sb->s_fs_info = NULL;
 
-	_leave(" = %d",ret);
+	kleave(" = %d", ret);
 	return ret;
 } /* end afs_fill_super() */
 
@@ -409,31 +304,78 @@
  */
 static struct super_block *afs_get_sb(struct file_system_type *fs_type,
 				      int flags,
-				      char *dev_name,
+				      const char *dev_name,
 				      void *options)
 {
+	struct afs_mount_params params;
 	struct super_block *sb;
-	void *data[2] = { dev_name, options };
 	int ret;
 
-	_enter(",,%s,%p",dev_name,options);
+	kenter(",,%s,%p", dev_name, options);
+
+	memset(&params, 0, sizeof(params));
 
 	/* start the cache manager */
 	ret = afscm_start();
-	if (ret<0) {
-		_leave(" = %d",ret);
+	if (ret < 0) {
+		kleave(" = %d", ret);
 		return ERR_PTR(ret);
 	}
 
+	/* parse the options */
+	if (options) {
+		ret = afs_super_parse_options(&params, options, &dev_name);
+		if (ret < 0)
+			goto error;
+		if (!dev_name) {
+			printk("kAFS: no volume name specified\n");
+			ret = -EINVAL;
+			goto error;
+		}
+	}
+
+	/* parse the device name */
+	ret = afs_volume_lookup(dev_name,
+				params.default_cell,
+				params.rwpath,
+				&params.volume);
+	if (ret < 0)
+		goto error;
+
 	/* allocate a deviceless superblock */
-	sb = get_sb_nodev(fs_type,flags,data,afs_fill_super);
-	if (IS_ERR(sb)) {
+#if 0
+	sb = get_sb_nodev(fs_type, flags, &params, afs_fill_super);
+	if (IS_ERR(sb))
 		afscm_stop();
-		return sb;
+
+#else
+	sb = sget(fs_type, afs_test_super, set_anon_super, &params);
+	if (IS_ERR(sb))
+		goto error;
+
+	sb->s_flags = flags;
+
+	ret = afs_fill_super(sb, &params, flags & MS_VERBOSE ? 1 : 0);
+	if (ret < 0) {
+		up_write(&sb->s_umount);
+		deactivate_super(sb);
+		goto error;
 	}
+	sb->s_flags |= MS_ACTIVE;
 
-	_leave("");
+#endif
+
+	afs_put_volume(params.volume);
+	afs_put_cell(params.default_cell);
+	kleave(" = %p", sb);
 	return sb;
+
+ error:
+	afs_put_volume(params.volume);
+	afs_put_cell(params.default_cell);
+	afscm_stop();
+	kleave(" = %d", ret);
+	return ERR_PTR(ret);
 } /* end afs_get_sb() */
 
 /*****************************************************************************/
@@ -446,11 +388,7 @@
 
 	_enter("");
 
-	if (as) {
-		if (as->volume)		afs_put_volume(as->volume);
-	}
-
-	/* stop the cache manager */
+	afs_put_volume(as->volume);
 	afscm_stop();
 
 	_leave("");
@@ -460,18 +398,21 @@
 /*
  * initialise an inode cache slab element prior to any use
  */
-static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, unsigned long flags)
+static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep,
+			    unsigned long flags)
 {
 	afs_vnode_t *vnode = (afs_vnode_t *) _vnode;
 
-	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) {
-		memset(vnode,0,sizeof(*vnode));
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		memset(vnode, 0, sizeof(*vnode));
 		inode_init_once(&vnode->vfs_inode);
 		init_waitqueue_head(&vnode->update_waitq);
 		spin_lock_init(&vnode->lock);
 		INIT_LIST_HEAD(&vnode->cb_link);
 		INIT_LIST_HEAD(&vnode->cb_hash_link);
-		afs_timer_init(&vnode->cb_timeout,&afs_vnode_cb_timed_out_ops);
+		afs_timer_init(&vnode->cb_timeout,
+			       &afs_vnode_cb_timed_out_ops);
 	}
 
 } /* end afs_i_init_once() */
@@ -484,16 +425,19 @@
 {
 	afs_vnode_t *vnode;
 
-	vnode = (afs_vnode_t *) kmem_cache_alloc(afs_inode_cachep,SLAB_KERNEL);
+	vnode = (afs_vnode_t *)
+		kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
 	if (!vnode)
 		return NULL;
 
-	memset(&vnode->fid,0,sizeof(vnode->fid));
-	memset(&vnode->status,0,sizeof(vnode->status));
+	atomic_inc(&afs_count_active_inodes);
 
-	vnode->volume = NULL;
-	vnode->update_cnt = 0;
-	vnode->flags = 0;
+	memset(&vnode->fid, 0, sizeof(vnode->fid));
+	memset(&vnode->status, 0, sizeof(vnode->status));
+
+	vnode->volume		= NULL;
+	vnode->update_cnt	= 0;
+	vnode->flags		= 0;
 
 	return &vnode->vfs_inode;
 } /* end afs_alloc_inode() */
@@ -504,6 +448,10 @@
  */
 static void afs_destroy_inode(struct inode *inode)
 {
-	_enter("{%lu}",inode->i_ino);
+	_enter("{%lu}", inode->i_ino);
+
 	kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
+
+	atomic_dec(&afs_count_active_inodes);
+
 } /* end afs_destroy_inode() */

Index: server.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/server.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- server.c	16 Oct 2002 09:59:50 -0000	1.3
+++ server.c	4 Jul 2003 15:26:31 -0000	1.4
@@ -148,6 +148,9 @@
 {
 	afs_cell_t *cell;
 
+	if (!server)
+		return;
+
 	_enter("%p",server);
 
 	cell = server->cell;

Index: mntpt.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/mntpt.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- mntpt.c	16 Oct 2002 12:45:03 -0000	1.6
+++ mntpt.c	4 Jul 2003 15:26:31 -0000	1.7
@@ -16,13 +16,20 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/namespace.h>
+#include "super.h"
+#include "cell.h"
 #include "volume.h"
 #include "vnode.h"
+#define __KDEBUG
 #include "internal.h"

 static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
+static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);
 
 struct file_operations afs_mntpt_file_operations = {
 	.open		= afs_mntpt_open,
@@ -30,10 +37,23 @@
 
 struct inode_operations afs_mntpt_inode_operations = {
 	.lookup		= afs_mntpt_lookup,
+	.follow_link	= afs_mntpt_follow_link,
 	.readlink	= page_readlink,
 	.getattr	= afs_inode_getattr,
 };
 
+static LIST_HEAD(afs_vfsmounts);
+
+static void afs_mntpt_expiry_timed_out(struct afs_timer *timer);
+
+struct afs_timer_ops afs_mntpt_expiry_timer_ops = {
+	.timed_out	= afs_mntpt_expiry_timed_out,
+};
+
+struct afs_timer afs_mntpt_expiry_timer;
+
+unsigned long afs_mntpt_expiry_timeout = 20;
+
 /*****************************************************************************/
 /*
  * check a symbolic link to see whether it actually encodes a mountpoint
@@ -95,6 +115,13 @@
  */
 static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry)
 {
+	kenter("%p,%p{%p{%s},%s}",
+	       dir,
+	       dentry,
+	       dentry->d_parent,
+	       dentry->d_parent ? dentry->d_parent->d_name.name : (const unsigned char*)"",
+	       dentry->d_name.name);
+
 	return ERR_PTR(-EREMOTE);
 } /* end afs_mntpt_lookup() */
 
@@ -104,5 +131,144 @@
  */
 static int afs_mntpt_open(struct inode *inode, struct file *file)
 {
+	kenter("%p,%p{%p{%s},%s}",
+	       inode, file,
+	       file->f_dentry->d_parent,
+	       file->f_dentry->d_parent ? file->f_dentry->d_parent->d_name.name : (const unsigned char*)"",
+	       file->f_dentry->d_name.name);
+
 	return -EREMOTE;
 } /* end afs_mntpt_open() */
+
+/*****************************************************************************/
+/*
+ * create a vfsmount to be automounted
+ */
+static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
+{
+	struct afs_super_info *super;
+	struct vfsmount *mnt;
+	struct page *page = NULL;
+	size_t size;
+	char *buf, *devname = NULL, *options = NULL;
+	int ret;
+
+	kenter("{%s}", mntpt->d_name.name);
+
+	BUG_ON(!mntpt->d_inode);
+
+	ret = -EINVAL;
+	size = mntpt->d_inode->i_size;
+	if (size > PAGE_SIZE - 1)
+		goto error;
+
+	ret = -ENOMEM;
+	devname = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!devname)
+		goto error;
+
+	options = (char *) get_zeroed_page(GFP_KERNEL);
+	if (!options)
+		goto error;
+
+	/* read the contents of the AFS special symlink */
+	page = read_cache_page(mntpt->d_inode->i_mapping,
+			       0,
+			       (filler_t*)mntpt->d_inode->i_mapping->a_ops->readpage,
+			       NULL);
+	if (IS_ERR(page)) {
+		ret = PTR_ERR(page);
+		goto error;
+	}
+
+	ret = -EIO;
+	wait_on_page_locked(page);
+	if (!PageUptodate(page) || PageError(page))
+		goto error;
+
+	buf = kmap(page);
+	memcpy(devname, buf, size);
+	kunmap(page);
+	page_cache_release(page);
+	page = NULL;
+
+	/* work out what options we want */
+	super = AFS_FS_S(mntpt->d_sb);
+	memcpy(options, "cell=", 5);
+	strcpy(options + 5, super->volume->cell->name);
+	if (super->volume->type == AFSVL_RWVOL)
+		strcat(options,",rwpath");
+
+	/* try and do the mount */
+	kdebug("--- attempting mount %s -o %s ---", devname, options);
+	mnt = do_kern_mount("afs", 0, devname, options);
+	kdebug("--- mount result %p ---", mnt);
+
+	free_page((unsigned long)devname);
+	free_page((unsigned long)options);
+	kleave(" = %p",mnt);
+	return mnt;
+
+ error:
+	if (page)
+		page_cache_release(page);
+	if (devname)
+		free_page((unsigned long)devname);
+	if (options)
+		free_page((unsigned long)options);
+	kleave(" = %d",ret);
+	return ERR_PTR(ret);
+} /* end afs_mntpt_do_automount() */
+
+/*****************************************************************************/
+/*
+ * follow a link from a mountpoint directory, thus causing it to be mounted
+ */
+static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct nameidata newnd;
+	struct vfsmount *newmnt;
+	int err;
+
+	kenter("%p{%s},{%s:%p{%s}}",
+	       dentry,
+	       dentry->d_name.name,
+	       nd->mnt->mnt_devname,
+	       dentry,
+	       nd->dentry->d_name.name);
+
+	newmnt = afs_mntpt_do_automount(dentry);
+	if (IS_ERR(newmnt))
+		return PTR_ERR(newmnt);
+
+	struct_cpy(&newnd,nd);
+	newnd.dentry = dentry;
+	err = do_add_mount(newmnt, &newnd, 0, &afs_vfsmounts);
+
+	if (!err) {
+		path_release(nd);
+		mntget(newmnt);
+		nd->mnt = newmnt;
+		dget(newmnt->mnt_root);
+		nd->dentry = newmnt->mnt_root;
+	}
+
+	kleave(" = %d", err);
+	return err;
+} /* end afs_mntpt_follow_link() */
+
+/*****************************************************************************/
+/*
+ * handle mountpoint expiry timer going off
+ */
+static void afs_mntpt_expiry_timed_out(struct afs_timer *timer)
+{
+	kenter("");
+
+	mark_mounts_for_expiry(&afs_vfsmounts);
+
+	afs_kafstimod_add_timer(&afs_mntpt_expiry_timer,
+				afs_mntpt_expiry_timeout * HZ);
+
+	kleave("");
+} /* end afs_mntpt_expiry_timed_out() */

Index: main.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/main.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- main.c	6 Jun 2003 08:33:37 -0000	1.11
+++ main.c	4 Jul 2003 15:26:31 -0000	1.12
@@ -210,3 +210,48 @@
 	_leave("");
 
 } /* end afs_discarding_peer() */
+
+/*****************************************************************************/
+/*
+ * clear the dead space between task_struct and kernel stack
+ * - called by supplying -finstrument-functions to gcc
+ */
+#if 1
+void __cyg_profile_func_enter (void *this_fn, void *call_site)
+__attribute__((no_instrument_function));
+
+void __cyg_profile_func_enter (void *this_fn, void *call_site)
+{
+       asm volatile("  movl    %%esp,%%edi     \n"
+                    "  andl    %0,%%edi        \n"
+                    "  addl    %1,%%edi        \n"
+                    "  movl    %%esp,%%ecx     \n"
+                    "  subl    %%edi,%%ecx     \n"
+                    "  shrl    $2,%%ecx        \n"
+                    "  movl    $0xedededed,%%eax     \n"
+                    "  rep stosl               \n"
+                    :
+                    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
+                    : "eax", "ecx", "edi", "memory", "cc"
+                    );
+}
+
+void __cyg_profile_func_exit(void *this_fn, void *call_site)
+__attribute__((no_instrument_function));
+
+void __cyg_profile_func_exit(void *this_fn, void *call_site)
+{
+       asm volatile("  movl    %%esp,%%edi     \n"
+                    "  andl    %0,%%edi        \n"
+                    "  addl    %1,%%edi        \n"
+                    "  movl    %%esp,%%ecx     \n"
+                    "  subl    %%edi,%%ecx     \n"
+                    "  shrl    $2,%%ecx        \n"
+                    "  movl    $0xdadadada,%%eax     \n"
+                    "  rep stosl               \n"
+                    :
+                    : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info))
+                    : "eax", "ecx", "edi", "memory", "cc"
+                    );
+}
+#endif

Index: kafstimod.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/kafstimod.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- kafstimod.c	9 Apr 2003 15:43:07 -0000	1.6
+++ kafstimod.c	4 Jul 2003 15:26:31 -0000	1.7
@@ -177,7 +177,7 @@
 	wake_up(&kafstimod_sleepq);
 
 	_leave("");
-} /* end afs_kafstimod_queue_vlocation() */
+} /* end afs_kafstimod_add_timer() */
 
 /*****************************************************************************/
 /*

Index: internal.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/internal.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- internal.h	6 Jun 2003 08:33:37 -0000	1.14
+++ internal.h	4 Jul 2003 15:26:31 -0000	1.15
@@ -28,7 +28,7 @@
 #define kproto(FMT, a...)	printk("### "FMT"\n" , ## a)
 #define knet(FMT, a...)		printk(FMT"\n" , ## a)
 
-#if 0
+#ifdef __KDEBUG
 #define _enter(FMT, a...)	kenter(FMT , ## a)
 #define _leave(FMT, a...)	kleave(FMT , ## a)
 #define _debug(FMT, a...)	kdebug(FMT , ## a)
@@ -92,8 +92,11 @@
  */
 extern struct inode_operations afs_mntpt_inode_operations;
 extern struct file_operations afs_mntpt_file_operations;
+extern struct afs_timer afs_mntpt_expiry_timer;
+extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
 
 extern int afs_mntpt_check_symlink(afs_vnode_t *vnode);
+extern unsigned long afs_mntpt_expiry_timeout;
 
 /*
  * super.c

Index: inode.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/inode.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- inode.c	9 Jun 2003 13:39:13 -0000	1.10
+++ inode.c	4 Jul 2003 15:26:31 -0000	1.11
@@ -79,7 +79,7 @@
 	inode->i_mapping->a_ops	= &afs_fs_aops;
 
 	/* check to see whether a symbolic link is really a mountpoint */
-	if (vnode->status.type==AFS_FTYPE_SYMLINK) {
+	if (vnode->status.type == AFS_FTYPE_SYMLINK) {
 		afs_mntpt_check_symlink(vnode);
 
 		if (vnode->flags & AFS_VNODE_MOUNTPOINT) {
@@ -105,7 +105,7 @@
 
 	ret = afs_vnode_fetch_status(vnode);
 
-	if (ret==0)
+	if (ret == 0)
 		ret = afs_inode_map_status(vnode);
 
 	return ret;
@@ -120,8 +120,8 @@
 {
 	struct afs_iget_data *data = opaque;
 
-	/* only match inodes with the same version number */
-	return inode->i_ino==data->fid.vnode && inode->i_version==data->fid.unique;
+	return inode->i_ino == data->fid.vnode &&
+		inode->i_version == data->fid.unique;
 } /* end afs_iget5_test() */
 
 /*****************************************************************************/
@@ -145,7 +145,8 @@
 /*
  * inode retrieval
  */
-inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inode)
+inline int afs_iget(struct super_block *sb, afs_fid_t *fid,
+		    struct inode **_inode)
 {
 	struct afs_iget_data data = { fid: *fid };
 	struct afs_super_info *as;
@@ -153,12 +154,13 @@
 	struct inode *inode;
 	int ret;
 
-	_enter(",{%u,%u,%u},,",fid->vid,fid->vnode,fid->unique);
+	_enter(",{%u,%u,%u},,", fid->vid, fid->vnode, fid->unique);
 
 	as = sb->s_fs_info;
 	data.volume = as->volume;
 
-	inode = iget5_locked(sb,fid->vnode,afs_iget5_test,afs_iget5_set,&data);
+	inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set,
+			     &data);
 	if (!inode) {
 		_leave(" = -ENOMEM");
 		return -ENOMEM;
@@ -173,7 +175,7 @@
 			*_inode = inode;
 		else
 			iput(inode);
-		_leave(" = %d",ret);
+		_leave(" = %d", ret);
 		return ret;
 	}
 
@@ -208,7 +210,7 @@
 	unlock_new_inode(inode);
 	iput(inode);
 
-	_leave(" = %d [bad]",ret);
+	_leave(" = %d [bad]", ret);
 	return ret;
 } /* end afs_iget() */
 
@@ -216,7 +218,8 @@
 /*
  * read the attributes of an inode
  */
-int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
+		      struct kstat *stat)
 {
 	struct inode *inode;
 	afs_vnode_t *vnode;
@@ -224,23 +227,25 @@
 
 	inode = dentry->d_inode;
 
-	_enter("{ ino=%lu v=%lu }",inode->i_ino,inode->i_version);
+	_enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version);
 
 	vnode = AFS_FS_I(inode);
 
 	ret = afs_inode_fetch_status(inode);
-	if (ret==-ENOENT) {
-		_leave(" = %d [%d %p]",ret,atomic_read(&dentry->d_count),dentry->d_inode);
+	if (ret == -ENOENT) {
+		_leave(" = %d [%d %p]",
+		       ret, atomic_read(&dentry->d_count), dentry->d_inode);
 		return ret;
 	}
-	else if (ret<0) {
+	else if (ret < 0) {
 		make_bad_inode(inode);
-		_leave(" = %d",ret);
+		_leave(" = %d", ret);
 		return ret;
 	}
 
-	/* transfer attributes from the inode structure to the stat structure */
-	generic_fillattr(inode,stat);
+	/* transfer attributes from the inode structure to the stat
+	 * structure */
+	generic_fillattr(inode, stat);
 
 	_leave(" = 0 CB { v=%u x=%u t=%u }",
 	       vnode->cb_version,
@@ -268,11 +273,11 @@
 	       vnode->cb_type
 	       );
 
-	if (inode->i_ino!=vnode->fid.vnode) BUG();
+	BUG_ON(inode->i_ino != vnode->fid.vnode);
 
 	afs_vnode_give_up_callback(vnode);
 
-	cachefs_relinquish_cookie(vnode->cache,0);
+	cachefs_relinquish_cookie(vnode->cache, 0);
 	vnode->cache = NULL;
 
 	_leave("");

Index: file.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/file.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- file.c	10 Jun 2003 17:49:49 -0000	1.7
+++ file.c	4 Jul 2003 15:26:31 -0000	1.8
@@ -230,8 +230,13 @@
 		 * The get_block cached value has been unconditionally invalidated,
 		 * so real IO is not possible anymore.
 		 */
-		if (offset == 0)
-			ret = try_to_release_page(page,0);
+		if (offset == 0) {
+			BUG_ON(!PageLocked(page));
+
+			ret = 0;
+			if (!PageWriteback(page))
+				ret = page->mapping->a_ops->releasepage(page, 0);
+		}
 	}
 
 	_leave(" = %d",ret);

Index: dir.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/dir.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- dir.c	9 Apr 2003 15:43:07 -0000	1.9
+++ dir.c	4 Jul 2003 15:26:31 -0000	1.10
@@ -423,11 +423,11 @@
 	unsigned fpos;
 	int ret;
 
-	_enter("{%lu},{%s}",dir->i_ino,dentry->d_name.name);
+	_enter("{%lu},%p{%s}",dir->i_ino,dentry,dentry->d_name.name);
 
 	/* insanity checks first */
-	if (sizeof(afs_dir_block_t) != 2048) BUG();
-	if (sizeof(afs_dirent_t) != 32) BUG();
+	BUG_ON(sizeof(afs_dir_block_t) != 2048);
+	BUG_ON(sizeof(afs_dirent_t) != 32);
 
 	if (dentry->d_name.len > 255) {
 		_leave(" = -ENAMETOOLONG");
@@ -495,7 +495,7 @@
 	unsigned fpos;
 	int ret;
 
-	_enter("%s,%x",dentry->d_name.name,flags);
+	_enter("{sb=%p n=%s},%x",dentry->d_sb,dentry->d_name.name,flags);
 
 	/* lock down the parent dentry so we can peer at it */
 	parent = dget_parent(dentry->d_parent);

Index: cmservice.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/cmservice.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- cmservice.c	2 Mar 2003 18:56:15 -0000	1.6
+++ cmservice.c	4 Jul 2003 15:26:31 -0000	1.7
@@ -301,15 +301,18 @@
 
 	down_write(&afscm_sem);
 	if (!afscm_usage) {
-		ret = kernel_thread(kafscmd,NULL,0);
-		if (ret<0)
+		ret = kernel_thread(kafscmd, NULL, 0);
+		if (ret < 0)
 			goto out;
 
 		wait_for_completion(&kafscmd_alive);
 
-		ret = rxrpc_add_service(afs_transport,&AFSCM_service);
+		ret = rxrpc_add_service(afs_transport, &AFSCM_service);
 		if (ret<0)
 			goto kill;
+
+		afs_kafstimod_add_timer(&afs_mntpt_expiry_timer,
+					afs_mntpt_expiry_timeout * HZ);
 	}
 
 	afscm_usage++;
@@ -338,17 +341,20 @@
 
 	down_write(&afscm_sem);
 
-	if (afscm_usage==0) BUG();
+	if (afscm_usage == 0) BUG();
 	afscm_usage--;
 
-	if (afscm_usage==0) {
+	if (afscm_usage == 0) {
 		/* don't want more incoming calls */
-		rxrpc_del_service(afs_transport,&AFSCM_service);
+		rxrpc_del_service(afs_transport, &AFSCM_service);
 
 		/* abort any calls I've still got open (the afscm_error() will dequeue them) */
 		spin_lock(&afscm_calls_lock);
 		while (!list_empty(&afscm_calls)) {
-			call = list_entry(afscm_calls.next,struct rxrpc_call,app_link);
+			call = list_entry(afscm_calls.next,
+					  struct rxrpc_call,
+					  app_link);
+
 			list_del_init(&call->app_link);
 			rxrpc_get_call(call);
 			spin_unlock(&afscm_calls_lock);
@@ -356,7 +362,8 @@
 			rxrpc_call_abort(call,-ESRCH); /* abort, dequeue and put */
 
 			_debug("nuking active call %08x.%d",
-			       ntohl(call->conn->conn_id),ntohl(call->call_id));
+			       ntohl(call->conn->conn_id),
+			       ntohl(call->call_id));
 			rxrpc_put_call(call);
 			rxrpc_put_call(call);
 
@@ -384,6 +391,8 @@
 			spin_lock(&kafscmd_attention_lock);
 		}
 		spin_unlock(&kafscmd_attention_lock);
+
+		afs_kafstimod_del_timer(&afs_mntpt_expiry_timer);
 	}
 
 	up_write(&afscm_sem);
@@ -498,7 +507,7 @@
 	if (ret<0)
 		rxrpc_call_abort(call,ret);
 
-	if (server) afs_put_server(server);
+	afs_put_server(server);
 
 	_leave(" = %d",ret);
 
@@ -564,7 +573,7 @@
 	if (ret<0)
 		rxrpc_call_abort(call,ret);
 
-	if (server) afs_put_server(server);
+	afs_put_server(server);
 
 	_leave(" = %d",ret);
 
@@ -630,7 +639,7 @@
 	if (ret<0)
 		rxrpc_call_abort(call,ret);
 
-	if (server) afs_put_server(server);
+	afs_put_server(server);
 
 	_leave(" = %d",ret);

Index: cell.h
===================================================================
RCS file: /home/cvs/afs/fs/afs/cell.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- cell.h	6 Jun 2003 08:33:37 -0000	1.4
+++ cell.h	4 Jul 2003 15:26:31 -0000	1.5
@@ -25,7 +25,7 @@
 struct afs_cache_cell
 {
 	char			name[64];	/* cell name (padded with NULs) */
-	struct in_addr		servers[15];	/* cached cell servers */
+	struct in_addr		vl_servers[15];	/* cached cell VL servers */
 };
 
 /*****************************************************************************/
@@ -60,15 +60,15 @@
 
 extern int afs_cell_init(void);
 
-extern int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell);
+extern int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell);
 
-extern int afs_cell_lookup(const char *name, afs_cell_t **_cell);
+extern int afs_cell_lookup(const char *name, unsigned nmsize, struct afs_cell **_cell);
 
 #define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
 
-extern afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell);
+extern struct afs_cell *afs_get_cell_maybe(struct afs_cell **_cell);
 
-extern void afs_put_cell(afs_cell_t *cell);
+extern void afs_put_cell(struct afs_cell *cell);
 
 extern void afs_cell_purge(void);

Index: cell.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/cell.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- cell.c	9 Jun 2003 13:52:04 -0000	1.8
+++ cell.c	4 Jul 2003 15:26:31 -0000	1.9
@@ -182,36 +182,45 @@
 /*
  * lookup a cell record
  */
-int afs_cell_lookup(const char *name, afs_cell_t **_cell)
+int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell)
 {
 	struct list_head *_p;
 	afs_cell_t *cell;
+	int ret;
 
-	_enter("\"%s\",",name?name:"*thiscell*");
+	_enter("\"%*.*s\",", namesz, namesz, name ? name : "");
 
-	cell = afs_cell_root;
+	*_cell = NULL;
 
 	if (name) {
 		/* if the cell was named, look for it in the cell record list */
+		ret = -ENOENT;
 		cell = NULL;
 		read_lock(&afs_cells_lock);
 
 		list_for_each(_p,&afs_cells) {
-			cell = list_entry(_p,afs_cell_t,link);
-			if (strcmp(cell->name,name)==0)
+			cell = list_entry(_p, struct afs_cell, link);
+			if (strncmp(cell->name, name, namesz) == 0) {
+				afs_get_cell(cell);
 				break;
+			}
 			cell = NULL;
 		}
 
 		read_unlock(&afs_cells_lock);
-	}
 
-	if (cell)
+		if (cell)
+			ret = 0;
+	}
+	else {
+		cell = afs_cell_root;
 		afs_get_cell(cell);
+		ret = 0;
+	}
 
 	*_cell = cell;
-	_leave(" = %d (%p)",cell?0:-ENOENT,cell);
-	return cell ? 0 : -ENOENT;
+	_leave(" = %d (%p)", ret, cell);
+	return ret;
 
 } /* end afs_cell_lookup() */
 
@@ -227,7 +236,7 @@
 
 	cell = *_cell;
 	if (cell && !list_empty(&cell->link))
-		atomic_inc(&cell->usage);
+		afs_get_cell(cell);
 	else
 		cell = NULL;
 
@@ -242,6 +251,9 @@
  */
 void afs_put_cell(afs_cell_t *cell)
 {
+	if (!cell)
+		return;
+
 	_enter("%p{%d,%s}",cell,atomic_read(&cell->usage),cell->name);
 
 	/* sanity check */
@@ -395,8 +407,7 @@
 
 	_enter("");
 
-	if (afs_cell_root)
-		afs_put_cell(afs_cell_root);
+	afs_put_cell(afs_cell_root);
 
 	while (!list_empty(&afs_cells)) {
 		cell = NULL;
@@ -480,7 +491,7 @@
 
 	_enter("");
 
-	if (strncmp(ccell->name,cell->name,sizeof(ccell->name))==0)
+	if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0)
 		return CACHEFS_MATCH_SUCCESS;
 
 	return CACHEFS_MATCH_FAILED;
@@ -495,8 +506,12 @@
 	struct afs_cache_cell *ccell = entry;
 	struct afs_cell *cell = source;
 
-	kenter("%p,%p",source,entry);
+	kenter("%p,%p", source, entry);
+
+	strncpy(ccell->name, cell->name, sizeof(ccell->name));
 
-	strncpy(ccell->name,cell->name,sizeof(ccell->name));
+	memcpy(ccell->vl_servers,
+	       cell->vl_addrs,
+	       min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs)));
 
 } /* end afs_cell_cache_update() */

Index: callback.c
===================================================================
RCS file: /home/cvs/afs/fs/afs/callback.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- callback.c	8 Oct 2002 09:06:33 -0000	1.3
+++ callback.c	4 Jul 2003 15:26:31 -0000	1.4
@@ -68,7 +68,7 @@
 			spin_unlock(&vnode->lock);
 
 			iput(inode);
-			if (release) afs_put_server(server);
+			afs_put_server(server);
 
 			spin_lock(&server->cb_lock);
 		}

Index: Makefile
===================================================================
RCS file: /home/cvs/afs/fs/afs/Makefile,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile	4 Feb 2003 16:12:05 -0000	1.11
+++ Makefile	4 Jul 2003 15:26:31 -0000	1.12
@@ -2,6 +2,8 @@
 # Makefile for Red Hat Linux AFS client.
 #
 
+CFLAGS += -finstrument-functions
+
 kafs-objs := \
 	callback.o \
 	cell.o \