[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