summaryrefslogtreecommitdiffstats
path: root/xlators/performance/io-cache/src/page.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/performance/io-cache/src/page.c')
-rw-r--r--xlators/performance/io-cache/src/page.c269
1 files changed, 182 insertions, 87 deletions
diff --git a/xlators/performance/io-cache/src/page.c b/xlators/performance/io-cache/src/page.c
index 0721f5f04..b2e20ba65 100644
--- a/xlators/performance/io-cache/src/page.c
+++ b/xlators/performance/io-cache/src/page.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -46,7 +37,7 @@ out:
ioc_page_t *
-ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
+__ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
{
ioc_page_t *page = NULL;
ioc_table_t *table = NULL;
@@ -72,14 +63,34 @@ out:
}
+ioc_page_t *
+ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
+{
+ ioc_page_t *page = NULL;
+
+ if (ioc_inode == NULL) {
+ goto out;
+ }
+
+ ioc_inode_lock (ioc_inode);
+ {
+ page = __ioc_page_get (ioc_inode, offset);
+ }
+ ioc_inode_unlock (ioc_inode);
+
+out:
+ return page;
+}
+
+
/*
- * ioc_page_destroy -
+ * __ioc_page_destroy -
*
* @page:
*
*/
int64_t
-ioc_page_destroy (ioc_page_t *page)
+__ioc_page_destroy (ioc_page_t *page)
{
int64_t page_size = 0;
@@ -91,6 +102,7 @@ ioc_page_destroy (ioc_page_t *page)
if (page->waitq) {
/* frames waiting on this page, do not destroy this page */
page_size = -1;
+ page->stale = 1;
} else {
rbthash_remove (page->inode->cache.page_table, &page->offset,
sizeof (page->offset));
@@ -119,6 +131,63 @@ out:
return page_size;
}
+
+int64_t
+ioc_page_destroy (ioc_page_t *page)
+{
+ int64_t ret = 0;
+
+ if (page == NULL) {
+ goto out;
+ }
+
+ ioc_inode_lock (page->inode);
+ {
+ ret = __ioc_page_destroy (page);
+ }
+ ioc_inode_unlock (page->inode);
+
+out:
+ return ret;
+}
+
+int32_t
+__ioc_inode_prune (ioc_inode_t *curr, uint64_t *size_pruned,
+ uint64_t size_to_prune, uint32_t index)
+{
+ ioc_page_t *page = NULL, *next = NULL;
+ int32_t ret = 0;
+ ioc_table_t *table = NULL;
+
+ if (curr == NULL) {
+ goto out;
+ }
+
+ table = curr->table;
+
+ list_for_each_entry_safe (page, next, &curr->cache.page_lru, page_lru) {
+ *size_pruned += page->size;
+ ret = __ioc_page_destroy (page);
+
+ if (ret != -1)
+ table->cache_used -= ret;
+
+ gf_log (table->xl->name, GF_LOG_TRACE,
+ "index = %d && table->cache_used = %"PRIu64" && table->"
+ "cache_size = %"PRIu64, index, table->cache_used,
+ table->cache_size);
+
+ if ((*size_pruned) >= size_to_prune)
+ break;
+ }
+
+ if (ioc_empty (&curr->cache)) {
+ list_del_init (&curr->inode_lru);
+ }
+
+out:
+ return 0;
+}
/*
* ioc_prune - prune the cache. we have a limit to the number of pages we
* can have in-memory.
@@ -130,8 +199,6 @@ int32_t
ioc_prune (ioc_table_t *table)
{
ioc_inode_t *curr = NULL, *next_ioc_inode = NULL;
- ioc_page_t *page = NULL, *next = NULL;
- int32_t ret = -1;
int32_t index = 0;
uint64_t size_to_prune = 0;
uint64_t size_pruned = 0;
@@ -149,37 +216,11 @@ ioc_prune (ioc_table_t *table)
/* prune page-by-page for this inode, till
* we reach the equilibrium */
ioc_inode_lock (curr);
- /* { */
-
- list_for_each_entry_safe (page, next,
- &curr->cache.page_lru,
- page_lru) {
- /* done with all pages, and not
- * reached equilibrium yet??
- * continue with next inode in
- * lru_list */
- size_pruned += page->size;
- ret = ioc_page_destroy (page);
-
- if (ret != -1)
- table->cache_used -= ret;
-
- gf_log (table->xl->name, GF_LOG_TRACE,
- "index = %d && table->cache_"
- "used = %"PRIu64" && table->"
- "cache_size = %"PRIu64,
- index, table->cache_used,
- table->cache_size);
-
- if (size_pruned >= size_to_prune)
- break;
- } /* list_for_each_entry_safe(page...) */
-
- if (ioc_empty (&curr->cache)) {
- list_del_init (&curr->inode_lru);
+ {
+ __ioc_inode_prune (curr, &size_pruned,
+ size_to_prune,
+ index);
}
-
- /* } */
ioc_inode_unlock (curr);
if (size_pruned >= size_to_prune)
@@ -198,14 +239,14 @@ out:
}
/*
- * ioc_page_create - create a new page.
+ * __ioc_page_create - create a new page.
*
* @ioc_inode:
* @offset:
*
*/
ioc_page_t *
-ioc_page_create (ioc_inode_t *ioc_inode, off_t offset)
+__ioc_page_create (ioc_inode_t *ioc_inode, off_t offset)
{
ioc_table_t *table = NULL;
ioc_page_t *page = NULL;
@@ -258,8 +299,8 @@ out:
*
*/
void
-ioc_wait_on_page (ioc_page_t *page, call_frame_t *frame, off_t offset,
- size_t size)
+__ioc_wait_on_page (ioc_page_t *page, call_frame_t *frame, off_t offset,
+ size_t size)
{
ioc_waitq_t *waitq = NULL;
ioc_local_t *local = NULL;
@@ -367,7 +408,8 @@ ioc_waitq_return (ioc_waitq_t *waitq)
int
ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iovec *vector,
- int32_t count, struct iatt *stbuf, struct iobref *iobref)
+ int32_t count, struct iatt *stbuf, struct iobref *iobref,
+ dict_t *xdata)
{
ioc_local_t *local = NULL;
off_t offset = 0;
@@ -414,14 +456,14 @@ ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (op_ret < 0) {
/* error, readv returned -1 */
- page = ioc_page_get (ioc_inode, offset);
+ page = __ioc_page_get (ioc_inode, offset);
if (page)
- waitq = ioc_page_error (page, op_ret,
- op_errno);
+ waitq = __ioc_page_error (page, op_ret,
+ op_errno);
} else {
gf_log (ioc_inode->table->xl->name, GF_LOG_TRACE,
"op_ret = %d", op_ret);
- page = ioc_page_get (ioc_inode, offset);
+ page = __ioc_page_get (ioc_inode, offset);
if (!page) {
/* page was flushed */
/* some serious bug ? */
@@ -439,11 +481,12 @@ ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* keep a copy of the page for our cache */
page->vector = iov_dup (vector, count);
if (page->vector == NULL) {
- page = ioc_page_get (ioc_inode, offset);
+ page = __ioc_page_get (ioc_inode,
+ offset);
if (page != NULL)
- waitq = ioc_page_error (page,
- -1,
- ENOMEM);
+ waitq = __ioc_page_error (page,
+ -1,
+ ENOMEM);
goto unlock;
}
@@ -467,6 +510,7 @@ ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
* byte replies */
page_size = iov_length(vector, count);
page->size = page_size;
+ page->op_errno = op_errno;
iobref_page_size = iobref_size (page->iobref);
@@ -474,7 +518,8 @@ ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* wake up all the frames waiting on
* this page, including
* the frame which triggered fault */
- waitq = ioc_page_wakeup (page);
+ waitq = __ioc_page_wakeup (page,
+ op_errno);
} /* if(page->waitq) */
} /* if(!page)...else */
} /* if(op_ret < 0)...else */
@@ -552,8 +597,7 @@ ioc_page_fault (ioc_inode_t *ioc_inode, call_frame_t *frame, fd_t *fd,
goto err;
}
- fault_local = GF_CALLOC (1, sizeof (ioc_local_t),
- gf_ioc_mt_ioc_local_t);
+ fault_local = mem_get0 (THIS->local_pool);
if (fault_local == NULL) {
op_ret = -1;
op_errno = ENOMEM;
@@ -580,23 +624,28 @@ ioc_page_fault (ioc_inode_t *ioc_inode, call_frame_t *frame, fd_t *fd,
STACK_WIND (fault_frame, ioc_fault_cbk, FIRST_CHILD(fault_frame->this),
FIRST_CHILD(fault_frame->this)->fops->readv, fd,
- table->page_size, offset);
+ table->page_size, offset, 0, NULL);
return;
err:
- page = ioc_page_get (ioc_inode, offset);
- if (page != NULL) {
- waitq = ioc_page_error (page, op_ret, op_errno);
- if (waitq != NULL) {
- ioc_waitq_return (waitq);
+ ioc_inode_lock (ioc_inode);
+ {
+ page = __ioc_page_get (ioc_inode, offset);
+ if (page != NULL) {
+ waitq = __ioc_page_error (page, op_ret, op_errno);
}
}
+ ioc_inode_unlock (ioc_inode);
+
+ if (waitq != NULL) {
+ ioc_waitq_return (waitq);
+ }
}
int32_t
-ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
- size_t size)
+__ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
+ size_t size, int32_t op_errno)
{
ioc_local_t *local = NULL;
ioc_fill_t *fill = NULL;
@@ -631,7 +680,13 @@ ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
/* immediately move this page to the end of the page_lru list */
list_move_tail (&page->page_lru, &ioc_inode->cache.page_lru);
/* fill local->pending_size bytes from local->pending_offset */
- if (local->op_ret != -1 && page->size) {
+ if (local->op_ret != -1) {
+ local->op_errno = op_errno;
+
+ if (page->size == 0) {
+ goto done;
+ }
+
if (offset > page->offset)
/* offset is offset in file, convert it to offset in
* page */
@@ -720,9 +775,11 @@ ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
}
}
}
+
local->op_ret += copy_size;
}
+done:
ret = 0;
out:
return ret;
@@ -747,7 +804,7 @@ ioc_frame_unwind (call_frame_t *frame)
int32_t copied = 0;
struct iobref *iobref = NULL;
struct iatt stbuf = {0,};
- int32_t op_ret = 0;
+ int32_t op_ret = 0, op_errno = 0;
GF_ASSERT (frame);
@@ -756,16 +813,21 @@ ioc_frame_unwind (call_frame_t *frame)
gf_log (frame->this->name, GF_LOG_WARNING,
"local is NULL");
op_ret = -1;
- local->op_errno = ENOMEM;
+ op_errno = ENOMEM;
+ goto unwind;
+ }
+
+ if (local->op_ret < 0) {
+ op_ret = local->op_ret;
+ op_errno = local->op_errno;
goto unwind;
}
// ioc_local_lock (local);
- frame->local = NULL;
iobref = iobref_new ();
if (iobref == NULL) {
op_ret = -1;
- local->op_errno = ENOMEM;
+ op_errno = ENOMEM;
}
if (list_empty (&local->fill_list)) {
@@ -782,7 +844,7 @@ ioc_frame_unwind (call_frame_t *frame)
vector = GF_CALLOC (count, sizeof (*vector), gf_ioc_mt_iovec);
if (vector == NULL) {
op_ret = -1;
- local->op_errno = ENOMEM;
+ op_errno = ENOMEM;
}
list_for_each_entry_safe (fill, next, &local->fill_list, list) {
@@ -812,8 +874,9 @@ unwind:
// ioc_local_unlock (local);
- STACK_UNWIND_STRICT (readv, frame, op_ret, local->op_errno, vector,
- count, &stbuf, iobref);
+ frame->local = NULL;
+ STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector,
+ count, &stbuf, iobref, NULL);
if (iobref != NULL) {
iobref_unref (iobref);
@@ -825,7 +888,8 @@ unwind:
}
pthread_mutex_destroy (&local->local_lock);
- GF_FREE (local);
+ if (local)
+ mem_put (local);
return;
}
@@ -867,7 +931,7 @@ ioc_frame_return (call_frame_t *frame)
* to be called only when a frame is waiting on an in-transit page
*/
ioc_waitq_t *
-ioc_page_wakeup (ioc_page_t *page)
+__ioc_page_wakeup (ioc_page_t *page, int32_t op_errno)
{
ioc_waitq_t *waitq = NULL, *trav = NULL;
call_frame_t *frame = NULL;
@@ -885,18 +949,23 @@ ioc_page_wakeup (ioc_page_t *page)
for (trav = waitq; trav; trav = trav->next) {
frame = trav->data;
- ret = ioc_frame_fill (page, frame, trav->pending_offset,
- trav->pending_size);
+ ret = __ioc_frame_fill (page, frame, trav->pending_offset,
+ trav->pending_size, op_errno);
if (ret == -1) {
break;
}
}
+ if (page->stale) {
+ __ioc_page_destroy (page);
+ }
+
out:
return waitq;
}
+
/*
* ioc_page_error -
* @page:
@@ -905,7 +974,7 @@ out:
*
*/
ioc_waitq_t *
-ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno)
+__ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno)
{
ioc_waitq_t *waitq = NULL, *trav = NULL;
call_frame_t *frame = NULL;
@@ -937,7 +1006,7 @@ ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno)
}
table = page->inode->table;
- ret = ioc_page_destroy (page);
+ ret = __ioc_page_destroy (page);
if (ret != -1) {
table->cache_used -= ret;
@@ -946,3 +1015,29 @@ ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno)
out:
return waitq;
}
+
+/*
+ * ioc_page_error -
+ * @page:
+ * @op_ret:
+ * @op_errno:
+ *
+ */
+ioc_waitq_t *
+ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno)
+{
+ ioc_waitq_t *waitq = NULL;
+
+ if (page == NULL) {
+ goto out;
+ }
+
+ ioc_inode_lock (page->inode);
+ {
+ waitq = __ioc_page_error (page, op_ret, op_errno);
+ }
+ ioc_inode_unlock (page->inode);
+
+out:
+ return waitq;
+}