[SSI] openssi/kernel/cluster/ssi/cfs cfs_ipcshm.c, 1.16, 1.17 cfs_server.c, 1.14, 1.15 cfs_subr.c, 1.23, 1.24 cfs_svc.c, 1.17, 1.18 cfsproc.c, 1.28, 1.29 cfstok.c, 1.19, 1.20 dir.c, 1.23, 1.24 file.c, 1.21, 1.22 inode.c, 1.56, 1.57 proc.c, 1.18, 1.19 read.c, 1.19, 1.20 svrcfs.c, 1.17, 1.18 symlink.c, 1.10, 1.11 vfs.c, 1.27, 1.28 write.c, 1.35, 1.36

Roger Tsang <[email protected]>
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8553/cluster/ssi/cfs

Modified Files:
      Tag: OPENSSI-FC
	cfs_ipcshm.c cfs_server.c cfs_subr.c cfs_svc.c cfsproc.c 
	cfstok.c dir.c file.c inode.c proc.c read.c svrcfs.c symlink.c 
	vfs.c write.c 
Log Message:
Bug fixes and enhancements. (see ChangeLog)


Index: cfs_ipcshm.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_ipcshm.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cfs_ipcshm.c	22 Apr 2005 02:09:15 -0000	1.16
+++ cfs_ipcshm.c	3 Feb 2009 06:18:12 -0000	1.17
@@ -67,8 +67,8 @@
 		key_t key,
 		int shmflg)
 {
-	struct shmid_kernel_svr *svr_shm = NULL;
-	struct dentry *de = NULL;
+	struct shmid_kernel_svr *svr_shm;
+	struct dentry *de;
 	nsc_nodelist_t *nl;
 	int err = 0;
 
@@ -95,6 +95,11 @@
 	svr_shm->shm_nodelist = nl;
 	svr_shm->shm_svr =(struct svrcfstok *)makehp(cfs_shm_sb,
 			ssidev_get_s_ssidev(shm_mnt->mnt_sb, FALSE),de);
+	SSI_ASSERT(svr_shm->shm_svr);
+#ifdef CFS_IPCSHM_DENTRY
+	if (!svr_shm->shm_svr->sct_dp)
+		svr_shm->shm_svr->sct_dp = dget(de);
+#endif
 	if (shm_svr_addid(svr_shm) < 0) {
 		printk("failed to add shm svr\n");
 		HASH_RELE(svr_shm->shm_svr);
@@ -137,7 +142,11 @@
 		de->d_sb = ip->i_sb;
 		de->d_parent = cfs_shm_sb->s_root;
 		d_instantiate(de, ip);
+#ifdef CFS_IPCSHM_DENTRY
+		d_rehash(de);
+#else
 		d_rehash(shmsvr->shm_svr->sct_dp);
+#endif
 		return de;
 	}
 	else {
@@ -266,7 +275,9 @@
 void
 shm_svr_cleanup(struct shmid_kernel_svr *shmsvr)
 {
+#ifndef CFS_IPCSHM_DENTRY
 	d_drop(shmsvr->shm_svr->sct_dp);
+#endif
 	HASH_RELE(shmsvr->shm_svr);
 }
 
@@ -301,17 +312,8 @@
 struct inode *
 shm_svr_get_inode(int id)
 {
-	struct inode *i;
-	struct svrcfstok *hp;
-	struct shmid_kernel_svr *shmsvr;
-
-	shmsvr = (struct shmid_kernel_svr *)shm_svr_get(id);
-	if (!shmsvr)
-		return NULL;
-	hp = shmsvr->shm_svr;
-	i = (struct inode *)hp->sct_ip;
-
-	return i;
+	struct shmid_kernel_svr *shmsvr = shm_svr_get(id);
+	return shmsvr ? shmsvr->shm_svr->sct_ip : NULL;
 }
 
 

Index: cfs_server.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_server.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- cfs_server.c	10 Oct 2008 08:10:31 -0000	1.14
+++ cfs_server.c	3 Feb 2009 06:18:12 -0000	1.15
@@ -473,6 +473,22 @@
 		else {
 			nlp = NSC_NODELIST_ALLOC();
 			if (nlp != NULL) {
+				if ((rootip = sb->s_root->d_inode)) {
+					igrab(rootip);
+					roothp = itoc(rootip)->c_hp;
+					if (roothp) {
+						HASH_HOLD(roothp);
+						*nlp = svrcfstok_get_mholdlist(roothp);
+						HASH_RELE(roothp);
+					} else
+						error = -EBUSY;
+					iput(rootip);
+				} else {
+					roothp = NULL;
+					error = -EBUSY;
+				}
+#ifdef SSI_SKIP
+/* Do not remove. Keep for reference */
 				/* SSI_XXX: Is this safe without locking? */
 				/* CTABLE_SHR_LOCK(); */
 				rootip = sb->s_root->d_inode;
@@ -484,15 +500,14 @@
 					roothp = itoc(rootip)->c_hp;
 				if (roothp != NULL) {
 					HASH_HOLD(roothp);
-					LOCK_LOCK(&roothp->sct_tcblock);
 					*nlp = svrcfstok_get_mholdlist(roothp);
-					UNLOCK_LOCK(&roothp->sct_tcblock);
 					HASH_RELE(roothp);
 				}
 				else
 					error = -EBUSY;
 				if (rootip != NULL)
 					iput(rootip);
+#endif
 			}
 		}
 		/* Success? */
@@ -704,7 +719,6 @@
 		return 0;
 
 	droot = sbtocmi(sb)->mi_pfs_sb->s_root;
-	dget(droot);	/* needed? */
 
 	down(&(droot->d_inode->i_sem));
 
@@ -718,6 +732,7 @@
 	ddir = lookup_one_len(CFS_UNLINKDIR, droot, strlen(CFS_UNLINKDIR));
 	if (IS_ERR(ddir)) {
 		error = PTR_ERR(ddir);
+		ddir = NULL;
 		goto done;
 	}
 	up(&(droot->d_inode->i_sem));
@@ -884,7 +899,6 @@
 		fput(filp);
 	if (dir_buf)
 		kfree(dir_buf);
-	dput(droot);	/* needed? */
 	if (ddir)
 		dput(ddir);
 	if (dhp)

Index: inode.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/inode.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- inode.c	10 Oct 2008 08:10:31 -0000	1.56
+++ inode.c	3 Feb 2009 06:18:12 -0000	1.57
@@ -72,7 +72,12 @@
 
 #define CFS_PARANOIA 1
 
+#ifdef RCU_CFSTOK_TABLE
+extern void svrcfstok_init(void);
+#endif
+#ifdef SSI_XXX
 void svrcfstok_deinit(void);
+#endif
 int ics_cfs_svc_init(void);
 void cfs_start_daemon(void);
 void cfstok_param_init (void);
@@ -458,18 +463,18 @@
 cfs_zap_caches(struct inode *inode)
 {
 #ifdef CFS_ZAP_CACHES
+	int mode = inode->i_mode;
+
 	LOCK_COND_LOCK(&itoc(inode)->c_statelock);
 
 #ifdef CFS_FILE_RW_NOLOCK
 	CFS_ATTRTIMEO(inode) = CFS_MINATTRTIMEO(inode);
 	CFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 #endif
-
-	/* Mark the attribute cache for revalidation */
-	CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR;
-	/* Directories and symlinks: invalidate page cache too */
-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-		CFS_FLAGS(inode) |= CFS_INO_INVALID_DATA;
+	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
+		CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR | CFS_INO_INVALID_DATA | CFS_INO_INVALID_ACCESS;
+	else
+		CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR | CFS_INO_INVALID_ACCESS;
 
 	UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
 #else
@@ -598,7 +603,7 @@
 #ifdef SSI_XXX
 		/* SSI_XXX: This may be needed instead ? */
 		if (memcmp (itocfh(inode), &(desc->cdrok->cdrok_fhandle),
-		    sizeof (cfhandle_t) != 0)
+		    sizeof (cfhandle_t) != 0))
 			return 0;
 #endif /* SSI_XXX */
 	} else {
@@ -607,7 +612,7 @@
 #ifdef SSI_XXX
 		/* SSI_XXX: This may be needed instead ? */
 		if (memcpy(itocfh(inode), &(desc->hp->sct_fh),
-		    sizeof (cfhandle_t) != 0)
+		    sizeof (cfhandle_t) != 0))
 			return 0;
 #endif /* SSI_XXX */
 	}
@@ -642,7 +647,7 @@
 		memcpy(itocfh(inode), &(desc->hp->sct_fh), sizeof (cfhandle_t));
 
 		itoc(inode)->c_hp = desc->hp;
-		HASH_HOLD(itoc(inode)->c_hp);
+		HASH_HOLD(desc->hp);
 
 		itoc(inode)->c_locknumber = (void *) &(desc->hp->sct_mhold);
 
@@ -801,9 +806,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	int error, result;
-#ifndef SSI_RECURSIVE_SEMAPHORE
 	int rwlocked;
-#endif
 
 #ifdef CFS_SETATTR_LAZY
 	if (attr->ia_valid & ATTR_SIZE) {
@@ -817,7 +820,6 @@
 		return 0;
 #endif
 
-#ifndef SSI_RECURSIVE_SEMAPHORE
 	/* Avoid deadlock with fs/open.c:do_truncate
 	 *	-Roger
 	 *
@@ -836,12 +838,30 @@
 	 * reaquiring i_sem.
 	 */
 	up(&inode->i_sem);
-#endif
 
 	/* Hold ATTR token */
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 				CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	down(&inode->i_sem);
+	if (rwlocked)
+		down_write(&inode->i_alloc_sem);
+#endif
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+#ifndef CFS_FILE_WRITE_LIVELOCK_FIX
+		down(&inode->i_sem);
+		if (rwlocked)
+			down_write(&inode->i_alloc_sem);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif /* !CFSTOK_INTR */
 
 	cfs_begin_data_update(inode);
 #ifdef CFS_SETATTR_LAZY_FLUSH
@@ -855,7 +875,7 @@
 	/* Flush early because the error case is not common */
 	error = cfs_wb_all(inode);
 #endif
-#ifndef SSI_RECURSIVE_SEMAPHORE
+#ifndef CFS_FILE_WRITE_LIVELOCK_FIX
 	down(&inode->i_sem);
 	if (rwlocked)
 		down_write(&inode->i_alloc_sem);
@@ -1082,7 +1102,7 @@
 	if (CFS_FLAGS(inode) & CFS_INO_INVALID_DATA) {
 		UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
 
-		if (S_ISREG(inode->i_mode) && inode->i_mapping->nrpages) { 
+		if (S_ISREG(inode->i_mode) && inode->i_mapping->nrpages) {
 			unmap_mapping_range(inode->i_mapping, 0, 0, 0);
 			if (!filemap_write_and_wait(inode->i_mapping))
 				(void)cfs_wb_all(inode);
@@ -1187,6 +1207,11 @@
 	struct cfs_server *server = itocmi(inode);
 	int	status;
 	int	result;
+#ifdef CFS_ZAP_CACHES
+#ifdef SSI_CFS_SKIP
+	int need_atime;
+#endif
+#endif
 
 	dfprintk(PAGECACHE, "CFS: revalidating (%x/%ld)\n",
 		inode->i_sb->s_dev, inode->i_ino);
@@ -1204,10 +1229,22 @@
 
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		status = -EINTR;
+		goto sb_error_check;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 #ifdef CFS_ZAP_CACHES
-#if SSI_EXNFS
-	int need_atime = CFS_FLAGS(inode) & CFS_INO_INVALID_ATIME;
+#ifdef SSI_CFS_SKIP
+	LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+	need_atime = CFS_FLAGS(inode) & CFS_INO_INVALID_ATIME;
+	UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
 
 	if (__IS_FLG(inode, MS_NOATIME))
 		need_atime = 0;
@@ -1301,12 +1338,20 @@
 #ifdef CLMS_PREEMPT
 	cur_isize = i_size_read(inode);
 #ifdef CFS_ZAP_CACHES
-	if (cur_isize != new_isize
-	    && (!cfs_have_writebacks(inode) || new_isize > cur_isize)) { 
-		i_size_write(inode, new_isize);
-		LOCK_COND_LOCK(&itoc(inode)->c_statelock);
-		CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA;
-		UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+	if (cur_isize != new_isize) {
+		if (S_ISREG(inode->i_mode) && cfs_have_writebacks(inode)) {
+			if (new_isize > cur_isize) {
+				i_size_write(inode, new_isize);
+				LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+				CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA;
+				UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+			}
+		} else {
+			i_size_write(inode, new_isize);
+			LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+			CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA;
+			UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+		}
 	}
 #else
 	if (cfs_have_writebacks(inode) && new_isize < cur_isize)
@@ -1336,9 +1381,11 @@
 #ifdef CFS_DEBUG_VERBOSE
 		printk(KERN_DEBUG "CFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
 #endif
-		LOCK_COND_LOCK(&itoc(inode)->c_statelock);
-		CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA;
-		UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+		if (!cfs_have_writebacks(inode)) {
+			LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+			CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA;
+			UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+		}
 	}
 #endif /* CFS_ZAP_CACHES */
 
@@ -1353,12 +1400,24 @@
  	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
  		inode->i_rdev = fattr->cna_rdev;
 
+#ifndef CFS_ZAP_CACHES
 	itoc(inode)->c_vn = fattr->cna_vn;
+#else
+	if (itoc(inode)->c_vn != fattr->cna_vn) {
+		itoc(inode)->c_vn = fattr->cna_vn;
+		if (!cfs_have_writebacks(inode)) {
+			LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+			CFS_FLAGS(inode) |= CFS_INO_INVALID_ATTR|CFS_INO_INVALID_DATA|CFS_INO_INVALID_ACCESS;
+			UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+		}
+	}
+#endif
 	inode->i_generation = fattr->cna_generation;
 
 	cfstok_putiflags(inode, fattr->cna_flags);
 
-#if defined(CFS_ZAP_CACHES) && defined(CFS_FILE_RW_NOLOCK)
+#if defined(CFS_ZAP_CACHES)
+#if defined(CFS_FILE_RW_NOLOCK)
 	/* Update attrtimeo value if we're out of the unstable period */
 	LOCK_COND_LOCK(&itoc(inode)->c_statelock);
 	if (CFS_FLAGS(inode) & CFS_INO_INVALID_ATTR) {
@@ -1370,7 +1429,7 @@
 		CFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 	}
 	UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
-#ifdef SSI_EXNFS
+#endif
 	/* Don't invalidate the data if we were to blame */
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode))) {
@@ -1379,7 +1438,6 @@
 		UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
 	}
 #endif
-#endif
 
 	return 0;
 
@@ -1509,21 +1567,48 @@
 tokseq_t *cfs_tsp;
 int cfs_initialized;
 
+#ifdef CFSTOK_KMEM_CACHE
+extern void cfstokhold_init(void);
+extern void cfs_delrel_init(void);
+#else
+extern SPIN_LOCK_T		(ctokhold_free_lock);
+extern SPIN_LOCK_T		(dr_free_lock);
+#endif
+#ifdef SVRCFS_KMEM_CACHE
+extern void hlist_cache_init(void);
+#else
+extern SPIN_LOCK_T		(hlist_t_free_lock);
+#endif
+#ifdef CLITOK_KMEM_CACHE
+extern void nrreq_init(void);
+extern void nrrevoke_init(void);
+#else
 extern SPIN_LOCK_T		(nrreq_free_lock);
 extern SPIN_LOCK_T		(nrrev_free_lock);
+#endif
+#ifdef SVRTOK_KMEM_CACHE
+extern void node_ent_init(void);
+extern void nrwant_init(void);
+#else
 extern SPIN_LOCK_T		(node_free_lock);
 extern SPIN_LOCK_T		(nrwant_free_lock);
-extern SPIN_LOCK_T		(ctokhold_free_lock);
-extern SPIN_LOCK_T		(dr_free_lock);
+#endif
+#ifdef MHSVRTOK_KMEM_CACHE
+extern void mhnode_init(void);
+#else
+extern SPIN_LOCK_T		mhnode_free_lock;
+#endif
 extern SOFTIRQ_SPIN_LOCK_T	(dr_list_lock);
-extern SPIN_LOCK_T		(hlist_t_free_lock);
 #ifdef SSI_CFS_POLICY
 extern SPIN_LOCK_T		(contention_free_lock);
 extern SPIN_LOCK_T		(condata_node_free_lock);
 #endif /* SSI_CFS_POLICY */
-extern SPIN_LOCK_T		mhnode_free_lock;
 
+#ifdef RCU_CFSTOK_TABLE
+extern spinlock_t		svrcfstok_table_lock;
+#else
 extern LOCK_T			svrcfstok_table_lock;
+#endif
 #ifdef SSI_EXNFS
 extern LOCK_T			exnfs_svr_lock;
 extern LOCK_T			exnfs_svr_start_lock;
@@ -1589,6 +1674,10 @@
 #endif
 		cp->c_hp = NULL;
 		INIT_CONDITION(&(cp->c_cxlock));
+#ifdef CFSTOKHOLD_LINUX_LIST
+		for(idx = 0; idx < CFSTOK_NTOKS; idx++)
+			INIT_LIST_HEAD(&cp->c_hlist[idx]);
+#endif
 		INIT_COND_LOCK(&(cp->c_statelock));
 		INIT_LOCK(&(cp->c_tcblock));
 		for (idx = 0 ; idx < CFS_MAX_LISTS ; idx++)
@@ -1627,10 +1716,13 @@
 {
 	cfs_init_inodecache();
 	
+#ifdef RCU_CFSTOK_TABLE
+	svrcfstok_init();
+#endif
 	cfstok_param_init();
 
 	/* Initialize Message Support code */
-	msgsup_init();
+	msgsup_init();		/* msgsup_msg_cache, msgsup_id_cache */
 
 	/* Initialize Range token code */
 	cliglue_global_init();
@@ -1655,24 +1747,39 @@
 	/*
 	 * initialize global fast spin locks
 	 */
+#ifndef CFSTOK_KMEM_CACHE
+	INIT_SPIN_LOCK(&ctokhold_free_lock);
+	INIT_SPIN_LOCK(&dr_free_lock);
+#endif
+#ifndef SVRCFS_KMEM_CACHE
+	INIT_SPIN_LOCK(&hlist_t_free_lock);
+#endif
+#ifndef CLITOK_KMEM_CACHE
 	INIT_SPIN_LOCK(&nrreq_free_lock);
 	INIT_SPIN_LOCK(&nrrev_free_lock);
+#endif
+#ifndef SVRTOK_KMEM_CACHE
 	INIT_SPIN_LOCK(&node_free_lock);
-	INIT_SPIN_LOCK(&mhnode_free_lock);
 	INIT_SPIN_LOCK(&nrwant_free_lock);
-	INIT_SPIN_LOCK(&ctokhold_free_lock);
-	INIT_SPIN_LOCK(&dr_free_lock);
+#endif
+#ifndef MHSVRTOK_KMEM_CACHE
+	INIT_SPIN_LOCK(&mhnode_free_lock);
+#endif
 	INIT_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
-	INIT_SPIN_LOCK(&hlist_t_free_lock);
 #ifdef SSI_CFS_POLICY
 	INIT_SPIN_LOCK(&contention_free_lock);
 	INIT_SPIN_LOCK(&condata_node_free_lock);
 #endif
+#ifdef RCU_CFSTOK_TABLE
+	spin_lock_init(&svrcfstok_table_lock);
+#endif
 
 	/*
 	 * initialize global sleep locks
 	 */
+#ifndef RCU_CFSTOK_TABLE
 	INIT_LOCK(&svrcfstok_table_lock);
+#endif
 #ifdef SSI_EXNFS
 	INIT_LOCK(&exnfs_svr_lock);
 	INIT_LOCK(&exnfs_svr_start_lock);
@@ -1698,17 +1805,45 @@
 	sb_nblks = (struct sb_nblks *)kmem_zalloc(MAX_SB_NBLKS_ENTRY * sizeof(struct sb_nblks), KM_SLEEP);
 #endif
 
+	/*
+	 * initialize token caches
+	 */
+#ifdef CFSTOK_KMEM_CACHE
+	cfstokhold_init();	/* cfstok_cache */
+	cfs_delrel_init();	/* cfsdr_cache */
+#else
 	/* SSI_XXX: What value of seeks here? dbz */
 	set_shrinker(DEFAULT_SEEKS, cfstok_free_memory);
 	set_shrinker(DEFAULT_SEEKS, cfsdr_free_memory);
+#endif
+#ifdef SVRCFS_KMEM_CACHE
+	hlist_cache_init();	/* svrhl_cache */
+#else
 	set_shrinker(DEFAULT_SEEKS, svrhl_free_memory);
+#endif
+#ifdef CLITOK_KMEM_CACHE
+	nrreq_init();		/* clitok_req_cache */
+	nrrevoke_init();	/* clitok_rev_cache */
+#else
 	set_shrinker(DEFAULT_SEEKS, clitok_req_free_memory);
 	set_shrinker(DEFAULT_SEEKS, clitok_rev_free_memory);
+#endif
+#ifdef SVRTOK_KMEM_CACHE
+	node_ent_init();	/* svrtok_nd_cache */
+	nrwant_init();		/* svrtok_wt_cache */
+#else
 	set_shrinker(DEFAULT_SEEKS, svrtok_nd_free_memory);
 	set_shrinker(DEFAULT_SEEKS, svrtok_wt_free_memory);
+#endif
+#ifdef MHSVRTOK_KMEM_CACHE
+	mhnode_init();		/* mhsvrtok_cache */
+#else
 	set_shrinker(DEFAULT_SEEKS, mhsvrtok_free_memory);
+#endif
+#ifndef RCU_MSGSUP
 	set_shrinker(DEFAULT_SEEKS, msgsup_msg_free_memory);
 	set_shrinker(DEFAULT_SEEKS, msgsup_id_free_memory);
+#endif
 
 	return;
 }

Index: cfs_svc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_svc.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- cfs_svc.c	10 Oct 2008 08:10:31 -0000	1.17
+++ cfs_svc.c	3 Feb 2009 06:18:12 -0000	1.18
@@ -685,6 +685,10 @@
         int i;
         int error;
 
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+	if (!vec_len)
+		return 0;
+#endif
 	*vec = __vec = kmalloc_nofail(sizeof(struct kvec) * vec_len);
 
         for (i = 0; i < vec_len; i++, __vec++) {
@@ -698,7 +702,7 @@
 
         return 0;
 }
-#endif
+#endif /* CFS_PAGEVEC */
 
 /*
  * param IN:XDR struct cfswriteargs *

Index: write.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/write.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- write.c	10 Oct 2008 08:10:32 -0000	1.35
+++ write.c	3 Feb 2009 06:18:12 -0000	1.36
@@ -438,6 +438,9 @@
 	pgoff_t end;
 	unsigned int npages = 0;
 #endif
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	int flushing = sem_flushing(&inode->i_sem);
+#endif
 
 	err = generic_writepages(mapping, wbc);
 	if (err)
@@ -445,8 +448,14 @@
 
 #ifdef CFS_WRITEPAGES_AT_SVR_SKIP_BDI
 	/* Don't interfere with backing device's request queue. */
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	while (!flushing &&
+	       test_and_set_bit(BDI_cfs_write_congested,
+					&bdi->state) != 0) {
+#else
 	while (test_and_set_bit(BDI_cfs_write_congested,
 					&bdi->state) != 0) {
+#endif
 #else
 	while (test_and_set_bit(BDI_write_congested,
 					&bdi->state) != 0) {
@@ -497,6 +506,10 @@
 	}
 out:
 #ifdef CFS_WRITEPAGES_AT_SVR_SKIP_BDI
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	if (flushing)
+		return err;
+#endif
 	smp_mb__before_clear_bit();
 	clear_bit(BDI_cfs_write_congested, &bdi->state);
 	smp_mb__after_clear_bit();
@@ -759,6 +772,28 @@
 	DEFINE_WAIT(wait);
 	int ret = 0;
 
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	/* RT: [ ssic-linux-Bugs-686748 ] Filesystem stacking deadlock. Part 2.
+	 *
+	 * Deadlock wait on bit:
+	 *				(pdflush)
+	 * 				...
+	 * BDI_cfs_write_congested	(cfs_writepages)
+	 * 				...
+	 * 				(generic_file_buffered_write)
+	 * 				...
+	 * 				(alloc_pages)
+	 * 				...
+	 * 				(shrink_caches)
+	 * 				...
+	 * 				(cfs_writepage)
+	 * 				...
+	 * cfs_write_congestion		(cfs_wait_on_write_congestion)
+	 */
+	if (sem_flushing(&mapping->host->i_sem))
+		return 0;
+#endif
+
 	might_sleep();
 
 #ifdef CFS_WRITEPAGES_AT_SVR_SKIP_BDI
@@ -1013,7 +1048,11 @@
  */
 static void cfs_async_handler_write(void *args)
 {
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+	struct cfs_write_data *data = (struct cfs_write_data *)args;
+#else
 	struct cfs_write_data *data = *(struct cfs_write_data **)args;
+#endif
 	struct inode		*inode = data->inode;
 	int stable = data->stable;
 	int status;
@@ -1271,9 +1310,21 @@
 #else
 	if (async) {
 #endif
+#ifdef NSC_ASYNC_SLAB_NOFS__FLAG
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_write,
+				    data, sizeof(*data),
+				    NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS)) {
+#else
+		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_write,
+				    &data, sizeof(data),
+				    NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS)) {
+#endif
+#else
 		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_write,
 				    &data, sizeof(struct cfs_write_data *),
 				    NSC_ASYNC_SLEEP)) {
+#endif
 
 			while (!list_empty(&data->pages)) {
 				req = cfs_list_entry(data->pages.next);
@@ -1291,7 +1342,11 @@
 			return -ENOMEM;
 		}
 	} else
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+		cfs_async_handler_write(data);
+#else
 		cfs_async_handler_write(&data);
+#endif
 #ifdef NSC_INHERIT_USER_NICE
 	if (how & FLUSH_LOWPRI)
 		set_user_nice(current, old_nice);
@@ -1349,7 +1404,11 @@
  */
 static void cfs_async_handler_commit(void *args)
 {
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+	struct cfs_write_data *data = (struct cfs_write_data *)args;
+#else
 	struct cfs_write_data *data = *(struct cfs_write_data **)args;
+#endif
 	int status = 0;
 	unsigned int res = 0;
 
@@ -1555,9 +1614,21 @@
 #else
 	if (async) {
 #endif
+#ifdef NSC_ASYNC_SLAB_NOFS__FLAG
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_commit,
+				    data, sizeof(*data),
+				    NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS)) {
+#else
+		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_commit,
+				    &data, sizeof(struct cfs_write_data *),
+				    NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS)) {
+#endif
+#else
 		if (nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_commit,
 				    &data, sizeof(struct cfs_write_data *),
 				    NSC_ASYNC_SLEEP)) {
+#endif
 
 			while (!list_empty(&data->pages)) {
 				req = cfs_list_entry(data->pages.next);
@@ -1573,7 +1644,11 @@
 			return -ENOMEM;
 		}
 	} else
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+		cfs_async_handler_commit(data);
+#else
 		cfs_async_handler_commit(&data);
+#endif
 #ifdef NSC_INHERIT_USER_NICE
 	if (how & FLUSH_LOWPRI)
 		set_user_nice(current, old_nice);

Index: file.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/file.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- file.c	10 Oct 2008 08:10:31 -0000	1.21
+++ file.c	3 Feb 2009 06:18:12 -0000	1.22
@@ -124,8 +124,23 @@
 	 * field.
 	 */
 	if (origin == 2)
+#ifdef CFSTOK_INTR
+	{
+		int status;
+
+		status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
+			CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+		if (status != CFSTOK_HELD) {
+#ifdef DEBUG
+			printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+			return -EINTR;
+		}
+	}
+#else
 		(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 			CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#endif
 
 	/* SSI_XXX: Subtle diff with default_llseek() & generic_file_llseek() */
 	result = remote_llseek(file, offset, origin);
@@ -152,12 +167,22 @@
 
 	/* Avoid invalidate_inode_pages race */
 #ifdef SSI_CFSTOK_SU
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #else
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
+#ifdef CFSTOK_INTR
+	if (status != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
+	SSI_ASSERT(status == CFSTOK_HELD);
+#endif
 
 	/* Ensure that data+attribute caches are up to date after close() */
 	status = cfs_wb_all(inode);
@@ -203,7 +228,7 @@
 
 #ifndef CFS_FILE_RW_NOLOCK
 	cfstok_hl_init(&held);
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
+	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, &held);
 
 	/* SSI_XXX: ATIME?
@@ -218,10 +243,20 @@
 	rnd_len = count + (*ppos & (PAGE_CACHE_SIZE - 1));
 	rnd_len = ((rnd_len + (PAGE_CACHE_SIZE - 1)) >> PAGE_CACHE_SHIFT)
 		<< PAGE_CACHE_SHIFT;
-	(void)cfstok_req(inode, CFSTOK_DATA, CFSTOK_READ,
+	result = cfstok_req(inode, CFSTOK_DATA, CFSTOK_READ,
 			CFSTOK_BLOCK|CFSTOK_HOLD, rnd_start, rnd_len, &held);
 #endif
 #endif /* !CFS_FILE_RW_NOLOCK */
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
+	SSI_ASSERT(result == CFSTOK_HELD);
+#endif /* !CFSTOK_INTR */
 #ifdef CFS_ZAP_CACHES
 	result = cfs_revalidate_inode(inode);
 	if (!result) {
@@ -292,13 +327,27 @@
 	struct page *result = NULL;
 	struct inode *inode = area->vm_file->f_dentry->d_inode;
 	int prio = ics_getpriority();
+#ifdef CFSTOK_INTR
+	int status;
+#endif
 
 	/* Up icsprio to avoid deadlock */
 	if (prio < ICS_MAX_PRIO)
 		ics_setpriority(prio + 1);
 
+#ifdef CFSTOK_INTR
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
+			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
+	if (status != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return ERR_PTR(-EINTR);
+	}
+#else
 	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
+#endif
 
 	result = filemap_nopage(area, address, typep);
 
@@ -331,13 +380,27 @@
 	struct inode *inode = area->vm_file->f_dentry->d_inode;
 	struct page *result = NULL;
 	int prio = ics_getpriority();
+#ifdef CFSTOK_INTR
+	int status;
+#endif
 
 	/* Up icsprio to avoid deadlock */
 	if (prio < ICS_MAX_PRIO)
 		ics_setpriority(prio + 1);
 
+#ifdef CFSTOK_INTR
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
+			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
+	if (status != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return ERR_PTR(-EINTR);
+	}
+#else
 	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
+#endif
 
 	result = filemap_nopage(area, address, typep);
 
@@ -410,13 +473,22 @@
 	dfprintk(VFS, "cfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
 #ifdef SSI_CFSTOK_SU
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #else
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
+	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
-
+#ifdef CFSTOK_INTR
+	if (status != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
+	SSI_ASSERT(status == CFSTOK_HELD);
+#endif
 	status = cfs_wb_all(inode);
 	if (!status) {
 		status = file->f_error;
@@ -515,10 +587,10 @@
 	cfstok_hl_init(&held);
 
 #ifdef SSI_CFSTOK_SU
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
+	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_SU,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, &held);
 #else
-	(void)cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
+	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, &held);
 #endif
 #ifdef SSI_CFS_FULLTOKENS
@@ -527,10 +599,20 @@
 	rnd_len = count + (*ppos & (PAGE_CACHE_SIZE - 1));
 	rnd_len = ((rnd_len + (PAGE_CACHE_SIZE - 1)) >> PAGE_CACHE_SHIFT)
 		<< PAGE_CACHE_SHIFT;
-	(void)cfstok_req(inode, CFSTOK_DATA, CFSTOK_EXCL
+	result = cfstok_req(inode, CFSTOK_DATA, CFSTOK_EXCL
 			CFSTOK_BLOCK|CFSTOK_HOLD, rnd_start, rnd_len, &held);
 #endif
 #endif /* !CFS_FILE_RW_NOLOCK */
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
+	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 #ifndef CFS_ZAP_CACHES
 	/* Don't need to revalidate inode at this point because that ended
@@ -592,7 +674,9 @@
 	cfs_mntinfo_t *mip = itocmi(inode);
 	int	status = 0;
 	struct cfslockargs la;
+#ifndef CFS_MIRROR_LOCK_WAIT
 	int new_lock = 0;
+#endif
 
 	dprintk("CFS: cfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_sb->s_dev, inode->i_ino,
@@ -642,7 +726,17 @@
 			if (status == 0)
 				status = res;
 		}
+#ifndef CFS_MIRROR_LOCK_WAIT
 		new_lock = 1;
+#else
+		/* Get the mirror lock ahead of the base under rebuild protection */
+		/* By being inside the CFS_SB_FSOP_START, rebuild can't proceed
+		 * and storing the mirror lock is safe vs rebuilding server.
+		 */
+		if (!status && posix_lock_file_wait(filp, fl) < 0)
+			printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+					__FUNCTION__);
+#endif
 	} else if (IS_GETLK(cmd)) {
 		struct cfsgetlockres res;
 
@@ -674,16 +768,12 @@
 		status = -EINVAL;
 	}
 
+#ifndef CFS_MIRROR_LOCK_WAIT
 	/* Get the mirror lock ahead of the base under rebuild protection */
 	/* By being inside the CFS_SB_FSOP_START, rebuild can't proceed
 	 * and storing the mirror lock is safe vs rebuilding server.
 	 */
-#ifdef CFS_MIRROR_LOCK_WAIT
-	if (new_lock && !status)
-		posix_lock_file_wait(filp, fl);
-#else
-#error mirror locks need to be serialized
-	/* SSI_XXX: FIXME: use sequence numbers. */
+#warn mirror locks could get out of sync with lock manager
 	if (new_lock) {
 		if (!status) {
 			int err;

Index: dir.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/dir.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- dir.c	10 Oct 2008 08:10:31 -0000	1.23
+++ dir.c	3 Feb 2009 06:18:12 -0000	1.24
@@ -351,6 +351,11 @@
 	desc->error = CFS_PROTO(inode)->readdir(inode, desc->target,
 						desc->ptr,
 						PAGE_CACHE_SIZE);
+#ifdef SSI_CFS_SKIP
+	LOCK_COND_LOCK(&itoc(inode)->c_statelock);
+	CFS_FLAGS(inode) |= CFS_INO_INVALID_ATIME;
+	UNLOCK_COND_LOCK(&itoc(inode)->c_statelock);
+#endif
 	if (desc->error >= 0) {
 		if ((status = cfs_dir_decode(desc)) == 0)
 			desc->entry->prev_cookie = desc->target;
@@ -364,7 +369,9 @@
 	/* Reset read descriptor so it searches the page cache from
 	 * the start upon the next call to readdir_search_pagecache() */
 	desc->page_index = 0;
-	memset(desc->entry, 0, sizeof(*desc->entry));
+	//memset(desc->entry, 0, sizeof(*desc->entry));
+	desc->entry->cookie = desc->entry->prev_cookie = 0;
+	desc->entry->eof = 0;
  out:
 	dfprintk(VFS, "CFS: uncached_readdir() returns %d\n", status);
 	return status;
@@ -378,7 +385,7 @@
 {
 	struct inode	*inode;
 	int		err;
-	struct file	file;
+	struct file	*file;
 	loff_t	origoffset = *offset;
 
 	err = cfsd_open(hp, S_IFDIR, MAY_READ, &file);
@@ -388,10 +395,10 @@
 		goto out_close;
 
 	err = -ENOTDIR;
-	if (!file.f_op->readdir)
+	if (!file->f_op->readdir)
 		goto out_close;
 	if (*offset != 0) {
-		err = (int)vfs_llseek(&file, *offset, 0);
+		err = (int)vfs_llseek(file, *offset, 0);
 		if (err < 0)
 			goto out_close;
 	}
@@ -401,7 +408,7 @@
 	 * readdir() is not guaranteed to fill up the entire buffer, but
 	 * may choose to do less.
 	 */
-	inode = file.f_dentry->d_inode;
+	inode = file->f_dentry->d_inode;
 	down(&inode->i_sem);
 	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
@@ -415,12 +422,12 @@
 		file.f_inode->i_sb->s_dev, file.f_inode->i_ino,
 		(int) file.f_pos);
 	 */
-	err = file.f_op->readdir(&file, dirent, filldir);
+	err = file->f_op->readdir(file, dirent, filldir);
 	if (err < 0)
 		goto out_cfserr;
 	up(&inode->i_sem);
 
-	*offset = file.f_pos;
+	*offset = file->f_pos;
 
 #if NBITPOFF == 64
 	dprintk("cfsd: readdir result %Ld bytes, offset %Ld\n",
@@ -431,7 +438,7 @@
 #endif
 	err = 0;
 out_close:
-	cfsd_close(&file);
+	cfsd_close(file);
 out:
 	return err;
 
@@ -456,7 +463,16 @@
 
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 #ifdef CFS_ZAP_CACHES
 	res = cfs_revalidate_inode(inode);
@@ -490,12 +506,14 @@
 
 	desc->file = filp;
 	desc->target = filp->f_pos;
-	desc->entry = &my_entry;
 	desc->decode = CFS_PROTO(inode)->decode_dirent;
 #ifdef CFS_READDIRPLUS
 #warning CFS readdirplus not yet supported.
 	desc->plus = CFS_USE_READDIRPLUS(inode);
 #endif
+	my_entry.cookie = my_entry.prev_cookie = 0;
+	my_entry.eof = 0;
+	desc->entry = &my_entry;
 
 	while(!desc->entry->eof) {
 		res = readdir_search_pagecache(desc);
@@ -639,7 +657,7 @@
 	dentry->d_time = jiffies;
 }
 
-#if defined(CFS_ZAP_CACHES) && defined(CFS_FILE_RW_NOLOCK)
+#if defined(CFS_ZAP_CACHES) //&& defined(CFS_FILE_RW_NOLOCK)
 static inline
 int cfs_lookup_verify_inode(struct inode *inode, int isopen)
 {
@@ -684,7 +702,7 @@
 #endif
 
 	parent = dget_parent(dentry);
-#ifdef SSI_EXNFS_XXX
+#ifdef SSI_CFS_SKIP
 	lock_kernel();
 #endif
 	dir = parent->d_inode;
@@ -721,22 +739,32 @@
 
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+		dput(parent);
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return 0;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 	lock = TRUE;
 #endif
 
 	/* Revalidate parent directory attribute cache */
-	cfs_revalidate_inode(dir);
+	(void) cfs_revalidate_inode(dir);
 
 	/* Force a full look up iff the parent directory has changed */
 	if (cfs_check_verifier(dir, dentry)) {
-#ifdef CFS_FILE_RW_NOLOCK
+//#ifdef CFS_FILE_RW_NOLOCK
 		int isopen = (nd && !(nd->flags & LOOKUP_CONTINUE)
 				      && (nd->flags & LOOKUP_OPEN));
 
 		if (cfs_lookup_verify_inode(inode, isopen))
 			goto out_zap_parent;
-#endif
+//#endif
 		goto out_valid;
 	}
 #ifdef CFS_FILE_RW_NOLOCK
@@ -803,16 +831,16 @@
 out_valid:
 	if (lock)
 		cfstok_relse(dir, CFSTOK_ATTR, CFSTOK_READ, NON_RANGE);
-#ifdef SSI_EXNFS_XXX
+#ifdef SSI_CFS_SKIP
 	unlock_kernel();
 #endif
 	dput(parent);
 	return 1;
 #ifdef CFS_ZAP_CACHES
-#ifdef CFS_FILE_RW_NOLOCK
+//#ifdef CFS_FILE_RW_NOLOCK
 out_zap_parent:
 	cfs_zap_caches(dir);
-#endif
+//#endif
 out_bad:
 	CFS_CACHEINV(dir, lock);
 #else
@@ -830,7 +858,7 @@
 	d_drop(dentry);
 	if (lock)
 		cfstok_relse(dir, CFSTOK_ATTR, CFSTOK_READ, NON_RANGE);
-#ifdef SSI_EXNFS_XXX
+#ifdef SSI_CFS_SKIP
 	unlock_kernel();
 #endif
 	dput(parent);
@@ -917,7 +945,17 @@
 
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+		res = ERR_PTR(-EINTR);
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		goto out;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	if ((error = _cfs_permission(dir, MAY_EXEC))) {
 		res = ERR_PTR(error);
@@ -925,7 +963,7 @@
 	}
 #ifdef CFS_ZAP_CACHES
         /* Revalidate parent directory attribute cache */
-        cfs_revalidate_inode(dir);
+        (void) cfs_revalidate_inode(dir);
 #endif
 
 #ifdef SSI_EXNFS_XXX
@@ -985,7 +1023,16 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1036,7 +1083,16 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1085,7 +1141,16 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1159,6 +1224,11 @@
 	 */
 	cfs_begin_data_update(dir);
 	error = CFS_PROTO(dir)->rmdir(dir, &dentry->d_name, ip);
+#ifdef SSI_CFS_SKIP
+	/* Ensure the VFS deletes this inode */
+	if (error == 0 && dentry->d_inode != NULL)
+		dentry->d_inode->i_nlink = 0;
+#endif
 	cfs_end_data_update(dir);
 
 fail_tokrelse:
@@ -1214,6 +1284,11 @@
 	cfs_begin_data_update(dir);
 	cfs_begin_data_update(inode);
 	error = CFS_PROTO(dir)->remove(dir, &dentry->d_name, inode);
+#ifdef SSI_CFS_SKIP
+	/* The VFS may want to delete this inode */
+	if (error == 0)
+		inode->i_nlink--;
+#endif
 	cfs_end_data_update(inode);
 	cfs_end_data_update(dir);
 	if (!error)
@@ -1222,11 +1297,13 @@
 fail_tokrelse:
 	cfstok_relse_list(&held);
 
+#ifdef SSI_CFS_SKIP
 	/* Flush Async writes */
 	/* SSI_XXX: Do cfs_onlyme() check here, to avoid writes? */
 	if (!error)
 		/* Still need? done in ->delete_inode */
 		(void)cfs_wb_all(inode);
+#endif
 
 fail:
 	return error;
@@ -1248,7 +1325,7 @@
 	/* Leave room for a termination byte */
 	/* SSI_XXX: Really needs to be as large as largest physical fs's */
 	if (strlen(symname) > maxlen - 1)
-		goto out;
+		return error;
 
 #ifdef SSI_CFSTOK_SU
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_SU,
@@ -1257,7 +1334,16 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_EXCL,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1283,7 +1369,6 @@
 #else
 	cfstok_relse(dir, CFSTOK_ATTR, CFSTOK_EXCL, NON_RANGE);
 #endif
-out:
 	return error;
 }
 
@@ -1600,7 +1685,16 @@
 	 */
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	//(void)cfs_revalidate_inode(inode, 1);
 	error = _cfs_permission(inode, mask);

Index: cfstok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfstok.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- cfstok.c	10 Oct 2008 08:10:31 -0000	1.19
+++ cfstok.c	3 Feb 2009 06:18:12 -0000	1.20
@@ -110,11 +110,15 @@
 STATIC void cfstok_queryfunc(object_t *objp, int oldmode, int newmode,
 	range_off_t start, range_off_t len);
 #endif
-STATIC struct ctokhold *checklist( object_t *objp, struct ctokhold **hlist,
+STATIC struct ctokhold *checklist( object_t *objp, hold_list_t *hlist,
 	struct cfstok  *cfstokinfo);
-STATIC struct ctokhold *instholdlist( struct ctokhold **hlist,
+STATIC struct ctokhold *instholdlist( hold_list_t *hlist,
 	struct cfstok *cfstokinfo, struct ctokhold *entry, int where);
+#ifdef CFSTOKHOLD_LINUX_LIST
+STATIC void delholdlist(struct ctokhold *entry);
+#else
 STATIC void delholdlist(struct ctokhold **hlist, struct ctokhold *entry);
+#endif
 
 extern tokseq_t *cfs_tsp;
 
@@ -223,7 +227,7 @@
 	struct	inode	*ip)
 {
 	int	which;
-	struct	ctokhold 	**list;
+	hold_list_t *list;
 	object_t obj;
 
 	obj.word1 = (long)ip;
@@ -237,7 +241,11 @@
 		 * Initialize HOLD list
 		 */
 		list = ITOHDLIST(ip, which);
+#ifdef CFSTOKHOLD_LINUX_LIST
+		INIT_LIST_HEAD(list);
+#else
 		*list = (struct ctokhold *)NULL;
+#endif
 
 		obj.word2 = which;
 #ifdef SSI_RANGE_TOKENS
@@ -253,7 +261,7 @@
 cfstok_destroy(struct inode *ip)
 {
 	int	which;
-	struct	ctokhold 	**list;
+	hold_list_t *list;
 	object_t obj;
 
 	obj.word1 = (long)ip;
@@ -264,7 +272,11 @@
 	for (which = 1; which < CFSTOK_NTOKS + 1; which++) {
 
 		list = ITOHDLIST( ip, which);
+#ifdef CFSTOKHOLD_LINUX_LIST
+		SSI_ASSERT(list_empty(list));
+#else
 		SSI_ASSERT(*list == NULL);
+#endif
 
 		obj.word2 = (long)which;
 
@@ -277,6 +289,7 @@
 	}
 }
 
+#ifdef SSI_NOTUSED
 //enum cfstok_res
 cfstok_res_t
 cfstok_req_set(
@@ -315,6 +328,7 @@
 	}
 	return	CFSTOK_HELD;
 }
+#endif /* SSI_NOTUSED */
 
 /*
  * cfstok_req: hold tokens
@@ -344,9 +358,9 @@
 	int	flags,
 	range_off_t	start,
 	range_off_t	len,
-	struct	ctokhold **phlist)  /* addr of ptr to proc's holdlist */
+	hold_list_t *phlist)  /* addr of ptr to proc's holdlist */
 {
-	struct	ctokhold	**hlist;/* addr of ptr to holdlist on cnode */
+	hold_list_t *hlist;/* addr of ptr to holdlist on cnode */
 	struct	ctokhold	*entry=(struct ctokhold *)NULL;
 	struct	cfstok		ctok;
 	object_t obj;
@@ -374,8 +388,6 @@
 		len = MAXLEN;
 	}
 
-	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
-
 	/*
 	 * Check for illegal combinations
 	 */
@@ -398,6 +410,8 @@
 	obj.word2 = (long)which_tok;
 	obj.obj_pp = &cliparam;
 
+	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
+
 	if (flags & CFSTOK_HOLD) {
 
 		if ((entry = (struct ctokhold  *)checklist(&obj, hlist, &ctok))) {
@@ -411,8 +425,8 @@
 			 * Add the new entry to begining of caller's
 			 * hold list.
 			 */
-			if( phlist != (struct ctokhold **)NULL)
-				instholdlist( phlist, &ctok, NULL, INS_START);
+			if (phlist)
+				(void) instholdlist( phlist, &ctok, NULL, INS_START);
 			ret = CFSTOK_HELD;
 			goto unlock;
 		}
@@ -451,12 +465,12 @@
 			/*
 			 * Add to the front of caller's holdlist
 			 */
-			if( phlist != (struct ctokhold **)NULL)
-				instholdlist( phlist, &ctok, NULL, INS_START);
+			if (phlist)
+				(void) instholdlist( phlist, &ctok, NULL, INS_START);
 			/*
 			 * Add to the end of inode hold list
 			 */
-			instholdlist(hlist, &ctok, NULL, INS_END);
+			(void) instholdlist(hlist, &ctok, NULL, INS_END);
 			ret = CFSTOK_HELD;
 		} else {
 			ret = CFSTOK_WOULDBLOCK;
@@ -489,7 +503,11 @@
 		 * indicate that this process has the
 		 * token.
 		 */
-		instholdlist( hlist, &ctok, NULL, INS_END);
+#ifdef CFSTOK_INTR
+		entry = instholdlist( hlist, &ctok, NULL, INS_END);
+#else
+		(void) instholdlist( hlist, &ctok, NULL, INS_END);
+#endif
 		CFSTOK_XRELE(itoc(ip));
 #ifdef SSI_NOTYET
 		if (flags & CFSTOK_CXUNLOCK)
@@ -504,21 +522,32 @@
 			tok_wait_range(waitcookie);
 		else
 #endif
+#ifdef CFSTOK_INTR
+			if (tok_wait(waitcookie)) {
+				/* Interrupted */
+				CFSTOK_XLOCK( itoc(ip));
+				BUG_ON(list_empty(&entry->ctok_list));
+				delholdlist(entry);
+				ret = CFSTOK_WOULDBLOCK;
+				goto unlock;
+			}
+#else
 			tok_wait( ITOTCB(ip, which_tok),
 				waitcookie );
+#endif /* !CFSTOK_INTR */
 #ifdef SSI_NOTYET
 		if (flags & CFSTOK_CXUNLOCK)
 			CXLOCK(cp);
 #endif
 		ret = CFSTOK_HELD;
 		if (phlist)
-			instholdlist( phlist, &ctok, NULL, INS_START);
+			(void) instholdlist( phlist, &ctok, NULL, INS_START);
 		goto no_unlock;
 	} else {
 		ret = CFSTOK_HELD;
-		instholdlist( hlist, &ctok, NULL, INS_END);
+		(void) instholdlist( hlist, &ctok, NULL, INS_END);
 		if (phlist)
-			instholdlist( phlist, &ctok, NULL, INS_START);
+			(void) instholdlist( phlist, &ctok, NULL, INS_START);
 		goto unlock;
 	}
 
@@ -545,8 +574,10 @@
  */
 
 int
-cfstok_req_m(int num_lock, cfs_lockop_t * ops,
-	struct	ctokhold **phlist)
+cfstok_req_m(
+	int num_lock,
+	cfs_lockop_t * ops,
+	hold_list_t *phlist)
 {
 	cfs_lockop_t *point[num_lock], *tmp;
 	int x;
@@ -598,11 +629,25 @@
 		status = cfstok_req(point[x]->lo_ip, point[x]->lo_which,
 			       	point[x]->lo_mode, CFSTOK_HOLD|CFSTOK_BLOCK,
 				NON_RANGE, phlist);
+#ifdef CFSTOK_INTR
+		if (status != CFSTOK_HELD)
+			break;
+#else
 		SSI_ASSERT(status == CFSTOK_HELD);
+#endif
 	}
 
-#ifdef SSI_XXX_CFS_NEED_ERROR_HANDLING
 	/* On error unlock the locks that we did hold */
+#ifdef CFSTOK_INTR
+	if (x < num_lock) {
+		cfstok_relse_list(phlist);
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return -EINTR;
+	}
+#else
+#ifdef SSI_XXX_CFS_NEED_ERROR_HANDLING
 	/* SSI_XXX: To really make this work need to release phlist stuff */
 	if (x < num_lock) {
 		int y;
@@ -611,6 +656,7 @@
 					point[y]->mode, NON_RANGE);
 	}
 #endif
+#endif /* !CFSTOK_INTR */
 
 	return error;
 }
@@ -645,14 +691,12 @@
 	int flags,
 	int delay)
 {
-	struct	ctokhold	**hlist;
+	hold_list_t *hlist;
 	struct	ctokhold	*retlist=(struct ctokhold *)NULL;
 	struct  cfstok		tokinfo;
 	object_t obj;
 	int ret;
 
-	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
-
 	hlist = ITOHDLIST( ip, which);
 
 	tokinfo.which = which;
@@ -668,6 +712,8 @@
 	obj.word2 = (long)which;
 	obj.obj_pp = &cliparam;
 
+	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
+
 	if ((retlist = (struct ctokhold *)checklist(&obj, hlist, &tokinfo)) !=NULL){
 
 		if ( retlist->ctok.held_count > 1 ){
@@ -709,7 +755,11 @@
 		 /*
 		  * delete from inode's hold list
 		  */
+#ifdef CFSTOKHOLD_LINUX_LIST
+		delholdlist(retlist);
+#else
 		delholdlist( hlist, retlist);
+#endif
 
 		CFSTOK_XRELE(itoc(ip));
 		process_msgs(FALSE);
@@ -720,27 +770,25 @@
 	panic( "cfstok_relsex: No hold found");
 }
 
-void
-cfstok_relse_list(
-	struct	ctokhold	**usrlist)
-{
-	cfstok_relse_listx(usrlist, 0, 0);
-}
-
-void
+static inline void
 cfstok_relse_listx(
-	struct	ctokhold	**usrlist,
+	hold_list_t *usrlist,
 	int flags,
 	int delay)
 {
 	struct	ctokhold	*rellist;
+#ifdef CFSTOKHOLD_LINUX_LIST
+	struct	ctokhold	*tmp;
 
+	list_for_each_entry_safe(rellist, tmp, usrlist, ctok_list) {
+#else
 	if ((*usrlist) == NULL)
 		return;
 
 	while(*usrlist) {
 
 		rellist = *usrlist;
+#endif /* !CFSTOKHOLD_LINUX_LIST */
 		cfstok_relsex( rellist->ctok.ip, rellist->ctok.which,
 		    rellist->ctok.mode, rellist->ctok.start,
 		    LEN(rellist->ctok), flags, delay );
@@ -748,10 +796,19 @@
 		/*
 		 * delete this list element from user list
 		 */
-
+#ifdef CFSTOKHOLD_LINUX_LIST
+		delholdlist(rellist);
+#else
 		delholdlist( usrlist, rellist);
+#endif
 	}
+}
 
+void
+cfstok_relse_list(
+	hold_list_t *usrlist)
+{
+	cfstok_relse_listx(usrlist, 0, 0);
 }
 
 void
@@ -773,7 +830,7 @@
 {
 
 	int	check;
-	struct	ctokhold	**hlist;
+	hold_list_t *hlist;
 	struct	ctokhold	*lastlist;
 	struct	ctokhold	*walklist;
 	struct	ctokhold	*tlist;
@@ -783,6 +840,15 @@
  	 */
 	for( check = ctok->which + 1; check < CFSTOK_NTOKS; check++){
 		hlist = ITOHDLIST( ip, ctok->which);
+#ifdef CFSTOKHOLD_LINUX_LIST
+		/*
+		 * check for matching pids i.e other
+		 * process may hold
+		 */
+		list_for_each_entry(walklist, hlist, ctok_list)
+			if ( walklist->ctok.unique == NSC_UNIQUE_ID )
+				return CFSTOK_EOUTORDER;
+#else
 		if ( *hlist != NULL) {
 			/*
 			 * check for matching pids i.e other
@@ -795,6 +861,7 @@
 				walklist = walklist->next;
 			}
 		}
+#endif /* !CFSTOKHOLD_LINUX_LIST */
 	}
 
 	/*
@@ -813,7 +880,11 @@
 
 	hlist = ITOHDLIST(ip, ctok->which);
 	lastlist = NULL;
+#ifdef CFSTOKHOLD_LINUX_LIST
+	list_for_each_entry(tlist, hlist, ctok_list)
+#else
 	for (tlist = *hlist ; tlist != NULL ; tlist = tlist->next)
+#endif
 		if (tlist->ctok.unique == NSC_UNIQUE_ID )
 			lastlist = tlist;
 
@@ -836,12 +907,16 @@
 STATIC struct	ctokhold *
 checklist(
 	object_t *objp,
-	struct ctokhold **hlist,	/* where to search */
+	hold_list_t *hlist,	/* where to search */
 	struct cfstok  *cfstokinfo)	/* search from this information */
 {
 	register struct ctokhold *foundptr;
 
+#ifdef CFSTOKHOLD_LINUX_LIST
+	list_for_each_entry(foundptr, hlist, ctok_list) {
+#else
 	for (foundptr = *hlist; foundptr !=NULL ; foundptr = foundptr->next) {
+#endif
 
 		SSI_ASSERT(foundptr->ctok.which == cfstokinfo->which);
 
@@ -865,9 +940,22 @@
 	return (struct	ctokhold *)NULL;
 }
 
+#ifdef CFSTOK_KMEM_CACHE
+STATIC kmem_cache_t *ctokhold_cachep;
+
+void
+cfstokhold_init(void)
+{
+	ctokhold_cachep = kmem_cache_create("cfstok_cache",
+				sizeof(struct ctokhold), 0,
+				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+				NULL, NULL);
+}
+#else
 STATIC struct ctokhold *ctokhold_free = NULL;
 STATIC int ctokhold_free_count = 0;
 SPIN_LOCK_T ctokhold_free_lock;
+#endif
 
 
 /*
@@ -883,15 +971,21 @@
 
 STATIC struct ctokhold *
 instholdlist(
-	struct	ctokhold	**hlist,
+	hold_list_t *hlist,
 	struct	cfstok		*cfstokinfo,
 	struct	ctokhold	*entry,
 	int	where)
 {
 	register struct ctokhold *inst;
+#ifndef CFSTOKHOLD_LINUX_LIST
 	register struct ctokhold *endlist=(struct ctokhold *)NULL;
 	register struct ctokhold *tmplist=(struct ctokhold *)NULL;
+#endif
 
+#ifdef CFSTOK_KMEM_CACHE
+	inst = kmem_cache_alloc(ctokhold_cachep, GFP_KERNEL|__GFP_NOFAIL);
+	memset(inst, 0, sizeof(struct ctokhold));
+#else
 	LOCK_SPIN_LOCK(&ctokhold_free_lock);
 	if ((inst = ctokhold_free)) {
 		ctokhold_free = inst->next;
@@ -909,7 +1003,24 @@
 		}
 		memset(inst, 0, sizeof(struct ctokhold));
 	}
+#endif /* !CFSTOK_KMEM_CACHE */
+
+#ifdef CFSTOKHOLD_LINUX_LIST
+	INIT_LIST_HEAD(&inst->ctok_list);
+	inst->ctok = *((cfstok_t *)cfstokinfo);
 
+	switch (where) {
+	    case INS_START:
+		list_add(&inst->ctok_list, hlist);
+		break;
+	    case INS_END:
+		list_add_tail(&inst->ctok_list, hlist);
+		break;
+	    default:
+		list_add(&inst->ctok_list, &entry->ctok_list);
+		break;
+	}
+#else
 	inst->next = (struct ctokhold *)NULL;
 	inst->prev = (struct ctokhold *)NULL;
 
@@ -940,6 +1051,7 @@
 		entry->next = inst;
 		inst->prev = entry;
 	}
+#endif /* !CFSTOKHOLD_LINUX_LIST */
 
 	return (struct	ctokhold *)inst;
 }
@@ -951,23 +1063,36 @@
  */
 
 STATIC void
+#ifdef CFSTOKHOLD_LINUX_LIST
 delholdlist(
-	struct ctokhold  **hlist,
 	struct ctokhold  *entry)
+#else
+delholdlist(
+	hold_list_t *hlist,
+	struct ctokhold  *entry)
+#endif
 {
+#ifdef CFSTOKHOLD_LINUX_LIST
+	list_del_init(&entry->ctok_list);
+#else
 	if ( entry->prev != NULL)
 		entry->prev->next = entry->next;
 	else
 		*hlist = entry->next;
 	if ( entry->next != NULL)
 		entry->next->prev = entry->prev;
+#endif
 
+#ifdef CFSTOK_KMEM_CACHE
+	kmem_cache_free(ctokhold_cachep, entry);
+#else
 	/* Free entry */
 	LOCK_SPIN_LOCK(&ctokhold_free_lock);
 	entry->next = ctokhold_free;
 	ctokhold_free = entry;
 	ctokhold_free_count++;
 	UNLOCK_SPIN_LOCK(&ctokhold_free_lock);
+#endif
 }
 
 /*
@@ -1209,7 +1334,7 @@
 cfstok_giveback(
 	struct	inode	*ip)
 {
-	struct	ctokhold 	**list;
+	hold_list_t *list;
 	agent_t agent;
 	int which;
 	int ret;
@@ -1264,7 +1389,11 @@
 	for (which = CFSTOK_NTOKS; which > 0 ; which--) {
 
 		list = ITOHDLIST(ip, which);
+#ifdef CFSTOKHOLD_LINUX_LIST
+		SSI_ASSERT(list_empty(list));
+#else
 		SSI_ASSERT(*list == NULL);
+#endif
 
 		agent = this_node;
 		obj.word1 = (long)ip;
@@ -1587,9 +1716,6 @@
 			break;
 #endif
 		case CFSTOK_SR:
-#ifdef CFS_ZAP_CACHES
-			/* refresh will determine whether need revalidation */
-#else
 			/* SSI_XXX: It would be better if we could downgrade these
 			 * mappings to read-only until he does a write fault.
 			 * This is not possible in Linux without further modifications.
@@ -1600,13 +1726,9 @@
 #else
 			unmap_mapping_range(ip->i_mapping, 0, 0, 0);
 #endif /* !SSI_RANGE_TOKENS */
-#endif /* !CFS_ZAP_CACHES */
 			break;
 		case TOK_NOMODE:
 		case CFSTOK_NULL:
-#ifdef CFS_ZAP_CACHES
-			/* refresh will determine whether need revalidation */
-#else
 #ifdef SSI_RANGE_TOKENS
 			if (!len || (!start && len == MAXLEN))
 				goto nonrange;
@@ -1632,6 +1754,11 @@
 #endif
 nonrange:
 #endif /* SSI_RANGE_TOKENS */
+#ifdef CFS_ZAP_CACHES
+			LOCK_COND_LOCK(&itoc(ip)->c_statelock);
+			CFS_FLAGS(ip) |= CFS_INO_INVALID_ATTR | CFS_INO_INVALID_DATA;
+			UNLOCK_COND_LOCK(&itoc(ip)->c_statelock);
+#else
 			unmap_mapping_range(ip->i_mapping, 0, 0, 0);
 			filemap_write_and_wait(ip->i_mapping);
 			invalidate_inode_pages2(ip->i_mapping);
@@ -1866,19 +1993,28 @@
 	struct inode *ip,
 	svrhold_list_t *hlistp)
 {
+	object_t obj;
+#ifdef SVRHOLD_LIST_LINUX_LIST
+	hlist_t *item, *tmp;
+#else
 	hlist_t *item;
-	int i;
 	u_int count;
-	object_t obj;
+	int i;
 
 	count = hlist_count(hlistp);
+#endif
 
 	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
 
+#ifdef SVRHOLD_LIST_LINUX_LIST
+	list_for_each_entry_safe(item, tmp, hlistp, hl_list) {
+		list_del(&item->hl_list);
+#else
 	for (i = 0 ; i < count ; i++) {
 		item = hlist_extract(hlistp);
 		if (item == NULL)
 			panic("cfstok_install_list: Internal Error\n");
+#endif
 
 		SSI_ASSERT(item->hl_op == INSTALL);
 		SSI_ASSERT(item->hl_type != CFSTOK_MHOLD);
@@ -1948,10 +2084,23 @@
 	process_msgs(FALSE);
 }
 
+#ifdef CFSTOK_KMEM_CACHE
+STATIC kmem_cache_t *delrel_cachep;
+
+void
+cfs_delrel_init(void)
+{
+	delrel_cachep = kmem_cache_create("cfsdr_cache",
+				sizeof(struct delrel), 0,
+				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
+				NULL, NULL);
+}
+#else
 /* Delay Release Structure free list */
 STATIC struct delrel *dr_free = NULL;
 STATIC int dr_free_count = 0;
 SPIN_LOCK_T dr_free_lock;
+#endif
 
 /* List of Delay Releases needed to be processed by the CFS daemon */
 STATIC struct delrel *delrel_list = NULL;
@@ -1990,6 +2139,7 @@
 		while(delrel_list) {
 			/* Pull one from list */
 			drp = delrel_list;
+			mb();
 			delrel_list = drp->dr_next;
 
 			UNLOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
@@ -1999,12 +2149,16 @@
 				drp->dr_mode, drp->dr_start, drp->dr_len);
 
 			iput(drp->dr_ip);
+#ifdef CFSTOK_KMEM_CACHE
+			kmem_cache_free(delrel_cachep, drp);
+#else
 			/* Now can be put on free list */
 			LOCK_SPIN_LOCK(&dr_free_lock);
 			drp->dr_next = dr_free;
 			dr_free = drp;
 			dr_free_count++;
 			UNLOCK_SPIN_LOCK(&dr_free_lock);
+#endif
 
 			LOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
 		}
@@ -2026,6 +2180,7 @@
 	/* Put release on Daemons list */
 	LOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
 	drp->dr_next = delrel_list;
+	mb();
 	delrel_list = drp;
 	UNLOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
 
@@ -2078,6 +2233,10 @@
 {
 	struct delrel *drp;
 
+#ifdef CFSTOK_KMEM_CACHE
+	drp = kmem_cache_alloc(delrel_cachep, GFP_KERNEL|__GFP_NOFAIL);
+	memset(drp, 0, sizeof(struct delrel));
+#else
 	/* Get struct from free list if possible */
 	LOCK_SPIN_LOCK(&dr_free_lock);
 	if ((drp = dr_free)) {
@@ -2091,6 +2250,7 @@
 			panic("cfs_delrel_add: Out of memory");
 		memset(drp, 0, sizeof(struct delrel));
 	}
+#endif /* !CFSTOK_KMEM_CACHE */
 
 	/* Hold inode because we are referencing it here */
 	atomic_inc(&ip->i_count);
@@ -2446,6 +2606,7 @@
 	return waiters;
 } /* cfstok_waitcount() */
 
+#ifndef CFSTOK_KMEM_CACHE
 int
 cfstok_free_memory(int count, unsigned int gfp_mask)
 {
@@ -2516,3 +2677,4 @@
 	}
 	return dr_free_count;
 }
+#endif /* !CFSTOK_KMEM_CACHE */

Index: cfsproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfsproc.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- cfsproc.c	10 Oct 2008 08:10:31 -0000	1.28
+++ cfsproc.c	3 Feb 2009 06:18:12 -0000	1.29
@@ -121,8 +121,7 @@
 
 	filp->f_op    = fops_get(inode->i_fop);
 	atomic_set(&filp->f_count, 1);
-	dget(dentry);
-	filp->f_dentry = dentry;
+	filp->f_dentry = dget(dentry);
 	filp->f_vfsmnt = NULL;		/* SSI_XXX: Do I need something? */
 
 	filp->f_flags = O_RDONLY|O_LARGEFILE;
@@ -172,7 +171,9 @@
 	struct svrcfstok *hp;
 	svrhold_list_t new_hold_list;
 	__u32 *fh = (__u32 *)&(argp->cgia_fh);
+#ifndef CFS_FH_TO_DENTRY_ANON
 	struct super_block *sb = NULL;
+#endif
 
 	dprintk("nfsd: GETINODE  %s\n", SVCFH_fmt(&argp->cgia_fh));
 
@@ -242,6 +243,7 @@
 			cfserr = -ESTALE;
 			goto out;
 		}
+		/* SSI_XXX: Missing dput ? */
 #endif /* ! CFS_FH_TO_DENTRY_ANON */
 	}
 
@@ -265,8 +267,10 @@
 	resp->cdr_status = cfserr;
 	if (hp)
 		HASH_RELE(hp);
+#ifndef CFS_FH_TO_DENTRY_ANON
 	if (sb)
 		drop_super(sb);
+#endif
 }
 
 #ifdef CFS_REVALIDATE_GETATTR
@@ -439,6 +443,17 @@
  */
 int
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_READ
+rcfs_read(
+	clusternode_t node,
+	int *rval,
+	struct cfsreadargs *argp,
+	struct cfsrdresults **respp,
+	struct kvec **vec,
+	int *vlen,
+	char **buffpp,
+	int *buffer_len)
+#else
 rcfs_read(
 	clusternode_t node,
 	int *rval,
@@ -447,6 +462,7 @@
 	unsigned long *count,
 	struct kvec **vec,
 	int *vlen)
+#endif
 #else
 rcfs_read(
 	clusternode_t node,
@@ -455,17 +471,20 @@
 	struct cfsrdresults **respp,
 	char **buffpp,
 	int *buffer_len)
-#endif
+#endif /* !CFS_PAGEVEC */
 {
 	int	cfserr;
 	struct svrcfstok *hp;
 	struct cfsrdresults *resp;
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
 	unsigned long mycount = *count;
 	struct kvec *__vec;
 	int i;
+#ifdef CFS_PAGEVEC_PAGE_ORDER
+	unsigned int order;
+#endif
 #define LAST_VEC_LEN(x) \
-	(((x - 1) & ~PAGE_CACHE_MASK) + 1)
+	(((x - 1) & ~PAGE_MASK) + 1)
 #else
 	unsigned long mycount = *buffer_len;
 	char *buffer;
@@ -480,7 +499,7 @@
 		BUG();
 #endif
 
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
 #ifdef CFS_PARANOIA
 	SSI_ASSERT(*vlen <= CFS_READ_MAXIOV);
 #endif
@@ -488,14 +507,39 @@
 	*vec = __vec = kmalloc_nofail(*vlen * sizeof(struct kvec));
 
 	/* Setup kvec array */
+#ifdef CFS_PAGEVEC_PAGE_ORDER
+	for (order = 0; (PAGE_SIZE << order) < *count; order++)
+		;
+	/* SSI_XXX: Borrowing mycount to track unused pages */
+	mycount = __vec->iov_base =
+			(void *) __get_free_pages(GFP_KERNEL|__GFP_NOFAIL, order);
+	__vec->iov_len = PAGE_SIZE - argp->cra_pgbase;
+	__vec++;
+
+	for (i = 1; i < *vlen; __vec++, i++) {
+		mycount += PAGE_SIZE;
+		__vec->iov_base = mycount;
+		__vec->iov_len = PAGE_SIZE;
+	}
+	(__vec-1)->iov_len = LAST_VEC_LEN(*count + argp->cra_pgbase);
+
+	/* Dealloc unused pages */
+	for (mycount += PAGE_SIZE;
+	     mycount < (PAGE_SIZE << order);
+	     mycount += PAGE_SIZE) {
+		free_page(mycount);
+	}
+	mycount = *count;
+#else
 	__vec->iov_base = (void *) __get_free_page(GFP_KERNEL|__GFP_NOFAIL);
-	__vec->iov_len = PAGE_CACHE_SIZE - argp->cra_pgbase;
+	__vec->iov_len = PAGE_SIZE - argp->cra_pgbase;
 	__vec++;
 	for (i = 1; i < *vlen; __vec++, i++) {
 		__vec->iov_base = (void *) __get_free_page(GFP_KERNEL|__GFP_NOFAIL);
-		__vec->iov_len = PAGE_CACHE_SIZE;
+		__vec->iov_len = PAGE_SIZE;
 	}
 	(__vec-1)->iov_len = LAST_VEC_LEN(mycount + argp->cra_pgbase);
+#endif /* !CFS_PAGEVEC_PAGE_ORDER */
 
 	hp = fhtohp(&(argp->cra_fhandle));
 
@@ -512,8 +556,8 @@
 		int __vlen = *vlen;
 		int mycount_base = mycount + argp->cra_pgbase;
 
-		*vlen = (mycount) ? PAGE_CACHE_ALIGN(mycount_base)
-							>> PAGE_CACHE_SHIFT : 0;
+		*vlen = (mycount) ? PAGE_ALIGN(mycount_base)
+							>> PAGE_SHIFT : 0;
 		__vec = (struct kvec *)(*vec + *vlen);
 		if (*vlen)
 			(__vec-1)->iov_len = LAST_VEC_LEN(mycount_base);
@@ -533,7 +577,12 @@
 	*buffpp = buffer = kmalloc_nofail(mycount); //kzmalloc_nofail(mycount);
 
 	hp = fhtohp(&(argp->cra_fhandle));
+#ifdef CFS_PAGEVEC_BUFFER_READ
+	*vec = NULL, *vlen = 0;
+	cfserr = cfsd_read(hp, argp->cra_offset, *vec, *vlen, buffer, &mycount);
+#else
 	cfserr = cfsd_read(hp, argp->cra_offset, buffer, &mycount);
+#endif
 
 	*respp = resp = kmalloc_nofail(sizeof(*resp));
 
@@ -542,7 +591,7 @@
 		/* For simple disk filesystem (ext2) this doesn't fail */
 		cfserr = cfsd_getattr(hp, &(resp->crr_attr));
 	}
-#endif /* ! CFS_PAGEVEC */
+#endif /* !( CFS_PAGEVEC && !CFS_PAGEVEC_BUFFER_READ ) */
 	HASH_RELE(hp);
 	resp->crr_status = cfserr;
 	*rval = 0;
@@ -567,6 +616,17 @@
  */
 int
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+rcfs_write(
+	clusternode_t node,
+	int	*rval,
+	struct cfswriteargs *argp,
+	struct cfswriteres	**resp_p,
+	struct kvec **kvec,
+	int vlen,
+	char *buffer,
+	int buffer_len)
+#else
 rcfs_write(
 	clusternode_t node,
 	int	*rval,
@@ -575,6 +635,7 @@
 	unsigned long count,
 	struct kvec **kvec,
 	int vlen)
+#endif
 #else
 rcfs_write(
 	clusternode_t node,
@@ -583,29 +644,41 @@
 	struct cfswriteres	**resp_p,
 	char *buffer,
 	int buffer_len)
-#endif
+#endif /* !CFS_PAGEVEC */
 {
 	int	cfserr;
 	struct svrcfstok *hp;
 	struct cfswriteres *resp;
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+	dprintk("cfsd: WRITE    %s %u bytes at %Ld vlen=%d\n",
+		SVCFH_fmt(&argp->cwa_fhandle),
+		buffer_len, (long long)argp->cwa_offset, vlen);
+#else
 	dprintk("cfsd: WRITE    %s %lu bytes at %Ld vlen=%d\n",
 		SVCFH_fmt(&argp->cwa_fhandle),
 		count, (long long)argp->cwa_offset, vlen);
+#endif
 #else
 	dprintk("cfsd: WRITE    %s %d bytes at %Ld\n",
 		SVCFH_fmt(&argp->cwa_fhandle),
 		buffer_len, (long long)argp->cwa_offset);
-#endif
+#endif /* !CFS_PAGEVEC */
 
 	hp = fhtohp(&(argp->cwa_fhandle));
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+	SSI_ASSERT(!vlen);
+	cfserr = cfsd_write(hp, argp->cwa_offset, *kvec, vlen,
+			buffer, (unsigned long) buffer_len, argp->cwa_stable);
+#else
 	cfserr = cfsd_write(hp, argp->cwa_offset, *kvec, vlen, count,
 		argp->cwa_stable);
+#endif
 #else
 	cfserr = cfsd_write(hp, argp->cwa_offset, buffer, buffer_len,
 		argp->cwa_stable);
-#endif
+#endif /* !CFS_PAGEVEC */
 	*resp_p = resp = kmalloc_nofail(sizeof(cfswriteres));
 
 	if (!cfserr) {
@@ -1588,8 +1661,7 @@
 			 */
 			if (ip == pfs_sb->s_root->d_inode) {
 				iput(ip);
-				dp = pfs_sb->s_root;
-				dget(dp);
+				dp = dget(pfs_sb->s_root);
 			} else
 				dp = d_alloc_root(ip);
 #ifdef CFS_DECODE_FH
@@ -1615,7 +1687,7 @@
 		 args->chr_ropncnt, args->chr_wopncnt);
 #endif
 
-	svrtok_relse(hp);
+	HASH_RELE(hp);
 out:
 	*statusp = error;
 	return;
@@ -1638,14 +1710,6 @@
 	dentry = hp->sct_dp;
 	SSI_ASSERT(dentry);
 
-#ifndef CFS_MIRROR_LOCK_WAIT
-	/* SSI_XXX: Mirror locks need to be ordered.
-	 *	Should embed lock in range token.
-	 *		-Roger
-	 */
-	CXLOCK(itoc(inode));
-#endif
-
 	error = -ENOLCK;
 	/* SSI_XXX: Why not just have this on the stack? */
 	fl = (struct file_lock *) kmalloc(sizeof(*fl), GFP_KERNEL);
@@ -1679,9 +1743,6 @@
 out:
 	kfree(fl);
 	*statusp = error;
-#ifndef CFS_MIRROR_LOCK_WAIT
-	CXUNLOCK(itoc(inode));
-#endif
 
 	HASH_RELE(hp);
 }
@@ -1851,7 +1912,7 @@
 	/* SSI_XXX: Not using sa_datasync at this point */
 	cfsd_sync_dir(hp->sct_dp, args->sa_datasync);
 
-	svrtok_relse(hp);
+	HASH_RELE(hp);
 out:
 	*statusp = error;
 	return;

Index: symlink.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/symlink.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- symlink.c	10 Oct 2008 08:10:32 -0000	1.10
+++ symlink.c	3 Feb 2009 06:18:12 -0000	1.11
@@ -181,7 +181,16 @@
 
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, 0, 0, NULL);
+#ifdef CFSTOK_INTR
+	if (result != CFSTOK_HELD) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
+#endif
+		return ERR_PTR(-EINTR);
+	}
+#else
 	SSI_ASSERT(result == CFSTOK_HELD);
+#endif
 
 	/* SSI_XXX: Mark ATIME here */
 

Index: proc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/proc.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- proc.c	10 Oct 2008 08:10:32 -0000	1.18
+++ proc.c	3 Feb 2009 06:18:12 -0000	1.19
@@ -47,22 +47,75 @@
 #include <cluster/assert.h>
 
 #ifdef CFS_PAGEVEC
-#define CFS_PAGEVEC_MAP(_data, _kvec, _vlen)				\
-	{								\
+#if defined(CFS_PAGEVEC_BUFFER_READ) || defined(CFS_PAGEVEC_BUFFER_WRITE)
+#define CFS_PAGEVEC_MAP_BUFFER(_data, _buf, _iswrite) do {		\
+	if (_data->page) {						\
+		_buf = kmap(_data->page) + _data->pgbase; 		\
+		break;							\
+	}								\
+	_buf = kmalloc(_data->count, GFP_NOFS|__GFP_NOFAIL); 		\
+	if (_iswrite) {							\
+		struct list_head *pos;					\
+		caddr_t _iov_base, _buffer = _buf;			\
+									\
+		list_for_each(pos, &_data->pages) {			\
+			struct cfs_page *req = cfs_list_entry(pos); 	\
+									\
+			_iov_base = kmap(req->wb_page) + req->wb_offset; \
+			memcpy(_buffer, _iov_base, req->wb_bytes); 	\
+			kunmap(req->wb_page);				\
+			_buffer += req->wb_bytes;			\
+		}							\
+	}								\
+} while (0)
+
+#define CFS_PAGEVEC_UNMAP_BUFFER(_data, _buf, _read) do {		\
+	if (_data->page) {						\
+		kunmap(_data->page);					\
+		break;							\
+	} else if (_read > 0) {						\
 		struct list_head *pos;					\
+		caddr_t _buffer = _buf;					\
+		ssize_t _count = _read;					\
+									\
+		/* Take care of truncated reads too */			\
+		list_for_each(pos, &_data->pages) {			\
+			struct cfs_page *req = cfs_list_entry(pos); 	\
+			caddr_t _iov_base;				\
+									\
+			_iov_base = kmap(req->wb_page) + req->wb_offset; \
+			if (_count < req->wb_bytes)			\
+				memcpy(_iov_base, _buffer, _count);	\
+			else						\
+				memcpy(_iov_base, _buffer, req->wb_bytes); \
+			kunmap(req->wb_page);				\
 									\
+			if (_count <= req->wb_bytes)			\
+				break;					\
+			_count -= req->wb_bytes;			\
+			_buffer += req->wb_bytes;			\
+		}							\
+	}								\
+	kfree(_buf);							\
+} while (0)
+#endif /* CFS_PAGEVEC_BUFFER_READ || CFS_PAGEVEC_BUFFER_WRITE */
+
+#define CFS_PAGEVEC_MAP(_data, _kvec, _vlen)				\
+	do {								\
 		if (unlikely(_data->page)) {				\
 			_vlen = 1;					\
-			_kvec = kmalloc_nofail(sizeof(struct kvec)); 	\
+			_kvec = kmalloc(sizeof(struct kvec), GFP_NOFS|__GFP_NOFAIL); \
 									\
 			_kvec->iov_base = kmap(_data->page) + _data->pgbase; \
 			_kvec->iov_len = _data->count;			\
 		} else {						\
+			struct list_head *pos;				\
 			struct kvec *__kvec;				\
 									\
+			_vlen = 0;					\
 			list_for_each(pos, &_data->pages) _vlen++;	\
 									\
-			__kvec = _kvec = kmalloc_nofail(sizeof(struct kvec) * _vlen); \
+			__kvec = _kvec = kmalloc(sizeof(struct kvec) * _vlen, GFP_NOFS|__GFP_NOFAIL); \
 									\
 			list_for_each(pos, &_data->pages) {		\
 				struct cfs_page *req = cfs_list_entry(pos); \
@@ -72,10 +125,10 @@
 				__kvec++;				\
 			}						\
 		}							\
-	}
+	} while (0)
 
 #define CFS_PAGEVEC_UNMAP(_data, _kvec)					\
-	{								\
+	do {								\
 		if (unlikely(_data->page)) {				\
 			kunmap(_data->page);				\
 		} else {						\
@@ -86,7 +139,7 @@
 			}						\
 		}							\
 		kfree(_kvec);						\
-	}
+	} while (0)
 #endif
 
 
@@ -111,6 +164,11 @@
 	if (status)
 		goto sb_error_check;
 
+#ifdef CFS_FH_TO_DENTRY_ANON
+	/* Overwrite possible stale ssidev */
+	((__u32 *)fhandle)[0] = server->mi_sb->s_ssidev;
+#endif
+
 	if (CFS_AT_SERVER_MIP(server)) {
 #ifdef CFS_FH_TO_DENTRY_ANON
 		struct svrcfstok *hp;
@@ -166,7 +224,7 @@
 		dentry->d_flags |= DCACHE_DISCONNECTED;
 found:
 		hp = makehp(NULL, server->mi_sb->s_ssidev, dentry);
-		dput(dentry); /* BUG: extra dput ?    -Roger */
+		dput(dentry);
 #endif /* ! CFS_FH_TO_DENTRY_ANON */
 
 		*ipp = __cfs_hpget(server->mi_sb, hp, *ipp);
@@ -448,10 +506,13 @@
 	int			status;
 #ifdef CFS_PAGEVEC
 	struct kvec *kvec;
-	int vlen = 0;
-	char async = (data->flags & RPC_TASK_ASYNC);
+#ifdef CFS_PAGEVEC_BUFFER_READ
+	caddr_t buffer;
+	loff_t offset = data->offset;
+#endif
 	cfs_mntinfo_t *mip = itocmi(data->inode);
 	struct inode *inode = data->inode;
+	int vlen, async = (data->flags & RPC_TASK_ASYNC);
 #else
 	cfs_mntinfo_t *mip = itocmi(inode);
 #endif
@@ -468,7 +529,7 @@
 	if (status)
 		goto sb_error_check;
 
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
 	CFS_PAGEVEC_MAP(data, kvec, vlen);
 #endif
 
@@ -477,7 +538,14 @@
 		unsigned long mycount = data->count;
 
 		/* SSI_XXX: Maximum ssize_t byte chunks */
+#ifdef CFS_PAGEVEC_BUFFER_READ
+		buffer = NULL;
+		CFS_PAGEVEC_MAP(data, kvec, vlen);
+		status = cfsd_read(itoc(inode)->c_hp, data->offset, kvec, vlen, buffer, &mycount);
+		CFS_PAGEVEC_UNMAP(data, kvec);
+#else
 		status = cfsd_read(itoc(inode)->c_hp, data->offset, kvec, vlen, &mycount);
+#endif
 		if (status == 0) {
 			data->res_count = mycount;
 #else
@@ -500,13 +568,17 @@
 		struct cfsrdresults *res_p = NULL;
 		int rval;
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_READ
+		int mycount = data->count;
+#else
 		unsigned long mycount = data->count;
+#endif
 #else
 		int mycount = count;
 #endif
 
 		args.cra_fhandle = *itocfh(inode);
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
 		args.cra_offset = data->offset;
 		args.cra_pgbase = data->pgbase;
 
@@ -515,26 +587,44 @@
 #else
 		args.cra_offset = offset;
 
+#ifdef CFS_PAGEVEC_BUFFER_READ
+		kvec = NULL, vlen = 0;
+		CFS_PAGEVEC_MAP_BUFFER(data, buffer, 0);
+		status = RCFS_READ(mip->mi_server, &rval,
+				   &args, &res_p, &kvec, &vlen,
+				   (char **)&buffer, &mycount);
+#else
 		status = RCFS_READ(mip->mi_server,&rval,
 				   &args, &res_p, (char **)&buffer,&mycount);
 #endif
+#endif
 
-		if (status != 0 || rval != 0)
+		if (status != 0 || rval != 0) {
+#ifdef CFS_PAGEVEC_BUFFER_READ
+			CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, 0);
+#endif
 			status = -ETIMEDOUT;
-		if (status == 0) {
+		} else if (status == 0) {
 			status = res_p->crr_status;
 			if (status == 0) {
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_READ
+				CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, (ssize_t)mycount);
+#endif
 				data->res_count = mycount;
 #endif
 				status = (ssize_t)mycount;
 				cfs_refresh_inode(inode, &(res_p->crr_attr));
 			}
+#ifdef CFS_PAGEVEC_BUFFER_READ
+			else
+				CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, 0);
+#endif
 			(void) xdr_free(xdr_cfsrdresults_p, &res_p);
 		}
 	}
 
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
 	CFS_PAGEVEC_UNMAP(data, kvec);
 #endif
 sb_error_check:
@@ -560,10 +650,12 @@
 	int			status;
 #ifdef CFS_PAGEVEC
 	struct kvec *kvec;
-	int vlen = 0;
-	char async = (data->flags & RPC_TASK_ASYNC);
 	cfs_mntinfo_t *mip = itocmi(data->inode);
 	struct inode *inode = data->inode;
+	int vlen, async = (data->flags & RPC_TASK_ASYNC);
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+	caddr_t buffer;
+#endif
 #else
 	cfs_mntinfo_t *mip = itocmi(inode);
 #endif
@@ -579,15 +671,23 @@
 	if (status)
 		goto sb_error_check;
 
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_WRITE)
 	CFS_PAGEVEC_MAP(data, kvec, vlen);
 #endif
 
 	if (CFS_AT_SERVER(inode)) {
 #ifdef CFS_PAGEVEC
 		/* SSI_XXX: per ssize_t byte chunk */
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+		buffer = NULL;
+		CFS_PAGEVEC_MAP(data, kvec, vlen);
+		status = cfsd_write(itoc(inode)->c_hp, data->offset, kvec, vlen,
+				    buffer, (unsigned long)data->count, data->stable);
+		CFS_PAGEVEC_UNMAP(data, kvec);
+#else
 		status = cfsd_write(itoc(inode)->c_hp, data->offset, kvec, vlen,
 				    (unsigned long)data->count, data->stable);
+#endif
 #else
 		status = cfsd_write(itoc(inode)->c_hp, offset, (char *)buffer,
 				    (unsigned long)count, stable);
@@ -610,17 +710,26 @@
 #ifdef CFS_PAGEVEC
 		args.cwa_offset = data->offset;
 		args.cwa_stable = data->stable;
+
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+		kvec = NULL, vlen = 0;
+		CFS_PAGEVEC_MAP_BUFFER(data, buffer, 1);
+		status = RCFS_WRITE(mip->mi_server, &rval, &args, &res_p,
+				    &kvec, vlen, buffer, (unsigned)data->count);
+		CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, 0);
+#else
 		status = RCFS_WRITE(mip->mi_server, &rval, &args, &res_p,
 				    (unsigned long)data->count, &kvec, vlen);
+#endif
 #else
 		args.cwa_offset = offset;
 		args.cwa_stable = stable;
 		status = RCFS_WRITE(mip->mi_server, &rval, &args, &res_p,
 				    buffer, count);
 #endif
-		if (status != 0 || rval != 0)
+		if (status != 0 || rval != 0) {
 			status = -ETIMEDOUT;
-		if (status == 0) {
+		} else if (status == 0) {
 			status = res_p->cwr_status;
 			if (status == 0)
 				cfs_refresh_inode(inode, &res_p->cwr_attr);
@@ -628,7 +737,7 @@
 		}
 	}
 
-#ifdef CFS_PAGEVEC
+#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_WRITE)
 	CFS_PAGEVEC_UNMAP(data, kvec);
 #endif
 sb_error_check:

Index: svrcfs.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/svrcfs.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- svrcfs.c	10 Oct 2008 08:10:32 -0000	1.17
+++ svrcfs.c	3 Feb 2009 06:18:12 -0000	1.18
@@ -29,6 +29,9 @@
 #include <linux/module.h>
 #include <linux/dcache.h>
 #include <linux/namei.h>
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+#include <linux/bootmem.h>
+#endif
 
 #include <cluster/icsgen.h>
 #include <cluster/nsc.h>
@@ -61,12 +64,31 @@
 #define	HASHSIZ		256
[...1248 lines suppressed...]
+#endif
+}
+
+#ifndef SVRCFS_KMEM_CACHE
 int
 svrhl_free_memory(int count, unsigned int gfp_mask)
 {
@@ -2568,6 +3026,7 @@
 			hlist_t_free_count -= chunk;
 			hlist_t_free = hlistp;
 			UNLOCK_SPIN_LOCK(&hlist_t_free_lock);
+			mb();
 			hlistp = startp;
 			for (; chunk > 0; chunk--) {
 				nextp = hlistp->hl_next;
@@ -2581,3 +3040,4 @@
 
 	return hlist_t_free_count;
 }
+#endif /* !SVRCFS_KMEM_CACHE */

Index: read.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/read.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- read.c	10 Oct 2008 08:10:32 -0000	1.19
+++ read.c	3 Feb 2009 06:18:12 -0000	1.20
@@ -337,7 +337,11 @@
 cfs_async_handler_read(
 	void *args)
 {
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+	struct cfs_read_data *data = (struct cfs_read_data *)args;
+#else
 	struct cfs_read_data *data = *(struct cfs_read_data **)args;
+#endif
 	int status; 
 #ifdef CFS_PAGEVEC
 	unsigned int count;
@@ -487,9 +491,21 @@
 	/* Must pass a cfs_read_data ** because we can't move a list_head
 	 * from one place to another, as cfs_async_queue() would.
 	 */
+#ifdef NSC_ASYNC_SLAB_NOFS__FLAG
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+	if ((status = nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_read,
+				      data, sizeof(*data),
+				      NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS))) {
+#else
+	if ((status = nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_read,
+				      &data, sizeof(data),
+				      NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS))) {
+#endif
+#else
 	if ((status = nsc_async_queue(nsc_async_cfs_queue, cfs_async_handler_read,
 				      &data, sizeof(struct cfs_read_data *),
 				      NSC_ASYNC_SLEEP))) {
+#endif
 
 		cfs_async_read_error(&data->pages);
 		cfs_readdata_free(data);
@@ -497,8 +513,12 @@
 	}
 #ifdef CFS_ASYNC_LOCAL_SYNC
 	} else
+#ifdef NSC_ASYNC_ARGS_ZERO_COPY
+		cfs_async_handler_read(data);
+#else
 		cfs_async_handler_read(&data);
 #endif
+#endif
 
 	return 0;
 out_bad:

Index: cfs_subr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_subr.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- cfs_subr.c	10 Oct 2008 08:10:31 -0000	1.23
+++ cfs_subr.c	3 Feb 2009 06:18:12 -0000	1.24
@@ -1054,7 +1054,9 @@
 		INIT_ATOMIC_INT(&mip->mi_sb_fsop_threads, 0);
 		INIT_INTR_CONDITION(&mip->mi_sb_state_cond);
 		INIT_INTR_CONDITION(&mip->mi_sb_down_cond);
+#ifdef SSI_CFS_SKIP
 		INIT_ATOMIC_INT(&mip->mi_svrcfstoks, 0);
+#endif
 #ifdef SSI_XXX_NOTUSED
 		INIT_LIST_HEAD(&mip->lru_read);
 		INIT_LIST_HEAD(&mip->lru_dirty);
@@ -1192,6 +1194,7 @@
 		/* Detach the cnode. */
 		LOCK_COND_LOCK(&cnode->c_statelock);
 		hp = cnode->c_hp;
+		mb();
 		cnode->c_hp = NULL;
 		UNLOCK_COND_LOCK(&cnode->c_statelock);
 		/* Free token structure. */
@@ -1604,6 +1607,7 @@
 	dev_t ssidev = ((__u32 *)fhp)[0];
 	struct super_block *sb;
 	struct dentry *dentry;
+	struct svrcfstok *hp;
 
 	sb = ssi_get_super(ssidev);
 	if (!sb)
@@ -1650,6 +1654,9 @@
 	}
 #endif
 
-	return (makehp(NULL, ssidev, dentry))? : ERR_PTR(-ESTALE);
+ 	hp = makehp(NULL, ssidev, dentry);
+ 	dput(dentry);
+
+ 	return hp ? : ERR_PTR(-ESTALE);
 }
 #endif

Index: vfs.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/vfs.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- vfs.c	10 Oct 2008 08:10:32 -0000	1.27
+++ vfs.c	3 Feb 2009 06:18:12 -0000	1.28
@@ -95,11 +95,11 @@
 		goto nolockout;
 	}
 
-	/* Lookup the name, but don't follow links */
 	down(&(dparent->d_inode->i_sem));
+	/* Lookup the name, but don't follow links */
 	dentry = lookup_hash(name, dparent);
-	err = PTR_ERR(dentry);
 	if (IS_ERR(dentry)) {
+		err = PTR_ERR(dentry);
 		goto out;
 	}
 	/*
@@ -154,9 +154,8 @@
 		locked = TRUE;
 	}
 	dentry = lookup_hash(name, dparent);
-	err = PTR_ERR(dentry);
 	if (IS_ERR(dentry)) {
-		*hpp = (struct svrcfstok *)NULL;
+		err = PTR_ERR(dentry);
 		goto out;
 	}
 	/*
@@ -236,9 +235,6 @@
 
 	inode = hp->sct_ip;
 
-	SSI_ASSERT(inode);
-	SSI_ASSERT(hp->sct_dp && hp->sct_dp->d_inode);
-
 #ifdef CFSD_PARANOIA
 	if (inode == NULL) {
 		dprintk("cfsd: getattr %p: NO INODE\n", hp);
@@ -246,10 +242,13 @@
 	}
 
 	/* Paranoid check */
-	if (hp->sct_dp == NULL) {
+	if (S_ISDIR(inode->i_mode) && hp->sct_dp == NULL) {
 		dprintk("WARNING: cfsd: getattr %p: NO DENTRY!\n", hp);
 		return -EINVAL;
 	}
+#else
+	SSI_ASSERT(inode);
+	SSI_ASSERT(!S_ISDIR(inode->i_mode) || (hp->sct_dp && hp->sct_dp->d_inode));
 #endif
 
 	_cfsd_getattr(inode, attrp);
@@ -355,14 +354,17 @@
  * The access argument indicates the type of open (read/write/lock)
  */
 int
+#ifdef CFSD_OPEN
+cfsd_open(struct svrcfstok *hp, int type, int access, struct file **filp)
+#else
 cfsd_open(struct svrcfstok *hp, int type, int access, struct file *filp)
+#endif
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
 #ifndef CFSD_OPEN
 	int		err;
 #else
-	struct file 	*f = filp;
 	int		flags = O_RDONLY|O_LARGEFILE, err;
 #endif
 
@@ -441,8 +443,23 @@
 		DQUOT_INIT(inode);
 	}
 
-	/* dentry_open() the fake struct file ... */
+	/* SSI_XXX: We don't have ex_mnt for CFS */
+	/* *filp = dentry_open(dget(dentry), mntget(hp->sct_fh->fh_export->ex_mnt), flags); */
+	*filp = dentry_open(dget(dentry), NULL, flags);
+	if (IS_ERR(*filp)) {
+		err = PTR_ERR(*filp);
+	} else if (is_shm_mmap(dentry, 1)) {
+		extern struct file_operations shm_file_operations;
 
+		(*filp)->f_op = &shm_file_operations;
+		if ((*filp)->f_op && (*filp)->f_op->open) {
+			err = (*filp)->f_op->open(inode, *filp);
+			if (err)
+				goto cleanup_all;
+		}
+	}
+#if 0
+	/* dentry_open() the fake struct file ... */
 	memset(filp, 0, sizeof(*filp));
 
 	f->f_flags = flags;
@@ -478,11 +495,24 @@
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | O_NOOPEN);
 
 	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
+#endif
 #endif /* CFSD_OPEN */
 out:
 	return err;
 #ifdef CFSD_OPEN
 cleanup_all:
+	fops_put((*filp)->f_op);
+	if ((*filp)->f_mode & FMODE_WRITE)
+		put_write_access(inode);
+	file_kill(*filp);
+	(*filp)->f_dentry = NULL;
+	/* (*filp)->f_vfsmnt = NULL; */
+	put_filp(*filp);
+	dput(dentry);
+	/* mntput(mnt); */
+	return err;
+#if 0
+cleanup_all:
 	fops_put(f->f_op);
 	if (f->f_mode & FMODE_WRITE)
 		put_write_access(inode);
@@ -497,6 +527,7 @@
 #endif
 	goto out;
 #endif
+#endif
 }
 
 /*
@@ -505,15 +536,7 @@
 void
 cfsd_close(struct file *filp)
 {
-	struct dentry	*dentry = filp->f_dentry;
-	struct inode	*inode = dentry->d_inode;
-
-	/* fput() fake struct file */
-	if (filp->f_op && filp->f_op->release)
-		filp->f_op->release(inode, filp);
-	fops_put(filp->f_op);
-	if (filp->f_mode & FMODE_WRITE)
-		put_write_access(inode);
+	fput(filp);
 }
 
 /*
@@ -582,21 +605,26 @@
  */
 int
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_READ
+cfsd_read(struct svrcfstok *hp, loff_t offset,
+	  struct kvec *vec, int vlen, char *buf, unsigned long *count)
+#else
 cfsd_read(struct svrcfstok *hp, loff_t offset,
 	  struct kvec *vec, int vlen, unsigned long *count)
+#endif
 #else
 cfsd_read(struct svrcfstok *hp, loff_t offset, char *buf, unsigned long *count)
 #endif
 {
 	mm_segment_t	oldfs;
 	int		err;
-	struct file	file;
+	struct file	*file;
 
 	err = cfsd_open(hp, S_IFREG, MAY_READ, &file);
 	if (err)
 		goto out;
 	err = -EPERM;
-	if (!file.f_op->read)
+	if (!file->f_op->read)
 		goto out_close;
 
 #ifdef CFS_PARANOIA
@@ -606,20 +634,26 @@
 	/* SSI_XXX: We should send the pid and actually do this mandatory lock
 	 * check.
 	 */
-	ret = locks_verify_area(FLOCK_VERIFY_READ, file.f_dentry->d_inode,
-				&file, file.f_pos, *count);
+	ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
+				file, file->f_pos, *count);
 #endif
 
 #ifdef CFS_READAHEAD
 	/* Get readahead parameters */
 	if (hp->sct_ra.ra_pages)
-		file.f_ra = hp->sct_ra;
+		file->f_ra = hp->sct_ra;
 #endif
 
 	oldfs = get_fs(); set_fs(KERNEL_DS);
 #ifdef CFS_PAGEVEC
-	if (file.f_op->readv)
-		err = file.f_op->readv(&file, (struct iovec __user *)vec, vlen, &offset);
+#ifdef CFS_PAGEVEC_BUFFER_READ
+	if (!vec) {
+		SSI_ASSERT(buf);
+		err = file->f_op->read(file, buf, *count, &offset);
+	} else
+#endif
+	if (file->f_op->readv)
+		err = file->f_op->readv(file, (struct iovec __user *)vec, vlen, &offset);
 	else {
 		/* Do it by hand, with file-ops. Borrowed from do_readv_writev */
 		err = 0;
@@ -633,7 +667,7 @@
 			vec++;
 			vlen--;
 
-			nr = file.f_op->read(&file, base, len, &offset);
+			nr = file->f_op->read(file, base, len, &offset);
 
 			if (nr < 0) {
 				if (!err) err = nr;
@@ -645,25 +679,25 @@
 		}
 	}
 #else
-	file.f_pos = offset;
+	file->f_pos = offset;
 
-	err = file.f_op->read(&file, buf, *count, &file.f_pos);
+	err = file->f_op->read(file, buf, *count, file->f_pos);
 #endif
 	set_fs(oldfs);
 
 #ifdef CFS_READAHEAD
 	/* Write back readahead params */
-	hp->sct_ra = file.f_ra;
+	hp->sct_ra = file->f_ra;
 #endif
 
 	dprintk("cfsd: read complete err=%d\n", err);
 	if (err >= 0) {
 		*count = err;
 		err = 0;
-		dnotify_parent(file.f_dentry, DN_ACCESS);
+		dnotify_parent(file->f_dentry, DN_ACCESS);
 	}
 out_close:
-	cfsd_close(&file);
+	cfsd_close(file);
 out:
 	return err;
 }
@@ -674,21 +708,28 @@
  */
 int
 #ifdef CFS_PAGEVEC
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+cfsd_write(struct svrcfstok *hp, loff_t offset, struct kvec *vec, int vlen,
+	   char *buf, unsigned long cnt, int stable)
+#else
 cfsd_write(struct svrcfstok *hp, loff_t offset, struct kvec *vec, int vlen,
 	   unsigned long cnt, int stable)
+#endif
 #else
 cfsd_write(struct svrcfstok *hp, loff_t offset, char *buf, unsigned long cnt,
 	int stable)
 #endif
 {
-	struct file		file;
+	struct file		*file;
 	struct dentry		*dentry;
 	struct inode		*inode;
 	mm_segment_t		oldfs;
 	ssize_t			err = 0;
 #ifdef CFS_GATHERWRITES
-	/* SSI_XXX: breaks CHARD */
-	int gathered_writes = 1;
+	int gathered_writes = ssi_isremote();
+#endif
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	int stacked;
 #endif
 
 	err = cfsd_open(hp, S_IFREG, MAY_WRITE, &file);
@@ -697,10 +738,10 @@
 	if (!cnt)
 		goto out_close;
 	err = -EPERM;
-	if (!file.f_op->write)
+	if (!file->f_op->write)
 		goto out_close;
 
-	dentry = file.f_dentry;
+	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
 	/*
@@ -710,7 +751,7 @@
 	 * When gathered writes have been configured for this volume,
 	 * flushing the data to disk is handled separately below.
 	 */
-	if (file.f_op->fsync == 0) {	/* COMMIT cannot work */
+	if (file->f_op->fsync == 0) {	/* COMMIT cannot work */
 	       stable = 2;
 	}
 
@@ -721,17 +762,16 @@
 #ifdef CFS_GATHERWRITES
 		if (!gathered_writes)
 #endif
-			file.f_flags |= O_SYNC;
+			file->f_flags |= O_SYNC;
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
 #ifdef CFS_PAGEVEC
-#if defined(CFS_ASYNC_LOCAL_SYNC) && defined(CFS_FILE_WRITE_LIVELOCK_FIX)
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
 	/* RT: [ ssic-linux-Bugs-686748 ] Filesystem stacking deadlock.
 	 *
 	 * Lock ordering:
 	 * 		(__cfs_file_write)
-	 * ->i_sem	(generic_file_aio_write)
 	 *		...
 	 *		(generic_file_buffered_write)
 	 *		(cfs_updatepage)
@@ -746,25 +786,22 @@
 	 *		...
 	 * ->i_sem	(generic_file_writev)
 	 */
-	if (file.f_op->writev == generic_file_writev && sem_owned(&inode->i_sem)) {
-		/* Prevent further generic_file_writev() recursion. */
-		current->balancing_dirty_pages = 1;
-		err = generic_file_write_nolock(&file,
-						(struct iovec __user *)vec,
-						vlen, &offset);
-		current->balancing_dirty_pages = 0;
-	} else if (file.f_op->writev) {
-		err = file.f_op->writev(&file,
-					(struct iovec __user *)vec,
-					vlen, &offset);
-	} else {
-		WARN_ON(file.f_op->write == generic_file_write &&
-				sem_owned(&inode->i_sem));
-#else
-	if (file.f_op->writev)
-		err = file.f_op->writev(&file, (struct iovec __user *)vec, vlen, &offset);
-	else {
+	if (sem_owned(&inode->i_sem) && !sem_flushing(&inode->i_sem)) {
+		inode->i_sem.flusher = current;
+		stacked = 1;
+	} else
+		stacked = 0;
 #endif
+
+#ifdef CFS_PAGEVEC_BUFFER_WRITE
+	if (!vlen) {
+		SSI_ASSERT(!vec);
+		err = file->f_op->write(file, buf, cnt, &offset);
+	} else
+#endif
+	if (file->f_op->writev) {
+		err = file->f_op->writev(file, (struct iovec __user *)vec, vlen, &offset);
+	} else {
 		/* Do it by hand, with file-ops. Borrowed from do_readv_writev */
 		err = 0;
 		while (vlen > 0) {
@@ -777,7 +814,7 @@
 			vec++;
 			vlen--;
 
-			nr = file.f_op->write(&file, base, len, &offset);
+			nr = file->f_op->write(file, base, len, &offset);
 
 			if (nr < 0) {
 				if (!err) err = nr;
@@ -788,15 +825,19 @@
 				break;
 		}
 	}
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	if (stacked)
+		inode->i_sem.flusher = NULL;
+#endif
 #else
-	file.f_pos = offset;		/* set write offset */
+	file->f_pos = offset;		/* set write offset */
 
-	err = file.f_op->write(&file, buf, cnt, &file.f_pos);
+	err = file->f_op->write(file, buf, cnt, file->f_pos);
 #endif /* !CFS_PAGEVEC */
 	/* err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset); */
 	set_fs(oldfs);
 	if (err > 0)
-		dnotify_parent(file.f_dentry, DN_MODIFY);
+		dnotify_parent(file->f_dentry, DN_MODIFY);
 
 	/* clear setuid/setgid flag after write */
 	if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
@@ -851,7 +892,7 @@
 	if (err >= 0)
 		err = 0;
 out_close:
-	cfsd_close(&file);
+	cfsd_close(file);
 out:
 	return err;
 }
@@ -896,9 +937,10 @@
 #endif
 		goto out_up;
 	dchild = lookup_hash(name, dentry);
-	err = PTR_ERR(dchild);
-	if (IS_ERR(dchild))
+	if (IS_ERR(dchild)) {
+		err = PTR_ERR(dchild);
 		goto out_up;
+	}
 
 #ifdef SSI_XXX_NOW_GET_O_EXCL
 	 * SSI_XXX: Like gfs in this unusual race we have problems with
@@ -1049,6 +1091,8 @@
 	SSI_ASSERT(!isdotent(fname->name, fname->len));
 	SSI_ASSERT(fname->len);
 
+	*hpp = NULL;
+
 	err = -ENOENT;
 	if (!fname->len)
 		goto out;
@@ -1066,9 +1110,10 @@
 #endif
 		goto out_up;
 	dnew = lookup_hash(fname, dentry);
-	err = PTR_ERR(dnew);
-	if (IS_ERR(dnew))
+	if (IS_ERR(dnew)) {
+		err = PTR_ERR(dnew);
 		goto out_unlock;
+	}
 
 #ifdef SSI_CFS_FROMNFS
 	mode = S_IALLUGO;
@@ -1157,9 +1202,10 @@
 		goto out_up;
 
 	dnew = lookup_hash(name, ddir);
-	err = PTR_ERR(dnew);
-	if (IS_ERR(dnew))
+	if (IS_ERR(dnew)) {
+		err = PTR_ERR(dnew);
 		goto out_up;
+	}
 
 	dold = thp->sct_dp;
 	dest = dold->d_inode;
@@ -1214,6 +1260,8 @@
 	struct svrcfstok *fhp = NULL, *thp = NULL;
 	dev_t			dev;
 
+	*fhpp = *thpp = NULL;
+
 	fdentry = fromhp->sct_dp;
 	fdir = fdentry->d_inode;
 
@@ -1243,9 +1291,10 @@
 		goto out_cfserr;
 
 	odentry = lookup_hash(fname, fdentry);
-	err = PTR_ERR(odentry);
-	if (IS_ERR(odentry))
+	if (IS_ERR(odentry)) {
+		err = PTR_ERR(odentry);
 		goto out_cfserr;
+	}
 
 	err = -ENOENT;
 	if (!odentry->d_inode)
@@ -1264,9 +1313,10 @@
 		goto out_dput_old;
 
 	ndentry = lookup_hash(tname, tdentry);
-	err = PTR_ERR(ndentry);
-	if (IS_ERR(ndentry))
+	if (IS_ERR(ndentry)) {
+		err = PTR_ERR(ndentry);
 		goto out_dput_old;
+	}
 #ifdef CFS_FROMNFS
 	err = -ENOTEMPTY;
 	if (ndentry == trap)
@@ -1433,9 +1483,10 @@
 		goto out;
 
 	rdentry = lookup_hash(name, dentry);
-	err = PTR_ERR(rdentry);
-	if (IS_ERR(rdentry))
+	if (IS_ERR(rdentry)) {
+		err = PTR_ERR(rdentry);
 		goto out;
+	}
 
 	if (!rdentry->d_inode) {
 		dput(rdentry);
@@ -1540,7 +1591,7 @@
 	struct inode	*inode;
 	u32		*p;
 	int		oldlen, eof, err;
-	struct file	file;
+	struct file	*file;
 	struct cfs_readdir_cd cd;
 
 	err = cfsd_open(hp, S_IFDIR, MAY_READ, &file);
@@ -1552,11 +1603,11 @@
 		goto out_close;
 
 	err = -ENOTDIR;
-	if (!file.f_op->readdir)
+	if (!file->f_op->readdir)
 		goto out_close;
 #endif /* CFS_SKIP */
 	if (offset) {
-		err = (int)vfs_llseek(&file, offset, 0);
+		err = (int)vfs_llseek(file, offset, 0);
 		if (err < 0)
 			goto out_close;
 	}
@@ -1571,7 +1622,7 @@
 	 * readdir() is not guaranteed to fill up the entire buffer, but
 	 * may choose to do less.
 	 */
-	inode = file.f_dentry->d_inode;
+	inode = file->f_dentry->d_inode;
 	down(&inode->i_sem);
 	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
@@ -1588,7 +1639,7 @@
 			file.f_inode->i_sb->s_dev, file.f_inode->i_ino,
 			(int) file.f_pos, (int) oldlen, (int) cd.buflen);
 		 */
-		err = file.f_op->readdir(&file, &cd, (filldir_t) func);
+		err = file->f_op->readdir(file, &cd, (filldir_t) func);
 		if (err < 0)
 			goto out_cfserr;
 		if (oldlen == cd.buflen)
@@ -1602,7 +1653,7 @@
 	eof = !cd.eob;
 
 	if (cd.offset)
-		*cd.offset = file.f_pos;
+		*cd.offset = file->f_pos;
 
 	p = cd.buffer;
 	*p++ = 0;			/* no more entries */
@@ -1614,7 +1665,7 @@
 				cd.offset? ntohl(*cd.offset) : -1);
 	err = 0;
 out_close:
-	cfsd_close(&file);
+	cfsd_close(file);
 out:
 	return err;
 
@@ -1758,21 +1809,22 @@
 	 * if it doesnt exist.
 	 */
 	droot = sbtocmi(hp->sct_sb)->mi_pfs_sb->s_root;
-	dget(droot);	/* needed? */
 
 	/* Lock if it isn't already locked by the caller */
 	if (dhp->sct_ip != droot->d_inode)
 		down(&(droot->d_inode->i_sem));
 
 	ddir = lookup_one_len(CFS_UNLINKDIR, droot, strlen(CFS_UNLINKDIR));
-	if (IS_ERR(ddir))
+	if (IS_ERR(ddir)) {
 		error = PTR_ERR(ddir);
-	if (!error) {
+	} else {
 		if (!ddir->d_inode) {
 			t = current;
 			save_cap = t->cap_effective;
+			mb();
 			t->cap_effective = CAP_FULL_SET;
 			save_fs = t->fs;
+			mb();
 			t->fs = copy_fs_struct(t->fs);
 			if (t->fs) {
 				t->fs->umask = 0;
@@ -1786,6 +1838,7 @@
 		} else if ((ddir->d_inode->i_mode & S_IALLUGO) != S_IRWXUGO) {
 			t = current;
 			save_cap = t->cap_effective;
+			mb();
 			t->cap_effective = CAP_FULL_SET;
 			down(&ddir->d_inode->i_sem);
 			newattrs.ia_mode = S_IRWXUGO |
@@ -1813,7 +1866,7 @@
 	/* Weird case he's trying to rename a delayed unlink file out
 	 * of the .cfs_unlink directory.  Hopefully this can't happen
 	 */
-	if (ddir->d_inode == dhp->sct_ip) {
+	if (unlikely(ddir->d_inode == dhp->sct_ip)) {
 		error = -EINVAL;
 		dput(ddir);
 		goto out;
@@ -1834,8 +1887,19 @@
 	down(&(ddir->d_inode->i_sem));
 
 	new = lookup_one_len(newname, ddir, strlen(newname));
-	SSI_ASSERT(!IS_ERR(new));
-	SSI_ASSERT(new->d_inode == NULL);
+	/*
+	 * SSI_ASSERT(!IS_ERR(new));
+	 * SSI_ASSERT(new->d_inode == NULL);
+	 */
+	if (unlikely(IS_ERR(new))) {
+		error = PTR_ERR(new);
+		new = NULL;
+		goto out_error;
+	}
+	if (unlikely(new->d_inode != NULL)) {
+		error = -ENOENT;
+		goto out_error;
+	}
 
 #ifdef DEBUG
 	printk(KERN_DEBUG
@@ -1855,6 +1919,7 @@
 					dp->d_name, newname, error) );
 #endif
 
+out_error:
 	up(&(ddir->d_inode->i_sem));
 	kfree(newname);
 	dput(ddir);	/* done with directory, let it go */
@@ -1893,7 +1958,6 @@
 #endif /* SVRCFSTOK_SCT_FLAGS_NOLOCK */
 
 out:
-	dput(droot);	/* needed? */
 	return error;
 }
 
@@ -1904,7 +1968,7 @@
  * 	with linkit passed as TRUE.  This is the only scenario in which it
  *	would be clean to undo.
  */
-static void
+static void __deprecated
 cfs_delayedunlink_undo(
 	struct inode *tip,
 	char *tnm,
@@ -1916,7 +1980,6 @@
 	int error;
 
 	droot = sbtocmi(hp->sct_sb)->mi_pfs_sb->s_root;
-	dget(droot);	/* needed? */
 
 	/* Lock if it isn't already locked by the caller */
 	if (dhp->sct_ip != droot->d_inode)
@@ -1928,7 +1991,6 @@
 
 	if (dhp->sct_ip != droot->d_inode)
 		up(&(droot->d_inode->i_sem));
-	dput(droot);	/* needed? */
 
 #ifdef DEBUG
 	if (error) {


------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.