summaryrefslogtreecommitdiffstats
path: root/xlators/performance/io-cache/src/io-cache.h
blob: b1e061eeef317c4113c9c43181b6865e31b89855 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
  Copyright (c) 2007-2009 Gluster, Inc. <http://www.gluster.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 __IO_CACHE_H
#define __IO_CACHE_H

#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif

#include <sys/types.h>
#include "compat-errno.h"

#include "glusterfs.h"
#include "logging.h"
#include "dict.h"
#include "xlator.h"
#include "common-utils.h"
#include "call-stub.h"
#include "rbthash.h"
#include "hashfn.h"
#include <sys/time.h>
#include <fnmatch.h>

#define IOC_PAGE_SIZE    (1024 * 128)   /* 128KB */
#define IOC_CACHE_SIZE   (32 * 1024 * 1024)
#define IOC_PAGE_TABLE_BUCKET_COUNT 1

struct ioc_table;
struct ioc_local;
struct ioc_page;
struct ioc_inode;

struct ioc_priority {
	struct list_head list;
	char             *pattern;
	uint32_t         priority;
};

/*
 * ioc_waitq - this structure is used to represents the waiting 
 *             frames on a page
 *
 * @next: pointer to next object in waitq
 * @data: pointer to the frame which is waiting
 */
struct ioc_waitq {
	struct ioc_waitq *next;
	void             *data;
	off_t            pending_offset;
	size_t           pending_size;
};

/*
 * ioc_fill - 
 *
 */
struct ioc_fill {
	struct list_head list;  /* list of ioc_fill structures of a frame */
	off_t            offset;          
	size_t           size;           
	struct iovec     *vector;  
	int32_t          count;
	struct iobref    *iobref;
};

struct ioc_local {
	mode_t           mode;
	int32_t          flags;
	loc_t            file_loc;
	off_t            offset;
	size_t           size;
	int32_t          op_ret;
	int32_t          op_errno;
	struct list_head fill_list;      /* list of ioc_fill structures */
	off_t            pending_offset; /* 
                                          * offset from this frame should
                                          * continue
                                          */
	size_t           pending_size;   /* 
                                          * size of data this frame is waiting
                                          * on
                                          */
	struct ioc_inode *inode;
	int32_t          wait_count;
	pthread_mutex_t  local_lock;
	struct ioc_waitq *waitq;
	void             *stub;
	fd_t             *fd;
	int32_t          need_xattr;
	dict_t           *xattr_req;
};

/*
 * ioc_page - structure to store page of data from file 
 *
 */
struct ioc_page {
	struct list_head    page_lru;
	struct ioc_inode    *inode;   /* inode this page belongs to */
	struct ioc_priority *priority;
	char                dirty;
	char                ready;
	struct iovec        *vector;
	int32_t             count;
	off_t               offset;
	size_t              size;
	struct ioc_waitq    *waitq;
	struct iobref       *iobref;
	pthread_mutex_t     page_lock;
};

struct ioc_cache {
        rbthash_table_t  *page_table;
        struct list_head  page_lru;
	time_t            mtime;       /*
                                        * mtime of the server file when last
                                        * cached
                                        */
	struct timeval    tv;          /*
                                        * time-stamp at last re-validate
                                        */
};

struct ioc_inode {
	struct ioc_table      *table;
        off_t                  st_size;
        struct ioc_cache       cache;        
	struct list_head       inode_list; /*
                                            * list of inodes, maintained by
                                            * io-cache translator
                                            */
	struct list_head       inode_lru;
	struct ioc_waitq      *waitq;
	pthread_mutex_t        inode_lock;
	uint32_t               weight;      /*
                                             * weight of the inode, increases
                                             * on each read
                                             */
};

struct ioc_table {
	uint64_t         page_size;
	uint64_t         cache_size;
	uint64_t         cache_used;
        int64_t          min_file_size;
        int64_t          max_file_size;
	struct list_head inodes; /* list of inodes cached */
	struct list_head active; 
	struct list_head *inode_lru;
	struct list_head priority_list;
	int32_t          readv_count;
	pthread_mutex_t  table_lock;
	xlator_t         *xl;
	uint32_t         inode_count;
	int32_t          cache_timeout;
	int32_t          max_pri;
        struct mem_pool  *mem_pool;
};

typedef struct ioc_table ioc_table_t;
typedef struct ioc_local ioc_local_t;
typedef struct ioc_page ioc_page_t;
typedef struct ioc_inode ioc_inode_t;
typedef struct ioc_waitq ioc_waitq_t;
typedef struct ioc_fill ioc_fill_t;

void *
str_to_ptr (char *string);

char *
ptr_to_str (void *ptr);

int32_t 
ioc_readv_disabled_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 stat *stbuf,
                        struct iobref *iobref);

ioc_page_t *
ioc_page_get (ioc_inode_t *ioc_inode, off_t offset);

ioc_page_t *
ioc_page_create (ioc_inode_t *ioc_inode, off_t offset);

void
ioc_page_fault (ioc_inode_t *ioc_inode,	call_frame_t *frame, fd_t *fd,
		off_t offset);
void
ioc_wait_on_page (ioc_page_t *page, call_frame_t *frame, off_t offset,
		  size_t size);

ioc_waitq_t *
ioc_page_wakeup (ioc_page_t *page);

void
ioc_page_flush (ioc_page_t *page);

ioc_waitq_t *
ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno);

void
ioc_page_purge (ioc_page_t *page);

void
ioc_frame_return (call_frame_t *frame);

void
ioc_waitq_return (ioc_waitq_t *waitq);

int32_t
ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
		size_t size);

#define ioc_inode_lock(ioc_inode)					\
	do {								\
		gf_log (ioc_inode->table->xl->name, GF_LOG_TRACE,	\
			"locked inode(%p)", ioc_inode);			\
		pthread_mutex_lock (&ioc_inode->inode_lock);		\
	} while (0)


#define ioc_inode_unlock(ioc_inode)					\
	do {								\
		gf_log (ioc_inode->table->xl->name, GF_LOG_TRACE,	\
			"unlocked inode(%p)", ioc_inode);		\
		pthread_mutex_unlock (&ioc_inode->inode_lock);		\
	} while (0)


#define ioc_table_lock(table)					\
	do {							\
		gf_log (table->xl->name, GF_LOG_TRACE,		\
			"locked table(%p)", table);		\
		pthread_mutex_lock (&table->table_lock);	\
	} while (0)


#define ioc_table_unlock(table)					\
	do {							\
		gf_log (table->xl->name, GF_LOG_TRACE,		\
			"unlocked table(%p)", table);		\
		pthread_mutex_unlock (&table->table_lock);	\
	} while (0)


#define ioc_local_lock(local)						\
	do {								\
		gf_log (local->inode->table->xl->name, GF_LOG_TRACE,	\
			"locked local(%p)", local);			\
		pthread_mutex_lock (&local->local_lock);		\
	} while (0)


#define ioc_local_unlock(local)						\
	do {								\
		gf_log (local->inode->table->xl->name, GF_LOG_TRACE,	\
			"unlocked local(%p)", local);			\
		pthread_mutex_unlock (&local->local_lock);		\
	} while (0)


#define ioc_page_lock(page)						\
	do {								\
		gf_log (page->inode->table->xl->name, GF_LOG_TRACE,	\
			"locked page(%p)", page);			\
		pthread_mutex_lock (&page->page_lock);			\
	} while (0)


#define ioc_page_unlock(page)						\
	do {								\
		gf_log (page->inode->table->xl->name, GF_LOG_TRACE,	\
			"unlocked page(%p)", page);			\
		pthread_mutex_unlock (&page->page_lock);		\
	} while (0)


static inline uint64_t
time_elapsed (struct timeval *now,
	      struct timeval *then)
{
	uint64_t sec = now->tv_sec - then->tv_sec;

	if (sec)
		return sec;
  
	return 0;
}

ioc_inode_t *
ioc_inode_search (ioc_table_t *table, inode_t *inode);

void 
ioc_inode_destroy (ioc_inode_t *ioc_inode);

ioc_inode_t *
ioc_inode_update (ioc_table_t *table, inode_t *inode, uint32_t weight);

int64_t 
ioc_page_destroy (ioc_page_t *page);

int64_t
__ioc_inode_flush (ioc_inode_t *ioc_inode);

void
ioc_inode_flush (ioc_inode_t *ioc_inode);

void
ioc_inode_wakeup (call_frame_t *frame, ioc_inode_t *ioc_inode,
                  struct stat *stbuf);

int8_t
ioc_cache_still_valid (ioc_inode_t *ioc_inode, struct stat *stbuf);

int32_t
ioc_prune (ioc_table_t *table);

int32_t
ioc_need_prune (ioc_table_t *table);

inline uint32_t
ioc_hashfn (void *data, int len);
#endif /* __IO_CACHE_H */