[FIX] clean up when error
[kernel/swap-modules.git] / parser / msg_parser.c
1 /*
2  *  SWAP Parser
3  *  modules/parser/msg_parser.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Vyacheslav Cherkashin, Vitaliy Cherepanov: SWAP Parser implement
22  *
23  */
24
25
26 #include <linux/slab.h>
27 #include "msg_parser.h"
28 #include "msg_buf.h"
29 #include "parser_defs.h"
30
31
32 static int str_to_u32(const char* str, u32 *val)
33 {
34         u32 result;
35         if(!str || !*str)
36                 return -EINVAL;
37
38         for (result = 0 ; *str; ++str) {
39                 if (*str < '0' || *str> '9')
40                         return -EINVAL;
41
42                 result = result * 10 + (*str - '0');
43         }
44
45         *val = result;
46
47         return 0;
48 }
49
50
51
52
53
54 /* ============================================================================
55  * ==                               APP_INFO                                 ==
56  * ============================================================================
57  */
58 struct app_info_data *create_app_info(struct msg_buf *mb)
59 {
60         int ret;
61         struct app_info_data *ai;
62         u32 app_type;
63         char *ta_id, *exec_path;
64
65         print_parse_debug("app_info:\n");
66
67         print_parse_debug("type:");
68         ret = get_u32(mb, &app_type);
69         if (ret) {
70                 print_err("failed to read target application type\n");
71                 return NULL;
72         }
73
74         print_parse_debug("id:");
75         ret = get_string(mb, &ta_id);
76         if (ret) {
77                 print_err("failed to read target application ID\n");
78                 return NULL;
79         }
80
81         print_parse_debug("exec path:");
82         ret = get_string(mb, &exec_path);
83         if (ret) {
84                 print_err("failed to read executable path\n");
85                 goto free_ta_id;
86         }
87
88         ai = kmalloc(sizeof(*ai), GFP_KERNEL);
89         if (ai == NULL) {
90                 print_err("out of memory\n");
91                 goto free_exec_path;
92         }
93
94         switch (app_type) {
95         case AT_TIZEN_NATIVE_APP:
96         case AT_COMMON_EXEC:
97                 ai->tgid = 0;
98                 break;
99         case AT_PID: {
100                 u32 tgid;
101                 ret = str_to_u32(ta_id, &tgid);
102                 if (ret) {
103                         print_err("converting string to PID, str='%s'\n", ta_id);
104                         goto free_ai;
105                 }
106
107                 ai->tgid = tgid;
108                 break;
109         }
110         default:
111                 print_err("wrong application type(%u)\n", app_type);
112                 ret = -EINVAL;
113                 goto free_ai;
114         }
115
116         ai->app_type = (enum APP_TYPE)app_type;
117         ai->exec_path = exec_path;
118
119         put_string(ta_id);
120
121         return ai;
122
123 free_ai:
124         kfree(ai);
125
126 free_exec_path:
127         put_string(exec_path);
128
129 free_ta_id:
130         put_string(ta_id);
131
132         return NULL;
133 }
134
135 void destroy_app_info(struct app_info_data *ai)
136 {
137         put_string(ai->exec_path);
138         kfree(ai);
139 }
140
141
142
143
144
145 /* ============================================================================
146  * ==                                CONFIG                                  ==
147  * ============================================================================
148  */
149 struct conf_data *create_conf_data(struct msg_buf *mb)
150 {
151         struct conf_data *conf;
152         u64 use_features0, use_features1;
153         u32 stp, dmp;
154
155         print_parse_debug("conf_data:\n");
156
157         print_parse_debug("features:");
158         if (get_u64(mb, &use_features0)) {
159                 print_err("failed to read use_features\n");
160                 return NULL;
161         }
162
163         if (get_u64(mb, &use_features1)) {
164                 print_err("failed to read use_features\n");
165                 return NULL;
166         }
167
168         print_parse_debug("sys trace period:");
169         if (get_u32(mb, &stp)) {
170                 print_err("failed to read sys trace period\n");
171                 return NULL;
172         }
173
174         print_parse_debug("data msg period:");
175         if (get_u32(mb, &dmp)) {
176                 print_err("failed to read data message period\n");
177                 return NULL;
178         }
179
180         conf = kmalloc(sizeof(*conf), GFP_KERNEL);
181         if (conf == NULL) {
182                 print_err("out of memory\n");
183                 return NULL;
184         }
185
186         conf->use_features0 = use_features0;
187         conf->use_features1 = use_features1;
188         conf->sys_trace_period = stp;
189         conf->data_msg_period = dmp;
190
191         return conf;
192 }
193
194 void destroy_conf_data(struct conf_data *conf)
195 {
196         kfree(conf);
197 }
198
199 static struct conf_data config;
200 void save_config(const struct conf_data *conf)
201 {
202         memcpy(&config, conf, sizeof(config));
203 }
204
205 void restore_config(struct conf_data *conf)
206 {
207         memcpy(conf, &config, sizeof(*conf));
208 }
209
210
211
212 /* ============================================================================
213  * ==                               FUNC_INST                                ==
214  * ============================================================================
215  */
216 struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
217 {
218         struct func_inst_data *fi;
219         u64 addr;
220         char *args;
221         char ret_type;
222
223         print_parse_debug("func addr:");
224         if (get_u64(mb, &addr)) {
225                 print_err("failed to read data function address\n");
226                 return NULL;
227         }
228
229         print_parse_debug("funct args:");
230         if (get_string(mb, &args)) {
231                 print_err("failed to read data function arguments\n");
232                 return NULL;
233         }
234
235         print_parse_debug("funct ret type:");
236         if (get_u8(mb, (u8 *)&ret_type)) {
237                 print_err("failed to read data function arguments\n");
238                 goto free_args;
239         }
240
241         fi = kmalloc(sizeof(*fi), GFP_KERNEL);
242         if (fi == NULL) {
243                 print_err("out of memory\n");
244                 goto free_args;
245         }
246
247         fi->addr = addr;
248         fi->args = args;
249         fi->ret_type = ret_type;
250
251         return fi;
252
253 free_args:
254         put_string(args);
255         return NULL;
256 }
257
258 void destroy_func_inst_data(struct func_inst_data *fi)
259 {
260         put_string(fi->args);
261         kfree(fi);
262 }
263
264
265
266
267
268 /* ============================================================================
269  * ==                               LIB_INST                                 ==
270  * ============================================================================
271  */
272 struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
273 {
274         struct lib_inst_data *li;
275         struct func_inst_data *fi;
276         char *path;
277         u32 cnt, j, i = 0;
278
279         print_parse_debug("bin path:");
280         if (get_string(mb, &path)) {
281                 print_err("failed to read path of binary\n");
282                 return NULL;
283         }
284
285         print_parse_debug("func count:");
286         if (get_u32(mb, &cnt)) {
287                 print_err("failed to read count of functions\n");
288                 goto free_path;
289         }
290
291         if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt) {
292                 print_err("to match count of functions(%u)\n", cnt);
293                 goto free_path;
294         }
295
296         li = kmalloc(sizeof(*li), GFP_KERNEL);
297         if (li == NULL)
298         if (li == NULL) {
299                 print_err("out of memory\n");
300                 goto free_path;
301         }
302
303         li->func = kmalloc(sizeof(struct func_inst_data *) * cnt, GFP_KERNEL);
304         if (li->func == NULL)
305         if (li->func == NULL) {
306                 print_err("out of memory\n");
307                 goto free_li;
308         }
309
310         for (i = 0; i < cnt; ++i) {
311                 print_parse_debug("func #%d:\n", i + 1);
312                 fi = create_func_inst_data(mb);
313                 if (fi == NULL)
314                         goto free_func;
315
316                 li->func[i] = fi;
317         }
318
319         li->path = path;
320         li->cnt_func = cnt;
321
322         return li;
323
324 free_func:
325         for (j = 0; j < i; ++j)
326                 destroy_func_inst_data(li->func[j]);
327         kfree(li->func);
328
329 free_li:
330         kfree(li);
331
332 free_path:
333         put_string(path);
334
335         return NULL;
336 }
337
338 void destroy_lib_inst_data(struct lib_inst_data *li)
339 {
340         int i;
341
342         put_string(li->path);
343
344         for (i = 0; i < li->cnt_func; ++i)
345                 destroy_func_inst_data(li->func[i]);
346
347         kfree(li->func);
348         kfree(li);
349 }
350
351
352
353
354
355 /* ============================================================================
356  * ==                               APP_INST                                 ==
357  * ============================================================================
358  */
359 struct app_inst_data *create_app_inst_data(struct msg_buf *mb)
360 {
361         struct app_inst_data *app_inst;
362         struct app_info_data *app_info;
363         struct func_inst_data *func;
364         struct lib_inst_data *lib;
365         u32 cnt_func, i_func = 0, cnt_lib, i_lib = 0, i;
366
367         app_info = create_app_info(mb);
368         if (app_info == NULL)
369                 return NULL;
370
371         print_parse_debug("func count:");
372         if (get_u32(mb, &cnt_func)) {
373                 print_err("failed to read count of functions\n");
374                 goto free_app_info;
375         }
376
377         if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt_func) {
378                 print_err("to match count of functions(%u)\n", cnt_func);
379                 goto free_app_info;
380         }
381
382         app_inst = kmalloc(sizeof(*app_inst), GFP_KERNEL);
383         if (app_inst == NULL) {
384                 print_err("out of memory\n");
385                 goto free_app_info;
386         }
387
388         app_inst->func = kmalloc(sizeof(struct func_inst_data *) * cnt_func,
389                                  GFP_KERNEL);
390         if (app_inst->func == NULL) {
391                 print_err("out of memory\n");
392                 goto free_app_inst;
393         }
394
395         for (i_func = 0; i_func < cnt_func; ++i_func) {
396                 print_parse_debug("func #%d:\n", i_func + 1);
397                 func = create_func_inst_data(mb);
398                 if (func == NULL)
399                         goto free_func;
400
401                 app_inst->func[i_func] = func;
402         }
403
404         print_parse_debug("lib count:");
405         if (get_u32(mb, &cnt_lib)) {
406                 print_err("failed to read count of libraries\n");
407                 goto free_func;
408         }
409
410         if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt_lib) {
411                 print_err("to match count of libraries(%u)\n", cnt_lib);
412                 goto free_func;
413         }
414
415         app_inst->lib = kmalloc(sizeof(struct lib_inst_data *) * cnt_lib,
416                                 GFP_KERNEL);
417         if (app_inst->lib == NULL) {
418                 print_err("out of memory\n");
419                 goto free_func;
420         }
421
422         for (i_lib = 0; i_lib < cnt_lib; ++i_lib) {
423                 print_parse_debug("lib #%d:\n", i_lib + 1);
424                 lib = create_lib_inst_data(mb);
425                 if (lib == NULL)
426                         goto free_lib;
427
428                 app_inst->lib[i_lib] = lib;
429         }
430
431         app_inst->app_info = app_info;
432         app_inst->cnt_func = cnt_func;
433         app_inst->cnt_lib = cnt_lib;
434
435         return app_inst;
436
437 free_lib:
438         for (i = 0; i < i_lib; ++i)
439                 destroy_lib_inst_data(app_inst->lib[i]);
440         kfree(app_inst->lib);
441
442 free_func:
443         for (i = 0; i < i_func; ++i)
444                 destroy_func_inst_data(app_inst->func[i]);
445         kfree(app_inst->func);
446
447 free_app_inst:
448         kfree(app_inst);
449
450 free_app_info:
451         destroy_app_info(app_info);
452
453         return NULL;
454 }
455
456 void destroy_app_inst_data(struct app_inst_data *ai)
457 {
458         int i;
459
460         for (i = 0; i < ai->cnt_lib; ++i)
461                 destroy_lib_inst_data(ai->lib[i]);
462         kfree(ai->lib);
463
464         for (i = 0; i < ai->cnt_func; ++i)
465                 destroy_func_inst_data(ai->func[i]);
466         kfree(ai->func);
467
468         destroy_app_info(ai->app_info);
469         kfree(ai);
470 }
471
472
473
474
475
476 /* ============================================================================
477  * ==                                US_INST                                 ==
478  * ============================================================================
479  */
480 struct us_inst_data *create_us_inst_data(struct msg_buf *mb)
481 {
482         struct us_inst_data *ui;
483         struct app_inst_data *ai;
484         u32 cnt, j, i = 0;
485
486         print_parse_debug("us_inst_data:\n");
487
488         print_parse_debug("app count:");
489         if (get_u32(mb, &cnt)) {
490                 print_err("failed to read count of applications\n");
491                 return NULL;
492         }
493
494         if (remained_mb(mb) / MIN_SIZE_APP_INST < cnt) {
495                 print_err("to match count of applications(%u)\n", cnt);
496                 return NULL;
497         }
498
499         ui = kmalloc(sizeof(struct us_inst_data), GFP_KERNEL);
500         if (ui == NULL) {
501                 print_err("out of memory\n");
502                 return NULL;
503         }
504
505         ui->app_inst = kmalloc(sizeof(struct app_inst_data *) * cnt,
506                                GFP_KERNEL);
507         if (ui->app_inst == NULL) {
508                 print_err("out of memory\n");
509                 goto free_ui;
510         }
511
512         for (i = 0; i < cnt; ++i) {
513                 print_parse_debug("app #%d:\n",i+1);
514                 ai = create_app_inst_data(mb);
515                 if (ai == NULL)
516                         goto free_app_inst;
517
518                 ui->app_inst[i] = ai;
519         }
520
521         ui->cnt = cnt;
522
523         return ui;
524
525 free_app_inst:
526         for (j = 0; j < i; ++j)
527                 destroy_app_inst_data(ui->app_inst[j]);
528         kfree(ui->app_inst);
529
530 free_ui:
531         kfree(ui);
532
533         return NULL;
534 }
535
536 void destroy_us_inst_data(struct us_inst_data *ui)
537 {
538         int i;
539
540         for (i = 0; i < ui->cnt; ++i)
541                 destroy_app_inst_data(ui->app_inst[i]);
542
543         kfree(ui->app_inst);
544         kfree(ui);
545 }