[SSI] openssi/kernel/cluster/ssi/cfs proc.c, 1.25, 1.26 read.c, 1.24, 1.25 write.c, 1.45, 1.46
Roger Tsang <[email protected]> Mon, 25 Oct 2010 05:53:41 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv12379/cluster/ssi/cfs
Modified Files:
Tag: OPENSSI-FC
proc.c read.c write.c
Log Message:
CFS_PROTO->write/read() avoid use of kmap pools. Remove contention when kmap pool limit is reached as the number of CFS threads grows.
- Pre-allocate pagevec during RPC setup only if the pages are not already physically mapped.
- Reduce default CFS_SERVER rsize/wsize from 1MB to 64KB.
cluster/ssi/cfs/proc.c | 54 ++++++++++++
cluster/ssi/cfs/read.c | 79 +++++++++++++++++-
cluster/ssi/cfs/write.c | 129 ++++++++++++++++++++++--------
include/cluster/ssi/cfs/cfs_fs.h | 6 +
include/cluster/ssi/cfs/cfs_xdr.h | 4
5 files changed, 231 insertions(+), 41 deletions(-)
Index: proc.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/proc.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- proc.c 13 Mar 2010 10:02:41 -0000 1.25
+++ proc.c 25 Oct 2010 05:53:39 -0000 1.26
@@ -57,7 +57,7 @@
#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 { \
+#define KMAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
int i, len = (_data)->count; \
\
(_vlen) = (_vlen) ? : \
@@ -88,7 +88,7 @@
BUG_ON(i != (_vlen)); \
} while (0)
-#define UNMAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+#define KUNMAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
int i; \
\
for (i = 0; i < (_vlen); i++) \
@@ -96,6 +96,56 @@
kfree(_vec); \
} while (0)
+#ifdef CFS_ASYNC_LOCAL_SYNC
+#define __MAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+ int i, len = (_data)->count; \
+ \
+ (_vlen) = (_vlen) ? : \
+ ((_data)->pgbase + (_data)->count + PAGE_SIZE - 1) \
+ >> PAGE_SHIFT; \
+ \
+ (_vec) = kmalloc((_vlen) * sizeof(struct kvec), GFP_NOFS|__GFP_NOFAIL); \
+ \
+ (_vec)[0].iov_base = page_address((_data)->pagevec[0]) + (_data)->pgbase; \
+ (_vec)[0].iov_len = min_t(typeof((_vec)[0].iov_len), \
+ len, PAGE_SIZE - (_data)->pgbase); \
+ len -= (PAGE_SIZE - (_data)->pgbase); \
+ \
+ i = 1; \
+ while (len > 0) { \
+ (_vec)[i].iov_base = page_address((_data)->pagevec[i]); \
+ (_vec)[i].iov_len = \
+ min_t(typeof((_vec)[0].iov_len), len, PAGE_SIZE); \
+ len -= PAGE_SIZE; \
+ i++; \
+ } \
+ \
+ BUG_ON(i != (_vlen)); \
+} while (0)
+
+#define __UNMAP_CFS_PAGEVEC(_data, _vec, _vlen) kfree(_vec)
+
+#define MAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+ if (likely((_data)->is_local)) \
+ __MAP_CFS_PAGEVEC(_data, _vec, _vlen); \
+ else \
+ KMAP_CFS_PAGEVEC(_data, _vec, _vlen); \
+} while (0)
+
+#define UNMAP_CFS_PAGEVEC(_data, _vec, _vlen) do { \
+ if (likely((_data)->is_local)) \
+ __UNMAP_CFS_PAGEVEC(_data, _vec, _vlen); \
+ else \
+ KUNMAP_CFS_PAGEVEC(_data, _vec, _vlen); \
+} while (0)
+
+#else /* CFS_ASYNC_LOCAL_SYNC */
+#define MAP_CFS_PAGEVEC(_data, _vec, _vlen) \
+ KMAP_CFS_PAGEVEC(_data, _vec, _vlen)
+#define UNMAP_CFS_PAGEVEC(_data, _vec, _vlen) \
+ KUNMAP_CFS_PAGEVEC(_data, _vec, _vlen)
+#endif /* !CFS_ASYNC_LOCAL_SYNC */
+
#ifndef ICS_OOL_STRUCT_PAGES
#define CFS_PAGEVEC_MAP_BUFFER(_data, _buf, _vlen) do { \
_vlen = _vlen ? : (_data->pgbase + _data->count + PAGE_SIZE - 1) \
Index: read.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/read.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- read.c 5 Mar 2010 05:23:57 -0000 1.24
+++ read.c 25 Oct 2010 05:53:39 -0000 1.25
@@ -90,6 +90,7 @@
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
#ifdef CFS_PAGEVEC
+ p->npages = pages;
if (pages <= CFS_PAGEVEC_SIZE)
p->pagevec = &p->page_array[0];
else {
@@ -108,6 +109,12 @@
static inline void cfs_readdata_free(struct cfs_read_data *p)
{
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ while (p->is_local && p->npages--) {
+ if (p->pagevec[p->npages])
+ __free_page(p->pagevec[p->npages]);
+ }
+#endif
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
#endif
@@ -338,10 +345,19 @@
/*
* Set up the CFS read request struct
*/
+#ifdef CFS_ASYNC_LOCAL_SYNC
+static int
+cfs_read_rpcsetup(struct list_head *head, struct cfs_read_data *data,
+ unsigned int count, unsigned int offset, unsigned npages)
+#else
static void
cfs_read_rpcsetup(struct cfs_page *req, struct cfs_read_data *data,
unsigned int count, unsigned int offset)
+#endif /* !CFS_ASYNC_LOCAL_SYNC */
{
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ struct cfs_page *req = cfs_list_entry(head->next);
+#endif
#ifdef CFS_PARANOIA
if (offset || req->wb_offset)
BUG();
@@ -355,15 +371,40 @@
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->is_local = CFS_AT_SERVER(data->inode);
+ if (!data->is_local || !CFS_SB_UP_MIP(itocmi(data->inode))) {
data->flags = RPC_TASK_ASYNC;
if (IS_SWAPFILE(req->wb_inode))
data->flags |= CFS_RPC_SWAPFLAGS;
}
+
+ if (data->is_local) {
+ struct cfs_page *cp;
+ /* Unset is_local, do zero-copy if page cache is not virtual */
+ list_for_each_entry(cp, head, wb_list) {
+ if (PageHighMem(cp->wb_page)) {
+ data->is_local = -1;
+ break;
+ }
+ }
+ if (data->is_local == -1) {
+ int count;
+ for (count = 0; count < npages; count++) {
+ data->pagevec[count] = alloc_page(GFP_NOFS);
+ if (!data->pagevec[count])
+ break;
+ }
+ if (count != npages) {
+ cfs_readdata_free(data);
+ return -ENOMEM;
+ }
+ } else
+ data->is_local = 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
+#endif /* !CFS_ASYNC_LOCAL_SYNC */
#ifdef SKIP
/* This is derived from nfs3_proc_read_setup() */
/* N.B. Do we need to test? Never called for swapfile inode */
@@ -375,6 +416,9 @@
dprintk("CFS: %8d initiated read call (req %x/%lu)\n",
current->pid,
data->inode->i_sb->s_dev, data->inode->i_ino);
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ return 0;
+#endif
}
static void
@@ -396,6 +440,9 @@
struct cfs_page *req;
struct page *page;
unsigned int count = (ssize_t)data->res_count;
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ int i = 0;
+#endif
dprintk("CFS: read (%x/%ld %d@%Ld)\n",
data->inode->i_sb->s_dev,
@@ -410,6 +457,12 @@
cfs_list_remove_request(req);
if (status >= 0) {
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ if (data->is_local) {
+ copy_highpage(page, data->pagevec[i]);
+ i++;
+ }
+#endif
if (count < PAGE_CACHE_SIZE) {
if (count < req->wb_bytes)
memclear_highpage_flush(page,
@@ -502,9 +555,12 @@
#ifndef CFS_CHARD_RACE_FIX
#error not supported
#endif
- do {
+ for (;;) {
status = CFS_PROTO(data->inode)->read(data);
- } while (cfs_readpage_result(data, status) == -EAGAIN);
+ if (cfs_readpage_result(data, status) != -EAGAIN)
+ break;
+ cond_resched();
+ }
#else /* CFS_PAGEVEC */
#ifdef CFS_CHARD_RACE_FIX
#warning deprecated
@@ -664,6 +720,10 @@
goto out_bad;
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ if (cfs_read_rpcsetup(head, data, 0, 0, npages))
+ goto out_bad;
+#endif
pages = data->pagevec;
#endif
count = 0;
@@ -673,13 +733,22 @@
cfs_list_add_request(req, &data->pages);
ClearPageError(req->wb_page);
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ if (data->is_local)
+ copy_highpage(*pages++, req->wb_page);
+ else
+#endif
*pages++ = req->wb_page;
#endif
count += req->wb_bytes;
}
- req = cfs_list_entry(data->pages.next);
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ data->count = count;
+#else
+ req = cfs_list_entry(data->pages.next);
cfs_read_rpcsetup(req, data, count, 0);
+#endif
return cfs_execute_read(data);
Index: write.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/cfs/write.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- write.c 2 Apr 2010 20:53:20 -0000 1.45
+++ write.c 25 Oct 2010 05:53:39 -0000 1.46
@@ -142,6 +142,7 @@
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
#ifdef CFS_PAGEVEC
+ p->npages = pages;
if (pages <= CFS_PAGEVEC_SIZE)
p->pagevec = &p->page_array[0];
else {
@@ -160,6 +161,12 @@
static __inline__ void cfs_writedata_free(struct cfs_write_data *p)
{
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ while (p->is_local && p->npages--) {
+ if (p->pagevec[p->npages])
+ __free_page(p->pagevec[p->npages]);
+ }
+#endif
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
#endif
@@ -1242,7 +1249,7 @@
#endif
int status;
#ifdef CFS_PAGEVEC
- int prio = 0;
+ u_char prio = 0;
#else
struct inode *inode = data->inode;
int stable = data->stable;
@@ -1254,27 +1261,28 @@
#ifndef CFS_CHARD_RACE_FIX
#warning not supported
#endif
- do {
#ifdef CFS_ASYNC_QUEUE
- if (data->priority == RPC_PRIORITY_HIGH) {
+ if (data->priority == RPC_PRIORITY_HIGH) {
#else
- if (data->ics_prio) {
+ if (data->ics_prio) {
#endif
- prio = ics_getpriority();
- if (prio < ICS_MAX_PRIO)
- ics_setpriority(prio + 1);
- }
+ prio = ics_getpriority();
+ if (prio < ICS_MAX_PRIO)
+ ics_setpriority(prio + 1);
+ }
+ for (;;) {
status = CFS_PROTO(data->inode)->write(data);
-
+ if (cfs_writeback_done(data, status) != -EAGAIN)
+ break;
+ cond_resched();
+ }
#ifdef CFS_ASYNC_QUEUE
- if (data->priority == RPC_PRIORITY_HIGH)
+ if (data->priority == RPC_PRIORITY_HIGH)
#else
- if (data->ics_prio)
+ if (data->ics_prio)
#endif
- ics_setpriority(prio);
-
- } while (cfs_writeback_done(data, status) == -EAGAIN);
+ ics_setpriority(prio);
#else /* CFS_PAGEVEC */
#ifdef CFS_CHARD_RACE_FIX
#warning deprecated
@@ -1459,11 +1467,21 @@
/*
* Set up the argument/result storage required for the RPC call.
*/
+#ifdef CFS_ASYNC_LOCAL_SYNC
+static int cfs_write_rpcsetup(struct list_head *head,
+ struct cfs_write_data *data,
+ unsigned int count, unsigned int offset,
+ int how, unsigned npages)
+#else
static void cfs_write_rpcsetup(struct cfs_page *req,
struct cfs_write_data *data,
unsigned int count, unsigned int offset,
int how)
+#endif /* !CFS_ASYNC_LOCAL_SYNC */
{
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ struct cfs_page *req = cfs_list_entry(head->next);
+#endif
struct inode *inode;
int stable;
@@ -1482,13 +1500,38 @@
* See related [ ssic-linux-Bugs-686748 ]
* -Roger
*/
+ data->is_local = CFS_AT_SERVER(inode);
if (!(how & FLUSH_SYNC) &&
- (!CFS_AT_SERVER(inode) || !CFS_SB_UP_SB(inode->i_sb)))
+ (!data->is_local || !CFS_SB_UP_SB(inode->i_sb)))
data->flags = RPC_TASK_ASYNC;
+
+ if (data->is_local) {
+ struct cfs_page *cp;
+ /* Unset is_local, do zero-copy if page cache is not virtual */
+ list_for_each_entry(cp, head, wb_list) {
+ if (PageHighMem(cp->wb_page)) {
+ data->is_local = -1;
+ break;
+ }
+ }
+ if (data->is_local == -1) {
+ int count;
+ for (count = 0; count < npages; count++) {
+ data->pagevec[count] = alloc_page(GFP_NOFS);
+ if (!data->pagevec[count])
+ break;
+ }
+ if (count != npages) {
+ cfs_writedata_free(data);
+ return -ENOMEM;
+ }
+ } else
+ data->is_local = 0;
+ }
#else
/* Set the initial flags for the task. */
data->flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
-#endif
+#endif /* !CFS_ASYNC_LOCAL_SYNC */
#endif /* CFS_PAGEVEC */
/* This is derived from nfs3_proc_write_setup() */
#ifdef CFS_ONLY_REMOTE_IS_CHARD
@@ -1526,6 +1569,9 @@
count,
(unsigned long long)data->offset);
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ return 0;
+#endif
#ifdef SSI_SKIP /* Don't delete this, keeps fs/nfs/write.c comparison */
/* Set up the RPC argument and reply structs
* NB: take care not to mess about with data->commit et al. */
@@ -1593,6 +1639,10 @@
goto out_bad;
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ if (cfs_write_rpcsetup(head, data, 0, 0, how, npages))
+ goto out_bad;
+#endif
pages = data->pagevec;
#endif
count = 0;
@@ -1607,14 +1657,23 @@
SetPageWriteback(req->wb_page);
#endif
#ifdef CFS_PAGEVEC
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ if (data->is_local)
+ copy_highpage(*pages++, req->wb_page);
+ else
+#endif
*pages++ = req->wb_page;
#endif
count += req->wb_bytes;
}
- req = cfs_list_entry(data->pages.next);
+#ifdef CFS_ASYNC_LOCAL_SYNC
+ data->count = count;
+#else
+ req = cfs_list_entry(data->pages.next);
/* Set up the argument struct */
cfs_write_rpcsetup(req, data, count, 0, how);
+#endif
return cfs_execute_write(data);
@@ -1797,38 +1856,42 @@
int status = 0;
#ifndef CFS_PAGEVEC
unsigned int res = 0;
+#else
+ u_char prio = 0;
#endif
#ifdef CFSD_COMMIT
- if (CFS_SB_HARD_MIP(itocmi(data->inode)))
+ if (CFS_SB_HARD_MIP(itocmi(data->inode))) {
#endif
#ifdef CFS_PAGEVEC
#ifndef CFS_CHARD_RACE_FIX
#error not supported
#endif
- do {
- u_char prio = 0;
-
#ifdef CFS_ASYNC_QUEUE
- if (data->priority == RPC_PRIORITY_HIGH) {
+ if (data->priority == RPC_PRIORITY_HIGH) {
#else
- if (data->ics_prio) {
+ if (data->ics_prio) {
#endif
- prio = ics_getpriority();
- if (prio < ICS_MAX_PRIO)
- ics_setpriority(prio + 1);
- }
+ prio = ics_getpriority();
+ if (prio < ICS_MAX_PRIO)
+ ics_setpriority(prio + 1);
+ }
+ for (;;) {
status = CFS_PROTO(data->inode)->commit(data);
-
+ if (cfs_commit_result(data, status) != -EAGAIN)
+ break;
+ cond_resched();
+ }
#ifdef CFS_ASYNC_QUEUE
- if (data->priority == RPC_PRIORITY_HIGH)
+ if (data->priority == RPC_PRIORITY_HIGH)
#else
- if (data->ics_prio)
+ if (data->ics_prio)
+#endif
+ ics_setpriority(prio);
+#ifdef CFSD_COMMIT
+ }
#endif
- ics_setpriority(prio);
-
- } while (cfs_commit_result(data, status) == -EAGAIN);
#else /* CFS_PAGEVEC */
#ifdef CFS_CHARD_RACE_FIX
#warning deprecated
------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store
http://p.sf.net/sfu/nokia-dev2dev