File: | xlators/performance/io-cache/src/page.c |
Location: | line 427, column 17 |
Description: | Access to field 'local' results in a dereference of a null pointer (loaded from variable 'frame') |
1 | /* | |||||
2 | Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> | |||||
3 | This file is part of GlusterFS. | |||||
4 | ||||||
5 | This file is licensed to you under your choice of the GNU Lesser | |||||
6 | General Public License, version 3 or any later version (LGPLv3 or | |||||
7 | later), or the GNU General Public License, version 2 (GPLv2), in all | |||||
8 | cases as published by the Free Software Foundation. | |||||
9 | */ | |||||
10 | ||||||
11 | #ifndef _CONFIG_H | |||||
12 | #define _CONFIG_H | |||||
13 | #include "config.h" | |||||
14 | #endif | |||||
15 | ||||||
16 | #include "glusterfs.h" | |||||
17 | #include "logging.h" | |||||
18 | #include "dict.h" | |||||
19 | #include "xlator.h" | |||||
20 | #include "io-cache.h" | |||||
21 | #include "ioc-mem-types.h" | |||||
22 | #include <assert.h> | |||||
23 | #include <sys/time.h> | |||||
24 | ||||||
25 | char | |||||
26 | ioc_empty (struct ioc_cache *cache) | |||||
27 | { | |||||
28 | char is_empty = -1; | |||||
29 | ||||||
30 | GF_VALIDATE_OR_GOTO ("io-cache", cache, out)do { if (!cache) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "cache"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 30, GF_LOG_ERROR, "invalid argument: " "cache"); } while (0); goto out; } } while (0); | |||||
31 | ||||||
32 | is_empty = list_empty (&cache->page_lru); | |||||
33 | ||||||
34 | out: | |||||
35 | return is_empty; | |||||
36 | } | |||||
37 | ||||||
38 | ||||||
39 | ioc_page_t * | |||||
40 | __ioc_page_get (ioc_inode_t *ioc_inode, off_t offset) | |||||
41 | { | |||||
42 | ioc_page_t *page = NULL((void*)0); | |||||
43 | ioc_table_t *table = NULL((void*)0); | |||||
44 | off_t rounded_offset = 0; | |||||
45 | ||||||
46 | GF_VALIDATE_OR_GOTO ("io-cache", ioc_inode, out)do { if (!ioc_inode) { (*__errno_location ()) = 22; do { do { if (0) printf ("invalid argument: " "ioc_inode"); } while (0 ); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 46, GF_LOG_ERROR, "invalid argument: " "ioc_inode"); } while (0) ; goto out; } } while (0); | |||||
47 | ||||||
48 | table = ioc_inode->table; | |||||
49 | GF_VALIDATE_OR_GOTO ("io-cache", ioc_inode, out)do { if (!ioc_inode) { (*__errno_location ()) = 22; do { do { if (0) printf ("invalid argument: " "ioc_inode"); } while (0 ); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 49, GF_LOG_ERROR, "invalid argument: " "ioc_inode"); } while (0) ; goto out; } } while (0); | |||||
50 | ||||||
51 | rounded_offset = floor (offset, table->page_size)(((offset)/((table->page_size)?(table->page_size):1))*( table->page_size)); | |||||
52 | ||||||
53 | page = rbthash_get (ioc_inode->cache.page_table, &rounded_offset, | |||||
54 | sizeof (rounded_offset)); | |||||
55 | ||||||
56 | if (page != NULL((void*)0)) { | |||||
57 | /* push the page to the end of the lru list */ | |||||
58 | list_move_tail (&page->page_lru, &ioc_inode->cache.page_lru); | |||||
59 | } | |||||
60 | ||||||
61 | out: | |||||
62 | return page; | |||||
63 | } | |||||
64 | ||||||
65 | ||||||
66 | ioc_page_t * | |||||
67 | ioc_page_get (ioc_inode_t *ioc_inode, off_t offset) | |||||
68 | { | |||||
69 | ioc_page_t *page = NULL((void*)0); | |||||
70 | ||||||
71 | if (ioc_inode == NULL((void*)0)) { | |||||
72 | goto out; | |||||
73 | } | |||||
74 | ||||||
75 | ioc_inode_lock (ioc_inode)do { do { do { if (0) printf ("locked inode(%p)", ioc_inode); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c" , __FUNCTION__, 75, GF_LOG_TRACE, "locked inode(%p)", ioc_inode ); } while (0); pthread_mutex_lock (&ioc_inode->inode_lock ); } while (0); | |||||
76 | { | |||||
77 | page = __ioc_page_get (ioc_inode, offset); | |||||
78 | } | |||||
79 | ioc_inode_unlock (ioc_inode)do { do { do { if (0) printf ("unlocked inode(%p)", ioc_inode ); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c", __FUNCTION__, 79, GF_LOG_TRACE, "unlocked inode(%p)" , ioc_inode); } while (0); pthread_mutex_unlock (&ioc_inode ->inode_lock); } while (0); | |||||
80 | ||||||
81 | out: | |||||
82 | return page; | |||||
83 | } | |||||
84 | ||||||
85 | ||||||
86 | /* | |||||
87 | * __ioc_page_destroy - | |||||
88 | * | |||||
89 | * @page: | |||||
90 | * | |||||
91 | */ | |||||
92 | int64_t | |||||
93 | __ioc_page_destroy (ioc_page_t *page) | |||||
94 | { | |||||
95 | int64_t page_size = 0; | |||||
96 | ||||||
97 | GF_VALIDATE_OR_GOTO ("io-cache", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 97, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
98 | ||||||
99 | if (page->iobref) | |||||
100 | page_size = iobref_size (page->iobref); | |||||
101 | ||||||
102 | if (page->waitq) { | |||||
103 | /* frames waiting on this page, do not destroy this page */ | |||||
104 | page_size = -1; | |||||
105 | page->stale = 1; | |||||
106 | } else { | |||||
107 | rbthash_remove (page->inode->cache.page_table, &page->offset, | |||||
108 | sizeof (page->offset)); | |||||
109 | list_del (&page->page_lru); | |||||
110 | ||||||
111 | gf_log (page->inode->table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("destroying page = %p, offset = %""ll" "d"" " "&& inode = %p", page, page->offset, page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 114, GF_LOG_TRACE, "destroying page = %p, offset = %" "ll" "d"" " "&& inode = %p", page, page->offset, page ->inode); } while (0) | |||||
112 | "destroying page = %p, offset = %"PRId64" "do { do { if (0) printf ("destroying page = %p, offset = %""ll" "d"" " "&& inode = %p", page, page->offset, page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 114, GF_LOG_TRACE, "destroying page = %p, offset = %" "ll" "d"" " "&& inode = %p", page, page->offset, page ->inode); } while (0) | |||||
113 | "&& inode = %p",do { do { if (0) printf ("destroying page = %p, offset = %""ll" "d"" " "&& inode = %p", page, page->offset, page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 114, GF_LOG_TRACE, "destroying page = %p, offset = %" "ll" "d"" " "&& inode = %p", page, page->offset, page ->inode); } while (0) | |||||
114 | page, page->offset, page->inode)do { do { if (0) printf ("destroying page = %p, offset = %""ll" "d"" " "&& inode = %p", page, page->offset, page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 114, GF_LOG_TRACE, "destroying page = %p, offset = %" "ll" "d"" " "&& inode = %p", page, page->offset, page ->inode); } while (0); | |||||
115 | ||||||
116 | if (page->vector){ | |||||
117 | iobref_unref (page->iobref); | |||||
118 | GF_FREE (page->vector)__gf_free (page->vector); | |||||
119 | page->vector = NULL((void*)0); | |||||
120 | } | |||||
121 | ||||||
122 | page->inode = NULL((void*)0); | |||||
123 | } | |||||
124 | ||||||
125 | if (page_size != -1) { | |||||
126 | pthread_mutex_destroy (&page->page_lock); | |||||
127 | GF_FREE (page)__gf_free (page); | |||||
128 | } | |||||
129 | ||||||
130 | out: | |||||
131 | return page_size; | |||||
132 | } | |||||
133 | ||||||
134 | ||||||
135 | int64_t | |||||
136 | ioc_page_destroy (ioc_page_t *page) | |||||
137 | { | |||||
138 | int64_t ret = 0; | |||||
139 | ||||||
140 | if (page == NULL((void*)0)) { | |||||
141 | goto out; | |||||
142 | } | |||||
143 | ||||||
144 | ioc_inode_lock (page->inode)do { do { do { if (0) printf ("locked inode(%p)", page->inode ); } while (0); _gf_log (page->inode->table->xl-> name, "page.c", __FUNCTION__, 144, GF_LOG_TRACE, "locked inode(%p)" , page->inode); } while (0); pthread_mutex_lock (&page ->inode->inode_lock); } while (0); | |||||
145 | { | |||||
146 | ret = __ioc_page_destroy (page); | |||||
147 | } | |||||
148 | ioc_inode_unlock (page->inode)do { do { do { if (0) printf ("unlocked inode(%p)", page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 148, GF_LOG_TRACE, "unlocked inode(%p)" , page->inode); } while (0); pthread_mutex_unlock (&page ->inode->inode_lock); } while (0); | |||||
149 | ||||||
150 | out: | |||||
151 | return ret; | |||||
152 | } | |||||
153 | ||||||
154 | int32_t | |||||
155 | __ioc_inode_prune (ioc_inode_t *curr, uint64_t *size_pruned, | |||||
156 | uint64_t size_to_prune, uint32_t index) | |||||
157 | { | |||||
158 | ioc_page_t *page = NULL((void*)0), *next = NULL((void*)0); | |||||
159 | int32_t ret = 0; | |||||
160 | ioc_table_t *table = NULL((void*)0); | |||||
161 | ||||||
162 | if (curr == NULL((void*)0)) { | |||||
163 | goto out; | |||||
164 | } | |||||
165 | ||||||
166 | table = curr->table; | |||||
167 | ||||||
168 | list_for_each_entry_safe (page, next, &curr->cache.page_lru, page_lru)for (page = ((typeof(*page) *)((char *)((&curr->cache. page_lru)->next)-(unsigned long)(&((typeof(*page) *)0) ->page_lru))), next = ((typeof(*page) *)((char *)(page-> page_lru.next)-(unsigned long)(&((typeof(*page) *)0)-> page_lru))); &page->page_lru != (&curr->cache.page_lru ); page = next, next = ((typeof(*next) *)((char *)(next->page_lru .next)-(unsigned long)(&((typeof(*next) *)0)->page_lru )))) { | |||||
169 | *size_pruned += page->size; | |||||
170 | ret = __ioc_page_destroy (page); | |||||
171 | ||||||
172 | if (ret != -1) | |||||
173 | table->cache_used -= ret; | |||||
174 | ||||||
175 | gf_log (table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("index = %d && table->cache_used = %" "ll" "u"" && table->" "cache_size = %""ll" "u", index , table->cache_used, table->cache_size); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 178, GF_LOG_TRACE , "index = %d && table->cache_used = %""ll" "u"" && table->" "cache_size = %""ll" "u", index, table->cache_used, table ->cache_size); } while (0) | |||||
176 | "index = %d && table->cache_used = %"PRIu64" && table->"do { do { if (0) printf ("index = %d && table->cache_used = %" "ll" "u"" && table->" "cache_size = %""ll" "u", index , table->cache_used, table->cache_size); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 178, GF_LOG_TRACE , "index = %d && table->cache_used = %""ll" "u"" && table->" "cache_size = %""ll" "u", index, table->cache_used, table ->cache_size); } while (0) | |||||
177 | "cache_size = %"PRIu64, index, table->cache_used,do { do { if (0) printf ("index = %d && table->cache_used = %" "ll" "u"" && table->" "cache_size = %""ll" "u", index , table->cache_used, table->cache_size); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 178, GF_LOG_TRACE , "index = %d && table->cache_used = %""ll" "u"" && table->" "cache_size = %""ll" "u", index, table->cache_used, table ->cache_size); } while (0) | |||||
178 | table->cache_size)do { do { if (0) printf ("index = %d && table->cache_used = %" "ll" "u"" && table->" "cache_size = %""ll" "u", index , table->cache_used, table->cache_size); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 178, GF_LOG_TRACE , "index = %d && table->cache_used = %""ll" "u"" && table->" "cache_size = %""ll" "u", index, table->cache_used, table ->cache_size); } while (0); | |||||
179 | ||||||
180 | if ((*size_pruned) >= size_to_prune) | |||||
181 | break; | |||||
182 | } | |||||
183 | ||||||
184 | if (ioc_empty (&curr->cache)) { | |||||
185 | list_del_init (&curr->inode_lru); | |||||
186 | } | |||||
187 | ||||||
188 | out: | |||||
189 | return 0; | |||||
190 | } | |||||
191 | /* | |||||
192 | * ioc_prune - prune the cache. we have a limit to the number of pages we | |||||
193 | * can have in-memory. | |||||
194 | * | |||||
195 | * @table: ioc_table_t of this translator | |||||
196 | * | |||||
197 | */ | |||||
198 | int32_t | |||||
199 | ioc_prune (ioc_table_t *table) | |||||
200 | { | |||||
201 | ioc_inode_t *curr = NULL((void*)0), *next_ioc_inode = NULL((void*)0); | |||||
202 | int32_t index = 0; | |||||
203 | uint64_t size_to_prune = 0; | |||||
204 | uint64_t size_pruned = 0; | |||||
205 | ||||||
206 | GF_VALIDATE_OR_GOTO ("io-cache", table, out)do { if (!table) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "table"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 206, GF_LOG_ERROR, "invalid argument: " "table"); } while (0); goto out; } } while (0); | |||||
207 | ||||||
208 | ioc_table_lock (table)do { do { do { if (0) printf ("locked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 208, GF_LOG_TRACE, "locked table(%p)", table); } while (0); pthread_mutex_lock (&table->table_lock); } while (0); | |||||
209 | { | |||||
210 | size_to_prune = table->cache_used - table->cache_size; | |||||
211 | /* take out the least recently used inode */ | |||||
212 | for (index=0; index < table->max_pri; index++) { | |||||
213 | list_for_each_entry_safe (curr, next_ioc_inode,for (curr = ((typeof(*curr) *)((char *)((&table->inode_lru [index])->next)-(unsigned long)(&((typeof(*curr) *)0)-> inode_lru))), next_ioc_inode = ((typeof(*curr) *)((char *)(curr ->inode_lru.next)-(unsigned long)(&((typeof(*curr) *)0 )->inode_lru))); &curr->inode_lru != (&table-> inode_lru[index]); curr = next_ioc_inode, next_ioc_inode = (( typeof(*next_ioc_inode) *)((char *)(next_ioc_inode->inode_lru .next)-(unsigned long)(&((typeof(*next_ioc_inode) *)0)-> inode_lru)))) | |||||
214 | &table->inode_lru[index],for (curr = ((typeof(*curr) *)((char *)((&table->inode_lru [index])->next)-(unsigned long)(&((typeof(*curr) *)0)-> inode_lru))), next_ioc_inode = ((typeof(*curr) *)((char *)(curr ->inode_lru.next)-(unsigned long)(&((typeof(*curr) *)0 )->inode_lru))); &curr->inode_lru != (&table-> inode_lru[index]); curr = next_ioc_inode, next_ioc_inode = (( typeof(*next_ioc_inode) *)((char *)(next_ioc_inode->inode_lru .next)-(unsigned long)(&((typeof(*next_ioc_inode) *)0)-> inode_lru)))) | |||||
215 | inode_lru)for (curr = ((typeof(*curr) *)((char *)((&table->inode_lru [index])->next)-(unsigned long)(&((typeof(*curr) *)0)-> inode_lru))), next_ioc_inode = ((typeof(*curr) *)((char *)(curr ->inode_lru.next)-(unsigned long)(&((typeof(*curr) *)0 )->inode_lru))); &curr->inode_lru != (&table-> inode_lru[index]); curr = next_ioc_inode, next_ioc_inode = (( typeof(*next_ioc_inode) *)((char *)(next_ioc_inode->inode_lru .next)-(unsigned long)(&((typeof(*next_ioc_inode) *)0)-> inode_lru)))) { | |||||
216 | /* prune page-by-page for this inode, till | |||||
217 | * we reach the equilibrium */ | |||||
218 | ioc_inode_lock (curr)do { do { do { if (0) printf ("locked inode(%p)", curr); } while (0); _gf_log (curr->table->xl->name, "page.c", __FUNCTION__ , 218, GF_LOG_TRACE, "locked inode(%p)", curr); } while (0); pthread_mutex_lock (&curr->inode_lock); } while (0); | |||||
219 | { | |||||
220 | __ioc_inode_prune (curr, &size_pruned, | |||||
221 | size_to_prune, | |||||
222 | index); | |||||
223 | } | |||||
224 | ioc_inode_unlock (curr)do { do { do { if (0) printf ("unlocked inode(%p)", curr); } while (0); _gf_log (curr->table->xl->name, "page.c", __FUNCTION__ , 224, GF_LOG_TRACE, "unlocked inode(%p)", curr); } while (0) ; pthread_mutex_unlock (&curr->inode_lock); } while (0 ); | |||||
225 | ||||||
226 | if (size_pruned >= size_to_prune) | |||||
227 | break; | |||||
228 | } /* list_for_each_entry_safe (curr...) */ | |||||
229 | ||||||
230 | if (size_pruned >= size_to_prune) | |||||
231 | break; | |||||
232 | } /* for(index=0;...) */ | |||||
233 | ||||||
234 | } /* ioc_inode_table locked region end */ | |||||
235 | ioc_table_unlock (table)do { do { do { if (0) printf ("unlocked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__ , 235, GF_LOG_TRACE, "unlocked table(%p)", table); } while (0 ); pthread_mutex_unlock (&table->table_lock); } while ( 0); | |||||
236 | ||||||
237 | out: | |||||
238 | return 0; | |||||
239 | } | |||||
240 | ||||||
241 | /* | |||||
242 | * __ioc_page_create - create a new page. | |||||
243 | * | |||||
244 | * @ioc_inode: | |||||
245 | * @offset: | |||||
246 | * | |||||
247 | */ | |||||
248 | ioc_page_t * | |||||
249 | __ioc_page_create (ioc_inode_t *ioc_inode, off_t offset) | |||||
250 | { | |||||
251 | ioc_table_t *table = NULL((void*)0); | |||||
252 | ioc_page_t *page = NULL((void*)0); | |||||
253 | off_t rounded_offset = 0; | |||||
254 | ioc_page_t *newpage = NULL((void*)0); | |||||
255 | ||||||
256 | GF_VALIDATE_OR_GOTO ("io-cache", ioc_inode, out)do { if (!ioc_inode) { (*__errno_location ()) = 22; do { do { if (0) printf ("invalid argument: " "ioc_inode"); } while (0 ); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 256 , GF_LOG_ERROR, "invalid argument: " "ioc_inode"); } while (0 ); goto out; } } while (0); | |||||
257 | ||||||
258 | table = ioc_inode->table; | |||||
259 | GF_VALIDATE_OR_GOTO ("io-cache", table, out)do { if (!table) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "table"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 259, GF_LOG_ERROR, "invalid argument: " "table"); } while (0); goto out; } } while (0); | |||||
260 | ||||||
261 | rounded_offset = floor (offset, table->page_size)(((offset)/((table->page_size)?(table->page_size):1))*( table->page_size)); | |||||
262 | ||||||
263 | newpage = GF_CALLOC (1, sizeof (*newpage), gf_ioc_mt_ioc_newpage_t)__gf_calloc (1, sizeof (*newpage), gf_ioc_mt_ioc_newpage_t); | |||||
264 | if (newpage == NULL((void*)0)) { | |||||
265 | goto out; | |||||
266 | } | |||||
267 | ||||||
268 | if (!ioc_inode) { | |||||
269 | GF_FREE (newpage)__gf_free (newpage); | |||||
270 | newpage = NULL((void*)0); | |||||
271 | goto out; | |||||
272 | } | |||||
273 | ||||||
274 | newpage->offset = rounded_offset; | |||||
275 | newpage->inode = ioc_inode; | |||||
276 | pthread_mutex_init (&newpage->page_lock, NULL((void*)0)); | |||||
277 | ||||||
278 | rbthash_insert (ioc_inode->cache.page_table, newpage, &rounded_offset, | |||||
279 | sizeof (rounded_offset)); | |||||
280 | ||||||
281 | list_add_tail (&newpage->page_lru, &ioc_inode->cache.page_lru); | |||||
282 | ||||||
283 | page = newpage; | |||||
284 | ||||||
285 | gf_log ("io-cache", GF_LOG_TRACE,do { do { if (0) printf ("returning new page %p", page); } while (0); _gf_log ("io-cache", "page.c", __FUNCTION__, 286, GF_LOG_TRACE , "returning new page %p", page); } while (0) | |||||
286 | "returning new page %p", page)do { do { if (0) printf ("returning new page %p", page); } while (0); _gf_log ("io-cache", "page.c", __FUNCTION__, 286, GF_LOG_TRACE , "returning new page %p", page); } while (0); | |||||
287 | ||||||
288 | out: | |||||
289 | return page; | |||||
290 | } | |||||
291 | ||||||
292 | /* | |||||
293 | * ioc_wait_on_page - pause a frame to wait till the arrival of a page. | |||||
294 | * here we need to handle the case when the frame who calls wait_on_page | |||||
295 | * himself has caused page_fault | |||||
296 | * | |||||
297 | * @page: page to wait on | |||||
298 | * @frame: call frame who is waiting on page | |||||
299 | * | |||||
300 | */ | |||||
301 | void | |||||
302 | __ioc_wait_on_page (ioc_page_t *page, call_frame_t *frame, off_t offset, | |||||
303 | size_t size) | |||||
304 | { | |||||
305 | ioc_waitq_t *waitq = NULL((void*)0); | |||||
306 | ioc_local_t *local = NULL((void*)0); | |||||
307 | ||||||
308 | GF_VALIDATE_OR_GOTO ("io-cache", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 308, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
309 | local = frame->local; | |||||
310 | ||||||
311 | GF_VALIDATE_OR_GOTO (frame->this->name, local, out)do { if (!local) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "local"); } while (0); _gf_log_callingfn (frame->this->name, "page.c", __FUNCTION__, 311, GF_LOG_ERROR , "invalid argument: " "local"); } while (0); goto out; } } while (0); | |||||
312 | ||||||
313 | if (page == NULL((void*)0)) { | |||||
314 | local->op_ret = -1; | |||||
315 | local->op_errno = ENOMEM12; | |||||
316 | gf_log (frame->this->name, GF_LOG_WARNING,do { do { if (0) printf ("asked to wait on a NULL page"); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 317, GF_LOG_WARNING, "asked to wait on a NULL page"); } while (0) | |||||
317 | "asked to wait on a NULL page")do { do { if (0) printf ("asked to wait on a NULL page"); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 317, GF_LOG_WARNING, "asked to wait on a NULL page"); } while (0); | |||||
318 | } | |||||
319 | ||||||
320 | waitq = GF_CALLOC (1, sizeof (*waitq), gf_ioc_mt_ioc_waitq_t)__gf_calloc (1, sizeof (*waitq), gf_ioc_mt_ioc_waitq_t); | |||||
321 | if (waitq == NULL((void*)0)) { | |||||
322 | local->op_ret = -1; | |||||
323 | local->op_errno = ENOMEM12; | |||||
324 | goto out; | |||||
325 | } | |||||
326 | ||||||
327 | gf_log (frame->this->name, GF_LOG_TRACE,do { do { if (0) printf ("frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 330, GF_LOG_TRACE, "frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0) | |||||
328 | "frame(%p) waiting on page = %p, offset=%"PRId64", "do { do { if (0) printf ("frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 330, GF_LOG_TRACE, "frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0) | |||||
329 | "size=%"GF_PRI_SIZET"",do { do { if (0) printf ("frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 330, GF_LOG_TRACE, "frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0) | |||||
330 | frame, page, offset, size)do { do { if (0) printf ("frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 330, GF_LOG_TRACE, "frame(%p) waiting on page = %p, offset=%" "ll" "d"", " "size=%""zu""", frame, page, offset, size); } while (0); | |||||
331 | ||||||
332 | waitq->data = frame; | |||||
333 | waitq->next = page->waitq; | |||||
334 | waitq->pending_offset = offset; | |||||
335 | waitq->pending_size = size; | |||||
336 | page->waitq = waitq; | |||||
337 | /* one frame can wait only once on a given page, | |||||
338 | * local->wait_count is number of pages a frame is waiting on */ | |||||
339 | ioc_local_lock (local)do { do { do { if (0) printf ("locked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name, "page.c" , __FUNCTION__, 339, GF_LOG_TRACE, "locked local(%p)", local) ; } while (0); pthread_mutex_lock (&local->local_lock) ; } while (0); | |||||
340 | { | |||||
341 | local->wait_count++; | |||||
342 | } | |||||
343 | ioc_local_unlock (local)do { do { do { if (0) printf ("unlocked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name , "page.c", __FUNCTION__, 343, GF_LOG_TRACE, "unlocked local(%p)" , local); } while (0); pthread_mutex_unlock (&local->local_lock ); } while (0); | |||||
344 | ||||||
345 | out: | |||||
346 | return; | |||||
347 | } | |||||
348 | ||||||
349 | ||||||
350 | /* | |||||
351 | * ioc_cache_still_valid - see if cached pages ioc_inode are still valid | |||||
352 | * against given stbuf | |||||
353 | * | |||||
354 | * @ioc_inode: | |||||
355 | * @stbuf: | |||||
356 | * | |||||
357 | * assumes ioc_inode is locked | |||||
358 | */ | |||||
359 | int8_t | |||||
360 | ioc_cache_still_valid (ioc_inode_t *ioc_inode, struct iatt *stbuf) | |||||
361 | { | |||||
362 | int8_t cache_still_valid = 1; | |||||
363 | ||||||
364 | GF_VALIDATE_OR_GOTO ("io-cache", ioc_inode, out)do { if (!ioc_inode) { (*__errno_location ()) = 22; do { do { if (0) printf ("invalid argument: " "ioc_inode"); } while (0 ); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 364 , GF_LOG_ERROR, "invalid argument: " "ioc_inode"); } while (0 ); goto out; } } while (0); | |||||
365 | ||||||
366 | #if 0 | |||||
367 | if (!stbuf || (stbuf->ia_mtime != ioc_inode->cache.mtime) || | |||||
368 | (stbuf->st_mtim.tv_nsec != ioc_inode->stbuf.st_mtim.tv_nsec)) | |||||
369 | cache_still_valid = 0; | |||||
370 | ||||||
371 | #else | |||||
372 | if (!stbuf || (stbuf->ia_mtime != ioc_inode->cache.mtime) | |||||
373 | || (stbuf->ia_mtime_nsec != ioc_inode->cache.mtime_nsec)) | |||||
374 | cache_still_valid = 0; | |||||
375 | ||||||
376 | #endif | |||||
377 | ||||||
378 | #if 0 | |||||
379 | /* talk with avati@gluster.com to enable this section */ | |||||
380 | if (!ioc_inode->mtime && stbuf) { | |||||
381 | cache_still_valid = 1; | |||||
382 | ioc_inode->mtime = stbuf->ia_mtime; | |||||
383 | } | |||||
384 | #endif | |||||
385 | ||||||
386 | out: | |||||
387 | return cache_still_valid; | |||||
388 | } | |||||
389 | ||||||
390 | ||||||
391 | void | |||||
392 | ioc_waitq_return (ioc_waitq_t *waitq) | |||||
393 | { | |||||
394 | ioc_waitq_t *trav = NULL((void*)0); | |||||
395 | ioc_waitq_t *next = NULL((void*)0); | |||||
396 | call_frame_t *frame = NULL((void*)0); | |||||
397 | ||||||
398 | for (trav = waitq; trav; trav = next) { | |||||
399 | next = trav->next; | |||||
400 | ||||||
401 | frame = trav->data; | |||||
402 | ioc_frame_return (frame); | |||||
403 | GF_FREE (trav)__gf_free (trav); | |||||
404 | } | |||||
405 | } | |||||
406 | ||||||
407 | ||||||
408 | int | |||||
409 | ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this, | |||||
410 | int32_t op_ret, int32_t op_errno, struct iovec *vector, | |||||
411 | int32_t count, struct iatt *stbuf, struct iobref *iobref, | |||||
412 | dict_t *xdata) | |||||
413 | { | |||||
414 | ioc_local_t *local = NULL((void*)0); | |||||
415 | off_t offset = 0; | |||||
416 | ioc_inode_t *ioc_inode = NULL((void*)0); | |||||
417 | ioc_table_t *table = NULL((void*)0); | |||||
418 | ioc_page_t *page = NULL((void*)0); | |||||
419 | int32_t destroy_size = 0; | |||||
420 | size_t page_size = 0; | |||||
421 | ioc_waitq_t *waitq = NULL((void*)0); | |||||
422 | size_t iobref_page_size = 0; | |||||
423 | char zero_filled = 0; | |||||
424 | ||||||
425 | GF_ASSERT (frame)do { if (!(frame)) { do { do { if (0) printf ("Assertion failed: " "frame"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 425, GF_LOG_ERROR, "Assertion failed: " "frame"); } while ( 0); } } while (0); | |||||
| ||||||
426 | ||||||
427 | local = frame->local; | |||||
| ||||||
428 | GF_ASSERT (local)do { if (!(local)) { do { do { if (0) printf ("Assertion failed: " "local"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 428, GF_LOG_ERROR, "Assertion failed: " "local"); } while ( 0); } } while (0); | |||||
429 | ||||||
430 | offset = local->pending_offset; | |||||
431 | ioc_inode = local->inode; | |||||
432 | GF_ASSERT (ioc_inode)do { if (!(ioc_inode)) { do { do { if (0) printf ("Assertion failed: " "ioc_inode"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 432, GF_LOG_ERROR, "Assertion failed: " "ioc_inode"); } while (0); } } while (0); | |||||
433 | ||||||
434 | table = ioc_inode->table; | |||||
435 | GF_ASSERT (table)do { if (!(table)) { do { do { if (0) printf ("Assertion failed: " "table"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 435, GF_LOG_ERROR, "Assertion failed: " "table"); } while ( 0); } } while (0); | |||||
436 | ||||||
437 | zero_filled = ((op_ret >=0) && (stbuf->ia_mtime == 0)); | |||||
438 | ||||||
439 | ioc_inode_lock (ioc_inode)do { do { do { if (0) printf ("locked inode(%p)", ioc_inode); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c" , __FUNCTION__, 439, GF_LOG_TRACE, "locked inode(%p)", ioc_inode ); } while (0); pthread_mutex_lock (&ioc_inode->inode_lock ); } while (0); | |||||
440 | { | |||||
441 | if (op_ret == -1 || !(zero_filled || | |||||
442 | ioc_cache_still_valid(ioc_inode, | |||||
443 | stbuf))) { | |||||
444 | gf_log (ioc_inode->table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("cache for inode(%p) is invalid. flushing " "all pages", ioc_inode); } while (0); _gf_log (ioc_inode-> table->xl->name, "page.c", __FUNCTION__, 446, GF_LOG_TRACE , "cache for inode(%p) is invalid. flushing " "all pages", ioc_inode ); } while (0) | |||||
445 | "cache for inode(%p) is invalid. flushing "do { do { if (0) printf ("cache for inode(%p) is invalid. flushing " "all pages", ioc_inode); } while (0); _gf_log (ioc_inode-> table->xl->name, "page.c", __FUNCTION__, 446, GF_LOG_TRACE , "cache for inode(%p) is invalid. flushing " "all pages", ioc_inode ); } while (0) | |||||
446 | "all pages", ioc_inode)do { do { if (0) printf ("cache for inode(%p) is invalid. flushing " "all pages", ioc_inode); } while (0); _gf_log (ioc_inode-> table->xl->name, "page.c", __FUNCTION__, 446, GF_LOG_TRACE , "cache for inode(%p) is invalid. flushing " "all pages", ioc_inode ); } while (0); | |||||
447 | destroy_size = __ioc_inode_flush (ioc_inode); | |||||
448 | } | |||||
449 | ||||||
450 | if ((op_ret >= 0) && !zero_filled) { | |||||
451 | ioc_inode->cache.mtime = stbuf->ia_mtime; | |||||
452 | ioc_inode->cache.mtime_nsec = stbuf->ia_mtime_nsec; | |||||
453 | } | |||||
454 | ||||||
455 | gettimeofday (&ioc_inode->cache.tv, NULL((void*)0)); | |||||
456 | ||||||
457 | if (op_ret < 0) { | |||||
458 | /* error, readv returned -1 */ | |||||
459 | page = __ioc_page_get (ioc_inode, offset); | |||||
460 | if (page) | |||||
461 | waitq = __ioc_page_error (page, op_ret, | |||||
462 | op_errno); | |||||
463 | } else { | |||||
464 | gf_log (ioc_inode->table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("op_ret = %d", op_ret); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c", __FUNCTION__ , 465, GF_LOG_TRACE, "op_ret = %d", op_ret); } while (0) | |||||
465 | "op_ret = %d", op_ret)do { do { if (0) printf ("op_ret = %d", op_ret); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c", __FUNCTION__ , 465, GF_LOG_TRACE, "op_ret = %d", op_ret); } while (0); | |||||
466 | page = __ioc_page_get (ioc_inode, offset); | |||||
467 | if (!page) { | |||||
468 | /* page was flushed */ | |||||
469 | /* some serious bug ? */ | |||||
470 | gf_log (frame->this->name, GF_LOG_WARNING,do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 473, GF_LOG_WARNING, "wasted copy: %""ll" "d""[+%""ll" "d""] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0) | |||||
471 | "wasted copy: %"PRId64"[+%"PRId64"] "do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 473, GF_LOG_WARNING, "wasted copy: %""ll" "d""[+%""ll" "d""] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0) | |||||
472 | "ioc_inode=%p", offset,do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 473, GF_LOG_WARNING, "wasted copy: %""ll" "d""[+%""ll" "d""] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0) | |||||
473 | table->page_size, ioc_inode)do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 473, GF_LOG_WARNING, "wasted copy: %""ll" "d""[+%""ll" "d""] " "ioc_inode=%p", offset, table->page_size, ioc_inode); } while (0); | |||||
474 | } else { | |||||
475 | if (page->vector) { | |||||
476 | iobref_unref (page->iobref); | |||||
477 | GF_FREE (page->vector)__gf_free (page->vector); | |||||
478 | page->vector = NULL((void*)0); | |||||
479 | } | |||||
480 | ||||||
481 | /* keep a copy of the page for our cache */ | |||||
482 | page->vector = iov_dup (vector, count); | |||||
483 | if (page->vector == NULL((void*)0)) { | |||||
484 | page = __ioc_page_get (ioc_inode, | |||||
485 | offset); | |||||
486 | if (page != NULL((void*)0)) | |||||
487 | waitq = __ioc_page_error (page, | |||||
488 | -1, | |||||
489 | ENOMEM12); | |||||
490 | goto unlock; | |||||
491 | } | |||||
492 | ||||||
493 | page->count = count; | |||||
494 | if (iobref) { | |||||
495 | page->iobref = iobref_ref (iobref); | |||||
496 | } else { | |||||
497 | /* TODO: we have got a response to | |||||
498 | * our request and no data */ | |||||
499 | gf_log (frame->this->name,do { do { if (0) printf ("frame>root>rsp_refs is null") ; } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 501, GF_LOG_CRITICAL, "frame>root>rsp_refs is null"); } while (0) | |||||
500 | GF_LOG_CRITICAL,do { do { if (0) printf ("frame>root>rsp_refs is null") ; } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 501, GF_LOG_CRITICAL, "frame>root>rsp_refs is null"); } while (0) | |||||
501 | "frame>root>rsp_refs is null")do { do { if (0) printf ("frame>root>rsp_refs is null") ; } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 501, GF_LOG_CRITICAL, "frame>root>rsp_refs is null"); } while (0); | |||||
502 | } /* if(frame->root->rsp_refs) */ | |||||
503 | ||||||
504 | /* page->size should indicate exactly how | |||||
505 | * much the readv call to the child | |||||
506 | * translator returned. earlier op_ret | |||||
507 | * from child translator was used, which | |||||
508 | * gave rise to a bug where reads from | |||||
509 | * io-cached volume were resulting in 0 | |||||
510 | * byte replies */ | |||||
511 | page_size = iov_length(vector, count); | |||||
512 | page->size = page_size; | |||||
513 | page->op_errno = op_errno; | |||||
514 | ||||||
515 | iobref_page_size = iobref_size (page->iobref); | |||||
516 | ||||||
517 | if (page->waitq) { | |||||
518 | /* wake up all the frames waiting on | |||||
519 | * this page, including | |||||
520 | * the frame which triggered fault */ | |||||
521 | waitq = __ioc_page_wakeup (page, | |||||
522 | op_errno); | |||||
523 | } /* if(page->waitq) */ | |||||
524 | } /* if(!page)...else */ | |||||
525 | } /* if(op_ret < 0)...else */ | |||||
526 | } /* ioc_inode locked region end */ | |||||
527 | unlock: | |||||
528 | ioc_inode_unlock (ioc_inode)do { do { do { if (0) printf ("unlocked inode(%p)", ioc_inode ); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c", __FUNCTION__, 528, GF_LOG_TRACE, "unlocked inode(%p)" , ioc_inode); } while (0); pthread_mutex_unlock (&ioc_inode ->inode_lock); } while (0); | |||||
529 | ||||||
530 | ioc_waitq_return (waitq); | |||||
531 | ||||||
532 | if (iobref_page_size) { | |||||
533 | ioc_table_lock (table)do { do { do { if (0) printf ("locked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 533, GF_LOG_TRACE, "locked table(%p)", table); } while (0); pthread_mutex_lock (&table->table_lock); } while (0); | |||||
534 | { | |||||
535 | table->cache_used += iobref_page_size; | |||||
536 | } | |||||
537 | ioc_table_unlock (table)do { do { do { if (0) printf ("unlocked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__ , 537, GF_LOG_TRACE, "unlocked table(%p)", table); } while (0 ); pthread_mutex_unlock (&table->table_lock); } while ( 0); | |||||
538 | } | |||||
539 | ||||||
540 | if (destroy_size) { | |||||
541 | ioc_table_lock (table)do { do { do { if (0) printf ("locked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__, 541, GF_LOG_TRACE, "locked table(%p)", table); } while (0); pthread_mutex_lock (&table->table_lock); } while (0); | |||||
542 | { | |||||
543 | table->cache_used -= destroy_size; | |||||
544 | } | |||||
545 | ioc_table_unlock (table)do { do { do { if (0) printf ("unlocked table(%p)", table); } while (0); _gf_log (table->xl->name, "page.c", __FUNCTION__ , 545, GF_LOG_TRACE, "unlocked table(%p)", table); } while (0 ); pthread_mutex_unlock (&table->table_lock); } while ( 0); | |||||
546 | } | |||||
547 | ||||||
548 | if (ioc_need_prune (ioc_inode->table)) { | |||||
549 | ioc_prune (ioc_inode->table); | |||||
550 | } | |||||
551 | ||||||
552 | gf_log (frame->this->name, GF_LOG_TRACE, "fault frame %p returned",do { do { if (0) printf ("fault frame %p returned", frame); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 553, GF_LOG_TRACE, "fault frame %p returned", frame); } while (0) | |||||
553 | frame)do { do { if (0) printf ("fault frame %p returned", frame); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 553, GF_LOG_TRACE, "fault frame %p returned", frame); } while (0); | |||||
554 | pthread_mutex_destroy (&local->local_lock); | |||||
555 | ||||||
556 | fd_unref (local->fd); | |||||
557 | ||||||
558 | STACK_DESTROY (frame->root); | |||||
559 | return 0; | |||||
560 | } | |||||
561 | ||||||
562 | ||||||
563 | /* | |||||
564 | * ioc_page_fault - | |||||
565 | * | |||||
566 | * @ioc_inode: | |||||
567 | * @frame: | |||||
568 | * @fd: | |||||
569 | * @offset: | |||||
570 | * | |||||
571 | */ | |||||
572 | void | |||||
573 | ioc_page_fault (ioc_inode_t *ioc_inode, call_frame_t *frame, fd_t *fd, | |||||
574 | off_t offset) | |||||
575 | { | |||||
576 | ioc_table_t *table = NULL((void*)0); | |||||
577 | call_frame_t *fault_frame = NULL((void*)0); | |||||
578 | ioc_local_t *fault_local = NULL((void*)0); | |||||
579 | int32_t op_ret = -1, op_errno = -1; | |||||
580 | ioc_waitq_t *waitq = NULL((void*)0); | |||||
581 | ioc_page_t *page = NULL((void*)0); | |||||
582 | ||||||
583 | GF_ASSERT (ioc_inode)do { if (!(ioc_inode)) { do { do { if (0) printf ("Assertion failed: " "ioc_inode"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 583, GF_LOG_ERROR, "Assertion failed: " "ioc_inode"); } while (0); } } while (0); | |||||
584 | if (frame == NULL((void*)0)) { | |||||
585 | op_ret = -1; | |||||
586 | op_errno = EINVAL22; | |||||
587 | gf_log ("io-cache", GF_LOG_WARNING,do { do { if (0) printf ("page fault on a NULL frame"); } while (0); _gf_log ("io-cache", "page.c", __FUNCTION__, 588, GF_LOG_WARNING , "page fault on a NULL frame"); } while (0) | |||||
588 | "page fault on a NULL frame")do { do { if (0) printf ("page fault on a NULL frame"); } while (0); _gf_log ("io-cache", "page.c", __FUNCTION__, 588, GF_LOG_WARNING , "page fault on a NULL frame"); } while (0); | |||||
589 | goto err; | |||||
590 | } | |||||
591 | ||||||
592 | table = ioc_inode->table; | |||||
593 | fault_frame = copy_frame (frame); | |||||
594 | if (fault_frame == NULL((void*)0)) { | |||||
595 | op_ret = -1; | |||||
596 | op_errno = ENOMEM12; | |||||
597 | goto err; | |||||
598 | } | |||||
599 | ||||||
600 | fault_local = mem_get0 (THIS(*__glusterfs_this_location())->local_pool); | |||||
601 | if (fault_local == NULL((void*)0)) { | |||||
602 | op_ret = -1; | |||||
603 | op_errno = ENOMEM12; | |||||
604 | STACK_DESTROY (fault_frame->root); | |||||
605 | goto err; | |||||
606 | } | |||||
607 | ||||||
608 | /* NOTE: copy_frame() means, the frame the fop whose fd_ref we | |||||
609 | * are using till now won't be valid till we get reply from server. | |||||
610 | * we unref this fd, in fault_cbk */ | |||||
611 | fault_local->fd = fd_ref (fd); | |||||
612 | ||||||
613 | fault_frame->local = fault_local; | |||||
614 | pthread_mutex_init (&fault_local->local_lock, NULL((void*)0)); | |||||
615 | ||||||
616 | INIT_LIST_HEAD (&fault_local->fill_list)do { (&fault_local->fill_list)->next = (&fault_local ->fill_list)->prev = &fault_local->fill_list; } while (0); | |||||
617 | fault_local->pending_offset = offset; | |||||
618 | fault_local->pending_size = table->page_size; | |||||
619 | fault_local->inode = ioc_inode; | |||||
620 | ||||||
621 | gf_log (frame->this->name, GF_LOG_TRACE,do { do { if (0) printf ("stack winding page fault for offset = %" "ll" "d"" with " "frame %p", offset, fault_frame); } while (0 ); _gf_log (frame->this->name, "page.c", __FUNCTION__, 623 , GF_LOG_TRACE, "stack winding page fault for offset = %""ll" "d"" with " "frame %p", offset, fault_frame); } while (0) | |||||
622 | "stack winding page fault for offset = %"PRId64" with "do { do { if (0) printf ("stack winding page fault for offset = %" "ll" "d"" with " "frame %p", offset, fault_frame); } while (0 ); _gf_log (frame->this->name, "page.c", __FUNCTION__, 623 , GF_LOG_TRACE, "stack winding page fault for offset = %""ll" "d"" with " "frame %p", offset, fault_frame); } while (0) | |||||
623 | "frame %p", offset, fault_frame)do { do { if (0) printf ("stack winding page fault for offset = %" "ll" "d"" with " "frame %p", offset, fault_frame); } while (0 ); _gf_log (frame->this->name, "page.c", __FUNCTION__, 623 , GF_LOG_TRACE, "stack winding page fault for offset = %""ll" "d"" with " "frame %p", offset, fault_frame); } while (0); | |||||
624 | ||||||
625 | STACK_WIND (fault_frame, ioc_fault_cbk, FIRST_CHILD(fault_frame->this),do { call_frame_t *_new = ((void*)0); xlator_t *old_THIS = (( void*)0); _new = mem_get0 (fault_frame->root->pool-> frame_mem_pool); if (!_new) { do { do { if (0) printf ("alloc failed" ); } while (0); _gf_log ("stack", "page.c", __FUNCTION__, 627 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ioc_fault_cbk; _new->root = fault_frame ->root; _new->this = (fault_frame->this->children ->xlator); _new->ret = (ret_fn_t) tmp_cbk; _new->parent = fault_frame; _new->cookie = _new; _new->wind_from = __FUNCTION__ ; _new->wind_to = "FIRST_CHILD(fault_frame->this)->fops->readv" ; _new->unwind_to = "ioc_fault_cbk"; pthread_spin_init (& _new->lock, 0); pthread_spin_lock (&fault_frame->root ->stack_lock); { _new->next = fault_frame->root-> frames.next; _new->prev = &fault_frame->root->frames ; if (fault_frame->root->frames.next) fault_frame->root ->frames.next->prev = _new; fault_frame->root->frames .next = _new; fault_frame->ref_count++; } pthread_spin_unlock (&fault_frame->root->stack_lock); old_THIS = (*__glusterfs_this_location ()); (*__glusterfs_this_location()) = (fault_frame->this-> children->xlator); if (fault_frame->this->ctx->measure_latency ) gf_latency_begin (_new, (fault_frame->this->children-> xlator)->fops->readv); (fault_frame->this->children ->xlator)->fops->readv (_new, (fault_frame->this-> children->xlator), fd, table->page_size, offset, 0, ((void *)0)); (*__glusterfs_this_location()) = old_THIS; } while (0) | |||||
626 | FIRST_CHILD(fault_frame->this)->fops->readv, fd,do { call_frame_t *_new = ((void*)0); xlator_t *old_THIS = (( void*)0); _new = mem_get0 (fault_frame->root->pool-> frame_mem_pool); if (!_new) { do { do { if (0) printf ("alloc failed" ); } while (0); _gf_log ("stack", "page.c", __FUNCTION__, 627 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ioc_fault_cbk; _new->root = fault_frame ->root; _new->this = (fault_frame->this->children ->xlator); _new->ret = (ret_fn_t) tmp_cbk; _new->parent = fault_frame; _new->cookie = _new; _new->wind_from = __FUNCTION__ ; _new->wind_to = "FIRST_CHILD(fault_frame->this)->fops->readv" ; _new->unwind_to = "ioc_fault_cbk"; pthread_spin_init (& _new->lock, 0); pthread_spin_lock (&fault_frame->root ->stack_lock); { _new->next = fault_frame->root-> frames.next; _new->prev = &fault_frame->root->frames ; if (fault_frame->root->frames.next) fault_frame->root ->frames.next->prev = _new; fault_frame->root->frames .next = _new; fault_frame->ref_count++; } pthread_spin_unlock (&fault_frame->root->stack_lock); old_THIS = (*__glusterfs_this_location ()); (*__glusterfs_this_location()) = (fault_frame->this-> children->xlator); if (fault_frame->this->ctx->measure_latency ) gf_latency_begin (_new, (fault_frame->this->children-> xlator)->fops->readv); (fault_frame->this->children ->xlator)->fops->readv (_new, (fault_frame->this-> children->xlator), fd, table->page_size, offset, 0, ((void *)0)); (*__glusterfs_this_location()) = old_THIS; } while (0) | |||||
627 | table->page_size, offset, 0, NULL)do { call_frame_t *_new = ((void*)0); xlator_t *old_THIS = (( void*)0); _new = mem_get0 (fault_frame->root->pool-> frame_mem_pool); if (!_new) { do { do { if (0) printf ("alloc failed" ); } while (0); _gf_log ("stack", "page.c", __FUNCTION__, 627 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ioc_fault_cbk; _new->root = fault_frame ->root; _new->this = (fault_frame->this->children ->xlator); _new->ret = (ret_fn_t) tmp_cbk; _new->parent = fault_frame; _new->cookie = _new; _new->wind_from = __FUNCTION__ ; _new->wind_to = "FIRST_CHILD(fault_frame->this)->fops->readv" ; _new->unwind_to = "ioc_fault_cbk"; pthread_spin_init (& _new->lock, 0); pthread_spin_lock (&fault_frame->root ->stack_lock); { _new->next = fault_frame->root-> frames.next; _new->prev = &fault_frame->root->frames ; if (fault_frame->root->frames.next) fault_frame->root ->frames.next->prev = _new; fault_frame->root->frames .next = _new; fault_frame->ref_count++; } pthread_spin_unlock (&fault_frame->root->stack_lock); old_THIS = (*__glusterfs_this_location ()); (*__glusterfs_this_location()) = (fault_frame->this-> children->xlator); if (fault_frame->this->ctx->measure_latency ) gf_latency_begin (_new, (fault_frame->this->children-> xlator)->fops->readv); (fault_frame->this->children ->xlator)->fops->readv (_new, (fault_frame->this-> children->xlator), fd, table->page_size, offset, 0, ((void *)0)); (*__glusterfs_this_location()) = old_THIS; } while (0); | |||||
628 | return; | |||||
629 | ||||||
630 | err: | |||||
631 | ioc_inode_lock (ioc_inode)do { do { do { if (0) printf ("locked inode(%p)", ioc_inode); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c" , __FUNCTION__, 631, GF_LOG_TRACE, "locked inode(%p)", ioc_inode ); } while (0); pthread_mutex_lock (&ioc_inode->inode_lock ); } while (0); | |||||
632 | { | |||||
633 | page = __ioc_page_get (ioc_inode, offset); | |||||
634 | if (page != NULL((void*)0)) { | |||||
635 | waitq = __ioc_page_error (page, op_ret, op_errno); | |||||
636 | } | |||||
637 | } | |||||
638 | ioc_inode_unlock (ioc_inode)do { do { do { if (0) printf ("unlocked inode(%p)", ioc_inode ); } while (0); _gf_log (ioc_inode->table->xl->name, "page.c", __FUNCTION__, 638, GF_LOG_TRACE, "unlocked inode(%p)" , ioc_inode); } while (0); pthread_mutex_unlock (&ioc_inode ->inode_lock); } while (0); | |||||
639 | ||||||
640 | if (waitq != NULL((void*)0)) { | |||||
641 | ioc_waitq_return (waitq); | |||||
642 | } | |||||
643 | } | |||||
644 | ||||||
645 | ||||||
646 | int32_t | |||||
647 | __ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset, | |||||
648 | size_t size, int32_t op_errno) | |||||
649 | { | |||||
650 | ioc_local_t *local = NULL((void*)0); | |||||
651 | ioc_fill_t *fill = NULL((void*)0); | |||||
652 | off_t src_offset = 0; | |||||
653 | off_t dst_offset = 0; | |||||
654 | ssize_t copy_size = 0; | |||||
655 | ioc_inode_t *ioc_inode = NULL((void*)0); | |||||
656 | ioc_fill_t *new = NULL((void*)0); | |||||
657 | int8_t found = 0; | |||||
658 | int32_t ret = -1; | |||||
659 | ||||||
660 | GF_VALIDATE_OR_GOTO ("io-cache", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 660, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
661 | ||||||
662 | local = frame->local; | |||||
663 | GF_VALIDATE_OR_GOTO (frame->this->name, local, out)do { if (!local) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "local"); } while (0); _gf_log_callingfn (frame->this->name, "page.c", __FUNCTION__, 663, GF_LOG_ERROR , "invalid argument: " "local"); } while (0); goto out; } } while (0); | |||||
664 | ||||||
665 | if (page == NULL((void*)0)) { | |||||
666 | gf_log (frame->this->name, GF_LOG_WARNING,do { do { if (0) printf ("NULL page has been provided to serve read request" ); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 667, GF_LOG_WARNING, "NULL page has been provided to serve read request" ); } while (0) | |||||
667 | "NULL page has been provided to serve read request")do { do { if (0) printf ("NULL page has been provided to serve read request" ); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 667, GF_LOG_WARNING, "NULL page has been provided to serve read request" ); } while (0); | |||||
668 | local->op_ret = -1; | |||||
669 | local->op_errno = EINVAL22; | |||||
670 | goto out; | |||||
671 | } | |||||
672 | ||||||
673 | ioc_inode = page->inode; | |||||
674 | ||||||
675 | gf_log (frame->this->name, GF_LOG_TRACE,do { do { if (0) printf ("frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 678, GF_LOG_TRACE, "frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0) | |||||
676 | "frame (%p) offset = %"PRId64" && size = %"GF_PRI_SIZET" "do { do { if (0) printf ("frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 678, GF_LOG_TRACE, "frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0) | |||||
677 | "&& page->size = %"GF_PRI_SIZET" && wait_count = %d",do { do { if (0) printf ("frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 678, GF_LOG_TRACE, "frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0) | |||||
678 | frame, offset, size, page->size, local->wait_count)do { do { if (0) printf ("frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__ , 678, GF_LOG_TRACE, "frame (%p) offset = %""ll" "d"" && size = %" "zu"" " "&& page->size = %""zu"" && wait_count = %d" , frame, offset, size, page->size, local->wait_count); } while (0); | |||||
679 | ||||||
680 | /* immediately move this page to the end of the page_lru list */ | |||||
681 | list_move_tail (&page->page_lru, &ioc_inode->cache.page_lru); | |||||
682 | /* fill local->pending_size bytes from local->pending_offset */ | |||||
683 | if (local->op_ret != -1) { | |||||
684 | local->op_errno = op_errno; | |||||
685 | ||||||
686 | if (page->size == 0) { | |||||
687 | goto done; | |||||
688 | } | |||||
689 | ||||||
690 | if (offset > page->offset) | |||||
691 | /* offset is offset in file, convert it to offset in | |||||
692 | * page */ | |||||
693 | src_offset = offset - page->offset; | |||||
694 | /*FIXME: since offset is the offset within page is the | |||||
695 | * else case valid? */ | |||||
696 | else | |||||
697 | /* local->pending_offset is in previous page. do not | |||||
698 | * fill until we have filled all previous pages */ | |||||
699 | dst_offset = page->offset - offset; | |||||
700 | ||||||
701 | /* we have to copy from offset to either end of this page | |||||
702 | * or till the requested size */ | |||||
703 | copy_size = min (page->size - src_offset,((page->size - src_offset)<(size - dst_offset)?(page-> size - src_offset):(size - dst_offset)) | |||||
704 | size - dst_offset)((page->size - src_offset)<(size - dst_offset)?(page-> size - src_offset):(size - dst_offset)); | |||||
705 | ||||||
706 | if (copy_size < 0) { | |||||
707 | /* if page contains fewer bytes and the required offset | |||||
708 | is beyond the page size in the page */ | |||||
709 | copy_size = src_offset = 0; | |||||
710 | } | |||||
711 | ||||||
712 | gf_log (page->inode->table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %""ll" "d""", copy_size , src_offset, dst_offset); } while (0); _gf_log (page->inode ->table->xl->name, "page.c", __FUNCTION__, 715, GF_LOG_TRACE , "copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %" "ll" "d""", copy_size, src_offset, dst_offset); } while (0) | |||||
713 | "copy_size = %"GF_PRI_SIZET" && src_offset = "do { do { if (0) printf ("copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %""ll" "d""", copy_size , src_offset, dst_offset); } while (0); _gf_log (page->inode ->table->xl->name, "page.c", __FUNCTION__, 715, GF_LOG_TRACE , "copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %" "ll" "d""", copy_size, src_offset, dst_offset); } while (0) | |||||
714 | "%"PRId64" && dst_offset = %"PRId64"",do { do { if (0) printf ("copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %""ll" "d""", copy_size , src_offset, dst_offset); } while (0); _gf_log (page->inode ->table->xl->name, "page.c", __FUNCTION__, 715, GF_LOG_TRACE , "copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %" "ll" "d""", copy_size, src_offset, dst_offset); } while (0) | |||||
715 | copy_size, src_offset, dst_offset)do { do { if (0) printf ("copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %""ll" "d""", copy_size , src_offset, dst_offset); } while (0); _gf_log (page->inode ->table->xl->name, "page.c", __FUNCTION__, 715, GF_LOG_TRACE , "copy_size = %""zu"" && src_offset = " "%""ll" "d"" && dst_offset = %" "ll" "d""", copy_size, src_offset, dst_offset); } while (0); | |||||
716 | ||||||
717 | { | |||||
718 | new = GF_CALLOC (1, sizeof (*new),__gf_calloc (1, sizeof (*new), gf_ioc_mt_ioc_fill_t) | |||||
719 | gf_ioc_mt_ioc_fill_t)__gf_calloc (1, sizeof (*new), gf_ioc_mt_ioc_fill_t); | |||||
720 | if (new == NULL((void*)0)) { | |||||
721 | local->op_ret = -1; | |||||
722 | local->op_errno = ENOMEM12; | |||||
723 | goto out; | |||||
724 | } | |||||
725 | ||||||
726 | new->offset = page->offset; | |||||
727 | new->size = copy_size; | |||||
728 | new->iobref = iobref_ref (page->iobref); | |||||
729 | new->count = iov_subset (page->vector, page->count, | |||||
730 | src_offset, | |||||
731 | src_offset + copy_size, | |||||
732 | NULL((void*)0)); | |||||
733 | ||||||
734 | new->vector = GF_CALLOC (new->count,__gf_calloc (new->count, sizeof (struct iovec), gf_ioc_mt_iovec ) | |||||
735 | sizeof (struct iovec),__gf_calloc (new->count, sizeof (struct iovec), gf_ioc_mt_iovec ) | |||||
736 | gf_ioc_mt_iovec)__gf_calloc (new->count, sizeof (struct iovec), gf_ioc_mt_iovec ); | |||||
737 | if (new->vector == NULL((void*)0)) { | |||||
738 | local->op_ret = -1; | |||||
739 | local->op_errno = ENOMEM12; | |||||
740 | ||||||
741 | iobref_unref (new->iobref); | |||||
742 | GF_FREE (new)__gf_free (new); | |||||
743 | goto out; | |||||
744 | } | |||||
745 | ||||||
746 | new->count = iov_subset (page->vector, page->count, | |||||
747 | src_offset, | |||||
748 | src_offset + copy_size, | |||||
749 | new->vector); | |||||
750 | ||||||
751 | /* add the ioc_fill to fill_list for this frame */ | |||||
752 | if (list_empty (&local->fill_list)) { | |||||
753 | /* if list is empty, then this is the first | |||||
754 | * time we are filling frame, add the | |||||
755 | * ioc_fill_t to the end of list */ | |||||
756 | list_add_tail (&new->list, &local->fill_list); | |||||
757 | } else { | |||||
758 | found = 0; | |||||
759 | /* list is not empty, we need to look for | |||||
760 | * where this offset fits in list */ | |||||
761 | list_for_each_entry (fill, &local->fill_list,for (fill = ((typeof(*fill) *)((char *)((&local->fill_list )->next)-(unsigned long)(&((typeof(*fill) *)0)->list ))); &fill->list != (&local->fill_list); fill = ((typeof(*fill) *)((char *)(fill->list.next)-(unsigned long )(&((typeof(*fill) *)0)->list)))) | |||||
762 | list)for (fill = ((typeof(*fill) *)((char *)((&local->fill_list )->next)-(unsigned long)(&((typeof(*fill) *)0)->list ))); &fill->list != (&local->fill_list); fill = ((typeof(*fill) *)((char *)(fill->list.next)-(unsigned long )(&((typeof(*fill) *)0)->list)))) { | |||||
763 | if (fill->offset > new->offset) { | |||||
764 | found = 1; | |||||
765 | break; | |||||
766 | } | |||||
767 | } | |||||
768 | ||||||
769 | if (found) { | |||||
770 | list_add_tail (&new->list, | |||||
771 | &fill->list); | |||||
772 | } else { | |||||
773 | list_add_tail (&new->list, | |||||
774 | &local->fill_list); | |||||
775 | } | |||||
776 | } | |||||
777 | } | |||||
778 | ||||||
779 | local->op_ret += copy_size; | |||||
780 | } | |||||
781 | ||||||
782 | done: | |||||
783 | ret = 0; | |||||
784 | out: | |||||
785 | return ret; | |||||
786 | } | |||||
787 | ||||||
788 | /* | |||||
789 | * ioc_frame_unwind - frame unwinds only from here | |||||
790 | * | |||||
791 | * @frame: call frame to unwind | |||||
792 | * | |||||
793 | * to be used only by ioc_frame_return(), when a frame has | |||||
794 | * finished waiting on all pages, required | |||||
795 | * | |||||
796 | */ | |||||
797 | static void | |||||
798 | ioc_frame_unwind (call_frame_t *frame) | |||||
799 | { | |||||
800 | ioc_local_t *local = NULL((void*)0); | |||||
801 | ioc_fill_t *fill = NULL((void*)0), *next = NULL((void*)0); | |||||
802 | int32_t count = 0; | |||||
803 | struct iovec *vector = NULL((void*)0); | |||||
804 | int32_t copied = 0; | |||||
805 | struct iobref *iobref = NULL((void*)0); | |||||
806 | struct iatt stbuf = {0,}; | |||||
807 | int32_t op_ret = 0, op_errno = 0; | |||||
808 | ||||||
809 | GF_ASSERT (frame)do { if (!(frame)) { do { do { if (0) printf ("Assertion failed: " "frame"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 809, GF_LOG_ERROR, "Assertion failed: " "frame"); } while ( 0); } } while (0); | |||||
810 | ||||||
811 | local = frame->local; | |||||
812 | if (local == NULL((void*)0)) { | |||||
813 | gf_log (frame->this->name, GF_LOG_WARNING,do { do { if (0) printf ("local is NULL"); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__, 814, GF_LOG_WARNING , "local is NULL"); } while (0) | |||||
814 | "local is NULL")do { do { if (0) printf ("local is NULL"); } while (0); _gf_log (frame->this->name, "page.c", __FUNCTION__, 814, GF_LOG_WARNING , "local is NULL"); } while (0); | |||||
815 | op_ret = -1; | |||||
816 | op_errno = ENOMEM12; | |||||
817 | goto unwind; | |||||
818 | } | |||||
819 | ||||||
820 | if (local->op_ret < 0) { | |||||
821 | op_ret = local->op_ret; | |||||
822 | op_errno = local->op_errno; | |||||
823 | goto unwind; | |||||
824 | } | |||||
825 | ||||||
826 | // ioc_local_lock (local); | |||||
827 | iobref = iobref_new (); | |||||
828 | if (iobref == NULL((void*)0)) { | |||||
829 | op_ret = -1; | |||||
830 | op_errno = ENOMEM12; | |||||
831 | } | |||||
832 | ||||||
833 | if (list_empty (&local->fill_list)) { | |||||
834 | gf_log (frame->this->name, GF_LOG_TRACE,do { do { if (0) printf ("frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0); _gf_log (frame-> this->name, "page.c", __FUNCTION__, 837, GF_LOG_TRACE, "frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0) | |||||
835 | "frame(%p) has 0 entries in local->fill_list "do { do { if (0) printf ("frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0); _gf_log (frame-> this->name, "page.c", __FUNCTION__, 837, GF_LOG_TRACE, "frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0) | |||||
836 | "(offset = %"PRId64" && size = %"GF_PRI_SIZET")",do { do { if (0) printf ("frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0); _gf_log (frame-> this->name, "page.c", __FUNCTION__, 837, GF_LOG_TRACE, "frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0) | |||||
837 | frame, local->offset, local->size)do { do { if (0) printf ("frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0); _gf_log (frame-> this->name, "page.c", __FUNCTION__, 837, GF_LOG_TRACE, "frame(%p) has 0 entries in local->fill_list " "(offset = %""ll" "d"" && size = %""zu"")", frame, local ->offset, local->size); } while (0); | |||||
838 | } | |||||
839 | ||||||
840 | list_for_each_entry (fill, &local->fill_list, list)for (fill = ((typeof(*fill) *)((char *)((&local->fill_list )->next)-(unsigned long)(&((typeof(*fill) *)0)->list ))); &fill->list != (&local->fill_list); fill = ((typeof(*fill) *)((char *)(fill->list.next)-(unsigned long )(&((typeof(*fill) *)0)->list)))) { | |||||
841 | count += fill->count; | |||||
842 | } | |||||
843 | ||||||
844 | vector = GF_CALLOC (count, sizeof (*vector), gf_ioc_mt_iovec)__gf_calloc (count, sizeof (*vector), gf_ioc_mt_iovec); | |||||
845 | if (vector == NULL((void*)0)) { | |||||
846 | op_ret = -1; | |||||
847 | op_errno = ENOMEM12; | |||||
848 | } | |||||
849 | ||||||
850 | list_for_each_entry_safe (fill, next, &local->fill_list, list)for (fill = ((typeof(*fill) *)((char *)((&local->fill_list )->next)-(unsigned long)(&((typeof(*fill) *)0)->list ))), next = ((typeof(*fill) *)((char *)(fill->list.next)-( unsigned long)(&((typeof(*fill) *)0)->list))); &fill ->list != (&local->fill_list); fill = next, next = ( (typeof(*next) *)((char *)(next->list.next)-(unsigned long )(&((typeof(*next) *)0)->list)))) { | |||||
851 | if ((vector != NULL((void*)0)) && (iobref != NULL((void*)0))) { | |||||
852 | memcpy (((char *)vector) + copied, | |||||
853 | fill->vector, | |||||
854 | fill->count * sizeof (*vector)); | |||||
855 | ||||||
856 | copied += (fill->count * sizeof (*vector)); | |||||
857 | ||||||
858 | iobref_merge (iobref, fill->iobref); | |||||
859 | } | |||||
860 | ||||||
861 | list_del (&fill->list); | |||||
862 | iobref_unref (fill->iobref); | |||||
863 | GF_FREE (fill->vector)__gf_free (fill->vector); | |||||
864 | GF_FREE (fill)__gf_free (fill); | |||||
865 | } | |||||
866 | ||||||
867 | if (op_ret != -1) { | |||||
868 | op_ret = iov_length (vector, count); | |||||
869 | } | |||||
870 | ||||||
871 | unwind: | |||||
872 | gf_log (frame->this->name, GF_LOG_TRACE,do { do { if (0) printf ("frame(%p) unwinding with op_ret=%d" , frame, op_ret); } while (0); _gf_log (frame->this->name , "page.c", __FUNCTION__, 873, GF_LOG_TRACE, "frame(%p) unwinding with op_ret=%d" , frame, op_ret); } while (0) | |||||
873 | "frame(%p) unwinding with op_ret=%d", frame, op_ret)do { do { if (0) printf ("frame(%p) unwinding with op_ret=%d" , frame, op_ret); } while (0); _gf_log (frame->this->name , "page.c", __FUNCTION__, 873, GF_LOG_TRACE, "frame(%p) unwinding with op_ret=%d" , frame, op_ret); } while (0); | |||||
874 | ||||||
875 | // ioc_local_unlock (local); | |||||
876 | ||||||
877 | frame->local = NULL((void*)0); | |||||
878 | STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector,do { fop_readv_cbk_t fn = ((void*)0); call_frame_t *_parent = ((void*)0); xlator_t *old_THIS = ((void*)0); if (!frame) { do { do { if (0) printf ("!frame"); } while (0); _gf_log ("stack" , "page.c", __FUNCTION__, 879, GF_LOG_CRITICAL, "!frame"); } while (0); break; } fn = (fop_readv_cbk_t )frame->ret; _parent = frame->parent; pthread_spin_lock (&frame->root-> stack_lock); { _parent->ref_count--; } pthread_spin_unlock (&frame->root->stack_lock); old_THIS = (*__glusterfs_this_location ()); (*__glusterfs_this_location()) = _parent->this; frame ->complete = _gf_true; frame->unwind_from = __FUNCTION__ ; if (frame->this->ctx->measure_latency) gf_latency_end (frame); fn (_parent, frame->cookie, _parent->this, op_ret , op_errno, vector, count, &stbuf, iobref, ((void*)0)); ( *__glusterfs_this_location()) = old_THIS; } while (0) | |||||
879 | count, &stbuf, iobref, NULL)do { fop_readv_cbk_t fn = ((void*)0); call_frame_t *_parent = ((void*)0); xlator_t *old_THIS = ((void*)0); if (!frame) { do { do { if (0) printf ("!frame"); } while (0); _gf_log ("stack" , "page.c", __FUNCTION__, 879, GF_LOG_CRITICAL, "!frame"); } while (0); break; } fn = (fop_readv_cbk_t )frame->ret; _parent = frame->parent; pthread_spin_lock (&frame->root-> stack_lock); { _parent->ref_count--; } pthread_spin_unlock (&frame->root->stack_lock); old_THIS = (*__glusterfs_this_location ()); (*__glusterfs_this_location()) = _parent->this; frame ->complete = _gf_true; frame->unwind_from = __FUNCTION__ ; if (frame->this->ctx->measure_latency) gf_latency_end (frame); fn (_parent, frame->cookie, _parent->this, op_ret , op_errno, vector, count, &stbuf, iobref, ((void*)0)); ( *__glusterfs_this_location()) = old_THIS; } while (0); | |||||
880 | ||||||
881 | if (iobref != NULL((void*)0)) { | |||||
882 | iobref_unref (iobref); | |||||
883 | } | |||||
884 | ||||||
885 | if (vector != NULL((void*)0)) { | |||||
886 | GF_FREE (vector)__gf_free (vector); | |||||
887 | vector = NULL((void*)0); | |||||
888 | } | |||||
889 | ||||||
890 | pthread_mutex_destroy (&local->local_lock); | |||||
891 | if (local) | |||||
892 | mem_put (local); | |||||
893 | ||||||
894 | return; | |||||
895 | } | |||||
896 | ||||||
897 | /* | |||||
898 | * ioc_frame_return - | |||||
899 | * @frame: | |||||
900 | * | |||||
901 | * to be called only when a frame is waiting on an in-transit page | |||||
902 | */ | |||||
903 | void | |||||
904 | ioc_frame_return (call_frame_t *frame) | |||||
905 | { | |||||
906 | ioc_local_t *local = NULL((void*)0); | |||||
907 | int32_t wait_count = 0; | |||||
908 | ||||||
909 | GF_ASSERT (frame)do { if (!(frame)) { do { do { if (0) printf ("Assertion failed: " "frame"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 909, GF_LOG_ERROR, "Assertion failed: " "frame"); } while ( 0); } } while (0); | |||||
910 | ||||||
911 | local = frame->local; | |||||
912 | GF_ASSERT (local->wait_count > 0)do { if (!(local->wait_count > 0)) { do { do { if (0) printf ("Assertion failed: " "local->wait_count > 0"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__, 912, GF_LOG_ERROR , "Assertion failed: " "local->wait_count > 0"); } while (0); } } while (0); | |||||
913 | ||||||
914 | ioc_local_lock (local)do { do { do { if (0) printf ("locked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name, "page.c" , __FUNCTION__, 914, GF_LOG_TRACE, "locked local(%p)", local) ; } while (0); pthread_mutex_lock (&local->local_lock) ; } while (0); | |||||
915 | { | |||||
916 | wait_count = --local->wait_count; | |||||
917 | } | |||||
918 | ioc_local_unlock (local)do { do { do { if (0) printf ("unlocked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name , "page.c", __FUNCTION__, 918, GF_LOG_TRACE, "unlocked local(%p)" , local); } while (0); pthread_mutex_unlock (&local->local_lock ); } while (0); | |||||
919 | ||||||
920 | if (!wait_count) { | |||||
921 | ioc_frame_unwind (frame); | |||||
922 | } | |||||
923 | ||||||
924 | return; | |||||
925 | } | |||||
926 | ||||||
927 | /* | |||||
928 | * ioc_page_wakeup - | |||||
929 | * @page: | |||||
930 | * | |||||
931 | * to be called only when a frame is waiting on an in-transit page | |||||
932 | */ | |||||
933 | ioc_waitq_t * | |||||
934 | __ioc_page_wakeup (ioc_page_t *page, int32_t op_errno) | |||||
935 | { | |||||
936 | ioc_waitq_t *waitq = NULL((void*)0), *trav = NULL((void*)0); | |||||
937 | call_frame_t *frame = NULL((void*)0); | |||||
938 | int32_t ret = -1; | |||||
939 | ||||||
940 | GF_VALIDATE_OR_GOTO ("io-cache", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 940, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
941 | ||||||
942 | waitq = page->waitq; | |||||
943 | page->waitq = NULL((void*)0); | |||||
944 | ||||||
945 | page->ready = 1; | |||||
946 | ||||||
947 | gf_log (page->inode->table->xl->name, GF_LOG_TRACE,do { do { if (0) printf ("page is %p && waitq = %p", page , waitq); } while (0); _gf_log (page->inode->table-> xl->name, "page.c", __FUNCTION__, 948, GF_LOG_TRACE, "page is %p && waitq = %p" , page, waitq); } while (0) | |||||
948 | "page is %p && waitq = %p", page, waitq)do { do { if (0) printf ("page is %p && waitq = %p", page , waitq); } while (0); _gf_log (page->inode->table-> xl->name, "page.c", __FUNCTION__, 948, GF_LOG_TRACE, "page is %p && waitq = %p" , page, waitq); } while (0); | |||||
949 | ||||||
950 | for (trav = waitq; trav; trav = trav->next) { | |||||
951 | frame = trav->data; | |||||
952 | ret = __ioc_frame_fill (page, frame, trav->pending_offset, | |||||
953 | trav->pending_size, op_errno); | |||||
954 | if (ret == -1) { | |||||
955 | break; | |||||
956 | } | |||||
957 | } | |||||
958 | ||||||
959 | if (page->stale) { | |||||
960 | __ioc_page_destroy (page); | |||||
961 | } | |||||
962 | ||||||
963 | out: | |||||
964 | return waitq; | |||||
965 | } | |||||
966 | ||||||
967 | ||||||
968 | ||||||
969 | /* | |||||
970 | * ioc_page_error - | |||||
971 | * @page: | |||||
972 | * @op_ret: | |||||
973 | * @op_errno: | |||||
974 | * | |||||
975 | */ | |||||
976 | ioc_waitq_t * | |||||
977 | __ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno) | |||||
978 | { | |||||
979 | ioc_waitq_t *waitq = NULL((void*)0), *trav = NULL((void*)0); | |||||
980 | call_frame_t *frame = NULL((void*)0); | |||||
981 | int64_t ret = 0; | |||||
982 | ioc_table_t *table = NULL((void*)0); | |||||
983 | ioc_local_t *local = NULL((void*)0); | |||||
984 | ||||||
985 | GF_VALIDATE_OR_GOTO ("io-cache", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("io-cache", "page.c", __FUNCTION__, 985, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
986 | ||||||
987 | waitq = page->waitq; | |||||
988 | page->waitq = NULL((void*)0); | |||||
989 | ||||||
990 | gf_log (page->inode->table->xl->name, GF_LOG_WARNING,do { do { if (0) printf ("page error for page = %p & waitq = %p" , page, waitq); } while (0); _gf_log (page->inode->table ->xl->name, "page.c", __FUNCTION__, 991, GF_LOG_WARNING , "page error for page = %p & waitq = %p", page, waitq); } while (0) | |||||
991 | "page error for page = %p & waitq = %p", page, waitq)do { do { if (0) printf ("page error for page = %p & waitq = %p" , page, waitq); } while (0); _gf_log (page->inode->table ->xl->name, "page.c", __FUNCTION__, 991, GF_LOG_WARNING , "page error for page = %p & waitq = %p", page, waitq); } while (0); | |||||
992 | ||||||
993 | for (trav = waitq; trav; trav = trav->next) { | |||||
994 | ||||||
995 | frame = trav->data; | |||||
996 | ||||||
997 | local = frame->local; | |||||
998 | ioc_local_lock (local)do { do { do { if (0) printf ("locked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name, "page.c" , __FUNCTION__, 998, GF_LOG_TRACE, "locked local(%p)", local) ; } while (0); pthread_mutex_lock (&local->local_lock) ; } while (0); | |||||
999 | { | |||||
1000 | if (local->op_ret != -1) { | |||||
1001 | local->op_ret = op_ret; | |||||
1002 | local->op_errno = op_errno; | |||||
1003 | } | |||||
1004 | } | |||||
1005 | ioc_local_unlock (local)do { do { do { if (0) printf ("unlocked local(%p)", local); } while (0); _gf_log (local->inode->table->xl->name , "page.c", __FUNCTION__, 1005, GF_LOG_TRACE, "unlocked local(%p)" , local); } while (0); pthread_mutex_unlock (&local->local_lock ); } while (0); | |||||
1006 | } | |||||
1007 | ||||||
1008 | table = page->inode->table; | |||||
1009 | ret = __ioc_page_destroy (page); | |||||
1010 | ||||||
1011 | if (ret != -1) { | |||||
1012 | table->cache_used -= ret; | |||||
1013 | } | |||||
1014 | ||||||
1015 | out: | |||||
1016 | return waitq; | |||||
1017 | } | |||||
1018 | ||||||
1019 | /* | |||||
1020 | * ioc_page_error - | |||||
1021 | * @page: | |||||
1022 | * @op_ret: | |||||
1023 | * @op_errno: | |||||
1024 | * | |||||
1025 | */ | |||||
1026 | ioc_waitq_t * | |||||
1027 | ioc_page_error (ioc_page_t *page, int32_t op_ret, int32_t op_errno) | |||||
1028 | { | |||||
1029 | ioc_waitq_t *waitq = NULL((void*)0); | |||||
1030 | ||||||
1031 | if (page == NULL((void*)0)) { | |||||
1032 | goto out; | |||||
1033 | } | |||||
1034 | ||||||
1035 | ioc_inode_lock (page->inode)do { do { do { if (0) printf ("locked inode(%p)", page->inode ); } while (0); _gf_log (page->inode->table->xl-> name, "page.c", __FUNCTION__, 1035, GF_LOG_TRACE, "locked inode(%p)" , page->inode); } while (0); pthread_mutex_lock (&page ->inode->inode_lock); } while (0); | |||||
1036 | { | |||||
1037 | waitq = __ioc_page_error (page, op_ret, op_errno); | |||||
1038 | } | |||||
1039 | ioc_inode_unlock (page->inode)do { do { do { if (0) printf ("unlocked inode(%p)", page-> inode); } while (0); _gf_log (page->inode->table->xl ->name, "page.c", __FUNCTION__, 1039, GF_LOG_TRACE, "unlocked inode(%p)" , page->inode); } while (0); pthread_mutex_unlock (&page ->inode->inode_lock); } while (0); | |||||
1040 | ||||||
1041 | out: | |||||
1042 | return waitq; | |||||
1043 | } |