File: | xlators/performance/read-ahead/src/page.c |
Location: | line 149, 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 "read-ahead.h" | |||||
21 | #include <assert.h> | |||||
22 | ||||||
23 | ra_page_t * | |||||
24 | ra_page_get (ra_file_t *file, off_t offset) | |||||
25 | { | |||||
26 | ra_page_t *page = NULL((void*)0); | |||||
27 | off_t rounded_offset = 0; | |||||
28 | ||||||
29 | GF_VALIDATE_OR_GOTO ("read-ahead", file, out)do { if (!file) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "file"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 29, GF_LOG_ERROR, "invalid argument: " "file"); } while (0); goto out; } } while (0); | |||||
30 | ||||||
31 | page = file->pages.next; | |||||
32 | rounded_offset = floor (offset, file->page_size)(((offset)/((file->page_size)?(file->page_size):1))*(file ->page_size)); | |||||
33 | ||||||
34 | while (page != &file->pages && page->offset < rounded_offset) | |||||
35 | page = page->next; | |||||
36 | ||||||
37 | if (page == &file->pages || page->offset != rounded_offset) | |||||
38 | page = NULL((void*)0); | |||||
39 | ||||||
40 | out: | |||||
41 | return page; | |||||
42 | } | |||||
43 | ||||||
44 | ||||||
45 | ra_page_t * | |||||
46 | ra_page_create (ra_file_t *file, off_t offset) | |||||
47 | { | |||||
48 | ra_page_t *page = NULL((void*)0); | |||||
49 | off_t rounded_offset = 0; | |||||
50 | ra_page_t *newpage = NULL((void*)0); | |||||
51 | ||||||
52 | GF_VALIDATE_OR_GOTO ("read-ahead", file, out)do { if (!file) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "file"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 52, GF_LOG_ERROR, "invalid argument: " "file"); } while (0); goto out; } } while (0); | |||||
53 | ||||||
54 | page = file->pages.next; | |||||
55 | rounded_offset = floor (offset, file->page_size)(((offset)/((file->page_size)?(file->page_size):1))*(file ->page_size)); | |||||
56 | ||||||
57 | while (page != &file->pages && page->offset < rounded_offset) | |||||
58 | page = page->next; | |||||
59 | ||||||
60 | if (page == &file->pages || page->offset != rounded_offset) { | |||||
61 | newpage = GF_CALLOC (1, sizeof (*newpage), gf_ra_mt_ra_page_t)__gf_calloc (1, sizeof (*newpage), gf_ra_mt_ra_page_t); | |||||
62 | if (!newpage) { | |||||
63 | goto out; | |||||
64 | } | |||||
65 | ||||||
66 | newpage->offset = rounded_offset; | |||||
67 | newpage->prev = page->prev; | |||||
68 | newpage->next = page; | |||||
69 | newpage->file = file; | |||||
70 | page->prev->next = newpage; | |||||
71 | page->prev = newpage; | |||||
72 | ||||||
73 | page = newpage; | |||||
74 | } | |||||
75 | ||||||
76 | out: | |||||
77 | return page; | |||||
78 | } | |||||
79 | ||||||
80 | ||||||
81 | void | |||||
82 | ra_wait_on_page (ra_page_t *page, call_frame_t *frame) | |||||
83 | { | |||||
84 | ra_waitq_t *waitq = NULL((void*)0); | |||||
85 | ra_local_t *local = NULL((void*)0); | |||||
86 | ||||||
87 | GF_VALIDATE_OR_GOTO ("read-ahead", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 87, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
88 | GF_VALIDATE_OR_GOTO (frame->this->name, page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn (frame->this->name, "page.c", __FUNCTION__, 88, GF_LOG_ERROR , "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
89 | ||||||
90 | local = frame->local; | |||||
91 | ||||||
92 | waitq = GF_CALLOC (1, sizeof (*waitq), gf_ra_mt_ra_waitq_t)__gf_calloc (1, sizeof (*waitq), gf_ra_mt_ra_waitq_t); | |||||
93 | if (!waitq) { | |||||
94 | local->op_ret = -1; | |||||
95 | local->op_errno = ENOMEM12; | |||||
96 | goto out; | |||||
97 | } | |||||
98 | ||||||
99 | waitq->data = frame; | |||||
100 | waitq->next = page->waitq; | |||||
101 | page->waitq = waitq; | |||||
102 | ||||||
103 | ra_local_lock (local); | |||||
104 | { | |||||
105 | local->wait_count++; | |||||
106 | } | |||||
107 | ra_local_unlock (local); | |||||
108 | ||||||
109 | out: | |||||
110 | return; | |||||
111 | } | |||||
112 | ||||||
113 | ||||||
114 | void | |||||
115 | ra_waitq_return (ra_waitq_t *waitq) | |||||
116 | { | |||||
117 | ra_waitq_t *trav = NULL((void*)0); | |||||
118 | ra_waitq_t *next = NULL((void*)0); | |||||
119 | call_frame_t *frame = NULL((void*)0); | |||||
120 | ||||||
121 | for (trav = waitq; trav; trav = next) { | |||||
122 | next = trav->next; | |||||
123 | ||||||
124 | frame = trav->data; | |||||
125 | ra_frame_return (frame); | |||||
126 | GF_FREE (trav)__gf_free (trav); | |||||
127 | } | |||||
128 | ||||||
129 | return; | |||||
130 | } | |||||
131 | ||||||
132 | ||||||
133 | int | |||||
134 | ra_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this, | |||||
135 | int32_t op_ret, int32_t op_errno, struct iovec *vector, | |||||
136 | int32_t count, struct iatt *stbuf, struct iobref *iobref, | |||||
137 | dict_t *xdata) | |||||
138 | { | |||||
139 | ra_local_t *local = NULL((void*)0); | |||||
140 | off_t pending_offset = 0; | |||||
141 | ra_file_t *file = NULL((void*)0); | |||||
142 | ra_page_t *page = NULL((void*)0); | |||||
143 | ra_waitq_t *waitq = NULL((void*)0); | |||||
144 | fd_t *fd = NULL((void*)0); | |||||
145 | uint64_t tmp_file = 0; | |||||
146 | ||||||
147 | GF_ASSERT (frame)do { if (!(frame)) { do { do { if (0) printf ("Assertion failed: " "frame"); } while (0); _gf_log_callingfn ("", "page.c", __FUNCTION__ , 147, GF_LOG_ERROR, "Assertion failed: " "frame"); } while ( 0); } } while (0); | |||||
| ||||||
148 | ||||||
149 | local = frame->local; | |||||
| ||||||
150 | fd = local->fd; | |||||
151 | ||||||
152 | fd_ctx_get (fd, this, &tmp_file); | |||||
153 | ||||||
154 | file = (ra_file_t *)(long)tmp_file; | |||||
155 | pending_offset = local->pending_offset; | |||||
156 | ||||||
157 | if (file == NULL((void*)0)) { | |||||
158 | gf_log (this->name, GF_LOG_WARNING,do { do { if (0) printf ("read-ahead context not set in fd (%p)" , fd); } while (0); _gf_log (this->name, "page.c", __FUNCTION__ , 159, GF_LOG_WARNING, "read-ahead context not set in fd (%p)" , fd); } while (0) | |||||
159 | "read-ahead context not set in fd (%p)", fd)do { do { if (0) printf ("read-ahead context not set in fd (%p)" , fd); } while (0); _gf_log (this->name, "page.c", __FUNCTION__ , 159, GF_LOG_WARNING, "read-ahead context not set in fd (%p)" , fd); } while (0); | |||||
160 | op_ret = -1; | |||||
161 | op_errno = EBADF9; | |||||
162 | goto out; | |||||
163 | } | |||||
164 | ||||||
165 | ra_file_lock (file); | |||||
166 | { | |||||
167 | if (op_ret >= 0) | |||||
168 | file->stbuf = *stbuf; | |||||
169 | ||||||
170 | page = ra_page_get (file, pending_offset); | |||||
171 | ||||||
172 | if (!page) { | |||||
173 | gf_log (this->name, GF_LOG_TRACE,do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] file=%p", pending_offset, file->page_size, file); } while (0); _gf_log (this->name, "page.c", __FUNCTION__, 175, GF_LOG_TRACE , "wasted copy: %""ll" "d""[+%""ll" "d""] file=%p", pending_offset , file->page_size, file); } while (0) | |||||
174 | "wasted copy: %"PRId64"[+%"PRId64"] file=%p",do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] file=%p", pending_offset, file->page_size, file); } while (0); _gf_log (this->name, "page.c", __FUNCTION__, 175, GF_LOG_TRACE , "wasted copy: %""ll" "d""[+%""ll" "d""] file=%p", pending_offset , file->page_size, file); } while (0) | |||||
175 | pending_offset, file->page_size, file)do { do { if (0) printf ("wasted copy: %""ll" "d""[+%""ll" "d" "] file=%p", pending_offset, file->page_size, file); } while (0); _gf_log (this->name, "page.c", __FUNCTION__, 175, GF_LOG_TRACE , "wasted copy: %""ll" "d""[+%""ll" "d""] file=%p", pending_offset , file->page_size, file); } while (0); | |||||
176 | goto unlock; | |||||
177 | } | |||||
178 | ||||||
179 | /* | |||||
180 | * "Dirty" means that the request was a pure read-ahead; it's | |||||
181 | * set for requests we issue ourselves, and cleared when user | |||||
182 | * requests are issued or put on the waitq. "Poisoned" means | |||||
183 | * that we got a write while a read was still in flight, and we | |||||
184 | * couldn't stop it so we marked it instead. If it's both | |||||
185 | * dirty and poisoned by the time we get here, we cancel its | |||||
186 | * effect so that a subsequent user read doesn't get data that | |||||
187 | * we know is stale (because we made it stale ourselves). We | |||||
188 | * can't use ESTALE because that has special significance. | |||||
189 | * ECANCELED has no such special meaning, and is close to what | |||||
190 | * we're trying to indicate. | |||||
191 | */ | |||||
192 | if (page->dirty && page->poisoned) { | |||||
193 | op_ret = -1; | |||||
194 | op_errno = ECANCELED125; | |||||
195 | } | |||||
196 | ||||||
197 | if (op_ret < 0) { | |||||
198 | waitq = ra_page_error (page, op_ret, op_errno); | |||||
199 | goto unlock; | |||||
200 | } | |||||
201 | ||||||
202 | if (page->vector) { | |||||
203 | iobref_unref (page->iobref); | |||||
204 | GF_FREE (page->vector)__gf_free (page->vector); | |||||
205 | } | |||||
206 | ||||||
207 | page->vector = iov_dup (vector, count); | |||||
208 | if (page->vector == NULL((void*)0)) { | |||||
209 | waitq = ra_page_error (page, -1, ENOMEM12); | |||||
210 | goto unlock; | |||||
211 | } | |||||
212 | ||||||
213 | page->count = count; | |||||
214 | page->iobref = iobref_ref (iobref); | |||||
215 | page->ready = 1; | |||||
216 | ||||||
217 | page->size = iov_length (vector, count); | |||||
218 | ||||||
219 | waitq = ra_page_wakeup (page); | |||||
220 | } | |||||
221 | unlock: | |||||
222 | ra_file_unlock (file); | |||||
223 | ||||||
224 | ra_waitq_return (waitq); | |||||
225 | ||||||
226 | fd_unref (local->fd); | |||||
227 | ||||||
228 | mem_put (frame->local); | |||||
229 | frame->local = NULL((void*)0); | |||||
230 | ||||||
231 | out: | |||||
232 | STACK_DESTROY (frame->root); | |||||
233 | return 0; | |||||
234 | } | |||||
235 | ||||||
236 | ||||||
237 | void | |||||
238 | ra_page_fault (ra_file_t *file, call_frame_t *frame, off_t offset) | |||||
239 | { | |||||
240 | call_frame_t *fault_frame = NULL((void*)0); | |||||
241 | ra_local_t *fault_local = NULL((void*)0); | |||||
242 | ra_page_t *page = NULL((void*)0); | |||||
243 | ra_waitq_t *waitq = NULL((void*)0); | |||||
244 | int32_t op_ret = -1, op_errno = -1; | |||||
245 | ||||||
246 | GF_VALIDATE_OR_GOTO ("read-ahead", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 246, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
247 | GF_VALIDATE_OR_GOTO (frame->this->name, file, out)do { if (!file) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "file"); } while (0); _gf_log_callingfn (frame->this->name, "page.c", __FUNCTION__, 247, GF_LOG_ERROR , "invalid argument: " "file"); } while (0); goto out; } } while (0); | |||||
248 | ||||||
249 | fault_frame = copy_frame (frame); | |||||
250 | if (fault_frame == NULL((void*)0)) { | |||||
251 | op_ret = -1; | |||||
252 | op_errno = ENOMEM12; | |||||
253 | goto err; | |||||
254 | } | |||||
255 | ||||||
256 | fault_local = mem_get0 (THIS(*__glusterfs_this_location())->local_pool); | |||||
257 | if (fault_local == NULL((void*)0)) { | |||||
258 | STACK_DESTROY (fault_frame->root); | |||||
259 | op_ret = -1; | |||||
260 | op_errno = ENOMEM12; | |||||
261 | goto err; | |||||
262 | } | |||||
263 | ||||||
264 | fault_frame->local = fault_local; | |||||
265 | fault_local->pending_offset = offset; | |||||
266 | fault_local->pending_size = file->page_size; | |||||
267 | ||||||
268 | fault_local->fd = fd_ref (file->fd); | |||||
269 | ||||||
270 | STACK_WIND (fault_frame, ra_fault_cbk,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__, 273 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ra_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 = "ra_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), file->fd, file->page_size, offset , 0, ((void*)0)); (*__glusterfs_this_location()) = old_THIS; } while (0) | |||||
271 | 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__, 273 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ra_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 = "ra_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), file->fd, file->page_size, offset , 0, ((void*)0)); (*__glusterfs_this_location()) = old_THIS; } while (0) | |||||
272 | FIRST_CHILD (fault_frame->this)->fops->readv,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__, 273 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ra_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 = "ra_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), file->fd, file->page_size, offset , 0, ((void*)0)); (*__glusterfs_this_location()) = old_THIS; } while (0) | |||||
273 | file->fd, file->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__, 273 , GF_LOG_ERROR, "alloc failed"); } while (0); break; } typeof ( (fault_frame->this->children->xlator)->fops-> readv_cbk) tmp_cbk = ra_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 = "ra_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), file->fd, file->page_size, offset , 0, ((void*)0)); (*__glusterfs_this_location()) = old_THIS; } while (0); | |||||
274 | ||||||
275 | return; | |||||
276 | ||||||
277 | err: | |||||
278 | ra_file_lock (file); | |||||
279 | { | |||||
280 | page = ra_page_get (file, offset); | |||||
281 | if (page) | |||||
282 | waitq = ra_page_error (page, op_ret, | |||||
283 | op_errno); | |||||
284 | } | |||||
285 | ra_file_unlock (file); | |||||
286 | ||||||
287 | if (waitq != NULL((void*)0)) { | |||||
288 | ra_waitq_return (waitq); | |||||
289 | } | |||||
290 | ||||||
291 | out: | |||||
292 | return; | |||||
293 | } | |||||
294 | ||||||
295 | ||||||
296 | void | |||||
297 | ra_frame_fill (ra_page_t *page, call_frame_t *frame) | |||||
298 | { | |||||
299 | ra_local_t *local = NULL((void*)0); | |||||
300 | ra_fill_t *fill = NULL((void*)0); | |||||
301 | off_t src_offset = 0; | |||||
302 | off_t dst_offset = 0; | |||||
303 | ssize_t copy_size = 0; | |||||
304 | ra_fill_t *new = NULL((void*)0); | |||||
305 | ||||||
306 | GF_VALIDATE_OR_GOTO ("read-ahead", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 306, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
307 | GF_VALIDATE_OR_GOTO (frame->this->name, page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn (frame->this->name, "page.c", __FUNCTION__, 307, GF_LOG_ERROR , "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
308 | ||||||
309 | local = frame->local; | |||||
310 | fill = &local->fill; | |||||
311 | ||||||
312 | if (local->op_ret != -1 && page->size) { | |||||
313 | if (local->offset > page->offset) | |||||
314 | src_offset = local->offset - page->offset; | |||||
315 | else | |||||
316 | dst_offset = page->offset - local->offset; | |||||
317 | ||||||
318 | copy_size = min (page->size - src_offset,((page->size - src_offset)<(local->size - dst_offset )?(page->size - src_offset):(local->size - dst_offset)) | |||||
319 | local->size - dst_offset)((page->size - src_offset)<(local->size - dst_offset )?(page->size - src_offset):(local->size - dst_offset)); | |||||
320 | ||||||
321 | if (copy_size < 0) { | |||||
322 | /* if page contains fewer bytes and the required offset | |||||
323 | is beyond the page size in the page */ | |||||
324 | copy_size = src_offset = 0; | |||||
325 | } | |||||
326 | ||||||
327 | fill = fill->next; | |||||
328 | while (fill != &local->fill) { | |||||
329 | if (fill->offset > page->offset) { | |||||
330 | break; | |||||
331 | } | |||||
332 | fill = fill->next; | |||||
333 | } | |||||
334 | ||||||
335 | new = GF_CALLOC (1, sizeof (*new), gf_ra_mt_ra_fill_t)__gf_calloc (1, sizeof (*new), gf_ra_mt_ra_fill_t); | |||||
336 | if (new == NULL((void*)0)) { | |||||
337 | local->op_ret = -1; | |||||
338 | local->op_errno = ENOMEM12; | |||||
339 | goto out; | |||||
340 | } | |||||
341 | ||||||
342 | new->offset = page->offset; | |||||
343 | new->size = copy_size; | |||||
344 | new->iobref = iobref_ref (page->iobref); | |||||
345 | new->count = iov_subset (page->vector, page->count, | |||||
346 | src_offset, src_offset+copy_size, | |||||
347 | NULL((void*)0)); | |||||
348 | new->vector = GF_CALLOC (new->count, sizeof (struct iovec),__gf_calloc (new->count, sizeof (struct iovec), gf_ra_mt_iovec ) | |||||
349 | gf_ra_mt_iovec)__gf_calloc (new->count, sizeof (struct iovec), gf_ra_mt_iovec ); | |||||
350 | if (new->vector == NULL((void*)0)) { | |||||
351 | local->op_ret = -1; | |||||
352 | local->op_errno = ENOMEM12; | |||||
353 | GF_FREE (new)__gf_free (new); | |||||
354 | goto out; | |||||
355 | } | |||||
356 | ||||||
357 | new->count = iov_subset (page->vector, page->count, | |||||
358 | src_offset, src_offset+copy_size, | |||||
359 | new->vector); | |||||
360 | ||||||
361 | new->next = fill; | |||||
362 | new->prev = new->next->prev; | |||||
363 | new->next->prev = new; | |||||
364 | new->prev->next = new; | |||||
365 | ||||||
366 | local->op_ret += copy_size; | |||||
367 | } | |||||
368 | ||||||
369 | out: | |||||
370 | return; | |||||
371 | } | |||||
372 | ||||||
373 | ||||||
374 | void | |||||
375 | ra_frame_unwind (call_frame_t *frame) | |||||
376 | { | |||||
377 | ra_local_t *local = NULL((void*)0); | |||||
378 | ra_fill_t *fill = NULL((void*)0); | |||||
379 | int32_t count = 0; | |||||
380 | struct iovec *vector = NULL((void*)0); | |||||
381 | int32_t copied = 0; | |||||
382 | struct iobref *iobref = NULL((void*)0); | |||||
383 | ra_fill_t *next = NULL((void*)0); | |||||
384 | fd_t *fd = NULL((void*)0); | |||||
385 | ra_file_t *file = NULL((void*)0); | |||||
386 | uint64_t tmp_file = 0; | |||||
387 | ||||||
388 | GF_VALIDATE_OR_GOTO ("read-ahead", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 388, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
389 | ||||||
390 | local = frame->local; | |||||
391 | fill = local->fill.next; | |||||
392 | ||||||
393 | iobref = iobref_new (); | |||||
394 | if (iobref == NULL((void*)0)) { | |||||
395 | local->op_ret = -1; | |||||
396 | local->op_errno = ENOMEM12; | |||||
397 | } | |||||
398 | ||||||
399 | frame->local = NULL((void*)0); | |||||
400 | ||||||
401 | while (fill != &local->fill) { | |||||
402 | count += fill->count; | |||||
403 | fill = fill->next; | |||||
404 | } | |||||
405 | ||||||
406 | vector = GF_CALLOC (count, sizeof (*vector), gf_ra_mt_iovec)__gf_calloc (count, sizeof (*vector), gf_ra_mt_iovec); | |||||
407 | if (vector == NULL((void*)0)) { | |||||
408 | local->op_ret = -1; | |||||
409 | local->op_errno = ENOMEM12; | |||||
410 | iobref_unref (iobref); | |||||
411 | iobref = NULL((void*)0); | |||||
412 | } | |||||
413 | ||||||
414 | fill = local->fill.next; | |||||
415 | ||||||
416 | while (fill != &local->fill) { | |||||
417 | next = fill->next; | |||||
418 | ||||||
419 | if ((vector != NULL((void*)0)) && (iobref != NULL((void*)0))) { | |||||
420 | memcpy (((char *)vector) + copied, fill->vector, | |||||
421 | fill->count * sizeof (*vector)); | |||||
422 | ||||||
423 | copied += (fill->count * sizeof (*vector)); | |||||
424 | iobref_merge (iobref, fill->iobref); | |||||
425 | } | |||||
426 | ||||||
427 | fill->next->prev = fill->prev; | |||||
428 | fill->prev->next = fill->prev; | |||||
429 | ||||||
430 | iobref_unref (fill->iobref); | |||||
431 | GF_FREE (fill->vector)__gf_free (fill->vector); | |||||
432 | GF_FREE (fill)__gf_free (fill); | |||||
433 | ||||||
434 | fill = next; | |||||
435 | } | |||||
436 | ||||||
437 | fd = local->fd; | |||||
438 | fd_ctx_get (fd, frame->this, &tmp_file); | |||||
439 | file = (ra_file_t *)(long)tmp_file; | |||||
440 | ||||||
441 | STACK_UNWIND_STRICT (readv, frame, local->op_ret, local->op_errno,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__, 442, 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, local ->op_ret, local->op_errno, vector, count, &file-> stbuf, iobref, ((void*)0)); (*__glusterfs_this_location()) = old_THIS ; } while (0) | |||||
442 | vector, count, &file->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__, 442, 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, local ->op_ret, local->op_errno, vector, count, &file-> stbuf, iobref, ((void*)0)); (*__glusterfs_this_location()) = old_THIS ; } while (0); | |||||
443 | ||||||
444 | iobref_unref (iobref); | |||||
445 | pthread_mutex_destroy (&local->local_lock); | |||||
446 | mem_put (local); | |||||
447 | GF_FREE (vector)__gf_free (vector); | |||||
448 | ||||||
449 | out: | |||||
450 | return; | |||||
451 | } | |||||
452 | ||||||
453 | /* | |||||
454 | * ra_frame_return - | |||||
455 | * @frame: | |||||
456 | * | |||||
457 | */ | |||||
458 | void | |||||
459 | ra_frame_return (call_frame_t *frame) | |||||
460 | { | |||||
461 | ra_local_t *local = NULL((void*)0); | |||||
462 | int32_t wait_count = 0; | |||||
463 | ||||||
464 | GF_VALIDATE_OR_GOTO ("read-ahead", frame, out)do { if (!frame) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "frame"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 464, GF_LOG_ERROR, "invalid argument: " "frame"); } while (0); goto out; } } while (0); | |||||
465 | ||||||
466 | local = frame->local; | |||||
467 | 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__, 467, GF_LOG_ERROR , "Assertion failed: " "local->wait_count > 0"); } while (0); } } while (0); | |||||
468 | ||||||
469 | ra_local_lock (local); | |||||
470 | { | |||||
471 | wait_count = --local->wait_count; | |||||
472 | } | |||||
473 | ra_local_unlock (local); | |||||
474 | ||||||
475 | if (!wait_count) | |||||
476 | ra_frame_unwind (frame); | |||||
477 | ||||||
478 | out: | |||||
479 | return; | |||||
480 | } | |||||
481 | ||||||
482 | /* | |||||
483 | * ra_page_wakeup - | |||||
484 | * @page: | |||||
485 | * | |||||
486 | */ | |||||
487 | ra_waitq_t * | |||||
488 | ra_page_wakeup (ra_page_t *page) | |||||
489 | { | |||||
490 | ra_waitq_t *waitq = NULL((void*)0), *trav = NULL((void*)0); | |||||
491 | call_frame_t *frame = NULL((void*)0); | |||||
492 | ||||||
493 | GF_VALIDATE_OR_GOTO ("read-ahead", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 493, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
494 | ||||||
495 | waitq = page->waitq; | |||||
496 | page->waitq = NULL((void*)0); | |||||
497 | ||||||
498 | for (trav = waitq; trav; trav = trav->next) { | |||||
499 | frame = trav->data; | |||||
500 | ra_frame_fill (page, frame); | |||||
501 | } | |||||
502 | ||||||
503 | if (page->stale) { | |||||
504 | ra_page_purge (page); | |||||
505 | } | |||||
506 | out: | |||||
507 | return waitq; | |||||
508 | } | |||||
509 | ||||||
510 | /* | |||||
511 | * ra_page_purge - | |||||
512 | * @page: | |||||
513 | * | |||||
514 | */ | |||||
515 | void | |||||
516 | ra_page_purge (ra_page_t *page) | |||||
517 | { | |||||
518 | GF_VALIDATE_OR_GOTO ("read-ahead", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 518, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
519 | ||||||
520 | page->prev->next = page->next; | |||||
521 | page->next->prev = page->prev; | |||||
522 | ||||||
523 | if (page->iobref) { | |||||
524 | iobref_unref (page->iobref); | |||||
525 | } | |||||
526 | ||||||
527 | GF_FREE (page->vector)__gf_free (page->vector); | |||||
528 | GF_FREE (page)__gf_free (page); | |||||
529 | ||||||
530 | out: | |||||
531 | return; | |||||
532 | } | |||||
533 | ||||||
534 | /* | |||||
535 | * ra_page_error - | |||||
536 | * @page: | |||||
537 | * @op_ret: | |||||
538 | * @op_errno: | |||||
539 | * | |||||
540 | */ | |||||
541 | ra_waitq_t * | |||||
542 | ra_page_error (ra_page_t *page, int32_t op_ret, int32_t op_errno) | |||||
543 | { | |||||
544 | ra_waitq_t *waitq = NULL((void*)0); | |||||
545 | ra_waitq_t *trav = NULL((void*)0); | |||||
546 | call_frame_t *frame = NULL((void*)0); | |||||
547 | ra_local_t *local = NULL((void*)0); | |||||
548 | ||||||
549 | GF_VALIDATE_OR_GOTO ("read-ahead", page, out)do { if (!page) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "page"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 549, GF_LOG_ERROR, "invalid argument: " "page"); } while (0); goto out; } } while (0); | |||||
550 | ||||||
551 | waitq = page->waitq; | |||||
552 | page->waitq = NULL((void*)0); | |||||
553 | ||||||
554 | for (trav = waitq; trav; trav = trav->next) { | |||||
555 | frame = trav->data; | |||||
556 | ||||||
557 | local = frame->local; | |||||
558 | if (local->op_ret != -1) { | |||||
559 | local->op_ret = op_ret; | |||||
560 | local->op_errno = op_errno; | |||||
561 | } | |||||
562 | } | |||||
563 | ||||||
564 | ra_page_purge (page); | |||||
565 | ||||||
566 | out: | |||||
567 | return waitq; | |||||
568 | } | |||||
569 | ||||||
570 | /* | |||||
571 | * ra_file_destroy - | |||||
572 | * @file: | |||||
573 | * | |||||
574 | */ | |||||
575 | void | |||||
576 | ra_file_destroy (ra_file_t *file) | |||||
577 | { | |||||
578 | ra_conf_t *conf = NULL((void*)0); | |||||
579 | ra_page_t *trav = NULL((void*)0); | |||||
580 | ||||||
581 | GF_VALIDATE_OR_GOTO ("read-ahead", file, out)do { if (!file) { (*__errno_location ()) = 22; do { do { if ( 0) printf ("invalid argument: " "file"); } while (0); _gf_log_callingfn ("read-ahead", "page.c", __FUNCTION__, 581, GF_LOG_ERROR, "invalid argument: " "file"); } while (0); goto out; } } while (0); | |||||
582 | ||||||
583 | conf = file->conf; | |||||
584 | ||||||
585 | ra_conf_lock (conf); | |||||
586 | { | |||||
587 | file->prev->next = file->next; | |||||
588 | file->next->prev = file->prev; | |||||
589 | } | |||||
590 | ra_conf_unlock (conf); | |||||
591 | ||||||
592 | trav = file->pages.next; | |||||
593 | while (trav != &file->pages) { | |||||
594 | ra_page_error (trav, -1, EINVAL22); | |||||
595 | trav = file->pages.next; | |||||
596 | } | |||||
597 | ||||||
598 | pthread_mutex_destroy (&file->file_lock); | |||||
599 | GF_FREE (file)__gf_free (file); | |||||
600 | ||||||
601 | out: | |||||
602 | return; | |||||
603 | } |