📄 io-cache.c
字号:
/* Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.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 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/#ifndef _CONFIG_H#define _CONFIG_H#include "config.h"#endif#include "glusterfs.h"#include "logging.h"#include "dict.h"#include "xlator.h"#include "io-cache.h"#include <assert.h>#include <sys/time.h>static inline ioc_inode_t *ioc_inode_reupdate (ioc_inode_t *ioc_inode){ ioc_table_t *table = ioc_inode->table; list_add_tail (&ioc_inode->inode_lru, &table->inode_lru[ioc_inode->weight]); return ioc_inode;}static inline ioc_inode_t *ioc_get_inode (dict_t *dict, char *name){ ioc_inode_t *ioc_inode = NULL; data_t *ioc_inode_data = dict_get (dict, name); ioc_table_t *table = NULL; if (ioc_inode_data) { ioc_inode = data_to_ptr (ioc_inode_data); table = ioc_inode->table; ioc_table_lock (table); if (list_empty (&ioc_inode->inode_lru)) { ioc_inode = ioc_inode_reupdate (ioc_inode); } ioc_table_unlock (table); } return ioc_inode;}int32_tioc_inode_need_revalidate (ioc_inode_t *ioc_inode){ int8_t need_revalidate = 0; struct timeval tv = {0,}; int32_t ret = -1; ioc_table_t *table = ioc_inode->table; ret = gettimeofday (&tv, NULL); if (time_elapsed (&tv, &ioc_inode->tv) >= table->force_revalidate_timeout) need_revalidate = 1; return need_revalidate;}/* * __ioc_inode_flush - flush all the cached pages of the given inode * * @ioc_inode: * * assumes lock is held */int32_t__ioc_inode_flush (ioc_inode_t *ioc_inode){ ioc_page_t *curr = NULL, *next = NULL; int32_t destroy_size = 0; int32_t ret = 0; list_for_each_entry_safe (curr, next, &ioc_inode->pages, pages) { ret = ioc_page_destroy (curr); if (ret != -1) destroy_size += ret; } return destroy_size;}voidioc_inode_flush (ioc_inode_t *ioc_inode){ int32_t destroy_size = 0; ioc_inode_lock (ioc_inode); destroy_size = __ioc_inode_flush (ioc_inode); ioc_inode_unlock (ioc_inode); if (destroy_size) { ioc_table_lock (ioc_inode->table); ioc_inode->table->cache_used -= destroy_size; ioc_table_unlock (ioc_inode->table); } return;}/* * ioc_utimens_cbk - * * @frame: * @cookie: * @this: * @op_ret: * @op_errno: * @stbuf: * */int32_tioc_utimens_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct stat *stbuf){ STACK_UNWIND (frame, op_ret, op_errno, stbuf); return 0;}/* * ioc_utimens - * * @frame: * @this: * @loc: * @tv: * */int32_tioc_utimens (call_frame_t *frame, xlator_t *this, loc_t *loc, struct timespec *tv){ ioc_inode_t *ioc_inode = ioc_get_inode (loc->inode->ctx, this->name); if (ioc_inode) ioc_inode_flush (ioc_inode); STACK_WIND (frame, ioc_utimens_cbk, FIRST_CHILD (this), FIRST_CHILD (this)->fops->utimens, loc, tv); return 0;}int32_tioc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct stat *stbuf, dict_t *dict){ ioc_inode_t *ioc_inode = NULL; uint8_t cache_still_valid = 0; if (op_ret == 0) ioc_inode = ioc_get_inode (inode->ctx, this->name); if (ioc_inode) { cache_still_valid = ioc_cache_still_valid (ioc_inode, stbuf); if (!cache_still_valid) { ioc_inode_flush (ioc_inode); } /* update the time-stamp of revalidation */ gettimeofday (&ioc_inode->tv, NULL); } STACK_UNWIND (frame, op_ret, op_errno, inode, stbuf, dict); return 0;}int32_t ioc_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t need_xattr){ STACK_WIND (frame, ioc_lookup_cbk, FIRST_CHILD (this), FIRST_CHILD (this)->fops->lookup, loc, need_xattr); return 0;}/* * ioc_forget - * * @frame: * @this: * @inode: * */int32_tioc_forget (call_frame_t *frame, xlator_t *this, inode_t *inode){ ioc_inode_t *ioc_inode = NULL; ioc_inode = ioc_get_inode (inode->ctx, this->name); if (ioc_inode) ioc_inode_destroy (ioc_inode); return 0;}/* * ioc_cache_validate_cbk - * * @frame: * @cookie: * @this: * @op_ret: * @op_errno: * @buf * */int32_tioc_cache_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct stat *stbuf){ ioc_local_t *local = frame->local; ioc_inode_t *ioc_inode = NULL; size_t destroy_size = 0; ioc_inode = local->inode; if (op_ret == -1 || (op_ret >= 0 && !ioc_cache_still_valid(ioc_inode, stbuf))) { gf_log (ioc_inode->table->xl->name, GF_LOG_DEBUG, "cache for inode(%p) is invalid. flushing all pages", ioc_inode); ioc_inode_lock (ioc_inode); destroy_size = __ioc_inode_flush (ioc_inode); if (op_ret >= 0) ioc_inode->mtime = stbuf->st_mtime; ioc_inode_unlock (ioc_inode); } if (destroy_size) { ioc_table_lock (ioc_inode->table); ioc_inode->table->cache_used -= destroy_size; ioc_table_unlock (ioc_inode->table); } if (op_ret < 0) stbuf = NULL; ioc_inode_lock (ioc_inode); gettimeofday (&ioc_inode->tv, NULL); ioc_inode_unlock (ioc_inode); ioc_inode_wakeup (frame, ioc_inode, stbuf); STACK_DESTROY (frame->root); return 0;}/* * ioc_cache_validate - * * @frame: * @ioc_inode: * @fd: * */static int32_tioc_cache_validate (call_frame_t *frame, ioc_inode_t *ioc_inode, fd_t *fd, ioc_page_t *page){ char need_validate = 0; ioc_waitq_t *waiter = calloc (1, sizeof (ioc_waitq_t)); call_frame_t *validate_frame = NULL; ioc_inode_lock (ioc_inode); if (!ioc_inode->waitq) { need_validate = 1; } waiter->data = page; waiter->next = ioc_inode->waitq; ioc_inode->waitq = waiter; ioc_inode_unlock (ioc_inode); if (need_validate) { ioc_local_t *validate_local = calloc (1, sizeof (ioc_local_t)); validate_frame = copy_frame (frame); validate_local->fd = fd; validate_local->inode = ioc_inode; validate_frame->local = validate_local; STACK_WIND (validate_frame, ioc_cache_validate_cbk, FIRST_CHILD (frame->this), FIRST_CHILD (frame->this)->fops->fstat, fd); } return 0;}static inline uint32_tis_match (const char *path, const char *pattern){ char *pathname = strdup (path); int32_t ret = 0; ret = fnmatch (pattern, path, FNM_NOESCAPE); free (pathname); return (ret == 0);}static uint32_tioc_get_priority (ioc_table_t *table, const char *path){ uint32_t priority = 0; struct ioc_priority *curr = NULL; list_for_each_entry (curr, &table->priority_list, list) { if (is_match (path, curr->pattern)) priority = curr->priority; } return priority;}/* * ioc_open_cbk - open callback for io cache * * @frame: call frame * @cookie: * @this: * @op_ret: * @op_errno: * @fd: * */int32_tioc_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd){ ioc_local_t *local = frame->local; ioc_table_t *table = this->private; ioc_inode_t *ioc_inode = NULL; inode_t *inode = local->file_loc.inode; uint32_t weight = 0; const char *path = local->file_loc.path; if (op_ret != -1) { /* look for ioc_inode corresponding to this fd */ LOCK (&fd->inode->lock); ioc_inode = ioc_get_inode (fd->inode->ctx, this->name); if (!ioc_inode) { /* this is the first time someone is opening this file */ /* assign weight */ weight = ioc_get_priority (table, path); ioc_inode = ioc_inode_update (table, inode, weight); dict_set (fd->inode->ctx, this->name, data_from_static_ptr (ioc_inode)); } else { ioc_table_lock (ioc_inode->table); list_move_tail (&ioc_inode->inode_lru, &table->inode_lru[ioc_inode->weight]); ioc_table_unlock (ioc_inode->table); } UNLOCK (&fd->inode->lock); /* If mandatory locking has been enabled on this file, we disable caching on it */ if (((inode->st_mode & S_ISGID) && !(inode->st_mode & S_IXGRP))) { dict_set (fd->ctx, this->name, data_from_uint32 (1)); } /* If O_DIRECT open, we disable caching on it */ if ((local->flags & O_DIRECT)){ /* O_DIRECT is only for one fd, not the inode as a whole */ dict_set (fd->ctx, this->name, data_from_uint32 (1)); } } freee (local); frame->local = NULL; STACK_UNWIND (frame, op_ret, op_errno, fd); return 0;}/* * ioc_create_cbk - create callback for io cache * * @frame: call frame * @cookie: * @this: * @op_ret: * @op_errno: * @fd: * @inode: * @buf: * */int32_tioc_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode, struct stat *buf){ ioc_local_t *local = frame->local; ioc_table_t *table = this->private; ioc_inode_t *ioc_inode = NULL; uint32_t weight = 0; const char *path = local->file_loc.path; if (op_ret != -1) { { /* assign weight */ weight = ioc_get_priority (table, path); ioc_inode = ioc_inode_update (table, inode, weight); LOCK (&fd->inode->lock); dict_set (fd->inode->ctx, this->name, data_from_static_ptr (ioc_inode)); UNLOCK (&fd->inode->lock); } /* If mandatory locking has been enabled on this file, we disable caching on it */ if ((inode->st_mode & S_ISGID) && !(inode->st_mode & S_IXGRP)) { dict_set (fd->ctx, this->name, data_from_uint32 (1)); } /* If O_DIRECT open, we disable caching on it */ if (local->flags & O_DIRECT){ /* O_DIRECT is only for one fd, not the inode as a whole */ dict_set (fd->ctx, this->name, data_from_uint32 (1)); } } frame->local = NULL; freee (local); STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf); return 0;}/* * ioc_open - open fop for io cache * @frame: * @this: * @loc: * @flags: * */int32_tioc_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, fd_t *fd){ ioc_local_t *local = calloc (1, sizeof (ioc_local_t)); local->flags = flags; local->file_loc.path = loc->path; local->file_loc.inode = loc->inode; frame->local = local; STACK_WIND (frame, ioc_open_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->open, loc, flags, fd); return 0;}/* * ioc_create - create fop for io cache * * @frame: * @this: * @pathname: * @flags: * @mode: * */int32_tioc_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, fd_t *fd){ ioc_local_t *local = calloc (1, sizeof (ioc_local_t)); local->flags = flags; local->file_loc.path = loc->path; frame->local = local; STACK_WIND (frame, ioc_create_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, loc, flags, mode, fd); return 0;}/* * ioc_close_cbk - close callback * * @frame: * @cookie: * @this: * @op_ret: * @op_errno: * */int32_tioc_close_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno){ STACK_UNWIND (frame, op_ret, op_errno); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -