Bug Summary

File:xlators/mgmt/glusterd/src/glusterd-rebalance.c
Location:line 196, column 14
Description:Dereference of null pointer

Annotated Source Code

1/*
2 Copyright (c) 2010-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#ifndef _CONFIG_H
11#define _CONFIG_H
12#include "config.h"
13#endif
14
15#include <inttypes.h>
16#include <sys/types.h>
17#include <unistd.h>
18#include <sys/resource.h>
19#include <sys/statvfs.h>
20
21#include "globals.h"
22#include "compat.h"
23#include "protocol-common.h"
24#include "xlator.h"
25#include "logging.h"
26#include "timer.h"
27#include "glusterd-mem-types.h"
28#include "glusterd.h"
29#include "glusterd-sm.h"
30#include "glusterd-op-sm.h"
31#include "glusterd-utils.h"
32#include "glusterd-store.h"
33#include "run.h"
34#include "glusterd-volgen.h"
35
36#include "syscall.h"
37#include "cli1-xdr.h"
38#include "xdr-generic.h"
39
40int32_t
41glusterd_brick_op_cbk (struct rpc_req *req, struct iovec *iov,
42 int count, void *myframe);
43int
44glusterd_defrag_start_validate (glusterd_volinfo_t *volinfo, char *op_errstr,
45 size_t len)
46{
47 int ret = -1;
48
49 if (glusterd_is_defrag_on (volinfo)) {
50 gf_log ("glusterd", GF_LOG_DEBUG,do { do { if (0) printf ("rebalance on volume %s already started"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 52, GF_LOG_DEBUG, "rebalance on volume %s already started"
, volinfo->volname); } while (0)
51 "rebalance on volume %s already started",do { do { if (0) printf ("rebalance on volume %s already started"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 52, GF_LOG_DEBUG, "rebalance on volume %s already started"
, volinfo->volname); } while (0)
52 volinfo->volname)do { do { if (0) printf ("rebalance on volume %s already started"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 52, GF_LOG_DEBUG, "rebalance on volume %s already started"
, volinfo->volname); } while (0)
;
53 snprintf (op_errstr, len, "Rebalance on %s is already started",
54 volinfo->volname);
55 goto out;
56 }
57
58 if (glusterd_is_rb_started (volinfo) ||
59 glusterd_is_rb_paused (volinfo)) {
60 gf_log ("glusterd", GF_LOG_DEBUG,do { do { if (0) printf ("Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 62, GF_LOG_DEBUG, "Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0)
61 "Rebalance failed as replace brick is in progress on volume %s",do { do { if (0) printf ("Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 62, GF_LOG_DEBUG, "Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0)
62 volinfo->volname)do { do { if (0) printf ("Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 62, GF_LOG_DEBUG, "Rebalance failed as replace brick is in progress on volume %s"
, volinfo->volname); } while (0)
;
63 snprintf (op_errstr, len, "Rebalance failed as replace brick is in progress on "
64 "volume %s", volinfo->volname);
65 goto out;
66 }
67 ret = 0;
68out:
69 gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret)do { do { if (0) printf ("Returning %d", ret); } while (0); _gf_log
("glusterd", "glusterd-rebalance.c", __FUNCTION__, 69, GF_LOG_DEBUG
, "Returning %d", ret); } while (0)
;
70 return ret;
71}
72
73
74int32_t
75__glusterd_defrag_notify (struct rpc_clnt *rpc, void *mydata,
76 rpc_clnt_event_t event, void *data)
77{
78 glusterd_volinfo_t *volinfo = NULL((void*)0);
79 glusterd_defrag_info_t *defrag = NULL((void*)0);
80 int ret = 0;
81 char pidfile[PATH_MAX4096];
82 glusterd_conf_t *priv = NULL((void*)0);
83
84 priv = THIS(*__glusterfs_this_location())->private;
85 if (!priv)
86 return 0;
87
88 volinfo = mydata;
89 if (!volinfo)
90 return 0;
91
92 defrag = volinfo->rebal.defrag;
93 if (!defrag)
94 return 0;
95
96 if ((event == RPC_CLNT_DISCONNECT) && defrag->connected)
97 volinfo->rebal.defrag = NULL((void*)0);
98
99 GLUSTERD_GET_DEFRAG_PID_FILE(pidfile, volinfo, priv)do { char defrag_path[4096]; do { char vol_path[4096]; snprintf
(vol_path, 4096, "%s/vols/%s", priv->workdir, volinfo->
volname);; snprintf (defrag_path, 4096, "%s/rebalance",vol_path
); } while (0); snprintf (pidfile, 4096, "%s/%s.pid", defrag_path
, uuid_utoa((__glusterd_uuid()))); } while (0)
;
100
101 switch (event) {
102 case RPC_CLNT_CONNECT:
103 {
104 if (defrag->connected)
105 return 0;
106
107 LOCK (&defrag->lock)pthread_spin_lock (&defrag->lock);
108 {
109 defrag->connected = 1;
110 }
111 UNLOCK (&defrag->lock)pthread_spin_unlock (&defrag->lock);
112
113 gf_log ("", GF_LOG_DEBUG, "%s got RPC_CLNT_CONNECT",do { do { if (0) printf ("%s got RPC_CLNT_CONNECT", rpc->conn
.trans->name); } while (0); _gf_log ("", "glusterd-rebalance.c"
, __FUNCTION__, 114, GF_LOG_DEBUG, "%s got RPC_CLNT_CONNECT",
rpc->conn.trans->name); } while (0)
114 rpc->conn.trans->name)do { do { if (0) printf ("%s got RPC_CLNT_CONNECT", rpc->conn
.trans->name); } while (0); _gf_log ("", "glusterd-rebalance.c"
, __FUNCTION__, 114, GF_LOG_DEBUG, "%s got RPC_CLNT_CONNECT",
rpc->conn.trans->name); } while (0)
;
115 break;
116 }
117
118 case RPC_CLNT_DISCONNECT:
119 {
120 if (!defrag->connected)
121 return 0;
122
123 LOCK (&defrag->lock)pthread_spin_lock (&defrag->lock);
124 {
125 defrag->connected = 0;
126 }
127 UNLOCK (&defrag->lock)pthread_spin_unlock (&defrag->lock);
128
129 if (!glusterd_is_service_running (pidfile, NULL((void*)0))) {
130 if (volinfo->rebal.defrag_status ==
131 GF_DEFRAG_STATUS_STARTED) {
132 volinfo->rebal.defrag_status =
133 GF_DEFRAG_STATUS_FAILED;
134 } else {
135 volinfo->rebal.defrag_cmd = 0;
136 }
137 }
138
139 glusterd_store_perform_node_state_store (volinfo);
140
141 if (defrag->rpc) {
142 rpc_clnt_unref (defrag->rpc);
143 defrag->rpc = NULL((void*)0);
144 }
145 if (defrag->cbk_fn)
146 defrag->cbk_fn (volinfo,
147 volinfo->rebal.defrag_status);
148
149 GF_FREE (defrag)__gf_free (defrag);
150 gf_log ("", GF_LOG_DEBUG, "%s got RPC_CLNT_DISCONNECT",do { do { if (0) printf ("%s got RPC_CLNT_DISCONNECT", rpc->
conn.trans->name); } while (0); _gf_log ("", "glusterd-rebalance.c"
, __FUNCTION__, 151, GF_LOG_DEBUG, "%s got RPC_CLNT_DISCONNECT"
, rpc->conn.trans->name); } while (0)
151 rpc->conn.trans->name)do { do { if (0) printf ("%s got RPC_CLNT_DISCONNECT", rpc->
conn.trans->name); } while (0); _gf_log ("", "glusterd-rebalance.c"
, __FUNCTION__, 151, GF_LOG_DEBUG, "%s got RPC_CLNT_DISCONNECT"
, rpc->conn.trans->name); } while (0)
;
152 break;
153 }
154 default:
155 gf_log ("", GF_LOG_TRACE,do { do { if (0) printf ("got some other RPC event %d", event
); } while (0); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__
, 156, GF_LOG_TRACE, "got some other RPC event %d", event); }
while (0)
156 "got some other RPC event %d", event)do { do { if (0) printf ("got some other RPC event %d", event
); } while (0); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__
, 156, GF_LOG_TRACE, "got some other RPC event %d", event); }
while (0)
;
157 ret = 0;
158 break;
159 }
160
161 return ret;
162}
163
164int32_t
165glusterd_defrag_notify (struct rpc_clnt *rpc, void *mydata,
166 rpc_clnt_event_t event, void *data)
167{
168 return glusterd_big_locked_notify (rpc, mydata, event,
169 data, __glusterd_defrag_notify);
170}
171
172int
173glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr,
174 size_t len, int cmd, defrag_cbk_fn_t cbk,
175 glusterd_op_t op)
176{
177 int ret = -1;
178 glusterd_defrag_info_t *defrag = NULL((void*)0);
179 runner_t runner = {0,};
180 glusterd_conf_t *priv = NULL((void*)0);
181 char defrag_path[PATH_MAX4096];
182 char sockfile[PATH_MAX4096] = {0,};
183 char pidfile[PATH_MAX4096] = {0,};
184 char logfile[PATH_MAX4096] = {0,};
185 dict_t *options = NULL((void*)0);
186 char valgrind_logfile[PATH_MAX4096] = {0,};
187
188 priv = THIS(*__glusterfs_this_location())->private;
189
190 GF_ASSERT (volinfo)do { if (!(volinfo)) { do { do { if (0) printf ("Assertion failed: "
"volinfo"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 190, GF_LOG_ERROR, "Assertion failed: " "volinfo"
); } while (0); } } while (0)
;
1
Within the expansion of the macro 'GF_ASSERT':
a
Assuming 'volinfo' is null
191 GF_ASSERT (op_errstr)do { if (!(op_errstr)) { do { do { if (0) printf ("Assertion failed: "
"op_errstr"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 191, GF_LOG_ERROR, "Assertion failed: " "op_errstr"
); } while (0); } } while (0)
;
192
193 ret = glusterd_defrag_start_validate (volinfo, op_errstr, len);
194 if (ret)
2
Taking false branch
195 goto out;
196 if (!volinfo->rebal.defrag)
3
Dereference of null pointer
197 volinfo->rebal.defrag =
198 GF_CALLOC (1, sizeof (*volinfo->rebal.defrag),__gf_calloc (1, sizeof (*volinfo->rebal.defrag), gf_gld_mt_defrag_info
)
199 gf_gld_mt_defrag_info)__gf_calloc (1, sizeof (*volinfo->rebal.defrag), gf_gld_mt_defrag_info
)
;
200 if (!volinfo->rebal.defrag)
201 goto out;
202
203 defrag = volinfo->rebal.defrag;
204
205 defrag->cmd = cmd;
206
207 volinfo->rebal.op = op;
208
209 LOCK_INIT (&defrag->lock)pthread_spin_init (&defrag->lock, 0);
210
211 volinfo->rebal.defrag_status = GF_DEFRAG_STATUS_STARTED;
212
213 glusterd_volinfo_reset_defrag_stats (volinfo);
214 glusterd_store_perform_node_state_store (volinfo);
215
216 GLUSTERD_GET_DEFRAG_DIR (defrag_path, volinfo, priv)do { char vol_path[4096]; snprintf (vol_path, 4096, "%s/vols/%s"
, priv->workdir, volinfo->volname);; snprintf (defrag_path
, 4096, "%s/rebalance",vol_path); } while (0)
;
217 ret = mkdir_p (defrag_path, 0777, _gf_true);
218 if (ret) {
219 gf_log (THIS->name, GF_LOG_ERROR, "Failed to create "do { do { if (0) printf ("Failed to create " "directory %s", defrag_path
); } while (0); _gf_log ((*__glusterfs_this_location())->name
, "glusterd-rebalance.c", __FUNCTION__, 220, GF_LOG_ERROR, "Failed to create "
"directory %s", defrag_path); } while (0)
220 "directory %s", defrag_path)do { do { if (0) printf ("Failed to create " "directory %s", defrag_path
); } while (0); _gf_log ((*__glusterfs_this_location())->name
, "glusterd-rebalance.c", __FUNCTION__, 220, GF_LOG_ERROR, "Failed to create "
"directory %s", defrag_path); } while (0)
;
221 goto out;
222 }
223
224 GLUSTERD_GET_DEFRAG_SOCK_FILE (sockfile, volinfo, priv)do { char defrag_path[4096]; do { char vol_path[4096]; snprintf
(vol_path, 4096, "%s/vols/%s", priv->workdir, volinfo->
volname);; snprintf (defrag_path, 4096, "%s/rebalance",vol_path
); } while (0); snprintf (sockfile, 4096, "%s/%s.sock", defrag_path
, uuid_utoa((__glusterd_uuid()))); } while (0)
;
225 GLUSTERD_GET_DEFRAG_PID_FILE (pidfile, volinfo, priv)do { char defrag_path[4096]; do { char vol_path[4096]; snprintf
(vol_path, 4096, "%s/vols/%s", priv->workdir, volinfo->
volname);; snprintf (defrag_path, 4096, "%s/rebalance",vol_path
); } while (0); snprintf (pidfile, 4096, "%s/%s.pid", defrag_path
, uuid_utoa((__glusterd_uuid()))); } while (0)
;
226 snprintf (logfile, PATH_MAX4096, "%s/%s-rebalance.log",
227 DEFAULT_LOG_FILE_DIRECTORY"/usr/local/var" "/log/glusterfs", volinfo->volname);
228 runinit (&runner);
229
230 if (priv->valgrind) {
231 snprintf (valgrind_logfile, PATH_MAX4096,
232 "%s/valgrind-%s-rebalance.log",
233 DEFAULT_LOG_FILE_DIRECTORY"/usr/local/var" "/log/glusterfs",
234 volinfo->volname);
235
236 runner_add_args (&runner, "valgrind", "--leak-check=full",
237 "--trace-children=yes", "--track-origins=yes",
238 NULL((void*)0));
239 runner_argprintf (&runner, "--log-file=%s", valgrind_logfile);
240 }
241
242 runner_add_args (&runner, SBIN_DIR"/usr/local/sbin""/glusterfs",
243 "-s", "localhost", "--volfile-id", volinfo->volname,
244 "--xlator-option", "*dht.use-readdirp=yes",
245 "--xlator-option", "*dht.lookup-unhashed=yes",
246 "--xlator-option", "*dht.assert-no-child-down=yes",
247 "--xlator-option", "*replicate*.data-self-heal=off",
248 "--xlator-option",
249 "*replicate*.metadata-self-heal=off",
250 "--xlator-option", "*replicate*.entry-self-heal=off",
251 "--xlator-option", "*replicate*.readdir-failover=off",
252 "--xlator-option", "*dht.readdir-optimize=on",
253 NULL((void*)0));
254 runner_add_arg (&runner, "--xlator-option");
255 runner_argprintf ( &runner, "*dht.rebalance-cmd=%d",cmd);
256 runner_add_arg (&runner, "--xlator-option");
257 runner_argprintf (&runner, "*dht.node-uuid=%s", uuid_utoa(MY_UUID(__glusterd_uuid())));
258 runner_add_arg (&runner, "--socket-file");
259 runner_argprintf (&runner, "%s",sockfile);
260 runner_add_arg (&runner, "--pid-file");
261 runner_argprintf (&runner, "%s",pidfile);
262 runner_add_arg (&runner, "-l");
263 runner_argprintf (&runner, logfile);
264 if (volinfo->memory_accounting)
265 runner_add_arg (&runner, "--mem-accounting");
266
267 ret = runner_run_nowait (&runner);
268 if (ret) {
269 gf_log ("glusterd", GF_LOG_DEBUG, "rebalance command failed")do { do { if (0) printf ("rebalance command failed"); } while
(0); _gf_log ("glusterd", "glusterd-rebalance.c", __FUNCTION__
, 269, GF_LOG_DEBUG, "rebalance command failed"); } while (0)
;
270 goto out;
271 }
272
273 sleep (5);
274
275 /* Setting frame-timeout to 10mins (600seconds).
276 * Unix domain sockets ensures that the connection is reliable. The
277 * default timeout of 30mins used for unreliable network connections is
278 * too long for unix domain socket connections.
279 */
280 ret = rpc_clnt_transport_unix_options_build (&options, sockfile, 600);
281 if (ret) {
282 gf_log (THIS->name, GF_LOG_ERROR, "Unix options build failed")do { do { if (0) printf ("Unix options build failed"); } while
(0); _gf_log ((*__glusterfs_this_location())->name, "glusterd-rebalance.c"
, __FUNCTION__, 282, GF_LOG_ERROR, "Unix options build failed"
); } while (0)
;
283 goto out;
284 }
285
286 synclock_unlock (&priv->big_lock);
287 ret = glusterd_rpc_create (&defrag->rpc, options,
288 glusterd_defrag_notify, volinfo);
289 synclock_lock (&priv->big_lock);
290 if (ret) {
291 gf_log (THIS->name, GF_LOG_ERROR, "RPC create failed")do { do { if (0) printf ("RPC create failed"); } while (0); _gf_log
((*__glusterfs_this_location())->name, "glusterd-rebalance.c"
, __FUNCTION__, 291, GF_LOG_ERROR, "RPC create failed"); } while
(0)
;
292 goto out;
293 }
294
295 if (cbk)
296 defrag->cbk_fn = cbk;
297
298out:
299 gf_log ("", GF_LOG_DEBUG, "Returning %d", ret)do { do { if (0) printf ("Returning %d", ret); } while (0); _gf_log
("", "glusterd-rebalance.c", __FUNCTION__, 299, GF_LOG_DEBUG
, "Returning %d", ret); } while (0)
;
300 return ret;
301}
302
303
304int
305glusterd_rebalance_rpc_create (glusterd_volinfo_t *volinfo,
306 glusterd_conf_t *priv, int cmd)
307{
308 dict_t *options = NULL((void*)0);
309 char sockfile[PATH_MAX4096] = {0,};
310 int ret = -1;
311 glusterd_defrag_info_t *defrag = NULL((void*)0);
312
313 if (!volinfo->rebal.defrag)
314 volinfo->rebal.defrag =
315 GF_CALLOC (1, sizeof (*volinfo->rebal.defrag),__gf_calloc (1, sizeof (*volinfo->rebal.defrag), gf_gld_mt_defrag_info
)
316 gf_gld_mt_defrag_info)__gf_calloc (1, sizeof (*volinfo->rebal.defrag), gf_gld_mt_defrag_info
)
;
317
318 if (!volinfo->rebal.defrag)
319 goto out;
320
321 defrag = volinfo->rebal.defrag;
322
323 defrag->cmd = cmd;
324
325 LOCK_INIT (&defrag->lock)pthread_spin_init (&defrag->lock, 0);
326
327 GLUSTERD_GET_DEFRAG_SOCK_FILE (sockfile, volinfo, priv)do { char defrag_path[4096]; do { char vol_path[4096]; snprintf
(vol_path, 4096, "%s/vols/%s", priv->workdir, volinfo->
volname);; snprintf (defrag_path, 4096, "%s/rebalance",vol_path
); } while (0); snprintf (sockfile, 4096, "%s/%s.sock", defrag_path
, uuid_utoa((__glusterd_uuid()))); } while (0)
;
328
329 /* Setting frame-timeout to 10mins (600seconds).
330 * Unix domain sockets ensures that the connection is reliable. The
331 * default timeout of 30mins used for unreliable network connections is
332 * too long for unix domain socket connections.
333 */
334 ret = rpc_clnt_transport_unix_options_build (&options, sockfile, 600);
335 if (ret) {
336 gf_log (THIS->name, GF_LOG_ERROR, "Unix options build failed")do { do { if (0) printf ("Unix options build failed"); } while
(0); _gf_log ((*__glusterfs_this_location())->name, "glusterd-rebalance.c"
, __FUNCTION__, 336, GF_LOG_ERROR, "Unix options build failed"
); } while (0)
;
337 goto out;
338 }
339
340 synclock_unlock (&priv->big_lock);
341 ret = glusterd_rpc_create (&defrag->rpc, options,
342 glusterd_defrag_notify, volinfo);
343 synclock_lock (&priv->big_lock);
344 if (ret) {
345 gf_log (THIS->name, GF_LOG_ERROR, "RPC create failed")do { do { if (0) printf ("RPC create failed"); } while (0); _gf_log
((*__glusterfs_this_location())->name, "glusterd-rebalance.c"
, __FUNCTION__, 345, GF_LOG_ERROR, "RPC create failed"); } while
(0)
;
346 goto out;
347 }
348 ret = 0;
349out:
350 return ret;
351}
352
353int
354glusterd_rebalance_cmd_validate (int cmd, char *volname,
355 glusterd_volinfo_t **volinfo,
356 char *op_errstr, size_t len)
357{
358 int ret = -1;
359
360 if (glusterd_volinfo_find(volname, volinfo)) {
361 gf_log ("glusterd", GF_LOG_ERROR, "Received rebalance on invalid"do { do { if (0) printf ("Received rebalance on invalid" " volname %s"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 362, GF_LOG_ERROR, "Received rebalance on invalid"
" volname %s", volname); } while (0)
362 " volname %s", volname)do { do { if (0) printf ("Received rebalance on invalid" " volname %s"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 362, GF_LOG_ERROR, "Received rebalance on invalid"
" volname %s", volname); } while (0)
;
363 snprintf (op_errstr, len, "Volume %s does not exist",
364 volname);
365 goto out;
366 }
367 if ((*volinfo)->brick_count <= (*volinfo)->dist_leaf_count) {
368 gf_log ("glusterd", GF_LOG_ERROR, "Volume %s is not a "do { do { if (0) printf ("Volume %s is not a " "distribute type or contains only 1 brick"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 369, GF_LOG_ERROR, "Volume %s is not a " "distribute type or contains only 1 brick"
, volname); } while (0)
369 "distribute type or contains only 1 brick", volname)do { do { if (0) printf ("Volume %s is not a " "distribute type or contains only 1 brick"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 369, GF_LOG_ERROR, "Volume %s is not a " "distribute type or contains only 1 brick"
, volname); } while (0)
;
370 snprintf (op_errstr, len, "Volume %s is not a distribute "
371 "volume or contains only 1 brick.\n"
372 "Not performing rebalance", volname);
373 goto out;
374 }
375
376 if ((*volinfo)->status != GLUSTERD_STATUS_STARTED) {
377 gf_log ("glusterd", GF_LOG_ERROR, "Received rebalance on stopped"do { do { if (0) printf ("Received rebalance on stopped" " volname %s"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 378, GF_LOG_ERROR, "Received rebalance on stopped"
" volname %s", volname); } while (0)
378 " volname %s", volname)do { do { if (0) printf ("Received rebalance on stopped" " volname %s"
, volname); } while (0); _gf_log ("glusterd", "glusterd-rebalance.c"
, __FUNCTION__, 378, GF_LOG_ERROR, "Received rebalance on stopped"
" volname %s", volname); } while (0)
;
379 snprintf (op_errstr, len, "Volume %s needs to "
380 "be started to perform rebalance", volname);
381 goto out;
382 }
383
384 ret = 0;
385
386out:
387 gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret)do { do { if (0) printf ("Returning %d", ret); } while (0); _gf_log
("glusterd", "glusterd-rebalance.c", __FUNCTION__, 387, GF_LOG_DEBUG
, "Returning %d", ret); } while (0)
;
388 return ret;
389}
390
391int
392__glusterd_handle_defrag_volume (rpcsvc_request_t *req)
393{
394 int32_t ret = -1;
395 gf_cli_req cli_req = {{0,}};
396 glusterd_conf_t *priv = NULL((void*)0);
397 dict_t *dict = NULL((void*)0);
398 char *volname = NULL((void*)0);
399 gf_cli_defrag_type cmd = 0;
400 char msg[2048] = {0,};
401 xlator_t *this = NULL((void*)0);
402
403 GF_ASSERT (req)do { if (!(req)) { do { do { if (0) printf ("Assertion failed: "
"req"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 403, GF_LOG_ERROR, "Assertion failed: " "req"
); } while (0); } } while (0)
;
404 this = THIS(*__glusterfs_this_location());
405 GF_ASSERT (this)do { if (!(this)) { do { do { if (0) printf ("Assertion failed: "
"this"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 405, GF_LOG_ERROR, "Assertion failed: " "this"
); } while (0); } } while (0)
;
406
407 priv = this->private;
408 GF_ASSERT (priv)do { if (!(priv)) { do { do { if (0) printf ("Assertion failed: "
"priv"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 408, GF_LOG_ERROR, "Assertion failed: " "priv"
); } while (0); } } while (0)
;
409
410 ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
411 if (ret < 0) {
412 //failed to decode msg;
413 req->rpc_err = GARBAGE_ARGS;
414 goto out;
415 }
416
417 if (cli_req.dict.dict_len) {
418 /* Unserialize the dictionary */
419 dict = dict_new ();
420
421 ret = dict_unserialize (cli_req.dict.dict_val,
422 cli_req.dict.dict_len,
423 &dict);
424 if (ret < 0) {
425 gf_log (this->name, GF_LOG_ERROR, "failed to "do { do { if (0) printf ("failed to " "unserialize req-buffer to dictionary"
); } while (0); _gf_log (this->name, "glusterd-rebalance.c"
, __FUNCTION__, 426, GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"
); } while (0)
426 "unserialize req-buffer to dictionary")do { do { if (0) printf ("failed to " "unserialize req-buffer to dictionary"
); } while (0); _gf_log (this->name, "glusterd-rebalance.c"
, __FUNCTION__, 426, GF_LOG_ERROR, "failed to " "unserialize req-buffer to dictionary"
); } while (0)
;
427 snprintf (msg, sizeof (msg), "Unable to decode the "
428 "command");
429 goto out;
430 }
431 }
432
433 ret = dict_get_str (dict, "volname", &volname);
434 if (ret) {
435 snprintf (msg, sizeof (msg), "Failed to get volume name");
436 gf_log (this->name, GF_LOG_ERROR, "%s", msg)do { do { if (0) printf ("%s", msg); } while (0); _gf_log (this
->name, "glusterd-rebalance.c", __FUNCTION__, 436, GF_LOG_ERROR
, "%s", msg); } while (0)
;
437 goto out;
438 }
439
440 ret = dict_get_int32 (dict, "rebalance-command", (int32_t*)&cmd);
441 if (ret) {
442 snprintf (msg, sizeof (msg), "Failed to get command");
443 gf_log (this->name, GF_LOG_ERROR, "%s", msg)do { do { if (0) printf ("%s", msg); } while (0); _gf_log (this
->name, "glusterd-rebalance.c", __FUNCTION__, 443, GF_LOG_ERROR
, "%s", msg); } while (0)
;
444 goto out;
445 }
446
447 ret = dict_set_static_bin (dict, "node-uuid", MY_UUID(__glusterd_uuid()), 16);
448 if (ret)
449 goto out;
450
451 if ((cmd == GF_DEFRAG_CMD_STATUS) ||
452 (cmd == GF_DEFRAG_CMD_STOP)) {
453 ret = glusterd_op_begin (req, GD_OP_DEFRAG_BRICK_VOLUME,
454 dict, msg, sizeof (msg));
455 } else
456 ret = glusterd_op_begin (req, GD_OP_REBALANCE, dict,
457 msg, sizeof (msg));
458
459out:
460
461 glusterd_friend_sm ();
462 glusterd_op_sm ();
463
464 if (ret) {
465 if (msg[0] == '\0')
466 snprintf (msg, sizeof (msg), "Operation failed");
467 ret = glusterd_op_send_cli_response (GD_OP_REBALANCE, ret, 0,
468 req, dict, msg);
469
470 }
471
472 free (cli_req.dict.dict_val);//malloced by xdr
473
474 return 0;
475}
476
477int
478glusterd_handle_defrag_volume (rpcsvc_request_t *req)
479{
480 return glusterd_big_locked_handler (req, __glusterd_handle_defrag_volume);
481}
482
483
484int
485glusterd_op_stage_rebalance (dict_t *dict, char **op_errstr)
486{
487 char *volname = NULL((void*)0);
488 int ret = 0;
489 int32_t cmd = 0;
490 char msg[2048] = {0};
491 glusterd_volinfo_t *volinfo = NULL((void*)0);
492 char *task_id_str = NULL((void*)0);
493 dict_t *op_ctx = NULL((void*)0);
494 xlator_t *this = 0;
495
496 this = THIS(*__glusterfs_this_location());
497 GF_ASSERT (this)do { if (!(this)) { do { do { if (0) printf ("Assertion failed: "
"this"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 497, GF_LOG_ERROR, "Assertion failed: " "this"
); } while (0); } } while (0)
;
498
499 ret = dict_get_str (dict, "volname", &volname);
500 if (ret) {
501 gf_log (this->name, GF_LOG_DEBUG, "volname not found")do { do { if (0) printf ("volname not found"); } while (0); _gf_log
(this->name, "glusterd-rebalance.c", __FUNCTION__, 501, GF_LOG_DEBUG
, "volname not found"); } while (0)
;
502 goto out;
503 }
504
505 ret = dict_get_int32 (dict, "rebalance-command", &cmd);
506 if (ret) {
507 gf_log (this->name, GF_LOG_DEBUG, "cmd not found")do { do { if (0) printf ("cmd not found"); } while (0); _gf_log
(this->name, "glusterd-rebalance.c", __FUNCTION__, 507, GF_LOG_DEBUG
, "cmd not found"); } while (0)
;
508 goto out;
509 }
510
511 ret = glusterd_rebalance_cmd_validate (cmd, volname, &volinfo,
512 msg, sizeof (msg));
513 if (ret) {
514 gf_log (this->name, GF_LOG_DEBUG, "failed to validate")do { do { if (0) printf ("failed to validate"); } while (0); _gf_log
(this->name, "glusterd-rebalance.c", __FUNCTION__, 514, GF_LOG_DEBUG
, "failed to validate"); } while (0)
;
515 goto out;
516 }
517 switch (cmd) {
518 case GF_DEFRAG_CMD_START:
519 case GF_DEFRAG_CMD_START_LAYOUT_FIX:
520 case GF_DEFRAG_CMD_START_FORCE:
521 if (is_origin_glusterd ()) {
522 op_ctx = glusterd_op_get_ctx ();
523 if (!op_ctx) {
524 ret = -1;
525 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Failed to get op_ctx"); } while (0)
; _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 526, GF_LOG_ERROR, "Failed to get op_ctx"); } while (0)
526 "Failed to get op_ctx")do { do { if (0) printf ("Failed to get op_ctx"); } while (0)
; _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 526, GF_LOG_ERROR, "Failed to get op_ctx"); } while (0)
;
527 goto out;
528 }
529
530 ret = glusterd_generate_and_set_task_id
531 (op_ctx, GF_REBALANCE_TID_KEY"rebalance-id");
532 if (ret) {
533 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Failed to generate task-id"); } while
(0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 534, GF_LOG_ERROR, "Failed to generate task-id"); } while (
0)
534 "Failed to generate task-id")do { do { if (0) printf ("Failed to generate task-id"); } while
(0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 534, GF_LOG_ERROR, "Failed to generate task-id"); } while (
0)
;
535 goto out;
536 }
537 } else {
538 ret = dict_get_str (dict, GF_REBALANCE_TID_KEY"rebalance-id",
539 &task_id_str);
540 if (ret) {
541 snprintf (msg, sizeof (msg),
542 "Missing rebalance-id");
543 gf_log (this->name, GF_LOG_WARNING, "%s", msg)do { do { if (0) printf ("%s", msg); } while (0); _gf_log (this
->name, "glusterd-rebalance.c", __FUNCTION__, 543, GF_LOG_WARNING
, "%s", msg); } while (0)
;
544 ret = 0;
545 }
546 }
547 ret = glusterd_defrag_start_validate (volinfo,
548 msg, sizeof (msg));
549 if (ret) {
550 gf_log (this->name, GF_LOG_DEBUG,do { do { if (0) printf ("start validate failed"); } while (0
); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 551, GF_LOG_DEBUG, "start validate failed"); } while (0)
551 "start validate failed")do { do { if (0) printf ("start validate failed"); } while (0
); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 551, GF_LOG_DEBUG, "start validate failed"); } while (0)
;
552 goto out;
553 }
554 break;
555 case GF_DEFRAG_CMD_STATUS:
556 case GF_DEFRAG_CMD_STOP:
557 break;
558 default:
559 break;
560 }
561
562 ret = 0;
563out:
564 if (ret && op_errstr && msg[0])
565 *op_errstr = gf_strdup (msg);
566
567 return ret;
568}
569
570
571int
572glusterd_op_rebalance (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
573{
574 char *volname = NULL((void*)0);
575 int ret = 0;
576 int32_t cmd = 0;
577 char msg[2048] = {0};
578 glusterd_volinfo_t *volinfo = NULL((void*)0);
579 glusterd_conf_t *priv = NULL((void*)0);
580 glusterd_brickinfo_t *brickinfo = NULL((void*)0);
581 glusterd_brickinfo_t *tmp = NULL((void*)0);
582 gf_boolean_t volfile_update = _gf_false;
583 char *task_id_str = NULL((void*)0);
584 dict_t *ctx = NULL((void*)0);
585 xlator_t *this = NULL((void*)0);
586
587 this = THIS(*__glusterfs_this_location());
588 GF_ASSERT (this)do { if (!(this)) { do { do { if (0) printf ("Assertion failed: "
"this"); } while (0); _gf_log_callingfn ("", "glusterd-rebalance.c"
, __FUNCTION__, 588, GF_LOG_ERROR, "Assertion failed: " "this"
); } while (0); } } while (0)
;
589 priv = this->private;
590
591 ret = dict_get_str (dict, "volname", &volname);
592 if (ret) {
593 gf_log (this->name, GF_LOG_DEBUG, "volname not given")do { do { if (0) printf ("volname not given"); } while (0); _gf_log
(this->name, "glusterd-rebalance.c", __FUNCTION__, 593, GF_LOG_DEBUG
, "volname not given"); } while (0)
;
594 goto out;
595 }
596
597 ret = dict_get_int32 (dict, "rebalance-command", &cmd);
598 if (ret) {
599 gf_log (this->name, GF_LOG_DEBUG, "command not given")do { do { if (0) printf ("command not given"); } while (0); _gf_log
(this->name, "glusterd-rebalance.c", __FUNCTION__, 599, GF_LOG_DEBUG
, "command not given"); } while (0)
;
600 goto out;
601 }
602
603
604 ret = glusterd_rebalance_cmd_validate (cmd, volname, &volinfo,
605 msg, sizeof (msg));
606 if (ret) {
607 gf_log (this->name, GF_LOG_DEBUG, "cmd validate failed")do { do { if (0) printf ("cmd validate failed"); } while (0);
_gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 607, GF_LOG_DEBUG, "cmd validate failed"); } while (0)
;
608 goto out;
609 }
610
611 /* Set task-id, if available, in op_ctx dict for operations other than
612 * start
613 */
614 if (cmd == GF_DEFRAG_CMD_STATUS || cmd == GF_DEFRAG_CMD_STOP) {
615 if (!uuid_is_null (volinfo->rebal.rebalance_id)) {
616 ctx = glusterd_op_get_ctx ();
617 if (!ctx) {
618 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Failed to get op_ctx"); } while (0)
; _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 619, GF_LOG_ERROR, "Failed to get op_ctx"); } while (0)
619 "Failed to get op_ctx")do { do { if (0) printf ("Failed to get op_ctx"); } while (0)
; _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 619, GF_LOG_ERROR, "Failed to get op_ctx"); } while (0)
;
620 ret = -1;
621 goto out;
622 }
623
624 if (GD_OP_REMOVE_BRICK == volinfo->rebal.op)
625 ret = glusterd_copy_uuid_to_dict
626 (volinfo->rebal.rebalance_id, ctx,
627 GF_REMOVE_BRICK_TID_KEY"remove-brick-id");
628 else
629 ret = glusterd_copy_uuid_to_dict
630 (volinfo->rebal.rebalance_id, ctx,
631 GF_REBALANCE_TID_KEY"rebalance-id");
632 if (ret) {
633 gf_log (this->name, GF_LOG_ERROR,do { do { if (0) printf ("Failed to set task-id"); } while (0
); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 634, GF_LOG_ERROR, "Failed to set task-id"); } while (0)
634 "Failed to set task-id")do { do { if (0) printf ("Failed to set task-id"); } while (0
); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 634, GF_LOG_ERROR, "Failed to set task-id"); } while (0)
;
635 goto out;
636 }
637 }
638 }
639
640 switch (cmd) {
641 case GF_DEFRAG_CMD_START:
642 case GF_DEFRAG_CMD_START_LAYOUT_FIX:
643 case GF_DEFRAG_CMD_START_FORCE:
644 ret = dict_get_str (dict, GF_REBALANCE_TID_KEY"rebalance-id", &task_id_str);
645 if (ret) {
646 gf_log (this->name, GF_LOG_DEBUG, "Missing rebalance "do { do { if (0) printf ("Missing rebalance " "id"); } while (
0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 647, GF_LOG_DEBUG, "Missing rebalance " "id"); } while (0)
647 "id")do { do { if (0) printf ("Missing rebalance " "id"); } while (
0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 647, GF_LOG_DEBUG, "Missing rebalance " "id"); } while (0)
;
648 ret = 0;
649 } else {
650 uuid_parse (task_id_str, volinfo->rebal.rebalance_id) ;
651 }
652 ret = glusterd_handle_defrag_start (volinfo, msg, sizeof (msg),
653 cmd, NULL((void*)0), GD_OP_REBALANCE);
654 break;
655 case GF_DEFRAG_CMD_STOP:
656 /* Clear task-id only on explicitly stopping the
657 * rebalance process.
658 */
659 uuid_clear (volinfo->rebal.rebalance_id);
660
661 /* Fall back to the old volume file in case of decommission*/
662 list_for_each_entry_safe (brickinfo, tmp, &volinfo->bricks,for (brickinfo = ((typeof(*brickinfo) *)((char *)((&volinfo
->bricks)->next)-(unsigned long)(&((typeof(*brickinfo
) *)0)->brick_list))), tmp = ((typeof(*brickinfo) *)((char
*)(brickinfo->brick_list.next)-(unsigned long)(&((typeof
(*brickinfo) *)0)->brick_list))); &brickinfo->brick_list
!= (&volinfo->bricks); brickinfo = tmp, tmp = ((typeof
(*tmp) *)((char *)(tmp->brick_list.next)-(unsigned long)(&
((typeof(*tmp) *)0)->brick_list))))
663 brick_list)for (brickinfo = ((typeof(*brickinfo) *)((char *)((&volinfo
->bricks)->next)-(unsigned long)(&((typeof(*brickinfo
) *)0)->brick_list))), tmp = ((typeof(*brickinfo) *)((char
*)(brickinfo->brick_list.next)-(unsigned long)(&((typeof
(*brickinfo) *)0)->brick_list))); &brickinfo->brick_list
!= (&volinfo->bricks); brickinfo = tmp, tmp = ((typeof
(*tmp) *)((char *)(tmp->brick_list.next)-(unsigned long)(&
((typeof(*tmp) *)0)->brick_list))))
{
664 if (!brickinfo->decommissioned)
665 continue;
666 brickinfo->decommissioned = 0;
667 volfile_update = _gf_true;
668 }
669
670 if (volfile_update == _gf_false) {
671 ret = 0;
672 break;
673 }
674
675 ret = glusterd_create_volfiles_and_notify_services (volinfo);
676 if (ret) {
677 gf_log (this->name, GF_LOG_WARNING,do { do { if (0) printf ("failed to create volfiles"); } while
(0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 678, GF_LOG_WARNING, "failed to create volfiles"); } while (
0)
678 "failed to create volfiles")do { do { if (0) printf ("failed to create volfiles"); } while
(0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 678, GF_LOG_WARNING, "failed to create volfiles"); } while (
0)
;
679 goto out;
680 }
681
682 ret = glusterd_store_volinfo (volinfo,
683 GLUSTERD_VOLINFO_VER_AC_INCREMENT);
684 if (ret) {
685 gf_log (this->name, GF_LOG_WARNING,do { do { if (0) printf ("failed to store volinfo"); } while (
0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 686, GF_LOG_WARNING, "failed to store volinfo"); } while (0
)
686 "failed to store volinfo")do { do { if (0) printf ("failed to store volinfo"); } while (
0); _gf_log (this->name, "glusterd-rebalance.c", __FUNCTION__
, 686, GF_LOG_WARNING, "failed to store volinfo"); } while (0
)
;
687 goto out;
688 }
689
690 ret = 0;
691 break;
692
693 case GF_DEFRAG_CMD_STATUS:
694 break;
695 default:
696 break;
697 }
698
699out:
700 if (ret && op_errstr && msg[0])
701 *op_errstr = gf_strdup (msg);
702
703 return ret;
704}
705
706int32_t
707glusterd_defrag_event_notify_handle (dict_t *dict)
708{
709 glusterd_volinfo_t *volinfo = NULL((void*)0);
710 char *volname = NULL((void*)0);
711 int32_t ret = -1;
712
713 ret = dict_get_str (dict, "volname", &volname);
714 if (ret) {
715 gf_log ("", GF_LOG_ERROR, "Failed to get volname")do { do { if (0) printf ("Failed to get volname"); } while (0
); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__, 715, GF_LOG_ERROR
, "Failed to get volname"); } while (0)
;
716 return ret;
717 }
718
719 ret = glusterd_volinfo_find (volname, &volinfo);
720 if (ret) {
721 gf_log ("", GF_LOG_ERROR, "Failed to get volinfo for %s"do { do { if (0) printf ("Failed to get volinfo for %s" , volname
); } while (0); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__
, 722, GF_LOG_ERROR, "Failed to get volinfo for %s" , volname
); } while (0)
722 , volname)do { do { if (0) printf ("Failed to get volinfo for %s" , volname
); } while (0); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__
, 722, GF_LOG_ERROR, "Failed to get volinfo for %s" , volname
); } while (0)
;
723 return ret;
724 }
725
726 ret = glusterd_defrag_volume_status_update (volinfo, dict);
727
728 if (ret)
729 gf_log ("", GF_LOG_ERROR, "Failed to update status")do { do { if (0) printf ("Failed to update status"); } while (
0); _gf_log ("", "glusterd-rebalance.c", __FUNCTION__, 729, GF_LOG_ERROR
, "Failed to update status"); } while (0)
;
730 return ret;
731}