[SSI] openssi/kernel/cluster/ssi/cfs cfs_chard.c, 1.16, 1.17 cfs_server.c, 1.16, 1.17 cfs_subr.c, 1.26, 1.27 cfs_svc.c, 1.18, 1.19 cfsfh.c, 1.9, 1.10 cfsproc.c, 1.33, 1.34 cfstok.c, 1.21, 1.22 dir.c, 1.27, 1.28 file.c, 1.23, 1.24 inode.c, 1.60, 1.61 pagelist.c, 1.13, 1.14 proc.c, 1.20, 1.21 read.c, 1.20, 1.21 svrcfs.c, 1.24, 1.25 symlink.c, 1.11, 1.12 vfs.c, 1.31, 1.32 write.c, 1.37, 1.38

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-serv16224/kernel/cluster/ssi/cfs

Modified Files:
      Tag: OPENSSI-FC
	cfs_chard.c cfs_server.c cfs_subr.c cfs_svc.c cfsfh.c 
	cfsproc.c cfstok.c dir.c file.c inode.c pagelist.c proc.c 
	read.c svrcfs.c symlink.c vfs.c write.c 
Log Message:
Bug fixes and enhancements. See ChangeLog.


Index: cfs_server.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_server.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cfs_server.c	24 Mar 2009 04:26:28 -0000	1.16
+++ cfs_server.c	27 Oct 2009 03:18:29 -0000	1.17
@@ -477,7 +477,7 @@
 			if (nlp != NULL) {
 				if ((rootip = sb->s_root->d_inode) && igrab(rootip)) {
 					if (itoc(rootip)->c_hp) {
-						*nlp = svrcfstok_get_mholdlist(itoc(rootip)->c_hp);
+						svrcfstok_get_mholdlist(itoc(rootip)->c_hp, nlp);
 					} else /* SSI_XXX: BUG? */
 						error = -EBUSY;
 					iput(rootip);

Index: inode.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/inode.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- inode.c	24 Mar 2009 04:26:28 -0000	1.60
+++ inode.c	27 Oct 2009 03:18:29 -0000	1.61
@@ -72,6 +72,9 @@
 
 #define CFS_PARANOIA 1
 
+#ifdef CFS_PAGES_CACHE
+extern void cfs_pagevec_init(void);
+#endif
 #ifdef RCU_CFSTOK_TABLE
 extern void svrcfstok_init(void);
 #endif
@@ -117,7 +120,11 @@
 extern int cfs_0_nproc;
 extern nsc_rpccall_t nsc_rpc_cfs_0[];
 
+#ifdef CFS_ASYNC_QUEUE
+void *nsc_async_cfs_queue[3]; /* RPC_NR_PRIORITY */
+#else
 void *nsc_async_cfs_queue;
+#endif
 
 struct super_operations cfs_sops = {
 	.alloc_inode	= cfs_alloc_inode,
@@ -298,7 +305,6 @@
 	cp = itoc(inode);
 	LOCK_COND_LOCK(&cp->c_statelock);
 	hp = cp->c_hp;
-	mb();
 	cp->c_hp = NULL;
 	UNLOCK_COND_LOCK(&cp->c_statelock);
 	if (hp)
@@ -337,7 +343,7 @@
 #endif /* SSI_XXX */
 }
 
-#ifdef SSI_NOT_YET
+#ifdef SSI_NOTYET
 static inline unsigned long
 cfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
 {
@@ -428,9 +434,9 @@
 		if (argp->pfs_data.pfs_data_val)
 			argp->pfs_data.pfs_data_val =
 				(void *)(((char *)data) + PAGE_SIZE);
-	}
+	} else
+		argp = data->payload;
 
- 	argp = data->payload;
 	if (!argp)
 		return mnt->mnt_uniqueid;
 	return argp->uniqueid;
@@ -457,6 +463,26 @@
 	return 0;
 }
 
+#ifdef KERNEL2616_53
+/**
+ * cfs_sync_mapping - helper to flush all mmapped dirty data to disk
+ */
+int cfs_sync_mapping(struct address_space *mapping)
+{
+	int ret;
+
+	if (mapping->nrpages == 0)
+		return 0;
+	unmap_mapping_range(mapping, 0, 0, 0);
+	ret = filemap_write_and_wait(mapping);
+	if (ret != 0)
+		goto out;
+	ret = cfs_wb_all(mapping->host);
+out:
+	return ret;
+}
+#endif
+
 /*
  * Invalidate the local caches
  */
@@ -543,7 +569,7 @@
 		inode->i_flags |= S_NOATIME;
 		CFS_FLAGS(inode) = 0;
 		inode->i_mode = fattr->cna_mode;
-		inode->i_ino = fattr->cna_ino;
+		/* inode->i_ino = fattr->cna_ino; */ /* done in cfs_init_locked() */
 		/* Why so? Because we want revalidate for devices/FIFOs, and
 		 * that's precisely what we have in cfs_file_inode_operations.
 		 */
@@ -600,6 +626,7 @@
 		__wait_on_new_inode(inode);
 }
 
+/* Called from base with inode_lock spin locked */
 int
 cfs_find_actor(struct inode *inode, void *opaque)
 {
@@ -628,6 +655,9 @@
 	return 1;
 }
 
+/* Called from base with inode_lock spin locked.
+ * Set i_ino here to avoid race with cfs_find_actor().
+ */
 static int
 cfs_init_locked(struct inode *inode, void *opaque)
 {
@@ -640,25 +670,33 @@
 	if (desc->cdrok) {
 		SSI_ASSERT (desc->hp == NULL);
 
+		inode->i_ino = desc->cdrok->cdrok_attr.cna_ino;
+
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(itocfh(inode), &(desc->cdrok->cdrok_fhandle));
+#else
 		memcpy (itocfh(inode), &(desc->cdrok->cdrok_fhandle),
 		      sizeof (cfhandle_t));
+#endif
 
 		itoc(inode)->c_locknumber = desc->cdrok->cdrok_locknumber;
 
-		//inode->i_ino = desc->cdrok->cdrok_attr.cna_ino;
-
 	} else {
 		SSI_ASSERT (desc->hp);
 		SSI_ASSERT (desc->cdrok == NULL);
 
+		inode->i_ino = desc->hp->sct_ip->i_ino;
+
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(itocfh(inode), &(desc->hp->sct_fh));
+#else
 		memcpy(itocfh(inode), &(desc->hp->sct_fh), sizeof (cfhandle_t));
+#endif
 
 		itoc(inode)->c_hp = desc->hp;
 		HASH_HOLD(desc->hp);
 
 		itoc(inode)->c_locknumber = (void *) &(desc->hp->sct_mhold);
-
-		//inode->i_ino = desc->hp->sct_ip->i_ino;
 	}
 
 	return 0;
@@ -695,6 +733,7 @@
 			 * send tokens back to server.  If we really are low on
 			 * memory, this could be trouble too.
 			 */
+			yield();
 			goto again;
 		}
 	} else
@@ -746,7 +785,7 @@
 	if (inode->i_state & I_NEW) {
 		/* We set i_ino for the few things that still rely on it,
 		 * such as stat(2) */
-		inode->i_ino = ino;
+		/* inode->i_ino = ino; */ /* done in cfs_init_locked() */
 
 		/* Get MHOLD for client at server CFS inode */
 		ret = svrcfstok_getinstall_range (hp, CFSTOK_MHOLD,
@@ -854,7 +893,7 @@
 		down_write(&inode->i_alloc_sem);
 #endif
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
@@ -865,9 +904,8 @@
 #endif
 		return -EINTR;
 	}
-#else
+#endif /* CFSTOK_INTR */
 	SSI_ASSERT(result == CFSTOK_HELD);
-#endif /* !CFSTOK_INTR */
 
 	cfs_begin_data_update(inode);
 #ifdef CFS_SETATTR_LAZY_FLUSH
@@ -1264,16 +1302,15 @@
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		status = -EINTR;
 		goto sb_error_check;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 #ifdef CFS_ZAP_CACHES
 #ifdef SSI_CFS_SKIP
 	LOCK_COND_LOCK(&itoc(inode)->c_statelock);
@@ -1537,14 +1574,13 @@
 
 	if (data->mode == CFS_DISCOVER) {
 		argp = data->payload = ((char *)data) + sizeof(struct cfs_mount_data);
-		mb();
 		argp->root.cdrok_res_toks =
 			(void *)(((char *)argp) + sizeof(*argp));
 		if (argp->pfs_data.pfs_data_val)
 			argp->pfs_data.pfs_data_val =
 				(void *)(((char *)data) + PAGE_SIZE);
-	}
-	argp = data->payload;
+	} else
+		argp = data->payload;
 	s = sgetx(fs_type, cfs_compare_super, cfs_set_super, data, 1, flags);
 
 	if (IS_ERR(s) || s->s_root) {
@@ -1638,9 +1674,7 @@
 extern SPIN_LOCK_T		(condata_node_free_lock);
 #endif /* SSI_CFS_POLICY */
 
-#ifdef RCU_CFSTOK_TABLE
-extern spinlock_t		svrcfstok_table_lock;
-#else
+#ifndef RCU_CFSTOK_TABLE
 extern LOCK_T			svrcfstok_table_lock;
 #endif
 #ifdef SSI_EXNFS
@@ -1807,9 +1841,6 @@
 	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
@@ -1841,6 +1872,9 @@
 	/* allocate memory for the sb_nblks structures */
 	sb_nblks = (struct sb_nblks *)kmem_zalloc(MAX_SB_NBLKS_ENTRY * sizeof(struct sb_nblks), KM_SLEEP);
 #endif
+#ifdef CFS_PAGES_CACHE
+	cfs_pagevec_init();
+#endif
 
 	/*
 	 * initialize token caches
@@ -1977,8 +2011,21 @@
 	if (err)
 		return err;
 
+#ifdef CFS_ASYNC_QUEUE
+	for (err = 0; err < ARRAY_SIZE(nsc_async_cfs_queue); err++) {
+		char name[TASK_COMM_LEN];
+
+		snprintf(name, TASK_COMM_LEN-1, "cfs_async_%d", err);
+
+		/* Only create one low / high priority thread */
+		nsc_async_cfs_queue[err] = nsc_async_queue_init(name,
+							(err == 1) ? 8 : 1,
+							NSC_ASYNC_NO_MAXARGSZ);
+	}
+#else
 	nsc_async_cfs_queue = nsc_async_queue_init("cfs_async", 8,
 						   NSC_ASYNC_NO_MAXARGSZ);
+#endif
 
 
 	cfs_doinit();

Index: cfs_chard.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_chard.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- cfs_chard.c	24 Mar 2009 04:26:28 -0000	1.16
+++ cfs_chard.c	27 Oct 2009 03:18:29 -0000	1.17
@@ -55,16 +55,28 @@
 	/* Sleep until something changes. */
 	while (!CFS_SB_UP_MIP(mip)) {
 		if (nowait) {
+#ifdef CFS_PAGEVEC
+			/* Server rebuild flushing */
+			if (CFS_SB_HARD_MIP(mip) &&
+			    mip->mi_sb_state >= MI_SB_STATE_REBUILD_FLUSH) {
+				if (!CFS_AT_SERVER_MIP(mip))
+					goto wait;
+				break;
+			}
+#endif
 			/* Yes: return an error. */
 			error = -ECFS_TRYAGAIN;
 			break;
 		}
 		/* Is this a down soft-mount? */
-		if (!CFS_SB_HARD_MIP(mip) && !CFS_SB_UP_MIP(mip)) {
+		if (!CFS_SB_HARD_MIP(mip)) { //&& !CFS_SB_UP_MIP(mip)) {
 			/* Yes: return an error. */
 			error = -ECFS_TRYAGAIN;
 			break;
 		}
+#ifdef CFS_PAGEVEC
+wait:
+#endif
 		/* Sleep may be interruptible. */
 		interruptible = (mip->mi_flags & MI_INTR);
 		/* Rebuild in progress? */
@@ -178,7 +190,12 @@
 	SSI_ASSERT(error != 0);
 
 	/* Is this CFS-inspired retryable error? */
+#ifdef CFS_CHARD_RACE_FIX
+	/* Other errors apply too if node is going down */
+	if (CFS_SB_RETRY_ERROR(error) || clms_isnodedown(mip->mi_server)) {
+#else
 	if (CFS_SB_RETRY_ERROR(error)) {
+#endif
 		/* Yes. */
 		/* Bring the local SB down? */
 		if (clms_isnodedown(mip->mi_server) && CFS_SB_UP_MIP(mip)) {
@@ -782,14 +799,22 @@
 static void
 clean_list(struct list_head *tofree_head, void *unused, int idx)
 {
+#ifndef CFS_CLIST_LLIST
 	struct list_head *act_head;
 	struct cnode *cnode;
+#else
+	struct cnode *cnode, *tmp;
+#endif
 	struct inode *inode;
 
+#ifndef CFS_CLIST_LLIST
 	act_head = tofree_head->next;
 	while (act_head != tofree_head) {
 		cnode = list_entry(act_head, struct cnode, c_ilists[idx]);
 		act_head = act_head->next;
+#else
+	list_for_each_entry_safe(cnode, tmp, tofree_head, c_ilists[idx]) {
+#endif
 		/* Remove from the list so we won't have problems... */
 		list_del_init(&cnode->c_ilists[idx]);
 		inode = ctoi(cnode);
@@ -800,7 +825,9 @@
 		UNLOCK_COND_LOCK(&cnode->c_statelock);
 		iput(inode);
 	}
+#ifndef CFS_CLIST_LLIST
 	cfs_free_cnode_idx(idx);
+#endif
 }
 
 static void

Index: cfs_svc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_svc.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- cfs_svc.c	3 Feb 2009 06:18:12 -0000	1.18
+++ cfs_svc.c	27 Oct 2009 03:18:29 -0000	1.19
@@ -57,7 +57,7 @@
 #include <cluster/assert.h>
 #include <cluster/ssisys.h>
 
-extern int cfs_root_failover(struct super_block *);
+extern void cfs_root_failover(struct super_block *);
 u_long debug_flag = 0;
 
 /* debug_func lets us chose where debugs go (console, log, or both).  */
@@ -80,7 +80,6 @@
 	clusternode_t node = (clusternode_t)arg;
 	struct super_block *sb;
 	cfs_mntinfo_t *mip;	/* CFS mount information. */
-	int error;
 
 	INCR_MEMPRIO(); /* avoid blocking for memory */
 
@@ -108,13 +107,9 @@
 
 		/* Failover root here */
 		lock_kernel();
-		error = cfs_root_failover(sb);
+		cfs_root_failover(sb);
 		unlock_kernel();
 
-		if (error) {
-			printk(KERN_CRIT "cfs_root _failover error %d\n", error);
-			panic("Unable to perform root failover");
-		}
 #ifdef NOTYET_DISABLED
 		clms_set_key_service_ready(CLUSTER_ROOT_SERVICE);
 #endif
@@ -363,27 +358,29 @@
 	(void) execve(shell, args, env);
 }
 
-int
+static exec_userproc_arg_t *
 spawn_failover_user_proc(const char *path, struct vfsmount *root,
 	 const char *arg1)
 {
 	exec_userproc_arg_t *euap;
 	int error;
 
-	/* Where do I free this? */
 	euap = (exec_userproc_arg_t *)kmalloc(sizeof(exec_userproc_arg_t),
 		GFP_KERNEL);
 
-	/* SSI_XXX: Hold the vfsmount here? */
 	euap->path = path;
 	euap->root = root;
 	euap->arg1 = arg1;
 
 	error = kernel_thread((int (*)(void *))exec_failover_userproc, euap, 0);
-	return error;
+	if (error < 0) {
+		kfree(euap);
+		return ERR_PTR(error);
+	}
+	return euap;
 }
 
-int
+void
 cfs_root_failover(struct super_block *cfssb)
 {
 	struct vfsmount *root;
@@ -392,6 +389,7 @@
 	extern char *root_dev_name, *root_fs;
 	cfs_mntinfo_t *mip;
 	struct super_block *sb;
+	exec_userproc_arg_t *euap;
 
 	if (root_fs == NULL)
 		panic("cfs_root_failover: no cfs_setroot performed");
@@ -402,9 +400,10 @@
 	 * super-block onto the global list.
 	 */
 	root = do_kern_mount(root_fs, MS_RDONLY|MS_REMOUNT, NULL, cfssb->s_mnt_info);
-	err = PTR_ERR(root);
-	if (IS_ERR(root))
+	if (IS_ERR(root)) {
+		err = PTR_ERR(root);
 		goto out;
+	}
 
 	arg1 = "failover";
 	/* SSI_XXX: Missing having fsck inherit caller's memory priority, so
@@ -414,19 +413,21 @@
 #ifdef NOTYET_DISABLED
 	set inherit memory priority
 #endif
-	err = spawn_failover_user_proc("/sbin/ckroot.ssi", root, arg1);
+	euap = spawn_failover_user_proc("/sbin/ckroot.ssi", root, arg1);
 #ifdef NOTYET_DISABLED
 	restore memory priority
 #endif
-	if (err < 0)
+	if (IS_ERR(euap)) {
+		err = PTR_ERR(euap);
 		goto out;
+	}
 
 	err = sys_wait4(-1, NULL, __WALL, NULL);
+	kfree(euap); /* clean up spawn_failover_user_proc() */
 	if (err < 0)
 		goto out;
-	err = 0; /* clear pid */
+	/* err = 0; */ /* clear pid */
 
-	/* SSI_XXX: Remount the root here */
 	/* Remount PFS from RDONLY to read/write */
 	sb = root->mnt_sb;
 
@@ -437,7 +438,7 @@
 		goto out;
 
 	mip = sbtocmi(cfssb);
-	/* SSI_XXX: Don't need vfsmount anymore */
+	/* Don't need vfsmount anymore */
 	atomic_inc(&sb->s_active);
 	mntput(root);
 
@@ -470,9 +471,10 @@
 		cfs_remount_cleanup(cfssb, sb);
 
 out:
-	if (err)
-		printk(KERN_ERR "cfs_root_failover: error %d\n", err);
-	return err;
+	if (err) {
+		printk(KERN_CRIT "%s: error %d\n", __FUNCTION__, err);
+		panic("Unable to perform root failover");
+	}
 }
 
 int
@@ -587,157 +589,155 @@
 	return(error);
 }
 
-#ifdef CFS_PAGEVEC
 /*
- * param OUT:OOL:VAR struct kvec **
+ * param IN:XDR struct cfswriteargs *
  */
+#define	cli_encode_xdr_struct_cfswriteargs_p(hndl,x) \
+	icscli_encode_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
+#define	svr_decode_xdr_struct_cfswriteargs_p(hndl,x) \
+	icssvr_decode_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
+#define	svr_free_xdr_struct_cfswriteargs_p(hndl,x) \
+	icssvr_free_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
 
-#define cli_encoderesp_var_ool_struct_kvec_p_p(hndl,x, n) \
-        (0)
-
+/*
+ * param OUT:XDR struct cfswriteres **
+ */
+#define cli_encoderesp_xdr_struct_cfswriteres_p_p(hndl,x) \
+	((*x) = NULL, 0)
 int
-cli_decode_var_ool_struct_kvec_p_p(cli_handle_t *hp, struct kvec **vec,
-                                  int vec_len)
+cli_decode_xdr_struct_cfswriteres_p_p(cli_handle_t *hndl,
+	 struct cfswriteres **objp)
 {
-	struct kvec *__vec = *vec;
-        int i;
-        int error;
-
-        for (i = 0; i < vec_len; i++, __vec++) {
-		cli_decode_gen_size_t(hp, __vec->iov_len);
-                error = icscli_decode_ool_data_t(hp, __vec->iov_base, 
-						 __vec->iov_len);
-                SSI_ASSERT(!error);
-        }
-
-        return 0;
+	icscli_decode_xdr(hndl, (u_char *)objp, xdr_cfswriteres_p);
+	return 0;
 }
 
-static void
-struct_kvec_p_p_free_data_callback(u_char *pgaddr, long page)
+extern void rcfs_write_0_free(struct cfswriteres **);
+
+int
+svr_encode_xdr_struct_cfswriteres_p_p(svr_handle_t *hndl,
+				struct cfswriteres **x)
 {
-	free_page((unsigned long) pgaddr);
+	int error;
+	error = icssvr_encode_xdr(hndl,(u_char*)x,xdr_cfswriteres_p);
+	rcfs_write_0_free(x);
+	return(error);
 }
 
-int     
-svr_encode_var_ool_struct_kvec_p_p(svr_handle_t *hp, struct kvec **vec,
-                                  int vec_len)
-{                       
-	struct kvec *__vec = *vec;
-	int i, error;
-
-	if (__vec == NULL)
-		return 0;
-
-	for (i = 0; i < vec_len; i++, __vec++) {
-		svr_encode_gen_size_t(hp, __vec->iov_len);
-		error = icssvr_encode_ool_data_t(hp, __vec->iov_base,
-						 __vec->iov_len,
-						 struct_kvec_p_p_free_data_callback,
-						 0);
-		SSI_ASSERT(!error);
-	}
+#ifdef ICS_OOL_STRUCT_PAGES
+/*
+ * param OUT:OOL:VAR struct page ***
+ */
 
-	kfree(*vec);
+#define cli_encoderesp_var_ool_struct_page_p_p_p(hndl,x, n) \
+        (0)
 
-	return 0;
-}
+static void
+free_pagevec_callback(u_char *param, long len)
+{
+#ifdef CFS_PAGES_CACHE
+	extern void cfs_pagevec_free(struct page **);
 
-int     
-cli_encode_var_ool_struct_kvec_p_p(cli_handle_t *hp, struct kvec **vec,
-                                  int vec_len)
-{                       
-	struct kvec *__vec = *vec;
-	int i, error;
+	cfs_pagevec_free((struct page **)param);
+#else
+	struct page **pages = (struct page **)param;
+	unsigned int i, vlen;
 
-	if (__vec == NULL)
-		return 0;
+/* SSI: Bottom PAGE_CACHE_SHIFT bits reserved for page base */
+#ifdef CFS_IOVEC
+#define VLEN(_x) \
+	((((_x) >> PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+#else
+#define VLEN(_x) \
+	((((_x) & ~PAGE_CACHE_MASK) + ((_x) >> PAGE_CACHE_SHIFT) + \
+	  PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+#endif /* !CFS_IOVEC */
+	vlen = VLEN((unsigned)len);
+#undef VLEN
 
-	for (i = 0; i < vec_len; i++, __vec++) {
-		cli_encode_gen_size_t(hp, __vec->iov_len);
-		error = icscli_encode_ool_data_t(hp, __vec->iov_base,
-						 __vec->iov_len,
-						 NULL, 0);
-		SSI_ASSERT(!error);
-	}
+	for (i = 0; i < vlen; i++)
+		__free_page(pages[i]);
 
-	return 0;
+	kfree(pages);
+#endif /* !CFS_PAGES_CACHE */
 }
 
-static void
-svr_free_var_ool_struct_kvec_p_p(svr_handle_t *hp, struct kvec **vec,
-				   int vec_len)
+int
+cli_decode_var_ool_struct_page_p_p_p(
+	cli_handle_t *hp,
+	struct page ***vec,
+	int len)
 {
-	struct kvec *__vec = *vec;
-	int i;
+	int error;
 
-	for (i = 0; i < vec_len; i++, __vec++)
-		free_page((unsigned long) __vec->iov_base);
+        if (!len)
+                return 0;
 
-	kfree(*vec);
+	BUG_ON(!*vec);
+	error = icscli_decode_ool_struct_page_p_p(hp, *vec, len);
+	SSI_ASSERT(!error);
+
+	return 0;
 }
 
 int
-svr_decode_var_ool_struct_kvec_p_p(svr_handle_t *hp, struct kvec **vec,
-                                  int vec_len)
+svr_encode_var_ool_struct_page_p_p_p(
+	svr_handle_t *hp,
+	struct page ***vec,
+	int len)
 {
-	struct kvec *__vec;
-        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++) {
-		__vec->iov_base = (void *) __get_free_page(GFP_KERNEL|__GFP_NOFAIL);
-
-		svr_decode_gen_size_t(hp, __vec->iov_len);
-                error = icssvr_decode_ool_data_t(hp, __vec->iov_base,
-						 __vec->iov_len);
-                SSI_ASSERT(!error);
-        }
+        if (!*vec)
+                return 0;
 
+	error = icssvr_encode_ool_struct_page_p_p(hp, *vec, (unsigned)len,
+						free_pagevec_callback, len);
+	SSI_ASSERT(!error);
         return 0;
 }
-#endif /* CFS_PAGEVEC */
 
 /*
- * param IN:XDR struct cfswriteargs *
+ * param IN:OOL:VAR struct page ***
  */
-#define	cli_encode_xdr_struct_cfswriteargs_p(hndl,x) \
-	icscli_encode_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
-#define	svr_decode_xdr_struct_cfswriteargs_p(hndl,x) \
-	icssvr_decode_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
-#define	svr_free_xdr_struct_cfswriteargs_p(hndl,x) \
-	icssvr_free_xdr(hndl,(u_char*)&x,xdr_cfswriteargs_p);
 
-/*
- * param OUT:XDR struct cfswriteres **
- */
-#define cli_encoderesp_xdr_struct_cfswriteres_p_p(hndl,x) \
-	((*x) = NULL, 0)
 int
-cli_decode_xdr_struct_cfswriteres_p_p(cli_handle_t *hndl,
-	 struct cfswriteres **objp)
+cli_encode_var_ool_struct_page_p_p_p(
+	cli_handle_t *hp,
+	struct page ***vec,
+	int len)
 {
-	icscli_decode_xdr(hndl, (u_char *)objp, xdr_cfswriteres_p);
+	int error;
+
+	error = icscli_encode_ool_struct_page_p_p(hp, *vec, len, NULL, 0);
+	SSI_ASSERT(!error);
+
 	return 0;
 }
 
-extern void rcfs_write_0_free(struct cfswriteres **);
+static void
+svr_free_var_ool_struct_page_p_p_p(
+	svr_handle_t *hp,
+	struct page ***vec,
+	int len)
+{
+	free_pagevec_callback((u_char *) *vec, (long) len);
+}
 
 int
-svr_encode_xdr_struct_cfswriteres_p_p(svr_handle_t *hndl,
-				struct cfswriteres **x)
+svr_decode_var_ool_struct_page_p_p_p(
+	svr_handle_t *hp,
+	struct page ***vec,
+	int len)
 {
 	int error;
-	error = icssvr_encode_xdr(hndl,(u_char*)x,xdr_cfswriteres_p);
-	rcfs_write_0_free(x);
-	return(error);
+
+	error = icssvr_decode_ool_struct_page_p_p(hp, vec, len);
+	SSI_ASSERT(!error);
+
+        return 0;
 }
+#endif /* ICS_OOL_STRUCT_PAGES */
 
 /*
  * param IN:XDR struct cfsrddirargs *
@@ -774,6 +774,18 @@
 	return(error);
 }
 
+#ifdef CFS_IOCTL
+/*
+ * param IN:XDR struct cfsioctlargs *
+ */
+#define	cli_encode_xdr_struct_cfsioctlargs_p(hndl,x) \
+	icscli_encode_xdr(hndl,(u_char*)&x,xdr_cfsioctlargs_p);
+#define	svr_decode_xdr_struct_cfsioctlargs_p(hndl,x) \
+	icssvr_decode_xdr(hndl,(u_char*)&x,xdr_cfsioctlargs_p);
+#define	svr_free_xdr_struct_cfsioctlargs_p(hndl,x) \
+	icssvr_free_xdr(hndl,(u_char*)&x,xdr_cfsioctlargs_p);
+#endif /* CFS_IOCTL */
+
 #ifdef SSI_NOTUSED
 /*
  * param IN:XDR struct bc_cacheargs *

Index: cfsfh.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfsfh.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cfsfh.c	20 Apr 2008 05:49:21 -0000	1.9
+++ cfsfh.c	27 Oct 2009 03:18:29 -0000	1.10
@@ -46,13 +46,13 @@
  * before the fh goes out on the wire ...
  */
 #ifdef CFS_EXPORT_OPS
-int
-cfs_fh_update(struct dentry *dentry, __u32 *data, int *max_len, int connectable)
+static inline int
+cfs_fh_update(struct dentry *dentry, __u32 *data, int *max_len)
 {
 	struct export_operations *nop = dentry->d_sb->s_export_op ?
 						: &export_op_default; /* cfs_shm_init */
 
-	return CALL(nop,encode_fh)(dentry, data, max_len, connectable);
+	return CALL(nop,encode_fh)(dentry, data, max_len, 0);
 }
 #else
 static inline int
@@ -121,7 +121,7 @@
 	datap++;		/* reserve type */
 	datap++;		/* reserve ino */
 
-	type = cfs_fh_update(dentry, datap, &size, 0);
+	type = cfs_fh_update(dentry, datap, &size);
 
 	*savedatap++ = size;
 	*savedatap++ = type;

Index: write.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/write.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- write.c	24 Mar 2009 04:26:28 -0000	1.37
+++ write.c	27 Oct 2009 03:18:29 -0000	1.38
@@ -88,7 +88,11 @@
 #include <cluster/assert.h>
 #include <cluster/ssi/ssidev.h>
 
+#ifdef CFS_ASYNC_QUEUE
+extern void *nsc_async_cfs_queue[3]; /* RPC_NR_PRIORITY */
+#else
 extern void *nsc_async_cfs_queue;
+#endif
 
 #ifndef CFS_PAGEVEC
 /*
[...1152 lines suppressed...]
 		cfs_unset_down(req);
 
+#ifndef CFS_CHARD_RACE_FIX
 		spin_unlock(&cfs_wreq_lock);
+#endif
 		cfs_mark_request_dirty(req);
 #ifndef KERNEL2616_53
 		cfs_unlock_request(req);
 #endif
+#ifndef CFS_CHARD_RACE_FIX
 		spin_lock(&cfs_wreq_lock);
+#endif
 	}
+#ifndef CFS_CHARD_RACE_FIX
 	spin_unlock(&cfs_wreq_lock);
+#endif
+#endif /* !CFS_ASYNC_QUEUE */
 
 	/* SSI_XXX: I would have liked to get all the data on disk
 	 * at this point, but the filesystem is still marked as down.

Index: file.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/file.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- file.c	24 Mar 2009 04:26:28 -0000	1.23
+++ file.c	27 Oct 2009 03:18:29 -0000	1.24
@@ -72,6 +72,9 @@
 #ifdef CFS_FLOCK
 static int cfs_flock(struct file *, int, struct file_lock *);
 #endif
+#ifdef CFS_IOCTL
+static long cfs_unlocked_ioctl(struct file *, unsigned int, unsigned long);
+#endif
 
 struct file_operations cfs_file_operations = {
 	.llseek 	= cfs_file_llseek,
@@ -79,8 +82,16 @@
 	.write		= do_sync_write,
 	.aio_read	= cfs_file_aio_read,
 	.aio_write	= cfs_file_aio_write,
+#ifdef CFS_IOCTL
+	.unlocked_ioctl	= cfs_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	/* SSI_XXX: Need compat_ioctl? */
+#endif
+#endif /* CFS_IOCTL */
 	.mmap		= cfs_file_mmap,
+#ifdef SSI_CFS_SKIP
 	.open		= cfs_open,
+#endif
 	.flush		= cfs_file_flush,
 #ifdef SSI_EXNFS
 	.release	= cfs_release,
@@ -107,7 +118,9 @@
 	read:		cfs_file_read,
 	write:		cfs_file_write,
 	mmap:		shm_mmap,
+#ifdef SSI_CFS_SKIP
 	open:		cfs_open,
+#endif
 #ifdef NOTUSED
 	flush:		cfs_file_flush,
 #endif
@@ -137,7 +150,7 @@
 
 		status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 			CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
-		if (status != CFSTOK_HELD) {
+		if (status == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 			printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
@@ -188,15 +201,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (status != CFSTOK_HELD) {
+	if (status == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(status == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(status == CFSTOK_HELD);
 
 	/* Ensure that data+attribute caches are up to date after close() */
 	status = cfs_wb_all(inode);
@@ -266,15 +278,14 @@
 #endif
 #endif /* !CFS_FILE_RW_NOLOCK */
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
+#endif
 	SSI_ASSERT(result == CFSTOK_HELD);
-#endif /* !CFSTOK_INTR */
 #ifdef CFS_ZAP_CACHES
 	result = cfs_revalidate_inode(inode);
 	if (!result) {
@@ -356,7 +367,7 @@
 #ifdef CFSTOK_INTR
 	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_EXCL,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
-	if (status != CFSTOK_HELD) {
+	if (status == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
@@ -409,7 +420,7 @@
 #ifdef CFSTOK_INTR
 	status = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 			 CFSTOK_BLOCK|CFSTOK_HOLD, NON_RANGE, NULL);
-	if (status != CFSTOK_HELD) {
+	if (status == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
@@ -498,15 +509,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (status != CFSTOK_HELD) {
+	if (status == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(status == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(status == CFSTOK_HELD);
 	status = cfs_wb_all(inode);
 	if (!status) {
 		status = file->f_error;
@@ -622,15 +632,14 @@
 #endif
 #endif /* !CFS_FILE_RW_NOLOCK */
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 #ifndef CFS_ZAP_CACHES
 	/* Don't need to revalidate inode at this point because that ended
@@ -675,6 +684,7 @@
 
 static int cfs_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
+	/* We don't compare fl_owner */
 	return fl1->fl_pid == fl2->fl_pid;
 }
 
@@ -682,6 +692,41 @@
 	.fl_compare_owner = cfs_same_owner,
 };
 
+#ifdef CFS_FLOCK
+static inline int __do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+	int res = 0;
+
+	switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+		case FL_POSIX:
+			res = posix_lock_file_wait(file, fl);
+			break;
+		case FL_FLOCK:
+			res = flock_lock_file_wait(file, fl);
+			break;
+		default:
+			BUG();
+	}
+	return res;
+}
+
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+	int res;
+
+	res = __do_vfs_lock(file, fl);
+	if (res < 0)
+		printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+				__FUNCTION__);
+	return res;
+}
+
+int do_cfs_lock(struct file_lock *fl)
+{
+	return __do_vfs_lock(fl->fl_file, fl);
+}
+#endif
+
 static int
 __cfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -689,8 +734,52 @@
 	cfs_mntinfo_t *mip = itocmi(inode);
 	int	status = 0;
 	struct cfslockargs la;
-#ifndef CFS_MIRROR_LOCK_WAIT
-	int new_lock = 0;
+
+	if (!(IS_SETLK(cmd) || IS_SETLKW(cmd) || IS_GETLK(cmd))) {
+		printk("%s: Unknown command %d\n", __FUNCTION__, cmd);
+		return -EINVAL;
+	}
+
+#ifdef CFS_ZAP_CACHES
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	if (!CFS_SB_HARD_MIP(mip) &&
+	    fl->fl_type != F_UNLCK && (IS_SETLK(cmd) || IS_SETLKW(cmd))) {
+#ifdef KERNEL2616_53
+		status = cfs_sync_mapping(filp->f_mapping);
+		if (status != 0)
+			goto out;
+#else
+		status = filemap_fdatawrite(filp->f_mapping);
+		if (status == 0) {
+			down(&inode->i_sem);
+			status = cfs_wb_all(inode);
+			up(&inode->i_sem);
+			if (status == 0)
+				status = filemap_fdatawait(filp->f_mapping);
+		}
+		if (status < 0)
+			goto out;
+#endif
+	}
+#endif /* CFS_ZAP_CACHES */
+#ifdef KERNEL2616_53
+	if (IS_GETLK(cmd)) {
+		struct file_lock *cfl;
+
+		lock_kernel();
+
+		/* Try local locking first */
+		cfl = posix_test_lock(filp, fl);
+		if (cfl != NULL) {
+			locks_copy_lock(fl, cfl);
+			unlock_kernel();
+			goto out;
+		}
+		unlock_kernel();
+	}
 #endif
 
 	la.cfrla_fh = *itocfh(inode);
@@ -708,7 +797,12 @@
 	if (status)
 		goto sb_error_check;
 
-	if (IS_SETLK(cmd) || IS_SETLKW(cmd) || IS_SETLK64(cmd) || IS_SETLKW64(cmd)) {
+#ifdef SSI_CFS_SKIP
+	/* Lock file against concurrent access */
+	CXLOCK(itoc(inode));
+#endif
+
+	if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
 		if (CFS_AT_SERVER(inode)) {
 			cfsd_proc_setlock_0(&la, &status);
 		} else {
@@ -722,29 +816,37 @@
 			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.
 		 */
+#ifndef CFS_MIGRATE_ACTIVE_PFS
+		if (!CFS_AT_SERVER(inode))
+#endif
+#ifdef CFS_MIRROR_LOCK_WAIT
+#ifdef CFS_FLOCK
+		if (!status) {
+			fl->fl_flags |= FL_SLEEP;
+			(void) do_vfs_lock(filp, fl);
+		}
+#else
 		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)) {
+#endif /* !CFS_FLOCK */
+#else
+#warn mirror locks could get out of sync with lock manager
+		if (!status) {
+			int err;
+			/* Can't fail if CFS server gaves us the lock */
+			fl->fl_flags &= ~FL_SLEEP;
+			err = posix_lock_file(filp, fl);
+			SSI_ASSERT(!err);
+		}
+#endif /* !CFS_MIRROR_LOCK_WAIT */
+	} else {
 		struct cfsgetlockres res;
-#ifdef KERNEL2616_53
-		struct file_lock *cfl;
 
-		/* Try local locking first */
-		cfl = posix_test_lock(filp, fl);
-		if (cfl != NULL) {
-			locks_copy_lock(fl, cfl);
-			goto sb_error_check;
-		}
-#endif
 		if (CFS_AT_SERVER(inode)) {
 			cfsd_proc_getlock_0(&la, &res);
 		} else {
@@ -754,7 +856,7 @@
 					(xdrproc_t)xdr_cfsgetlockres,
 					(caddr_t)&res);
 			if (status != 0)
-				goto sb_error_check;
+				goto out_unlock;
 		}
 
 		if (res.clro_status)
@@ -768,46 +870,39 @@
 			fl->fl_start = res.clro_start;
 			fl->fl_end = res.clro_end;
 		}
-	} else {
-		printk("cfs_lock: Unknown command %d\n", cmd);
-		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.
-	 */
-#warn mirror locks could get out of sync with lock manager
-	if (new_lock) {
-		if (!status) {
-			int err;
-			/* Can't fail if CFS server gaves us the lock */
-			fl->fl_flags &= ~FL_SLEEP;
-			err = posix_lock_file(filp, fl);
-			SSI_ASSERT(!err);
-		}
 	}
-#endif /* !CFS_MIRROR_LOCK_WAIT */
 
+out_unlock:
+#ifdef SSI_CFS_SKIP
+	CXUNLOCK(itoc(inode));
+#endif
 sb_error_check:
 	if (CFS_SB_RETRY(mip, status))
 		goto sb_down_retry;
 	CFS_SB_FSOP_DONE(mip);
 
-#if defined(CFS_FILE_RW_NOLOCK) && defined(CFS_ZAP_CACHES)
-	if (IS_GETLK(cmd) && !status) {
-		/*
-		 * Make sure we clear the cache whenever we try to get the lock.
-		 * This makes locking act as a cache coherency point.
-		 */
+#ifdef CFS_ZAP_CACHES
+	/*
+	 * Make sure we clear the cache whenever we try to get the lock.
+	 * This makes locking act as a cache coherency point.
+	 */
+	if (!status && !CFS_SB_HARD_MIP(mip) &&
+	    (fl->fl_type != F_UNLCK) &&
+	    (IS_SETLK(cmd) || IS_SETLKW(cmd))) {
+#ifdef KERNEL2616_53
+		cfs_sync_mapping(filp->f_mapping);
+#else
 		filemap_fdatawrite(filp->f_mapping);
 		down(&inode->i_sem);
 		cfs_wb_all(inode);	/* we may have slept */
 		up(&inode->i_sem);
 		filemap_fdatawait(filp->f_mapping);
+#endif
 		cfs_zap_caches(inode);
 	}
+#endif /* CFS_ZAP_CACHES */
+#if defined(CFS_ZAP_CACHES) || defined(KERNEL2616_53)
+out:
 #endif
 	return status;
 }
@@ -827,9 +922,12 @@
 	if (!inode)
 		return -EINVAL;
 
+#ifndef VPROC_HOLD_ZERO_GET_TASK
+	/* SSI_XXX: Not sure why this is needed. */
 	/* For unlock don't tell the server, our pid must still exist. */
 	if ((fl->fl_type == F_UNLCK) && ssi_vproc_destroy(current))
 		return 0; /* Let base code clean-up mirror */
+#endif
 
 	/* No mandatory locks over CFS */
 #ifdef KERNEL2616_53
@@ -858,9 +956,11 @@
 	if (!inode)
 		return -EINVAL;
 
+#ifndef VPROC_HOLD_ZERO_GET_TASK
 	/* For unlock don't tell the server, our pid must still exist. */
 	if ((fl->fl_type == F_UNLCK) && ssi_vproc_destroy(current))
 		return 0; /* Let base code clean-up mirror */
+#endif
 
 	/*
 	 * No BSD flocks over CFS allowed.
@@ -915,3 +1015,11 @@
 struct file_operations cfs_dev_operations = {
 	open: cfs_dev_open,
 };
+
+#ifdef CFS_IOCTL
+static long
+cfs_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	return CFS_PROTO(filp->f_dentry->d_inode)->ioctl(filp, cmd, arg);
+}
+#endif /* CFS_IOCTL */

Index: pagelist.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/pagelist.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- pagelist.c	24 Mar 2009 04:26:28 -0000	1.13
+++ pagelist.c	27 Oct 2009 03:18:29 -0000	1.14
@@ -23,10 +23,12 @@
 
 #define CFS_PARANOIA 1
 
+#ifndef CFS_CHARD_RACE_FIX
 /*
  * Spinlock
  */
 DEFINE_SPINLOCK(cfs_wreq_lock); 
+#endif
 
 static kmem_cache_t *cfs_page_cachep;
 

Index: dir.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/dir.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- dir.c	28 Mar 2009 23:44:15 -0000	1.27
+++ dir.c	27 Oct 2009 03:18:29 -0000	1.28
@@ -78,7 +78,9 @@
 struct file_operations cfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= cfs_readdir,
+#ifdef SSI_CFS_SKIP
 	.open		= cfs_open,
+#endif
 	.fsync		= cfs_fsync_dir,
 #ifdef SSI_CFS_EXNFS
 	.release	= cfs_release,
@@ -463,15 +465,14 @@
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 #ifdef CFS_ZAP_CACHES
 	res = cfs_revalidate_inode(inode);
@@ -739,18 +740,17 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 		dput(parent);
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return 0;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 	lock = TRUE;
-#endif
+#endif /* !CFS_FILE_RW_NOLOCK */
 
 	/* Revalidate parent directory attribute cache */
 #ifdef KERNEL2616_53
@@ -789,6 +789,9 @@
 
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
+#ifdef CFSTOK_INTR
+#error CFSTOK_INTERRUPTED not supported
+#endif
 	SSI_ASSERT(result == CFSTOK_HELD);
 	lock = TRUE;
 
@@ -947,6 +950,7 @@
 	res = ERR_PTR(-ENOMEM);
 	dentry->d_op = &cfs_dentry_operations;
 
+	/* TODO: allocate from kmem_cache */
 	dcd = (cfs_dcached_t *) kzmalloc(sizeof(cfs_dcached_t), GFP_KERNEL);
 	if (!dcd)
 		goto out;
@@ -954,16 +958,15 @@
 	result = cfstok_req(dir, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 		res = ERR_PTR(-EINTR);
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		goto out;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 	if ((error = _cfs_permission(dir, MAY_EXEC))) {
 		res = ERR_PTR(error);
@@ -1043,15 +1046,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1103,15 +1105,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1161,15 +1162,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1354,15 +1354,14 @@
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #endif
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 
 	/* Re-check directory permission with token held */
 	if ((error = _cfs_permission(dir, MAY_WRITE|MAY_EXEC)))
@@ -1576,9 +1575,10 @@
 		dir_rename = TRUE;
 	}
 #ifdef KERNEL2616_53
+#ifdef SSI_CFS_SKIP
 	else if (!(atomic_read(&ndentry->d_count) > 2))
 		nip->i_nlink--;
-
+#endif
 go_ahead:
 #endif
 	lock[0].lo_ip = odir;
@@ -1665,16 +1665,15 @@
 			goto fail_gunlock;
 		};
 	}
-#endif
 
 	/*
 	 * ... prune child dentries and writebacks if needed.
 	 *	(borrowed from NFS)
 	 */
 #ifdef CFS_ZAP_CACHES 
-	if (CFS_SB_HARD_MIP(itocmi(odir)) && !CFS_AT_SERVER(odir) &&
-	    atomic_read(&odentry->d_count) > 1) {
-		cfs_wb_all(ip);
+	if (atomic_read(&odentry->d_count) > 1) {
+		if (!CFS_SB_HARD_MIP(itocmi(odir)) && !CFS_AT_SERVER(odir))
+			cfs_wb_all(ip);
 		shrink_dcache_parent(odentry);
 	}
 #endif
@@ -1682,9 +1681,12 @@
 #ifdef KERNEL2616_53
 	if (!d_unhashed(ndentry))
 		d_drop(ndentry);
+#endif
+#ifdef SSI_SKIP
 	if (nip)
 		d_delete(ndentry);
 #endif
+#endif /* SSI_CFS_SKIP */
 
 	cfs_begin_data_update(ndir);
 	cfs_begin_data_update(odir);
@@ -1745,14 +1747,11 @@
 #endif
 			break;
 		case S_IFDIR:
-			/* SSI: will check permissions when we perform the op */
-#ifdef SSI_CFS_SKIP
 			/*
 			 * Optimize away all write operations, since the server
 			 * will check permissions when we perform the op.
 			 */
 			if ((mask & MAY_WRITE) && !(mask & MAY_READ))
-#endif
 				goto out;
  	}
 
@@ -1780,15 +1779,14 @@
 	result = cfstok_req(inode, CFSTOK_ATTR, CFSTOK_READ,
 		CFSTOK_HOLD|CFSTOK_BLOCK, NON_RANGE, NULL);
 #ifdef CFSTOK_INTR
-	if (result != CFSTOK_HELD) {
+	if (result == CFSTOK_INTERRUPTED) {
 #ifdef DEBUG
 		printk(KERN_DEBUG "%s: Interrupted\n", __FUNCTION__);
 #endif
 		return -EINTR;
 	}
-#else
-	SSI_ASSERT(result == CFSTOK_HELD);
 #endif
+	SSI_ASSERT(result == CFSTOK_HELD);
 #ifdef KERNEL2616_53
 	res = cfs_revalidate_inode(inode);
 	if (res == 0)

Index: cfstok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfstok.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cfstok.c	24 Mar 2009 04:26:28 -0000	1.21
+++ cfstok.c	27 Oct 2009 03:18:29 -0000	1.22
@@ -238,7 +238,7 @@
 	obj.obj_pp = &cliparam;
 	mhtok_init(&obj, &(itoc(ip)->c_mhold));
 
-	for( which = 1; which < CFSTOK_NTOKS + 1; which++) {
+	for(which = 1; which <= CFSTOK_NTOKS; which++) {
 
 		/*
 		 * Initialize HOLD list
@@ -272,7 +272,7 @@
 	obj.obj_pp = &cliparam;
 	mhtok_destroy(&obj, &(itoc(ip)->c_mhold));
 
-	for (which = 1; which < CFSTOK_NTOKS + 1; which++) {
+	for (which = 1; which <= CFSTOK_NTOKS; which++) {
 
 		list = ITOHDLIST( ip, which);
 #ifdef CFSTOKHOLD_LINUX_LIST
@@ -368,7 +368,6 @@
 	struct	cfstok		ctok;
 	object_t obj;
 
-	int	err;
 	int	ret = -1;
 	agent_t	agent;
 	waitcookie_t waitcookie;
@@ -380,7 +379,7 @@
 #ifdef SSI_CFS_POLICY
 	cfspol_touchfile(ip);
 #endif
-
+	BUG_ON(which_tok < 1 || which_tok > CFSTOK_NTOKS);
 	hlist = ITOHDLIST(ip, which_tok);
 	agent = (agent_t)this_node;
 #ifdef SSI_RANGE_TOKENS
@@ -415,25 +414,15 @@
 
 	CFSTOK_XLOCK( itoc(ip));/* exclusive lock token info in cfs inode*/
 
-	if (flags & CFSTOK_HOLD) {
-
-		if ((entry = (struct ctokhold  *)checklist(&obj, hlist, &ctok))) {
-
-			/*
-			 * Bump the hold count on cnode's hold list.
-			 */
-			++entry->ctok.held_count;
-
-			/*
-			 * Add the new entry to begining of caller's
-			 * hold list.
-			 */
-			if (phlist)
-				(void) instholdlist( phlist, &ctok, NULL, INS_START);
-			ret = CFSTOK_HELD;
-			goto unlock;
-		}
+	if ((flags & CFSTOK_HOLD) &&
+	    (entry = (struct ctokhold *)checklist(&obj, hlist, &ctok))) {
+		/*
+		 * Bump the hold count on cnode's hold list.
+		 */
+		++entry->ctok.held_count;
+		goto held_phlist;
 	}
+
 	/*
 	 * Check for deadlock on token request.
 	 * If you are holding a higher order token and request
@@ -445,12 +434,17 @@
 	 * CAN NOT ask for lower range while already holding
 	 * higher range tokens of same type.
 	 */
-	if (flags & CFSTOK_BLOCK) {
-		 if ( (err = outoforder( ip, &ctok)) != CFSTOK_OK) {
-			if ( err == CFSTOK_EOUTORDER)
-				panic("outoforder: hold request may deadlock");
-			else if ( err == CFSTOK_EOUTRANGE)
-				panic("outoforder: hold range may deadlock");
+	if ((flags & CFSTOK_BLOCK)) {
+		ret = outoforder(ip, &ctok);
+		switch (ret) {
+		case CFSTOK_OK:
+			break;
+		case CFSTOK_EOUTORDER:
+			panic("outoforder: hold request may deadlock");
+		case CFSTOK_EOUTRANGE:
+			panic("outoforder: hold range may deadlock");
+		default:
+			panic("outoforder: unknown status %d", ret);
 		}
 	}
 
@@ -464,20 +458,10 @@
 #endif
 			ret = tok_hold(&obj, ITOTCB(ip, which_tok), mode,
 				TOK_HOLD, agent, (waitcookie_t *)NULL);
-		if (ret) {
-			/*
-			 * Add to the front of caller's holdlist
-			 */
-			if (phlist)
-				(void) instholdlist( phlist, &ctok, NULL, INS_START);
-			/*
-			 * Add to the end of inode hold list
-			 */
-			(void) instholdlist(hlist, &ctok, NULL, INS_END);
-			ret = CFSTOK_HELD;
-		} else {
-			ret = CFSTOK_WOULDBLOCK;
-		}
+		if (ret)
+			goto held;
+
+		ret = CFSTOK_WOULDBLOCK;
 		goto unlock;
 	}
 
@@ -489,70 +473,67 @@
 	 * request to Token layer because, it is more clean
 	 * to do unlock at this layer.
 	 */
-
 #ifdef SSI_RANGE_TOKENS
 	if (BITVAL(which_tok) & CFSTOK_RANGE)
-		ret = !tok_hold_range(&obj,
+		ret = tok_hold_range(&obj,
 			ITORTCB(ip, which_tok), mode,
 			TOK_HOLD|TOK_REQUEST,
 			agent, &waitcookie, start, len );
 	else
 #endif
-		ret = !tok_hold(&obj, ITOTCB(ip, which_tok),
+		ret = tok_hold(&obj, ITOTCB(ip, which_tok),
 			mode, TOK_HOLD|TOK_REQUEST,
 			agent, &waitcookie);
-	if (ret) {
-		/* Before release TCB exclusive lock
-		 * indicate that this process has the
-		 * token.
-		 */
+	if (ret)
+		goto held;
+
+	/* Before release TCB exclusive lock
+	 * indicate that this process has the
+	 * token.
+	 */
 #ifdef CFSTOK_INTR
-		entry = instholdlist( hlist, &ctok, NULL, INS_END);
+	entry = instholdlist( hlist, &ctok, NULL, INS_END);
 #else
-		(void) instholdlist( hlist, &ctok, NULL, INS_END);
+	(void) instholdlist( hlist, &ctok, NULL, INS_END);
 #endif
-		CFSTOK_XRELE(itoc(ip));
+	CFSTOK_XRELE(itoc(ip));
 #ifdef SSI_NOTYET
-		if (flags & CFSTOK_CXUNLOCK)
-			CXUNLOCK(cp);
+	if (flags & CFSTOK_CXUNLOCK)
+		CXUNLOCK(cp);
 #endif
-		process_msgs(FALSE);
-		DBG(DBGCLI,("cfstok_req:tok_hold_range waiting 0x%x\n",
-			waitcookie));
-		/* Track token waits. */
+	process_msgs(FALSE);
+	DBG(DBGCLI,("cfstok_req:tok_hold_range waiting 0x%x\n",
+		waitcookie));
+	/* Track token waits. */
 #ifdef SSI_RANGE_TOKENS
-		if (BITVAL(which_tok) & CFSTOK_RANGE)
-			tok_wait_range(waitcookie);
-		else
+	if (BITVAL(which_tok) & CFSTOK_RANGE)
+		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;
-			}
+		if (tok_wait(waitcookie)) {
+			/* Interrupted */
+			CFSTOK_XLOCK( itoc(ip));
+			BUG_ON(list_empty(&entry->ctok_list));
+			delholdlist(entry);
+			ret = CFSTOK_INTERRUPTED;
+			goto unlock;
+		}
 #else
-			tok_wait( ITOTCB(ip, which_tok),
-				waitcookie );
+		tok_wait( ITOTCB(ip, which_tok),
+			waitcookie );
 #endif /* !CFSTOK_INTR */
 #ifdef SSI_NOTYET
-		if (flags & CFSTOK_CXUNLOCK)
-			CXLOCK(cp);
+	if (flags & CFSTOK_CXUNLOCK)
+		CXLOCK(cp);
 #endif
-		ret = CFSTOK_HELD;
-		if (phlist)
-			(void) instholdlist( phlist, &ctok, NULL, INS_START);
-		goto no_unlock;
-	} else {
-		ret = CFSTOK_HELD;
-		(void) instholdlist( hlist, &ctok, NULL, INS_END);
-		if (phlist)
-			(void) instholdlist( phlist, &ctok, NULL, INS_START);
-		goto unlock;
-	}
+	/*
+	 * Add to the front of caller's holdlist
+	 */
+	if (phlist)
+		(void) instholdlist( phlist, &ctok, NULL, INS_START);
+	ret = CFSTOK_HELD;
+	goto no_unlock;
 
 unlock:
 	CFSTOK_XRELE(itoc(ip));
@@ -560,6 +541,20 @@
 no_unlock:
 	SSI_ASSERT(ret != -1);
 	return ret;
+
+held:
+	/*
+	 * Add to the end of inode hold list
+	 */
+	(void) instholdlist(hlist, &ctok, NULL, INS_END);
+held_phlist:
+	/*
+	 * Add to the front of caller's holdlist
+	 */
+	if (phlist)
+		(void) instholdlist( phlist, &ctok, NULL, INS_START);
+	ret = CFSTOK_HELD;
+	goto unlock;
 }
 
 /**
@@ -633,11 +628,10 @@
 			       	point[x]->lo_mode, CFSTOK_HOLD|CFSTOK_BLOCK,
 				NON_RANGE, phlist);
 #ifdef CFSTOK_INTR
-		if (status != CFSTOK_HELD)
+		if (status == CFSTOK_INTERRUPTED)
 			break;
-#else
-		SSI_ASSERT(status == CFSTOK_HELD);
 #endif
+		SSI_ASSERT(status == CFSTOK_HELD);
 	}
 
 	/* On error unlock the locks that we did hold */
@@ -841,8 +835,8 @@
 	/*
 	 * check for any token held above the requested hold
  	 */
-	for( check = ctok->which + 1; check < CFSTOK_NTOKS; check++){
-		hlist = ITOHDLIST( ip, ctok->which);
+	for(check = ctok->which + 1; check <= CFSTOK_NTOKS; check++){
+		hlist = ITOHDLIST( ip, check);
 #ifdef CFSTOKHOLD_LINUX_LIST
 		/*
 		 * check for matching pids i.e other
@@ -949,7 +943,7 @@
 void
 cfstokhold_init(void)
 {
-	ctokhold_cachep = kmem_cache_create("cfstok_cache",
+	ctokhold_cachep = kmem_cache_create("cfs_ctokhold",
 				sizeof(struct ctokhold), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -1461,6 +1455,7 @@
 	struct inode *ip;
 
 	ip = (struct inode *)objp->word1;
+	SSI_ASSERT(atomic_read(&ip->i_count));
 	atomic_inc(&ip->i_count);
 }
 
@@ -1842,6 +1837,7 @@
 	return buffer;
 }
 
+#ifdef SSI_NOT_YET
 void
 cfstok_checkholds(struct cnode *cp)
 {
@@ -1849,7 +1845,7 @@
 	int which_tok;
 
 	CFSTOK_XLOCK(cp);
-	for (which_tok = 0 ; which_tok < CFSTOK_NTOKS; which_tok++) {
+	for (which_tok = 1 ; which_tok <= CFSTOK_NTOKS; which_tok++) {
 		hlist = ITOHDLIST(ctoi(cp), which_tok);
 		for (foundptr = *hlist; foundptr; foundptr = foundptr->next) {
 			if (foundptr->ctok.unique == NSC_UNIQUE_ID)
@@ -1858,6 +1854,7 @@
 	}
 	CFSTOK_XRELE(cp);
 }
+#endif
 #endif /* DEBUG */
 
 /*
@@ -2069,7 +2066,7 @@
 	CFSTOK_XLOCK(itoc(ip));
 
 	/* Skip MHOLD token for since it is never waited for */
-	for (which = 1; which < CFSTOK_NTOKS + 1; which++) {
+	for (which = 1; which <= CFSTOK_NTOKS; which++) {
 		obj.word1 = (long)ip;
 		obj.word2 = (long)which;
 		obj.obj_pp = &cliparam;
@@ -2101,7 +2098,7 @@
 void
 cfs_delrel_init(void)
 {
-	delrel_cachep = kmem_cache_create("cfsdr_cache",
+	delrel_cachep = kmem_cache_create("cfs_delrel",
 				sizeof(struct delrel), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -2142,7 +2139,6 @@
 
 	while(1) {
 		WAIT_EVENT(&delrel_ev);
-		/* allow_reschedule(); */
 
 		LOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
 
@@ -2150,7 +2146,6 @@
 		while(delrel_list) {
 			/* Pull one from list */
 			drp = delrel_list;
-			mb();
 			delrel_list = drp->dr_next;
 
 			UNLOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
@@ -2174,6 +2169,7 @@
 			LOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
 		}
 		UNLOCK_SOFTIRQ_SPIN_LOCK(&dr_list_lock);
+		allow_reschedule();
 	}
 }
 
@@ -2191,7 +2187,6 @@
 	/* 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);
 
@@ -2294,13 +2289,12 @@
 cfstok_start_svrcfstok(cnode_t *cp)
 {
 	struct cfshaveargs args;
+	enum cfsstat status;
 	int error;
-	clusternode_t server = ctomi(cp)->mi_server;
-	struct inode *ip = ctoi(cp);
 	object_t obj;
 
 	/* Force MHOLD to have a single count */
-	obj.word1 = (long)ip;
+	obj.word1 = (long)ctoi(cp);
 	obj.word2 = (long)CFSTOK_MHOLD;
 	obj.obj_pp = &cliparam;
 	/* Resets the count to 1. Don't need to send the count
@@ -2315,16 +2309,13 @@
 	args.chr_wopncnt = cp->c_wopncnt;
 #endif
 
-	if (server == this_node) {
-		enum cfsstat status;
-
+	if (ctomi(cp)->mi_server == this_node) {
 		cfsd_proc_haverpc_0(&args, &status);
 		error = status;
 	} else {
 		nsc_handle_t *th;
-		enum cfsstat status;
 
-		th = nsc_hcreate(server, cluster_fs_svc, 0, 0);
+		th = nsc_hcreate(ctomi(cp)->mi_server, cluster_fs_svc, 0, 0);
 		error = nsc_rcall(th, CFSD_PROC_HAVERPC,
 				(xdrproc_t)xdr_cfshaveargs,
 				(caddr_t)&args,
@@ -2401,7 +2392,7 @@
 #endif /* CFS_FASTPATH */
 	/* Do individuals, except MHOLD (handled by RPC above). */
 	/* MHOLD also never needs tok_rebuild() for non-do_haves phase */
-	for (which = 1; which < CFSTOK_NTOKS + 1; which++) {
+	for (which = 1; which <= CFSTOK_NTOKS; which++) {
 		obj.word2 = (long)which;
 #ifdef SSI_RANGE_TOKENS
 		if (BITVAL(which) & CFSTOK_RANGE)
@@ -2601,7 +2592,7 @@
 	CFSTOK_XLOCK(cp);
 	obj.word1 = (long)ip;
 	obj.obj_pp = &cliparam;
-	for (which = 1 ; which < CFSTOK_NTOKS + 1; which++) {
+	for (which = 1 ; which <= CFSTOK_NTOKS; which++) {
 		/* Count token waits. */
 		obj.word2 = (long)which;
 #ifdef SSI_RANGE_TOKENS

Index: cfsproc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfsproc.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- cfsproc.c	24 Mar 2009 04:26:28 -0000	1.33
+++ cfsproc.c	27 Oct 2009 03:18:29 -0000	1.34
@@ -50,13 +50,14 @@
 
 #ifdef RCU_CFSTOK_TABLE
 	hp = hfind(fh);
+	/* No need to HASH_HOLD() held by hfind() */
 #else
 	hp = svrtok_lookup(fh, NULL, NULL);
+	/* No need to HASH_HOLD() held by svrtok_lookup() */
 #endif
 	if (hp == NULL)
 		panic("fhtohp: Can't find hash structure");
-	/* No need to HASH_HOLD() held by svrtok_lookup() */
[...1545 lines suppressed...]
+
+		if (pstate) {
+			ssi_procstate_get(&save_pstate);
+			ssi_procstate_set(pstate);
+		}
+
+		/* Linux fs/ioctl.c:do_ioctl() */
+		*rval = do_ioctl(hp->sct_fp, args->cia_cmd, (unsigned long __user)*arg);
+
+		if (pstate)
+			ssi_procstate_set(&save_pstate);
+	}
+	HASH_RELE(hp);
+	return 0;
+}
+#endif /* CFS_IOCTL */
+
 #ifdef SKIP_NOTUSED
 /*
  * CFS Server procedures.

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

Index: proc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/proc.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- proc.c	24 Mar 2009 04:26:28 -0000	1.20
+++ proc.c	27 Oct 2009 03:18:29 -0000	1.21
@@ -46,101 +46,80 @@
 #endif
 #include <cluster/assert.h>
 
+/* TODO: NSC / ICS alloc from mempool and set GFP_ATOMIC for RPC_TASK_SWAPPER.
+ * See rpc_malloc()
+ */
+
 #ifdef CFS_PAGEVEC
-#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;			\
-		}							\
-	}								\
+/* Used by MAP_CFS_PAGEVEC() to avoid kmap_high() deadlock. */
+static DECLARE_MUTEX(map_cfs_pagevec_sem);
+
+#define CFS_ASYNC(_data) (_data->flags & RPC_TASK_ASYNC)
+
+/* _data argument is pointer to struct cfs_read_data or cfs_write_data */
+#define MAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+	int i, len = (_data)->count; \
+ \
+	(_vlen) = (_vlen) ? : \
+			((_data)->pgbase + (_data)->count + PAGE_CACHE_SIZE - 1) \
+			>> PAGE_SHIFT; \
+ \
+	(_vec) = kmalloc_nofail((_vlen) * sizeof(struct kvec)); \
+ \
+	if (PageHighMem((_data)->pagevec[0])) \
+		down(&map_cfs_pagevec_sem); \
+ \
+	(_vec)[0].iov_base = kmap((_data)->pagevec[0]) + (_data)->pgbase; \
+	(_vec)[0].iov_len = len < (PAGE_SIZE - (_data)->pgbase) ? len : \
+					(PAGE_SIZE - (_data)->pgbase); \
+	len -= (PAGE_SIZE - (_data)->pgbase); \
+ \
+	i = 1; \
+	while (len > 0) { \
+		(_vec)[i].iov_base = kmap((_data)->pagevec[i]); \
+		(_vec)[i].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; \
+		len -= PAGE_SIZE; \
+		i++; \
+	} \
+ \
+	if (PageHighMem((_data)->pagevec[0])) \
+		up(&map_cfs_pagevec_sem); \
+ \
+	BUG_ON(i != (_vlen)); \
 } 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);							\
+#define UNMAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+	int i; \
+ \
+	for (i = 0; i < (_vlen); i++) \
+		kunmap((_data)->pagevec[i]); \
+	kfree(_vec); \
 } 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(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(sizeof(struct kvec) * _vlen, GFP_NOFS|__GFP_NOFAIL); \
-									\
-			list_for_each(pos, &_data->pages) {		\
-				struct cfs_page *req = cfs_list_entry(pos); \
+#ifndef ICS_OOL_STRUCT_PAGES
+#define CFS_PAGEVEC_MAP_BUFFER(_data, _buf, _vlen) do {			\
+	_vlen = _vlen ? : (_data->pgbase + _data->count + PAGE_CACHE_SIZE - 1) \
+			>> PAGE_SHIFT; \
 									\
-				__kvec->iov_base = kmap(req->wb_page) + req->wb_offset; \
-				__kvec->iov_len = req->wb_bytes;	\
-				__kvec++;				\
-			}						\
+	if (_vlen == 1) {						\
+		_buf = kmap(_data->pagevec[0]);				\
+	} else {							\
+		_buf = vmap(_data->pagevec, _vlen, VM_MAP, PAGE_KERNEL); \
+		if (!_buf) {						\
+			nidelay(HZ/50);					\
+			goto sb_down_retry;				\
 		}							\
-	} while (0)
+	}								\
+} while (0)
 
-#define CFS_PAGEVEC_UNMAP(_data, _kvec)					\
-	do {								\
-		if (unlikely(_data->page)) {				\
-			kunmap(_data->page);				\
-		} else {						\
-			struct list_head *pos;				\
-			list_for_each(pos, &_data->pages) {		\
-				struct cfs_page *req = cfs_list_entry(pos); \
-				kunmap(req->wb_page);			\
-			}						\
-		}							\
-		kfree(_kvec);						\
-	} while (0)
-#endif
+#define CFS_PAGEVEC_UNMAP_BUFFER(_data, _buf, _vlen) do {		\
+	if (_vlen == 1) {						\
+		kunmap(_data->pagevec[0]);				\
+	} else								\
+		vunmap(_buf);						\
+} while (0)
+#endif /* !ICS_OOL_STRUCT_PAGES */
+#endif /* CFS_PAGEVEC */
 
 
 /*
@@ -237,7 +216,11 @@
 		struct cfs_nettok res_toks[CFS_NTOKS];
 
 		res.cdr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(arg.cgia_fh), fhandle);
+#else
 		arg.cgia_fh = *fhandle;
+#endif
 		cfstok_get_agent(&arg.cgia_agent);
 		status = rcfscall(server, CFSD_PROC_GETINODE,
 				(xdrproc_t)xdr_cfsgetinoarg,
@@ -366,7 +349,11 @@
 		struct cfslookargs args;
 		int result;
 
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.clua_fhandle), itocfh(dir));
+#else
 		args.clua_fhandle = *itocfh(dir);
+#endif
 		args.clua_name = *name;
 		cfstok_get_agent(&args.clua_agent); /* notused */
 
@@ -414,7 +401,11 @@
 		struct cfs_nettok res_toks[CFS_NTOKS];
 
 		res.cdr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.clua_fhandle), itocfh(dir));
+#else
 		args.clua_fhandle = *itocfh(dir);
+#endif
 		args.clua_name = *name;
 		cfstok_get_agent(&args.clua_agent);
 
@@ -492,36 +483,100 @@
 	return status;
 }
 
+#ifdef CFS_PAGEVEC
+static int
+cfs_proc_read(struct cfs_read_data *data)
+{
+	cfs_mntinfo_t *mip = itocmi(data->inode);
+	unsigned long mycount = data->count;
+	unsigned int vlen = 0;
+	int status;
+
+	dprintk("CFS call  read %d @ %Ld\n", data->count, (long long)data->offset);
+
+	CFS_SB_FSOP_START(mip);
+sb_down_retry:
+	status = (CFS_ASYNC(data) ? CFS_SB_CHECK_NOHANG(mip): CFS_SB_CHECK(mip));
+	if (status)
+		goto sb_error_check;
+
+#ifdef CFS_UPDATE_ATTR_LOCKED
+#error no longer supported
+#endif
+	if (CFS_AT_SERVER(data->inode)) {
+		struct kvec *vec; /* SSI_XXX: belongs in cfs_read_data struct? */
+
+		MAP_CFS_PAGEVEC(data, vec, vlen);
+		status = cfsd_read(itoc(data->inode)->c_hp, data->offset,
+				   vec, vlen, &mycount);
+		UNMAP_CFS_PAGEVEC(data, vec, vlen);
+
+		if (status == 0) {
+			data->res_count = mycount;
+			status = (ssize_t)mycount;
+			cfs_update_attr(itoc(data->inode)->c_hp, data->inode, 1);
+		}
+	} else {
+		struct cfsrdresults *res_p = NULL;
+		int rval;
+#ifndef ICS_OOL_STRUCT_PAGES
+		caddr_t buffer;
+#endif
+
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(data->args.cra_fhandle), itocfh(data->inode));
+#else
+		data->args.cra_fhandle = *itocfh(data->inode);
+#endif
+		data->args.cra_offset = data->offset;
+#ifdef ICS_OOL_STRUCT_PAGES
+		vlen = data->pgbase | (data->count << PAGE_SHIFT);
+
+		status = RCFS_READ(mip->mi_server, &rval, &data->args, &res_p,
+				   &data->pagevec, &vlen);
+#else
+		CFS_PAGEVEC_MAP_BUFFER(data, buffer, vlen);
+		status = RCFS_READ(mip->mi_server, &rval,
+				   &data->args, &res_p,
+				   &(buffer + data->pgbase), &mycount);
+		CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, vlen);
+#endif /* !ICS_OOL_STRUCT_PAGES */
+		if (status != 0 || rval != 0) {
+			status = -ETIMEDOUT;
+		} else if (status == 0) {
+			status = res_p->crr_status;
+			if (status == 0) {
+#ifdef ICS_OOL_STRUCT_PAGES
+				mycount = (vlen >> PAGE_SHIFT);
+#endif
+				status = (ssize_t)mycount;
+				data->res_count = mycount;
+				cfs_refresh_inode(data->inode, &(res_p->crr_attr));
+			}
+			(void) xdr_free(xdr_cfsrdresults_p, &res_p);
+		}
+	}
+
+sb_error_check:
+	if (CFS_ASYNC(data) ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
+		goto sb_down_retry;
+	CFS_SB_FSOP_DONE(mip);
+
+	dprintk("CFS reply read: %d\n", status);
+	return status;
+}
+#else /* CFS_PAGEVEC */
 /* The async arg is used to inform this routine it is being called from
  * an async handler process.  It should not hang on a down hard mount.
  */
 static int
-#ifdef CFS_PAGEVEC
-cfs_proc_read(struct cfs_read_data *data)
-#else
 cfs_proc_read(struct inode *inode, loff_t offset, unsigned int count,
 		 void *buffer, int async)
-#endif
 {
 	int			status;
-#ifdef CFS_PAGEVEC
-	struct kvec *kvec;
-#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
 
-#ifdef CFS_PAGEVEC
-	dprintk("CFS call  read %d @ %Ld\n", data->count, (long long)data->offset);
-#else
 	dprintk("CFS call  read %d @ %Ld\n", count, (long long)offset);
-#endif
 
 	CFS_SB_FSOP_START(mip);
 sb_down_retry:
@@ -529,31 +584,11 @@
 	if (status)
 		goto sb_error_check;
 
-#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
-	CFS_PAGEVEC_MAP(data, kvec, vlen);
-#endif
-
 	if (CFS_AT_SERVER(inode)) {
-#ifdef CFS_PAGEVEC
-		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
 		unsigned long mycount = count;
 
 		status = cfsd_read(itoc(inode)->c_hp, offset, buffer, &mycount);
 		if (status == 0) {
-#endif /* !CFS_PAGEVEC */
 			status = (ssize_t)mycount;
 #ifdef CFS_UPDATE_ATTR_LOCKED
 			CXLOCK(itoc(inode));	/* Prevent i_sem deadlock with VFS waiter */
@@ -564,69 +599,29 @@
 #endif
 		}
 	} else {
-		struct cfsreadargs args;
 		struct cfsrdresults *res_p = NULL;
+		struct cfsreadargs args;
 		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);
-#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
-		args.cra_offset = data->offset;
-		args.cra_pgbase = data->pgbase;
-
-		status = RCFS_READ(mip->mi_server,&rval,
-				   &args, &res_p, &mycount, &kvec, &vlen);
-#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) {
-#ifdef CFS_PAGEVEC_BUFFER_READ
-			CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, 0);
-#endif
 			status = -ETIMEDOUT;
 		} 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);
 		}
 	}
 
-#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_READ)
-	CFS_PAGEVEC_UNMAP(data, kvec);
-#endif
 sb_error_check:
 	if (async ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
 		goto sb_down_retry;
@@ -635,63 +630,104 @@
 	dprintk("CFS reply read: %d\n", status);
 	return status;
 }
+#endif /* !CFS_PAGEVEC */
 
-/* The async arg is used to inform this routine it is being called from
- * an async handler process.  It should not hang on a down hard mount.
- */
-static int
 #ifdef CFS_PAGEVEC
+static int
 cfs_proc_write(struct cfs_write_data *data)
-#else
-cfs_proc_write(struct inode *inode, loff_t offset, unsigned int count,
-		 void *buffer, int stable, int async)
-#endif
 {
 	int			status;
-#ifdef CFS_PAGEVEC
-	struct kvec *kvec;
 	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;
+	unsigned int vlen = 0;
+
+	dprintk("CFS call  write %d @ %Ld\n", (ssize_t)data->count, (long long)data->offset);
+
+	CFS_SB_FSOP_START(mip);
+sb_down_retry:
+	status = (CFS_ASYNC(data) ? CFS_SB_CHECK_NOHANG(mip): CFS_SB_CHECK(mip));
+	if (status)
+		goto sb_error_check;
+
+#ifdef CFS_UPDATE_ATTR_LOCKED
+#error no longer supported
+#endif
+	if (CFS_AT_SERVER(data->inode)) {
+		struct kvec *vec; /* SSI_XXX: belongs in cfs_write_data struct? */
+
+		MAP_CFS_PAGEVEC(data, vec, vlen);
+		status = cfsd_write(itoc(data->inode)->c_hp, data->offset,
+				    vec, vlen, (unsigned long)data->count,
+				    data->stable);
+		UNMAP_CFS_PAGEVEC(data, vec, vlen);
+
+		if (status == 0)
+			cfs_update_attr(itoc(data->inode)->c_hp, data->inode, 1);
+	} else {
+		struct cfswriteres *res_p = NULL;
+		int rval;
+#ifndef ICS_OOL_STRUCT_PAGES
+		caddr_t buffer;
 #endif
+
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(data->args.cwa_fhandle), itocfh(data->inode));
 #else
-	cfs_mntinfo_t *mip = itocmi(inode);
+		data->args.cwa_fhandle = *itocfh(data->inode);
 #endif
+		data->args.cwa_offset = data->offset;
+		data->args.cwa_stable = data->stable;
+#ifdef ICS_OOL_STRUCT_PAGES
+		vlen = data->pgbase | (data->count << PAGE_SHIFT);
 
-#ifdef CFS_PAGEVEC
-	dprintk("CFS call  write %d @ %Ld\n", (ssize_t)data->count, (long long)data->offset);
+		status = RCFS_WRITE(mip->mi_server, &rval, &data->args, &res_p,
+				&data->pagevec, vlen);
 #else
+#warning ICS should support sendpage
+		CFS_PAGEVEC_MAP_BUFFER(data, buffer, vlen);
+		status = RCFS_WRITE(mip->mi_server, &rval, &data->args, &res_p,
+				    &(buffer + data->pgbase), data->count);
+		CFS_PAGEVEC_UNMAP_BUFFER(data, buffer, vlen);
+#endif /* !ICS_OOL_STRUCT_PAGES */
+		if (status != 0 || rval != 0) {
+			status = -ETIMEDOUT;
+		} else if (status == 0) {
+			status = res_p->cwr_status;
+			if (status == 0)
+				cfs_refresh_inode(data->inode, &res_p->cwr_attr);
+			(void) xdr_free(xdr_cfswriteres_p, &res_p);
+		}
+	}
+
+sb_error_check:
+	if (CFS_ASYNC(data) ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
+		goto sb_down_retry;
+	CFS_SB_FSOP_DONE(mip);
+
+	dprintk("CFS reply write: %d\n", status);
+	return (status < 0) ? status : (ssize_t)data->count;
+}
+#else /* CFS_PAGEVEC */
+/* The async arg is used to inform this routine it is being called from
+ * an async handler process.  It should not hang on a down hard mount.
+ */
+static int
+cfs_proc_write(struct inode *inode, loff_t offset, unsigned int count,
+		 void *buffer, int stable, int async)
+{
+	int			status;
+	cfs_mntinfo_t *mip = itocmi(inode);
+
 	dprintk("CFS call  write %d @ %Ld\n", count, (long long)offset);
-#endif
+
 	CFS_SB_FSOP_START(mip);
 sb_down_retry:
 	status = (async ? CFS_SB_CHECK_NOHANG(mip): CFS_SB_CHECK(mip));
 	if (status)
 		goto sb_error_check;
 
-#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);
-#endif /* !CFS_PAGEVEC */
 		if (status == 0) {
 #ifdef CFS_UPDATE_ATTR_LOCKED
 			CXLOCK(itoc(inode));	/* Prevent i_sem deadlock with VFS waiter */
@@ -702,31 +738,14 @@
 #endif
 		}
 	} else {
-		struct cfswriteargs args;
 		struct cfswriteres *res_p = NULL;
 		int rval;
 
 		args.cwa_fhandle = *itocfh(inode);
-#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) {
 			status = -ETIMEDOUT;
 		} else if (status == 0) {
@@ -737,21 +756,15 @@
 		}
 	}
 
-#if defined(CFS_PAGEVEC) && !defined(CFS_PAGEVEC_BUFFER_WRITE)
-	CFS_PAGEVEC_UNMAP(data, kvec);
-#endif
 sb_error_check:
 	if (async ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
 		goto sb_down_retry;
 	CFS_SB_FSOP_DONE(mip);
 
 	dprintk("CFS reply write: %d\n", status);
-#ifdef CFS_PAGEVEC
-	return (status < 0) ? status : (ssize_t)data->count;
-#else
 	return status < 0? status : count;
-#endif
 }
+#endif /* !CFS_PAGEVEC */
 
 static int
 cfs_proc_create(struct inode *dir, struct qstr *name, int mode,
@@ -791,8 +804,13 @@
 		struct svrcfstok *hp;
 
 		/* File doesn't exist. Create it and set attrs */
+#ifdef CFS_UMASK_FIX
+		status = cfsd_create(itoc(dir)->c_hp, name, mode,
+					0, S_IFREG, 0, flags, &hp);
+#else
 		status = cfsd_create(itoc(dir)->c_hp, name, mode,
 					S_IFREG, 0, flags, &hp);
+#endif
 		if (!status) {
 			/* Directory inode changed fix CFS inode */
 			cfs_update_attr(itoc(dir)->c_hp, dir, 0);
@@ -810,9 +828,16 @@
 		struct cfscreatargs args;
 
 		res.ccr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.cca_fhandle), itocfh(dir));
+#else
 		args.cca_fhandle = *itocfh(dir);
+#endif
 		args.cca_name = *name;
 		args.cca_mode = mode;
+#ifdef CFS_UMASK_FIX
+		args.cca_umask = current->fs ? current->fs->umask : 0;
+#endif
 		args.cca_type = S_IFREG;
 		args.cca_dev = 0;
 		args.cca_flags = flags;
@@ -879,7 +904,11 @@
 		struct cfsrmres res;
 		struct cfsunlinkargs args;
 
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.crma_fhandle), itocfh(dir));
+#else
 		args.crma_fhandle = *itocfh(dir);
+#endif
 		args.crma_qstr = *name;
 
 		status = rcfscall(mip, CFSD_PROC_UNLINK,
@@ -951,9 +980,15 @@
 		struct cfsrnmres res;
 		struct cfsrnmargs args;
 
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.crna_from.cda_fhandle), itocfh(old_dir));
+		args.crna_from.cda_name = *old_name;
+		COPY_CFS_FH(&(args.crna_to.cda_fhandle), itocfh(new_dir));
+#else
 		args.crna_from.cda_fhandle = *itocfh(old_dir);
 		args.crna_from.cda_name = *old_name;
 		args.crna_to.cda_fhandle = *itocfh(new_dir);
+#endif
 		args.crna_to.cda_name = *new_name;
 		cfstok_get_agent(&args.crna_agent);
 
@@ -1037,7 +1072,11 @@
 		struct cfslinkargs args;
 
 		args.cla_from = *itocfh(inode);
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.cla_to.cda_fhandle), itocfh(dir));
+#else
 		args.cla_to.cda_fhandle = *itocfh(dir);
+#endif
 		args.cla_to.cda_name = *name;
 		args.fsuid = current->fsuid;
 		args.fsgid = current->fsgid;
@@ -1130,7 +1169,11 @@
 		struct cfsslargs args;
 
 		res.ccr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.csla_from.cda_fhandle), itocfh(dir));
+#else
 		args.csla_from.cda_fhandle = *itocfh(dir);
+#endif
 		args.csla_from.cda_name = *name;
 		args.csla_tnm = (char *)path;
 		args.fsuid = current->fsuid;
@@ -1210,8 +1253,13 @@
 	if (CFS_AT_SERVER(dir)) {
 		struct svrcfstok *hp;
 
+#ifdef CFS_UMASK_FIX
+		status = cfsd_create(itoc(dir)->c_hp, name, mode, 0, S_IFDIR, 0,
+			 0, &hp);
+#else
 		status = cfsd_create(itoc(dir)->c_hp, name, mode, S_IFDIR, 0,
 			 0, &hp);
+#endif
 		if (status == 0) {
 			/* Directory inode changed fix CFS inode */
 			cfs_update_attr(itoc(dir)->c_hp, dir, 0);
@@ -1229,9 +1277,16 @@
 		struct cfs_nettok res_toks[CFS_NTOKS];
 
 		res.ccr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.cca_fhandle), itocfh(dir));
+#else
 		args.cca_fhandle = *itocfh(dir);
+#endif
 		args.cca_name = *name;
 		args.cca_mode = mode;
+#ifdef CFS_UMASK_FIX
+		args.cca_umask = current->fs ? current->fs->umask : 0;
+#endif
 		args.cca_type = S_IFDIR;
 		args.cca_dev = 0;
 		args.fsuid = current->fsuid;
@@ -1299,7 +1354,11 @@
 		struct cfsrmdrargs args;
 		struct cfsrmres res;
 
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.crmda_fhandle), itocfh(dir));
+#else
 		args.crmda_fhandle = *itocfh(dir);
+#endif
 		args.crmda_name = *name;
 
 		status = rcfscall(mip, CFSD_PROC_RMDIR,
@@ -1410,8 +1469,13 @@
 		struct svrcfstok *hp;
 
 		/* File doesn't exist. Create it and set attrs */
+#ifdef CFS_UMASK_FIX
+		status = cfsd_create(itoc(dir)->c_hp, name, mode, 0,
+					type, rdev, 0, &hp);
+#else
 		status = cfsd_create(itoc(dir)->c_hp, name, mode,
 					type, rdev, 0, &hp);
+#endif
 		if (!status) {
 			/* Directory inode changed fix CFS inode */
 			cfs_update_attr(itoc(dir)->c_hp, dir, 0);
@@ -1429,9 +1493,16 @@
 		struct cfs_nettok res_toks[CFS_NTOKS];
 
 		res.ccr_res_toks = res_toks;
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.cca_fhandle), itocfh(dir));
+#else
 		args.cca_fhandle = *itocfh(dir);
+#endif
 		args.cca_name = *name;
 		args.cca_mode = mode;
+#ifdef CFS_UMASK_FIX
+		args.cca_umask = current->fs ? current->fs->umask : 0;
+#endif
 		args.cca_type = type;
 		args.cca_dev = rdev;
 		args.fsuid = current->fsuid;
@@ -1561,7 +1632,11 @@
 		struct cfsdiropargs args;
 		struct cfsrevres res;
 
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.cda_fhandle), itocfh(dir));
+#else
 		args.cda_fhandle = *itocfh(dir);
+#endif
 		args.cda_name = *name;
 
 		status = rcfscall(mip, CFSD_PROC_REVALIDATE,
@@ -1599,8 +1674,6 @@
 	cfs_mntinfo_t *mip = itocmi(inode);
 #else
 	cfs_mntinfo_t *mip = itocmi(data->inode);
-	struct inode *inode = data->inode;
-	char async = (data->flags & RPC_TASK_ASYNC);
 #endif
 
 #ifdef CFS_PAGEVEC
@@ -1610,30 +1683,41 @@
 #endif
 	CFS_SB_FSOP_START(mip);
 sb_down_retry:
+#ifdef CFS_PAGEVEC
+	status = (CFS_ASYNC(data) ? CFS_SB_CHECK_NOHANG(mip): CFS_SB_CHECK(mip));
+#else
 	status = (async ? CFS_SB_CHECK_NOHANG(mip): CFS_SB_CHECK(mip));
+#endif
 	if (status)
 		goto sb_error_check;
 
-	if (CFS_AT_SERVER(inode)) {
 #ifdef CFS_PAGEVEC
-		cfsd_sync(itoc(inode)->c_hp, data->offset, data->count);
+	if (CFS_AT_SERVER(data->inode)) {
+		cfsd_sync(itoc(data->inode)->c_hp, data->offset, data->count);
+		cfs_update_attr(itoc(data->inode)->c_hp, data->inode, 1);
 #else
+	if (CFS_AT_SERVER(inode)) {
 		cfsd_sync(itoc(inode)->c_hp, offset, count);
-#endif
 		cfs_update_attr(itoc(inode)->c_hp, inode, 1);
+#endif
 		status = 0;
 	} else {
 		struct cfscommitargs args;
 		struct cfscommitres res;
 
-		args.coma_fhandle = *itocfh(inode);
 #ifdef CFS_PAGEVEC
+#ifdef CFS_EXPORT_OPS
+		COPY_CFS_FH(&(args.coma_fhandle), itocfh(data->inode));
+#else
+		args.coma_fhandle = *itocfh(data->inode);
+#endif
 		args.coma_offset = data->offset;
 		args.coma_count = data->count;
 #else
+		args.coma_fhandle = *itocfh(inode);
 		args.coma_offset = offset;
 		args.coma_count = count;
-#endif
+#endif /* !CFS_PAGEVEC */
 
 		status = rcfscall(mip, CFSD_PROC_COMMIT,
 				(xdrproc_t)xdr_cfscommitargs,
@@ -1643,12 +1727,20 @@
 		if (status == 0) {
 			status = res.comr_status;
 			if (status == 0)
+#ifdef CFS_PAGEVEC
+				cfs_refresh_inode(data->inode, &res.comr_attr);
+#else
 				cfs_refresh_inode(inode, &res.comr_attr);
+#endif
 		}
 	}
 
 sb_error_check:
+#ifdef CFS_PAGEVEC
+	if (CFS_ASYNC(data) ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
+#else
 	if (async ? CFS_SB_RETRY_NOHANG(mip, status):CFS_SB_RETRY(mip, status))
+#endif
 		goto sb_down_retry;
 	CFS_SB_FSOP_DONE(mip);
 
@@ -1660,6 +1752,54 @@
 #endif
 }
 
+#ifdef CFS_IOCTL
+int
+cfs_proc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct cfsioctlargs args;
+	struct inode *ip = filp->f_dentry->d_inode;
+	cfs_mntinfo_t *mip = itocmi(ip);
+	int error;
+
+#ifdef CFS_EXPORT_OPS
+	COPY_CFS_FH(&(args.cia_fhandle), itocfh(ip));
+#else
+	args.cia_fhandle = *itocfh(ip);
+#endif
+	args.cia_fflags = filp->f_flags;
+	args.cia_cmd = cmd;
+
+	CFS_SB_FSOP_START(mip);
+sb_down_retry:
+	error = CFS_SB_CHECK(mip);
+	if (error)
+		goto sb_error_check;
+
+	if (CFS_AT_SERVER_MIP(mip)) {
+		(void) rcfs_ioctl(this_node, &error, &args, &arg, NULL);
+	} else {
+		ssi_procstate_t pstate;
+		unsigned long buf = arg;
+		int rval;
+
+		ssi_procstate_get(&pstate);
+
+		error = RCFS_IOCTL(mip->mi_server, &rval, &args, &buf, &pstate);
+		if (error != 0)
+			goto sb_error_check;
+		if (rval)
+			error = rval;
+	}
+
+sb_error_check:
+	if (CFS_SB_RETRY(mip, error))
+		goto sb_down_retry;
+	CFS_SB_FSOP_DONE(mip);
+
+	return error;
+}
+#endif /* CFS_IOCTL */
+
 struct cfs_rpc_ops     cfs_clientops = {
 	.getinode	= cfs_proc_getinode,
 #ifdef CFS_REVALIDATE_GETATTR
@@ -1683,4 +1823,7 @@
 	.decode_dirent	= cfs_decode_dirent,
 	.revalidate	= cfs_proc_revalidate,
 	.commit		= cfs_proc_commit,
+#ifdef CFS_IOCTL
+	.ioctl		= cfs_proc_ioctl,
+#endif
 };

Index: svrcfs.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/svrcfs.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- svrcfs.c	24 Mar 2009 04:26:28 -0000	1.24
+++ svrcfs.c	27 Oct 2009 03:18:29 -0000	1.25
@@ -31,6 +31,7 @@
 #include <linux/namei.h>
 #ifdef ALLOC_SVRCFS_HASH_TABLE
 #include <linux/bootmem.h>
+#include <linux/hash.h>
 #endif
 
 #include <cluster/icsgen.h>
@@ -57,6 +58,10 @@
 STATIC int svrcfstok_send_remove_notify(int,struct svrcfstok *,
 	struct svrcfstok *, struct qstr *, agent_t);
 
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+static unsigned int s_hash_shift;
+#define	HASHSIZ		(1 << s_hash_shift)
+#else
 /* SSI_XXX: This hash table size should scale based on maximum number of
  * mountable filesystems in the cluster
  */
@@ -64,19 +69,13 @@
 #define	HASHSIZ		256
 #define	HASHSIZLOG2	0xff
 #else
-#ifdef ALLOC_SVRCFS_HASH_TABLE
-static unsigned int s_hash_shift;
-static unsigned int s_hash_mask;
-#define	HASHSIZ		s_hash_shift
-#define	HASHSIZLOG2	s_hash_mask
-#else
 #define	HASHSIZ		1<<15
 #define	HASHSIZLOG2	0xffff
-#endif /* !ALLOC_SVRCFS_HASH_TABLE */
 #endif
+#endif /* !ALLOC_SVRCFS_HASH_TABLE */
 
 #ifdef RCU_CFSTOK_TABLE
-spinlock_t svrcfstok_table_lock;
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(svrcfstok_table_lock);
 #ifdef ALLOC_SVRCFS_HASH_TABLE
 static struct hlist_head *svrcfs_hash_table;
 #else
@@ -88,7 +87,7 @@
 #else
 LOCK_T svrcfstok_table_lock;
 static struct svrcfstok *svrcfs_hash_table[HASHSIZ];
-#endif
+#endif /* !RCU_CFSTOK_TABLE */
 
 struct timespec NOTIME	= { (u_long)-1, (u_long)-1 };
 
@@ -132,7 +131,7 @@
 void
 hlist_cache_init(void)
 {
-	hlist_cachep = kmem_cache_create("svrhl_cache",
+	hlist_cachep = kmem_cache_create("cfs_hlist",
 				sizeof(hlist_t), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -143,7 +142,6 @@
 SPIN_LOCK_T hlist_t_free_lock;
 #endif
 
-#ifdef RCU_CFSTOK_TABLE
 #ifdef SVRCFS_TOKEN_KMEM_CACHE
 static void
 svrcfstok_ctor(void * foo, kmem_cache_t * cachep, unsigned long flags)
@@ -169,7 +167,11 @@
 void
 svrcfstok_init(void)
 {
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+	unsigned long i;
+#else
 	int i;
+#endif
 
 #ifdef ALLOC_SVRCFS_HASH_TABLE
 	svrcfs_hash_table =
@@ -181,10 +183,8 @@
 						(27 - PAGE_SHIFT),
 					HASH_HIGHMEM,
 					&s_hash_shift,
-					&s_hash_mask,
+					NULL,
 					0);
-
-	HASHSIZ = 1 << s_hash_shift;
 #endif
 	for (i = 0; i < HASHSIZ ; i++) {
 #ifdef RCU_CFSTOK_TABLE
@@ -195,18 +195,21 @@
 	}
 
 #ifdef SVRCFS_TOKEN_KMEM_CACHE
-	svrcfstok_cachep = kmem_cache_create("svrcfstok_struct",
+	svrcfstok_cachep = kmem_cache_create("cfs_svrcfstok",
 				sizeof(svrcfstok_t), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				svrcfstok_ctor, NULL);
 #endif
 }
-#endif /* RCU_CFSTOK_TABLE */
 
 /*
  * Return the hash index for the specified file-handle+token-type.
  */
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+static unsigned long
+#else
 static int
+#endif
 svrhash(cfhandle_t *fhp)
 {
 	u_char *fhpp;
@@ -222,61 +225,78 @@
 	fhsum = 0;
 	while (i-- > 0)
 		fhsum += *fhpp++;
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+	return hash_long(fhsum, s_hash_shift);
+#else
 	return(fhsum & HASHSIZLOG2);
+#endif
 }
 
 #ifdef RCU_CFSTOK_TABLE
-static inline int
-hash_hold_and_check(svrcfstok_t *hp)
+static inline struct svrcfstok *
+__hash_hold_and_check(svrcfstok_t *hp)
 {
 	LOCK_COND_LOCK(&hp->sct_statelock);
-	if (hp->sct_flags & CFS_NOTREADY) {
+	if (hp->sct_magic != CFSTOK_MAGIC) {
 		UNLOCK_COND_LOCK(&hp->sct_statelock);
-		return 0;
+		return NULL;
 	}
 	HASH_HOLD(hp);
 	UNLOCK_COND_LOCK(&hp->sct_statelock);
-	return 1;
+	return hp;
+}
+
+static int
+hash_hold_and_check(svrcfstok_t *hp)
+{
+	struct svrcfstok *h;
+
+	rcu_read_lock();
+	if (hp->sct_magic != CFSTOK_MAGIC) {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	h = __hash_hold_and_check(hp);
+	rcu_read_unlock();
+
+	return (h != NULL);
 }
 #endif
 
 /*
  * hfind: Search for svrcfstok structure with matching handle
- *
- * SMP: Called with svrcfstok_table_lock locked.
  */
 #ifndef RCU_CFSTOK_TABLE
+/* SMP: Called with svrcfstok_table_lock locked. */
 static
 #endif
 struct svrcfstok *
 hfind(cfhandle_t *fhp)
 {
-#ifdef RCU_CFSTOK_TABLE
-	struct svrcfstok *hp = NULL;
-	struct hlist_node *pos;
-	int found = 0;
+	struct svrcfstok *hp;
 #ifdef CFS_EXPORT_OPS
 	int fh_size = CFS_FH_LEN(fhp);
 #else
 	int fh_size = sizeof(cfhandle_t);
 #endif
-#else
-	struct svrcfstok *hp;
-#endif
-	int hash = svrhash(fhp);
-
 #ifdef RCU_CFSTOK_TABLE
+	struct hlist_node *pos;
+
 	rcu_read_lock();
-	hlist_for_each_entry_rcu(hp, pos, &svrcfs_hash_table[hash], sct_hlist) {
+	hlist_for_each_entry_rcu(hp, pos,
+				 &svrcfs_hash_table[svrhash(fhp)], sct_hlist) {
 		if (memcmp((caddr_t)fhp, (caddr_t)&(hp->sct_fh), fh_size))
 			continue;
-		found = hash_hold_and_check(hp);
-		break;
+		hp = __hash_hold_and_check(hp);
+		rcu_read_unlock();
+		return hp;
 	}
 	rcu_read_unlock();
-
-	return found ? hp : NULL;
+	return NULL;
 #else
+	int hash = svrhash(fhp);
+
 	for (hp = svrcfs_hash_table[hash]; hp; hp = hp->sct_next) {
 		if (memcmp((caddr_t)fhp, (caddr_t)&(hp->sct_fh),
 		    sizeof(hp->sct_fh)))
@@ -361,7 +381,11 @@
 #ifdef NOTYET
 	object_t obj;
 #endif
+#ifdef ALLOC_SVRCFS_HASH_TABLE
+	unsigned long hash;
+#else
 	int hash;
+#endif
 
 	while (1) {
 #ifndef RCU_CFSTOK_TABLE
@@ -410,7 +434,7 @@
 		hash = svrhash(fhp);
 
 #ifdef CFS_EXPORT_OPS
-		memcpy(&hp->sct_fh, fhp, CFS_FH_LEN(fhp));
+		COPY_CFS_FH(&hp->sct_fh, fhp);
 #else
 		hp->sct_fh = *fhp;
 #endif
@@ -422,9 +446,7 @@
 		INIT_RCU_HEAD(&hp->sct_rcu);
 #endif
 		atomic_set(&hp->sct_refcnt, 1);
-#ifdef DEBUG
 		hp->sct_magic = CFSTOK_MAGIC;
-#endif
 #else
 		hp->sct_refcnt = 1;
 #endif /* !RCU_CFSTOK_TABLE */
@@ -454,7 +476,7 @@
 		mhsvrtok_init(NULL, &(hp->sct_mhold));
 #endif
 
-		for (i = 1 ; i < CFSTOK_NTOKS + 1; i++) {
+		for (i = 1 ; i <= CFSTOK_NTOKS; i++) {
 
 #ifdef NOTYET
 			obj.word2 = i;
@@ -633,7 +655,7 @@
 #ifdef RCU_CFSTOK_TABLE
 	might_sleep_if(atomic_read(&hp->sct_refcnt) == 1);
 	if (!atomic_dec_and_lock(&hp->sct_refcnt, &svrcfstok_table_lock)) {
-		WARN_ON(atomic_read(&hp->sct_refcnt) < 0);
+		/* WARN_ON(atomic_read(&hp->sct_refcnt) < 0); */
 		return;
 	}
 	LOCK_COND_LOCK(&hp->sct_statelock);
@@ -642,12 +664,9 @@
 		spin_unlock(&svrcfstok_table_lock);
 		return;
 	}
-	hp->sct_flags |= CFS_NOTREADY;
+	hp->sct_magic = 0;
 	UNLOCK_COND_LOCK(&hp->sct_statelock);
 	hlist_del_rcu(&hp->sct_hlist);
-#ifdef DEBUG
-	hp->sct_magic = 0;
-#endif
 	spin_unlock(&svrcfstok_table_lock);
 
 	WARN_ON(hp->sct_tokmask);
@@ -733,7 +752,7 @@
 	struct cfstokargs args;
 
 #ifdef CFS_EXPORT_OPS
-	memcpy(&args.cta_fhandle, fhp, CFS_FH_LEN(fhp));
+	COPY_CFS_FH(&args.cta_fhandle, fhp);
 #else
 	args.cta_fhandle = *fhp;
 #endif
@@ -1079,7 +1098,7 @@
 		return 0;
 	}
 #ifdef CFS_EXPORT_OPS
-	memcpy(&ctargs.cta_fhandle, fhp, CFS_FH_LEN(fhp));
+	COPY_CFS_FH(&ctargs.cta_fhandle, fhp);
 #else
 	ctargs.cta_fhandle = *fhp;
 #endif
@@ -1647,12 +1666,11 @@
 
 	list_for_each_entry_safe(item, tmp, hlistp, hl_list) {
 		list_del_init(&item->hl_list);
-		(*tokspp)[i] = item->hl_tok;
+		(*tokspp)[i++] = item->hl_tok;
 		hlist_free(item);
-		i++;
 	}
+	BUG_ON(i > CFS_NTOKS);
 	*ntoksp = i;
-	BUG_ON(*ntoksp > CFS_NTOKS);
 #endif /* SVRHOLD_LIST_LINUX_LIST */
 }
 
@@ -1662,21 +1680,33 @@
 	u_int *ntoksp,
 	struct cfs_nettok **tokspp)
 {
-
-	*tokspp = NULL;
 #ifdef SVRHOLD_LIST_LINUX_LIST
-	if (list_empty(hlistp)) {
+	struct list_head *pos;
+	int count = 0;
+
+#ifndef SSI_FULL_CFS_TOKENS
+	__list_for_each(pos, hlistp) count++;
+#else
+	list_for_each(pos, hlistp) count++;
+#endif
+	if (!count) {
 		*ntoksp = 0;
+		*tokspp = NULL;
 		return;
 	}
+	BUG_ON(count > CFS_NTOKS);
+
+	*tokspp = (struct cfs_nettok *)
+		malloc(sizeof(cfs_nettok) * count);
 #else
+	*tokspp = NULL;
 	*ntoksp = hlist_count(hlistp);
 	if (*ntoksp == 0)
 		return;
 	SSI_ASSERT(*ntoksp <= CFS_NTOKS);
-#endif
 	*tokspp = (struct cfs_nettok *)
 		malloc(sizeof(cfs_nettok) * CFS_NTOKS);
+#endif
 	if (*tokspp == NULL)
 		panic("svrcfstok_convert: Out of memory");
 
@@ -1693,7 +1723,11 @@
 		SSI_ASSERT(toksp != NULL);
 		SSI_ASSERT(ntoks <= CFS_NTOKS);
 
+#ifdef SVRHOLD_LIST_LINUX_LIST
+		free(toksp, sizeof(cfs_nettok) * ntoks);
+#else
 		free(toksp, sizeof(cfs_nettok) * CFS_NTOKS);
+#endif
 	}
 }
 
@@ -1720,7 +1754,7 @@
 	SSI_ASSERT(op == REVOKE || op == QUERY || op == INSTALL);
 
 #ifdef CFS_EXPORT_OPS
-	memcpy(&ctargs.cta_fhandle, fhp, CFS_FH_LEN(fhp));
+	COPY_CFS_FH(&ctargs.cta_fhandle, fhp);
 #else
 	ctargs.cta_fhandle = *fhp;
 #endif
@@ -1812,7 +1846,7 @@
 #ifdef CFS_EXPORT_OPS
 	desc.cdrok = &cdrok;
 	desc.cdrok->cdrok_attr.cna_ino = ino;
-	memcpy(&desc.cdrok->cdrok_fhandle, fhp, CFS_FH_LEN(fhp));
+	COPY_CFS_FH(&desc.cdrok->cdrok_fhandle, fhp);
 
 	ip = ilookup5(sb, ino, cfs_find_actor, &desc);
 #else
@@ -1829,29 +1863,16 @@
  * This provides the same functionality which use to be called
  * svrcfstok_get_nodelist() which now is a more general purpose
  * function.
- *
- * SMP: Call with hp->sct_tcblock held
  */
-static inline nsc_nodelist_t
-__svrcfstok_get_mholdlist(svrcfstok_t *hp)
+void
+svrcfstok_get_mholdlist(svrcfstok_t *hp, nsc_nodelist_t *nl)
 {
-	nsc_nodelist_t nodelist;
 	int ret;
 
-	ret = svrcfstok_get_nodelist(hp, CFSTOK_MHOLD, &nodelist, NULL);
-	SSI_ASSERT(ret);
-	return nodelist;
-}
-
-nsc_nodelist_t
-svrcfstok_get_mholdlist(svrcfstok_t *hp)
-{
-	nsc_nodelist_t nodelist;
-
 	LOCK_LOCK(&hp->sct_tcblock);
-	nodelist = __svrcfstok_get_mholdlist(hp);
+	ret = svrcfstok_get_nodelist(hp, CFSTOK_MHOLD, nl, NULL);
 	UNLOCK_LOCK(&hp->sct_tcblock);
-	return nodelist;
+	SSI_ASSERT(ret);
 }
 
 /* svrcfstok_get_nodelist()
@@ -1879,9 +1900,7 @@
 	struct nodeent nodeent;
 	object_t obj;
 
-#ifdef NOTAVAIL
-	SSI_ASSERT(SLEEP_LOCKOWNED(&hp->sct_tcblock));
-#endif
+	SSI_ASSERT(LOCK_LOCKOWNED(&hp->sct_tcblock));
 	SSI_ASSERT(!(modep && type == CFSTOK_MHOLD));
 
 	NSC_NODELIST_INIT(nodelist);
@@ -2017,12 +2036,12 @@
 	if (name == NULL) {
 		NSC_NODELIST_INIT(&dir);
 	} else {
-		dir = svrcfstok_get_mholdlist(dhp);
+		svrcfstok_get_mholdlist(dhp, &dir);
 	}
 
 	/* Get list of target MHOLDS */
 	if (thp) {
-		target = svrcfstok_get_mholdlist(thp);
+		svrcfstok_get_mholdlist(thp, &target);
 
 		/* Only need DNLC purge on subset of target this which
 		 * also has directory cached
@@ -2086,15 +2105,11 @@
 		 */
 		if (notokencache && NSC_NODELIST_TESTALL(&target)) {
 
-#ifdef SVRCFSTOK_REMOVE_NOTIFY__LIVELOCK_DEAD_ICACHE_FIX
-			nidelay(HZ);
-#else
-			allow_reschedule();
-#endif
+			nidelay(HZ>>4);
 			/* Do not remove; keep original for reference */
 			/* nidelay(1); */
 
-			tmpnodelist = svrcfstok_get_mholdlist(thp);
+			svrcfstok_get_mholdlist(thp, &tmpnodelist);
 
 			/* Send to nodes which failed and still have MHOLD */
 			NSC_NODELIST_ANDN(&target, &tmpnodelist);
@@ -2213,7 +2228,7 @@
 	SSI_ASSERT(server != (clusternode_t)this_node);
 
 #ifdef CFS_EXPORT_OPS
-	memcpy(&ctargs.cta_fhandle, fhp, CFS_FH_LEN(fhp));
+	COPY_CFS_FH(&ctargs.cta_fhandle, fhp);
 #else
 	ctargs.cta_fhandle = *fhp;
 #endif
@@ -2270,8 +2285,9 @@
 		HASH_RELE(*hpp);
 		entry++;
 	}
+	SSI_ASSERT(icp->ic_freeme == 1);
 	ics_chunk_free(icp);
-	kfree(icp);
+	/* kfree(icp); */ /* Done in ics_chunk_free() */
 }
 
 void
@@ -2290,18 +2306,17 @@
 	object_t obj;
 	int error;
 	unsigned int count;
-	ics_chunk_t *icp;
-
-	icp = (ics_chunk_t *)kmalloc_nofail(sizeof(ics_chunk_t));
-	ics_chunk_init(icp, sizeof(struct svrcfstok *));
+	ics_chunk_t *icp = NULL;
 
 tryagain:
 	count = 0;
 #ifdef RCU_CFSTOK_TABLE
 	for (hash = 0; hash <  HASHSIZ ; hash++) {
 		rcu_read_lock();
-		hlist_for_each_rcu(pos, &svrcfs_hash_table[hash])
+		hlist_for_each_rcu(pos, &svrcfs_hash_table[hash]) {
+			BUG_ON(count == UINT_MAX);
 			count++;
+		}
 		rcu_read_unlock();
 	}
 #else
@@ -2315,9 +2330,17 @@
 #endif
 
 	/* Nothing to do */
-	if (count == 0)
+	if (count == 0) {
+		if (icp)
+			ics_chunk_free(icp);
 		return;
+	}
 
+	if (!icp) {
+		icp = (ics_chunk_t *)kmalloc_nofail(sizeof(ics_chunk_t));
+		ics_chunk_init(icp, sizeof(struct svrcfstok *));
+		icp->ic_freeme = 1;
+	}
 	ics_chunk_prealloc(icp, count);
 
 #ifndef RCU_CFSTOK_TABLE
@@ -2328,7 +2351,7 @@
 #ifdef RCU_CFSTOK_TABLE
 		rcu_read_lock();
 		hlist_for_each_entry_rcu(hp, pos, &svrcfs_hash_table[hash], sct_hlist) {
-			if (!hash_hold_and_check(hp))
+			if (!__hash_hold_and_check(hp))
 				continue;
 #else
 		for (hp = svrcfs_hash_table[hash]; hp; hp = hp->sct_next) {
@@ -2368,10 +2391,12 @@
 
 		hp = *hpp;
 #endif
-			LOCK_LOCK(&hp->sct_tcblock);
 			obj.word1 = (long)hp;
 			obj.word2 = CFSTOK_MHOLD;
 			obj.obj_pp = &svrparam;
+
+			LOCK_LOCK(&hp->sct_tcblock);
+
 			ret = mhsvrtok_clear(&obj, &(hp->sct_mhold), agent);
 			if (ret)
 #ifdef RCU_CFSTOK_TABLE
@@ -2380,8 +2405,7 @@
 				hp->sct_tokmask &= ~(BITVAL(CFSTOK_MHOLD));
 #endif
 
-			for (type = 1 ; type < CFSTOK_NTOKS + 1; type++) {
-
+			for (type = 1 ; type <= CFSTOK_NTOKS; type++) {
 				obj.word2 = type;
 #ifdef CFSTOK_RANGE
 				if (BITVAL(type) & CFSTOK_RANGE)
@@ -2490,7 +2514,7 @@
 				continue;
 
 #ifdef RCU_CFSTOK_TABLE
-			if (!hash_hold_and_check(hp))
+			if (!__hash_hold_and_check(hp))
 				continue;
 #else
 			HASH_HOLD(hp);
@@ -2578,7 +2602,6 @@
 		      sizeof(*argsp), NULL, NULL);
 }
 
-#ifdef SSI_CFS_SKIP
 #if	defined(DEBUG) || defined(DEBUG_TOOLS)
 void
 print_svrcfstok(struct svrcfstok *hp)
@@ -2587,7 +2610,16 @@
 	object_t obj;
 	extern int cfs_print_tokens;
 	extern char *cfstok_names[];
+	extern tok_param_t svrparam;
+	extern void mhsvrtok_print(const object_t *, const mhsvrtcb_t *);
 
+#ifdef RCU_CFSTOK_TABLE
+	printk("svrcfstok 0x%p next 0x%p\n",
+		hp, hlist_entry((&hp->sct_hlist)->next, svrcfstok_t, sct_hlist));
+	printk("tokmask 0x%x refcnt %d\n",
+		hp->sct_tokmask, atomic_read(&hp->sct_refcnt));
+	printk("flags 0x%lx\n", hp->sct_flags);
+#else
 	printk("svrcfstok 0x%x next 0x%x prev 0x%x\n",
 		hp, hp->sct_next, hp->sct_prev);
 	printk("tokmask 0x%x refcnt %d\n",
@@ -2595,21 +2627,21 @@
 	printk("flags 0x%x%s%s\n", hp->sct_flags,
 		(hp->sct_flags & CFS_NOTOKENCACHE ? " NOTOKENCACHE" : ""),
 		(hp->sct_flags & CFS_NOTREADY ? " NOTREADY" : ""));
+#endif
 	if (hp->sct_dp->d_name.name)
 		printk("filename \"%s\"\n", hp->sct_dp->d_name.name);
 #ifdef SKIP
 	print_cfhandle((long *)&(hp->sct_fh));
 #endif
-	printk("cfs sb 0x%x\n", hp->sct_sb);
-	printk("phy ip 0x%x dentry 0x%x\n", hp->sct_ip, hp->sct_dp);
+	printk("cfs sb 0x%p\n", hp->sct_sb);
+	printk("phy ip 0x%p dentry 0x%p\n", hp->sct_ip, hp->sct_dp);
 	obj.word1 = (long)hp;
 	obj.obj_pp = &svrparam;
-#ifdef SKIP
 	if (cfs_print_tokens) {
 	obj.word2 = CFSTOK_MHOLD;
 	printk(" Tok %s: ", cfstok_names[CFSTOK_MHOLD]);
 	mhsvrtok_print(&obj, &(hp->sct_mhold));
-	for (i = 1; i < CFSTOK_NTOKS + 1; i++) {
+	for (i = 1; i <= CFSTOK_NTOKS; i++) {
 		printk(" Tok %s: ", cfstok_names[i]);
 		obj.word2 = i;
 #ifdef CFSTOK_RANGE
@@ -2621,9 +2653,9 @@
 		printk("\n");
 	}
 	}
-#endif
 }
 
+#ifdef SSI_CFS_SKIP
 void
 print_findsvrcfs(struct super_block *sb)
 {
@@ -2664,9 +2696,9 @@
 		}
 	}
 }
+#endif /* SSI_CFS_SKIP */
 
 #endif /* DEBUG || DEBUG_TOOLS */
-#endif
 
 #ifdef SSI_CFS_FULLTIMES
 void
@@ -2786,10 +2818,7 @@
 					doagain = TRUE;
 					continue;
 				}
-				hp->sct_flags |= CFS_NOTREADY;
-#ifdef DEBUG
 				hp->sct_magic = 0;
-#endif
 				UNLOCK_COND_LOCK(&hp->sct_statelock);
 				spin_lock(&svrcfstok_table_lock);
 				hlist_del_rcu(&hp->sct_hlist);
@@ -2892,8 +2921,7 @@
 	obj.obj_pp = &svrparam;
 	mhsvrtok_destroy(&obj, &(hp->sct_mhold), forced);
 
-	for (i = 1; i < CFSTOK_NTOKS + 1; i++) {
-
+	for (i = 1; i <= CFSTOK_NTOKS; i++) {
 		obj.word2 = i;
 #ifdef CFSTOK_RANGE
 		if (BITVAL(i) & CFSTOK_RANGE)
@@ -3076,7 +3104,6 @@
 			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;

Index: read.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/read.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- read.c	3 Feb 2009 06:18:12 -0000	1.20
+++ read.c	27 Oct 2009 03:18:29 -0000	1.21
@@ -48,8 +48,16 @@
 #include <asm/system.h>
 #include <cluster/assert.h>
 
+#ifdef CFS_ASYNC_QUEUE
+extern void *nsc_async_cfs_queue[3]; /* RPC_NR_PRIORITY */
+#else
 extern void *nsc_async_cfs_queue;
+#endif
+#ifdef CFS_PAGEVEC
+static int cfs_pagein_one(struct list_head *, unsigned);
+#else
 static int cfs_pagein_one(struct list_head *, struct inode *);
+#endif
 
 #ifndef CFS_PAGEVEC
 struct cfs_read_data {
@@ -70,17 +78,39 @@
 
 #define MIN_POOL_READ	(32)
 
+#ifdef CFS_PAGEVEC
+static inline struct cfs_read_data *cfs_readdata_alloc(unsigned int pages)
+#else
 static struct cfs_read_data *cfs_readdata_alloc(void)
+#endif
 {
 	struct cfs_read_data   *p;
 	p = (struct cfs_read_data *)mempool_alloc(cfs_rdata_mempool, SLAB_NOFS);
-	if (p)
+	if (p) {
 		memset(p, 0, sizeof(*p));
+		INIT_LIST_HEAD(&p->pages);
+#ifdef CFS_PAGEVEC
+		if (pages <= CFS_PAGEVEC_SIZE)
+			p->pagevec = &p->page_array[0];
+		else {
+			size_t size = pages * sizeof(struct page *);
+			p->pagevec = kzmalloc(size, GFP_NOFS);
+			if (!p->pagevec) {
+				mempool_free(p, cfs_rdata_mempool);
+				p = NULL;
+			}
+		}
+#endif
+	}
 	return p;
 }
 
-static __inline__ void cfs_readdata_free(struct cfs_read_data *p)
+static inline void cfs_readdata_free(struct cfs_read_data *p)
 {
+#ifdef CFS_PAGEVEC
+	if (p && (p->pagevec != &p->page_array[0]))
+		kfree(p->pagevec);
+#endif
 	mempool_free(p, cfs_rdata_mempool);
 }
 
@@ -126,16 +156,16 @@
 	struct cfs_read_data *rdata;
 	u_char		prio = 0;
 
-	rdata = cfs_readdata_alloc();
+	rdata = cfs_readdata_alloc(1);
 	if (!rdata)
 		return -ENOMEM;
 
 	rdata->flags = (IS_SWAPFILE(inode)? CFS_RPC_SWAPFLAGS : 0);
 	rdata->inode = inode;
-	rdata->page = page;
+	rdata->pagevec = &page;
 	rdata->pgbase = 0UL;
 	rdata->count = rsize;
-#endif
+#endif /* CFS_PAGEVEC */
 #ifdef SSI_SKIP	/* Keep as reference */
 	rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
 	rdata->cred = ctx->cred;
@@ -160,7 +190,7 @@
 	offset = page_offset(page) + rdata->pgbase;
 #else
 	/* N.B. Not sure if this should be done elsewhere */
-	if (rdata->flags & CFS_RPC_SWAPFLAGS) {
+	if (rdata->flags & RPC_TASK_SWAPPER) {
 		prio = ics_getpriority();
 
 		/* Up icsprio to avoid deadlock */
@@ -228,7 +258,7 @@
 	} while (count);
 
 #ifdef CFS_PAGEVEC
-	if (rdata->flags & CFS_RPC_SWAPFLAGS)
+	if (rdata->flags & RPC_TASK_SWAPPER)
 		ics_setpriority(prio);
 
 	if (count)
@@ -275,7 +305,11 @@
 	cfs_lock_request(new);
 #endif
 	cfs_list_add_request(new, &one_request);
+#ifdef CFS_PAGEVEC
+	cfs_pagein_one(&one_request, 1);
+#else
 	cfs_pagein_one(&one_request, inode);
+#endif
 	return 0;
 }
 
@@ -314,10 +348,26 @@
 #ifdef CFS_PAGEVEC
 	data->offset	  = req_offset(req) + offset;
 
+#ifdef CFS_ASYNC_LOCAL_SYNC
+	if (!CFS_AT_SERVER(data->inode) || !CFS_SB_UP_MIP(itocmi(data->inode))) {
+		data->flags = RPC_TASK_ASYNC | (IS_SWAPFILE(req->wb_inode)? CFS_RPC_SWAPFLAGS : 0);
+	} else
+		data->flags = 0;
+#else
+	/* N.B. Do we need to test? Never called for swapfile inode */
+	data->flags = RPC_TASK_ASYNC | (IS_SWAPFILE(req->wb_inode)? CFS_RPC_SWAPFLAGS : 0);
+#endif
+#ifdef SKIP
 	/* This is derived from nfs3_proc_read_setup() */
 	/* N.B. Do we need to test? Never called for swapfile inode */
 	data->flags = RPC_TASK_ASYNC | (IS_SWAPFILE(req->wb_inode)? CFS_RPC_SWAPFLAGS : 0);
+	/* data->priority = RPC_PRIORITY_NORMAL */
 #endif
+#endif /* CFS_PAGEVEC */
+
+	dprintk("CFS: %8d initiated read call (req %x/%lu)\n",
+		current->pid,
+		data->inode->i_sb->s_dev, data->inode->i_ino);
 }
 
 static void
@@ -333,52 +383,124 @@
 	}
 }
 
-void
-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;
-	u_char prio = 0;
+static void cfs_readpage_result_full(struct cfs_read_data *data, int status)
+{
+	struct cfs_page *req;
+	struct page *page;
+	unsigned int count = (ssize_t)data->res_count;
 
-	/* N.B. Not sure if this should be done elsewhere */
-	if (data->flags & CFS_RPC_SWAPFLAGS) {
-		prio = ics_getpriority();
+	dprintk("CFS: read (%x/%ld %d@%Ld)\n",
+		data->inode->i_sb->s_dev,
+		data->inode->i_ino,
+		count,
+		(long long)(data->offset));
 
-		/* Up icsprio to avoid deadlock */
-		if (prio < ICS_MAX_PRIO)
-			ics_setpriority(prio + 1);
+	while (!list_empty(&(data->pages))) {
+		req = cfs_list_entry(data->pages.next);
+		page = req->wb_page;
+
+		cfs_list_remove_request(req);
+
+		if (status >= 0) {
+			if (count < PAGE_CACHE_SIZE) {
+				if (count < req->wb_bytes)
+					memclear_highpage_flush(page,
+						req->wb_pgbase + count,
+						req->wb_bytes - count);
+				count = 0;
+			} else
+				count -= PAGE_CACHE_SIZE;
+			SetPageUptodate(page);
+		} else
+			SetPageError(page);
+
+		cfs_readpage_release(req);
 	}
 
-	status = CFS_PROTO(data->inode)->read(data);
+	cfs_readdata_free(data);
+}
 
-	if (unlikely(status == -ECFS_TRYAGAIN))
-		printk(KERN_WARNING "read handler down off %llo len %u\n",
+static int cfs_readpage_result(struct cfs_read_data *data, int status)
+{
+	struct cfs_page *req;
+	cfs_mntinfo_t *mip;
+
+	if (unlikely(status == -ECFS_TRYAGAIN)) {
+		mip = itocmi(data->inode);
+
+		if (!CFS_SB_HARD_MIP(mip))
+			goto done;
+
+		/* Synchronize SB down/rebuild operations. */
+		LOCK_COND_LOCK(&mip->mi_cond_lock);
+
+		/*
+		 * Bug [1925545]: Processes stuck in I/O after failover.
+		 */
+		if (mip->mi_sb_state > MI_SB_STATE_REBUILD_WANTS_DONE) {
+			UNLOCK_COND_LOCK(&mip->mi_cond_lock);
+
+			SSI_ASSERT(data->flags & RPC_TASK_ASYNC);
+			printk(KERN_WARNING "CFS: %d read handler delayed data 0x%p\n",
+				current->pid, data);
+			//idelay(HZ);
+			return -EAGAIN;
+		}
+
+		printk(KERN_WARNING "CFS: read handler down off %llo len %u\n",
 			data->offset, data->count);
 
-	if (data->flags & CFS_RPC_SWAPFLAGS)
-		ics_setpriority(prio);
+		while (!list_empty(&(data->pages))) {
+			req = cfs_list_entry(data->pages.next);
+			cfs_list_remove_request(req);
+			cfs_list_add_request(req, &CFS_SERVER(data->inode)->read_down);
+			SetPageError(req->wb_page);
+			flush_dcache_page(req->wb_page);
+		}
 
-	count = (ssize_t)data->res_count;
+		UNLOCK_COND_LOCK(&mip->mi_cond_lock);
+
+		cfs_readdata_free(data);
+		return 0;
+	}
+done:
+	cfs_readpage_result_full(data, status);
+	return 0;
+}
+#endif /* CFS_PAGEVEC */
+
+void
+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
+#ifndef CFS_CHARD_RACE_FIX
+#error not supported
+#endif
+	do {
+		status = CFS_PROTO(data->inode)->read(data);
+	} while (cfs_readpage_result(data, status) == -EAGAIN);
+#else /* CFS_PAGEVEC */
+#ifdef CFS_CHARD_RACE_FIX
+#warning deprecated
+#endif
 	while (!list_empty(&(data->pages))) {
 		struct cfs_page *req = cfs_list_entry(data->pages.next);
 		struct page *page = req->wb_page;
-#ifndef CFS_PAGEVEC
 		loff_t offset;
 		unsigned int count;
 		void *buffer;
-#endif
 
 		cfs_list_remove_request(req);
-#ifndef CFS_PAGEVEC
+
 		count = req->wb_bytes;
 		buffer = kmap(page) + req->wb_offset;
 		offset = page_offset(page) + req->wb_offset;
@@ -388,13 +510,8 @@
 		 * inode after last read in this bunch finished.
 		 */
 		status = CFS_PROTO(data->inode)->read(data->inode, offset, count, buffer, TRUE);
-#endif
 
 		if (unlikely(status == -ECFS_TRYAGAIN)) {
-#ifdef CFS_PAGEVEC
-			SetPageError(page);
-			BUG_ON(data->inode != req->wb_inode);
-#else
 			offset = page_offset(page) + req->wb_offset;
 			SetPageError(page);
 			flush_dcache_page(page);
@@ -405,7 +522,6 @@
 				printk(KERN_WARNING "inode fix %p\n", req->wb_inode);
 				req->wb_inode = data->inode;
 			}
-#endif
 			spin_lock(&cfs_wreq_lock);
 			list_add(&req->wb_list, &CFS_SERVER(data->inode)->read_down);
 			req->wb_list_head = &CFS_SERVER(data->inode)->read_down;
@@ -419,29 +535,16 @@
 
 		if (status >= 0) {
 			if (count < PAGE_CACHE_SIZE) {
-#ifdef CFS_PAGEVEC
-				if (count < req->wb_bytes)
-					memclear_highpage_flush(page,
-							req->wb_pgbase + count,
-							req->wb_bytes - count);
-				count = 0;
-			} else
-				count -= PAGE_CACHE_SIZE;
-#else
-				if (status < count) {
+				if (status < count)
 					memset(buffer + status, 0, count - status);
-				}
 			}
-#endif /* !CFS_PAGEVEC */
 			SetPageUptodate(page);
 		} else
 			SetPageError(page);
 
-#ifndef CFS_PAGEVEC
 		flush_dcache_page(page);
 		/* CFS_ClearPageSync(page); */
 		kunmap(page);
-#endif
 
 		dprintk("CFS: read (%x/%ld %d@%Ld)\n",
 			req->wb_inode->i_sb->s_dev,
@@ -453,60 +556,57 @@
 	}
 
 	cfs_readdata_free(data);
+#endif /* !CFS_PAGEVEC */
 }
 
-static int
-cfs_pagein_one(struct list_head *head, struct inode *inode)
+static int cfs_execute_read(struct cfs_read_data *data)
 {
-	struct cfs_page         *req;
-	struct cfs_read_data	*data;
-	int status;
-	unsigned int		count;
-
-	data = cfs_readdata_alloc();
-	if (!data)
-		goto out_bad;
+#ifdef CFS_ASYNC_QUEUE
+	int flags;
 
-	INIT_LIST_HEAD(&data->pages);
-	count = 0;
-	while (!list_empty(head)) {
-		req = cfs_list_entry(head->next);
-		cfs_list_remove_request(req);
-		cfs_list_add_request(req, &data->pages);
-		ClearPageError(req->wb_page);
-		count += req->wb_bytes;
+	if (!(data->flags & RPC_TASK_ASYNC)) {
+		cfs_async_handler_read(data);
+		return 0;
 	}
-	req = cfs_list_entry(data->pages.next);
 
-	cfs_read_rpcsetup(req, data, count, 0);
+	if (!(data->flags & RPC_TASK_SWAPPER))
+		flags = NSC_ASYNC_SLEEP | NSC_ASYNC_SLAB_NOFS;
+	else
+		flags = NSC_ASYNC_STACK;
 
-	/* Start the async call */
-	dprintk("CFS: %8d initiated read call (req %x/%lu)\n",
-		current->pid,
-		inode->i_sb->s_dev, inode->i_ino);
+	if (nsc_async_queue(nsc_async_cfs_queue[1], /* RPC_PRIORITY_NORMAL */
+			    cfs_async_handler_read, data, sizeof(*data),
+			    flags)) {
+		cfs_async_read_error(&data->pages);
+		cfs_readdata_free(data);
+		return -ENOMEM;
+	}
+
+	return 0;
+#else /* CFS_ASYNC_QUEUE */
+	struct inode *inode = data->inode;
+	int status;
 
 #ifdef CFS_ASYNC_LOCAL_SYNC
+#ifdef CFS_CHARD_RACE_FIX
+	if (!CFS_AT_SERVER(inode)
+	    || itocmi(inode)->mi_sb_state == MI_SB_STATE_REBUILD_FLUSH) {
+#else
 	if (!CFS_AT_SERVER(inode)) {
 #endif
-	/* 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
+#endif /* CFS_ASYNC_LOCAL_SYNC */
 #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
+	/* Must pass a cfs_read_data ** because we can't move a list_head
+	 * from one place to another, as cfs_async_queue() would.
+	 */
 	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);
 		return status;
@@ -518,9 +618,54 @@
 #else
 		cfs_async_handler_read(&data);
 #endif
-#endif
+#endif /* CFS_ASYNC_LOCAL_SYNC */
 
 	return 0;
+#endif /* !CFS_ASYNC_QUEUE */
+}
+
+static int
+#ifdef CFS_PAGEVEC
+cfs_pagein_one(struct list_head *head, unsigned npages)
+#else
+cfs_pagein_one(struct list_head *head, struct inode *inode)
+#endif
+{
+	struct cfs_page         *req;
+#ifdef CFS_PAGEVEC
+	struct page		**pages;
+#endif
+	struct cfs_read_data	*data;
+	unsigned int		count;
+
+#ifdef CFS_PAGEVEC
+	data = cfs_readdata_alloc(npages);
+#else
+	data = cfs_readdata_alloc();
+#endif
+	if (!data)
+		goto out_bad;
+
+#ifdef CFS_PAGEVEC
+	pages = data->pagevec;
+#endif
+	count = 0;
+	while (!list_empty(head)) {
+		req = cfs_list_entry(head->next);
+		cfs_list_remove_request(req);
+		cfs_list_add_request(req, &data->pages);
+		ClearPageError(req->wb_page);
+#ifdef CFS_PAGEVEC
+		*pages++ = req->wb_page;
+#endif
+		count += req->wb_bytes;
+	}
+	req = cfs_list_entry(data->pages.next);
+
+	cfs_read_rpcsetup(req, data, count, 0);
+
+	return cfs_execute_read(data);
+
 out_bad:
 	cfs_async_read_error(head);
 	return -ENOMEM;
@@ -530,14 +675,23 @@
 cfs_pagein_list(struct list_head *head, unsigned rpages)
 {
 	LIST_HEAD(one_request);
+#ifdef CFS_PAGEVEC
+	unsigned int		pages = 0, npages;
+#else
 	struct cfs_page		*req;
-	int			error = 0;
 	unsigned int		pages = 0;
+#endif
+	int			error = 0;
 
 	while (!list_empty(head)) {
+#ifdef CFS_PAGEVEC
+		pages += npages = cfs_coalesce_requests(head, &one_request, rpages);
+		error = cfs_pagein_one(&one_request, npages);
+#else
 		pages += cfs_coalesce_requests(head, &one_request, rpages);
 		req = cfs_list_entry(one_request.next);
 		error = cfs_pagein_one(&one_request, req->wb_inode);
+#endif
 		if (error < 0)
 			break;
 	}
@@ -682,11 +836,22 @@
 void
 cfs_restart_read(struct cfs_server *server)
 {
-	struct list_head	*pos, *tmp;
+#ifdef CFS_ASYNC_QUEUE
+	int err;
+
+	if (!list_empty(&server->read_down)) {
+		err = cfs_pagein_list(&server->read_down, server->rpages);
+		if (err < 0)
+			printk(KERN_ERR "%s: error %d\n", __FUNCTION__, err);
+	}
+#else /* CFS_ASYNC_QUEUE */
 	struct cfs_page		*req;
 	LIST_HEAD(one_request);
+	struct list_head	*pos, *tmp;
 
+#ifndef CFS_CHARD_RACE_FIX
 	spin_lock(&cfs_wreq_lock);
+#endif
 	list_for_each_safe(pos, tmp, &(server->read_down)) {
 
 		req = cfs_list_entry(pos);
@@ -700,10 +865,17 @@
 
 		cfs_list_remove_request(req);
 		cfs_unset_down(req);
+#ifndef CFS_CHARD_RACE_FIX
 		spin_unlock(&cfs_wreq_lock);
+#endif
 		cfs_list_add_request(req, &one_request);
 		cfs_pagein_one(&one_request, req->wb_inode);
+#ifndef CFS_CHARD_RACE_FIX
 		spin_lock(&cfs_wreq_lock);
+#endif
 	}
+#ifndef CFS_CHARD_RACE_FIX
 	spin_unlock(&cfs_wreq_lock);
+#endif
+#endif /* !CFS_ASYNC_QUEUE */
 }

Index: cfs_subr.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/cfs_subr.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- cfs_subr.c	24 Mar 2009 04:26:28 -0000	1.26
+++ cfs_subr.c	27 Oct 2009 03:18:29 -0000	1.27
@@ -120,8 +120,10 @@
 	 */
 	cfs_data_inval_range(ctoi(cp), 0, 0);
 }
+#endif /* SSI_CFS_SKIP */
 
 #ifdef DEBUG
+#ifdef SSI_NOT_YET
 void
 cfs_checkallholds()
 {
@@ -135,8 +137,8 @@
 		}
 	}
 }
+#endif
 #endif /* DEBUG */
-#endif /* SSI_CFS_SKIP */
 
 #define	PIDS_SIZE	16
 
@@ -154,6 +156,9 @@
 	struct inode	 *inode = hp->sct_ip;
 	struct file_lock *fl;
 	unsigned int *pids;
+#ifdef CFS_FLOCK
+	unsigned char *flags; /* fl_flags */
+#endif
 	int	pcount = PIDS_SIZE;
 	int pos, i;
 	struct file_lock lock;
@@ -163,7 +168,10 @@
 		return;
 
 again:
-	pids = (unsigned int *)kzmalloc_nofail(pcount*sizeof(unsigned int));
+	pids = (unsigned int *)kmalloc_nofail(pcount*sizeof(unsigned int));
+#ifdef CFS_FLOCK
+	flags = kmalloc_nofail(pcount * sizeof(*flags));
+#endif
 	pos = 0;
 
 	SSI_ASSERT(inode == hp->sct_fp->f_dentry->d_inode);
@@ -187,12 +195,18 @@
 			unlock_kernel();
 			printk(KERN_INFO "Need more pids in cfs_cleanuplocks\n");
 			kfree(pids);
+#ifdef CFS_FLOCK
+			kfree(flags);
+#endif
 			pcount += PIDS_SIZE;
 			goto again;
 		}
 
 		/* New pid */
 		pids[pos] = fl->fl_pid;
+#ifdef CFS_FLOCK
+		flags[pos] = fl->fl_flags;
+#endif
 		pos++;
 	}
 	unlock_kernel();
@@ -202,12 +216,14 @@
 		goto out;
 
 	locks_init_lock(&lock);
-	lock.fl_owner = NULL;	/* SSI_XXX: Do I need a better value here? */
 	lock.fl_file = hp->sct_fp;
+#ifndef CFS_FLOCK
 	lock.fl_flags = FL_POSIX;
+#endif
 	lock.fl_type  = F_UNLCK;
-	lock.fl_start = 0;
+	/* lock.fl_start = 0; */
 	lock.fl_end   = OFFSET_MAX;
+	lock.fl_lmops = &cfs_lockm_operations;
 
 	for (i = 0; i < pos; i++) {
 
@@ -220,7 +236,12 @@
 /* #endif DEBUG */
 
 		lock.fl_pid = pids[i];
-		if (posix_lock_file(hp->sct_fp, &lock) < 0) {
+#ifdef CFS_FLOCK
+		lock.fl_flags = flags[i];
+		if (do_cfs_lock(&lock) < 0) {
+#else
+		if (posix_lock_file(lock.fl_file, &lock) < 0) {
+#endif
 			printk("cfs_cleanuplocks: unlock failure in %s:%d\n",
 					__FILE__, __LINE__);
 			BUG();
@@ -229,6 +250,9 @@
 
 out:
 	kfree(pids);
+#ifdef CFS_FLOCK
+	kfree(flags);
+#endif
 
 	return;
 }
@@ -389,17 +413,50 @@
 }
 #endif /* DEBUG */
 
+#ifdef CFS_CLIST_LLIST
+static dev_t inuse[CFS_MAX_LISTS];
+#else
 static int inuse[CFS_MAX_LISTS];
-static DEFINE_SPINLOCK(inuse_lock);
+#endif
+static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inuse_lock);
 
+#ifdef CFS_CLIST_LLIST
+int
+cfs_get_cnode_idx(dev_t ssidev)
+#else
 int
 cfs_get_cnode_idx(void)
+#endif
 {
 	int output = 0;
+#ifndef CFS_CLIST_LLIST
 	int idx;
+#else
+	int pos, idx = -1;
+
+	BUG_ON(ssidev == 0);
+#endif
 
 retry:
 	spin_lock(&inuse_lock);
+#ifdef CFS_CLIST_LLIST
+	for (pos = 0 ; pos < CFS_MAX_LISTS ; pos++) {
+		if (inuse[pos] == ssidev) {
+			/* ssidev busy */
+			if (idx != -1) {
+				inuse[idx] = FALSE;
+				idx = -1;
+			}
+			//output = TRUE;
+			break;
+		} else if (idx == -1 && !inuse[pos]) { 
+			inuse[pos] = ssidev;
+			idx = pos;
+		}
+	}
+	spin_unlock(&inuse_lock);
+	if (idx == -1) {
+#else
 	for (idx = 0 ; idx < CFS_MAX_LISTS ; idx++) {
 		if (!inuse[idx]) {
 			inuse[idx] = TRUE;
@@ -408,6 +465,7 @@
 	}
 	spin_unlock(&inuse_lock);
 	if (idx == CFS_MAX_LISTS) {
+#endif
 	    if (!output) {
 		printk(KERN_WARNING "Possible deadlock waiting for c_ilists[] availability\n");
 		output = TRUE;
@@ -463,7 +521,11 @@
 	void *arg, int idx)
 {
 	struct list_head *act_head;
+#ifndef CFS_CLIST_LLIST
 	struct cnode *cnode;
+#else
+	struct cnode *cnode, *tmp;
+#endif
 	ics_chunk_t *icp;
 	struct inode **ipp;
 #ifdef ICS_CHUNKS_LIMIT
@@ -472,20 +534,27 @@
 
 	SSI_ASSERT(arg != NULL);
 
-	icp = (ics_chunk_t *)kmalloc_nofail(sizeof(ics_chunk_t));
+	icp = kmalloc_nofail(sizeof(*icp));
 	ics_chunk_init(icp, sizeof(struct inode **));
+	icp->ic_freeme = 1;
+
+	*(ics_chunk_t **)arg = icp;
 
 #ifdef ICS_CHUNKS_LIMIT
 	list_for_each(act_head, tofree_head) count++;
-
-	if (!count) return;
+	if (!count)
+		return;
 
 	ics_chunk_prealloc(icp, count);
 #endif
+#ifndef CFS_CLIST_LLIST
 	act_head = tofree_head->next;
 	while (act_head != tofree_head) {
 		cnode = list_entry(act_head, struct cnode, c_ilists[idx]);
 		act_head = act_head->next;
+#else
+	list_for_each_entry_safe(cnode, tmp, tofree_head, c_ilists[idx]) {
+#endif
 		/* Remove from the list so we won't have problems... */
 		list_del_init(&cnode->c_ilists[idx]);
 
@@ -510,8 +579,9 @@
 		 */
 		*ipp = ctoi(cnode);
 	}
-	*(ics_chunk_t **)arg = icp;
+#ifndef CFS_CLIST_LLIST
 	cfs_free_cnode_idx(idx);
+#endif
 } /* end cfs_rebuild_tokens_cnode_filter() */
 
 void
@@ -652,20 +722,30 @@
 static void
 count_waiters(struct list_head *tofree_head, void *arg, int idx)
 {
+#ifndef CFS_CLIST_LLIST
 	struct list_head *act_head;
 	struct cnode *cnode;
+#else
+	struct cnode *cnode, *tmp;
+#endif
 	int *waiters = (int *)arg;
 
+#ifndef CFS_CLIST_LLIST
 	act_head = tofree_head->next;
 	while (act_head != tofree_head) {
 		cnode = list_entry(act_head, struct cnode, c_ilists[idx]);
 		act_head = act_head->next;
+#else
+	list_for_each_entry_safe(cnode, tmp, tofree_head, c_ilists[idx]) {
+#endif
 		/* Remove from the list so we won't have problems... */
 		list_del_init(&cnode->c_ilists[idx]);
 		*waiters += cfstok_waitcount(ctoi(cnode));
 		iput(ctoi(cnode));
 	}
+#ifndef CFS_CLIST_LLIST
 	cfs_free_cnode_idx(idx);
+#endif
 }
 
 int
@@ -685,7 +765,6 @@
 	return waiters;
 } /* end cfs_struct superok_waitcount() */
 
-#ifdef SSI_CFS_SKIP
 #if defined(DEBUG) || defined(DEBUG_TOOLS)
 #ifdef DEBUG
 
@@ -744,7 +823,9 @@
 {
 	int i;
 	object_t obj;
-	extern tok_param_t svrparam, cliparam;
+	extern tok_param_t cliparam;
+	extern void tok_print(object_t *, nrtcb_t *);
+#ifdef SSI_CFS_SKIP
 	struct inode *ip = ctoi(cp);
 
 	debug_printf("cp = 0x%x, freef = %8x, freeb = %8x, hash = %8x\n",
@@ -808,25 +889,31 @@
 				rp->start, rp->len);
 	}
 #endif
+#endif /* SSI_CFS_SKIP */
 	obj.word1 = (long)ctoi(cp);
 	obj.obj_pp = &cliparam;
 	if (cfs_print_tokens)
-	for (i = 0; i < CFSTOK_NTOKS; i++) {
+	for (i = 1; i <= CFSTOK_NTOKS; i++) {
 		obj.word2 = i;
 		debug_printf(" Tok %s: ", cfstok_names[i]);
+#ifdef CFSTOK_RANGE
 		if (BITVAL(i) & CFSTOK_RANGE)
 			tok_print_range(&obj, VTORTCB(ctoi(cp), i));
 		else
-			tok_print(&obj, VTOTCB(ctoi(cp), i));
+#endif
+			tok_print(&obj, ITOTCB(ctoi(cp), i));
 		debug_printf("\n");
 	}
+#ifdef SSI_CFS_SKIP
 	debug_printf(" dinext 0x%x diprev 0x%x\n",
 		     cp->c_dinext, cp->c_diprev);
 	debug_printf(" resv %d resv ret %d\n",
 		     cp->c_resv, cp->c_resv_ret);
 	debug_printf("c_lkpendlist 0x%x\n", cp->c_lkpendlist );
+#endif
 }
 
+#ifdef SSI_CFS_SKIP
 print_time(char *str, timestruc_t *timep)
 {
 	debug_printf("%s: %d sec, %d nsec\n", str, timep->tv_sec,
@@ -950,8 +1037,10 @@
 		     READ_ATOMIC_INT(&mip->mi_svrcfstoks));
 } /* end print_cfs_mntinfo() */
 
+#endif /* SSI_CFS_SKIP */
 #endif /* DEBUG || DEBUG_TOOLS */
 
+#ifdef SSI_CFS_SKIP
 static int
 cfs_sb_path_alloc(char **outpp,
 		   const char *pathp,
@@ -1068,6 +1157,9 @@
 		INIT_LIST_HEAD(&mip->lru_busy);
 #endif
 		INIT_LIST_HEAD(&mip->dirty_down);
+#ifdef CFS_COMMIT_DOWN
+		INIT_LIST_HEAD(&mip->commit_down);
+#endif
 		INIT_LIST_HEAD(&mip->read_down);
 #ifdef KERNEL2616_53
 		mip->rsize = CFS_MAX_FILE_IO_SIZE;
@@ -1194,21 +1286,28 @@
 
 void detach_hp(struct list_head *tofree_head, void *unused, int idx)
 {
+#ifndef CFS_CLIST_LLIST
 	struct list_head *act_head;
 	struct cnode *cnode;
+#else
+	struct cnode *cnode, *tmp;
+#endif
 	struct svrcfstok *hp;	/* Pointer to server token structure. */
 
+#ifndef CFS_CLIST_LLIST
 	act_head = tofree_head->next;
 	while (act_head != tofree_head) {
 		cnode = list_entry(act_head, struct cnode, c_ilists[idx]);
 		act_head = act_head->next;
+#else
+	list_for_each_entry_safe(cnode, tmp, tofree_head, c_ilists[idx]) {
+#endif
 		/* Remove from the list so we won't have problems... */
 		list_del_init(&cnode->c_ilists[idx]);
 
 		/* 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. */
@@ -1216,7 +1315,9 @@
 			HASH_RELE(hp);
 		iput(ctoi(cnode));
 	}
+#ifndef CFS_CLIST_LLIST
 	cfs_free_cnode_idx(idx);
+#endif
 }
 
 void
@@ -1289,6 +1390,7 @@
 	clargs.cla_fhandle = *ctofh(cp);
 	clargs.cla_fromnode = this_node;
 
+	lock_kernel();
 	for (fl = inode->i_flock; fl; fl = fl->fl_next) {
 		/* Walk the i_flock list until all locks are rebuilt */
 		clargs.cla_seq = tokseq_getseq(cfs_tsp, server,
@@ -1325,6 +1427,7 @@
 			error = cfs_nsc_rcall_errno("cfs_rb_locks_send",error);
 		SSI_ASSERT(!error);
 	}
+	unlock_kernel();
 
 	return error;
 }

Index: vfs.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/vfs.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- vfs.c	24 Mar 2009 04:26:28 -0000	1.31
+++ vfs.c	27 Oct 2009 03:18:29 -0000	1.32
@@ -89,9 +89,9 @@
 
 	SSI_ASSERT(!isdotent(name->name, name->len));
 
-	err = -EACCES;
 	if (isdotent(name->name, name->len)) {
 		dprintk("lookup got . or .. at server\n");
+		err = -EACCES;
 		goto nolockout;
 	}
 
@@ -379,11 +379,10 @@
 	/* Disallow access to files with the append-only bit set or
 	 * with mandatory locking enabled
 	 */
-	err = -EPERM;
-	if (IS_APPEND(inode) || IS_ISMNDLK(inode))
-		goto out;
-	if (!inode->i_fop)
+	if (IS_APPEND(inode) || IS_ISMNDLK(inode) || !inode->i_fop) {
+		err = -EPERM;
 		goto out;
+	}
 
 	/*
 	 * Check to see if there are any leases on this file.
@@ -595,6 +594,55 @@
 	cfsd_dosync(NULL, dp, dp->d_inode->i_fop, datasync);
 }
 
+#ifdef CFS_PAGEVEC_SENDFILE
+struct cfs_svc_rqst {
+	struct page **	svr_pages;
+	unsigned int	svr_count;
+	unsigned long	svr_pglen;
+	unsigned long	svr_pgbase;
+	unsigned long	cli_count;
+	unsigned long	cli_pgbase;
+	struct page **	cli_pages;
+};
+
+/*
+ * Grab and keep cached pages assosiated with a file in the svc_rqst
+ * so that they can be passed to the netowork sendmsg/sendpage routines
+ * directrly. They will be released after the sending has completed.
+ */
+static int
+cfsd_read_actor(
+	read_descriptor_t *desc,
+	struct page *page,
+	unsigned long offset,
+	unsigned long size)
+{
+	unsigned long count = desc->count;
+	struct cfs_svc_rqst *rqst = desc->arg.data;
+
+	if (size > count)
+		size = count;
+
+	if (rqst->svr_pglen == 0) {
+		get_page(page);
+		rqst->svr_pages[rqst->svr_count++] = page;
+		rqst->svr_pgbase = offset;
+		rqst->svr_pglen = size;
+	} else if (page != rqst->svr_pages[rqst->svr_count-1]) {
+		get_page(page);
+		rqst->svr_pages[rqst->svr_count++] = page;
+		rqst->svr_pglen += size;
+	} else {
+		/* Partial page */
+		rqst->svr_pglen += size;
+	}
+
+	desc->count = count - size;
+	desc->written += size;
+	return size;
+}
+#endif /* CFS_PAGEVEC_SENDFILE */
+
 /**
  * Read data from a file. count must contain the requested read count
  * on entry. On return, *count contains the number of bytes actually read.
@@ -605,13 +653,13 @@
  */
 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)
+#ifdef CFS_PAGEVEC_SENDFILE
+cfsd_read(struct svrcfstok *hp, loff_t offset, struct kvec *vec, int vlen,
+	  unsigned long *count, struct cfs_svc_rqst *rqst)
 #else
-cfsd_read(struct svrcfstok *hp, loff_t offset,
-	  struct kvec *vec, int vlen, unsigned long *count)
-#endif
+cfsd_read(struct svrcfstok *hp, loff_t offset, struct kvec *vec, int vlen,
+	  unsigned long *count)
+#endif /* !CFS_PAGEVEC_SENDFILE */
 #else
 cfsd_read(struct svrcfstok *hp, loff_t offset, char *buf, unsigned long *count)
 #endif
@@ -623,9 +671,10 @@
 	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) {
+		err = -EPERM;
 		goto out_close;
+	}
 
 #ifdef CFS_PARANOIA
 	SSI_ASSERT((ssize_t)count > 0);
@@ -640,54 +689,43 @@
 
 #ifdef CFS_READAHEAD
 	/* Get readahead parameters */
+	LOCK_COND_LOCK(&hp->sct_statelock);
 	if (hp->sct_ra.ra_pages)
 		file->f_ra = hp->sct_ra;
+	UNLOCK_COND_LOCK(&hp->sct_statelock);
 #endif
 
-	oldfs = get_fs(); set_fs(KERNEL_DS);
 #ifdef CFS_PAGEVEC
-#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;
-		while (vlen > 0) {
-			void __user * base;
-			size_t len;
-			ssize_t nr;
-
-			base = vec->iov_base;
-			len = vec->iov_len;
-			vec++;
-			vlen--;
-
-			nr = file->f_op->read(file, base, len, &offset);
-
-			if (nr < 0) {
-				if (!err) err = nr;
-				break;
-			}
-			err += nr;
-			if (nr != len)
-				break;
+#ifdef CFS_PAGEVEC_SENDFILE
+	if (file->f_op->sendfile) {
+		if (target) {
+			err = file->f_op->sendfile(file, &offset, *count,
+						cfsd_read_actor, rqst);
+			goto done;
 		}
+		if (!test_bit(CFS_SENDFILE, &hp->sct_flags))
+			set_bit(CFS_SENDFILE, &hp->sct_flags);
 	}
-#else
+#endif
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
+	set_fs(oldfs);
+#ifdef CFS_PAGEVEC_SENDFILE
+done:
+#endif
+#else /* CFS_PAGEVEC */
 	file->f_pos = offset;
 
+	oldfs = get_fs(); set_fs(KERNEL_DS);
 	err = file->f_op->read(file, buf, *count, file->f_pos);
-#endif
 	set_fs(oldfs);
+#endif /* !CFS_PAGEVEC */
 
 #ifdef CFS_READAHEAD
 	/* Write back readahead params */
+	LOCK_COND_LOCK(&hp->sct_statelock);
 	hp->sct_ra = file->f_ra;
+	UNLOCK_COND_LOCK(&hp->sct_statelock);
 #endif
 
 	dprintk("cfsd: read complete err=%d\n", err);
@@ -708,13 +746,8 @@
  */
 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)
@@ -737,9 +770,10 @@
 		goto out;
 	if (!cnt)
 		goto out_close;
-	err = -EPERM;
-	if (!file->f_op->write)
+	if (!file->f_op->write) {
+		err = -EPERM;
 		goto out_close;
+	}
 
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
@@ -765,8 +799,6 @@
 			file->f_flags |= O_SYNC;
 
 	/* Write the data. */
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-#ifdef CFS_PAGEVEC
 #ifdef CFS_FILE_WRITE_LIVELOCK_FIX
 	/* RT: [ ssic-linux-Bugs-686748 ] Filesystem stacking deadlock.
 	 *
@@ -792,50 +824,20 @@
 	} else
 		stacked = 0;
 #endif
+	oldfs = get_fs(); set_fs(KERNEL_DS);
 
-#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) {
-			void __user * base;
-			size_t len;
-			ssize_t nr;
-
-			base = vec->iov_base;
-			len = vec->iov_len;
-			vec++;
-			vlen--;
-
-			nr = file->f_op->write(file, base, len, &offset);
-
-			if (nr < 0) {
-				if (!err) err = nr;
-				break;
-			}
-			err += nr;
-			if (nr != len)
-				break;
-		}
-	}
-#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
-	if (stacked)
-		inode->i_sem.flusher = NULL;
-#endif
+#ifdef CFS_PAGEVEC
+	err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
 #else
 	file->f_pos = offset;		/* set write offset */
 
 	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);
+#ifdef CFS_FILE_WRITE_LIVELOCK_FIX
+	if (stacked)
+		inode->i_sem.flusher = NULL;
+#endif
 	if (err > 0)
 		dnotify_parent(file->f_dentry, DN_MODIFY);
 
@@ -904,38 +906,48 @@
  * already be locked. Note that the parent directory is left locked.
  */
 int
+#ifdef CFS_UMASK_FIX
+cfsd_create(struct svrcfstok *dhp, struct qstr *name, int mode, int umask,
+		int type, dev_t rdev, int flags, struct svrcfstok **hpp)
+#else
 cfsd_create(struct svrcfstok *dhp, struct qstr *name, int mode,
 		int type, dev_t rdev, int flags, struct svrcfstok **hpp)
+#endif
 {
 	struct dentry	*dentry, *dchild = NULL;
 	struct inode	*dirp;
 	int		err;
-	dev_t			dev = (dev_t)*(__u32 *)(&dhp->sct_fh);
+	dev_t		dev = (dev_t)*(__u32 *)(&dhp->sct_fh);
 
 	*hpp = NULL;
 
-	err = -EPERM;
-	if (!name->len)
+	if (!name->len) {
+		err = -EPERM;
 		goto out;
-	err = -EPERM;
-	if (isdotent(name->name, name->len))
+	}
+	if (isdotent(name->name, name->len)) {
+		err = -EEXIST;
 		goto out;
+	}
 
 	dentry = dhp->sct_dp;
 	dirp = dentry->d_inode;
 
-	err = -ENOTDIR;
-	if(!dirp->i_op || !dirp->i_op->lookup)
+	if(!dirp->i_op || !dirp->i_op->lookup) {
+		err = -ENOTDIR;
 		goto out;
+	}
 
 	down(&dirp->i_sem);
-	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &dhp->sct_flags))
 #else
 	if (dhp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out_up;
+	}
 	dchild = lookup_hash(name, dentry);
 	if (IS_ERR(dchild)) {
 		err = PTR_ERR(dchild);
@@ -961,7 +973,7 @@
 	 * was getting the parent directory token exclusively.
 	 *
 	 */
-	if (dchild->d_inode) {
+	if (unlikely(dchild->d_inode)) {
 		dprintk("cfsd_create: dentry %s/%s not negative!\n",
 			dentry->d_name.name, dchild->d_name.name);
 		/* mkdir, mknod always work like O_EXCL */
@@ -974,12 +986,21 @@
 		goto out_up;
 	}
 
-	mode = (mode & S_IALLUGO) | type;
+#ifdef CFS_UMASK_FIX
+	if (umask) {
+		SSI_ASSERT(ssi_isremote());
+		SSI_ASSERT(current->fs->umask == 0);
+		/* client umask for MS_POSIXACL */
+		current->fs->umask = umask;
+	}
+#else
+	mode = (mode & S_IALLUGO) | type; /* still need? done in VFS */
+#endif
 
 	/*
 	 * Get the dir op function pointer.
 	 */
-	err = -EPERM;
+	/* err = -EPERM; */
 	switch (type) {
 	case S_IFREG:
 		err = vfs_create(dirp, dchild, mode, NULL);
@@ -997,10 +1018,14 @@
 	        printk("cfsd: bad file type %o in cfsd_create\n", type);
 		err = -EINVAL;
 	}
+#ifdef CFS_UMASK_FIX
+	if (umask)
+		current->fs->umask = 0;
+#endif
 	if (err < 0)
 		goto out_up;
 
-	err = 0;
+	/* err = 0; */
 
 #ifdef SSI_CFS_NEGDCACHE
 	/* Bump generation number due to directory change */
@@ -1044,9 +1069,10 @@
 	dentry = hp->sct_dp;
 	inode = dentry->d_inode;
 
-	err = -EINVAL;
-	if (!inode->i_op || !inode->i_op->readlink)
+	if (!inode->i_op || !inode->i_op->readlink) {
+		err = -EINVAL;
 		goto out;
+	}
 
 #ifdef SSI_CFS_XXX
 	/* SSI_XXX: Following unlink it is possible the d_inode
@@ -1093,22 +1119,26 @@
 
 	*hpp = NULL;
 
-	err = -ENOENT;
-	if (!fname->len)
+	if (!fname->len) {
+		err = -ENOENT;
 		goto out;
-	err = -EEXIST;
-	if (isdotent(fname->name, fname->len))
+	}
+	if (isdotent(fname->name, fname->len)) {
+		err = -EEXIST;
 		goto out;
+	}
 
 	dentry = dhp->sct_dp;
 	down(&dentry->d_inode->i_sem);
-	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &dhp->sct_flags))
 #else
 	if (dhp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out_up;
+	}
 	dnew = lookup_hash(fname, dentry);
 	if (IS_ERR(dnew)) {
 		err = PTR_ERR(dnew);
@@ -1182,24 +1212,28 @@
 	struct inode	*dirp, *dest;
 	int		err;
 
-	err = -EPERM;
-	if (!name->len)
+	if (!name->len) {
+		err = -EPERM;
 		goto out;
-	err = -EEXIST;
-	if (isdotent(name->name, name->len))
+	}
+	if (isdotent(name->name, name->len)) {
+		err = -EEXIST;
 		goto out;
+	}
 
 	ddir = dhp->sct_dp;
 	dirp = ddir->d_inode;
 	down(&dirp->i_sem);
 
-	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &dhp->sct_flags))
 #else
 	if (dhp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out_up;
+	}
 
 	dnew = lookup_hash(name, ddir);
 	if (IS_ERR(dnew)) {
@@ -1209,14 +1243,16 @@
 
 	dold = thp->sct_dp;
 	dest = dold->d_inode;
-	err = -ENOENT;
 	/* Serialized by dirp->i_sem */
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &thp->sct_flags))
 #else
 	if (thp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out_dput;
+	}
 
 	err = vfs_link(dold, dirp, dnew);
 	if (!err) {
@@ -1255,32 +1291,28 @@
 		 struct svrcfstok **thpp)
 {
 	struct dentry	*fdentry, *tdentry, *odentry, *ndentry, *trap;
-	struct inode	*fdir, *tdir;
-	int		err;
-	struct svrcfstok *fhp = NULL, *thp = NULL;
+	struct svrcfstok *fhp, *thp;
 	dev_t			dev;
+	int		err;
 
 	*fhpp = *thpp = NULL;
 
-	fdentry = fromhp->sct_dp;
-	fdir = fdentry->d_inode;
-
-	tdentry = tohp->sct_dp;
-	tdir = tdentry->d_inode;
-
 #ifdef SSI_CFS_FROMNFS
 	/* The client should be able to accurately make this check */
 	err = -EACCES;
-	if (fdir->i_sb->s_dev != tdir->i_sb->s_dev)
+	if (fdentry->d_inode->i_sb->s_dev != tdentry->d_inode->i_sb->s_dev)
 		goto out;
 #endif
 
-	err = -EPERM;
-	if (!fname->len || isdotent(fname->name, fname->len) || !tname->len || isdotent(tname->name, tname->len))
+	if (!fname->len || isdotent(fname->name, fname->len) || !tname->len || isdotent(tname->name, tname->len)) {
+		err = -EPERM;
 		goto out;
+	}
+
+	fdentry = fromhp->sct_dp;
+	tdentry = tohp->sct_dp;
 
 	trap = lock_rename(tdentry, fdentry);
-	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &fromhp->sct_flags)
 	    || test_bit(CFS_DELAYUNLNK, &tohp->sct_flags))
@@ -1288,7 +1320,10 @@
 	if ((fromhp->sct_flags & CFS_DELAYUNLNK) ||
 	    (tohp->sct_flags & CFS_DELAYUNLNK))
 #endif
+	{
+		err = -ENOENT;
 		goto out_cfserr;
+	}
 
 	odentry = lookup_hash(fname, fdentry);
 	if (IS_ERR(odentry)) {
@@ -1296,13 +1331,19 @@
 		goto out_cfserr;
 	}
 
-	err = -ENOENT;
-	if (!odentry->d_inode)
+	fhp = thp = NULL;
+
+	if (!odentry->d_inode) {
+		err = -ENOENT;
 		goto out_dput_old;
-	err = -EINVAL;
-	if (odentry == trap)
+	}
+	if (odentry == trap) {
+		err = -EINVAL;
 		goto out_dput_old;
+	}
+
 	dev = (dev_t)*(__u32 *)(&fromhp->sct_fh);
+
 	fhp = makehp(fromhp->sct_sb, dev, odentry);
 	SSI_ASSERT(fhp);
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
@@ -1310,7 +1351,10 @@
 #else
 	if (fhp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -EINVAL;
 		goto out_dput_old;
+	}
 
 	ndentry = lookup_hash(tname, tdentry);
 	if (IS_ERR(ndentry)) {
@@ -1361,7 +1405,7 @@
 #ifdef SKIP
 	lock_kernel();	/* SSI_XXX: for cfs_remount ? */
 #endif
-	err = vfs_rename(fdir, odentry, tdir, ndentry);
+	err = vfs_rename(fdentry->d_inode, odentry, tdentry->d_inode, ndentry);
 #ifdef SKIP
 	unlock_kernel();
 #endif
@@ -1471,16 +1515,19 @@
 
 	down(&(dirp->i_sem));
 
-	err = -EACCES;
-	if (!name->len || isdotent(name->name, name->len))
+	if (!name->len || isdotent(name->name, name->len)) {
+		err = -EACCES;
 		goto out;
-	err = -ENOENT;
+	}
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &dhp->sct_flags))
 #else
 	if (dhp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out;
+	}
 
 	rdentry = lookup_hash(name, dentry);
 	if (IS_ERR(rdentry)) {
@@ -1624,13 +1671,15 @@
 	 */
 	inode = file->f_dentry->d_inode;
 	down(&inode->i_sem);
-	err = -ENOENT;
 #ifdef SVRCFSTOK_SCT_FLAGS_NOLOCK
 	if (test_bit(CFS_DELAYUNLNK, &hp->sct_flags))
 #else
 	if (hp->sct_flags & CFS_DELAYUNLNK)
 #endif
+	{
+		err = -ENOENT;
 		goto out_cfserr;
+	}
 	while (1) {
 		oldlen = cd.buflen;
 
@@ -1821,24 +1870,21 @@
 		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;
+				t->cap_effective = CAP_FULL_SET;
 				error = vfs_mkdir(droot->d_inode, ddir,
 						  S_IRWXUGO);
+				t->cap_effective = save_cap;
 				put_fs_struct(t->fs);
 			} else
 				error = -ENOMEM;
 			t->fs = save_fs;
-			t->cap_effective = save_cap;
 		} 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 |


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
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.