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