Add a new operation type (BLOCK_LUKS_CLOSE)
[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_PATH   "/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         BLOCK_LUKS_CLOSE,
127 };
128
129 enum private_operation_state {
130         REQ_NORMAL,
131         REQ_PRIVATE,
132         REQ_PRIVATE_FORMAT,
133 };
134
135 struct operation_queue {
136         enum block_dev_operation op;
137         dbus_method_reply_handle_h reply_handle;
138         void *data;
139         bool done;
140 };
141
142 struct block_device {
143         struct block_data *data;
144         dd_list *op_queue;
145         int thread_id;          /* Current thread ID */
146         bool removed;           /* True when device is physically removed but operation is not precessed yet */
147         enum private_operation_state on_private_op;
148         bool mount_point_updated;
149         pid_t private_pid;
150 };
151
152 struct format_data {
153         struct block_device *bdev;
154         char *fs_type;
155         enum unmount_operation option;
156 };
157
158 struct pipe_data {
159         enum block_dev_operation op;
160         struct block_device *bdev;
161         int result;
162 };
163
164 static struct block_conf {
165         bool multimount;
166         bool extendedinternal;
167 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
168
169 static struct manage_thread {
170         dd_list *th_node_list;  /* List of devnode which thread dealt with. Only main thread access */
171         dd_list *block_dev_list; /* Use thread mutex */
172         pthread_t th;
173         pthread_mutex_t mutex;
174         pthread_cond_t cond;
175         int num_dev;            /* Number of devices which thread holds. Only main thread access */
176         int op_len;             /* Number of operation of thread. Use thread mutex */
177         int thread_id;          /* Never changed */
178         bool start_th;
179 } th_manager[THREAD_MAX];
180
181 static dd_list *fs_head;
182 static dd_list *block_ops_list;
183 static bool smack;
184 static int pfds[2];
185 static fd_handler_h phandler;
186 static bool block_control = false;
187 static bool block_boot = false;
188 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
189
190 /* Assume there is only one physical internal storage */
191 static int dev_internal = -1;
192 static char dev_internal_scsi = '\0';
193 static char dev_internal_emul = '\0';
194
195 static int 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_PATH);
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)
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         retrieve_udev_device(data, mount_point_updated);
1494 out:
1495         return r;
1496 }
1497
1498 static int format_block_device(struct block_device *bdev,
1499                 const char *fs_type,
1500                 enum unmount_operation option)
1501 {
1502         struct block_data *data;
1503         int r;
1504
1505         assert(bdev);
1506         assert(bdev->data);
1507
1508         data = bdev->data;
1509
1510         _I("Format Start : (%s -> %s)",
1511                         data->devnode, data->mount_point);
1512
1513         if (data->state == BLOCK_MOUNT) {
1514                 r = block_unmount(bdev, option);
1515                 if (r < 0) {
1516                         _E("fail to unmount %s device : %d", data->devnode, r);
1517                         goto out;
1518                 }
1519         }
1520
1521         r = block_format(data, fs_type, bdev->mount_point_updated);
1522         if (r < 0)
1523                 _E("fail to format %s device : %d", data->devnode, r);
1524
1525 out:
1526         _I("%s result : %s, %d", __func__, data->devnode, r);
1527
1528         r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1529         if (r < 0)
1530                 _E("fail to trigger pipe");
1531
1532         return r;
1533 }
1534
1535 static struct format_data *get_format_data(
1536                 const char *fs_type, enum unmount_operation option)
1537 {
1538         struct format_data *fdata;
1539
1540         fdata = (struct format_data *)malloc(sizeof(struct format_data));
1541         if (!fdata) {
1542                 _E("fail to allocate format data");
1543                 return NULL;
1544         }
1545
1546         if (fs_type)
1547                 fdata->fs_type = strdup(fs_type);
1548         else
1549                 fdata->fs_type = NULL;
1550         fdata->option = option;
1551
1552         return fdata;
1553 }
1554
1555 static void release_format_data(struct format_data *data)
1556 {
1557         if (data) {
1558                 if (data->fs_type)
1559                         free(data->fs_type);
1560                 free(data);
1561         }
1562 }
1563
1564 // Called by BlockThread - Real Mount Op
1565 static int block_mount_device(struct block_device *bdev, void *data)
1566 {
1567         dd_list *l;
1568         int ret;
1569         int thread_id;
1570
1571         if (!bdev)
1572                 return -EINVAL;
1573
1574         thread_id = bdev->thread_id;
1575         if (thread_id < 0 || thread_id >= THREAD_MAX)
1576                 return -EINVAL;
1577         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1578         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1579         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1580         if (!l) {
1581                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1582                 return -ENOENT;
1583         }
1584
1585         /* mount automatically */
1586         ret = mount_block_device(bdev);
1587         if (ret < 0)
1588                 _E("fail to mount block device for %s", bdev->data->devnode);
1589
1590         return ret;
1591 }
1592
1593 // Called by BlockThread - Real Format Op
1594 static int block_format_device(struct block_device *bdev, void *data)
1595 {
1596         dd_list *l;
1597         int ret;
1598         int thread_id;
1599         struct format_data *fdata = (struct format_data *)data;
1600
1601         if (!bdev || !fdata) {
1602                 ret = -EINVAL;
1603                 goto out;
1604         }
1605
1606         thread_id = bdev->thread_id;
1607         if (thread_id < 0 || thread_id >= THREAD_MAX)
1608                 return -EINVAL;
1609         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1610         l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1611         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1612         if (!l) {
1613                 _E("(%d) does not exist in the device list", bdev->data->devnode);
1614                 ret = -ENOENT;
1615                 goto out;
1616         }
1617
1618         ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1619         if (ret < 0)
1620                 _E("fail to mount block device for %s", bdev->data->devnode);
1621
1622 out:
1623         release_format_data(fdata);
1624
1625         return ret;
1626 }
1627
1628 // Called by BlockThread - Real Unmount Op
1629 static int block_unmount_device(struct block_device *bdev, void *data)
1630 {
1631         int ret;
1632         long option = (long)data;
1633
1634         if (!bdev)
1635                 return -EINVAL;
1636
1637         ret = unmount_block_device(bdev, option);
1638         if (ret < 0) {
1639                 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1640                 return ret;
1641         }
1642
1643         return 0;
1644 }
1645
1646 /* Called by BlockThread - Remove Operation
1647    Direct Call at BlockThread
1648    Previously this function was called by MainThread. However, it will increase complexity.
1649    Need thread lock before to call remove_operation
1650 */
1651 static void remove_operation(struct block_device *bdev)
1652 {
1653         struct operation_queue *op;
1654         dd_list *l, *next;
1655         char name[16];
1656         int thread_id;
1657
1658         assert(bdev);
1659
1660         thread_id = bdev->thread_id;
1661         if (thread_id < 0 || thread_id >= THREAD_MAX)
1662                 return;
1663
1664         DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1665                 if (op->done) {
1666                         _D("Remove operation (%s, %s)",
1667                                         get_operation_char(op->op, name, sizeof(name)),
1668                                         bdev->data->devnode);
1669
1670                         DD_LIST_REMOVE(bdev->op_queue, op);
1671                         free(op);
1672                 }
1673         }
1674 }
1675
1676 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1677 {
1678         DBusMessage *rep;
1679
1680         if (!reply_handle)
1681                 return;
1682
1683         rep = make_dbus_reply_message_simple(reply_handle, result);
1684         reply_dbus_method_result(reply_handle, rep);
1685 }
1686
1687 // Called by BlockThread
1688 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1689 {
1690         struct operation_queue *temp;
1691         dd_list *l;
1692         int thread_id;
1693
1694         if (!bdev)
1695                 return;
1696
1697         if (!queue)
1698                 return;
1699
1700         if (!op)
1701                 return;
1702
1703         thread_id = bdev->thread_id;
1704         if (thread_id < 0 || thread_id >= THREAD_MAX)
1705                 return;
1706
1707         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1708
1709         DD_LIST_FOREACH(*queue, l, temp) {
1710                 if (temp->op == BLOCK_DEV_REMOVE) {
1711                         *op = temp;
1712                         break;
1713                 }
1714                 temp->done = true;
1715                 th_manager[thread_id].op_len--;
1716                 block_send_dbus_reply((*op)->reply_handle, 0);
1717         }
1718
1719         remove_operation(bdev);
1720         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1721 }
1722
1723 // Called by BlockThread
1724 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1725 {
1726         struct operation_queue *temp;
1727         dd_list *l;
1728         int thread_id;
1729         bool unmounted = false;
1730
1731         if (!bdev)
1732                 return false;
1733
1734         if (!queue)
1735                 return false;
1736
1737         if (!op)
1738                 return false;
1739
1740         thread_id = bdev->thread_id;
1741         if (thread_id < 0 || thread_id >= THREAD_MAX)
1742                 return false;
1743
1744         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1745         DD_LIST_FOREACH(*queue, l, temp) {
1746                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1747                         unmounted = true;
1748                         _D("Operation queue has unmount operation");
1749                         break;
1750                 }
1751         }
1752         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1753
1754         if (!unmounted)
1755                 return unmounted;
1756
1757         pthread_mutex_lock(&(th_manager[thread_id].mutex));
1758
1759         DD_LIST_FOREACH(*queue, l, temp) {
1760                 if (temp->op == BLOCK_DEV_UNMOUNT) {
1761                         *op = temp;
1762                         break;
1763                 }
1764                 temp->done = true;
1765                 th_manager[thread_id].op_len--;
1766                 block_send_dbus_reply((*op)->reply_handle, 0);
1767         }
1768
1769         remove_operation(bdev);
1770         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1771
1772         return unmounted;
1773 }
1774
1775 // Called by BlockThread
1776 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1777 {
1778         int ret = 0;
1779         int thread_id;
1780         char devnode[PATH_MAX];
1781         char name[16];
1782         enum block_dev_operation operation;
1783         bool unmounted = false;
1784
1785         assert(bdev);
1786
1787         if (!queue)
1788                 return;
1789
1790         thread_id = bdev->thread_id;
1791         if (thread_id < 0 || thread_id >= THREAD_MAX)
1792                 return;
1793
1794         snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1795
1796         do {
1797                 if (!op)
1798                         return;
1799                 if (op->done)
1800                         return;
1801
1802                 operation = op->op;
1803
1804                 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1805                         get_operation_char(operation, name, sizeof(name)), devnode);
1806
1807                 unmounted = false;
1808                 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1809                         check_removed(bdev, &queue, &op);
1810                         operation = op->op;
1811                         _D("Trigger operation again (%s, %s)",
1812                                 get_operation_char(operation, name, sizeof(name)), devnode);
1813                 }
1814                 if (operation == BLOCK_DEV_MOUNT) {
1815                         unmounted = check_unmount(bdev, &queue, &op);
1816                         if (unmounted) {
1817                                 operation = op->op;
1818                                 _D("Trigger operation again (%s, %s)",
1819                                         get_operation_char(operation, name, sizeof(name)), devnode);
1820                         }
1821                 }
1822
1823                 switch (operation) {
1824                 case BLOCK_DEV_INSERT:
1825                         break;
1826                 case BLOCK_DEV_MOUNT:
1827                         ret = block_mount_device(bdev, op->data);
1828                         _D("Mount (%s) result:(%d)", devnode, ret);
1829                         break;
1830                 case BLOCK_DEV_FORMAT:
1831                         ret = block_format_device(bdev, op->data);
1832                         _D("Format (%s) result:(%d)", devnode, ret);
1833                         break;
1834                 case BLOCK_DEV_UNMOUNT:
1835                         ret = block_unmount_device(bdev, op->data);
1836                         _D("Unmount (%s) result:(%d)", devnode, ret);
1837                         break;
1838                 case BLOCK_DEV_REMOVE:
1839                         /* Do nothing */
1840                         break;
1841                 case BLOCK_LUKS_CLOSE:
1842                         ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1843                         if (ret < 0)
1844                                 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1845                         break;
1846                 default:
1847                         _E("Operation type is invalid (%d)", op->op);
1848                         ret = -EINVAL;
1849                         break;
1850                 }
1851
1852                 /* LOCK
1853                  * during checking the queue length */
1854                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1855
1856                 op->done = true;
1857                 th_manager[thread_id].op_len--;
1858
1859                 block_send_dbus_reply(op->reply_handle, ret);
1860
1861                 queue = bdev->op_queue;
1862                 if (queue != NULL) {
1863                         queue = DD_LIST_NEXT(queue);
1864                         if (queue != NULL)
1865                                 op = DD_LIST_NTH(queue, 0);
1866                         else
1867                                 op = NULL;
1868                 } else
1869                         op = NULL;
1870
1871                 remove_operation(bdev);
1872
1873                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1874                 /* UNLOCK */
1875
1876                 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1877                         if (pipe_trigger(operation, bdev, 0) < 0)
1878                                 _E("fail to trigger pipe");
1879                 }
1880
1881         } while (true);
1882
1883 }
1884
1885 // Called by BlockThread
1886 static void *block_th_start(void *arg)
1887 {
1888         struct block_device *temp;
1889         struct manage_thread *th = (struct manage_thread *)arg;
1890         struct operation_queue *op = NULL;
1891         dd_list *elem;
1892         dd_list *queue = NULL;
1893         int thread_id;
1894
1895         assert(th);
1896
1897         thread_id = th->thread_id;
1898         if (thread_id < 0 || thread_id >= THREAD_MAX) {
1899                 _E("Thread Number: %d", th->thread_id);
1900                 return NULL;
1901         }
1902
1903         do {
1904                 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1905                 if (th_manager[thread_id].op_len == 0) {
1906                         _D("Operation queue of thread is empty");
1907                         pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1908                         _D("Wake up %d", thread_id);
1909                 }
1910
1911                 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1912                         queue = temp->op_queue;
1913                         do {
1914                                 op = DD_LIST_NTH(queue, 0);
1915                                 if (!op) {
1916                                         _D("Operation queue for device %s is Empty", temp->data->devnode);
1917                                         break;
1918                                 }
1919                                 if (op->done) {
1920                                         queue = DD_LIST_NEXT(queue);
1921                                         continue;
1922                                 }
1923                                 break;
1924                         } while (true);
1925                         if (op)
1926                                 break;
1927                 }
1928                 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1929
1930                 if (op && !op->done)
1931                         trigger_operation(temp, queue, op);
1932
1933         } while (true);
1934 }
1935
1936 // This function will be refactored later
1937 // Especially, we don't need to keep th_node_list.
1938 static int find_thread(char *devnode)
1939 {
1940         dd_list *elem;
1941         char str[PATH_MAX];
1942         char *th_node;
1943         char *temp;
1944         char dev_scsi;
1945         int i, len, min, min_num;
1946         int dev_mmc = -1, part = -1, num;
1947
1948         len = 0;
1949         if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1950                 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1951                 num = dev_mmc;
1952                 while (num > 0) {
1953                         num = num / 10;
1954                         len++;
1955                 }
1956                 len = len + 12;
1957                 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1958                 th_node = strdup(str);
1959         } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1960                 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1961                 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1962                 th_node = strdup(str);
1963         } else
1964                 th_node = strdup(devnode);
1965
1966         len = strlen(th_node) + 1;
1967         min_num = 1000;
1968         min = -1;
1969         for (i = 0; i < THREAD_MAX; i++) {
1970                 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1971                         if (!strncmp(temp, th_node, len)) {
1972                                 free(th_node);
1973                                 return i;
1974                         }
1975                 }
1976                 if (th_manager[i].num_dev < min_num) {
1977                         min_num = th_manager[i].num_dev;
1978                         min = i;
1979                 }
1980         }
1981
1982         if (min >= 0 && min < THREAD_MAX) {
1983                 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1984                 return min;
1985         }
1986
1987         _E("Finding thread is failed");
1988         DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1989         return 0;
1990 }
1991
1992 /* Only Main thread is permmited */
1993 // Called by MainThread
1994 static int add_operation(struct block_device *bdev,
1995                 enum block_dev_operation operation,
1996                 dbus_method_reply_handle_h reply_handle, void *data)
1997 {
1998         struct operation_queue *op;
1999         int ret;
2000         int thread_id;
2001         bool start_th;
2002         char name[16];
2003
2004         if (!bdev)
2005                 return -EINVAL;
2006
2007
2008         _I("Add operation (%s, %s)",
2009                         get_operation_char(operation, name, sizeof(name)),
2010                         bdev->data->devnode);
2011
2012         thread_id = bdev->thread_id;
2013         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2014                 _E("Fail to find thread to add");
2015                 return -EPERM;
2016         }
2017
2018         op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2019         if (!op) {
2020                 _E("malloc failed");
2021                 return -ENOMEM;
2022         }
2023
2024         op->op = operation;
2025         op->data = data;
2026         op->reply_handle = reply_handle;
2027
2028         /* LOCK
2029          * during adding queue and checking the queue length */
2030         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2031
2032         /* Only modified between lock and unlock of mutex */
2033         op->done = false;
2034
2035         start_th = th_manager[thread_id].start_th;
2036         DD_LIST_APPEND(bdev->op_queue, op);
2037         th_manager[thread_id].op_len++;
2038
2039         if (th_manager[thread_id].op_len == 1 && !start_th)
2040                 pthread_cond_signal(&(th_manager[thread_id].cond));
2041
2042         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2043         /* UNLOCK */
2044
2045         /* Need to disble app2ext whenever unmounting mmc */
2046         if (op->op == BLOCK_DEV_UNMOUNT &&
2047                 bdev->data->state == BLOCK_MOUNT &&
2048                 bdev->data->block_type == BLOCK_MMC_DEV &&
2049                 bdev->data->primary)
2050                 if (app2ext_disable_all_external_pkgs() < 0)
2051                         _E("app2ext_disable_all_external_pkgs() failed");
2052
2053
2054         if (start_th) {
2055                 _D("Start New thread for block device");
2056                 th_manager[thread_id].start_th = false;
2057                 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2058                 if (ret != 0) {
2059                         _E("fail to create thread for %s", bdev->data->devnode);
2060                         return -EPERM;
2061                 }
2062
2063                 pthread_detach(th_manager[thread_id].th);
2064         }
2065
2066         return 0;
2067 }
2068
2069 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2070 {
2071         DIR *dp;
2072         struct dirent entry;
2073         struct dirent *dir;
2074         const char *syspath;
2075         bool ret = false;
2076
2077         syspath = udev_device_get_syspath(dev);
2078         if (!syspath)
2079                 goto out;
2080
2081         dp = opendir(syspath);
2082         if (!dp) {
2083                 _E("fail to open %s", syspath);
2084                 goto out;
2085         }
2086
2087         /* TODO compare devname and d_name */
2088         while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2089                 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2090                     !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2091                         ret = true;
2092                         break;
2093                 }
2094         }
2095
2096         closedir(dp);
2097
2098 out:
2099         return ret;
2100 }
2101
2102 static bool check_partition(struct udev_device *dev)
2103 {
2104         const char *devtype;
2105         const char *part_table_type;
2106         const char *fs_usage;
2107         bool ret = false;
2108
2109         /* only consider disk type, never partitions */
2110         devtype = udev_device_get_devtype(dev);
2111         if (!devtype)
2112                 goto out;
2113
2114         if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2115                                 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2116                 goto out;
2117
2118         part_table_type = udev_device_get_property_value(dev,
2119                         "ID_PART_TABLE_TYPE");
2120         if (part_table_type) {
2121                 fs_usage = udev_device_get_property_value(dev,
2122                                 "ID_FS_USAGE");
2123                 if (fs_usage &&
2124                     strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2125                         if (!disk_is_partitioned_by_kernel(dev))
2126                                         goto out;
2127                 }
2128                 ret = true;
2129                 goto out;
2130         }
2131
2132         if (disk_is_partitioned_by_kernel(dev)) {
2133                 ret = true;
2134                 goto out;
2135         }
2136
2137 out:
2138         return ret;
2139 }
2140
2141 // Called by MainThread
2142 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2143 {
2144         struct block_data *data;
2145         struct block_device *bdev;
2146         //char id_string[PATH_LEN];
2147         bool partition;
2148         int ret;
2149         int thread_id;
2150         bool need_format = false;
2151
2152         partition = check_partition(dev);
2153         if (partition) {
2154                 /* if there is a partition, skip this request */
2155                 _I("%s device has partitions, skip this time", devnode);
2156                 return 0;
2157         }
2158
2159         if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2160                 char syspath[128] = {0};
2161                 char *r;
2162
2163                 r = rindex(udev_device_get_syspath(dev), '/');
2164                 if (!r) return -ENODEV;
2165
2166                 sprintf(syspath, "/sys/block%s", r);
2167                 data = make_block_data(devnode,
2168                                 syspath,
2169                                 FILESYSTEM,
2170                                 EXT4_NAME,
2171                                 "1.0",
2172                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2173                                 udev_device_get_sysattr_value(dev, "ro"));
2174                 need_format = true;
2175         } else {
2176                 data = make_block_data(devnode,
2177                                 udev_device_get_syspath(dev),
2178                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2179                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2180                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2181                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2182                                 udev_device_get_sysattr_value(dev, "ro"));
2183         }
2184
2185         if (!data) {
2186                 _E("fail to make block data for %s", devnode);
2187                 return -EPERM;
2188         }
2189
2190         if (!block_conf[data->block_type].multimount && !data->primary &&
2191             data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM)) {
2192                 _D("Not support multi mount by config info");
2193                 free_block_data(data);
2194                 return -EPERM;
2195         }
2196
2197         bdev = make_block_device(data);
2198         if (!bdev) {
2199                 _E("fail to make block device for %s", devnode);
2200                 free_block_data(data);
2201                 return -EPERM;
2202         }
2203
2204         thread_id = find_thread(bdev->data->devnode);
2205         if (thread_id < 0 || thread_id >= THREAD_MAX) {
2206                 _E("Fail to find thread to add");
2207                 free_block_device(bdev);
2208                 return -EPERM;
2209         }
2210         bdev->thread_id = thread_id;
2211
2212         pthread_mutex_lock(&(th_manager[thread_id].mutex));
2213         th_manager[thread_id].num_dev++;
2214         DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2215         pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2216
2217         if (need_format) {
2218                 struct format_data *fdata;
2219
2220                 fdata = get_format_data(NULL, UNMOUNT_FORCE);
2221                 if (!fdata) {
2222                         _E("Failed to get format data");
2223                         return -ENOMEM;
2224                 }
2225
2226                 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2227                 if (ret < 0) {
2228                         _E("Failed to add operation (format %s)", bdev->data->devnode);
2229                         release_format_data(fdata);
2230                 }
2231         }
2232
2233         if (!bdev->data->fs_type) {
2234                 _E("Unformatted Storage");
2235                 free_block_device(bdev);
2236                 return -EPERM;
2237         } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2238                 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2239                 _D("Need to unlock encrypted sdcard");
2240                 // ---- ODE UI launch ----
2241                 ret = launch_system_app(POPUP_DEFAULT
2242                                       , 8
2243                                       , POPUP_KEY_CONTENT
2244                                       , "unlockextendedsd"
2245                                       , VIEWTYPE_KEY
2246                                       , INSERT_SD_CARD
2247                                       , DEVPATH_KEY
2248                                       , bdev->data->devnode
2249                                       , MAPPING_NODE_KEY
2250                                       , EXTENDEDSD_NAME);
2251                 if (ret < 0)
2252                         _E("Failed to launch popup");
2253
2254                 return 0;
2255         } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2256                 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2257                 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2258                 if (ret < 0) {
2259                         ret = -EPERM;
2260                         free_block_device(bdev);
2261                         return ret;
2262                 }
2263         }
2264
2265         ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2266         if (ret < 0) {
2267                 _E("Failed to add operation (insert %s)", devnode);
2268                 free_block_device(bdev);
2269                 return ret;
2270         }
2271
2272         // Not a regular filesystem -> skip mounting
2273         if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM)) {
2274                 _I("Not a filesystem. Not mounting");
2275                 return 0;
2276         }
2277
2278         /* Create file for block device /run/external-storage/id */
2279         create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2280         ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2281         if (ret < 0) {
2282                 _E("Failed to add operation (mount %s)", devnode);
2283                 return ret;
2284         }
2285         return 0;
2286 }
2287
2288 static int remove_block_device(struct udev_device *dev, const char *devnode)
2289 {
2290         struct block_device *bdev;
2291         struct block_device *bdev_extended;
2292         int ret;
2293
2294         bdev = find_block_device(devnode);
2295         if (!bdev) {
2296                 _E("fail to find block data for %s", devnode);
2297                 return -ENODEV;
2298         }
2299
2300         BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2301
2302         bdev->removed = true;
2303         if (bdev->on_private_op != REQ_NORMAL) {
2304                 bdev->on_private_op = REQ_NORMAL;
2305                 _D("Private operation state: %d", bdev->on_private_op);
2306         }
2307
2308         if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2309                 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2310
2311                 if (bdev_extended) {
2312                         BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2313
2314                         bdev_extended->removed = true;
2315                         if (bdev_extended->on_private_op != REQ_NORMAL) {
2316                                 bdev_extended->on_private_op = REQ_NORMAL;
2317                                 _D("Private operation state: %d", bdev_extended->on_private_op);
2318                         }
2319
2320                         ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2321                         if (ret < 0) {
2322                                 _E("Failed to add operation (unmount %s)", devnode);
2323                                 return ret;
2324                         }
2325
2326                         ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2327                         if (ret < 0) {
2328                                 _E("Failed to add operation (remove %s)", devnode);
2329                                 return ret;
2330                         }
2331
2332                         ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2333                         if (ret < 0) {
2334                                 _E("Failed to add operation (luks_close %s)", devnode);
2335                                 return ret;
2336                         }
2337                 } else
2338                         _E("fail to find block data for extended sd card");
2339         }
2340
2341         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2342         if (ret < 0) {
2343                 _E("Failed to add operation (unmount %s)", devnode);
2344                 return ret;
2345         }
2346
2347         ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2348         if (ret < 0) {
2349                 _E("Failed to add operation (remove %s)", devnode);
2350                 return ret;
2351         }
2352
2353         return 0;
2354 }
2355
2356 static int get_internal_storage_number(void)
2357 {
2358         struct libmnt_table *t = NULL;
2359         struct libmnt_fs *fs;
2360         const char *temp;
2361         char *name;
2362         int r = 0, dev_temp;
2363
2364         if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2365                 (is_emulator() && dev_internal_emul != '\0'))
2366                 return 0;
2367
2368         t = mnt_new_table();
2369         if (!t)
2370                 return -EPERM;
2371
2372         r = mnt_table_parse_mtab(t, NULL);
2373         if (r < 0) {
2374                 mnt_free_table(t);
2375                 return -EPERM;
2376         }
2377
2378         fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2379
2380         if (!fs) {
2381                 mnt_free_table(t);
2382                 return -EPERM;
2383         }
2384         temp = mnt_fs_get_srcpath(fs);
2385         if (!temp)
2386                 return -EPERM;
2387
2388         name = strrchr(temp, '/');
2389         if (!name)
2390                 return -EPERM;
2391         name++;
2392         /* Boot from USB is not handled */
2393         if (!is_emulator()) {
2394                 if (!fnmatch(MMC_PATH, temp, 0))
2395                         sscanf(name, "mmcblk%d", &dev_internal);
2396                 else if (!fnmatch(SCSI_PATH, temp, 0))
2397                         sscanf(name, "sd%c", &dev_internal_scsi);
2398         } else {
2399                 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2400                         sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2401                 else
2402                         dev_internal_emul = '\0';
2403         }
2404
2405         mnt_free_table(t);
2406
2407         return 0;
2408 }
2409
2410 static int check_external_storage(const char* devnode)
2411 {
2412         char dev_scsi = '\0';
2413         char *name;
2414         char emul = '\0';
2415         int dev_num = -1, dev_temp;
2416
2417         if (!devnode)
2418                 return -EPERM;
2419
2420         name = strrchr(devnode, '/');
2421         if (!name)
2422                 return -EPERM;
2423         name++;
2424         if (!is_emulator()) {
2425                 if (!fnmatch(MMC_PATH, devnode, 0)) {
2426                         sscanf(name, "mmcblk%d", &dev_num);
2427                         if (dev_internal == dev_num) {
2428                                 _D("%s is internal storage", devnode);
2429                                 return 0;
2430                         }
2431                 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2432                         sscanf(name, "sd%c", &dev_scsi);
2433                         if (dev_internal_scsi == dev_scsi) {
2434                                 _D("%s is internal storage", devnode);
2435                                 return 0;
2436                         }
2437                 }
2438         } else {
2439                 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2440                         sscanf(name, "vd%c%d", &emul, &dev_temp);
2441                         if (dev_internal_emul == emul) {
2442                                 _D("%s is internal storage", devnode);
2443                                 return 0;
2444                         }
2445                 }
2446         }
2447
2448         return 1;
2449 }
2450
2451 static int check_already_handled(const char* devnode)
2452 {
2453         struct block_device *bdev;
2454         struct block_data *data;
2455         dd_list *elem;
2456         int i;
2457
2458         for (i = 0; i < THREAD_MAX; i++) {
2459                 pthread_mutex_lock(&(th_manager[i].mutex));
2460                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2461                         data = bdev->data;
2462                         if (!data)
2463                                 continue;
2464                         if (bdev->removed)
2465                                 continue;
2466                         if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2467                                 pthread_mutex_unlock(&(th_manager[i].mutex));
2468                                 return -1;
2469                         }
2470                 }
2471                 pthread_mutex_unlock(&(th_manager[i].mutex));
2472         }
2473
2474         return 0;
2475 }
2476
2477 static int block_init_from_udev_enumerate(void)
2478 {
2479         struct udev *udev;
2480         struct udev_enumerate *enumerate;
2481         struct udev_list_entry *list_entry, *list_sub_entry;
2482         struct udev_device *dev;
2483         const char *syspath;
2484         const char *devnode;
2485         int r = 0;
2486
2487         udev = udev_new();
2488         if (!udev) {
2489                 _E("fail to create udev library context");
2490                 return -EPERM;
2491         }
2492
2493         /* create a list of the devices in the 'usb' subsystem */
2494         enumerate = udev_enumerate_new(udev);
2495         if (!enumerate) {
2496                 _E("fail to create an enumeration context");
2497                 return -EPERM;
2498         }
2499
2500         if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2501                 (is_emulator() && dev_internal_emul == '\0')) {
2502                 r = get_internal_storage_number();
2503                 if (r < 0)
2504                         return -EPERM;
2505         }
2506
2507         udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2508         udev_enumerate_add_match_property(enumerate,
2509                         UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2510         udev_enumerate_add_match_property(enumerate,
2511                         UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2512         udev_enumerate_scan_devices(enumerate);
2513
2514         udev_list_entry_foreach(list_entry,
2515                         udev_enumerate_get_list_entry(enumerate)) {
2516                 syspath = udev_list_entry_get_name(list_entry);
2517                 if (!syspath)
2518                         continue;
2519
2520                 dev = udev_device_new_from_syspath(
2521                                 udev_enumerate_get_udev(enumerate),
2522                                 syspath);
2523                 if (!dev)
2524                         continue;
2525
2526                 devnode = NULL;
2527                 udev_list_entry_foreach(list_sub_entry,
2528                                 udev_device_get_devlinks_list_entry(dev)) {
2529                         const char *devlink = udev_list_entry_get_name(list_sub_entry);
2530                         if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2531                                 devnode = devlink;
2532                                 break;
2533                         }
2534                 }
2535
2536                 if (!devnode) {
2537                         devnode = udev_device_get_devnode(dev);
2538                         if (!devnode)
2539                                 continue;
2540
2541                         if (fnmatch(MMC_PATH, devnode, 0) &&
2542                             fnmatch(SCSI_PATH, devnode, 0) &&
2543                             fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
2544                                 continue;
2545                 }
2546
2547                 r = check_external_storage(devnode);
2548                 if (r <= 0)
2549                         continue;
2550
2551                 r = check_already_handled(devnode);
2552                 if (r < 0) {
2553                         _I("%s is already handled", devnode);
2554                         continue;
2555                 }
2556
2557                 _I("%s device add", devnode);
2558                 add_block_device(dev, devnode, false);
2559
2560                 udev_device_unref(dev);
2561         }
2562
2563         udev_enumerate_unref(enumerate);
2564         udev_unref(udev);
2565         return 0;
2566 }
2567
2568 // Called by MainThread
2569 static void show_block_device_list(void)
2570 {
2571         struct block_device *bdev;
2572         struct block_data *data;
2573         dd_list *elem;
2574         int i;
2575
2576         for (i = 0; i < THREAD_MAX; i++) {
2577                 pthread_mutex_lock(&(th_manager[i].mutex));
2578                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2579                         data = bdev->data;
2580                         if (!data)
2581                                 continue;
2582                         if (bdev->removed)
2583                                 continue;
2584                         _D("%s:", data->devnode);
2585                         _D("\tSyspath: %s", data->syspath);
2586                         _D("\tBlock type: %d", data->block_type);
2587                         _D("\tFs type: %s", data->fs_type);
2588                         _D("\tFs usage: %s", data->fs_usage);
2589                         _D("\tFs version: %s", data->fs_version);
2590                         _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2591                         _D("\tReadonly: %s",
2592                                         (data->readonly ? "true" : "false"));
2593                         _D("\tMount point: %s", data->mount_point);
2594                         _D("\tMount state: %s",
2595                                         (data->state == BLOCK_MOUNT ?
2596                                          "mount" : "unmount"));
2597                         _D("\tPrimary: %s",
2598                                         (data->primary ? "true" : "false"));
2599                         _D("\tID: %d", data->id);
2600                 }
2601                 pthread_mutex_unlock(&(th_manager[i].mutex));
2602         }
2603 }
2604
2605 // Called by MainThread
2606 static void remove_whole_block_device(void)
2607 {
2608         struct block_device *bdev;
2609         dd_list *elem;
2610         dd_list *next;
2611         int r;
2612         int i;
2613
2614         for (i = 0; i < THREAD_MAX; i++) {
2615                 do {
2616                         pthread_mutex_lock(&(th_manager[i].mutex));
2617                         DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2618                                 if (bdev->removed == false)
2619                                         break;
2620                         }
2621                         pthread_mutex_unlock(&(th_manager[i].mutex));
2622
2623                         if (bdev && bdev->removed == false) {
2624                                 bdev->removed = true;
2625                                 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2626                                 if (r < 0)
2627                                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2628
2629                                 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2630                                 if (r < 0)
2631                                         _E("Failed to add operation (remove %s)", bdev->data->devnode);
2632                         } else
2633                                 break;
2634                 } while (true);
2635         }
2636 }
2637
2638 static void booting_done(const char *sender_name,
2639                 const char *object_path, const char *interface_name,
2640                 const char *signal_name, DBusMessage *msg,
2641                 void *data)
2642 {
2643         static int done = 0;
2644         if (done > 0)
2645                 return;
2646         done = 1;
2647         _I("Booting done");
2648         /* if there is the attached device, try to mount */
2649         block_init_from_udev_enumerate();
2650         block_control = true;
2651         block_boot = true;
2652 }
2653
2654 static void block_poweroff(const char *sender_name,
2655                 const char *object_path, const char *interface_name,
2656                 const char *signal_name, DBusMessage *msg,
2657                 void *data)
2658 {
2659         static int status = 0;
2660         if (status > 0)
2661                 return;
2662         status = 1;
2663         _I("Power off");
2664         /* unregister mmc uevent control routine */
2665         unregister_udev_uevent_control(&uh);
2666         remove_whole_block_device();
2667 }
2668
2669 static void uevent_block_handler(struct udev_device *dev)
2670 {
2671         const char *devnode = NULL;
2672         const char *action;
2673         struct udev_list_entry *list_entry;
2674         int r;
2675         bool mapper = false;
2676
2677         udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2678                 const char *devlink = udev_list_entry_get_name(list_entry);
2679                 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2680                         devnode = devlink;
2681                         break;
2682                 }
2683                 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2684                         mapper = true;
2685                         devnode = devlink;
2686                         break;
2687                 }
2688         }
2689
2690         if (!devnode) {
2691                 devnode = udev_device_get_devnode(dev);
2692                 if (!devnode)
2693                         return;
2694
2695                 if (fnmatch(MMC_PATH, devnode, 0) &&
2696                     fnmatch(SCSI_PATH, devnode, 0))
2697                         return;
2698         }
2699
2700         r = check_external_storage(devnode);
2701         if (r <= 0)
2702                 return;
2703
2704         action = udev_device_get_action(dev);
2705         if (!action)
2706                 return;
2707
2708         _I("%s device %s", devnode, action);
2709         if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2710            (mapper && !strcmp(action, UDEV_CHANGE))) {
2711                 r = check_already_handled(devnode);
2712                 if (r < 0) {
2713                         _I("%s is already handled", devnode);
2714                         return;
2715                 }
2716
2717                 add_block_device(dev, devnode, mapper);
2718         } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2719                 remove_block_device(dev, devnode);
2720         } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2721                 struct block_device *bdev;
2722                 bdev = find_block_device(devnode);
2723                 if (!bdev) {
2724                         _E("fail to find block data for %s", devnode);
2725                         return;
2726                 }
2727                 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2728                         return;
2729
2730                 r = update_block_data(bdev->data,
2731                                 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2732                                 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2733                                 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2734                                 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2735                                 udev_device_get_sysattr_value(dev, "ro"),
2736                                 false);
2737                 if (r < 0)
2738                         _E("fail to update block data for %s", bdev->data->devnode);
2739         }
2740 }
2741
2742 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2743                 DBusMessage *msg, bool onprivate)
2744 {
2745         struct block_device *bdev;
2746         char *mount_point;
2747         int id;
2748         int ret = -EBADMSG;
2749
2750         if (!reply_handle || !msg)
2751                 goto out;
2752
2753         ret = dbus_message_get_args(msg, NULL,
2754                         DBUS_TYPE_INT32, &id,
2755                         DBUS_TYPE_STRING, &mount_point,
2756                         DBUS_TYPE_INVALID);
2757         if (!ret)
2758                 goto out;
2759
2760         bdev = find_block_device_by_id(id);
2761         if (!bdev) {
2762                 _E("Failed to find (%d) in the device list", id);
2763                 ret = -ENOENT;
2764                 goto out;
2765         }
2766         if (bdev->on_private_op != REQ_NORMAL) {
2767                 ret = -EPERM;
2768                 goto out;
2769         }
2770
2771         if (bdev->data->state == BLOCK_MOUNT) {
2772                 _I("%s is already mounted", bdev->data->devnode);
2773                 ret = -EALREADY;
2774                 goto out;
2775         }
2776
2777         if (onprivate) {
2778                 bdev->on_private_op = REQ_PRIVATE;
2779                 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2780                 _D("Private operation state: %d", bdev->on_private_op);
2781         } else {
2782                 if (bdev->on_private_op != REQ_NORMAL) {
2783                         _E("Failed to process mount operation");
2784                         ret = -EPERM;
2785                         goto out;
2786                 }
2787         }
2788
2789         /* if requester want to use a specific mount point */
2790         if (mount_point &&
2791                 !strncmp(mount_point, EXTENDEDSD_STRING, strlen(EXTENDEDSD_STRING) + 1) != 0) {
2792                 if (!block_conf[bdev->data->block_type].extendedinternal ||
2793                         !bdev->data->primary) {
2794                         _E("Not support extended internal storage");
2795                         ret = -EPERM;
2796                         goto out;
2797                 } else {
2798                         bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2799                         ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2800                         if (ret < 0) {
2801                                 ret = -EPERM;
2802                                 goto out;
2803                         }
2804
2805                         create_file(bdev->data->id, bdev->data->mount_point, true);
2806                 }
2807         } else if (mount_point && strncmp(mount_point, "", 1) != 0) {
2808                 ret = change_mount_point(bdev, mount_point);
2809                 if (ret < 0) {
2810                         ret = -EPERM;
2811                         goto out;
2812                 }
2813
2814                 /* Create /run/external-storage/id file */
2815                 create_file(bdev->data->id, bdev->data->mount_point, false);
2816         } else {
2817                 /* Create file for block device /run/external-storage/id */
2818                 create_file(bdev->data->id, bdev->data->mount_point, false);
2819         }
2820
2821         ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2822         if (ret < 0) {
2823                 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2824                 goto out;
2825         }
2826
2827         return NULL;
2828
2829 out:
2830         return make_dbus_reply_message_simple(reply_handle, ret);
2831 }
2832
2833 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2834                 DBusMessage *msg)
2835 {
2836         return request_mount_block(reply_handle, msg, false);
2837 }
2838
2839 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2840                 DBusMessage *msg)
2841 {
2842         return request_mount_block(reply_handle, msg, true);
2843 }
2844
2845 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2846                 DBusMessage *msg, bool onprivate)
2847 {
2848         struct block_device *bdev;
2849         pid_t pid;
2850         long option;
2851         int id;
2852         int ret = -EBADMSG;
2853
2854         if (!reply_handle || !msg)
2855                 goto out;
2856
2857         ret = dbus_message_get_args(msg, NULL,
2858                         DBUS_TYPE_INT32, &id,
2859                         DBUS_TYPE_INT32, &option,
2860                         DBUS_TYPE_INVALID);
2861         if (!ret)
2862                 goto out;
2863
2864         bdev = find_block_device_by_id(id);
2865         if (!bdev) {
2866                 _E("Failed to find (%d) in the device list", id);
2867                 ret = -ENOENT;
2868                 goto out;
2869         }
2870
2871         if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2872                 _I("Impossible to request unmount extended internal sdcard");
2873                 ret = -EPERM;
2874                 goto out;
2875         }
2876
2877         if (onprivate) {
2878                 pid = get_dbus_method_sender_pid(reply_handle);
2879                 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2880                         _E("Failed to process private unmount operation");
2881                         ret = -EPERM;
2882                         goto out;
2883                 }
2884         } else {
2885                 if (bdev->on_private_op != REQ_NORMAL) {
2886                         _E("Failed to process unmount operation");
2887                         ret = -EPERM;
2888                         goto out;
2889                 }
2890         }
2891
2892         ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2893         if (ret < 0) {
2894                 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2895                 goto out;
2896         }
2897
2898         return NULL;
2899
2900 out:
2901         return make_dbus_reply_message_simple(reply_handle, ret);
2902 }
2903
2904 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2905                 DBusMessage *msg)
2906 {
2907         return request_unmount_block(reply_handle, msg, false);
2908 }
2909
2910 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2911                 DBusMessage *msg)
2912 {
2913         return request_unmount_block(reply_handle, msg, true);
2914 }
2915
2916 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2917                 DBusMessage *msg)
2918 {
2919         struct block_device *bdev;
2920         struct format_data *fdata;
2921         pid_t pid;
2922         int id;
2923         int option;
2924         int ret = -EBADMSG;
2925         int prev_state;
2926
2927         if (!reply_handle || !msg)
2928                 goto out;
2929
2930         ret = dbus_message_get_args(msg, NULL,
2931                         DBUS_TYPE_INT32, &id,
2932                         DBUS_TYPE_INT32, &option,
2933                         DBUS_TYPE_INVALID);
2934         if (!ret)
2935                 goto out;
2936
2937         bdev = find_block_device_by_id(id);
2938         if (!bdev) {
2939                 _E("Failed to find (%d) in the device list", id);
2940                 goto out;
2941         }
2942
2943         pid = get_dbus_method_sender_pid(reply_handle);
2944         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2945                 _E("Failed to format on private state");
2946                 ret = -EPERM;
2947                 goto out;
2948         }
2949
2950         fdata = get_format_data(NULL, option);
2951         if (!fdata) {
2952                 _E("Failed to get format data");
2953                 goto out;
2954         }
2955
2956         prev_state = bdev->data->state;
2957         if (prev_state == BLOCK_MOUNT) {
2958                 if (bdev->on_private_op == REQ_PRIVATE) {
2959                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
2960                         _D("Private operation state: %d", bdev->on_private_op);
2961                 }
2962                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2963                 if (ret < 0) {
2964                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2965                         release_format_data(fdata);
2966                         goto out;
2967                 }
2968         }
2969
2970         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2971         if (ret < 0) {
2972                 _E("Failed to add operation (format %s)", bdev->data->devnode);
2973                 release_format_data(fdata);
2974         }
2975
2976         /* Maintain previous state of mount/unmount */
2977         if (prev_state == BLOCK_MOUNT) {
2978                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2979                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
2980                         goto out;
2981                 }
2982         }
2983
2984         return NULL;
2985
2986 out:
2987         return make_dbus_reply_message_simple(reply_handle, ret);
2988 }
2989
2990 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2991                 DBusMessage *msg)
2992 {
2993         struct block_device *bdev;
2994         struct format_data *fdata;
2995         char *type;
2996         pid_t pid;
2997         int id;
2998         int option;
2999         int ret = -EBADMSG;
3000         int prev_state;
3001
3002         if (!reply_handle || !msg)
3003                 goto out;
3004
3005         ret = dbus_message_get_args(msg, NULL,
3006                         DBUS_TYPE_INT32, &id,
3007                         DBUS_TYPE_INT32, &option,
3008                         DBUS_TYPE_STRING, &type,
3009                         DBUS_TYPE_INVALID);
3010         if (!ret)
3011                 goto out;
3012
3013         bdev = find_block_device_by_id(id);
3014         if (!bdev) {
3015                 _E("Failed to find (%d) in the device list", id);
3016                 goto out;
3017         }
3018
3019         pid = get_dbus_method_sender_pid(reply_handle);
3020         if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3021                 _E("Failed to format on private state");
3022                 ret = -EPERM;
3023                 goto out;
3024         }
3025
3026         fdata = get_format_data(type, option);
3027         if (!fdata) {
3028                 _E("Failed to get format data");
3029                 goto out;
3030         }
3031
3032         prev_state = bdev->data->state;
3033         if (prev_state == BLOCK_MOUNT) {
3034                 if (bdev->on_private_op == REQ_PRIVATE) {
3035                         bdev->on_private_op = REQ_PRIVATE_FORMAT;
3036                         _D("Private operation state: %d", bdev->on_private_op);
3037                 }
3038                 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3039                 if (ret < 0) {
3040                         _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3041                         release_format_data(fdata);
3042                         goto out;
3043                 }
3044         }
3045
3046         ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3047         if (ret < 0) {
3048                 _E("Failed to add operation (format %s)", bdev->data->devnode);
3049                 release_format_data(fdata);
3050         }
3051
3052         /* Maintain previous state of mount/unmount */
3053         if (prev_state == BLOCK_MOUNT) {
3054                 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3055                         _E("Failed to add operation (mount %s)", bdev->data->devnode);
3056                         goto out;
3057                 }
3058         }
3059
3060         return NULL;
3061
3062 out:
3063         return make_dbus_reply_message_simple(reply_handle, ret);
3064 }
3065
3066 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3067 {
3068         char *str_null = "";
3069
3070         if (!data || !piter)
3071                 return -EINVAL;
3072
3073         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3074                         &(data->block_type));
3075         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3076                         data->devnode ? &(data->devnode) : &str_null);
3077         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3078                         data->syspath ? &(data->syspath) : &str_null);
3079         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3080                         data->fs_usage ? &(data->fs_usage) : &str_null);
3081         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3082                         data->fs_type ? &(data->fs_type) : &str_null);
3083         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3084                         data->fs_version ? &(data->fs_version) : &str_null);
3085         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3086                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3087         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3088                         &(data->readonly));
3089         dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3090                         data->mount_point ? &(data->mount_point) : &str_null);
3091         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3092                         &(data->state));
3093         dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3094                         &(data->primary));
3095         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3096                         &(data->flags));
3097         dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3098                         &(data->id));
3099
3100         return 0;
3101 }
3102
3103
3104 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3105 {
3106         DBusMessageIter piter;
3107
3108         if (!data || !iter)
3109                 return -EINVAL;
3110
3111         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3112         add_device_to_iter(data, &piter);
3113         dbus_message_iter_close_container(iter, &piter);
3114
3115         return 0;
3116 }
3117
3118 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3119 {
3120         DBusMessageIter piter;
3121         char *str_null = "";
3122
3123         if (!data || !iter)
3124                 return -EINVAL;
3125
3126         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3127         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3128                         &(data->block_type));
3129         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3130                         data->devnode ? &(data->devnode) : &str_null);
3131         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3132                         data->syspath ? &(data->syspath) : &str_null);
3133         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3134                         data->fs_usage ? &(data->fs_usage) : &str_null);
3135         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3136                         data->fs_type ? &(data->fs_type) : &str_null);
3137         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3138                         data->fs_version ? &(data->fs_version) : &str_null);
3139         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3140                         data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3141         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3142                         &(data->readonly));
3143         dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3144                         data->mount_point ? &(data->mount_point) : &str_null);
3145         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3146                         &(data->state));
3147         dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3148                         &(data->primary));
3149         dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3150                         &(data->flags));
3151         dbus_message_iter_close_container(iter, &piter);
3152
3153         return 0;
3154 }
3155
3156 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3157                 DBusMessage *msg)
3158 {
3159         DBusMessageIter iter;
3160         DBusMessage *reply;
3161         struct block_device *bdev;
3162         struct block_data *data;
3163         int ret, id;
3164
3165         if (!reply_handle || !msg)
3166                 return NULL;
3167
3168         reply = make_dbus_reply_message(reply_handle);
3169         if (!reply)
3170                 goto out;
3171
3172         ret = dbus_message_get_args(msg, NULL,
3173                         DBUS_TYPE_INT32, &id,
3174                         DBUS_TYPE_INVALID);
3175         if (!ret)
3176                 goto out;
3177
3178         bdev = find_block_device_by_id(id);
3179         if (!bdev)
3180                 goto out;
3181         data = bdev->data;
3182         if (!data)
3183                 goto out;
3184
3185         dbus_message_iter_init_append(reply, &iter);
3186         add_device_to_iter(data, &iter);
3187
3188 out:
3189         return reply;
3190 }
3191
3192 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3193                 DBusMessage *msg)
3194 {
3195         show_block_device_list();
3196         return make_dbus_reply_message(reply_handle);
3197 }
3198
3199 // Called by MainThread
3200 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3201                 DBusMessage *msg)
3202 {
3203         DBusMessageIter iter;
3204         DBusMessageIter aiter;
3205         DBusMessage *reply;
3206         struct block_device *bdev;
3207         struct block_data *data;
3208         dd_list *elem;
3209         char *type = NULL;
3210         int ret = -EBADMSG;
3211         int block_type;
3212         int i;
3213
3214         reply = make_dbus_reply_message(reply_handle);
3215
3216         ret = dbus_message_get_args(msg, NULL,
3217                         DBUS_TYPE_STRING, &type,
3218                         DBUS_TYPE_INVALID);
3219         if (!ret) {
3220                 _E("Failed to get args");
3221                 goto out;
3222         }
3223
3224         if (!type) {
3225                 _E("Delivered type is NULL");
3226                 goto out;
3227         }
3228
3229         _D("Block (%s) device list is requested", type);
3230
3231         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3232                 block_type = BLOCK_SCSI_DEV;
3233         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3234                 block_type = BLOCK_MMC_DEV;
3235         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3236                 block_type = -1;
3237         else {
3238                 _E("Invalid type (%s) is requested", type);
3239                 goto out;
3240         }
3241
3242         dbus_message_iter_init_append(reply, &iter);
3243         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3244
3245         for (i = 0; i < THREAD_MAX; i++) {
3246                 pthread_mutex_lock(&(th_manager[i].mutex));
3247                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3248                         data = bdev->data;
3249                         if (!data)
3250                                 continue;
3251                         if (bdev->removed)
3252                                 continue;
3253
3254                         switch (block_type) {
3255                         case BLOCK_SCSI_DEV:
3256                         case BLOCK_MMC_DEV:
3257                                 if (data->block_type != block_type)
3258                                         continue;
3259                                 break;
3260                         default:
3261                                 break;
3262                         }
3263                         add_device_to_struct_iter(data, &aiter);
3264                 }
3265                 pthread_mutex_unlock(&(th_manager[i].mutex));
3266         }
3267         dbus_message_iter_close_container(&iter, &aiter);
3268
3269 out:
3270         return reply;
3271 }
3272
3273 // Called by MainThread
3274 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3275                 DBusMessage *msg)
3276 {
3277         DBusMessageIter iter;
3278         DBusMessageIter aiter;
3279         DBusMessage *reply;
3280         struct block_device *bdev;
3281         struct block_data *data;
3282         dd_list *elem;
3283         char *type = NULL;
3284         int ret = -EBADMSG;
3285         int block_type;
3286         int i;
3287
3288         reply = make_dbus_reply_message(reply_handle);
3289
3290         ret = dbus_message_get_args(msg, NULL,
3291                         DBUS_TYPE_STRING, &type,
3292                         DBUS_TYPE_INVALID);
3293         if (!ret) {
3294                 _E("Failed to get args");
3295                 goto out;
3296         }
3297
3298         if (!type) {
3299                 _E("Delivered type is NULL");
3300                 goto out;
3301         }
3302
3303         _D("Block (%s) device list is requested", type);
3304
3305         if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3306                 block_type = BLOCK_SCSI_DEV;
3307         else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3308                 block_type = BLOCK_MMC_DEV;
3309         else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3310                 block_type = -1;
3311         else {
3312                 _E("Invalid type (%s) is requested", type);
3313                 goto out;
3314         }
3315
3316         dbus_message_iter_init_append(reply, &iter);
3317         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3318
3319         for (i = 0; i < THREAD_MAX; i++) {
3320                 pthread_mutex_lock(&(th_manager[i].mutex));
3321                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3322                         data = bdev->data;
3323                         if (!data)
3324                                 continue;
3325                         if (bdev->removed)
3326                                 continue;
3327
3328                         switch (block_type) {
3329                         case BLOCK_SCSI_DEV:
3330                         case BLOCK_MMC_DEV:
3331                                 if (data->block_type != block_type)
3332                                         continue;
3333                                 break;
3334                         default:
3335                                 break;
3336                         }
3337
3338                         add_device_to_iter_2(data, &aiter);
3339                 }
3340                 pthread_mutex_unlock(&(th_manager[i].mutex));
3341         }
3342         dbus_message_iter_close_container(&iter, &aiter);
3343
3344 out:
3345         return reply;
3346 }
3347
3348 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3349                 DBusMessage *msg)
3350 {
3351         DBusMessageIter iter;
3352         DBusMessage *reply;
3353         struct block_device *bdev;
3354         struct block_data *data, nodata = {0,};
3355         dd_list *elem;
3356         bool found;
3357         int i;
3358
3359         if (!reply_handle || !msg)
3360                 return NULL;
3361
3362         reply = make_dbus_reply_message(reply_handle);
3363         if (!reply)
3364                 goto out;
3365
3366         found = false;
3367         for (i = 0; i < THREAD_MAX; i++) {
3368                 pthread_mutex_lock(&(th_manager[i].mutex));
3369                 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3370                         data = bdev->data;
3371                         if (!data)
3372                                 continue;
3373                         if (bdev->removed)
3374                                 continue;
3375                         if (data->block_type != BLOCK_MMC_DEV &&
3376                             data->block_type != BLOCK_EXTENDEDSD_DEV)
3377                                 continue;
3378                         if (!data->primary)
3379                                 continue;
3380                         found = true;
3381                         break;
3382                 }
3383                 pthread_mutex_unlock(&(th_manager[i].mutex));
3384                 if (found)
3385                         break;
3386         }
3387
3388         dbus_message_iter_init_append(reply, &iter);
3389         if (found)
3390                 add_device_to_iter(data, &iter);
3391         else {
3392                 nodata.id = -ENODEV;
3393                 add_device_to_iter(&nodata, &iter);
3394         }
3395
3396 out:
3397         return reply;
3398 }
3399
3400 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3401                 DBusMessage *msg)
3402 {
3403         struct timespec start_time, end_time;
3404         DBusMessageIter iter;
3405         DBusMessage *reply;
3406         struct block_device *bdev;
3407         struct block_data *data;
3408         char *buf;
3409         int ret = 0;
3410         int id;
3411         int fd;
3412
3413         if (!reply_handle || !msg)
3414                 return NULL;
3415
3416         ret = dbus_message_get_args(msg, NULL,
3417                         DBUS_TYPE_INT32, &id,
3418                         DBUS_TYPE_INVALID);
3419         if (!ret) {
3420                 ret = -1;
3421                 goto out;
3422         }
3423
3424         bdev = find_block_device_by_id(id);
3425         if (!bdev) {
3426                 ret = -1;
3427                 goto out;
3428         }
3429         data = bdev->data;
3430         if (!data) {
3431                 ret = -1;
3432                 goto out;
3433         }
3434
3435         _D("speed check: %s", data->devnode);
3436         fd = open(data->devnode, O_RDWR | O_SYNC);
3437         buf = calloc(1, SPEEDCHECK * 1024 * 1024);
3438         if (!buf) {
3439                 _E("calloc() failed");
3440                 close(fd);
3441                 ret = -1;
3442                 goto out;
3443         }
3444         clock_gettime(CLOCK_REALTIME, &start_time);
3445         _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3446         ret = write(fd, buf, SPEEDCHECK * 1024 * 1024);
3447         clock_gettime(CLOCK_REALTIME, &end_time);
3448         _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3449
3450         free(buf);
3451
3452         if (SPEEDCHECK / (end_time.tv_sec - start_time.tv_sec) < 4) {
3453                 ret = -1;
3454                 close(fd);
3455                 goto out;
3456         }
3457
3458         if (ret < 0) {
3459                 _E("write() failed %d", errno);
3460                 close(fd);
3461                 goto out;
3462         }
3463
3464         close(fd);
3465 out:
3466         reply = dbus_message_new_method_return(msg);
3467         dbus_message_iter_init_append(reply, &iter);
3468         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3469         return reply;
3470 }
3471
3472 /*
3473   Method name      Method call format string  Reply format string
3474 { "ShowDeviceList",                      NULL,               NULL, request_show_device_list },
3475 { "GetDeviceList",                        "s", "a(issssssisibii)", request_get_device_list },
3476 { "GetDeviceList2",                       "s",  "a(issssssisibi)", request_get_device_list_2 },
3477 { "Mount",                               "is",                "i", request_public_mount_block },
3478 { "Unmoun,                               "ii",                "i", request_public_unmount_block },
3479 { "Format",                              "ii",                "i", request_format_block },
3480 { "GetDeviceInfo",                        "i",  "(issssssisibii)", request_get_device_info },
3481 { "GetMmcPrimary",                       NULL, "(issssssisibii)" , request_get_mmc_primary },
3482 { "PrivateMount",                        "is",                "i", request_private_mount_block },
3483 { "PrivateUnmount",                      "ii",                "i", request_private_unmount_block },
3484 */
3485
3486 static const dbus_method_s manager_methods[] = {
3487         { "ShowDeviceList",         NULL, request_show_device_list },
3488         { "GetDeviceList" ,         "s", request_get_device_list },
3489         { "GetDeviceList2",         "s", request_get_device_list_2 },
3490         { "Mount",                  "is", request_public_mount_block },
3491         { "Unmount",                "ii", request_public_unmount_block },
3492         { "Format",                 "ii", request_format_block },
3493         { "FormatwithType",        "iis", request_format_block_type },
3494         { "GetDeviceInfo",          "i", request_get_device_info },
3495         { "GetMmcPrimary" ,         NULL, request_get_mmc_primary },
3496         { "PrivateMount",           "is", request_private_mount_block },
3497         { "PrivateUnmount",         "ii", request_private_unmount_block },
3498         { "CheckSpeed",              "i", request_check_speed },
3499 };
3500
3501 static dbus_interface_s block_interface = {
3502         .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3503         .methods = manager_methods,
3504         .nr_methods = ARRAY_SIZE(manager_methods),
3505 };
3506
3507 static int load_config(struct parse_result *result, void *user_data)
3508 {
3509         int index;
3510
3511         if (MATCH(result->section, "Block"))
3512                 return 0;
3513
3514         if (MATCH(result->section, "SCSI"))
3515                 index = BLOCK_SCSI_DEV;
3516         else if (MATCH(result->section, "MMC"))
3517                 index = BLOCK_MMC_DEV;
3518         else if (MATCH(result->section, "Mapper"))
3519                 index = BLOCK_EXTENDEDSD_DEV;
3520         else
3521                 return -EINVAL;
3522
3523         if (MATCH(result->name, "Multimount"))
3524                 block_conf[index].multimount =
3525                         (MATCH(result->value, "yes") ? true : false);
3526         if (MATCH(result->name, "ExtendedInternalStorage"))
3527                 block_conf[index].extendedinternal =
3528                         (MATCH(result->value, "yes") ? true : false);
3529
3530         return 0;
3531 }
3532
3533 #ifdef BLOCK_TMPFS
3534 static int mount_root_path_tmpfs(void)
3535 {
3536         int ret;
3537         const char *root;
3538
3539         root = tzplatform_getenv(TZ_SYS_MEDIA);
3540         if (!root)
3541                 return -ENOTSUP;
3542
3543         if (access(root, F_OK) != 0)
3544                 return -ENODEV;
3545
3546         if (mount_check(root))
3547                 return 0;
3548
3549         ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3550         if (ret < 0) {
3551                 ret = -errno;
3552                 _E("tmpfs mount failed (%d)", ret);
3553                 return ret;
3554         }
3555
3556         return 0;
3557 }
3558 #else
3559 #define mount_root_path_tmpfs() 0
3560 #endif
3561
3562 static void block_init(void *data)
3563 {
3564         struct stat buf;
3565         int ret;
3566         int i;
3567         dbus_handle_h handle;
3568
3569         udev_init(NULL);
3570
3571         /* load config */
3572         ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3573         if (ret < 0)
3574                 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3575
3576         ret = mount_root_path_tmpfs();
3577         if (ret < 0)
3578                 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3579
3580         ret = dbus_get_connection(&handle);
3581         if (ret < 0)
3582                 _E("Failed to get dbus connection(%d)", ret);
3583
3584         /* register block manager object and interface */
3585         ret = register_dbus_methods(handle,
3586                         STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3587                         NULL, NULL);
3588         if (ret < 0)
3589                 _E("Failed to register block interface and methods (%d)", ret);
3590
3591         /* init pipe */
3592         ret = pipe_init();
3593         if (ret < 0)
3594                 _E("fail to init pipe");
3595
3596         /* register mmc uevent control routine */
3597         ret = register_udev_uevent_control(&uh);
3598         if (ret < 0)
3599                 _E("fail to register block uevent : %d", ret);
3600
3601         /* System Session is loaded completely */
3602         register_dbus_signal(SYSTEMD_DBUS_PATH,
3603                     SYSTEMD_DBUS_IFACE_MANAGER,
3604                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3605                     booting_done, NULL, NULL);
3606
3607         register_dbus_signal(DEVICED_PATH_POWEROFF,
3608                         DEVICED_INTERFACE_POWEROFF,
3609                         SIGNAL_POWEROFF_STATE,
3610                         block_poweroff, NULL, NULL);
3611
3612         for (i = 0; i < THREAD_MAX; i++) {
3613                 th_manager[i].num_dev = 0;
3614                 th_manager[i].op_len = 0;
3615                 th_manager[i].start_th = true;
3616                 th_manager[i].thread_id = i;
3617                 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3618                 pthread_cond_init(&(th_manager[i].cond), NULL);
3619         }
3620
3621         ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3622         if (ret < 0) {
3623                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3624                 if (ret < 0)
3625                         _E("Failed to make directory: %d", errno);
3626         } else if (!S_ISDIR(buf.st_mode)) {
3627                 ret = remove(EXTERNAL_STORAGE_PATH);
3628                 if (ret < 0)
3629                         _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3630                 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3631                 if (ret < 0)
3632                         _E("Failed to make directory: %d", errno);
3633         } else {
3634                 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3635                 if (ret < 0)
3636                         _E("Fail to change permissions of a file");
3637         }
3638
3639         ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3640         if (ret < 0) {
3641                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3642                 if (ret < 0)
3643                         _E("Failed to make directory: %d", errno);
3644         } else if (!S_ISDIR(buf.st_mode)) {
3645                 ret = remove(EXTENDED_INTERNAL_PATH);
3646                 if (ret < 0)
3647                         _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3648                 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3649                 if (ret < 0)
3650                         _E("Failed to make directory: %d", errno);
3651         } else {
3652                 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3653                 if (ret < 0)
3654                         _E("Fail to change permissions of a file");
3655         }
3656 }
3657
3658 static void block_exit(void *data)
3659 {
3660         dd_list *elem, *elem_next;
3661         char *temp;
3662         int ret, i;
3663
3664         udev_exit(NULL);
3665
3666         /* unregister notifier for below each event */
3667         unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3668                     SYSTEMD_DBUS_IFACE_MANAGER,
3669                     SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3670                     booting_done);
3671
3672         unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3673                         DEVICED_INTERFACE_POWEROFF,
3674                         SIGNAL_POWEROFF_STATE, block_poweroff);
3675
3676         /* exit pipe */
3677         pipe_exit();
3678
3679         /* unregister mmc uevent control routine */
3680         ret = unregister_udev_uevent_control(&uh);
3681         if (ret < 0)
3682                 _E("fail to unregister block uevent : %d", ret);
3683
3684         /* remove remaining blocks */
3685         remove_whole_block_device();
3686
3687         for (i = 0; i < THREAD_MAX; i++) {
3688                 if (!th_manager[i].start_th)
3689                         pthread_cancel(th_manager[i].th);
3690                 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3691                         DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3692                         free(temp);
3693                 }
3694         }
3695
3696         block_control = false;
3697 }
3698
3699 static int block_start(void *data)
3700 {
3701         int ret;
3702
3703         if (!block_boot) {
3704                 _E("Cannot be started. Booting is not ready");
3705                 return -ENODEV;
3706         }
3707
3708         if (block_control) {
3709                 _I("Already started");
3710                 return 0;
3711         }
3712
3713         /* register mmc uevent control routine */
3714         ret = register_udev_uevent_control(&uh);
3715         if (ret < 0)
3716                 _E("fail to register block uevent : %d", ret);
3717
3718         block_init_from_udev_enumerate();
3719
3720         block_control = true;
3721
3722         _I("start");
3723         return 0;
3724 }
3725
3726 static int block_stop(void *data)
3727 {
3728         if (!block_boot) {
3729                 _E("Cannot be stopped. Booting is not ready");
3730                 return -ENODEV;
3731         }
3732
3733         if (!block_control) {
3734                 _I("Already stopped");
3735                 return 0;
3736         }
3737
3738         /* unregister mmc uevent control routine */
3739         unregister_udev_uevent_control(&uh);
3740
3741         /* remove the existing blocks */
3742         remove_whole_block_device();
3743
3744         block_control = false;
3745
3746         _I("stop");
3747         return 0;
3748 }
3749
3750 static storaged_module_interface block_module = {
3751         .name     = "block",
3752         .init     = block_init,
3753         .exit     = block_exit,
3754         .start    = block_start,
3755         .stop     = block_stop,
3756 };
3757
3758 __attribute__ ((visibility("default")))storaged_module_interface *
3759 storaged_get_module_interface(void)
3760 {
3761         return &block_module;
3762 }