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