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