glusterfs
227 строк · 5.8 Кб
1/*
2Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include "io-cache.h"12#include "ioc-mem-types.h"13
14extern int ioc_log2_page_size;15
16/*
17* str_to_ptr - convert a string to pointer
18* @string: string
19*
20*/
21void *22str_to_ptr(char *string)23{
24void *ptr = NULL;25
26GF_VALIDATE_OR_GOTO("io-cache", string, out);27
28ptr = (void *)strtoul(string, NULL, 16);29
30out:31return ptr;32}
33
34/*
35* ptr_to_str - convert a pointer to string
36* @ptr: pointer
37*
38*/
39char *40ptr_to_str(void *ptr)41{
42int ret = 0;43char *str = NULL;44
45GF_VALIDATE_OR_GOTO("io-cache", ptr, out);46
47ret = gf_asprintf(&str, "%p", ptr);48if (-1 == ret) {49gf_smsg("io-cache", GF_LOG_WARNING, 0,50IO_CACHE_MSG_STR_COVERSION_FAILED, NULL);51str = NULL;52goto out;53}54
55out:56return str;57}
58
59void
60ioc_inode_wakeup(call_frame_t *frame, ioc_inode_t *ioc_inode,61struct iatt *stbuf)62{
63ioc_waitq_t *waiter = NULL, *waited = NULL;64ioc_waitq_t *page_waitq = NULL;65int8_t cache_still_valid = 1;66ioc_local_t *local = NULL;67int8_t need_fault = 0;68ioc_page_t *waiter_page = NULL;69
70GF_VALIDATE_OR_GOTO("io-cache", frame, out);71
72local = frame->local;73GF_VALIDATE_OR_GOTO(frame->this->name, local, out);74
75if (ioc_inode == NULL) {76local->op_ret = -1;77local->op_errno = EINVAL;78gf_smsg(frame->this->name, GF_LOG_WARNING, 0, IO_CACHE_MSG_INODE_NULL,79NULL);80goto out;81}82
83if (stbuf)84cache_still_valid = ioc_cache_still_valid(ioc_inode, stbuf);85else86cache_still_valid = 0;87
88ioc_inode_lock(ioc_inode);89{90waiter = ioc_inode->waitq;91if (!waiter) {92gf_smsg(frame->this->name, GF_LOG_WARNING, 0,93IO_CACHE_MSG_PAGE_WAIT_VALIDATE, NULL);94
95ioc_inode_unlock(ioc_inode);96goto out;97}98
99while (waiter) {100waiter_page = waiter->data;101ioc_inode->waitq = waiter->next;102page_waitq = NULL;103
104if (waiter_page) {105if (cache_still_valid) {106/* cache valid, wake up page */107page_waitq = __ioc_page_wakeup(waiter_page,108waiter_page->op_errno);109if (page_waitq) {110ioc_inode_unlock(ioc_inode);111ioc_waitq_return(page_waitq);112ioc_inode_lock(ioc_inode);113}114} else {115/* cache invalid, generate page fault and set116* page->ready = 0, to avoid double faults
117*/
118if (waiter_page->ready) {119waiter_page->ready = 0;120need_fault = 1;121} else {122gf_msg_trace(frame->this->name, 0,123"validate "124"frame(%p) is "125"waiting for "126"in-transit"127" page = %p",128frame, waiter_page);129}130
131if (need_fault) {132need_fault = 0;133ioc_inode_unlock(ioc_inode);134ioc_page_fault(ioc_inode, frame, local->fd,135waiter_page->offset);136ioc_inode_lock(ioc_inode);137}138}139}140
141waited = waiter;142waiter = ioc_inode->waitq;143
144waited->data = NULL;145GF_FREE(waited);146}147}148ioc_inode_unlock(ioc_inode);149
150out:151return;152}
153
154/*
155* ioc_inode_create - create a new ioc_inode_t structure and add it to
156* the table table. fill in the fields which are derived
157* from inode_t corresponding to the file
158*
159* @table: io-table structure
160* @inode: inode structure
161*
162* not for external reference
163*/
164ioc_inode_t *165ioc_inode_create(ioc_table_t *table, inode_t *inode, uint32_t weight)166{
167ioc_inode_t *ioc_inode = NULL;168
169GF_VALIDATE_OR_GOTO("io-cache", table, out);170
171ioc_inode = GF_CALLOC(1, sizeof(ioc_inode_t), gf_ioc_mt_ioc_inode_t);172if (ioc_inode == NULL) {173goto out;174}175
176ioc_inode->inode = inode;177ioc_inode->table = table;178INIT_LIST_HEAD(&ioc_inode->cache.page_lru);179pthread_mutex_init(&ioc_inode->inode_lock, NULL);180ioc_inode->weight = weight;181
182ioc_table_lock(table);183{184table->inode_count++;185list_add(&ioc_inode->inode_list, &table->inodes);186list_add_tail(&ioc_inode->inode_lru, &table->inode_lru[weight]);187}188ioc_table_unlock(table);189
190gf_msg_trace(table->xl->name, 0, "adding to inode_lru[%d]", weight);191
192out:193return ioc_inode;194}
195
196/*
197* ioc_inode_destroy - destroy an ioc_inode_t object.
198*
199* @inode: inode to destroy
200*
201* to be called only from ioc_forget.
202*/
203void
204ioc_inode_destroy(ioc_inode_t *ioc_inode)205{
206ioc_table_t *table = NULL;207
208GF_VALIDATE_OR_GOTO("io-cache", ioc_inode, out);209
210table = ioc_inode->table;211
212ioc_table_lock(table);213{214table->inode_count--;215list_del(&ioc_inode->inode_list);216list_del(&ioc_inode->inode_lru);217}218ioc_table_unlock(table);219
220ioc_inode_flush(ioc_inode);221rbthash_table_destroy(ioc_inode->cache.page_table);222
223pthread_mutex_destroy(&ioc_inode->inode_lock);224GF_FREE(ioc_inode);225out:226return;227}
228