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