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