DPM support
[platform/core/system/storaged.git] / src / block / block.c
1 /*
2  * storaged
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #define _GNU_SOURCE
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/mount.h>
28 #include <sys/statvfs.h>
29 #include <fnmatch.h>
30 #include <errno.h>
31 #include <dirent.h>
32 #include <sys/statfs.h>
33 #include <stdbool.h>
34 #include <pthread.h>
35 #include <time.h>
36 #include <assert.h>
37 #include <vconf.h>
38 #include <ctype.h>
39 #include <tzplatform_config.h>
40 #include <app2ext_interface.h>
41 #include <libmount.h>
42 #include <blkid/blkid.h>
43 #include <ode/luks.h>
44
45 #include "log.h"
46 #include "config-parser.h"
47 #include "module-intf.h"
48 #include "udev.h"
49 #include "list.h"
50 #include "block.h"
51 #include "dbus.h"
52 #include "fd_handler.h"
53 #include "utils.h"
54 #include "apps.h"
55
56 /**
57  * TODO  Assume root device is always mmcblk0*.
58  */
59 #define MMC_PATH                "*/mmcblk[0-9]*"
60 #define MMC_PARTITION_PATH      "mmcblk[0-9]p[0-9]"
61 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
62 #define MMC_LINK_PATH           "*/sdcard/*"
63 #define SCSI_PATH               "*/sd[a-z]*"
64 #define SCSI_PARTITION_PATH     "sd[a-z][0-9]"
65 #define SCSI_PARTITION_LENGTH   9
66 #define EXTENDEDSD_NODE_PATH    "/dev/mapper/extendedsd"
67
68 #define FILESYSTEM_NAME         "filesystem"
69
70 #define DEV_PREFIX              "/dev/"
71 #define ROOT_DIR                "/"
72
73 #define UNMOUNT_RETRY           5
74 #define TIMEOUT_MAKE_OBJECT     500 /* milliseconds */
75
76 #define SIGNAL_POWEROFF_STATE   "ChangeState"
77
78 #define BLOCK_DEVICE_ADDED      "DeviceAdded"
79 #define BLOCK_DEVICE_REMOVED    "DeviceRemoved"
80 #define BLOCK_DEVICE_BLOCKED    "DeviceBlocked"
81 #define BLOCK_DEVICE_CHANGED    "DeviceChanged"
82 #define BLOCK_DEVICE_CHANGED_2  "DeviceChanged2"
83
84 #define BLOCK_TYPE_MMC          "mmc"
85 #define BLOCK_TYPE_SCSI         "scsi"
86 #define BLOCK_TYPE_ALL          "all"
87
88 #define BLOCK_MMC_NODE_PREFIX   "SDCard"
89 #define BLOCK_SCSI_NODE_PREFIX  "USBDrive"
90
91 #define BLOCK_CONF_FILE         "/etc/storaged/block.conf"
92
93 #define EXTERNAL_STORAGE_PATH   "/run/external-storage"
94 #define EXTENDED_INTERNAL_PATH  "/run/extended-internal-sd"
95 #define PATH_LEN                55
96
97 #define EXTENDEDSD_MOUNT_PATH   "/opt/extendedsd"
98
99 #define EXT4_NAME               "ext4"
100 #define LUKS_NAME               "crypto_LUKS"
101 #define EXTENDEDSD_NAME         "extendedsd"
102
103 /* Minimum value of block id */
104 #define BLOCK_ID_MIN 10
105 /* For 2.4 Backward Compatibility */
106 #define EXT_PRIMARY_SD_FIXID    1
107
108 /* Maximum number of thread */
109 #define THREAD_MAX 5
110
111 #define SPEEDCHECK 16
112
113 #define PKGDIR_BUS_NAME         "org.tizen.pkgdir_tool"
114 #define PKGDIR_PATH             "/org/tizen/pkgdir_tool"
115 #define PKGDIR_INTERFACE        "org.tizen.pkgdir_tool"
116
117 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
118
119 enum block_dev_operation {
120         BLOCK_DEV_MOUNT,
121         BLOCK_DEV_UNMOUNT,
122         BLOCK_DEV_FORMAT,
123         BLOCK_DEV_INSERT,
124         BLOCK_DEV_REMOVE,
125         BLOCK_LUKS_CLOSE,
126 };
127
128 enum private_operation_state {
129         REQ_NORMAL,
130         REQ_PRIVATE,
131         REQ_PRIVATE_FORMAT,
132 };
133
134 struct operation_queue {
135         enum block_dev_operation op;
136         dbus_method_reply_handle_h reply_handle;
137         void *data;
138         bool done;
139 };
140
141 struct block_device {
142         struct block_data *data;
143         dd_list *op_queue;
144         int thread_id;          /* Current thread ID */
145         bool removed;           /* True when device is physically removed but operation is not precessed yet */
146         enum private_operation_state on_private_op;
147         bool mount_point_updated;
148         pid_t private_pid;
149 };
150
151 struct format_data {
152         struct block_device *bdev;
153         char *fs_type;
154         enum unmount_operation option;
155 };
156
157 struct pipe_data {
158         enum block_dev_operation op;
159         struct block_device *bdev;
160         int result;
161 };
162
163 static struct block_conf {
164         bool multimount;
165         bool extendedinternal;
166 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
167
168 static struct manage_thread {
169         dd_list *th_node_list;  /* List of devnode which thread dealt with. Only main thread access */
170         dd_list *block_dev_list; /* Use thread mutex */
171         pthread_t th;
172         pthread_mutex_t mutex;
173         pthread_cond_t cond;
174         int num_dev;            /* Number of devices which thread holds. Only main thread access */
175         int op_len;             /* Number of operation of thread. Use thread mutex */
176         int thread_id;          /* Never changed */
177         bool start_th;
178 } th_manager[THREAD_MAX];
179
180 static dd_list *fs_head;
181 static dd_list *block_ops_list;
182 static bool smack;
183 static int pfds[2];
184 static fd_handler_h phandler;
185 static bool block_control = false;
186 static bool block_boot = false;
187 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
188
189 /* Assume there is only one physical internal storage */
190 static int dev_internal = -1;
191 static char dev_internal_scsi = '\0';
192 static char dev_internal_emul = '\0';
193
194 static int block_start(void *data);
195 static int block_stop(void *data);
196
197 static int add_operation(struct block_device *bdev,
198                 enum block_dev_operation operation,
199                 dbus_method_reply_handle_h reply_handle, void *data);
200 static void remove_operation(struct block_device *bdev);
201 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
202 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
203 static int change_mount_point(struct block_device *bdev, const char *mount_point);
204
205 static void uevent_block_handler(struct udev_device *dev);
206 static struct uevent_handler uh = {
207         .subsystem = BLOCK_SUBSYSTEM,
208         .uevent_func = uevent_block_handler,
209 };
210
211 static void __CONSTRUCTOR__ smack_check(void)
212 {
213         FILE *fp;
214         char buf[128];
215
216         fp = fopen("/proc/filesystems", "r");
217         if (!fp)
218                 return;
219
220         while (fgets(buf, sizeof(buf), fp) != NULL) {
221                 if (strstr(buf, "smackfs")) {
222                         smack = true;
223                         break;
224                 }
225         }
226
227         fclose(fp);
228 }
229
230 void add_fs(const struct block_fs_ops *fs)
231 {
232         DD_LIST_APPEND(fs_head, (void *)fs);
233 }
234
235 void remove_fs(const struct block_fs_ops *fs)
236 {
237         DD_LIST_REMOVE(fs_head, (void *)fs);
238 }
239
240 const struct block_fs_ops *find_fs(enum block_fs_type type)
241 {
242         struct block_fs_ops *fs;
243         dd_list *elem;
244
245         DD_LIST_FOREACH(fs_head, elem, fs) {
246                 if (fs->type == type)
247                         return fs;
248         }
249         return NULL;
250 }
251
252 void add_block_dev(const struct block_dev_ops *ops)
253 {
254         DD_LIST_APPEND(block_ops_list, (void *)ops);
255 }
256
257 void remove_block_dev(const struct block_dev_ops *ops)
258 {
259         DD_LIST_REMOVE(block_ops_list, (void *)ops);
260 }
261
262 static void broadcast_block_info(enum block_dev_operation op,
263                 struct block_data *data, int result)
264 {
265         struct block_dev_ops *ops;
266         dd_list *elem;
267
268         if (data->primary != true)
269                 return;
270
271         DD_LIST_FOREACH(block_ops_list, elem, ops) {
272                 int data_block_type = (data->block_type == BLOCK_EXTENDEDSD_DEV)
273                                       ? BLOCK_MMC_DEV : data->block_type;
274
275                 if (ops->block_type != data_block_type)
276                         continue;
277                 // TODO What happend on extended internal storage case?
278                 if (op == BLOCK_DEV_MOUNT) {
279                         ops->mounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
280                 } else if (op == BLOCK_DEV_UNMOUNT) {
281                         ops->unmounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
282                 } else if (op == BLOCK_DEV_FORMAT) {
283                         ops->formatted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
284                 } else if (op == BLOCK_DEV_INSERT)
285                         ops->inserted(data);
286                 else if (op == BLOCK_DEV_REMOVE)
287                         ops->removed(data);
288         }
289 }
290
291 // Called by MainThread - Insert
292 static int block_get_new_id(void)
293 {
294         static int id = BLOCK_ID_MIN;
295         struct block_device *bdev;
296         dd_list *elem;
297         bool found;
298         int i, j;
299
300         for (i = 0 ; i < INT_MAX ; i++) {
301                 found = false;
302                 for (j = 0; j < THREAD_MAX; j++) {
303                         pthread_mutex_lock(&(th_manager[j].mutex));
304                         DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
305                                 if (bdev->data->id == id) {
306                                         found = true;
307                                         break;
308                                 }
309                         }
310                         pthread_mutex_unlock(&(th_manager[j].mutex));
311                         if (found)
312                                 break;
313                 }
314
315                 if (!found)
316                         return id++;
317
318                 if (++id == INT_MAX)
319                         id = BLOCK_ID_MIN;
320         }
321
322         return -ENOENT;
323 }
324
325 static void remove_file(int id, bool extendedsd)
326 {
327         char file_name[PATH_LEN];
328         int ret;
329
330         if (id < 0)
331                 return;
332
333         if (extendedsd)
334                 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
335         else
336                 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
337
338         ret = remove(file_name);
339         if (ret < 0)
340                 _E("Fail to remove %s. errno: %d", file_name, errno);
341 }
342
343 static void create_file(int id, char *mount_point, bool extendedsd)
344 {
345         FILE *fp;
346         char file_name[PATH_LEN];
347
348         if (id < 0)
349                 return;
350
351         if (extendedsd)
352                 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
353         else
354                 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
355
356         fp = fopen(file_name, "w+");
357         if (fp) {
358                 fprintf(fp, "%s", mount_point);
359                 fclose(fp);
360         } else
361                 _E("Fail to open %s", file_name);
362 }
363
364 static void signal_device_blocked(struct block_device *bdev)
365 {
366         struct block_data *data;
367         char *arr[13];
368         char str_block_type[32];
369         char str_readonly[32];
370         char str_state[32];
371         char str_primary[32];
372         char str_flags[32];
373         char str_id[32];
374         char *str_null = "";
375         int flags;
376
377         if (!bdev || !bdev->data)
378                 return;
379
380         data = bdev->data;
381         flags = 0;
382
383         /* Broadcast outside with BlockManager iface */
384         snprintf(str_block_type, sizeof(str_block_type),
385                         "%d", data->block_type);
386         arr[0] = str_block_type;
387         arr[1] = (data->devnode ? data->devnode : str_null);
388         arr[2] = (data->syspath ? data->syspath : str_null);
389         arr[3] = (data->fs_usage ? data->fs_usage : str_null);
390         arr[4] = (data->fs_type ? data->fs_type : str_null);
391         arr[5] = (data->fs_version ? data->fs_version : str_null);
392         arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
393         snprintf(str_readonly, sizeof(str_readonly),
394                         "%d", data->readonly);
395         arr[7] = str_readonly;
396         arr[8] = (data->mount_point ? data->mount_point : str_null);
397         snprintf(str_state, sizeof(str_state),
398                         "%d", data->state);
399         arr[9] = str_state;
400         snprintf(str_primary, sizeof(str_primary),
401                         "%d", data->primary);
402         arr[10] = str_primary;
403         snprintf(str_flags, sizeof(str_flags), "%d", flags);
404         arr[11] = str_flags;
405         snprintf(str_id, sizeof(str_id), "%d", data->id);
406         arr[12] = str_id;
407
408         broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
409                         STORAGED_INTERFACE_BLOCK_MANAGER,
410                         BLOCK_DEVICE_BLOCKED,
411                         "issssssisibii", arr);
412 }
413
414 static void signal_device_changed(struct block_device *bdev,
415                 enum block_dev_operation op)
416 {
417         struct block_data *data;
418         char *arr[13];
419         char str_block_type[32];
420         char str_readonly[32];
421         char str_state[32];
422         char str_primary[32];
423         char str_flags[32];
424         char str_id[32];
425         char *str_null = "";
426         int flags;
427
428         if (!bdev || !bdev->data)
429                 return;
430
431         data = bdev->data;
432
433         switch (op) {
434         case BLOCK_DEV_MOUNT:
435                 BLOCK_GET_MOUNT_FLAGS(data, flags);
436                 break;
437         case BLOCK_DEV_UNMOUNT:
438                 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
439                 break;
440         case BLOCK_DEV_FORMAT:
441                 BLOCK_GET_FORMAT_FLAGS(data, flags);
442                 break;
443         default:
444                 flags = 0;
445                 break;
446         }
447
448         /* Broadcast outside with BlockManager iface */
449         snprintf(str_block_type, sizeof(str_block_type),
450                         "%d", data->block_type);
451         arr[0] = str_block_type;
452         arr[1] = (data->devnode ? data->devnode : str_null);
453         arr[2] = (data->syspath ? data->syspath : str_null);
454         arr[3] = (data->fs_usage ? data->fs_usage : str_null);
455         arr[4] = (data->fs_type ? data->fs_type : str_null);
456         arr[5] = (data->fs_version ? data->fs_version : str_null);
457         arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
458         snprintf(str_readonly, sizeof(str_readonly),
459                         "%d", data->readonly);
460         arr[7] = str_readonly;
461         arr[8] = (data->mount_point ? data->mount_point : str_null);
462         snprintf(str_state, sizeof(str_state),
463                         "%d", data->state);
464         arr[9] = str_state;
465         snprintf(str_primary, sizeof(str_primary),
466                         "%d", data->primary);
467         arr[10] = str_primary;
468         snprintf(str_flags, sizeof(str_flags), "%d", flags);
469         arr[11] = str_flags;
470         snprintf(str_id, sizeof(str_id), "%d", data->id);
471         arr[12] = str_id;
472
473         if (op == BLOCK_DEV_INSERT)
474                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
475                                 STORAGED_INTERFACE_BLOCK_MANAGER,
476                                 BLOCK_DEVICE_ADDED,
477                                 "issssssisibii", arr);
478         else if (op == BLOCK_DEV_REMOVE)
479                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
480                                 STORAGED_INTERFACE_BLOCK_MANAGER,
481                                 BLOCK_DEVICE_REMOVED,
482                                 "issssssisibii", arr);
483         else {
484                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
485                                 STORAGED_INTERFACE_BLOCK_MANAGER,
486                                 BLOCK_DEVICE_CHANGED,
487                                 "issssssisibii", arr);
488                 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
489                                 STORAGED_INTERFACE_BLOCK_MANAGER,
490                                 BLOCK_DEVICE_CHANGED_2,
491                                 "issssssisibi", arr);
492         }
493 }
494
495 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
496 {
497         char *name = devnode;
498         int dev = -1, part = -1;
499         char emul[32] = { 0, };
500         int i;
501
502         if (!name)
503                 return -EINVAL;
504
505         /* Check Target */
506         sscanf(name, "mmcblk%dp%d", &dev, &part);
507         if (dev >= 0) {
508                 if (part < 0)
509                         snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
510                 else
511                         snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
512                 return 0;
513         }
514
515         /* Check Emulator */
516         sscanf(name, "vd%31s", emul);
517         if (emul[0] == '\0')
518                 return -EINVAL;
519         for (i = 0 ; i < strlen(emul) ; i++)
520                 emul[i] = toupper(emul[i]);
521         snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
522         return 0;
523 }
524
525 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
526 {
527         char dev[64], *name;
528         int i;
529
530         if (!devnode)
531                 return -EINVAL;
532
533         snprintf(dev, sizeof(dev), "%s", devnode);
534
535         if (!strstr(dev, "sd"))
536                 return -EINVAL;
537
538         name = dev;
539         name += strlen("sd");
540
541         for (i = 0 ; i < strlen(name) ; i++)
542                 name[i] = toupper(name[i]);
543         snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
544
545         return 0;
546 }
547
548 static char *generate_mount_path(struct block_data *data)
549 {
550         const char *str;
551         char *name, node[64];
552         int ret;
553
554         if (!data || !data->devnode || !data->fs_usage || (strcmp(data->fs_usage, FILESYSTEM_NAME) && strncmp(data->fs_usage, "crypto", strlen("crypto"))))
555                 return NULL;
556
557         name = strrchr(data->devnode, '/');
558         if (!name)
559                 goto out;
560         name++;
561
562         switch (data->block_type) {
563         case BLOCK_MMC_DEV:
564                 ret = get_mmc_mount_node(name, node, sizeof(node));
565                 break;
566         case BLOCK_SCSI_DEV:
567                 ret = get_scsi_mount_node(name, node, sizeof(node));
568                 break;
569         case BLOCK_EXTENDEDSD_DEV:
570                 return strdup(EXTENDEDSD_MOUNT_PATH);
571         default:
572                 _E("Invalid block type (%d)", data->block_type);
573                 return NULL;
574         }
575         if (ret < 0)
576                 goto out;
577
578         str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
579         if (!str)
580                 return NULL;
581         return strdup(str);
582
583 out:
584         _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
585         return NULL;
586 }
587
588 static bool check_primary_partition(const char *devnode)
589 {
590         struct block_fs_ops *fs;
591         blkid_probe probe;
592         dd_list *elem;
593         const char *filesystem = NULL;
594         char *temp;
595         char str[PATH_MAX];
596         char str2[PATH_MAX];
597         size_t fs_len;
598         int len;
599         int ret;
600         int i;
601         bool found = false;
602
603         if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
604                 fnmatch(MMC_PATH, devnode, 0) &&
605                 fnmatch(SCSI_PATH, devnode, 0) &&
606                 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
607                 return false;
608
609         temp = strrchr(devnode, '/');
610         if (!temp)
611                 return false;
612         if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
613                 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
614                 return true;
615
616         /* Emulator support only one partition */
617         if (is_emulator())
618                 return true;
619
620         snprintf(str, sizeof(str), "%s", devnode);
621
622         len = strlen(str);
623         str[len - 1] = '\0';
624
625         for (i = 1; i <= 9; ++i) {
626                 snprintf(str2, sizeof(str2), "%s%d", str, i);
627                 if (access(str2, R_OK) != 0)
628                         continue;
629
630                 probe = blkid_new_probe_from_filename(str2);
631                 if (!probe)
632                         continue;
633                 if (blkid_do_probe(probe) != 0)
634                         continue;
635
636                 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
637                 if (ret < 0) {
638                         blkid_free_probe(probe);
639                         continue;
640                 }
641                 DD_LIST_FOREACH(fs_head, elem, fs) {
642                         if (!strncmp(fs->name, filesystem, fs_len)) {
643                                 found = true;
644                                 break;
645                         }
646                 }
647                 blkid_free_probe(probe);
648                 if (!found)
649                         continue;
650                 break;
651         }
652
653         if (found && !strncmp(devnode, str2, strlen(str2) + 1))
654                 return true;
655
656         return false;
657 }
658
659 /* Whole data in struct block_data should be freed. */
660 static struct block_data *make_block_data(const char *devnode,
661                 const char *syspath,
662                 const char *fs_usage,
663                 const char *fs_type,
664                 const char *fs_version,
665                 const char *fs_uuid_enc,
666                 const char *readonly)
667 {
668         struct block_data *data;
669
670         /* devnode is unique value so it should exist. */
671         if (!devnode)
672                 return NULL;
673
674         if (!fs_type)
675                 _I("Unknown fs type");
676
677         data = calloc(1, sizeof(struct block_data));
678         if (!data) {
679                 _E("calloc() failed");
680                 return NULL;
681         }
682
683         data->devnode = strdup(devnode);
684         if (syspath)
685                 data->syspath = strdup(syspath);
686         if (fs_usage)
687                 data->fs_usage = strdup(fs_usage);
688         if (fs_type)
689                 data->fs_type = strdup(fs_type);
690         if (fs_version)
691                 data->fs_version = strdup(fs_version);
692         if (fs_uuid_enc)
693                 data->fs_uuid_enc = strdup(fs_uuid_enc);
694         if (readonly)
695                 data->readonly = atoi(readonly);
696         data->primary = check_primary_partition(devnode);
697
698         /* TODO should we know block dev type? */
699         if (!fnmatch(MMC_LINK_PATH, devnode, 0))
700                 data->block_type = BLOCK_MMC_DEV;
701         else if (!fnmatch(MMC_PATH, devnode, 0))
702                 data->block_type = BLOCK_MMC_DEV;
703         else if (!fnmatch(SCSI_PATH, devnode, 0))
704                 data->block_type = BLOCK_SCSI_DEV;
705         else if (!fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
706                 data->block_type = BLOCK_EXTENDEDSD_DEV;
707         else
708                 data->block_type = -1;
709
710         data->mount_point = generate_mount_path(data);
711         BLOCK_FLAG_CLEAR_ALL(data);
712
713         /* for 2.4 backward compatibility */
714         // What if storage id 1 is existed? (multi sdcard case)
715         if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
716             data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME))
717                 data->id = EXT_PRIMARY_SD_FIXID;
718         else
719                 data->id = block_get_new_id();
720
721         return data;
722 }
723
724 static void free_block_data(struct block_data *data)
725 {
726         if (!data)
727                 return;
728         free(data->devnode);
729         free(data->syspath);
730         free(data->fs_usage);
731         free(data->fs_type);
732         free(data->fs_version);
733         free(data->fs_uuid_enc);
734         free(data->mount_point);
735         free(data);
736 }
737
738 static int update_block_data(struct block_data *data,
739                 const char *fs_usage,
740                 const char *fs_type,
741                 const char *fs_version,
742                 const char *fs_uuid_enc,
743                 const char *readonly,
744                 bool mount_point_updated)
745 {
746         if (!data)
747                 return -EINVAL;
748
749         free(data->fs_usage);
750         data->fs_usage = NULL;
751         if (fs_usage)
752                 data->fs_usage = strdup(fs_usage);
753
754         free(data->fs_type);
755         data->fs_type = NULL;
756         if (fs_type)
757                 data->fs_type = strdup(fs_type);
758
759         free(data->fs_version);
760         data->fs_version = NULL;
761         if (fs_version)
762                 data->fs_version = strdup(fs_version);
763
764         free(data->fs_uuid_enc);
765         data->fs_uuid_enc = NULL;
766         if (fs_uuid_enc)
767                 data->fs_uuid_enc = strdup(fs_uuid_enc);
768
769         /* generate_mount_path function should be invoked
770          * after fs_uuid_enc is updated */
771         if (!mount_point_updated) {
772                 free(data->mount_point);
773                 data->mount_point = generate_mount_path(data);
774         }
775
776         data->readonly = false;
777         if (readonly)
778                 data->readonly = atoi(readonly);
779
780         BLOCK_FLAG_MOUNT_CLEAR(data);
781
782         return 0;
783 }
784
785 static struct block_device *make_block_device(struct block_data *data)
786 {
787         struct block_device *bdev;
788
789         if (!data)
790                 return NULL;
791
792         bdev = calloc(1, sizeof(struct block_device));
793         if (!bdev)
794                 return NULL;
795
796         bdev->data = data;
797         bdev->thread_id = -1;
798         bdev->removed = false;
799         bdev->on_private_op = REQ_NORMAL;
800         bdev->private_pid = 0;
801         bdev->mount_point_updated = false;
802
803         return bdev;
804 }
805
806 // Called by MainThread - Remove DevNode
807 static void free_block_device(struct block_device *bdev)
808 {
809         dd_list *l, *next;
810         struct operation_queue *op;
811         int thread_id;
812
813         if (!bdev)
814                 return;
815
816         thread_id = bdev->thread_id;
817         if (thread_id < 0 || thread_id >= THREAD_MAX)
818                 return;
819
820         pthread_mutex_lock(&(th_manager[thread_id].mutex));
821
822         th_manager[thread_id].num_dev--;
823         DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
824         free_block_data(bdev->data);
825
826         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
827                 if (!op->done)
828                         th_manager[thread_id].op_len--;
829                 DD_LIST_REMOVE(bdev->op_queue, op);
830                 free(op);
831         }
832         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
833
834         free(bdev);
835 }
836
837 // Called By MainThread - Remove Device
838 static struct block_device *find_block_device(const char *devnode)
839 {
840         struct block_device *bdev;
841         dd_list *elem;
842         int len;
843         int i;
844
845         len = strlen(devnode) + 1;
846         for (i = 0; i < THREAD_MAX; i++) {
847                 pthread_mutex_lock(&(th_manager[i].mutex));
848                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
849                         if (bdev->data && !bdev->removed &&
850                             !strncmp(bdev->data->devnode, devnode, len)) {
851                                 pthread_mutex_unlock(&(th_manager[i].mutex));
852                                 return bdev;
853                         }
854                 }
855                 pthread_mutex_unlock(&(th_manager[i].mutex));
856         }
857
858         return NULL;
859 }
860
861 // Called By MainThread - Remove Device
862 static struct block_device *find_block_device_path(const char *mount_point)
863 {
864         struct block_device *bdev;
865         dd_list *elem;
866         int len;
867         int i;
868
869         len = strlen(mount_point) + 1;
870         for (i = 0; i < THREAD_MAX; i++) {
871                 pthread_mutex_lock(&(th_manager[i].mutex));
872                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
873                         if (bdev->data && !bdev->removed &&
874                            (bdev->data->mount_point != NULL && !strncmp(bdev->data->mount_point, mount_point, len))) {
875                                 pthread_mutex_unlock(&(th_manager[i].mutex));
876                                 return bdev;
877                         }
878                 }
879                 pthread_mutex_unlock(&(th_manager[i].mutex));
880         }
881
882         return NULL;
883 }
884
885 // Called By MainThread - Mount,Unmount,Format,GetInfo
886 static struct block_device *find_block_device_by_id(int id)
887 {
888         struct block_device *bdev;
889         dd_list *elem;
890         int i;
891
892         for (i = 0; i < THREAD_MAX; i++) {
893                 pthread_mutex_lock(&(th_manager[i].mutex));
894                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
895                         if (!bdev->data)
896                                 continue;
897                         if (bdev->removed)
898                                 continue;
899                         if (bdev->data->id == id) {
900                                 pthread_mutex_unlock(&(th_manager[i].mutex));
901                                 return bdev;
902                         }
903                 }
904                 pthread_mutex_unlock(&(th_manager[i].mutex));
905         }
906
907         return NULL;
908 }
909
910 static char *get_operation_char(enum block_dev_operation op,
911                 char *name, unsigned int len)
912 {
913         char *str = "unknown";
914
915         if (!name)
916                 return NULL;
917
918         switch (op) {
919         case BLOCK_DEV_MOUNT:
920                 str = "MOUNT";
921                 break;
922         case BLOCK_DEV_UNMOUNT:
923                 str = "UNMOUNT";
924                 break;
925         case BLOCK_DEV_FORMAT:
926                 str = "FORMAT";
927                 break;
928         case BLOCK_DEV_INSERT:
929                 str = "INSERT";
930                 break;
931         case BLOCK_DEV_REMOVE:
932                 str = "REMOVE";
933                 break;
934         case BLOCK_LUKS_CLOSE:
935                 str = "LUKS CLOSE";
936                 break;
937         default:
938                 _E("invalid operation (%d)", op);
939                 break;
940         }
941
942         snprintf(name, len, "%s", str);
943         return name;
944 }
945
946 static void create_external_apps_directory(void)
947 {
948         int ret;
949
950         ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
951                         PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
952                         NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
953         if (ret)
954                 _E("Fail to create external directory");
955 }
956
957 static int pipe_trigger(enum block_dev_operation op,
958                 struct block_device *bdev, int result)
959 {
960         struct pipe_data pdata = { op, bdev, result };
961         int n;
962         char name[16];
963
964         _D("op : %s, bdev : %p, result : %d",
965                         get_operation_char(pdata.op, name, sizeof(name)),
966                         pdata.bdev, pdata.result);
967
968         // Multi thread should not write at the same time
969         pthread_mutex_lock(&pipe_mutex);
970         n = write(pfds[1], &pdata, sizeof(struct pipe_data));
971         pthread_mutex_unlock(&pipe_mutex);
972
973         return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
974 }
975
976 static bool pipe_cb(int fd, void *data)
977 {
978         struct pipe_data pdata = {0,};
979         int n;
980         int thread_id;
981         int ret;
982         char name[16];
983
984         n = read(fd, &pdata, sizeof(pdata));
985         if (n != sizeof(pdata) || !pdata.bdev) {
986                 _E("fail to read struct pipe data");
987                 goto out;
988         }
989
990         _I("op : %s, bdev : %p, result : %d",
991                         get_operation_char(pdata.op, name, sizeof(name)),
992                         pdata.bdev, pdata.result);
993
994         if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
995                 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
996                         ret = change_mount_point(pdata.bdev, "");
997                         /* Modify /run/external-storage/id file */
998                         if (ret == 0) {
999                                 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
1000                                         create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
1001                                 else
1002                                         create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
1003                         }
1004                 }
1005                 goto out;
1006         }
1007         if (pdata.op == BLOCK_DEV_MOUNT &&
1008                 pdata.bdev->data->state == BLOCK_MOUNT &&
1009                 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
1010                 pdata.bdev->data->primary)
1011                 create_external_apps_directory();
1012         if (pdata.op == BLOCK_DEV_UNMOUNT) {
1013                 /* Remove file for block device /run/xxxxxx/id */
1014                 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
1015         }
1016
1017         /* Broadcast to mmc and usb storage module */
1018         broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
1019
1020         /* Broadcast outside with Block iface */
1021         if (pdata.bdev->on_private_op == REQ_NORMAL)
1022                 signal_device_changed(pdata.bdev, pdata.op);
1023         else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
1024                 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1025                         pdata.bdev->on_private_op = REQ_NORMAL;
1026                         _D("Private operation state: %d", pdata.bdev->on_private_op);
1027                 }
1028         } else {
1029                 if (pdata.op == BLOCK_DEV_MOUNT) {
1030                         pdata.bdev->on_private_op = REQ_PRIVATE;
1031                         _D("Private operation state: %d", pdata.bdev->on_private_op);
1032                 }
1033         }
1034
1035         if (pdata.op == BLOCK_DEV_REMOVE) {
1036                 thread_id = pdata.bdev->thread_id;
1037                 if (thread_id < 0 || thread_id >= THREAD_MAX)
1038                         return true;
1039                 free_block_device(pdata.bdev);
1040         }
1041
1042 out:
1043         return true;
1044 }
1045
1046 static int pipe_init(void)
1047 {
1048         int ret;
1049
1050         ret = pipe2(pfds, O_CLOEXEC);
1051         if (ret == -1)
1052                 return -errno;
1053
1054         ret = add_fd_read_handler(pfds[0], pipe_cb,
1055                         NULL, NULL, &phandler);
1056         if (ret < 0) {
1057                 _E("Failed to add pipe handler (%d)", ret);
1058                 return ret;
1059         }
1060
1061         return 0;
1062 }
1063
1064 static void pipe_exit(void)
1065 {
1066         if (phandler) {
1067                 remove_fd_read_handler(&phandler);
1068                 phandler = NULL;
1069         }
1070
1071         if (pfds[0])
1072                 close(pfds[0]);
1073         if (pfds[1])
1074                 close(pfds[1]);
1075 }
1076
1077 static int mmc_check_and_unmount(const char *path)
1078 {
1079         int ret = 0;
1080         int retry = 0;
1081
1082         if (!path)
1083                 return 0;
1084
1085         while (mount_check(path)) {
1086                 ret = umount(path);
1087                 if (ret < 0) {
1088                         retry++;
1089                         if (retry > UNMOUNT_RETRY)
1090                                 return -errno;
1091                 }
1092         }
1093         return ret;
1094 }
1095
1096 static bool check_rw_mount(const char *szPath)
1097 {
1098         struct statvfs mount_stat;
1099
1100         if (!statvfs(szPath, &mount_stat)) {
1101                 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1102                         return false;
1103         }
1104         return true;
1105 }
1106
1107 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1108 {
1109         struct udev *udev;
1110         struct udev_device *dev;
1111         int r;
1112         int wait;
1113
1114         if (!data)
1115                 return -EINVAL;
1116
1117         for (wait = 0; wait < 10; wait++) {
1118                 udev = udev_new();
1119                 if (!udev) {
1120                         _E("fail to create udev library context");
1121                         return -EPERM;
1122                 }
1123
1124                 dev = udev_device_new_from_syspath(udev, data->syspath);
1125                 if (!dev) {
1126                         _E("fail to create new udev device");
1127                         udev_unref(udev);
1128                         return -EPERM;
1129                 }
1130
1131                 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
1132                         sleep(1);
1133                 else
1134                         break;
1135
1136                 udev_device_unref(dev);
1137                 udev_unref(udev);
1138         }
1139
1140         r = update_block_data(data,
1141                         udev_device_get_property_value(dev, "ID_FS_USAGE"),
1142                         udev_device_get_property_value(dev, "ID_FS_TYPE"),
1143                         udev_device_get_property_value(dev, "ID_FS_VERSION"),
1144                         udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1145                         udev_device_get_sysattr_value(dev, "ro"),
1146                         mount_point_updated);
1147         if (r < 0)
1148                 _E("fail to update block data for %s", data->devnode);
1149
1150         udev_device_unref(dev);
1151         udev_unref(udev);
1152         return r;
1153 }
1154
1155 static int block_mount(struct block_data *data)
1156 {
1157         struct block_fs_ops *fs;
1158         dd_list *elem;
1159         int r;
1160         int len;
1161
1162         if (!data || !data->devnode || !data->mount_point)
1163                 return -EINVAL;
1164
1165         /* check existing mounted */
1166         if (mount_check(data->mount_point))
1167                 return -EEXIST;
1168
1169         /* create mount point */
1170         if (access(data->mount_point, R_OK) != 0) {
1171                 if (mkdir(data->mount_point, 0755) < 0)
1172                         return -errno;
1173         }
1174
1175         /* check matched file system */
1176         if (!data->fs_usage ||
1177             strncmp(data->fs_usage, FILESYSTEM_NAME,
1178                     sizeof(FILESYSTEM_NAME)) != 0) {
1179                 r = -ENODEV;
1180                 goto out;
1181         }
1182
1183         if (!data->fs_type) {
1184                 _E("There is no file system");
1185                 BLOCK_FLAG_SET(data, FS_EMPTY);
1186                 r = -ENODATA;
1187                 goto out;
1188         }
1189
1190         fs = NULL;
1191         len = strlen(data->fs_type) + 1;
1192         DD_LIST_FOREACH(fs_head, elem, fs) {
1193                 if (!strncmp(fs->name, data->fs_type, len))
1194                         break;
1195         }
1196
1197         if (!fs) {
1198                 _E("Not supported file system (%s)", data->fs_type);
1199                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1200                 r = -ENOTSUP;
1201                 goto out;
1202         }
1203
1204         if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1205                 r = fs->mount(false, data->devnode, data->mount_point);
1206         else
1207                 r = fs->mount(smack, data->devnode, data->mount_point);
1208
1209         if (r == -EIO)
1210                 BLOCK_FLAG_SET(data, FS_BROKEN);
1211
1212         if (r < 0)
1213                 goto out;
1214
1215         r = check_rw_mount(data->mount_point);
1216         if (!r)
1217                 return -EROFS;
1218
1219         return 0;
1220
1221 out:
1222         rmdir(data->mount_point);
1223         return r;
1224 }
1225
1226 static int mount_start(struct block_device *bdev)
1227 {
1228         struct block_data *data;
1229         int ret;
1230         int r;
1231
1232         assert(bdev);
1233         assert(bdev->data);
1234
1235         data = bdev->data;
1236         _I("Mount Start : (%s -> %s)",
1237                         data->devnode, data->mount_point);
1238
1239         /* mount operation */
1240         r = block_mount(data);
1241         if (r != -EROFS && r < 0) {
1242                 _E("fail to mount %s device : %d", data->devnode, r);
1243                 goto out;
1244         }
1245
1246         if (r == -EROFS) {
1247                 data->readonly = true;
1248                 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1249         }
1250
1251         data->state = BLOCK_MOUNT;
1252
1253         if (data->block_type == BLOCK_MMC_DEV) {
1254                 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1255                 ret = app2ext_migrate_legacy_all();
1256                 if (ret < 0)
1257                         _E("app2ext failed");
1258         }
1259
1260 out:
1261         if (r < 0 && r != -EROFS)
1262                 data->state = BLOCK_UNMOUNT;
1263
1264         _I("%s result : %s, %d", __func__, data->devnode, r);
1265
1266         if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1267                 _E("fail to trigger pipe");
1268
1269         return r;
1270 }
1271
1272 static int change_mount_point(struct block_device *bdev,
1273                 const char *mount_point)
1274 {
1275         struct block_data *data;
1276
1277         if (!bdev)
1278                 return -EINVAL;
1279
1280         data = bdev->data;
1281         free(data->mount_point);
1282
1283         /* If the mount path already exists, the path cannot be used */
1284         if (mount_point &&
1285                 access(mount_point, F_OK) != 0) {
1286                 data->mount_point = strdup(mount_point);
1287                 bdev->mount_point_updated = true;
1288         } else {
1289                 data->mount_point = generate_mount_path(data);
1290                 bdev->mount_point_updated = false;
1291         }
1292
1293         return 0;
1294 }
1295
1296 static int mount_block_device(struct block_device *bdev)
1297 {
1298         struct block_data *data;
1299         int r;
1300
1301         if (!bdev || !bdev->data)
1302                 return -EINVAL;
1303
1304         data = bdev->data;
1305         if (data->state == BLOCK_MOUNT) {
1306                 _I("%s is already mounted", data->devnode);
1307                 return 0;
1308         }
1309
1310         if (!block_conf[data->block_type].multimount &&
1311             !data->primary) {
1312                 _I("Not support multi mount by config info");
1313                 return 0;
1314         }
1315
1316         r = mount_start(bdev);
1317         if (r < 0) {
1318                 _E("Failed to mount (%s)", data->devnode);
1319                 return r;
1320         }
1321
1322         return 0;
1323 }
1324
1325 static int block_unmount(struct block_device *bdev,
1326                 enum unmount_operation option)
1327 {
1328         struct block_data *data;
1329         int r, retry = 0;
1330         struct timespec time = {0,};
1331
1332         if (!bdev || !bdev->data || !bdev->data->mount_point)
1333                 return -EINVAL;
1334
1335         data = bdev->data;
1336
1337         if (bdev->on_private_op == REQ_NORMAL)
1338                 signal_device_blocked(bdev);
1339
1340         /* it must called before unmounting mmc */
1341         r = mmc_check_and_unmount(data->mount_point);
1342         if (!r)
1343                 goto out;
1344         if (option == UNMOUNT_NORMAL) {
1345                 _I("Failed to unmount with normal option : %d", r);
1346                 return r;
1347         }
1348
1349         _I("Execute force unmount!");
1350         /* Force Unmount Scenario */
1351         while (1) {
1352                 switch (retry++) {
1353                 case 0:
1354                         /* Mobile specific:
1355                          * should unmount the below vconf key. */
1356                         if ((data->block_type == BLOCK_MMC_DEV ||
1357                                 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1358                                 data->primary) {
1359                                 /* At first, notify to other app
1360                                  * who already access sdcard */
1361                                 _I("Notify to other app who already access sdcard");
1362                                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1363                                                 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1364                         }
1365                         break;
1366                 case 1:
1367                         /* Second, kill app with SIGTERM */
1368                         _I("Kill app with SIGTERM");
1369                         terminate_process(data->mount_point, false);
1370                         break;
1371                 case 2:
1372                         /* Last time, kill app with SIGKILL */
1373                         _I("Kill app with SIGKILL");
1374                         terminate_process(data->mount_point, true);
1375                         break;
1376                 default:
1377                         if (umount2(data->mount_point, MNT_DETACH) != 0) {
1378                                 _I("Failed to unmount with lazy option : %d",
1379                                                 errno);
1380                                 return -errno;
1381                         }
1382                         goto out;
1383                 }
1384
1385                 /* it takes some seconds til other app completely clean up */
1386                 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1387                 nanosleep(&time, NULL);
1388
1389                 print_open_files(data->mount_point);
1390
1391                 r = mmc_check_and_unmount(data->mount_point);
1392                 if (!r) {
1393                         _D("Success to unmount (%s)", data->mount_point);
1394                         break;
1395                 }
1396         }
1397
1398 out:
1399         data->state = BLOCK_UNMOUNT;
1400
1401         if (rmdir(data->mount_point) < 0)
1402                 _E("fail to remove %s directory", data->mount_point);
1403
1404         return r;
1405 }
1406
1407 static int unmount_block_device(struct block_device *bdev,
1408                 enum unmount_operation option)
1409 {
1410         struct block_data *data;
1411         int r;
1412
1413         if (!bdev || !bdev->data)
1414                 return -EINVAL;
1415
1416         data = bdev->data;
1417         if (data->state == BLOCK_UNMOUNT) {
1418                 _I("%s is already unmounted", data->devnode);
1419                 r = mmc_check_and_unmount(data->mount_point);
1420                 if (r < 0)
1421                         _E("The path was existed, but could not delete it(%s)",
1422                                         data->mount_point);
1423                 return 0;
1424         }
1425
1426         _I("Unmount Start : (%s -> %s)",
1427                         data->devnode, data->mount_point);
1428
1429         r = block_unmount(bdev, option);
1430         if (r < 0) {
1431                 _E("fail to unmount %s device : %d", data->devnode, r);
1432                 goto out;
1433         }
1434
1435         BLOCK_FLAG_MOUNT_CLEAR(data);
1436
1437 out:
1438         _I("%s result : %s, %d", __func__, data->devnode, r);
1439
1440         if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1441                 _E("fail to trigger pipe");
1442
1443         return r;
1444 }
1445
1446 static int block_format(struct block_data *data,
1447                 const char *fs_type, bool mount_point_updated)
1448 {
1449         const struct block_fs_ops *fs;
1450         dd_list *elem;
1451         const char *fstype;
1452         int len;
1453         int r;
1454
1455         if (!data || !data->devnode || !data->mount_point)
1456                 return -EINVAL;
1457
1458         if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1459                 fstype = EXT4_NAME;
1460         else {
1461                 if (!fs_type) {
1462                         if (!data->fs_type)
1463                                 return -ENOTSUP;
1464                         fstype = data->fs_type;
1465                 } else
1466                         fstype = fs_type;
1467         }
1468
1469         fs = NULL;
1470         len = strlen(fstype);
1471         DD_LIST_FOREACH(fs_head, elem, fs) {
1472                 if (!strncmp(fs->name, fstype, len))
1473                         break;
1474         }
1475
1476         if (!fs) {
1477                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1478                 _E("not supported file system(%s)", fstype);
1479                 return -ENOTSUP;
1480         }
1481
1482         _I("format path : %s", data->devnode);
1483         fs->check(data->devnode);
1484         r = fs->format(data->devnode);
1485         if (r < 0) {
1486                 _E("fail to format block data for %s", data->devnode);
1487                 goto out;
1488         }
1489
1490         /* need to update the partition data.
1491          * It can be changed in doing format. */
1492         retrieve_udev_device(data, mount_point_updated);
1493 out:
1494         return r;
1495 }
1496
1497 static int format_block_device(struct block_device *bdev,
1498                 const char *fs_type,
1499                 enum unmount_operation option)
1500 {
1501         struct block_data *data;
1502         int r;
1503
1504         assert(bdev);
1505         assert(bdev->data);
1506
1507         data = bdev->data;
1508
1509         _I("Format Start : (%s -> %s)",
1510                         data->devnode, data->mount_point);
1511
1512         if (data->state == BLOCK_MOUNT) {
1513                 r = block_unmount(bdev, option);
1514                 if (r < 0) {
1515                         _E("fail to unmount %s device : %d", data->devnode, r);
1516                         goto out;
1517                 }
1518         }
1519
1520         r = block_format(data, fs_type, bdev->mount_point_updated);
1521         if (r < 0)
1522                 _E("fail to format %s device : %d", data->devnode, r);
1523
1524 out:
1525         _I("%s result : %s, %d", __func__, data->devnode, r);
1526
1527         r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1528         if (r < 0)
1529                 _E("fail to trigger pipe");
1530
1531         return r;
1532 }
1533
1534 static struct format_data *get_format_data(
1535                 const char *fs_type, enum unmount_operation option)
1536 {
1537         struct format_data *fdata;
1538
1539         fdata = (struct format_data *)malloc(sizeof(struct format_data));
1540         if (!fdata) {
1541                 _E("fail to allocate format data");
1542                 return NULL;
1543         }
1544
1545         if (fs_type)
1546                 fdata->fs_type = strdup(fs_type);
1547         else
1548                 fdata->fs_type = NULL;
1549         fdata->option = option;
1550
1551         return fdata;
1552 }
1553
1554 static void release_format_data(struct format_data *data)
1555 {
1556         if (data) {
1557                 if (data->fs_type)
1558                         free(data->fs_type);
1559                 free(data);
1560         }
1561 }
1562
1563 // Called by BlockThread - Real Mount Op
1564 static int block_mount_device(struct block_device *bdev, void *data)
1565 {
1566         dd_list *l;
1567         int ret;
1568         int thread_id;
1569
1570         if (!bdev)
1571                 return -EINVAL;
1572
1573         thread_id = bdev->thread_id;
1574         if (thread_id < 0 || thread_id >= THREAD_MAX)
1575                 return -EINVAL;
1576         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1577         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1578         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1579         if (!l) {
1580                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1581                 return -ENOENT;
1582         }
1583
1584         /* mount automatically */
1585         ret = mount_block_device(bdev);
1586         if (ret < 0)
1587                 _E("fail to mount block device for %s", bdev->data->devnode);
1588
1589         return ret;
1590 }
1591
1592 // Called by BlockThread - Real Format Op
1593 static int block_format_device(struct block_device *bdev, void *data)
1594 {
1595         dd_list *l;
1596         int ret;
1597         int thread_id;
1598         struct format_data *fdata = (struct format_data *)data;
1599
1600         if (!bdev || !fdata) {
1601                 ret = -EINVAL;
1602                 goto out;
1603         }
1604
1605         thread_id = bdev->thread_id;
1606         if (thread_id < 0 || thread_id >= THREAD_MAX)
1607                 return -EINVAL;
1608         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1609         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1610         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1611         if (!l) {
1612                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1613                 ret = -ENOENT;
1614                 goto out;
1615         }
1616
1617         ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1618         if (ret < 0)
1619                 _E("fail to mount block device for %s", bdev->data->devnode);
1620
1621 out:
1622         release_format_data(fdata);
1623
1624         return ret;
1625 }
1626
1627 // Called by BlockThread - Real Unmount Op
1628 static int block_unmount_device(struct block_device *bdev, void *data)
1629 {
1630         int ret;
1631         long option = (long)data;
1632
1633         if (!bdev)
1634                 return -EINVAL;
1635
1636         ret = unmount_block_device(bdev, option);
1637         if (ret < 0) {
1638                 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1639                 return ret;
1640         }
1641
1642         return 0;
1643 }
1644
1645 /* Called by BlockThread - Remove Operation
1646    Direct Call at BlockThread
1647    Previously this function was called by MainThread. However, it will increase complexity.
1648    Need thread lock before to call remove_operation
1649 */
1650 static void remove_operation(struct block_device *bdev)
1651 {
1652         struct operation_queue *op;
1653         dd_list *l, *next;
1654         char name[16];
1655         int thread_id;
1656
1657         assert(bdev);
1658
1659         thread_id = bdev->thread_id;
1660         if (thread_id < 0 || thread_id >= THREAD_MAX)
1661                 return;
1662
1663         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1664                 if (op->done) {
1665                         _D("Remove operation (%s, %s)",
1666                                         get_operation_char(op->op, name, sizeof(name)),
1667                                         bdev->data->devnode);
1668
1669                         DD_LIST_REMOVE(bdev->op_queue, op);
1670                         free(op);
1671                 }
1672         }
1673 }
1674
1675 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1676 {
1677         DBusMessage *rep;
1678
1679         if (!reply_handle)
1680                 return;
1681
1682         rep = make_dbus_reply_message_simple(reply_handle, result);
1683         reply_dbus_method_result(reply_handle, rep);
1684 }
1685
1686 // Called by BlockThread
1687 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1688 {
1689         struct operation_queue *temp;
1690         dd_list *l;
1691         int thread_id;
1692
1693         if (!bdev)
1694                 return;
1695
1696         if (!queue)
1697                 return;
1698
1699         if (!op)
1700                 return;
1701
1702         thread_id = bdev->thread_id;
1703         if (thread_id < 0 || thread_id >= THREAD_MAX)
1704                 return;
1705
1706         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1707
1708         DD_LIST_FOREACH(*queue, l, temp) {
1709                 if (temp->op == BLOCK_DEV_REMOVE) {
1710                         *op = temp;
1711                         break;
1712                 }
1713                 temp->done = true;
1714                 th_manager[thread_id].op_len--;
1715                 block_send_dbus_reply((*op)->reply_handle, 0);
1716         }
1717
1718         remove_operation(bdev);
1719         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1720 }
1721
1722 // Called by BlockThread
1723 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1724 {
1725         struct operation_queue *temp;
1726         dd_list *l;
1727         int thread_id;
1728         bool unmounted = false;
1729
1730         if (!bdev)
1731                 return false;
1732
1733         if (!queue)
1734                 return false;
1735
1736         if (!op)
1737                 return false;
1738
1739         thread_id = bdev->thread_id;
1740         if (thread_id < 0 || thread_id >= THREAD_MAX)
1741                 return false;
1742
1743         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1744         DD_LIST_FOREACH(*queue, l, temp) {
1745                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1746                         unmounted = true;
1747                         _D("Operation queue has unmount operation");
1748                         break;
1749                 }
1750         }
1751         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1752
1753         if (!unmounted)
1754                 return unmounted;
1755
1756         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1757
1758         DD_LIST_FOREACH(*queue, l, temp) {
1759                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1760                         *op = temp;
1761                         break;
1762                 }
1763                 temp->done = true;
1764                 th_manager[thread_id].op_len--;
1765                 block_send_dbus_reply((*op)->reply_handle, 0);
1766         }
1767
1768         remove_operation(bdev);
1769         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1770
1771         return unmounted;
1772 }
1773
1774 // Called by BlockThread
1775 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1776 {
1777         int ret = 0;
1778         int thread_id;
1779         char devnode[PATH_MAX];
1780         char name[16];
1781         enum block_dev_operation operation;
1782         bool unmounted = false;
1783
1784         assert(bdev);
1785
1786         if (!queue)
1787                 return;
1788
1789         thread_id = bdev->thread_id;
1790         if (thread_id < 0 || thread_id >= THREAD_MAX)
1791                 return;
1792
1793         snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1794
1795         do {
1796                 if (!op)
1797                         return;
1798                 if (op->done)
1799                         return;
1800
1801                 operation = op->op;
1802
1803                 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1804                         get_operation_char(operation, name, sizeof(name)), devnode);
1805
1806                 unmounted = false;
1807                 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1808                         check_removed(bdev, &queue, &op);
1809                         operation = op->op;
1810                         _D("Trigger operation again (%s, %s)",
1811                                 get_operation_char(operation, name, sizeof(name)), devnode);
1812                 }
1813                 if (operation == BLOCK_DEV_MOUNT) {
1814                         unmounted = check_unmount(bdev, &queue, &op);
1815                         if (unmounted) {
1816                                 operation = op->op;
1817                                 _D("Trigger operation again (%s, %s)",
1818                                         get_operation_char(operation, name, sizeof(name)), devnode);
1819                         }
1820                 }
1821
1822                 switch (operation) {
1823                 case BLOCK_DEV_INSERT:
1824                         break;
1825                 case BLOCK_DEV_MOUNT:
1826                         ret = block_mount_device(bdev, op->data);
1827                         _D("Mount (%s) result:(%d)", devnode, ret);
1828                         break;
1829                 case BLOCK_DEV_FORMAT:
1830                         ret = block_format_device(bdev, op->data);
1831                         _D("Format (%s) result:(%d)", devnode, ret);
1832                         break;
1833                 case BLOCK_DEV_UNMOUNT:
1834                         ret = block_unmount_device(bdev, op->data);
1835                         _D("Unmount (%s) result:(%d)", devnode, ret);
1836                         break;
1837                 case BLOCK_DEV_REMOVE:
1838                         /* Do nothing */
1839                         break;
1840                 case BLOCK_LUKS_CLOSE:
1841                         ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1842                         if (ret < 0)
1843                                 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1844                         break;
1845                 default:
1846                         _E("Operation type is invalid (%d)", op->op);
1847                         ret = -EINVAL;
1848                         break;
1849                 }
1850
1851                 /* LOCK
1852                  * during checking the queue length */
1853                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1854
1855                 op->done = true;
1856                 th_manager[thread_id].op_len--;
1857
1858                 block_send_dbus_reply(op->reply_handle, ret);
1859
1860                 queue = bdev->op_queue;
1861                 if (queue != NULL) {
1862                         queue = DD_LIST_NEXT(queue);
1863                         if (queue != NULL)
1864                                 op = DD_LIST_NTH(queue, 0);
1865                         else
1866                                 op = NULL;
1867                 } else
1868                         op = NULL;
1869
1870                 remove_operation(bdev);
1871
1872                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1873                 /* UNLOCK */
1874
1875                 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1876                         if (pipe_trigger(operation, bdev, 0) < 0)
1877                                 _E("fail to trigger pipe");
1878                 }
1879
1880         } while (true);
1881
1882 }
1883
1884 // Called by BlockThread
1885 static void *block_th_start(void *arg)
1886 {
1887         struct block_device *temp;
1888         struct manage_thread *th = (struct manage_thread *)arg;
1889         struct operation_queue *op = NULL;
1890         dd_list *elem;
1891         dd_list *queue = NULL;
1892         int thread_id;
1893
1894         assert(th);
1895
1896         thread_id = th->thread_id;
1897         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1898                 _E("Thread Number: %d", th->thread_id);
1899                 return NULL;
1900         }
1901
1902         do {
1903                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1904                 if (th_manager[thread_id].op_len == 0) {
1905                         _D("Operation queue of thread is empty");
1906                         pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1907                         _D("Wake up %d", thread_id);
1908                 }
1909
1910                 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1911                         queue = temp->op_queue;
1912                         do {
1913                                 op = DD_LIST_NTH(queue, 0);
1914                                 if (!op) {
1915                                         _D("Operation queue for device %s is Empty", temp->data->devnode);
1916                                         break;
1917                                 }
1918                                 if (op->done) {
1919                                         queue = DD_LIST_NEXT(queue);
1920                                         continue;
1921                                 }
1922                                 break;
1923                         } while (true);
1924                         if (op)
1925                                 break;
1926                 }
1927                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1928
1929                 if (op && !op->done)
1930                         trigger_operation(temp, queue, op);
1931
1932         } while (true);
1933 }
1934
1935 // This function will be refactored later
1936 // Especially, we don't need to keep th_node_list.
1937 static int find_thread(char *devnode)
1938 {
1939         dd_list *elem;
1940         char str[PATH_MAX];
1941         char *th_node;
1942         char *temp;
1943         char dev_scsi;
1944         int i, len, min, min_num;
1945         int dev_mmc = -1, part = -1, num;
1946
1947         len = 0;
1948         if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1949                 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1950                 num = dev_mmc;
1951                 while (num > 0) {
1952                         num = num / 10;
1953                         len++;
1954                 }
1955                 len = len + 12;
1956                 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1957                 th_node = strdup(str);
1958         } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1959                 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1960                 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1961                 th_node = strdup(str);
1962         } else
1963                 th_node = strdup(devnode);
1964
1965         len = strlen(th_node) + 1;
1966         min_num = 1000;
1967         min = -1;
1968         for (i = 0; i < THREAD_MAX; i++) {
1969                 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1970                         if (!strncmp(temp, th_node, len)) {
1971                                 free(th_node);
1972                                 return i;
1973                         }
1974                 }
1975                 if (th_manager[i].num_dev < min_num) {
1976                         min_num = th_manager[i].num_dev;
1977                         min = i;
1978                 }
1979         }
1980
1981         if (min >= 0 && min < THREAD_MAX) {
1982                 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1983                 return min;
1984         }
1985
1986         _E("Finding thread is failed");
1987         DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1988         return 0;
1989 }
1990
1991 /* Only Main thread is permmited */
1992 // Called by MainThread
1993 static int add_operation(struct block_device *bdev,
1994                 enum block_dev_operation operation,
1995                 dbus_method_reply_handle_h reply_handle, void *data)
1996 {
1997         struct operation_queue *op;
1998         int ret;
1999         int thread_id;
2000         bool start_th;
2001         char name[16];
2002
2003         if (!bdev)
2004                 return -EINVAL;
2005
2006
2007         _I("Add operation (%s, %s)",
2008                         get_operation_char(operation, name, sizeof(name)),
2009                         bdev->data->devnode);
2010
2011         thread_id = bdev->thread_id;
2012         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2013                 _E("Fail to find thread to add");
2014                 return -EPERM;
2015         }
2016
2017         op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2018         if (!op) {
2019                 _E("malloc failed");
2020                 return -ENOMEM;
2021         }
2022
2023         op->op = operation;
2024         op->data = data;
2025         op->reply_handle = reply_handle;
2026
2027         /* LOCK
2028          * during adding queue and checking the queue length */
2029         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2030
2031         /* Only modified between lock and unlock of mutex */
2032         op->done = false;
2033
2034         start_th = th_manager[thread_id].start_th;
2035         DD_LIST_APPEND(bdev->op_queue, op);
2036         th_manager[thread_id].op_len++;
2037
2038         if (th_manager[thread_id].op_len == 1 && !start_th)
2039                 pthread_cond_signal(&(th_manager[thread_id].cond));
2040
2041         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2042         /* UNLOCK */
2043
2044         /* Need to disble app2ext whenever unmounting mmc */
2045         if (op->op == BLOCK_DEV_UNMOUNT &&
2046                 bdev->data->state == BLOCK_MOUNT &&
2047                 bdev->data->block_type == BLOCK_MMC_DEV &&
2048                 bdev->data->primary)
2049                 if (app2ext_disable_all_external_pkgs() < 0)
2050                         _E("app2ext_disable_all_external_pkgs() failed");
2051
2052
2053         if (start_th) {
2054                 _D("Start New thread for block device");
2055                 th_manager[thread_id].start_th = false;
2056                 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2057                 if (ret != 0) {
2058                         _E("fail to create thread for %s", bdev->data->devnode);
2059                         return -EPERM;
2060                 }
2061
2062                 pthread_detach(th_manager[thread_id].th);
2063         }
2064
2065         return 0;
2066 }
2067
2068 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2069 {
2070         DIR *dp;
2071         struct dirent entry;
2072         struct dirent *dir;
2073         const char *syspath;
2074         bool ret = false;
2075
2076         syspath = udev_device_get_syspath(dev);
2077         if (!syspath)
2078                 goto out;
2079
2080         dp = opendir(syspath);
2081         if (!dp) {
2082                 _E("fail to open %s", syspath);
2083                 goto out;
2084         }
2085
2086         /* TODO compare devname and d_name */
2087         while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2088                 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2089                     !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2090                         ret = true;
2091                         break;
2092                 }
2093         }
2094
2095         closedir(dp);
2096
2097 out:
2098         return ret;
2099 }
2100
2101 static bool check_partition(struct udev_device *dev)
2102 {
2103         const char *devtype;
2104         const char *part_table_type;
2105         const char *fs_usage;
2106         bool ret = false;
2107
2108         /* only consider disk type, never partitions */
2109         devtype = udev_device_get_devtype(dev);
2110         if (!devtype)
2111                 goto out;
2112
2113         if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2114                                 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2115                 goto out;
2116
2117         part_table_type = udev_device_get_property_value(dev,
2118                         "ID_PART_TABLE_TYPE");
2119         if (part_table_type) {
2120                 fs_usage = udev_device_get_property_value(dev,
2121                                 "ID_FS_USAGE");
2122                 if (fs_usage &&
2123                     strncmp(fs_usage, FILESYSTEM_NAME, sizeof(FILESYSTEM_NAME)) == 0) {
2124                         if (!disk_is_partitioned_by_kernel(dev))
2125                                         goto out;
2126                 }
2127                 ret = true;
2128                 goto out;
2129         }
2130
2131         if (disk_is_partitioned_by_kernel(dev)) {
2132                 ret = true;
2133                 goto out;
2134         }
2135
2136 out:
2137         return ret;
2138 }
2139
2140 // Called by MainThread
2141 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2142 {
2143         struct block_data *data;
2144         struct block_device *bdev;
2145         //char id_string[PATH_LEN];
2146         bool partition;
2147         int ret;
2148         int thread_id;
2149         bool need_format = false;
2150
2151         partition = check_partition(dev);
2152         if (partition) {
2153                 /* if there is a partition, skip this request */
2154                 _I("%s device has partitions, skip this time", devnode);
2155                 return 0;
2156         }
2157
2158         if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2159                 char syspath[128] = {0};
2160                 char *r;
2161
2162                 r = rindex(udev_device_get_syspath(dev), '/');
2163                 if (!r) return -ENODEV;
2164
2165                 snprintf(syspath, sizeof(syspath), "/sys/block%s", r);
2166
2167                 data = make_block_data(devnode,
2168                                 syspath,
2169                                 FILESYSTEM_NAME,
2170                                 EXT4_NAME,
2171                                 "1.0",
2172                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2173                                 udev_device_get_sysattr_value(dev, "ro"));
2174                 need_format = true;
2175         } else {
2176                 data = make_block_data(devnode,
2177                                 udev_device_get_syspath(dev),
2178                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2179                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2180                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2181                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2182                                 udev_device_get_sysattr_value(dev, "ro"));
2183         }
2184
2185         if (!data) {
2186                 _E("fail to make block data for %s", devnode);
2187                 return -EPERM;
2188         }
2189
2190         if (!block_conf[data->block_type].multimount && !data->primary &&
2191             data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME)) {
2192                 _D("Not support multi mount by config info");
2193                 free_block_data(data);
2194                 return -EPERM;
2195         }
2196
2197         bdev = make_block_device(data);
2198         if (!bdev) {
2199                 _E("fail to make block device for %s", devnode);
2200                 free_block_data(data);
2201                 return -EPERM;
2202         }
2203
2204         thread_id = find_thread(bdev->data->devnode);
2205         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2206                 _E("Fail to find thread to add");
2207                 free_block_device(bdev);
2208                 return -EPERM;
2209         }
2210         bdev->thread_id = thread_id;
2211
2212         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2213         th_manager[thread_id].num_dev++;
2214         DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2215         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2216
2217         if (need_format) {
2218                 struct format_data *fdata;
2219
2220                 fdata = get_format_data(NULL, UNMOUNT_FORCE);
2221                 if (!fdata) {
2222                         _E("Failed to get format data");
2223                         return -ENOMEM;
2224                 }
2225
2226                 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2227                 if (ret < 0) {
2228                         _E("Failed to add operation (format %s)", bdev->data->devnode);
2229                         release_format_data(fdata);
2230                 }
2231         }
2232
2233         if (!bdev->data->fs_type) {
2234                 _E("Unformatted Storage");
2235                 free_block_device(bdev);
2236                 return -EPERM;
2237         } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2238 //              bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2239                 bdev->data->primary = true;
2240                 _D("Need to unlock encrypted sdcard");
2241                 // ---- ODE UI launch ----
2242                 ret = launch_system_app(POPUP_DEFAULT
2243                                       , 8
2244                                       , POPUP_KEY_CONTENT
2245                                       , "unlockextendedsd"
2246                                       , VIEWTYPE_KEY
2247                                       , INSERT_SD_CARD
2248                                       , DEVPATH_KEY
2249                                       , bdev->data->devnode
2250                                       , MAPPING_NODE_KEY
2251                                       , EXTENDEDSD_NAME);
2252                 if (ret < 0)
2253                         _E("Failed to launch popup");
2254
2255                 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2256                 if (ret < 0) {
2257                         _E("Failed to add operation (insert %s)", devnode);
2258                         free_block_device(bdev);
2259                         return ret;
2260                 }
2261
2262                 return 0;
2263         } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2264                 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2265                 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2266                 if (ret < 0) {
2267                         ret = -EPERM;
2268                         free_block_device(bdev);
2269                         return ret;
2270                 }
2271         }
2272
2273         ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2274         if (ret < 0) {
2275                 _E("Failed to add operation (insert %s)", devnode);
2276                 free_block_device(bdev);
2277                 return ret;
2278         }
2279
2280         // Not a regular filesystem -> skip mounting
2281         if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM_NAME)) {
2282                 _I("Not a filesystem. Not mounting");
2283                 return 0;
2284         }
2285
2286         /* Create file for block device /run/external-storage/id */
2287         create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2288         ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2289         if (ret < 0) {
2290                 _E("Failed to add operation (mount %s)", devnode);
2291                 return ret;
2292         }
2293         return 0;
2294 }
2295
2296 static int remove_block_device(struct udev_device *dev, const char *devnode)
2297 {
2298         struct block_device *bdev;
2299         struct block_device *bdev_extended;
2300         int ret;
2301
2302         bdev = find_block_device(devnode);
2303         if (!bdev) {
2304                 _E("fail to find block data for %s", devnode);
2305                 return -ENODEV;
2306         }
2307
2308         BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2309
2310         bdev->removed = true;
2311         if (bdev->on_private_op != REQ_NORMAL) {
2312                 bdev->on_private_op = REQ_NORMAL;
2313                 _D("Private operation state: %d", bdev->on_private_op);
2314         }
2315
2316         if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2317                 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2318
2319                 if (bdev_extended) {
2320                         BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2321
2322                         bdev_extended->removed = true;
2323                         if (bdev_extended->on_private_op != REQ_NORMAL) {
2324                                 bdev_extended->on_private_op = REQ_NORMAL;
2325                                 _D("Private operation state: %d", bdev_extended->on_private_op);
2326                         }
2327
2328                         ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2329                         if (ret < 0) {
2330                                 _E("Failed to add operation (unmount %s)", devnode);
2331                                 return ret;
2332                         }
2333
2334                         ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2335                         if (ret < 0) {
2336                                 _E("Failed to add operation (remove %s)", devnode);
2337                                 return ret;
2338                         }
2339
2340                         ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2341                         if (ret < 0) {
2342                                 _E("Failed to add operation (luks_close %s)", devnode);
2343                                 return ret;
2344                         }
2345                 } else
2346                         _E("fail to find block data for extended sd card");
2347         }
2348
2349         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2350         if (ret < 0) {
2351                 _E("Failed to add operation (unmount %s)", devnode);
2352                 return ret;
2353         }
2354
2355         ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2356         if (ret < 0) {
2357                 _E("Failed to add operation (remove %s)", devnode);
2358                 return ret;
2359         }
2360
2361         return 0;
2362 }
2363
2364 static int get_internal_storage_number(void)
2365 {
2366         struct libmnt_table *t = NULL;
2367         struct libmnt_fs *fs;
2368         const char *temp;
2369         char *name;
2370         int r = 0, dev_temp;
2371
2372         if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2373                 (is_emulator() && dev_internal_emul != '\0'))
2374                 return 0;
2375
2376         t = mnt_new_table();
2377         if (!t)
2378                 return -EPERM;
2379
2380         r = mnt_table_parse_mtab(t, NULL);
2381         if (r < 0) {
2382                 mnt_free_table(t);
2383                 return -EPERM;
2384         }
2385
2386         fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2387
2388         if (!fs) {
2389                 mnt_free_table(t);
2390                 return -EPERM;
2391         }
2392         temp = mnt_fs_get_srcpath(fs);
2393         if (!temp)
2394                 return -EPERM;
2395
2396         name = strrchr(temp, '/');
2397         if (!name)
2398                 return -EPERM;
2399         name++;
2400         /* Boot from USB is not handled */
2401         if (!is_emulator()) {
2402                 if (!fnmatch(MMC_PATH, temp, 0))
2403                         sscanf(name, "mmcblk%d", &dev_internal);
2404                 else if (!fnmatch(SCSI_PATH, temp, 0))
2405                         sscanf(name, "sd%c", &dev_internal_scsi);
2406         } else {
2407                 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2408                         sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2409                 else
2410                         dev_internal_emul = '\0';
2411         }
2412
2413         mnt_free_table(t);
2414
2415         return 0;
2416 }
2417
2418 static int check_external_storage(const char* devnode)
2419 {
2420         char dev_scsi = '\0';
2421         char *name;
2422         char emul = '\0';
2423         int dev_num = -1, dev_temp;
2424
2425         if (!devnode)
2426                 return -EPERM;
2427
2428         name = strrchr(devnode, '/');
2429         if (!name)
2430                 return -EPERM;
2431         name++;
2432         if (!is_emulator()) {
2433                 if (!fnmatch(MMC_PATH, devnode, 0)) {
2434                         sscanf(name, "mmcblk%d", &dev_num);
2435                         if (dev_internal == dev_num) {
2436                                 _D("%s is internal storage", devnode);
2437                                 return 0;
2438                         }
2439                 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2440                         sscanf(name, "sd%c", &dev_scsi);
2441                         if (dev_internal_scsi == dev_scsi) {
2442                                 _D("%s is internal storage", devnode);
2443                                 return 0;
2444                         }
2445                 }
2446         } else {
2447                 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2448                         sscanf(name, "vd%c%d", &emul, &dev_temp);
2449                         if (dev_internal_emul == emul) {
2450                                 _D("%s is internal storage", devnode);
2451                                 return 0;
2452                         }
2453                 }
2454         }
2455
2456         return 1;
2457 }
2458
2459 static int check_already_handled(const char* devnode)
2460 {
2461         struct block_device *bdev;
2462         struct block_data *data;
2463         dd_list *elem;
2464         int i;
2465
2466         for (i = 0; i < THREAD_MAX; i++) {
2467                 pthread_mutex_lock(&(th_manager[i].mutex));
2468                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2469                         data = bdev->data;
2470                         if (!data)
2471                                 continue;
2472                         if (bdev->removed)
2473                                 continue;
2474                         if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2475                                 pthread_mutex_unlock(&(th_manager[i].mutex));
2476                                 return -1;
2477                         }
2478                 }
2479                 pthread_mutex_unlock(&(th_manager[i].mutex));
2480         }
2481
2482         return 0;
2483 }
2484
2485 static int block_init_from_udev_enumerate(void)
2486 {
2487         struct udev *udev;
2488         struct udev_enumerate *enumerate;
2489         struct udev_list_entry *list_entry, *list_sub_entry;
2490         struct udev_device *dev;
2491         const char *syspath;
2492         const char *devnode;
2493         int r = 0;
2494
2495         udev = udev_new();
2496         if (!udev) {
2497                 _E("fail to create udev library context");
2498                 return -EPERM;
2499         }
2500
2501         /* create a list of the devices in the 'usb' subsystem */
2502         enumerate = udev_enumerate_new(udev);
2503         if (!enumerate) {
2504                 _E("fail to create an enumeration context");
2505                 return -EPERM;
2506         }
2507
2508         if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2509                 (is_emulator() && dev_internal_emul == '\0')) {
2510                 r = get_internal_storage_number();
2511                 if (r < 0)
2512                         return -EPERM;
2513         }
2514
2515         udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2516         udev_enumerate_add_match_property(enumerate,
2517                         UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2518         udev_enumerate_add_match_property(enumerate,
2519                         UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2520         udev_enumerate_scan_devices(enumerate);
2521
2522         udev_list_entry_foreach(list_entry,
2523                         udev_enumerate_get_list_entry(enumerate)) {
2524                 syspath = udev_list_entry_get_name(list_entry);
2525                 if (!syspath)
2526                         continue;
2527
2528                 dev = udev_device_new_from_syspath(
2529                                 udev_enumerate_get_udev(enumerate),
2530                                 syspath);
2531                 if (!dev)
2532                         continue;
2533
2534                 devnode = NULL;
2535                 udev_list_entry_foreach(list_sub_entry,
2536                                 udev_device_get_devlinks_list_entry(dev)) {
2537                         const char *devlink = udev_list_entry_get_name(list_sub_entry);
2538                         if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2539                                 devnode = devlink;
2540                                 break;
2541                         }
2542                 }
2543
2544                 if (!devnode) {
2545                         devnode = udev_device_get_devnode(dev);
2546                         if (!devnode)
2547                                 continue;
2548
2549                         if (fnmatch(MMC_PATH, devnode, 0) &&
2550                             fnmatch(SCSI_PATH, devnode, 0) &&
2551                             fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
2552                                 continue;
2553                 }
2554
2555                 r = check_external_storage(devnode);
2556                 if (r <= 0)
2557                         continue;
2558
2559                 r = check_already_handled(devnode);
2560                 if (r < 0) {
2561                         _I("%s is already handled", devnode);
2562                         continue;
2563                 }
2564
2565                 _I("%s device add", devnode);
2566                 add_block_device(dev, devnode, false);
2567
2568                 udev_device_unref(dev);
2569         }
2570
2571         udev_enumerate_unref(enumerate);
2572         udev_unref(udev);
2573         return 0;
2574 }
2575
2576 // Called by MainThread
2577 static void show_block_device_list(void)
2578 {
2579         struct block_device *bdev;
2580         struct block_data *data;
2581         dd_list *elem;
2582         int i;
2583
2584         for (i = 0; i < THREAD_MAX; i++) {
2585                 pthread_mutex_lock(&(th_manager[i].mutex));
2586                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2587                         data = bdev->data;
2588                         if (!data)
2589                                 continue;
2590                         if (bdev->removed)
2591                                 continue;
2592                         _D("%s:", data->devnode);
2593                         _D("\tSyspath: %s", data->syspath);
2594                         _D("\tBlock type: %d", data->block_type);
2595                         _D("\tFs type: %s", data->fs_type);
2596                         _D("\tFs usage: %s", data->fs_usage);
2597                         _D("\tFs version: %s", data->fs_version);
2598                         _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2599                         _D("\tReadonly: %s",
2600                                         (data->readonly ? "true" : "false"));
2601                         _D("\tMount point: %s", data->mount_point);
2602                         _D("\tMount state: %s",
2603                                         (data->state == BLOCK_MOUNT ?
2604                                          "mount" : "unmount"));
2605                         _D("\tPrimary: %s",
2606                                         (data->primary ? "true" : "false"));
2607                         _D("\tID: %d", data->id);
2608                 }
2609                 pthread_mutex_unlock(&(th_manager[i].mutex));
2610         }
2611 }
2612
2613 // Called by MainThread
2614 static void remove_whole_block_device(void)
2615 {
2616         struct block_device *bdev;
2617         dd_list *elem;
2618         dd_list *next;
2619         int r;
2620         int i;
2621
2622         for (i = 0; i < THREAD_MAX; i++) {
2623                 do {
2624                         pthread_mutex_lock(&(th_manager[i].mutex));
2625                         DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2626                                 if (bdev->removed == false)
2627                                         break;
2628                         }
2629                         pthread_mutex_unlock(&(th_manager[i].mutex));
2630
2631                         if (bdev && bdev->removed == false) {
2632                                 bdev->removed = true;
2633                                 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2634                                 if (r < 0)
2635                                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2636
2637                                 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2638                                 if (r < 0)
2639                                         _E("Failed to add operation (remove %s)", bdev->data->devnode);
2640                         } else
2641                                 break;
2642                 } while (true);
2643         }
2644 }
2645
2646 static void booting_done(const char *sender_name,
2647                 const char *object_path, const char *interface_name,
2648                 const char *signal_name, DBusMessage *msg,
2649                 void *data)
2650 {
2651         static int done = 0;
2652         if (done > 0)
2653                 return;
2654         done = 1;
2655         _I("Booting done");
2656         /* if there is the attached device, try to mount */
2657         block_init_from_udev_enumerate();
2658         block_control = true;
2659         block_boot = true;
2660 }
2661
2662 static void block_poweroff(const char *sender_name,
2663                 const char *object_path, const char *interface_name,
2664                 const char *signal_name, DBusMessage *msg,
2665                 void *data)
2666 {
2667         static int status = 0;
2668         if (status > 0)
2669                 return;
2670         status = 1;
2671         _I("Power off");
2672         /* unregister mmc uevent control routine */
2673         unregister_udev_uevent_control(&uh);
2674         remove_whole_block_device();
2675 }
2676
2677 static void uevent_block_handler(struct udev_device *dev)
2678 {
2679         const char *devnode = NULL;
2680         const char *action;
2681         struct udev_list_entry *list_entry;
2682         int r;
2683         bool mapper = false;
2684
2685         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2686                 const char *devlink = udev_list_entry_get_name(list_entry);
2687                 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2688                         devnode = devlink;
2689                         break;
2690                 }
2691                 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2692                         mapper = true;
2693                         devnode = devlink;
2694                         break;
2695                 }
2696         }
2697
2698         if (!devnode) {
2699                 devnode = udev_device_get_devnode(dev);
2700                 if (!devnode)
2701                         return;
2702
2703                 if (fnmatch(MMC_PATH, devnode, 0) &&
2704                     fnmatch(SCSI_PATH, devnode, 0))
2705                         return;
2706         }
2707
2708         r = check_external_storage(devnode);
2709         if (r <= 0)
2710                 return;
2711
2712         action = udev_device_get_action(dev);
2713         if (!action)
2714                 return;
2715
2716         _I("%s device %s", devnode, action);
2717         if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2718            (mapper && !strcmp(action, UDEV_CHANGE))) {
2719                 r = check_already_handled(devnode);
2720                 if (r < 0) {
2721                         _I("%s is already handled", devnode);
2722                         return;
2723                 }
2724
2725                 add_block_device(dev, devnode, mapper);
2726         } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2727                 remove_block_device(dev, devnode);
2728         } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2729                 struct block_device *bdev;
2730                 bdev = find_block_device(devnode);
2731                 if (!bdev) {
2732                         _E("fail to find block data for %s", devnode);
2733                         return;
2734                 }
2735                 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2736                         return;
2737
2738                 r = update_block_data(bdev->data,
2739                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2740                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2741                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2742                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2743                                 udev_device_get_sysattr_value(dev, "ro"),
2744                                 false);
2745                 if (r < 0)
2746                         _E("fail to update block data for %s", bdev->data->devnode);
2747                 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
2748                         _I("filesystem type is updated: crypto_LUKS");
2749         }
2750 }
2751
2752 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2753                 DBusMessage *msg, bool onprivate)
2754 {
2755         struct block_device *bdev;
2756         char *mount_point;
2757         int id;
2758         int ret = -EBADMSG;
2759
2760         if (!reply_handle || !msg)
2761                 goto out;
2762
2763         ret = dbus_message_get_args(msg, NULL,
2764                         DBUS_TYPE_INT32, &id,
2765                         DBUS_TYPE_STRING, &mount_point,
2766                         DBUS_TYPE_INVALID);
2767         if (!ret)
2768                 goto out;
2769
2770         bdev = find_block_device_by_id(id);
2771         if (!bdev) {
2772                 _E("Failed to find (%d) in the device list", id);
2773                 ret = -ENOENT;
2774                 goto out;
2775         }
2776         if (bdev->on_private_op != REQ_NORMAL) {
2777                 ret = -EPERM;
2778                 goto out;
2779         }
2780
2781         if (bdev->data->state == BLOCK_MOUNT) {
2782                 _I("%s is already mounted", bdev->data->devnode);
2783                 ret = -EALREADY;
2784                 goto out;
2785         }
2786
2787         if (onprivate) {
2788                 bdev->on_private_op = REQ_PRIVATE;
2789                 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2790                 _D("Private operation state: %d", bdev->on_private_op);
2791         } else {
2792                 if (bdev->on_private_op != REQ_NORMAL) {
2793                         _E("Failed to process mount operation");
2794                         ret = -EPERM;
2795                         goto out;
2796                 }
2797         }
2798
2799         /* if requester want to use a specific mount point */
2800         if (mount_point && strncmp(mount_point, "", 1) != 0) {
2801                 ret = change_mount_point(bdev, mount_point);
2802                 if (ret < 0) {
2803                         ret = -EPERM;
2804                         goto out;
2805                 }
2806
2807                 /* Create /run/external-storage/id file */
2808                 create_file(bdev->data->id, bdev->data->mount_point, false);
2809         } else {
2810                 /* Create file for block device /run/external-storage/id */
2811                 create_file(bdev->data->id, bdev->data->mount_point, false);
2812         }
2813
2814         ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2815         if (ret < 0) {
2816                 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2817                 goto out;
2818         }
2819
2820         return NULL;
2821
2822 out:
2823         return make_dbus_reply_message_simple(reply_handle, ret);
2824 }
2825
2826 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2827                 DBusMessage *msg)
2828 {
2829         return request_mount_block(reply_handle, msg, false);
2830 }
2831
2832 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2833                 DBusMessage *msg)
2834 {
2835         return request_mount_block(reply_handle, msg, true);
2836 }
2837
2838 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2839                 DBusMessage *msg, bool onprivate)
2840 {
2841         struct block_device *bdev;
2842         pid_t pid;
2843         long option;
2844         int id;
2845         int ret = -EBADMSG;
2846
2847         if (!reply_handle || !msg)
2848                 goto out;
2849
2850         ret = dbus_message_get_args(msg, NULL,
2851                         DBUS_TYPE_INT32, &id,
2852                         DBUS_TYPE_INT32, &option,
2853                         DBUS_TYPE_INVALID);
2854         if (!ret)
2855                 goto out;
2856
2857         bdev = find_block_device_by_id(id);
2858         if (!bdev) {
2859                 _E("Failed to find (%d) in the device list", id);
2860                 ret = -ENOENT;
2861                 goto out;
2862         }
2863
2864         if (onprivate) {
2865                 pid = get_dbus_method_sender_pid(reply_handle);
2866                 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2867                         _E("Failed to process private unmount operation");
2868                         ret = -EPERM;
2869                         goto out;
2870                 }
2871         } else {
2872                 if (bdev->on_private_op != REQ_NORMAL) {
2873                         _E("Failed to process unmount operation");
2874                         ret = -EPERM;
2875                         goto out;
2876                 }
2877         }
2878
2879         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2880         if (ret < 0) {
2881                 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2882                 goto out;
2883         }
2884
2885         if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2886                 ret = add_operation(bdev, BLOCK_LUKS_CLOSE, NULL, NULL);
2887                 if (ret < 0)
2888                         _E("Failed to add operation (luks_close %s)", bdev->data->devnode);
2889         }
2890
2891         return NULL;
2892
2893 out:
2894         return make_dbus_reply_message_simple(reply_handle, ret);
2895 }
2896
2897 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2898                 DBusMessage *msg)
2899 {
2900         return request_unmount_block(reply_handle, msg, false);
2901 }
2902
2903 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2904                 DBusMessage *msg)
2905 {
2906         return request_unmount_block(reply_handle, msg, true);
2907 }
2908
2909 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2910                 DBusMessage *msg)
2911 {
2912         struct block_device *bdev;
2913         struct format_data *fdata;
2914         pid_t pid;
2915         int id;
2916         int option;
2917         int ret = -EBADMSG;
2918         int prev_state;
2919
2920         if (!reply_handle || !msg)
2921                 goto out;
2922
2923         ret = dbus_message_get_args(msg, NULL,
2924                         DBUS_TYPE_INT32, &id,
2925                         DBUS_TYPE_INT32, &option,
2926                         DBUS_TYPE_INVALID);
2927         if (!ret)
2928                 goto out;
2929
2930         bdev = find_block_device_by_id(id);
2931         if (!bdev) {
2932                 _E("Failed to find (%d) in the device list", id);
2933                 goto out;
2934         }
2935
2936         pid = get_dbus_method_sender_pid(reply_handle);
2937         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2938                 _E("Failed to format on private state");
2939                 ret = -EPERM;
2940                 goto out;
2941         }
2942
2943         fdata = get_format_data(NULL, option);
2944         if (!fdata) {
2945                 _E("Failed to get format data");
2946                 goto out;
2947         }
2948
2949         prev_state = bdev->data->state;
2950         if (prev_state == BLOCK_MOUNT) {
2951                 if (bdev->on_private_op == REQ_PRIVATE) {
2952                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
2953                         _D("Private operation state: %d", bdev->on_private_op);
2954                 }
2955                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2956                 if (ret < 0) {
2957                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2958                         release_format_data(fdata);
2959                         goto out;
2960                 }
2961         }
2962
2963         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2964         if (ret < 0) {
2965                 _E("Failed to add operation (format %s)", bdev->data->devnode);
2966                 release_format_data(fdata);
2967         }
2968
2969         /* Maintain previous state of mount/unmount */
2970         if (prev_state == BLOCK_MOUNT) {
2971                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2972                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
2973                         goto out;
2974                 }
2975         }
2976
2977         return NULL;
2978
2979 out:
2980         return make_dbus_reply_message_simple(reply_handle, ret);
2981 }
2982
2983 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2984                 DBusMessage *msg)
2985 {
2986         struct block_device *bdev;
2987         struct format_data *fdata;
2988         char *type;
2989         pid_t pid;
2990         int id;
2991         int option;
2992         int ret = -EBADMSG;
2993         int prev_state;
2994
2995         if (!reply_handle || !msg)
2996                 goto out;
2997
2998         ret = dbus_message_get_args(msg, NULL,
2999                         DBUS_TYPE_INT32, &id,
3000                         DBUS_TYPE_INT32, &option,
3001                         DBUS_TYPE_STRING, &type,
3002                         DBUS_TYPE_INVALID);
3003         if (!ret)
3004                 goto out;
3005
3006         bdev = find_block_device_by_id(id);
3007         if (!bdev) {
3008                 _E("Failed to find (%d) in the device list", id);
3009                 goto out;
3010         }
3011
3012         pid = get_dbus_method_sender_pid(reply_handle);
3013         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3014                 _E("Failed to format on private state");
3015                 ret = -EPERM;
3016                 goto out;
3017         }
3018
3019         fdata = get_format_data(type, option);
3020         if (!fdata) {
3021                 _E("Failed to get format data");
3022                 goto out;
3023         }
3024
3025         prev_state = bdev->data->state;
3026         if (prev_state == BLOCK_MOUNT) {
3027                 if (bdev->on_private_op == REQ_PRIVATE) {
3028                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
3029                         _D("Private operation state: %d", bdev->on_private_op);
3030                 }
3031                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3032                 if (ret < 0) {
3033                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3034                         release_format_data(fdata);
3035                         goto out;
3036                 }
3037         }
3038
3039         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3040         if (ret < 0) {
3041                 _E("Failed to add operation (format %s)", bdev->data->devnode);
3042                 release_format_data(fdata);
3043         }
3044
3045         /* Maintain previous state of mount/unmount */
3046         if (prev_state == BLOCK_MOUNT) {
3047                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3048                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
3049                         goto out;
3050                 }
3051         }
3052
3053         return NULL;
3054
3055 out:
3056         return make_dbus_reply_message_simple(reply_handle, ret);
3057 }
3058
3059 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3060 {
3061         char *str_null = "";
3062
3063         if (!data || !piter)
3064                 return -EINVAL;
3065
3066         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3067                         &(data->block_type));
3068         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3069                         data->devnode ? &(data->devnode) : &str_null);
3070         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3071                         data->syspath ? &(data->syspath) : &str_null);
3072         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3073                         data->fs_usage ? &(data->fs_usage) : &str_null);
3074         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3075                         data->fs_type ? &(data->fs_type) : &str_null);
3076         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3077                         data->fs_version ? &(data->fs_version) : &str_null);
3078         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3079                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3080         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3081                         &(data->readonly));
3082         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3083                         data->mount_point ? &(data->mount_point) : &str_null);
3084         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3085                         &(data->state));
3086         dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3087                         &(data->primary));
3088         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3089                         &(data->flags));
3090         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3091                         &(data->id));
3092
3093         return 0;
3094 }
3095
3096
3097 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3098 {
3099         DBusMessageIter piter;
3100
3101         if (!data || !iter)
3102                 return -EINVAL;
3103
3104         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3105         add_device_to_iter(data, &piter);
3106         dbus_message_iter_close_container(iter, &piter);
3107
3108         return 0;
3109 }
3110
3111 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3112 {
3113         DBusMessageIter piter;
3114         char *str_null = "";
3115
3116         if (!data || !iter)
3117                 return -EINVAL;
3118
3119         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3120         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3121                         &(data->block_type));
3122         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3123                         data->devnode ? &(data->devnode) : &str_null);
3124         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3125                         data->syspath ? &(data->syspath) : &str_null);
3126         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3127                         data->fs_usage ? &(data->fs_usage) : &str_null);
3128         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3129                         data->fs_type ? &(data->fs_type) : &str_null);
3130         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3131                         data->fs_version ? &(data->fs_version) : &str_null);
3132         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3133                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3134         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3135                         &(data->readonly));
3136         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3137                         data->mount_point ? &(data->mount_point) : &str_null);
3138         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3139                         &(data->state));
3140         dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3141                         &(data->primary));
3142         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3143                         &(data->flags));
3144         dbus_message_iter_close_container(iter, &piter);
3145
3146         return 0;
3147 }
3148
3149 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3150                 DBusMessage *msg)
3151 {
3152         DBusMessageIter iter;
3153         DBusMessage *reply;
3154         struct block_device *bdev;
3155         struct block_data *data;
3156         int ret, id;
3157
3158         if (!reply_handle || !msg)
3159                 return NULL;
3160
3161         reply = make_dbus_reply_message(reply_handle);
3162         if (!reply)
3163                 goto out;
3164
3165         ret = dbus_message_get_args(msg, NULL,
3166                         DBUS_TYPE_INT32, &id,
3167                         DBUS_TYPE_INVALID);
3168         if (!ret)
3169                 goto out;
3170
3171         bdev = find_block_device_by_id(id);
3172         if (!bdev)
3173                 goto out;
3174         data = bdev->data;
3175         if (!data)
3176                 goto out;
3177
3178         dbus_message_iter_init_append(reply, &iter);
3179         add_device_to_iter(data, &iter);
3180
3181 out:
3182         return reply;
3183 }
3184
3185 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3186                 DBusMessage *msg)
3187 {
3188         show_block_device_list();
3189         return make_dbus_reply_message(reply_handle);
3190 }
3191
3192 // Called by MainThread
3193 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3194                 DBusMessage *msg)
3195 {
3196         DBusMessageIter iter;
3197         DBusMessageIter aiter;
3198         DBusMessage *reply;
3199         struct block_device *bdev;
3200         struct block_data *data;
3201         dd_list *elem;
3202         char *type = NULL;
3203         int ret = -EBADMSG;
3204         int block_type;
3205         int i;
3206
3207         reply = make_dbus_reply_message(reply_handle);
3208
3209         ret = dbus_message_get_args(msg, NULL,
3210                         DBUS_TYPE_STRING, &type,
3211                         DBUS_TYPE_INVALID);
3212         if (!ret) {
3213                 _E("Failed to get args");
3214                 goto out;
3215         }
3216
3217         if (!type) {
3218                 _E("Delivered type is NULL");
3219                 goto out;
3220         }
3221
3222         _D("Block (%s) device list is requested", type);
3223
3224         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3225                 block_type = BLOCK_SCSI_DEV;
3226         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3227                 block_type = BLOCK_MMC_DEV;
3228         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3229                 block_type = -1;
3230         else {
3231                 _E("Invalid type (%s) is requested", type);
3232                 goto out;
3233         }
3234
3235         dbus_message_iter_init_append(reply, &iter);
3236         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3237
3238         for (i = 0; i < THREAD_MAX; i++) {
3239                 pthread_mutex_lock(&(th_manager[i].mutex));
3240                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3241                         data = bdev->data;
3242                         if (!data)
3243                                 continue;
3244                         if (bdev->removed)
3245                                 continue;
3246
3247                         switch (block_type) {
3248                         case BLOCK_SCSI_DEV:
3249                         case BLOCK_MMC_DEV:
3250                                 if (data->block_type != block_type)
3251                                         continue;
3252                                 break;
3253                         default:
3254                                 break;
3255                         }
3256                         add_device_to_struct_iter(data, &aiter);
3257                 }
3258                 pthread_mutex_unlock(&(th_manager[i].mutex));
3259         }
3260         dbus_message_iter_close_container(&iter, &aiter);
3261
3262 out:
3263         return reply;
3264 }
3265
3266 // Called by MainThread
3267 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3268                 DBusMessage *msg)
3269 {
3270         DBusMessageIter iter;
3271         DBusMessageIter aiter;
3272         DBusMessage *reply;
3273         struct block_device *bdev;
3274         struct block_data *data;
3275         dd_list *elem;
3276         char *type = NULL;
3277         int ret = -EBADMSG;
3278         int block_type;
3279         int i;
3280
3281         reply = make_dbus_reply_message(reply_handle);
3282
3283         ret = dbus_message_get_args(msg, NULL,
3284                         DBUS_TYPE_STRING, &type,
3285                         DBUS_TYPE_INVALID);
3286         if (!ret) {
3287                 _E("Failed to get args");
3288                 goto out;
3289         }
3290
3291         if (!type) {
3292                 _E("Delivered type is NULL");
3293                 goto out;
3294         }
3295
3296         _D("Block (%s) device list is requested", type);
3297
3298         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3299                 block_type = BLOCK_SCSI_DEV;
3300         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3301                 block_type = BLOCK_MMC_DEV;
3302         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3303                 block_type = -1;
3304         else {
3305                 _E("Invalid type (%s) is requested", type);
3306                 goto out;
3307         }
3308
3309         dbus_message_iter_init_append(reply, &iter);
3310         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3311
3312         for (i = 0; i < THREAD_MAX; i++) {
3313                 pthread_mutex_lock(&(th_manager[i].mutex));
3314                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3315                         data = bdev->data;
3316                         if (!data)
3317                                 continue;
3318                         if (bdev->removed)
3319                                 continue;
3320
3321                         switch (block_type) {
3322                         case BLOCK_SCSI_DEV:
3323                         case BLOCK_MMC_DEV:
3324                                 if (data->block_type != block_type)
3325                                         continue;
3326                                 break;
3327                         default:
3328                                 break;
3329                         }
3330
3331                         add_device_to_iter_2(data, &aiter);
3332                 }
3333                 pthread_mutex_unlock(&(th_manager[i].mutex));
3334         }
3335         dbus_message_iter_close_container(&iter, &aiter);
3336
3337 out:
3338         return reply;
3339 }
3340
3341 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3342                 DBusMessage *msg)
3343 {
3344         DBusMessageIter iter;
3345         DBusMessage *reply;
3346         struct block_device *bdev;
3347         struct block_data *data, nodata = {0,};
3348         dd_list *elem;
3349         bool found;
3350         int i;
3351
3352         if (!reply_handle || !msg)
3353                 return NULL;
3354
3355         reply = make_dbus_reply_message(reply_handle);
3356         if (!reply)
3357                 goto out;
3358
3359         found = false;
3360         for (i = 0; i < THREAD_MAX; i++) {
3361                 pthread_mutex_lock(&(th_manager[i].mutex));
3362                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3363                         data = bdev->data;
3364                         if (!data)
3365                                 continue;
3366                         if (bdev->removed)
3367                                 continue;
3368                         if (data->block_type != BLOCK_MMC_DEV &&
3369                             data->block_type != BLOCK_EXTENDEDSD_DEV)
3370                                 continue;
3371                         if (!data->primary)
3372                                 continue;
3373                         // Return mapper node(/dev/mapper/extendedsd) for primary mmc (not /dev/mmcblk1p1(ex))
3374                         if (!strncmp(data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
3375                                 continue;
3376                         found = true;
3377                         break;
3378                 }
3379                 pthread_mutex_unlock(&(th_manager[i].mutex));
3380                 if (found)
3381                         break;
3382         }
3383
3384         dbus_message_iter_init_append(reply, &iter);
3385         if (found)
3386                 add_device_to_iter(data, &iter);
3387         else {
3388                 nodata.id = -ENODEV;
3389                 add_device_to_iter(&nodata, &iter);
3390         }
3391
3392 out:
3393         return reply;
3394 }
3395
3396 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3397                 DBusMessage *msg)
3398 {
3399         struct timespec start_time, end_time;
3400         DBusMessageIter iter;
3401         DBusMessage *reply;
3402         struct block_device *bdev;
3403         struct block_data *data;
3404         char *buf;
3405         int ret = 0;
3406         int id;
3407         int fd;
3408         int time_diff;
3409
3410         if (!reply_handle || !msg)
3411                 return NULL;
3412
3413         ret = dbus_message_get_args(msg, NULL,
3414                         DBUS_TYPE_INT32, &id,
3415                         DBUS_TYPE_INVALID);
3416         if (!ret) {
3417                 ret = -1;
3418                 goto out;
3419         }
3420
3421         bdev = find_block_device_by_id(id);
3422         if (!bdev) {
3423                 ret = -1;
3424                 goto out;
3425         }
3426         data = bdev->data;
3427         if (!data) {
3428                 ret = -1;
3429                 goto out;
3430         }
3431
3432         _D("speed check: %s", data->devnode);
3433         fd = open(data->devnode, O_RDWR | O_SYNC);
3434         buf = calloc(1, SPEEDCHECK << 20);
3435         if (!buf) {
3436                 _E("calloc() failed");
3437                 close(fd);
3438                 ret = -1;
3439                 goto out;
3440         }
3441         clock_gettime(CLOCK_REALTIME, &start_time);
3442         _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3443         ret = write(fd, buf, SPEEDCHECK << 20);
3444         clock_gettime(CLOCK_REALTIME, &end_time);
3445         _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3446
3447         free(buf);
3448
3449         time_diff = end_time.tv_sec - start_time.tv_sec;
3450         if (time_diff > 0 && (SPEEDCHECK / time_diff < 4)) {
3451                 ret = -1;
3452                 close(fd);
3453                 goto out;
3454         }
3455
3456         if (ret < 0) {
3457                 _E("write() failed %d", errno);
3458                 close(fd);
3459                 goto out;
3460         }
3461
3462         close(fd);
3463 out:
3464         reply = dbus_message_new_method_return(msg);
3465         dbus_message_iter_init_append(reply, &iter);
3466         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3467         return reply;
3468 }
3469
3470
3471 static DBusMessage *request_control_block(dbus_method_reply_handle_h reply_handle,
3472                 DBusMessage *msg)
3473 {
3474         int ret;
3475         int enable;
3476         DBusMessage *reply;
3477         DBusMessageIter iter;
3478
3479         ret = dbus_message_get_args(msg, NULL,
3480                         DBUS_TYPE_INT32, &enable,
3481                         DBUS_TYPE_INVALID);
3482         if (!ret) {
3483                 ret = -1;
3484                 goto out;
3485         }
3486
3487         if (enable == 1) {
3488                 _I("control block Enable");
3489                 block_start(NULL);
3490         } else if (enable == 0) {
3491                 _I("control block Disable");
3492                 block_stop(NULL);
3493         } else {
3494                 _E("control block : Wrong request by client");
3495                 ret = -1;
3496                 goto out;
3497         }
3498
3499 out:
3500         reply = dbus_message_new_method_return(msg);
3501         dbus_message_iter_init_append(reply, &iter);
3502         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3503
3504         return reply;
3505 }
3506
3507 static DBusMessage *request_getcontrol_block(dbus_method_reply_handle_h reply_handle,
3508                 DBusMessage *msg)
3509 {
3510         int is_enabled;
3511         DBusMessage *reply;
3512         DBusMessageIter iter;
3513
3514         _I("getcontrol block");
3515
3516         is_enabled = block_control;
3517
3518         reply = dbus_message_new_method_return(msg);
3519         dbus_message_iter_init_append(reply, &iter);
3520         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &is_enabled);
3521
3522         return reply;
3523 }
3524
3525 /*
3526   Method name      Method call format string  Reply format string
3527 { "ShowDeviceList",                      NULL,               NULL, request_show_device_list },
3528 { "GetDeviceList",                        "s", "a(issssssisibii)", request_get_device_list },
3529 { "GetDeviceList2",                       "s",  "a(issssssisibi)", request_get_device_list_2 },
3530 { "Mount",                               "is",                "i", request_public_mount_block },
3531 { "Unmoun,                               "ii",                "i", request_public_unmount_block },
3532 { "Format",                              "ii",                "i", request_format_block },
3533 { "GetDeviceInfo",                        "i",  "(issssssisibii)", request_get_device_info },
3534 { "GetMmcPrimary",                       NULL, "(issssssisibii)" , request_get_mmc_primary },
3535 { "PrivateMount",                        "is",                "i", request_private_mount_block },
3536 { "PrivateUnmount",                      "ii",                "i", request_private_unmount_block },
3537 */
3538
3539 static const dbus_method_s manager_methods[] = {
3540         { "ShowDeviceList",         NULL, request_show_device_list },
3541         { "GetDeviceList" ,         "s", request_get_device_list },
3542         { "GetDeviceList2",         "s", request_get_device_list_2 },
3543         { "Mount",                  "is", request_public_mount_block },
3544         { "Unmount",                "ii", request_public_unmount_block },
3545         { "Format",                 "ii", request_format_block },
3546         { "FormatwithType",        "iis", request_format_block_type },
3547         { "GetDeviceInfo",          "i", request_get_device_info },
3548         { "GetMmcPrimary" ,         NULL, request_get_mmc_primary },
3549         { "PrivateMount",           "is", request_private_mount_block },
3550         { "PrivateUnmount",         "ii", request_private_unmount_block },
3551         { "CheckSpeed",              "i", request_check_speed },
3552         { "Control",                 "i", request_control_block },
3553         { "GetControl",              "i", request_getcontrol_block },
3554 };
3555
3556 static dbus_interface_s block_interface = {
3557         .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3558         .methods = manager_methods,
3559         .nr_methods = ARRAY_SIZE(manager_methods),
3560 };
3561
3562 static int load_config(struct parse_result *result, void *user_data)
3563 {
3564         int index;
3565
3566         if (MATCH(result->section, "Block"))
3567                 return 0;
3568
3569         if (MATCH(result->section, "SCSI"))
3570                 index = BLOCK_SCSI_DEV;
3571         else if (MATCH(result->section, "MMC"))
3572                 index = BLOCK_MMC_DEV;
3573         else if (MATCH(result->section, "Mapper"))
3574                 index = BLOCK_EXTENDEDSD_DEV;
3575         else
3576                 return -EINVAL;
3577
3578         if (MATCH(result->name, "Multimount"))
3579                 block_conf[index].multimount =
3580                         (MATCH(result->value, "yes") ? true : false);
3581         if (MATCH(result->name, "ExtendedInternalStorage"))
3582                 block_conf[index].extendedinternal =
3583                         (MATCH(result->value, "yes") ? true : false);
3584
3585         return 0;
3586 }
3587
3588 #ifdef BLOCK_TMPFS
3589 static int mount_root_path_tmpfs(void)
3590 {
3591         int ret;
3592         const char *root;
3593
3594         root = tzplatform_getenv(TZ_SYS_MEDIA);
3595         if (!root)
3596                 return -ENOTSUP;
3597
3598         if (access(root, F_OK) != 0)
3599                 return -ENODEV;
3600
3601         if (mount_check(root))
3602                 return 0;
3603
3604         ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3605         if (ret < 0) {
3606                 ret = -errno;
3607                 _E("tmpfs mount failed (%d)", ret);
3608                 return ret;
3609         }
3610
3611         return 0;
3612 }
3613 #else
3614 #define mount_root_path_tmpfs() 0
3615 #endif
3616
3617 static void block_init(void *data)
3618 {
3619         struct stat buf;
3620         int ret;
3621         int i;
3622         dbus_handle_h handle;
3623
3624         udev_init(NULL);
3625
3626         /* load config */
3627         ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3628         if (ret < 0)
3629                 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3630
3631         ret = mount_root_path_tmpfs();
3632         if (ret < 0)
3633                 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3634
3635         ret = dbus_get_connection(&handle);
3636         if (ret < 0)
3637                 _E("Failed to get dbus connection(%d)", ret);
3638
3639         /* register block manager object and interface */
3640         ret = register_dbus_methods(handle,
3641                         STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3642                         NULL, NULL);
3643         if (ret < 0)
3644                 _E("Failed to register block interface and methods (%d)", ret);
3645
3646         /* init pipe */
3647         ret = pipe_init();
3648         if (ret < 0)
3649                 _E("fail to init pipe");
3650
3651         /* register mmc uevent control routine */
3652         ret = register_udev_uevent_control(&uh);
3653         if (ret < 0)
3654                 _E("fail to register block uevent : %d", ret);
3655
3656         /* System Session is loaded completely */
3657         register_dbus_signal(SYSTEMD_DBUS_PATH,
3658                     SYSTEMD_DBUS_IFACE_MANAGER,
3659                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3660                     booting_done, NULL, NULL);
3661
3662         register_dbus_signal(DEVICED_PATH_POWEROFF,
3663                         DEVICED_INTERFACE_POWEROFF,
3664                         SIGNAL_POWEROFF_STATE,
3665                         block_poweroff, NULL, NULL);
3666
3667         for (i = 0; i < THREAD_MAX; i++) {
3668                 th_manager[i].num_dev = 0;
3669                 th_manager[i].op_len = 0;
3670                 th_manager[i].start_th = true;
3671                 th_manager[i].thread_id = i;
3672                 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3673                 pthread_cond_init(&(th_manager[i].cond), NULL);
3674         }
3675
3676         ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3677         if (ret < 0) {
3678                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3679                 if (ret < 0)
3680                         _E("Failed to make directory: %d", errno);
3681         } else if (!S_ISDIR(buf.st_mode)) {
3682                 ret = remove(EXTERNAL_STORAGE_PATH);
3683                 if (ret < 0)
3684                         _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3685                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3686                 if (ret < 0)
3687                         _E("Failed to make directory: %d", errno);
3688         } else {
3689                 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3690                 if (ret < 0)
3691                         _E("Fail to change permissions of a file");
3692         }
3693
3694         ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3695         if (ret < 0) {
3696                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3697                 if (ret < 0)
3698                         _E("Failed to make directory: %d", errno);
3699         } else if (!S_ISDIR(buf.st_mode)) {
3700                 ret = remove(EXTENDED_INTERNAL_PATH);
3701                 if (ret < 0)
3702                         _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3703                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3704                 if (ret < 0)
3705                         _E("Failed to make directory: %d", errno);
3706         } else {
3707                 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3708                 if (ret < 0)
3709                         _E("Fail to change permissions of a file");
3710         }
3711 }
3712
3713 static void block_exit(void *data)
3714 {
3715         dd_list *elem, *elem_next;
3716         char *temp;
3717         int ret, i;
3718
3719         udev_exit(NULL);
3720
3721         /* unregister notifier for below each event */
3722         unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3723                     SYSTEMD_DBUS_IFACE_MANAGER,
3724                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3725                     booting_done);
3726
3727         unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3728                         DEVICED_INTERFACE_POWEROFF,
3729                         SIGNAL_POWEROFF_STATE, block_poweroff);
3730
3731         /* exit pipe */
3732         pipe_exit();
3733
3734         /* unregister mmc uevent control routine */
3735         ret = unregister_udev_uevent_control(&uh);
3736         if (ret < 0)
3737                 _E("fail to unregister block uevent : %d", ret);
3738
3739         /* remove remaining blocks */
3740         remove_whole_block_device();
3741
3742         for (i = 0; i < THREAD_MAX; i++) {
3743                 if (!th_manager[i].start_th)
3744                         pthread_cancel(th_manager[i].th);
3745                 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3746                         DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3747                         free(temp);
3748                 }
3749         }
3750
3751         block_control = false;
3752 }
3753
3754 static int block_start(void *data)
3755 {
3756         int ret;
3757
3758         if (!block_boot) {
3759                 _E("Cannot be started. Booting is not ready");
3760                 return -ENODEV;
3761         }
3762
3763         if (block_control) {
3764                 _I("Already started");
3765                 return 0;
3766         }
3767
3768         /* register mmc uevent control routine */
3769         ret = register_udev_uevent_control(&uh);
3770         if (ret < 0)
3771                 _E("fail to register block uevent : %d", ret);
3772
3773         block_init_from_udev_enumerate();
3774
3775         block_control = true;
3776
3777         _I("start");
3778         return 0;
3779 }
3780
3781 static int block_stop(void *data)
3782 {
3783         if (!block_boot) {
3784                 _E("Cannot be stopped. Booting is not ready");
3785                 return -ENODEV;
3786         }
3787
3788         if (!block_control) {
3789                 _I("Already stopped");
3790                 return 0;
3791         }
3792
3793         /* unregister mmc uevent control routine */
3794         unregister_udev_uevent_control(&uh);
3795
3796         /* remove the existing blocks */
3797         remove_whole_block_device();
3798
3799         block_control = false;
3800
3801         _I("stop");
3802         return 0;
3803 }
3804
3805 static storaged_module_interface block_module = {
3806         .name     = "block",
3807         .init     = block_init,
3808         .exit     = block_exit,
3809         .start    = block_start,
3810         .stop     = block_stop,
3811 };
3812
3813 __attribute__ ((visibility("default")))storaged_module_interface *
3814 storaged_get_module_interface(void)
3815 {
3816         return &block_module;
3817 }