refactoring : remove unused parameter.
[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 const char *get_operation_char(enum block_dev_operation op)
911 {
912         switch (op) {
913         case BLOCK_DEV_MOUNT:
914                 return "MOUNT";
915
916         case BLOCK_DEV_UNMOUNT:
917                 return "UNMOUNT";
918
919         case BLOCK_DEV_FORMAT:
920                 return "FORMAT";
921
922         case BLOCK_DEV_INSERT:
923                 return "INSERT";
924
925         case BLOCK_DEV_REMOVE:
926                 return "REMOVE";
927
928         case BLOCK_LUKS_CLOSE:
929                 return "LUKS CLOSE";
930         }
931
932         _E("invalid operation (%d)", op);
933         return "unknown";
934 }
935
936 static void create_external_apps_directory(void)
937 {
938         int ret;
939
940         ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
941                         PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
942                         NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
943         if (ret)
944                 _E("Fail to create external directory");
945 }
946
947 static int pipe_trigger(enum block_dev_operation op,
948                 struct block_device *bdev, int result)
949 {
950         struct pipe_data pdata = { op, bdev, result };
951         int n;
952
953         _D("op : %s, bdev : %p, result : %d",
954                         get_operation_char(pdata.op),
955                         pdata.bdev, pdata.result);
956
957         // Multi thread should not write at the same time
958         pthread_mutex_lock(&pipe_mutex);
959         n = write(pfds[1], &pdata, sizeof(struct pipe_data));
960         pthread_mutex_unlock(&pipe_mutex);
961
962         return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
963 }
964
965 static bool pipe_cb(int fd, void *data)
966 {
967         struct pipe_data pdata = {0,};
968         int n;
969         int thread_id;
970         int ret;
971
972         n = read(fd, &pdata, sizeof(pdata));
973         if (n != sizeof(pdata) || !pdata.bdev) {
974                 _E("fail to read struct pipe data");
975                 goto out;
976         }
977
978         _I("op : %s, bdev : %p, result : %d",
979                         get_operation_char(pdata.op),
980                         pdata.bdev, pdata.result);
981
982         if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
983                 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
984                         ret = change_mount_point(pdata.bdev, "");
985                         /* Modify /run/external-storage/id file */
986                         if (ret == 0) {
987                                 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
988                                         create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
989                                 else
990                                         create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
991                         }
992                 }
993                 goto out;
994         }
995         if (pdata.op == BLOCK_DEV_MOUNT &&
996                 pdata.bdev->data->state == BLOCK_MOUNT &&
997                 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
998                 pdata.bdev->data->primary)
999                 create_external_apps_directory();
1000         if (pdata.op == BLOCK_DEV_UNMOUNT) {
1001                 /* Remove file for block device /run/xxxxxx/id */
1002                 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
1003         }
1004
1005         /* Broadcast to mmc and usb storage module */
1006         broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
1007
1008         /* Broadcast outside with Block iface */
1009         if (pdata.bdev->on_private_op == REQ_NORMAL)
1010                 signal_device_changed(pdata.bdev, pdata.op);
1011         else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
1012                 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1013                         pdata.bdev->on_private_op = REQ_NORMAL;
1014                         _D("Private operation state: %d", pdata.bdev->on_private_op);
1015                 }
1016         } else {
1017                 if (pdata.op == BLOCK_DEV_MOUNT) {
1018                         pdata.bdev->on_private_op = REQ_PRIVATE;
1019                         _D("Private operation state: %d", pdata.bdev->on_private_op);
1020                 }
1021         }
1022
1023         if (pdata.op == BLOCK_DEV_REMOVE) {
1024                 thread_id = pdata.bdev->thread_id;
1025                 if (thread_id < 0 || thread_id >= THREAD_MAX)
1026                         return true;
1027                 free_block_device(pdata.bdev);
1028         }
1029
1030 out:
1031         return true;
1032 }
1033
1034 static int pipe_init(void)
1035 {
1036         int ret;
1037
1038         ret = pipe2(pfds, O_CLOEXEC);
1039         if (ret == -1)
1040                 return -errno;
1041
1042         ret = add_fd_read_handler(pfds[0], pipe_cb,
1043                         NULL, NULL, &phandler);
1044         if (ret < 0) {
1045                 _E("Failed to add pipe handler (%d)", ret);
1046                 return ret;
1047         }
1048
1049         return 0;
1050 }
1051
1052 static void pipe_exit(void)
1053 {
1054         if (phandler) {
1055                 remove_fd_read_handler(&phandler);
1056                 phandler = NULL;
1057         }
1058
1059         if (pfds[0])
1060                 close(pfds[0]);
1061         if (pfds[1])
1062                 close(pfds[1]);
1063 }
1064
1065 static int mmc_check_and_unmount(const char *path)
1066 {
1067         int ret = 0;
1068         int retry = 0;
1069
1070         if (!path)
1071                 return 0;
1072
1073         while (mount_check(path)) {
1074                 ret = umount(path);
1075                 if (ret < 0) {
1076                         retry++;
1077                         if (retry > UNMOUNT_RETRY)
1078                                 return -errno;
1079                 }
1080         }
1081         return ret;
1082 }
1083
1084 static bool check_rw_mount(const char *szPath)
1085 {
1086         struct statvfs mount_stat;
1087
1088         if (!statvfs(szPath, &mount_stat)) {
1089                 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1090                         return false;
1091         }
1092         return true;
1093 }
1094
1095 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1096 {
1097         struct udev *udev;
1098         struct udev_device *dev;
1099         int r;
1100         int wait;
1101
1102         if (!data)
1103                 return -EINVAL;
1104
1105         for (wait = 0; wait < 10; wait++) {
1106                 udev = udev_new();
1107                 if (!udev) {
1108                         _E("fail to create udev library context");
1109                         return -EPERM;
1110                 }
1111
1112                 dev = udev_device_new_from_syspath(udev, data->syspath);
1113                 if (!dev) {
1114                         _E("fail to create new udev device");
1115                         udev_unref(udev);
1116                         return -EPERM;
1117                 }
1118
1119                 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
1120                         sleep(1);
1121                 else
1122                         break;
1123
1124                 udev_device_unref(dev);
1125                 udev_unref(udev);
1126         }
1127
1128         r = update_block_data(data,
1129                         udev_device_get_property_value(dev, "ID_FS_USAGE"),
1130                         udev_device_get_property_value(dev, "ID_FS_TYPE"),
1131                         udev_device_get_property_value(dev, "ID_FS_VERSION"),
1132                         udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1133                         udev_device_get_sysattr_value(dev, "ro"),
1134                         mount_point_updated);
1135         if (r < 0)
1136                 _E("fail to update block data for %s", data->devnode);
1137
1138         udev_device_unref(dev);
1139         udev_unref(udev);
1140         return r;
1141 }
1142
1143 static int block_mount(struct block_data *data)
1144 {
1145         struct block_fs_ops *fs;
1146         dd_list *elem;
1147         int r;
1148         int len;
1149
1150         if (!data || !data->devnode || !data->mount_point)
1151                 return -EINVAL;
1152
1153         /* check existing mounted */
1154         if (mount_check(data->mount_point))
1155                 return -EEXIST;
1156
1157         /* create mount point */
1158         if (access(data->mount_point, R_OK) != 0) {
1159                 if (mkdir(data->mount_point, 0755) < 0)
1160                         return -errno;
1161         }
1162
1163         /* check matched file system */
1164         if (!data->fs_usage ||
1165             strncmp(data->fs_usage, FILESYSTEM_NAME,
1166                     sizeof(FILESYSTEM_NAME)) != 0) {
1167                 r = -ENODEV;
1168                 goto out;
1169         }
1170
1171         if (!data->fs_type) {
1172                 _E("There is no file system");
1173                 BLOCK_FLAG_SET(data, FS_EMPTY);
1174                 r = -ENODATA;
1175                 goto out;
1176         }
1177
1178         fs = NULL;
1179         len = strlen(data->fs_type) + 1;
1180         DD_LIST_FOREACH(fs_head, elem, fs) {
1181                 if (!strncmp(fs->name, data->fs_type, len))
1182                         break;
1183         }
1184
1185         if (!fs) {
1186                 _E("Not supported file system (%s)", data->fs_type);
1187                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1188                 r = -ENOTSUP;
1189                 goto out;
1190         }
1191
1192         if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1193                 r = fs->mount(false, data->devnode, data->mount_point);
1194         else
1195                 r = fs->mount(smack, data->devnode, data->mount_point);
1196
1197         if (r == -EIO)
1198                 BLOCK_FLAG_SET(data, FS_BROKEN);
1199
1200         if (r < 0)
1201                 goto out;
1202
1203         r = check_rw_mount(data->mount_point);
1204         if (!r)
1205                 return -EROFS;
1206
1207         return 0;
1208
1209 out:
1210         rmdir(data->mount_point);
1211         return r;
1212 }
1213
1214 static int mount_start(struct block_device *bdev)
1215 {
1216         struct block_data *data;
1217         int ret;
1218         int r;
1219
1220         assert(bdev);
1221         assert(bdev->data);
1222
1223         data = bdev->data;
1224         _I("Mount Start : (%s -> %s)",
1225                         data->devnode, data->mount_point);
1226
1227         /* mount operation */
1228         r = block_mount(data);
1229         if (r != -EROFS && r < 0) {
1230                 _E("fail to mount %s device : %d", data->devnode, r);
1231                 goto out;
1232         }
1233
1234         if (r == -EROFS) {
1235                 data->readonly = true;
1236                 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1237         }
1238
1239         data->state = BLOCK_MOUNT;
1240
1241         if (data->block_type == BLOCK_MMC_DEV) {
1242                 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1243                 ret = app2ext_migrate_legacy_all();
1244                 if (ret < 0)
1245                         _E("app2ext failed");
1246         }
1247
1248 out:
1249         if (r < 0 && r != -EROFS)
1250                 data->state = BLOCK_UNMOUNT;
1251
1252         _I("%s result : %s, %d", __func__, data->devnode, r);
1253
1254         if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1255                 _E("fail to trigger pipe");
1256
1257         return r;
1258 }
1259
1260 static int change_mount_point(struct block_device *bdev,
1261                 const char *mount_point)
1262 {
1263         struct block_data *data;
1264
1265         if (!bdev)
1266                 return -EINVAL;
1267
1268         data = bdev->data;
1269         free(data->mount_point);
1270
1271         /* If the mount path already exists, the path cannot be used */
1272         if (mount_point &&
1273                 access(mount_point, F_OK) != 0) {
1274                 data->mount_point = strdup(mount_point);
1275                 bdev->mount_point_updated = true;
1276         } else {
1277                 data->mount_point = generate_mount_path(data);
1278                 bdev->mount_point_updated = false;
1279         }
1280
1281         return 0;
1282 }
1283
1284 static int mount_block_device(struct block_device *bdev)
1285 {
1286         struct block_data *data;
1287         int r;
1288
1289         if (!bdev || !bdev->data)
1290                 return -EINVAL;
1291
1292         data = bdev->data;
1293         if (data->state == BLOCK_MOUNT) {
1294                 _I("%s is already mounted", data->devnode);
1295                 return 0;
1296         }
1297
1298         if (!block_conf[data->block_type].multimount &&
1299             !data->primary) {
1300                 _I("Not support multi mount by config info");
1301                 return 0;
1302         }
1303
1304         r = mount_start(bdev);
1305         if (r < 0) {
1306                 _E("Failed to mount (%s)", data->devnode);
1307                 return r;
1308         }
1309
1310         return 0;
1311 }
1312
1313 static int block_unmount(struct block_device *bdev,
1314                 enum unmount_operation option)
1315 {
1316         struct block_data *data;
1317         int r, retry = 0;
1318         struct timespec time = {0,};
1319
1320         if (!bdev || !bdev->data || !bdev->data->mount_point)
1321                 return -EINVAL;
1322
1323         data = bdev->data;
1324
1325         if (bdev->on_private_op == REQ_NORMAL)
1326                 signal_device_blocked(bdev);
1327
1328         /* it must called before unmounting mmc */
1329         r = mmc_check_and_unmount(data->mount_point);
1330         if (!r)
1331                 goto out;
1332         if (option == UNMOUNT_NORMAL) {
1333                 _I("Failed to unmount with normal option : %d", r);
1334                 return r;
1335         }
1336
1337         _I("Execute force unmount!");
1338         /* Force Unmount Scenario */
1339         while (1) {
1340                 switch (retry++) {
1341                 case 0:
1342                         /* Mobile specific:
1343                          * should unmount the below vconf key. */
1344                         if ((data->block_type == BLOCK_MMC_DEV ||
1345                                 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1346                                 data->primary) {
1347                                 /* At first, notify to other app
1348                                  * who already access sdcard */
1349                                 _I("Notify to other app who already access sdcard");
1350                                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1351                                                 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1352                         }
1353                         break;
1354                 case 1:
1355                         /* Second, kill app with SIGTERM */
1356                         _I("Kill app with SIGTERM");
1357                         terminate_process(data->mount_point, false);
1358                         break;
1359                 case 2:
1360                         /* Last time, kill app with SIGKILL */
1361                         _I("Kill app with SIGKILL");
1362                         terminate_process(data->mount_point, true);
1363                         break;
1364                 default:
1365                         if (umount2(data->mount_point, MNT_DETACH) != 0) {
1366                                 _I("Failed to unmount with lazy option : %d",
1367                                                 errno);
1368                                 return -errno;
1369                         }
1370                         goto out;
1371                 }
1372
1373                 /* it takes some seconds til other app completely clean up */
1374                 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1375                 nanosleep(&time, NULL);
1376
1377                 print_open_files(data->mount_point);
1378
1379                 r = mmc_check_and_unmount(data->mount_point);
1380                 if (!r) {
1381                         _D("Success to unmount (%s)", data->mount_point);
1382                         break;
1383                 }
1384         }
1385
1386 out:
1387         data->state = BLOCK_UNMOUNT;
1388
1389         if (rmdir(data->mount_point) < 0)
1390                 _E("fail to remove %s directory", data->mount_point);
1391
1392         return r;
1393 }
1394
1395 static int unmount_block_device(struct block_device *bdev,
1396                 enum unmount_operation option)
1397 {
1398         struct block_data *data;
1399         int r;
1400
1401         if (!bdev || !bdev->data)
1402                 return -EINVAL;
1403
1404         data = bdev->data;
1405         if (data->state == BLOCK_UNMOUNT) {
1406                 _I("%s is already unmounted", data->devnode);
1407                 r = mmc_check_and_unmount(data->mount_point);
1408                 if (r < 0)
1409                         _E("The path was existed, but could not delete it(%s)",
1410                                         data->mount_point);
1411                 return 0;
1412         }
1413
1414         _I("Unmount Start : (%s -> %s)",
1415                         data->devnode, data->mount_point);
1416
1417         r = block_unmount(bdev, option);
1418         if (r < 0) {
1419                 _E("fail to unmount %s device : %d", data->devnode, r);
1420                 goto out;
1421         }
1422
1423         BLOCK_FLAG_MOUNT_CLEAR(data);
1424
1425 out:
1426         _I("%s result : %s, %d", __func__, data->devnode, r);
1427
1428         if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1429                 _E("fail to trigger pipe");
1430
1431         return r;
1432 }
1433
1434 static int block_format(struct block_data *data,
1435                 const char *fs_type, bool mount_point_updated)
1436 {
1437         const struct block_fs_ops *fs;
1438         dd_list *elem;
1439         const char *fstype;
1440         int len;
1441         int r;
1442
1443         if (!data || !data->devnode || !data->mount_point)
1444                 return -EINVAL;
1445
1446         if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1447                 fstype = EXT4_NAME;
1448         else {
1449                 if (!fs_type) {
1450                         if (!data->fs_type)
1451                                 return -ENOTSUP;
1452                         fstype = data->fs_type;
1453                 } else
1454                         fstype = fs_type;
1455         }
1456
1457         fs = NULL;
1458         len = strlen(fstype);
1459         DD_LIST_FOREACH(fs_head, elem, fs) {
1460                 if (!strncmp(fs->name, fstype, len))
1461                         break;
1462         }
1463
1464         if (!fs) {
1465                 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1466                 _E("not supported file system(%s)", fstype);
1467                 return -ENOTSUP;
1468         }
1469
1470         _I("format path : %s", data->devnode);
1471         fs->check(data->devnode);
1472         r = fs->format(data->devnode);
1473         if (r < 0) {
1474                 _E("fail to format block data for %s", data->devnode);
1475                 goto out;
1476         }
1477
1478         /* need to update the partition data.
1479          * It can be changed in doing format. */
1480         retrieve_udev_device(data, mount_point_updated);
1481 out:
1482         return r;
1483 }
1484
1485 static int format_block_device(struct block_device *bdev,
1486                 const char *fs_type,
1487                 enum unmount_operation option)
1488 {
1489         struct block_data *data;
1490         int r;
1491
1492         assert(bdev);
1493         assert(bdev->data);
1494
1495         data = bdev->data;
1496
1497         _I("Format Start : (%s -> %s)",
1498                         data->devnode, data->mount_point);
1499
1500         if (data->state == BLOCK_MOUNT) {
1501                 r = block_unmount(bdev, option);
1502                 if (r < 0) {
1503                         _E("fail to unmount %s device : %d", data->devnode, r);
1504                         goto out;
1505                 }
1506         }
1507
1508         r = block_format(data, fs_type, bdev->mount_point_updated);
1509         if (r < 0)
1510                 _E("fail to format %s device : %d", data->devnode, r);
1511
1512 out:
1513         _I("%s result : %s, %d", __func__, data->devnode, r);
1514
1515         r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1516         if (r < 0)
1517                 _E("fail to trigger pipe");
1518
1519         return r;
1520 }
1521
1522 static struct format_data *get_format_data(
1523                 const char *fs_type, enum unmount_operation option)
1524 {
1525         struct format_data *fdata;
1526
1527         fdata = (struct format_data *)malloc(sizeof(struct format_data));
1528         if (!fdata) {
1529                 _E("fail to allocate format data");
1530                 return NULL;
1531         }
1532
1533         if (fs_type)
1534                 fdata->fs_type = strdup(fs_type);
1535         else
1536                 fdata->fs_type = NULL;
1537         fdata->option = option;
1538
1539         return fdata;
1540 }
1541
1542 static void release_format_data(struct format_data *data)
1543 {
1544         if (data) {
1545                 if (data->fs_type)
1546                         free(data->fs_type);
1547                 free(data);
1548         }
1549 }
1550
1551 // Called by BlockThread - Real Mount Op
1552 static int block_mount_device(struct block_device *bdev, void *data)
1553 {
1554         dd_list *l;
1555         int ret;
1556         int thread_id;
1557
1558         if (!bdev)
1559                 return -EINVAL;
1560
1561         thread_id = bdev->thread_id;
1562         if (thread_id < 0 || thread_id >= THREAD_MAX)
1563                 return -EINVAL;
1564         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1565         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1566         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1567         if (!l) {
1568                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1569                 return -ENOENT;
1570         }
1571
1572         /* mount automatically */
1573         ret = mount_block_device(bdev);
1574         if (ret < 0)
1575                 _E("fail to mount block device for %s", bdev->data->devnode);
1576
1577         return ret;
1578 }
1579
1580 // Called by BlockThread - Real Format Op
1581 static int block_format_device(struct block_device *bdev, void *data)
1582 {
1583         dd_list *l;
1584         int ret;
1585         int thread_id;
1586         struct format_data *fdata = (struct format_data *)data;
1587
1588         if (!bdev || !fdata) {
1589                 ret = -EINVAL;
1590                 goto out;
1591         }
1592
1593         thread_id = bdev->thread_id;
1594         if (thread_id < 0 || thread_id >= THREAD_MAX)
1595                 return -EINVAL;
1596         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1597         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1598         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1599         if (!l) {
1600                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1601                 ret = -ENOENT;
1602                 goto out;
1603         }
1604
1605         ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1606         if (ret < 0)
1607                 _E("fail to mount block device for %s", bdev->data->devnode);
1608
1609 out:
1610         release_format_data(fdata);
1611
1612         return ret;
1613 }
1614
1615 // Called by BlockThread - Real Unmount Op
1616 static int block_unmount_device(struct block_device *bdev, void *data)
1617 {
1618         int ret;
1619         long option = (long)data;
1620
1621         if (!bdev)
1622                 return -EINVAL;
1623
1624         ret = unmount_block_device(bdev, option);
1625         if (ret < 0) {
1626                 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1627                 return ret;
1628         }
1629
1630         return 0;
1631 }
1632
1633 /* Called by BlockThread - Remove Operation
1634    Direct Call at BlockThread
1635    Previously this function was called by MainThread. However, it will increase complexity.
1636    Need thread lock before to call remove_operation
1637 */
1638 static void remove_operation(struct block_device *bdev)
1639 {
1640         struct operation_queue *op;
1641         dd_list *l, *next;
1642         int thread_id;
1643
1644         assert(bdev);
1645
1646         thread_id = bdev->thread_id;
1647         if (thread_id < 0 || thread_id >= THREAD_MAX)
1648                 return;
1649
1650         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1651                 if (op->done) {
1652                         _D("Remove operation (%s, %s)",
1653                                         get_operation_char(op->op),
1654                                         bdev->data->devnode);
1655
1656                         DD_LIST_REMOVE(bdev->op_queue, op);
1657                         free(op);
1658                 }
1659         }
1660 }
1661
1662 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1663 {
1664         DBusMessage *rep;
1665
1666         if (!reply_handle)
1667                 return;
1668
1669         rep = make_dbus_reply_message_simple(reply_handle, result);
1670         reply_dbus_method_result(reply_handle, rep);
1671 }
1672
1673 // Called by BlockThread
1674 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1675 {
1676         struct operation_queue *temp;
1677         dd_list *l;
1678         int thread_id;
1679
1680         if (!bdev)
1681                 return;
1682
1683         if (!queue)
1684                 return;
1685
1686         if (!op)
1687                 return;
1688
1689         thread_id = bdev->thread_id;
1690         if (thread_id < 0 || thread_id >= THREAD_MAX)
1691                 return;
1692
1693         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1694
1695         DD_LIST_FOREACH(*queue, l, temp) {
1696                 if (temp->op == BLOCK_DEV_REMOVE) {
1697                         *op = temp;
1698                         break;
1699                 }
1700                 temp->done = true;
1701                 th_manager[thread_id].op_len--;
1702                 block_send_dbus_reply((*op)->reply_handle, 0);
1703         }
1704
1705         remove_operation(bdev);
1706         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1707 }
1708
1709 // Called by BlockThread
1710 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1711 {
1712         struct operation_queue *temp;
1713         dd_list *l;
1714         int thread_id;
1715         bool unmounted = false;
1716
1717         if (!bdev)
1718                 return false;
1719
1720         if (!queue)
1721                 return false;
1722
1723         if (!op)
1724                 return false;
1725
1726         thread_id = bdev->thread_id;
1727         if (thread_id < 0 || thread_id >= THREAD_MAX)
1728                 return false;
1729
1730         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1731         DD_LIST_FOREACH(*queue, l, temp) {
1732                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1733                         unmounted = true;
1734                         _D("Operation queue has unmount operation");
1735                         break;
1736                 }
1737         }
1738         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1739
1740         if (!unmounted)
1741                 return unmounted;
1742
1743         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1744
1745         DD_LIST_FOREACH(*queue, l, temp) {
1746                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1747                         *op = temp;
1748                         break;
1749                 }
1750                 temp->done = true;
1751                 th_manager[thread_id].op_len--;
1752                 block_send_dbus_reply((*op)->reply_handle, 0);
1753         }
1754
1755         remove_operation(bdev);
1756         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1757
1758         return unmounted;
1759 }
1760
1761 // Called by BlockThread
1762 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1763 {
1764         int ret = 0;
1765         int thread_id;
1766         char devnode[PATH_MAX];
1767         enum block_dev_operation operation;
1768         bool unmounted = false;
1769
1770         assert(bdev);
1771
1772         if (!queue)
1773                 return;
1774
1775         thread_id = bdev->thread_id;
1776         if (thread_id < 0 || thread_id >= THREAD_MAX)
1777                 return;
1778
1779         snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1780
1781         do {
1782                 if (!op)
1783                         return;
1784                 if (op->done)
1785                         return;
1786
1787                 operation = op->op;
1788
1789                 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1790                         get_operation_char(operation), devnode);
1791
1792                 unmounted = false;
1793                 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1794                         check_removed(bdev, &queue, &op);
1795                         operation = op->op;
1796                         _D("Trigger operation again (%s, %s)",
1797                                 get_operation_char(operation), devnode);
1798                 }
1799                 if (operation == BLOCK_DEV_MOUNT) {
1800                         unmounted = check_unmount(bdev, &queue, &op);
1801                         if (unmounted) {
1802                                 operation = op->op;
1803                                 _D("Trigger operation again (%s, %s)",
1804                                         get_operation_char(operation), devnode);
1805                         }
1806                 }
1807
1808                 switch (operation) {
1809                 case BLOCK_DEV_INSERT:
1810                         break;
1811                 case BLOCK_DEV_MOUNT:
1812                         ret = block_mount_device(bdev, op->data);
1813                         _D("Mount (%s) result:(%d)", devnode, ret);
1814                         break;
1815                 case BLOCK_DEV_FORMAT:
1816                         ret = block_format_device(bdev, op->data);
1817                         _D("Format (%s) result:(%d)", devnode, ret);
1818                         break;
1819                 case BLOCK_DEV_UNMOUNT:
1820                         ret = block_unmount_device(bdev, op->data);
1821                         _D("Unmount (%s) result:(%d)", devnode, ret);
1822                         break;
1823                 case BLOCK_DEV_REMOVE:
1824                         /* Do nothing */
1825                         break;
1826                 case BLOCK_LUKS_CLOSE:
1827                         ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1828                         if (ret < 0)
1829                                 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1830                         break;
1831                 default:
1832                         _E("Operation type is invalid (%d)", op->op);
1833                         ret = -EINVAL;
1834                         break;
1835                 }
1836
1837                 /* LOCK
1838                  * during checking the queue length */
1839                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1840
1841                 op->done = true;
1842                 th_manager[thread_id].op_len--;
1843
1844                 block_send_dbus_reply(op->reply_handle, ret);
1845
1846                 queue = bdev->op_queue;
1847                 if (queue != NULL) {
1848                         queue = DD_LIST_NEXT(queue);
1849                         if (queue != NULL)
1850                                 op = DD_LIST_NTH(queue, 0);
1851                         else
1852                                 op = NULL;
1853                 } else
1854                         op = NULL;
1855
1856                 remove_operation(bdev);
1857
1858                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1859                 /* UNLOCK */
1860
1861                 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1862                         if (pipe_trigger(operation, bdev, 0) < 0)
1863                                 _E("fail to trigger pipe");
1864                 }
1865
1866         } while (true);
1867
1868 }
1869
1870 // Called by BlockThread
1871 static void *block_th_start(void *arg)
1872 {
1873         struct block_device *temp;
1874         struct manage_thread *th = (struct manage_thread *)arg;
1875         struct operation_queue *op = NULL;
1876         dd_list *elem;
1877         dd_list *queue = NULL;
1878         int thread_id;
1879
1880         assert(th);
1881
1882         thread_id = th->thread_id;
1883         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1884                 _E("Thread Number: %d", th->thread_id);
1885                 return NULL;
1886         }
1887
1888         do {
1889                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1890                 if (th_manager[thread_id].op_len == 0) {
1891                         _D("Operation queue of thread is empty");
1892                         pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1893                         _D("Wake up %d", thread_id);
1894                 }
1895
1896                 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1897                         queue = temp->op_queue;
1898                         do {
1899                                 op = DD_LIST_NTH(queue, 0);
1900                                 if (!op) {
1901                                         _D("Operation queue for device %s is Empty", temp->data->devnode);
1902                                         break;
1903                                 }
1904                                 if (op->done) {
1905                                         queue = DD_LIST_NEXT(queue);
1906                                         continue;
1907                                 }
1908                                 break;
1909                         } while (true);
1910                         if (op)
1911                                 break;
1912                 }
1913                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1914
1915                 if (op && !op->done)
1916                         trigger_operation(temp, queue, op);
1917
1918         } while (true);
1919 }
1920
1921 // This function will be refactored later
1922 // Especially, we don't need to keep th_node_list.
1923 static int find_thread(char *devnode)
1924 {
1925         dd_list *elem;
1926         char str[PATH_MAX];
1927         char *th_node;
1928         char *temp;
1929         char dev_scsi;
1930         int i, len, min, min_num;
1931         int dev_mmc = -1, part = -1, num;
1932
1933         len = 0;
1934         if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1935                 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1936                 num = dev_mmc;
1937                 while (num > 0) {
1938                         num = num / 10;
1939                         len++;
1940                 }
1941                 len = len + 12;
1942                 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1943                 th_node = strdup(str);
1944         } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1945                 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1946                 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1947                 th_node = strdup(str);
1948         } else
1949                 th_node = strdup(devnode);
1950
1951         len = strlen(th_node) + 1;
1952         min_num = 1000;
1953         min = -1;
1954         for (i = 0; i < THREAD_MAX; i++) {
1955                 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1956                         if (!strncmp(temp, th_node, len)) {
1957                                 free(th_node);
1958                                 return i;
1959                         }
1960                 }
1961                 if (th_manager[i].num_dev < min_num) {
1962                         min_num = th_manager[i].num_dev;
1963                         min = i;
1964                 }
1965         }
1966
1967         if (min >= 0 && min < THREAD_MAX) {
1968                 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1969                 return min;
1970         }
1971
1972         _E("Finding thread is failed");
1973         DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1974         return 0;
1975 }
1976
1977 /* Only Main thread is permmited */
1978 // Called by MainThread
1979 static int add_operation(struct block_device *bdev,
1980                 enum block_dev_operation operation,
1981                 dbus_method_reply_handle_h reply_handle, void *data)
1982 {
1983         struct operation_queue *op;
1984         int ret;
1985         int thread_id;
1986         bool start_th;
1987
1988         if (!bdev)
1989                 return -EINVAL;
1990
1991
1992         _I("Add operation (%s, %s)",
1993                         get_operation_char(operation),
1994                         bdev->data->devnode);
1995
1996         thread_id = bdev->thread_id;
1997         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1998                 _E("Fail to find thread to add");
1999                 return -EPERM;
2000         }
2001
2002         op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2003         if (!op) {
2004                 _E("malloc failed");
2005                 return -ENOMEM;
2006         }
2007
2008         op->op = operation;
2009         op->data = data;
2010         op->reply_handle = reply_handle;
2011
2012         /* LOCK
2013          * during adding queue and checking the queue length */
2014         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2015
2016         /* Only modified between lock and unlock of mutex */
2017         op->done = false;
2018
2019         start_th = th_manager[thread_id].start_th;
2020         DD_LIST_APPEND(bdev->op_queue, op);
2021         th_manager[thread_id].op_len++;
2022
2023         if (th_manager[thread_id].op_len == 1 && !start_th)
2024                 pthread_cond_signal(&(th_manager[thread_id].cond));
2025
2026         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2027         /* UNLOCK */
2028
2029         /* Need to disble app2ext whenever unmounting mmc */
2030         if (op->op == BLOCK_DEV_UNMOUNT &&
2031                 bdev->data->state == BLOCK_MOUNT &&
2032                 bdev->data->block_type == BLOCK_MMC_DEV &&
2033                 bdev->data->primary)
2034                 if (app2ext_disable_all_external_pkgs() < 0)
2035                         _E("app2ext_disable_all_external_pkgs() failed");
2036
2037
2038         if (start_th) {
2039                 _D("Start New thread for block device");
2040                 th_manager[thread_id].start_th = false;
2041                 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2042                 if (ret != 0) {
2043                         _E("fail to create thread for %s", bdev->data->devnode);
2044                         return -EPERM;
2045                 }
2046
2047                 pthread_detach(th_manager[thread_id].th);
2048         }
2049
2050         return 0;
2051 }
2052
2053 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2054 {
2055         DIR *dp;
2056         struct dirent entry;
2057         struct dirent *dir;
2058         const char *syspath;
2059         bool ret = false;
2060
2061         syspath = udev_device_get_syspath(dev);
2062         if (!syspath)
2063                 goto out;
2064
2065         dp = opendir(syspath);
2066         if (!dp) {
2067                 _E("fail to open %s", syspath);
2068                 goto out;
2069         }
2070
2071         /* TODO compare devname and d_name */
2072         while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2073                 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2074                     !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2075                         ret = true;
2076                         break;
2077                 }
2078         }
2079
2080         closedir(dp);
2081
2082 out:
2083         return ret;
2084 }
2085
2086 static bool check_partition(struct udev_device *dev)
2087 {
2088         const char *devtype;
2089         const char *part_table_type;
2090         const char *fs_usage;
2091         bool ret = false;
2092
2093         /* only consider disk type, never partitions */
2094         devtype = udev_device_get_devtype(dev);
2095         if (!devtype)
2096                 goto out;
2097
2098         if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2099                                 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2100                 goto out;
2101
2102         part_table_type = udev_device_get_property_value(dev,
2103                         "ID_PART_TABLE_TYPE");
2104         if (part_table_type) {
2105                 fs_usage = udev_device_get_property_value(dev,
2106                                 "ID_FS_USAGE");
2107                 if (fs_usage &&
2108                     strncmp(fs_usage, FILESYSTEM_NAME, sizeof(FILESYSTEM_NAME)) == 0) {
2109                         if (!disk_is_partitioned_by_kernel(dev))
2110                                         goto out;
2111                 }
2112                 ret = true;
2113                 goto out;
2114         }
2115
2116         if (disk_is_partitioned_by_kernel(dev)) {
2117                 ret = true;
2118                 goto out;
2119         }
2120
2121 out:
2122         return ret;
2123 }
2124
2125 // Called by MainThread
2126 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2127 {
2128         struct block_data *data;
2129         struct block_device *bdev;
2130         //char id_string[PATH_LEN];
2131         bool partition;
2132         int ret;
2133         int thread_id;
2134         bool need_format = false;
2135
2136         partition = check_partition(dev);
2137         if (partition) {
2138                 /* if there is a partition, skip this request */
2139                 _I("%s device has partitions, skip this time", devnode);
2140                 return 0;
2141         }
2142
2143         if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2144                 char syspath[128] = {0};
2145                 char *r;
2146
2147                 r = rindex(udev_device_get_syspath(dev), '/');
2148                 if (!r) return -ENODEV;
2149
2150                 snprintf(syspath, sizeof(syspath), "/sys/block%s", r);
2151
2152                 data = make_block_data(devnode,
2153                                 syspath,
2154                                 FILESYSTEM_NAME,
2155                                 EXT4_NAME,
2156                                 "1.0",
2157                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2158                                 udev_device_get_sysattr_value(dev, "ro"));
2159                 need_format = true;
2160         } else {
2161                 data = make_block_data(devnode,
2162                                 udev_device_get_syspath(dev),
2163                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2164                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2165                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2166                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2167                                 udev_device_get_sysattr_value(dev, "ro"));
2168         }
2169
2170         if (!data) {
2171                 _E("fail to make block data for %s", devnode);
2172                 return -EPERM;
2173         }
2174
2175         if (!block_conf[data->block_type].multimount && !data->primary &&
2176             data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME)) {
2177                 _D("Not support multi mount by config info");
2178                 free_block_data(data);
2179                 return -EPERM;
2180         }
2181
2182         bdev = make_block_device(data);
2183         if (!bdev) {
2184                 _E("fail to make block device for %s", devnode);
2185                 free_block_data(data);
2186                 return -EPERM;
2187         }
2188
2189         thread_id = find_thread(bdev->data->devnode);
2190         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2191                 _E("Fail to find thread to add");
2192                 free_block_device(bdev);
2193                 return -EPERM;
2194         }
2195         bdev->thread_id = thread_id;
2196
2197         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2198         th_manager[thread_id].num_dev++;
2199         DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2200         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2201
2202         if (need_format) {
2203                 struct format_data *fdata;
2204
2205                 fdata = get_format_data(NULL, UNMOUNT_FORCE);
2206                 if (!fdata) {
2207                         _E("Failed to get format data");
2208                         return -ENOMEM;
2209                 }
2210
2211                 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2212                 if (ret < 0) {
2213                         _E("Failed to add operation (format %s)", bdev->data->devnode);
2214                         release_format_data(fdata);
2215                 }
2216         }
2217
2218         if (!bdev->data->fs_type) {
2219                 _E("Unformatted Storage");
2220                 free_block_device(bdev);
2221                 return -EPERM;
2222         } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2223 //              bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2224                 bdev->data->primary = true;
2225                 _D("Need to unlock encrypted sdcard");
2226                 // ---- ODE UI launch ----
2227                 ret = launch_system_app(POPUP_DEFAULT
2228                                       , 8
2229                                       , POPUP_KEY_CONTENT
2230                                       , "unlockextendedsd"
2231                                       , VIEWTYPE_KEY
2232                                       , INSERT_SD_CARD
2233                                       , DEVPATH_KEY
2234                                       , bdev->data->devnode
2235                                       , MAPPING_NODE_KEY
2236                                       , EXTENDEDSD_NAME);
2237                 if (ret < 0)
2238                         _E("Failed to launch popup");
2239
2240                 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2241                 if (ret < 0) {
2242                         _E("Failed to add operation (insert %s)", devnode);
2243                         free_block_device(bdev);
2244                         return ret;
2245                 }
2246
2247                 return 0;
2248         } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2249                 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2250                 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2251                 if (ret < 0) {
2252                         ret = -EPERM;
2253                         free_block_device(bdev);
2254                         return ret;
2255                 }
2256         }
2257
2258         ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2259         if (ret < 0) {
2260                 _E("Failed to add operation (insert %s)", devnode);
2261                 free_block_device(bdev);
2262                 return ret;
2263         }
2264
2265         // Not a regular filesystem -> skip mounting
2266         if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM_NAME)) {
2267                 _I("Not a filesystem. Not mounting");
2268                 return 0;
2269         }
2270
2271         /* Create file for block device /run/external-storage/id */
2272         create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2273         ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2274         if (ret < 0) {
2275                 _E("Failed to add operation (mount %s)", devnode);
2276                 return ret;
2277         }
2278         return 0;
2279 }
2280
2281 static int remove_block_device(struct udev_device *dev, const char *devnode)
2282 {
2283         struct block_device *bdev;
2284         struct block_device *bdev_extended;
2285         int ret;
2286
2287         bdev = find_block_device(devnode);
2288         if (!bdev) {
2289                 _E("fail to find block data for %s", devnode);
2290                 return -ENODEV;
2291         }
2292
2293         BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2294
2295         bdev->removed = true;
2296         if (bdev->on_private_op != REQ_NORMAL) {
2297                 bdev->on_private_op = REQ_NORMAL;
2298                 _D("Private operation state: %d", bdev->on_private_op);
2299         }
2300
2301         if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2302                 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2303
2304                 if (bdev_extended) {
2305                         BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2306
2307                         bdev_extended->removed = true;
2308                         if (bdev_extended->on_private_op != REQ_NORMAL) {
2309                                 bdev_extended->on_private_op = REQ_NORMAL;
2310                                 _D("Private operation state: %d", bdev_extended->on_private_op);
2311                         }
2312
2313                         ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2314                         if (ret < 0) {
2315                                 _E("Failed to add operation (unmount %s)", devnode);
2316                                 return ret;
2317                         }
2318
2319                         ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2320                         if (ret < 0) {
2321                                 _E("Failed to add operation (remove %s)", devnode);
2322                                 return ret;
2323                         }
2324
2325                         ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2326                         if (ret < 0) {
2327                                 _E("Failed to add operation (luks_close %s)", devnode);
2328                                 return ret;
2329                         }
2330                 } else
2331                         _E("fail to find block data for extended sd card");
2332         }
2333
2334         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2335         if (ret < 0) {
2336                 _E("Failed to add operation (unmount %s)", devnode);
2337                 return ret;
2338         }
2339
2340         ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2341         if (ret < 0) {
2342                 _E("Failed to add operation (remove %s)", devnode);
2343                 return ret;
2344         }
2345
2346         return 0;
2347 }
2348
2349 static int get_internal_storage_number(void)
2350 {
2351         struct libmnt_table *t = NULL;
2352         struct libmnt_fs *fs;
2353         const char *temp;
2354         char *name;
2355         int r = 0, dev_temp;
2356
2357         if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2358                 (is_emulator() && dev_internal_emul != '\0'))
2359                 return 0;
2360
2361         t = mnt_new_table();
2362         if (!t)
2363                 return -EPERM;
2364
2365         r = mnt_table_parse_mtab(t, NULL);
2366         if (r < 0) {
2367                 mnt_free_table(t);
2368                 return -EPERM;
2369         }
2370
2371         fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2372
2373         if (!fs) {
2374                 mnt_free_table(t);
2375                 return -EPERM;
2376         }
2377         temp = mnt_fs_get_srcpath(fs);
2378         if (!temp)
2379                 return -EPERM;
2380
2381         name = strrchr(temp, '/');
2382         if (!name)
2383                 return -EPERM;
2384         name++;
2385         /* Boot from USB is not handled */
2386         if (!is_emulator()) {
2387                 if (!fnmatch(MMC_PATH, temp, 0))
2388                         sscanf(name, "mmcblk%d", &dev_internal);
2389                 else if (!fnmatch(SCSI_PATH, temp, 0))
2390                         sscanf(name, "sd%c", &dev_internal_scsi);
2391         } else {
2392                 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2393                         sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2394                 else
2395                         dev_internal_emul = '\0';
2396         }
2397
2398         mnt_free_table(t);
2399
2400         return 0;
2401 }
2402
2403 static int check_external_storage(const char* devnode)
2404 {
2405         char dev_scsi = '\0';
2406         char *name;
2407         char emul = '\0';
2408         int dev_num = -1, dev_temp;
2409
2410         if (!devnode)
2411                 return -EPERM;
2412
2413         name = strrchr(devnode, '/');
2414         if (!name)
2415                 return -EPERM;
2416         name++;
2417         if (!is_emulator()) {
2418                 if (!fnmatch(MMC_PATH, devnode, 0)) {
2419                         sscanf(name, "mmcblk%d", &dev_num);
2420                         if (dev_internal == dev_num) {
2421                                 _D("%s is internal storage", devnode);
2422                                 return 0;
2423                         }
2424                 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2425                         sscanf(name, "sd%c", &dev_scsi);
2426                         if (dev_internal_scsi == dev_scsi) {
2427                                 _D("%s is internal storage", devnode);
2428                                 return 0;
2429                         }
2430                 }
2431         } else {
2432                 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2433                         sscanf(name, "vd%c%d", &emul, &dev_temp);
2434                         if (dev_internal_emul == emul) {
2435                                 _D("%s is internal storage", devnode);
2436                                 return 0;
2437                         }
2438                 }
2439         }
2440
2441         return 1;
2442 }
2443
2444 static int check_already_handled(const char* devnode)
2445 {
2446         struct block_device *bdev;
2447         struct block_data *data;
2448         dd_list *elem;
2449         int i;
2450
2451         for (i = 0; i < THREAD_MAX; i++) {
2452                 pthread_mutex_lock(&(th_manager[i].mutex));
2453                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2454                         data = bdev->data;
2455                         if (!data)
2456                                 continue;
2457                         if (bdev->removed)
2458                                 continue;
2459                         if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2460                                 pthread_mutex_unlock(&(th_manager[i].mutex));
2461                                 return -1;
2462                         }
2463                 }
2464                 pthread_mutex_unlock(&(th_manager[i].mutex));
2465         }
2466
2467         return 0;
2468 }
2469
2470 static int block_init_from_udev_enumerate(void)
2471 {
2472         struct udev *udev;
2473         struct udev_enumerate *enumerate;
2474         struct udev_list_entry *list_entry, *list_sub_entry;
2475         struct udev_device *dev;
2476         const char *syspath;
2477         const char *devnode;
2478         int r = 0;
2479
2480         udev = udev_new();
2481         if (!udev) {
2482                 _E("fail to create udev library context");
2483                 return -EPERM;
2484         }
2485
2486         /* create a list of the devices in the 'usb' subsystem */
2487         enumerate = udev_enumerate_new(udev);
2488         if (!enumerate) {
2489                 _E("fail to create an enumeration context");
2490                 return -EPERM;
2491         }
2492
2493         udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2494         udev_enumerate_add_match_property(enumerate,
2495                         UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2496         udev_enumerate_add_match_property(enumerate,
2497                         UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2498         udev_enumerate_scan_devices(enumerate);
2499
2500         udev_list_entry_foreach(list_entry,
2501                         udev_enumerate_get_list_entry(enumerate)) {
2502                 syspath = udev_list_entry_get_name(list_entry);
2503                 if (!syspath)
2504                         continue;
2505
2506                 dev = udev_device_new_from_syspath(
2507                                 udev_enumerate_get_udev(enumerate),
2508                                 syspath);
2509                 if (!dev)
2510                         continue;
2511
2512                 devnode = NULL;
2513                 udev_list_entry_foreach(list_sub_entry,
2514                                 udev_device_get_devlinks_list_entry(dev)) {
2515                         const char *devlink = udev_list_entry_get_name(list_sub_entry);
2516                         if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2517                                 devnode = devlink;
2518                                 break;
2519                         }
2520                 }
2521
2522                 if (!devnode) {
2523                         devnode = udev_device_get_devnode(dev);
2524                         if (!devnode) {
2525                                 udev_device_unref(dev);
2526                                 continue;
2527                         }
2528
2529                         if (fnmatch(MMC_PATH, devnode, 0) &&
2530                             fnmatch(SCSI_PATH, devnode, 0) &&
2531                             fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0)) {
2532                                 udev_device_unref(dev);
2533                                 continue;
2534                         }
2535                 }
2536
2537                 r = check_external_storage(devnode);
2538                 if (r <= 0) {
2539                         udev_device_unref(dev);
2540                         continue;
2541                 }
2542
2543                 r = check_already_handled(devnode);
2544                 if (r < 0) {
2545                         _I("%s is already handled", devnode);
2546                         udev_device_unref(dev);
2547                         continue;
2548                 }
2549
2550                 _I("%s device add", devnode);
2551                 add_block_device(dev, devnode, false);
2552
2553                 udev_device_unref(dev);
2554         }
2555
2556         udev_enumerate_unref(enumerate);
2557         udev_unref(udev);
2558         return 0;
2559 }
2560
2561 // Called by MainThread
2562 static void show_block_device_list(void)
2563 {
2564         struct block_device *bdev;
2565         struct block_data *data;
2566         dd_list *elem;
2567         int i;
2568
2569         for (i = 0; i < THREAD_MAX; i++) {
2570                 pthread_mutex_lock(&(th_manager[i].mutex));
2571                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2572                         data = bdev->data;
2573                         if (!data)
2574                                 continue;
2575                         if (bdev->removed)
2576                                 continue;
2577                         _D("%s:", data->devnode);
2578                         _D("\tSyspath: %s", data->syspath);
2579                         _D("\tBlock type: %d", data->block_type);
2580                         _D("\tFs type: %s", data->fs_type);
2581                         _D("\tFs usage: %s", data->fs_usage);
2582                         _D("\tFs version: %s", data->fs_version);
2583                         _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2584                         _D("\tReadonly: %s",
2585                                         (data->readonly ? "true" : "false"));
2586                         _D("\tMount point: %s", data->mount_point);
2587                         _D("\tMount state: %s",
2588                                         (data->state == BLOCK_MOUNT ?
2589                                          "mount" : "unmount"));
2590                         _D("\tPrimary: %s",
2591                                         (data->primary ? "true" : "false"));
2592                         _D("\tID: %d", data->id);
2593                 }
2594                 pthread_mutex_unlock(&(th_manager[i].mutex));
2595         }
2596 }
2597
2598 // Called by MainThread
2599 static void remove_whole_block_device(void)
2600 {
2601         struct block_device *bdev;
2602         dd_list *elem;
2603         dd_list *next;
2604         int r;
2605         int i;
2606
2607         for (i = 0; i < THREAD_MAX; i++) {
2608                 do {
2609                         pthread_mutex_lock(&(th_manager[i].mutex));
2610                         DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2611                                 if (bdev->removed == false)
2612                                         break;
2613                         }
2614                         pthread_mutex_unlock(&(th_manager[i].mutex));
2615
2616                         if (bdev && bdev->removed == false) {
2617                                 bdev->removed = true;
2618                                 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2619                                 if (r < 0)
2620                                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2621
2622                                 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2623                                 if (r < 0)
2624                                         _E("Failed to add operation (remove %s)", bdev->data->devnode);
2625                         } else
2626                                 break;
2627                 } while (true);
2628         }
2629 }
2630
2631 static void booting_done(const char *sender_name,
2632                 const char *object_path, const char *interface_name,
2633                 const char *signal_name, DBusMessage *msg,
2634                 void *data)
2635 {
2636         static int done = 0;
2637         int ret;
2638
2639         if (done > 0)
2640                 return;
2641         done = 1;
2642         _I("Booting done");
2643
2644         /* register mmc uevent control routine */
2645         ret = register_udev_uevent_control(&uh);
2646         if (ret < 0)
2647                 _E("fail to register block uevent : %d", ret);
2648
2649         /* if there is the attached device, try to mount */
2650         block_init_from_udev_enumerate();
2651
2652         block_control = true;
2653         block_boot = true;
2654 }
2655
2656 static void block_poweroff(const char *sender_name,
2657                 const char *object_path, const char *interface_name,
2658                 const char *signal_name, DBusMessage *msg,
2659                 void *data)
2660 {
2661         static int status = 0;
2662         if (status > 0)
2663                 return;
2664         status = 1;
2665         _I("Power off");
2666         /* unregister mmc uevent control routine */
2667         unregister_udev_uevent_control(&uh);
2668         remove_whole_block_device();
2669 }
2670
2671 static void uevent_block_handler(struct udev_device *dev)
2672 {
2673         const char *devnode = NULL;
2674         const char *action;
2675         struct udev_list_entry *list_entry;
2676         int r;
2677         bool mapper = false;
2678
2679         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2680                 const char *devlink = udev_list_entry_get_name(list_entry);
2681                 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2682                         devnode = devlink;
2683                         break;
2684                 }
2685                 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2686                         mapper = true;
2687                         devnode = devlink;
2688                         break;
2689                 }
2690         }
2691
2692         if (!devnode) {
2693                 devnode = udev_device_get_devnode(dev);
2694                 if (!devnode)
2695                         return;
2696
2697                 if (fnmatch(MMC_PATH, devnode, 0) &&
2698                     fnmatch(SCSI_PATH, devnode, 0))
2699                         return;
2700         }
2701
2702         r = check_external_storage(devnode);
2703         if (r <= 0)
2704                 return;
2705
2706         action = udev_device_get_action(dev);
2707         if (!action)
2708                 return;
2709
2710         _I("%s device %s", devnode, action);
2711         if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2712            (mapper && !strcmp(action, UDEV_CHANGE))) {
2713                 r = check_already_handled(devnode);
2714                 if (r < 0) {
2715                         _I("%s is already handled", devnode);
2716                         return;
2717                 }
2718
2719                 add_block_device(dev, devnode, mapper);
2720         } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2721                 remove_block_device(dev, devnode);
2722         } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2723                 struct block_device *bdev;
2724                 bdev = find_block_device(devnode);
2725                 if (!bdev) {
2726                         _E("fail to find block data for %s", devnode);
2727                         return;
2728                 }
2729                 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2730                         return;
2731
2732                 r = update_block_data(bdev->data,
2733                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2734                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2735                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2736                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2737                                 udev_device_get_sysattr_value(dev, "ro"),
2738                                 false);
2739                 if (r < 0)
2740                         _E("fail to update block data for %s", bdev->data->devnode);
2741                 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
2742                         _I("filesystem type is updated: crypto_LUKS");
2743         }
2744 }
2745
2746 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2747                 DBusMessage *msg, bool onprivate)
2748 {
2749         struct block_device *bdev;
2750         char *mount_point;
2751         int id;
2752         int ret = -EBADMSG;
2753
2754         if (!reply_handle || !msg)
2755                 goto out;
2756
2757         ret = dbus_message_get_args(msg, NULL,
2758                         DBUS_TYPE_INT32, &id,
2759                         DBUS_TYPE_STRING, &mount_point,
2760                         DBUS_TYPE_INVALID);
2761         if (!ret)
2762                 goto out;
2763
2764         bdev = find_block_device_by_id(id);
2765         if (!bdev) {
2766                 _E("Failed to find (%d) in the device list", id);
2767                 ret = -ENOENT;
2768                 goto out;
2769         }
2770         if (bdev->on_private_op != REQ_NORMAL) {
2771                 ret = -EPERM;
2772                 goto out;
2773         }
2774
2775         if (bdev->data->state == BLOCK_MOUNT) {
2776                 _I("%s is already mounted", bdev->data->devnode);
2777                 ret = -EALREADY;
2778                 goto out;
2779         }
2780
2781         if (onprivate) {
2782                 bdev->on_private_op = REQ_PRIVATE;
2783                 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2784                 _D("Private operation state: %d", bdev->on_private_op);
2785         } else {
2786                 if (bdev->on_private_op != REQ_NORMAL) {
2787                         _E("Failed to process mount operation");
2788                         ret = -EPERM;
2789                         goto out;
2790                 }
2791         }
2792
2793         /* if requester want to use a specific mount point */
2794         if (mount_point && strncmp(mount_point, "", 1) != 0) {
2795                 ret = change_mount_point(bdev, mount_point);
2796                 if (ret < 0) {
2797                         ret = -EPERM;
2798                         goto out;
2799                 }
2800
2801                 /* Create /run/external-storage/id file */
2802                 create_file(bdev->data->id, bdev->data->mount_point, false);
2803         } else {
2804                 /* Create file for block device /run/external-storage/id */
2805                 create_file(bdev->data->id, bdev->data->mount_point, false);
2806         }
2807
2808         ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2809         if (ret < 0) {
2810                 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2811                 goto out;
2812         }
2813
2814         return NULL;
2815
2816 out:
2817         return make_dbus_reply_message_simple(reply_handle, ret);
2818 }
2819
2820 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2821                 DBusMessage *msg)
2822 {
2823         return request_mount_block(reply_handle, msg, false);
2824 }
2825
2826 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2827                 DBusMessage *msg)
2828 {
2829         return request_mount_block(reply_handle, msg, true);
2830 }
2831
2832 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2833                 DBusMessage *msg, bool onprivate)
2834 {
2835         struct block_device *bdev;
2836         pid_t pid;
2837         long option;
2838         int id;
2839         int ret = -EBADMSG;
2840
2841         if (!reply_handle || !msg)
2842                 goto out;
2843
2844         ret = dbus_message_get_args(msg, NULL,
2845                         DBUS_TYPE_INT32, &id,
2846                         DBUS_TYPE_INT32, &option,
2847                         DBUS_TYPE_INVALID);
2848         if (!ret)
2849                 goto out;
2850
2851         bdev = find_block_device_by_id(id);
2852         if (!bdev) {
2853                 _E("Failed to find (%d) in the device list", id);
2854                 ret = -ENOENT;
2855                 goto out;
2856         }
2857
2858         if (onprivate) {
2859                 pid = get_dbus_method_sender_pid(reply_handle);
2860                 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2861                         _E("Failed to process private unmount operation");
2862                         ret = -EPERM;
2863                         goto out;
2864                 }
2865         } else {
2866                 if (bdev->on_private_op != REQ_NORMAL) {
2867                         _E("Failed to process unmount operation");
2868                         ret = -EPERM;
2869                         goto out;
2870                 }
2871         }
2872
2873         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2874         if (ret < 0) {
2875                 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2876                 goto out;
2877         }
2878
2879         if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2880                 ret = add_operation(bdev, BLOCK_LUKS_CLOSE, NULL, NULL);
2881                 if (ret < 0)
2882                         _E("Failed to add operation (luks_close %s)", bdev->data->devnode);
2883         }
2884
2885         return NULL;
2886
2887 out:
2888         return make_dbus_reply_message_simple(reply_handle, ret);
2889 }
2890
2891 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2892                 DBusMessage *msg)
2893 {
2894         return request_unmount_block(reply_handle, msg, false);
2895 }
2896
2897 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2898                 DBusMessage *msg)
2899 {
2900         return request_unmount_block(reply_handle, msg, true);
2901 }
2902
2903 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2904                 DBusMessage *msg)
2905 {
2906         struct block_device *bdev;
2907         struct format_data *fdata;
2908         pid_t pid;
2909         int id;
2910         int option;
2911         int ret = -EBADMSG;
2912         int prev_state;
2913
2914         if (!reply_handle || !msg)
2915                 goto out;
2916
2917         ret = dbus_message_get_args(msg, NULL,
2918                         DBUS_TYPE_INT32, &id,
2919                         DBUS_TYPE_INT32, &option,
2920                         DBUS_TYPE_INVALID);
2921         if (!ret)
2922                 goto out;
2923
2924         bdev = find_block_device_by_id(id);
2925         if (!bdev) {
2926                 _E("Failed to find (%d) in the device list", id);
2927                 goto out;
2928         }
2929
2930         pid = get_dbus_method_sender_pid(reply_handle);
2931         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2932                 _E("Failed to format on private state");
2933                 ret = -EPERM;
2934                 goto out;
2935         }
2936
2937         fdata = get_format_data(NULL, option);
2938         if (!fdata) {
2939                 _E("Failed to get format data");
2940                 goto out;
2941         }
2942
2943         prev_state = bdev->data->state;
2944         if (prev_state == BLOCK_MOUNT) {
2945                 if (bdev->on_private_op == REQ_PRIVATE) {
2946                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
2947                         _D("Private operation state: %d", bdev->on_private_op);
2948                 }
2949                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2950                 if (ret < 0) {
2951                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2952                         release_format_data(fdata);
2953                         goto out;
2954                 }
2955         }
2956
2957         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2958         if (ret < 0) {
2959                 _E("Failed to add operation (format %s)", bdev->data->devnode);
2960                 release_format_data(fdata);
2961         }
2962
2963         /* Maintain previous state of mount/unmount */
2964         if (prev_state == BLOCK_MOUNT) {
2965                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2966                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
2967                         goto out;
2968                 }
2969         }
2970
2971         return NULL;
2972
2973 out:
2974         return make_dbus_reply_message_simple(reply_handle, ret);
2975 }
2976
2977 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2978                 DBusMessage *msg)
2979 {
2980         struct block_device *bdev;
2981         struct format_data *fdata;
2982         char *type;
2983         pid_t pid;
2984         int id;
2985         int option;
2986         int ret = -EBADMSG;
2987         int prev_state;
2988
2989         if (!reply_handle || !msg)
2990                 goto out;
2991
2992         ret = dbus_message_get_args(msg, NULL,
2993                         DBUS_TYPE_INT32, &id,
2994                         DBUS_TYPE_INT32, &option,
2995                         DBUS_TYPE_STRING, &type,
2996                         DBUS_TYPE_INVALID);
2997         if (!ret)
2998                 goto out;
2999
3000         bdev = find_block_device_by_id(id);
3001         if (!bdev) {
3002                 _E("Failed to find (%d) in the device list", id);
3003                 goto out;
3004         }
3005
3006         pid = get_dbus_method_sender_pid(reply_handle);
3007         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3008                 _E("Failed to format on private state");
3009                 ret = -EPERM;
3010                 goto out;
3011         }
3012
3013         fdata = get_format_data(type, option);
3014         if (!fdata) {
3015                 _E("Failed to get format data");
3016                 goto out;
3017         }
3018
3019         prev_state = bdev->data->state;
3020         if (prev_state == BLOCK_MOUNT) {
3021                 if (bdev->on_private_op == REQ_PRIVATE) {
3022                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
3023                         _D("Private operation state: %d", bdev->on_private_op);
3024                 }
3025                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3026                 if (ret < 0) {
3027                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3028                         release_format_data(fdata);
3029                         goto out;
3030                 }
3031         }
3032
3033         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3034         if (ret < 0) {
3035                 _E("Failed to add operation (format %s)", bdev->data->devnode);
3036                 release_format_data(fdata);
3037         }
3038
3039         /* Maintain previous state of mount/unmount */
3040         if (prev_state == BLOCK_MOUNT) {
3041                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3042                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
3043                         goto out;
3044                 }
3045         }
3046
3047         return NULL;
3048
3049 out:
3050         return make_dbus_reply_message_simple(reply_handle, ret);
3051 }
3052
3053 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3054 {
3055         char *str_null = "";
3056
3057         if (!data || !piter)
3058                 return -EINVAL;
3059
3060         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3061                         &(data->block_type));
3062         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3063                         data->devnode ? &(data->devnode) : &str_null);
3064         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3065                         data->syspath ? &(data->syspath) : &str_null);
3066         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3067                         data->fs_usage ? &(data->fs_usage) : &str_null);
3068         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3069                         data->fs_type ? &(data->fs_type) : &str_null);
3070         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3071                         data->fs_version ? &(data->fs_version) : &str_null);
3072         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3073                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3074         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3075                         &(data->readonly));
3076         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3077                         data->mount_point ? &(data->mount_point) : &str_null);
3078         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3079                         &(data->state));
3080         dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3081                         &(data->primary));
3082         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3083                         &(data->flags));
3084         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3085                         &(data->id));
3086
3087         return 0;
3088 }
3089
3090
3091 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3092 {
3093         DBusMessageIter piter;
3094
3095         if (!data || !iter)
3096                 return -EINVAL;
3097
3098         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3099         add_device_to_iter(data, &piter);
3100         dbus_message_iter_close_container(iter, &piter);
3101
3102         return 0;
3103 }
3104
3105 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3106 {
3107         DBusMessageIter piter;
3108         char *str_null = "";
3109
3110         if (!data || !iter)
3111                 return -EINVAL;
3112
3113         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3114         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3115                         &(data->block_type));
3116         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3117                         data->devnode ? &(data->devnode) : &str_null);
3118         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3119                         data->syspath ? &(data->syspath) : &str_null);
3120         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3121                         data->fs_usage ? &(data->fs_usage) : &str_null);
3122         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3123                         data->fs_type ? &(data->fs_type) : &str_null);
3124         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3125                         data->fs_version ? &(data->fs_version) : &str_null);
3126         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3127                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3128         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3129                         &(data->readonly));
3130         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3131                         data->mount_point ? &(data->mount_point) : &str_null);
3132         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3133                         &(data->state));
3134         dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3135                         &(data->primary));
3136         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3137                         &(data->flags));
3138         dbus_message_iter_close_container(iter, &piter);
3139
3140         return 0;
3141 }
3142
3143 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3144                 DBusMessage *msg)
3145 {
3146         DBusMessageIter iter;
3147         DBusMessage *reply;
3148         struct block_device *bdev;
3149         struct block_data *data;
3150         int ret, id;
3151
3152         if (!reply_handle || !msg)
3153                 return NULL;
3154
3155         reply = make_dbus_reply_message(reply_handle);
3156         if (!reply)
3157                 goto out;
3158
3159         ret = dbus_message_get_args(msg, NULL,
3160                         DBUS_TYPE_INT32, &id,
3161                         DBUS_TYPE_INVALID);
3162         if (!ret)
3163                 goto out;
3164
3165         bdev = find_block_device_by_id(id);
3166         if (!bdev)
3167                 goto out;
3168         data = bdev->data;
3169         if (!data)
3170                 goto out;
3171
3172         dbus_message_iter_init_append(reply, &iter);
3173         add_device_to_iter(data, &iter);
3174
3175 out:
3176         return reply;
3177 }
3178
3179 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3180                 DBusMessage *msg)
3181 {
3182         show_block_device_list();
3183         return make_dbus_reply_message(reply_handle);
3184 }
3185
3186 // Called by MainThread
3187 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3188                 DBusMessage *msg)
3189 {
3190         DBusMessageIter iter;
3191         DBusMessageIter aiter;
3192         DBusMessage *reply;
3193         struct block_device *bdev;
3194         struct block_data *data;
3195         dd_list *elem;
3196         char *type = NULL;
3197         int ret = -EBADMSG;
3198         int block_type;
3199         int i;
3200
3201         reply = make_dbus_reply_message(reply_handle);
3202
3203         ret = dbus_message_get_args(msg, NULL,
3204                         DBUS_TYPE_STRING, &type,
3205                         DBUS_TYPE_INVALID);
3206         if (!ret) {
3207                 _E("Failed to get args");
3208                 goto out;
3209         }
3210
3211         if (!type) {
3212                 _E("Delivered type is NULL");
3213                 goto out;
3214         }
3215
3216         _D("Block (%s) device list is requested", type);
3217
3218         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3219                 block_type = BLOCK_SCSI_DEV;
3220         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3221                 block_type = BLOCK_MMC_DEV;
3222         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3223                 block_type = -1;
3224         else {
3225                 _E("Invalid type (%s) is requested", type);
3226                 goto out;
3227         }
3228
3229         dbus_message_iter_init_append(reply, &iter);
3230         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3231
3232         for (i = 0; i < THREAD_MAX; i++) {
3233                 pthread_mutex_lock(&(th_manager[i].mutex));
3234                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3235                         data = bdev->data;
3236                         if (!data)
3237                                 continue;
3238                         if (bdev->removed)
3239                                 continue;
3240
3241                         switch (block_type) {
3242                         case BLOCK_SCSI_DEV:
3243                         case BLOCK_MMC_DEV:
3244                                 if (data->block_type != block_type)
3245                                         continue;
3246                                 break;
3247                         default:
3248                                 break;
3249                         }
3250                         add_device_to_struct_iter(data, &aiter);
3251                 }
3252                 pthread_mutex_unlock(&(th_manager[i].mutex));
3253         }
3254         dbus_message_iter_close_container(&iter, &aiter);
3255
3256 out:
3257         return reply;
3258 }
3259
3260 // Called by MainThread
3261 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3262                 DBusMessage *msg)
3263 {
3264         DBusMessageIter iter;
3265         DBusMessageIter aiter;
3266         DBusMessage *reply;
3267         struct block_device *bdev;
3268         struct block_data *data;
3269         dd_list *elem;
3270         char *type = NULL;
3271         int ret = -EBADMSG;
3272         int block_type;
3273         int i;
3274
3275         reply = make_dbus_reply_message(reply_handle);
3276
3277         ret = dbus_message_get_args(msg, NULL,
3278                         DBUS_TYPE_STRING, &type,
3279                         DBUS_TYPE_INVALID);
3280         if (!ret) {
3281                 _E("Failed to get args");
3282                 goto out;
3283         }
3284
3285         if (!type) {
3286                 _E("Delivered type is NULL");
3287                 goto out;
3288         }
3289
3290         _D("Block (%s) device list is requested", type);
3291
3292         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3293                 block_type = BLOCK_SCSI_DEV;
3294         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3295                 block_type = BLOCK_MMC_DEV;
3296         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3297                 block_type = -1;
3298         else {
3299                 _E("Invalid type (%s) is requested", type);
3300                 goto out;
3301         }
3302
3303         dbus_message_iter_init_append(reply, &iter);
3304         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3305
3306         for (i = 0; i < THREAD_MAX; i++) {
3307                 pthread_mutex_lock(&(th_manager[i].mutex));
3308                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3309                         data = bdev->data;
3310                         if (!data)
3311                                 continue;
3312                         if (bdev->removed)
3313                                 continue;
3314
3315                         switch (block_type) {
3316                         case BLOCK_SCSI_DEV:
3317                         case BLOCK_MMC_DEV:
3318                                 if (data->block_type != block_type)
3319                                         continue;
3320                                 break;
3321                         default:
3322                                 break;
3323                         }
3324
3325                         add_device_to_iter_2(data, &aiter);
3326                 }
3327                 pthread_mutex_unlock(&(th_manager[i].mutex));
3328         }
3329         dbus_message_iter_close_container(&iter, &aiter);
3330
3331 out:
3332         return reply;
3333 }
3334
3335 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3336                 DBusMessage *msg)
3337 {
3338         DBusMessageIter iter;
3339         DBusMessage *reply;
3340         struct block_device *bdev;
3341         struct block_data *data, nodata = {0,};
3342         dd_list *elem;
3343         bool found;
3344         int i;
3345
3346         if (!reply_handle || !msg)
3347                 return NULL;
3348
3349         reply = make_dbus_reply_message(reply_handle);
3350         if (!reply)
3351                 goto out;
3352
3353         found = false;
3354         for (i = 0; i < THREAD_MAX; i++) {
3355                 pthread_mutex_lock(&(th_manager[i].mutex));
3356                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3357                         data = bdev->data;
3358                         if (!data)
3359                                 continue;
3360                         if (bdev->removed)
3361                                 continue;
3362                         if (data->block_type != BLOCK_MMC_DEV &&
3363                             data->block_type != BLOCK_EXTENDEDSD_DEV)
3364                                 continue;
3365                         if (!data->primary)
3366                                 continue;
3367                         // Return mapper node(/dev/mapper/extendedsd) for primary mmc (not /dev/mmcblk1p1(ex))
3368                         if (!strncmp(data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
3369                                 continue;
3370                         found = true;
3371                         break;
3372                 }
3373                 pthread_mutex_unlock(&(th_manager[i].mutex));
3374                 if (found)
3375                         break;
3376         }
3377
3378         dbus_message_iter_init_append(reply, &iter);
3379         if (found)
3380                 add_device_to_iter(data, &iter);
3381         else {
3382                 nodata.id = -ENODEV;
3383                 add_device_to_iter(&nodata, &iter);
3384         }
3385
3386 out:
3387         return reply;
3388 }
3389
3390 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3391                 DBusMessage *msg)
3392 {
3393         struct timespec start_time, end_time;
3394         DBusMessageIter iter;
3395         DBusMessage *reply;
3396         struct block_device *bdev;
3397         struct block_data *data;
3398         char *buf;
3399         int ret = 0;
3400         int id;
3401         int fd;
3402         int time_diff;
3403
3404         if (!reply_handle || !msg)
3405                 return NULL;
3406
3407         ret = dbus_message_get_args(msg, NULL,
3408                         DBUS_TYPE_INT32, &id,
3409                         DBUS_TYPE_INVALID);
3410         if (!ret) {
3411                 ret = -1;
3412                 goto out;
3413         }
3414
3415         bdev = find_block_device_by_id(id);
3416         if (!bdev) {
3417                 ret = -1;
3418                 goto out;
3419         }
3420         data = bdev->data;
3421         if (!data) {
3422                 ret = -1;
3423                 goto out;
3424         }
3425
3426         _D("speed check: %s", data->devnode);
3427         fd = open(data->devnode, O_RDWR | O_SYNC);
3428         buf = calloc(1, SPEEDCHECK << 20);
3429         if (!buf) {
3430                 _E("calloc() failed");
3431                 close(fd);
3432                 ret = -1;
3433                 goto out;
3434         }
3435         clock_gettime(CLOCK_REALTIME, &start_time);
3436         _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3437         ret = write(fd, buf, SPEEDCHECK << 20);
3438         clock_gettime(CLOCK_REALTIME, &end_time);
3439         _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3440
3441         free(buf);
3442
3443         time_diff = end_time.tv_sec - start_time.tv_sec;
3444         if (time_diff > 0 && (SPEEDCHECK / time_diff < 4)) {
3445                 ret = -1;
3446                 close(fd);
3447                 goto out;
3448         }
3449
3450         if (ret < 0) {
3451                 _E("write() failed %d", errno);
3452                 close(fd);
3453                 goto out;
3454         }
3455
3456         close(fd);
3457 out:
3458         reply = dbus_message_new_method_return(msg);
3459         dbus_message_iter_init_append(reply, &iter);
3460         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3461         return reply;
3462 }
3463
3464
3465 static DBusMessage *request_control_block(dbus_method_reply_handle_h reply_handle,
3466                 DBusMessage *msg)
3467 {
3468         int ret;
3469         int enable;
3470         DBusMessage *reply;
3471         DBusMessageIter iter;
3472
3473         ret = dbus_message_get_args(msg, NULL,
3474                         DBUS_TYPE_INT32, &enable,
3475                         DBUS_TYPE_INVALID);
3476         if (!ret) {
3477                 ret = -1;
3478                 goto out;
3479         }
3480
3481         if (enable == 1) {
3482                 _I("control block Enable");
3483                 block_start(NULL);
3484         } else if (enable == 0) {
3485                 _I("control block Disable");
3486                 block_stop(NULL);
3487         } else {
3488                 _E("control block : Wrong request by client");
3489                 ret = -1;
3490                 goto out;
3491         }
3492
3493 out:
3494         reply = dbus_message_new_method_return(msg);
3495         dbus_message_iter_init_append(reply, &iter);
3496         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3497
3498         return reply;
3499 }
3500
3501 static DBusMessage *request_getcontrol_block(dbus_method_reply_handle_h reply_handle,
3502                 DBusMessage *msg)
3503 {
3504         int is_enabled;
3505         DBusMessage *reply;
3506         DBusMessageIter iter;
3507
3508         _I("getcontrol block");
3509
3510         is_enabled = block_control;
3511
3512         reply = dbus_message_new_method_return(msg);
3513         dbus_message_iter_init_append(reply, &iter);
3514         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &is_enabled);
3515
3516         return reply;
3517 }
3518
3519 /*
3520   Method name      Method call format string  Reply format string
3521 { "ShowDeviceList",                      NULL,               NULL, request_show_device_list },
3522 { "GetDeviceList",                        "s", "a(issssssisibii)", request_get_device_list },
3523 { "GetDeviceList2",                       "s",  "a(issssssisibi)", request_get_device_list_2 },
3524 { "Mount",                               "is",                "i", request_public_mount_block },
3525 { "Unmoun,                               "ii",                "i", request_public_unmount_block },
3526 { "Format",                              "ii",                "i", request_format_block },
3527 { "GetDeviceInfo",                        "i",  "(issssssisibii)", request_get_device_info },
3528 { "GetMmcPrimary",                       NULL, "(issssssisibii)" , request_get_mmc_primary },
3529 { "PrivateMount",                        "is",                "i", request_private_mount_block },
3530 { "PrivateUnmount",                      "ii",                "i", request_private_unmount_block },
3531 */
3532
3533 static const dbus_method_s manager_methods[] = {
3534         { "ShowDeviceList",         NULL, request_show_device_list },
3535         { "GetDeviceList" ,         "s", request_get_device_list },
3536         { "GetDeviceList2",         "s", request_get_device_list_2 },
3537         { "Mount",                  "is", request_public_mount_block },
3538         { "Unmount",                "ii", request_public_unmount_block },
3539         { "Format",                 "ii", request_format_block },
3540         { "FormatwithType",        "iis", request_format_block_type },
3541         { "GetDeviceInfo",          "i", request_get_device_info },
3542         { "GetMmcPrimary" ,         NULL, request_get_mmc_primary },
3543         { "PrivateMount",           "is", request_private_mount_block },
3544         { "PrivateUnmount",         "ii", request_private_unmount_block },
3545         { "CheckSpeed",              "i", request_check_speed },
3546         { "Control",                 "i", request_control_block },
3547         { "GetControl",              "i", request_getcontrol_block },
3548 };
3549
3550 static dbus_interface_s block_interface = {
3551         .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3552         .methods = manager_methods,
3553         .nr_methods = ARRAY_SIZE(manager_methods),
3554 };
3555
3556 static int load_config(struct parse_result *result, void *user_data)
3557 {
3558         int index;
3559
3560         if (MATCH(result->section, "Block"))
3561                 return 0;
3562
3563         if (MATCH(result->section, "SCSI"))
3564                 index = BLOCK_SCSI_DEV;
3565         else if (MATCH(result->section, "MMC"))
3566                 index = BLOCK_MMC_DEV;
3567         else if (MATCH(result->section, "Mapper"))
3568                 index = BLOCK_EXTENDEDSD_DEV;
3569         else
3570                 return -EINVAL;
3571
3572         if (MATCH(result->name, "Multimount"))
3573                 block_conf[index].multimount =
3574                         (MATCH(result->value, "yes") ? true : false);
3575         if (MATCH(result->name, "ExtendedInternalStorage"))
3576                 block_conf[index].extendedinternal =
3577                         (MATCH(result->value, "yes") ? true : false);
3578
3579         return 0;
3580 }
3581
3582 #ifdef BLOCK_TMPFS
3583 static int mount_root_path_tmpfs(void)
3584 {
3585         int ret;
3586         const char *root;
3587
3588         root = tzplatform_getenv(TZ_SYS_MEDIA);
3589         if (!root)
3590                 return -ENOTSUP;
3591
3592         if (access(root, F_OK) != 0)
3593                 return -ENODEV;
3594
3595         if (mount_check(root))
3596                 return 0;
3597
3598         ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3599         if (ret < 0) {
3600                 ret = -errno;
3601                 _E("tmpfs mount failed (%d)", ret);
3602                 return ret;
3603         }
3604
3605         return 0;
3606 }
3607 #else
3608 #define mount_root_path_tmpfs() 0
3609 #endif
3610
3611 static void block_init(void *data)
3612 {
3613         struct stat buf;
3614         int ret;
3615         int i;
3616         dbus_handle_h handle;
3617
3618         udev_init(NULL);
3619
3620         /* load config */
3621         ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3622         if (ret < 0)
3623                 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3624
3625         ret = mount_root_path_tmpfs();
3626         if (ret < 0)
3627                 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3628
3629         ret = dbus_get_connection(&handle);
3630         if (ret < 0)
3631                 _E("Failed to get dbus connection(%d)", ret);
3632
3633         /* register block manager object and interface */
3634         ret = register_dbus_methods(handle,
3635                         STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3636                         NULL, NULL);
3637         if (ret < 0)
3638                 _E("Failed to register block interface and methods (%d)", ret);
3639
3640         /* init pipe */
3641         ret = pipe_init();
3642         if (ret < 0)
3643                 _E("fail to init pipe");
3644
3645         /* System Session is loaded completely */
3646         register_dbus_signal(SYSTEMD_DBUS_PATH,
3647                     SYSTEMD_DBUS_IFACE_MANAGER,
3648                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3649                     booting_done, NULL, NULL);
3650
3651         register_dbus_signal(DEVICED_PATH_POWEROFF,
3652                         DEVICED_INTERFACE_POWEROFF,
3653                         SIGNAL_POWEROFF_STATE,
3654                         block_poweroff, NULL, NULL);
3655
3656         for (i = 0; i < THREAD_MAX; i++) {
3657                 th_manager[i].num_dev = 0;
3658                 th_manager[i].op_len = 0;
3659                 th_manager[i].start_th = true;
3660                 th_manager[i].thread_id = i;
3661                 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3662                 pthread_cond_init(&(th_manager[i].cond), NULL);
3663         }
3664
3665         ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3666         if (ret < 0) {
3667                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3668                 if (ret < 0)
3669                         _E("Failed to make directory: %d", errno);
3670         } else if (!S_ISDIR(buf.st_mode)) {
3671                 ret = remove(EXTERNAL_STORAGE_PATH);
3672                 if (ret < 0)
3673                         _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3674                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3675                 if (ret < 0)
3676                         _E("Failed to make directory: %d", errno);
3677         } else {
3678                 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3679                 if (ret < 0)
3680                         _E("Fail to change permissions of a file");
3681         }
3682
3683         ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3684         if (ret < 0) {
3685                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3686                 if (ret < 0)
3687                         _E("Failed to make directory: %d", errno);
3688         } else if (!S_ISDIR(buf.st_mode)) {
3689                 ret = remove(EXTENDED_INTERNAL_PATH);
3690                 if (ret < 0)
3691                         _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3692                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3693                 if (ret < 0)
3694                         _E("Failed to make directory: %d", errno);
3695         } else {
3696                 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3697                 if (ret < 0)
3698                         _E("Fail to change permissions of a file");
3699         }
3700
3701         ret = get_internal_storage_number();
3702         if (ret < 0)
3703                 _E("Failed to get internal storage number");
3704 }
3705
3706 static void block_exit(void *data)
3707 {
3708         dd_list *elem, *elem_next;
3709         char *temp;
3710         int ret, i;
3711
3712         udev_exit(NULL);
3713
3714         /* unregister notifier for below each event */
3715         unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3716                     SYSTEMD_DBUS_IFACE_MANAGER,
3717                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3718                     booting_done);
3719
3720         unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3721                         DEVICED_INTERFACE_POWEROFF,
3722                         SIGNAL_POWEROFF_STATE, block_poweroff);
3723
3724         /* unregister mmc uevent control routine */
3725         ret = unregister_udev_uevent_control(&uh);
3726         if (ret < 0)
3727                 _E("fail to unregister block uevent : %d", ret);
3728
3729         /* remove remaining blocks */
3730         remove_whole_block_device();
3731
3732         for (i = 0; i < THREAD_MAX; i++) {
3733                 if (!th_manager[i].start_th)
3734                         pthread_cancel(th_manager[i].th);
3735                 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3736                         DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3737                         free(temp);
3738                 }
3739         }
3740
3741         /* exit pipe */
3742         pipe_exit();
3743
3744         block_control = false;
3745 }
3746
3747 static int block_start(void *data)
3748 {
3749         int ret;
3750
3751         if (!block_boot) {
3752                 _E("Cannot be started. Booting is not ready");
3753                 return -ENODEV;
3754         }
3755
3756         if (block_control) {
3757                 _I("Already started");
3758                 return 0;
3759         }
3760
3761         /* register mmc uevent control routine */
3762         ret = register_udev_uevent_control(&uh);
3763         if (ret < 0)
3764                 _E("fail to register block uevent : %d", ret);
3765
3766         block_init_from_udev_enumerate();
3767
3768         block_control = true;
3769
3770         _I("start");
3771         return 0;
3772 }
3773
3774 static int block_stop(void *data)
3775 {
3776         if (!block_boot) {
3777                 _E("Cannot be stopped. Booting is not ready");
3778                 return -ENODEV;
3779         }
3780
3781         if (!block_control) {
3782                 _I("Already stopped");
3783                 return 0;
3784         }
3785
3786         /* unregister mmc uevent control routine */
3787         unregister_udev_uevent_control(&uh);
3788
3789         /* remove the existing blocks */
3790         remove_whole_block_device();
3791
3792         block_control = false;
3793
3794         _I("stop");
3795         return 0;
3796 }
3797
3798 static storaged_module_interface block_module = {
3799         .name     = "block",
3800         .init     = block_init,
3801         .exit     = block_exit,
3802         .start    = block_start,
3803         .stop     = block_stop,
3804 };
3805
3806 __attribute__ ((visibility("default")))storaged_module_interface *
3807 storaged_get_module_interface(void)
3808 {
3809         return &block_module;
3810 }