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