diff options
Diffstat (limited to 'xlators/performance/io-cache/src/page.c')
| -rw-r--r-- | xlators/performance/io-cache/src/page.c | 269 |
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; +} |
