4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/mount.h>
28 #include <sys/statvfs.h>
32 #include <sys/statfs.h>
39 #include <tzplatform_config.h>
40 #include <app2ext_interface.h>
42 #include <blkid/blkid.h>
46 #include "config-parser.h"
47 #include "module-intf.h"
52 #include "fd_handler.h"
57 * TODO Assume root device is always mmcblk0*.
59 #define MMC_PATH "*/mmcblk[0-9]*"
60 #define MMC_PARTITION_PATH "mmcblk[0-9]p[0-9]"
61 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
62 #define MMC_LINK_PATH "*/sdcard/*"
63 #define SCSI_PATH "*/sd[a-z]*"
64 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
65 #define SCSI_PARTITION_LENGTH 9
66 #define EXTENDEDSD_NODE_PATH "/dev/mapper/extendedsd"
68 #define FILESYSTEM_NAME "filesystem"
70 #define DEV_PREFIX "/dev/"
73 #define UNMOUNT_RETRY 5
74 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
76 #define SIGNAL_POWEROFF_STATE "ChangeState"
78 #define BLOCK_DEVICE_ADDED "DeviceAdded"
79 #define BLOCK_DEVICE_REMOVED "DeviceRemoved"
80 #define BLOCK_DEVICE_BLOCKED "DeviceBlocked"
81 #define BLOCK_DEVICE_CHANGED "DeviceChanged"
82 #define BLOCK_DEVICE_CHANGED_2 "DeviceChanged2"
84 #define BLOCK_TYPE_MMC "mmc"
85 #define BLOCK_TYPE_SCSI "scsi"
86 #define BLOCK_TYPE_ALL "all"
88 #define BLOCK_MMC_NODE_PREFIX "SDCard"
89 #define BLOCK_SCSI_NODE_PREFIX "USBDrive"
91 #define BLOCK_CONF_FILE "/etc/storaged/block.conf"
93 #define EXTERNAL_STORAGE_PATH "/run/external-storage"
94 #define EXTENDED_INTERNAL_PATH "/run/extended-internal-sd"
97 #define EXTENDEDSD_MOUNT_PATH "/opt/extendedsd"
99 #define EXT4_NAME "ext4"
100 #define LUKS_NAME "crypto_LUKS"
101 #define EXTENDEDSD_NAME "extendedsd"
103 /* Minimum value of block id */
104 #define BLOCK_ID_MIN 10
105 /* For 2.4 Backward Compatibility */
106 #define EXT_PRIMARY_SD_FIXID 1
108 /* Maximum number of thread */
111 #define SPEEDCHECK 16
113 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
114 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
115 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
117 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
119 enum block_dev_operation {
128 enum private_operation_state {
134 struct operation_queue {
135 enum block_dev_operation op;
136 dbus_method_reply_handle_h reply_handle;
141 struct block_device {
142 struct block_data *data;
144 int thread_id; /* Current thread ID */
145 bool removed; /* True when device is physically removed but operation is not precessed yet */
146 enum private_operation_state on_private_op;
147 bool mount_point_updated;
152 struct block_device *bdev;
154 enum unmount_operation option;
158 enum block_dev_operation op;
159 struct block_device *bdev;
163 static struct block_conf {
165 bool extendedinternal;
166 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
168 static struct manage_thread {
169 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
170 dd_list *block_dev_list; /* Use thread mutex */
172 pthread_mutex_t mutex;
174 int num_dev; /* Number of devices which thread holds. Only main thread access */
175 int op_len; /* Number of operation of thread. Use thread mutex */
176 int thread_id; /* Never changed */
178 } th_manager[THREAD_MAX];
180 static dd_list *fs_head;
181 static dd_list *block_ops_list;
184 static fd_handler_h phandler;
185 static bool block_control = false;
186 static bool block_boot = false;
187 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
189 /* Assume there is only one physical internal storage */
190 static int dev_internal = -1;
191 static char dev_internal_scsi = '\0';
192 static char dev_internal_emul = '\0';
194 static int block_start(void *data);
195 static int block_stop(void *data);
197 static int add_operation(struct block_device *bdev,
198 enum block_dev_operation operation,
199 dbus_method_reply_handle_h reply_handle, void *data);
200 static void remove_operation(struct block_device *bdev);
201 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
202 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
203 static int change_mount_point(struct block_device *bdev, const char *mount_point);
205 static void uevent_block_handler(struct udev_device *dev);
206 static struct uevent_handler uh = {
207 .subsystem = BLOCK_SUBSYSTEM,
208 .uevent_func = uevent_block_handler,
211 static void __CONSTRUCTOR__ smack_check(void)
216 fp = fopen("/proc/filesystems", "r");
220 while (fgets(buf, sizeof(buf), fp) != NULL) {
221 if (strstr(buf, "smackfs")) {
230 void add_fs(const struct block_fs_ops *fs)
232 DD_LIST_APPEND(fs_head, (void *)fs);
235 void remove_fs(const struct block_fs_ops *fs)
237 DD_LIST_REMOVE(fs_head, (void *)fs);
240 const struct block_fs_ops *find_fs(enum block_fs_type type)
242 struct block_fs_ops *fs;
245 DD_LIST_FOREACH(fs_head, elem, fs) {
246 if (fs->type == type)
252 void add_block_dev(const struct block_dev_ops *ops)
254 DD_LIST_APPEND(block_ops_list, (void *)ops);
257 void remove_block_dev(const struct block_dev_ops *ops)
259 DD_LIST_REMOVE(block_ops_list, (void *)ops);
262 static void broadcast_block_info(enum block_dev_operation op,
263 struct block_data *data, int result)
265 struct block_dev_ops *ops;
268 if (data->primary != true)
271 DD_LIST_FOREACH(block_ops_list, elem, ops) {
272 int data_block_type = (data->block_type == BLOCK_EXTENDEDSD_DEV)
273 ? BLOCK_MMC_DEV : data->block_type;
275 if (ops->block_type != data_block_type)
277 // TODO What happend on extended internal storage case?
278 if (op == BLOCK_DEV_MOUNT) {
279 ops->mounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
280 } else if (op == BLOCK_DEV_UNMOUNT) {
281 ops->unmounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
282 } else if (op == BLOCK_DEV_FORMAT) {
283 ops->formatted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
284 } else if (op == BLOCK_DEV_INSERT)
286 else if (op == BLOCK_DEV_REMOVE)
291 // Called by MainThread - Insert
292 static int block_get_new_id(void)
294 static int id = BLOCK_ID_MIN;
295 struct block_device *bdev;
300 for (i = 0 ; i < INT_MAX ; i++) {
302 for (j = 0; j < THREAD_MAX; j++) {
303 pthread_mutex_lock(&(th_manager[j].mutex));
304 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
305 if (bdev->data->id == id) {
310 pthread_mutex_unlock(&(th_manager[j].mutex));
325 static void remove_file(int id, bool extendedsd)
327 char file_name[PATH_LEN];
334 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
336 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
338 ret = remove(file_name);
340 _E("Fail to remove %s. errno: %d", file_name, errno);
343 static void create_file(int id, char *mount_point, bool extendedsd)
346 char file_name[PATH_LEN];
352 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
354 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
356 fp = fopen(file_name, "w+");
358 fprintf(fp, "%s", mount_point);
361 _E("Fail to open %s", file_name);
364 static void signal_device_blocked(struct block_device *bdev)
366 struct block_data *data;
368 char str_block_type[32];
369 char str_readonly[32];
371 char str_primary[32];
377 if (!bdev || !bdev->data)
383 /* Broadcast outside with BlockManager iface */
384 snprintf(str_block_type, sizeof(str_block_type),
385 "%d", data->block_type);
386 arr[0] = str_block_type;
387 arr[1] = (data->devnode ? data->devnode : str_null);
388 arr[2] = (data->syspath ? data->syspath : str_null);
389 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
390 arr[4] = (data->fs_type ? data->fs_type : str_null);
391 arr[5] = (data->fs_version ? data->fs_version : str_null);
392 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
393 snprintf(str_readonly, sizeof(str_readonly),
394 "%d", data->readonly);
395 arr[7] = str_readonly;
396 arr[8] = (data->mount_point ? data->mount_point : str_null);
397 snprintf(str_state, sizeof(str_state),
400 snprintf(str_primary, sizeof(str_primary),
401 "%d", data->primary);
402 arr[10] = str_primary;
403 snprintf(str_flags, sizeof(str_flags), "%d", flags);
405 snprintf(str_id, sizeof(str_id), "%d", data->id);
408 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
409 STORAGED_INTERFACE_BLOCK_MANAGER,
410 BLOCK_DEVICE_BLOCKED,
411 "issssssisibii", arr);
414 static void signal_device_changed(struct block_device *bdev,
415 enum block_dev_operation op)
417 struct block_data *data;
419 char str_block_type[32];
420 char str_readonly[32];
422 char str_primary[32];
428 if (!bdev || !bdev->data)
434 case BLOCK_DEV_MOUNT:
435 BLOCK_GET_MOUNT_FLAGS(data, flags);
437 case BLOCK_DEV_UNMOUNT:
438 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
440 case BLOCK_DEV_FORMAT:
441 BLOCK_GET_FORMAT_FLAGS(data, flags);
448 /* Broadcast outside with BlockManager iface */
449 snprintf(str_block_type, sizeof(str_block_type),
450 "%d", data->block_type);
451 arr[0] = str_block_type;
452 arr[1] = (data->devnode ? data->devnode : str_null);
453 arr[2] = (data->syspath ? data->syspath : str_null);
454 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
455 arr[4] = (data->fs_type ? data->fs_type : str_null);
456 arr[5] = (data->fs_version ? data->fs_version : str_null);
457 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
458 snprintf(str_readonly, sizeof(str_readonly),
459 "%d", data->readonly);
460 arr[7] = str_readonly;
461 arr[8] = (data->mount_point ? data->mount_point : str_null);
462 snprintf(str_state, sizeof(str_state),
465 snprintf(str_primary, sizeof(str_primary),
466 "%d", data->primary);
467 arr[10] = str_primary;
468 snprintf(str_flags, sizeof(str_flags), "%d", flags);
470 snprintf(str_id, sizeof(str_id), "%d", data->id);
473 if (op == BLOCK_DEV_INSERT)
474 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
475 STORAGED_INTERFACE_BLOCK_MANAGER,
477 "issssssisibii", arr);
478 else if (op == BLOCK_DEV_REMOVE)
479 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
480 STORAGED_INTERFACE_BLOCK_MANAGER,
481 BLOCK_DEVICE_REMOVED,
482 "issssssisibii", arr);
484 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
485 STORAGED_INTERFACE_BLOCK_MANAGER,
486 BLOCK_DEVICE_CHANGED,
487 "issssssisibii", arr);
488 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
489 STORAGED_INTERFACE_BLOCK_MANAGER,
490 BLOCK_DEVICE_CHANGED_2,
491 "issssssisibi", arr);
495 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
497 char *name = devnode;
498 int dev = -1, part = -1;
499 char emul[32] = { 0, };
506 sscanf(name, "mmcblk%dp%d", &dev, &part);
509 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
511 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
516 sscanf(name, "vd%31s", emul);
519 for (i = 0 ; i < strlen(emul) ; i++)
520 emul[i] = toupper(emul[i]);
521 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
525 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
533 snprintf(dev, sizeof(dev), "%s", devnode);
535 if (!strstr(dev, "sd"))
539 name += strlen("sd");
541 for (i = 0 ; i < strlen(name) ; i++)
542 name[i] = toupper(name[i]);
543 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
548 static char *generate_mount_path(struct block_data *data)
551 char *name, node[64];
554 if (!data || !data->devnode || !data->fs_usage || (strcmp(data->fs_usage, FILESYSTEM_NAME) && strncmp(data->fs_usage, "crypto", strlen("crypto"))))
557 name = strrchr(data->devnode, '/');
562 switch (data->block_type) {
564 ret = get_mmc_mount_node(name, node, sizeof(node));
567 ret = get_scsi_mount_node(name, node, sizeof(node));
569 case BLOCK_EXTENDEDSD_DEV:
570 return strdup(EXTENDEDSD_MOUNT_PATH);
572 _E("Invalid block type (%d)", data->block_type);
578 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
584 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
588 static bool check_primary_partition(const char *devnode)
590 struct block_fs_ops *fs;
593 const char *filesystem = NULL;
603 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
604 fnmatch(MMC_PATH, devnode, 0) &&
605 fnmatch(SCSI_PATH, devnode, 0) &&
606 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
609 temp = strrchr(devnode, '/');
612 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
613 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
616 /* Emulator support only one partition */
620 snprintf(str, sizeof(str), "%s", devnode);
625 for (i = 1; i <= 9; ++i) {
626 snprintf(str2, sizeof(str2), "%s%d", str, i);
627 if (access(str2, R_OK) != 0)
630 probe = blkid_new_probe_from_filename(str2);
633 if (blkid_do_probe(probe) != 0)
636 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
638 blkid_free_probe(probe);
641 DD_LIST_FOREACH(fs_head, elem, fs) {
642 if (!strncmp(fs->name, filesystem, fs_len)) {
647 blkid_free_probe(probe);
653 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
659 /* Whole data in struct block_data should be freed. */
660 static struct block_data *make_block_data(const char *devnode,
662 const char *fs_usage,
664 const char *fs_version,
665 const char *fs_uuid_enc,
666 const char *readonly)
668 struct block_data *data;
670 /* devnode is unique value so it should exist. */
675 _I("Unknown fs type");
677 data = calloc(1, sizeof(struct block_data));
679 _E("calloc() failed");
683 data->devnode = strdup(devnode);
685 data->syspath = strdup(syspath);
687 data->fs_usage = strdup(fs_usage);
689 data->fs_type = strdup(fs_type);
691 data->fs_version = strdup(fs_version);
693 data->fs_uuid_enc = strdup(fs_uuid_enc);
695 data->readonly = atoi(readonly);
696 data->primary = check_primary_partition(devnode);
698 /* TODO should we know block dev type? */
699 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
700 data->block_type = BLOCK_MMC_DEV;
701 else if (!fnmatch(MMC_PATH, devnode, 0))
702 data->block_type = BLOCK_MMC_DEV;
703 else if (!fnmatch(SCSI_PATH, devnode, 0))
704 data->block_type = BLOCK_SCSI_DEV;
705 else if (!fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
706 data->block_type = BLOCK_EXTENDEDSD_DEV;
708 data->block_type = -1;
710 data->mount_point = generate_mount_path(data);
711 BLOCK_FLAG_CLEAR_ALL(data);
713 /* for 2.4 backward compatibility */
714 // What if storage id 1 is existed? (multi sdcard case)
715 if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
716 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME))
717 data->id = EXT_PRIMARY_SD_FIXID;
719 data->id = block_get_new_id();
724 static void free_block_data(struct block_data *data)
730 free(data->fs_usage);
732 free(data->fs_version);
733 free(data->fs_uuid_enc);
734 free(data->mount_point);
738 static int update_block_data(struct block_data *data,
739 const char *fs_usage,
741 const char *fs_version,
742 const char *fs_uuid_enc,
743 const char *readonly,
744 bool mount_point_updated)
749 free(data->fs_usage);
750 data->fs_usage = NULL;
752 data->fs_usage = strdup(fs_usage);
755 data->fs_type = NULL;
757 data->fs_type = strdup(fs_type);
759 free(data->fs_version);
760 data->fs_version = NULL;
762 data->fs_version = strdup(fs_version);
764 free(data->fs_uuid_enc);
765 data->fs_uuid_enc = NULL;
767 data->fs_uuid_enc = strdup(fs_uuid_enc);
769 /* generate_mount_path function should be invoked
770 * after fs_uuid_enc is updated */
771 if (!mount_point_updated) {
772 free(data->mount_point);
773 data->mount_point = generate_mount_path(data);
776 data->readonly = false;
778 data->readonly = atoi(readonly);
780 BLOCK_FLAG_MOUNT_CLEAR(data);
785 static struct block_device *make_block_device(struct block_data *data)
787 struct block_device *bdev;
792 bdev = calloc(1, sizeof(struct block_device));
797 bdev->thread_id = -1;
798 bdev->removed = false;
799 bdev->on_private_op = REQ_NORMAL;
800 bdev->private_pid = 0;
801 bdev->mount_point_updated = false;
806 // Called by MainThread - Remove DevNode
807 static void free_block_device(struct block_device *bdev)
810 struct operation_queue *op;
816 thread_id = bdev->thread_id;
817 if (thread_id < 0 || thread_id >= THREAD_MAX)
820 pthread_mutex_lock(&(th_manager[thread_id].mutex));
822 th_manager[thread_id].num_dev--;
823 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
824 free_block_data(bdev->data);
826 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
828 th_manager[thread_id].op_len--;
829 DD_LIST_REMOVE(bdev->op_queue, op);
832 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
837 // Called By MainThread - Remove Device
838 static struct block_device *find_block_device(const char *devnode)
840 struct block_device *bdev;
845 len = strlen(devnode) + 1;
846 for (i = 0; i < THREAD_MAX; i++) {
847 pthread_mutex_lock(&(th_manager[i].mutex));
848 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
849 if (bdev->data && !bdev->removed &&
850 !strncmp(bdev->data->devnode, devnode, len)) {
851 pthread_mutex_unlock(&(th_manager[i].mutex));
855 pthread_mutex_unlock(&(th_manager[i].mutex));
861 // Called By MainThread - Remove Device
862 static struct block_device *find_block_device_path(const char *mount_point)
864 struct block_device *bdev;
869 len = strlen(mount_point) + 1;
870 for (i = 0; i < THREAD_MAX; i++) {
871 pthread_mutex_lock(&(th_manager[i].mutex));
872 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
873 if (bdev->data && !bdev->removed &&
874 (bdev->data->mount_point != NULL && !strncmp(bdev->data->mount_point, mount_point, len))) {
875 pthread_mutex_unlock(&(th_manager[i].mutex));
879 pthread_mutex_unlock(&(th_manager[i].mutex));
885 // Called By MainThread - Mount,Unmount,Format,GetInfo
886 static struct block_device *find_block_device_by_id(int id)
888 struct block_device *bdev;
892 for (i = 0; i < THREAD_MAX; i++) {
893 pthread_mutex_lock(&(th_manager[i].mutex));
894 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
899 if (bdev->data->id == id) {
900 pthread_mutex_unlock(&(th_manager[i].mutex));
904 pthread_mutex_unlock(&(th_manager[i].mutex));
910 static char *get_operation_char(enum block_dev_operation op,
911 char *name, unsigned int len)
913 char *str = "unknown";
919 case BLOCK_DEV_MOUNT:
922 case BLOCK_DEV_UNMOUNT:
925 case BLOCK_DEV_FORMAT:
928 case BLOCK_DEV_INSERT:
931 case BLOCK_DEV_REMOVE:
934 case BLOCK_LUKS_CLOSE:
938 _E("invalid operation (%d)", op);
942 snprintf(name, len, "%s", str);
946 static void create_external_apps_directory(void)
950 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
951 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
952 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
954 _E("Fail to create external directory");
957 static int pipe_trigger(enum block_dev_operation op,
958 struct block_device *bdev, int result)
960 struct pipe_data pdata = { op, bdev, result };
964 _D("op : %s, bdev : %p, result : %d",
965 get_operation_char(pdata.op, name, sizeof(name)),
966 pdata.bdev, pdata.result);
968 // Multi thread should not write at the same time
969 pthread_mutex_lock(&pipe_mutex);
970 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
971 pthread_mutex_unlock(&pipe_mutex);
973 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
976 static bool pipe_cb(int fd, void *data)
978 struct pipe_data pdata = {0,};
984 n = read(fd, &pdata, sizeof(pdata));
985 if (n != sizeof(pdata) || !pdata.bdev) {
986 _E("fail to read struct pipe data");
990 _I("op : %s, bdev : %p, result : %d",
991 get_operation_char(pdata.op, name, sizeof(name)),
992 pdata.bdev, pdata.result);
994 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
995 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
996 ret = change_mount_point(pdata.bdev, "");
997 /* Modify /run/external-storage/id file */
999 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
1000 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
1002 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
1007 if (pdata.op == BLOCK_DEV_MOUNT &&
1008 pdata.bdev->data->state == BLOCK_MOUNT &&
1009 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
1010 pdata.bdev->data->primary)
1011 create_external_apps_directory();
1012 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1013 /* Remove file for block device /run/xxxxxx/id */
1014 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
1017 /* Broadcast to mmc and usb storage module */
1018 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
1020 /* Broadcast outside with Block iface */
1021 if (pdata.bdev->on_private_op == REQ_NORMAL)
1022 signal_device_changed(pdata.bdev, pdata.op);
1023 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
1024 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1025 pdata.bdev->on_private_op = REQ_NORMAL;
1026 _D("Private operation state: %d", pdata.bdev->on_private_op);
1029 if (pdata.op == BLOCK_DEV_MOUNT) {
1030 pdata.bdev->on_private_op = REQ_PRIVATE;
1031 _D("Private operation state: %d", pdata.bdev->on_private_op);
1035 if (pdata.op == BLOCK_DEV_REMOVE) {
1036 thread_id = pdata.bdev->thread_id;
1037 if (thread_id < 0 || thread_id >= THREAD_MAX)
1039 free_block_device(pdata.bdev);
1046 static int pipe_init(void)
1050 ret = pipe2(pfds, O_CLOEXEC);
1054 ret = add_fd_read_handler(pfds[0], pipe_cb,
1055 NULL, NULL, &phandler);
1057 _E("Failed to add pipe handler (%d)", ret);
1064 static void pipe_exit(void)
1067 remove_fd_read_handler(&phandler);
1077 static int mmc_check_and_unmount(const char *path)
1085 while (mount_check(path)) {
1089 if (retry > UNMOUNT_RETRY)
1096 static bool check_rw_mount(const char *szPath)
1098 struct statvfs mount_stat;
1100 if (!statvfs(szPath, &mount_stat)) {
1101 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1107 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1110 struct udev_device *dev;
1117 for (wait = 0; wait < 10; wait++) {
1120 _E("fail to create udev library context");
1124 dev = udev_device_new_from_syspath(udev, data->syspath);
1126 _E("fail to create new udev device");
1131 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
1136 udev_device_unref(dev);
1140 r = update_block_data(data,
1141 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1142 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1143 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1144 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1145 udev_device_get_sysattr_value(dev, "ro"),
1146 mount_point_updated);
1148 _E("fail to update block data for %s", data->devnode);
1150 udev_device_unref(dev);
1155 static int block_mount(struct block_data *data)
1157 struct block_fs_ops *fs;
1162 if (!data || !data->devnode || !data->mount_point)
1165 /* check existing mounted */
1166 if (mount_check(data->mount_point))
1169 /* create mount point */
1170 if (access(data->mount_point, R_OK) != 0) {
1171 if (mkdir(data->mount_point, 0755) < 0)
1175 /* check matched file system */
1176 if (!data->fs_usage ||
1177 strncmp(data->fs_usage, FILESYSTEM_NAME,
1178 sizeof(FILESYSTEM_NAME)) != 0) {
1183 if (!data->fs_type) {
1184 _E("There is no file system");
1185 BLOCK_FLAG_SET(data, FS_EMPTY);
1191 len = strlen(data->fs_type) + 1;
1192 DD_LIST_FOREACH(fs_head, elem, fs) {
1193 if (!strncmp(fs->name, data->fs_type, len))
1198 _E("Not supported file system (%s)", data->fs_type);
1199 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1204 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1205 r = fs->mount(false, data->devnode, data->mount_point);
1207 r = fs->mount(smack, data->devnode, data->mount_point);
1210 BLOCK_FLAG_SET(data, FS_BROKEN);
1215 r = check_rw_mount(data->mount_point);
1222 rmdir(data->mount_point);
1226 static int mount_start(struct block_device *bdev)
1228 struct block_data *data;
1236 _I("Mount Start : (%s -> %s)",
1237 data->devnode, data->mount_point);
1239 /* mount operation */
1240 r = block_mount(data);
1241 if (r != -EROFS && r < 0) {
1242 _E("fail to mount %s device : %d", data->devnode, r);
1247 data->readonly = true;
1248 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1251 data->state = BLOCK_MOUNT;
1253 if (data->block_type == BLOCK_MMC_DEV) {
1254 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1255 ret = app2ext_migrate_legacy_all();
1257 _E("app2ext failed");
1261 if (r < 0 && r != -EROFS)
1262 data->state = BLOCK_UNMOUNT;
1264 _I("%s result : %s, %d", __func__, data->devnode, r);
1266 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1267 _E("fail to trigger pipe");
1272 static int change_mount_point(struct block_device *bdev,
1273 const char *mount_point)
1275 struct block_data *data;
1281 free(data->mount_point);
1283 /* If the mount path already exists, the path cannot be used */
1285 access(mount_point, F_OK) != 0) {
1286 data->mount_point = strdup(mount_point);
1287 bdev->mount_point_updated = true;
1289 data->mount_point = generate_mount_path(data);
1290 bdev->mount_point_updated = false;
1296 static int mount_block_device(struct block_device *bdev)
1298 struct block_data *data;
1301 if (!bdev || !bdev->data)
1305 if (data->state == BLOCK_MOUNT) {
1306 _I("%s is already mounted", data->devnode);
1310 if (!block_conf[data->block_type].multimount &&
1312 _I("Not support multi mount by config info");
1316 r = mount_start(bdev);
1318 _E("Failed to mount (%s)", data->devnode);
1325 static int block_unmount(struct block_device *bdev,
1326 enum unmount_operation option)
1328 struct block_data *data;
1330 struct timespec time = {0,};
1332 if (!bdev || !bdev->data || !bdev->data->mount_point)
1337 if (bdev->on_private_op == REQ_NORMAL)
1338 signal_device_blocked(bdev);
1340 /* it must called before unmounting mmc */
1341 r = mmc_check_and_unmount(data->mount_point);
1344 if (option == UNMOUNT_NORMAL) {
1345 _I("Failed to unmount with normal option : %d", r);
1349 _I("Execute force unmount!");
1350 /* Force Unmount Scenario */
1355 * should unmount the below vconf key. */
1356 if ((data->block_type == BLOCK_MMC_DEV ||
1357 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1359 /* At first, notify to other app
1360 * who already access sdcard */
1361 _I("Notify to other app who already access sdcard");
1362 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1363 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1367 /* Second, kill app with SIGTERM */
1368 _I("Kill app with SIGTERM");
1369 terminate_process(data->mount_point, false);
1372 /* Last time, kill app with SIGKILL */
1373 _I("Kill app with SIGKILL");
1374 terminate_process(data->mount_point, true);
1377 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1378 _I("Failed to unmount with lazy option : %d",
1385 /* it takes some seconds til other app completely clean up */
1386 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1387 nanosleep(&time, NULL);
1389 print_open_files(data->mount_point);
1391 r = mmc_check_and_unmount(data->mount_point);
1393 _D("Success to unmount (%s)", data->mount_point);
1399 data->state = BLOCK_UNMOUNT;
1401 if (rmdir(data->mount_point) < 0)
1402 _E("fail to remove %s directory", data->mount_point);
1407 static int unmount_block_device(struct block_device *bdev,
1408 enum unmount_operation option)
1410 struct block_data *data;
1413 if (!bdev || !bdev->data)
1417 if (data->state == BLOCK_UNMOUNT) {
1418 _I("%s is already unmounted", data->devnode);
1419 r = mmc_check_and_unmount(data->mount_point);
1421 _E("The path was existed, but could not delete it(%s)",
1426 _I("Unmount Start : (%s -> %s)",
1427 data->devnode, data->mount_point);
1429 r = block_unmount(bdev, option);
1431 _E("fail to unmount %s device : %d", data->devnode, r);
1435 BLOCK_FLAG_MOUNT_CLEAR(data);
1438 _I("%s result : %s, %d", __func__, data->devnode, r);
1440 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1441 _E("fail to trigger pipe");
1446 static int block_format(struct block_data *data,
1447 const char *fs_type, bool mount_point_updated)
1449 const struct block_fs_ops *fs;
1455 if (!data || !data->devnode || !data->mount_point)
1458 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1464 fstype = data->fs_type;
1470 len = strlen(fstype);
1471 DD_LIST_FOREACH(fs_head, elem, fs) {
1472 if (!strncmp(fs->name, fstype, len))
1477 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1478 _E("not supported file system(%s)", fstype);
1482 _I("format path : %s", data->devnode);
1483 fs->check(data->devnode);
1484 r = fs->format(data->devnode);
1486 _E("fail to format block data for %s", data->devnode);
1490 /* need to update the partition data.
1491 * It can be changed in doing format. */
1492 retrieve_udev_device(data, mount_point_updated);
1497 static int format_block_device(struct block_device *bdev,
1498 const char *fs_type,
1499 enum unmount_operation option)
1501 struct block_data *data;
1509 _I("Format Start : (%s -> %s)",
1510 data->devnode, data->mount_point);
1512 if (data->state == BLOCK_MOUNT) {
1513 r = block_unmount(bdev, option);
1515 _E("fail to unmount %s device : %d", data->devnode, r);
1520 r = block_format(data, fs_type, bdev->mount_point_updated);
1522 _E("fail to format %s device : %d", data->devnode, r);
1525 _I("%s result : %s, %d", __func__, data->devnode, r);
1527 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1529 _E("fail to trigger pipe");
1534 static struct format_data *get_format_data(
1535 const char *fs_type, enum unmount_operation option)
1537 struct format_data *fdata;
1539 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1541 _E("fail to allocate format data");
1546 fdata->fs_type = strdup(fs_type);
1548 fdata->fs_type = NULL;
1549 fdata->option = option;
1554 static void release_format_data(struct format_data *data)
1558 free(data->fs_type);
1563 // Called by BlockThread - Real Mount Op
1564 static int block_mount_device(struct block_device *bdev, void *data)
1573 thread_id = bdev->thread_id;
1574 if (thread_id < 0 || thread_id >= THREAD_MAX)
1576 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1577 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1578 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1580 _E("(%d) does not exist in the device list", bdev->data->devnode);
1584 /* mount automatically */
1585 ret = mount_block_device(bdev);
1587 _E("fail to mount block device for %s", bdev->data->devnode);
1592 // Called by BlockThread - Real Format Op
1593 static int block_format_device(struct block_device *bdev, void *data)
1598 struct format_data *fdata = (struct format_data *)data;
1600 if (!bdev || !fdata) {
1605 thread_id = bdev->thread_id;
1606 if (thread_id < 0 || thread_id >= THREAD_MAX)
1608 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1609 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1610 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1612 _E("(%d) does not exist in the device list", bdev->data->devnode);
1617 ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1619 _E("fail to mount block device for %s", bdev->data->devnode);
1622 release_format_data(fdata);
1627 // Called by BlockThread - Real Unmount Op
1628 static int block_unmount_device(struct block_device *bdev, void *data)
1631 long option = (long)data;
1636 ret = unmount_block_device(bdev, option);
1638 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1645 /* Called by BlockThread - Remove Operation
1646 Direct Call at BlockThread
1647 Previously this function was called by MainThread. However, it will increase complexity.
1648 Need thread lock before to call remove_operation
1650 static void remove_operation(struct block_device *bdev)
1652 struct operation_queue *op;
1659 thread_id = bdev->thread_id;
1660 if (thread_id < 0 || thread_id >= THREAD_MAX)
1663 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1665 _D("Remove operation (%s, %s)",
1666 get_operation_char(op->op, name, sizeof(name)),
1667 bdev->data->devnode);
1669 DD_LIST_REMOVE(bdev->op_queue, op);
1675 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1682 rep = make_dbus_reply_message_simple(reply_handle, result);
1683 reply_dbus_method_result(reply_handle, rep);
1686 // Called by BlockThread
1687 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1689 struct operation_queue *temp;
1702 thread_id = bdev->thread_id;
1703 if (thread_id < 0 || thread_id >= THREAD_MAX)
1706 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1708 DD_LIST_FOREACH(*queue, l, temp) {
1709 if (temp->op == BLOCK_DEV_REMOVE) {
1714 th_manager[thread_id].op_len--;
1715 block_send_dbus_reply((*op)->reply_handle, 0);
1718 remove_operation(bdev);
1719 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1722 // Called by BlockThread
1723 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1725 struct operation_queue *temp;
1728 bool unmounted = false;
1739 thread_id = bdev->thread_id;
1740 if (thread_id < 0 || thread_id >= THREAD_MAX)
1743 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1744 DD_LIST_FOREACH(*queue, l, temp) {
1745 if (temp->op == BLOCK_DEV_UNMOUNT) {
1747 _D("Operation queue has unmount operation");
1751 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1756 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1758 DD_LIST_FOREACH(*queue, l, temp) {
1759 if (temp->op == BLOCK_DEV_UNMOUNT) {
1764 th_manager[thread_id].op_len--;
1765 block_send_dbus_reply((*op)->reply_handle, 0);
1768 remove_operation(bdev);
1769 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1774 // Called by BlockThread
1775 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1779 char devnode[PATH_MAX];
1781 enum block_dev_operation operation;
1782 bool unmounted = false;
1789 thread_id = bdev->thread_id;
1790 if (thread_id < 0 || thread_id >= THREAD_MAX)
1793 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1803 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1804 get_operation_char(operation, name, sizeof(name)), devnode);
1807 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1808 check_removed(bdev, &queue, &op);
1810 _D("Trigger operation again (%s, %s)",
1811 get_operation_char(operation, name, sizeof(name)), devnode);
1813 if (operation == BLOCK_DEV_MOUNT) {
1814 unmounted = check_unmount(bdev, &queue, &op);
1817 _D("Trigger operation again (%s, %s)",
1818 get_operation_char(operation, name, sizeof(name)), devnode);
1822 switch (operation) {
1823 case BLOCK_DEV_INSERT:
1825 case BLOCK_DEV_MOUNT:
1826 ret = block_mount_device(bdev, op->data);
1827 _D("Mount (%s) result:(%d)", devnode, ret);
1829 case BLOCK_DEV_FORMAT:
1830 ret = block_format_device(bdev, op->data);
1831 _D("Format (%s) result:(%d)", devnode, ret);
1833 case BLOCK_DEV_UNMOUNT:
1834 ret = block_unmount_device(bdev, op->data);
1835 _D("Unmount (%s) result:(%d)", devnode, ret);
1837 case BLOCK_DEV_REMOVE:
1840 case BLOCK_LUKS_CLOSE:
1841 ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1843 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1846 _E("Operation type is invalid (%d)", op->op);
1852 * during checking the queue length */
1853 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1856 th_manager[thread_id].op_len--;
1858 block_send_dbus_reply(op->reply_handle, ret);
1860 queue = bdev->op_queue;
1861 if (queue != NULL) {
1862 queue = DD_LIST_NEXT(queue);
1864 op = DD_LIST_NTH(queue, 0);
1870 remove_operation(bdev);
1872 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1875 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1876 if (pipe_trigger(operation, bdev, 0) < 0)
1877 _E("fail to trigger pipe");
1884 // Called by BlockThread
1885 static void *block_th_start(void *arg)
1887 struct block_device *temp;
1888 struct manage_thread *th = (struct manage_thread *)arg;
1889 struct operation_queue *op = NULL;
1891 dd_list *queue = NULL;
1896 thread_id = th->thread_id;
1897 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1898 _E("Thread Number: %d", th->thread_id);
1903 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1904 if (th_manager[thread_id].op_len == 0) {
1905 _D("Operation queue of thread is empty");
1906 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1907 _D("Wake up %d", thread_id);
1910 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1911 queue = temp->op_queue;
1913 op = DD_LIST_NTH(queue, 0);
1915 _D("Operation queue for device %s is Empty", temp->data->devnode);
1919 queue = DD_LIST_NEXT(queue);
1927 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1929 if (op && !op->done)
1930 trigger_operation(temp, queue, op);
1935 // This function will be refactored later
1936 // Especially, we don't need to keep th_node_list.
1937 static int find_thread(char *devnode)
1944 int i, len, min, min_num;
1945 int dev_mmc = -1, part = -1, num;
1948 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1949 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1956 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1957 th_node = strdup(str);
1958 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1959 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1960 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1961 th_node = strdup(str);
1963 th_node = strdup(devnode);
1965 len = strlen(th_node) + 1;
1968 for (i = 0; i < THREAD_MAX; i++) {
1969 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1970 if (!strncmp(temp, th_node, len)) {
1975 if (th_manager[i].num_dev < min_num) {
1976 min_num = th_manager[i].num_dev;
1981 if (min >= 0 && min < THREAD_MAX) {
1982 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1986 _E("Finding thread is failed");
1987 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1991 /* Only Main thread is permmited */
1992 // Called by MainThread
1993 static int add_operation(struct block_device *bdev,
1994 enum block_dev_operation operation,
1995 dbus_method_reply_handle_h reply_handle, void *data)
1997 struct operation_queue *op;
2007 _I("Add operation (%s, %s)",
2008 get_operation_char(operation, name, sizeof(name)),
2009 bdev->data->devnode);
2011 thread_id = bdev->thread_id;
2012 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2013 _E("Fail to find thread to add");
2017 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2019 _E("malloc failed");
2025 op->reply_handle = reply_handle;
2028 * during adding queue and checking the queue length */
2029 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2031 /* Only modified between lock and unlock of mutex */
2034 start_th = th_manager[thread_id].start_th;
2035 DD_LIST_APPEND(bdev->op_queue, op);
2036 th_manager[thread_id].op_len++;
2038 if (th_manager[thread_id].op_len == 1 && !start_th)
2039 pthread_cond_signal(&(th_manager[thread_id].cond));
2041 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2044 /* Need to disble app2ext whenever unmounting mmc */
2045 if (op->op == BLOCK_DEV_UNMOUNT &&
2046 bdev->data->state == BLOCK_MOUNT &&
2047 bdev->data->block_type == BLOCK_MMC_DEV &&
2048 bdev->data->primary)
2049 if (app2ext_disable_all_external_pkgs() < 0)
2050 _E("app2ext_disable_all_external_pkgs() failed");
2054 _D("Start New thread for block device");
2055 th_manager[thread_id].start_th = false;
2056 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2058 _E("fail to create thread for %s", bdev->data->devnode);
2062 pthread_detach(th_manager[thread_id].th);
2068 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2071 struct dirent entry;
2073 const char *syspath;
2076 syspath = udev_device_get_syspath(dev);
2080 dp = opendir(syspath);
2082 _E("fail to open %s", syspath);
2086 /* TODO compare devname and d_name */
2087 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2088 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2089 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2101 static bool check_partition(struct udev_device *dev)
2103 const char *devtype;
2104 const char *part_table_type;
2105 const char *fs_usage;
2108 /* only consider disk type, never partitions */
2109 devtype = udev_device_get_devtype(dev);
2113 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2114 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2117 part_table_type = udev_device_get_property_value(dev,
2118 "ID_PART_TABLE_TYPE");
2119 if (part_table_type) {
2120 fs_usage = udev_device_get_property_value(dev,
2123 strncmp(fs_usage, FILESYSTEM_NAME, sizeof(FILESYSTEM_NAME)) == 0) {
2124 if (!disk_is_partitioned_by_kernel(dev))
2131 if (disk_is_partitioned_by_kernel(dev)) {
2140 // Called by MainThread
2141 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2143 struct block_data *data;
2144 struct block_device *bdev;
2145 //char id_string[PATH_LEN];
2149 bool need_format = false;
2151 partition = check_partition(dev);
2153 /* if there is a partition, skip this request */
2154 _I("%s device has partitions, skip this time", devnode);
2158 if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2159 char syspath[128] = {0};
2162 r = rindex(udev_device_get_syspath(dev), '/');
2163 if (!r) return -ENODEV;
2165 snprintf(syspath, sizeof(syspath), "/sys/block%s", r);
2167 data = make_block_data(devnode,
2172 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2173 udev_device_get_sysattr_value(dev, "ro"));
2176 data = make_block_data(devnode,
2177 udev_device_get_syspath(dev),
2178 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2179 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2180 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2181 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2182 udev_device_get_sysattr_value(dev, "ro"));
2186 _E("fail to make block data for %s", devnode);
2190 if (!block_conf[data->block_type].multimount && !data->primary &&
2191 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME)) {
2192 _D("Not support multi mount by config info");
2193 free_block_data(data);
2197 bdev = make_block_device(data);
2199 _E("fail to make block device for %s", devnode);
2200 free_block_data(data);
2204 thread_id = find_thread(bdev->data->devnode);
2205 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2206 _E("Fail to find thread to add");
2207 free_block_device(bdev);
2210 bdev->thread_id = thread_id;
2212 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2213 th_manager[thread_id].num_dev++;
2214 DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2215 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2218 struct format_data *fdata;
2220 fdata = get_format_data(NULL, UNMOUNT_FORCE);
2222 _E("Failed to get format data");
2226 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2228 _E("Failed to add operation (format %s)", bdev->data->devnode);
2229 release_format_data(fdata);
2233 if (!bdev->data->fs_type) {
2234 _E("Unformatted Storage");
2235 free_block_device(bdev);
2237 } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2238 // bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2239 bdev->data->primary = true;
2240 _D("Need to unlock encrypted sdcard");
2241 // ---- ODE UI launch ----
2242 ret = launch_system_app(POPUP_DEFAULT
2245 , "unlockextendedsd"
2249 , bdev->data->devnode
2253 _E("Failed to launch popup");
2255 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2257 _E("Failed to add operation (insert %s)", devnode);
2258 free_block_device(bdev);
2263 } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2264 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2265 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2268 free_block_device(bdev);
2273 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2275 _E("Failed to add operation (insert %s)", devnode);
2276 free_block_device(bdev);
2280 // Not a regular filesystem -> skip mounting
2281 if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM_NAME)) {
2282 _I("Not a filesystem. Not mounting");
2286 /* Create file for block device /run/external-storage/id */
2287 create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2288 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2290 _E("Failed to add operation (mount %s)", devnode);
2296 static int remove_block_device(struct udev_device *dev, const char *devnode)
2298 struct block_device *bdev;
2299 struct block_device *bdev_extended;
2302 bdev = find_block_device(devnode);
2304 _E("fail to find block data for %s", devnode);
2308 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2310 bdev->removed = true;
2311 if (bdev->on_private_op != REQ_NORMAL) {
2312 bdev->on_private_op = REQ_NORMAL;
2313 _D("Private operation state: %d", bdev->on_private_op);
2316 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2317 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2319 if (bdev_extended) {
2320 BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2322 bdev_extended->removed = true;
2323 if (bdev_extended->on_private_op != REQ_NORMAL) {
2324 bdev_extended->on_private_op = REQ_NORMAL;
2325 _D("Private operation state: %d", bdev_extended->on_private_op);
2328 ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2330 _E("Failed to add operation (unmount %s)", devnode);
2334 ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2336 _E("Failed to add operation (remove %s)", devnode);
2340 ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2342 _E("Failed to add operation (luks_close %s)", devnode);
2346 _E("fail to find block data for extended sd card");
2349 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2351 _E("Failed to add operation (unmount %s)", devnode);
2355 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2357 _E("Failed to add operation (remove %s)", devnode);
2364 static int get_internal_storage_number(void)
2366 struct libmnt_table *t = NULL;
2367 struct libmnt_fs *fs;
2370 int r = 0, dev_temp;
2372 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2373 (is_emulator() && dev_internal_emul != '\0'))
2376 t = mnt_new_table();
2380 r = mnt_table_parse_mtab(t, NULL);
2386 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2392 temp = mnt_fs_get_srcpath(fs);
2396 name = strrchr(temp, '/');
2400 /* Boot from USB is not handled */
2401 if (!is_emulator()) {
2402 if (!fnmatch(MMC_PATH, temp, 0))
2403 sscanf(name, "mmcblk%d", &dev_internal);
2404 else if (!fnmatch(SCSI_PATH, temp, 0))
2405 sscanf(name, "sd%c", &dev_internal_scsi);
2407 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2408 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2410 dev_internal_emul = '\0';
2418 static int check_external_storage(const char* devnode)
2420 char dev_scsi = '\0';
2423 int dev_num = -1, dev_temp;
2428 name = strrchr(devnode, '/');
2432 if (!is_emulator()) {
2433 if (!fnmatch(MMC_PATH, devnode, 0)) {
2434 sscanf(name, "mmcblk%d", &dev_num);
2435 if (dev_internal == dev_num) {
2436 _D("%s is internal storage", devnode);
2439 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2440 sscanf(name, "sd%c", &dev_scsi);
2441 if (dev_internal_scsi == dev_scsi) {
2442 _D("%s is internal storage", devnode);
2447 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2448 sscanf(name, "vd%c%d", &emul, &dev_temp);
2449 if (dev_internal_emul == emul) {
2450 _D("%s is internal storage", devnode);
2459 static int check_already_handled(const char* devnode)
2461 struct block_device *bdev;
2462 struct block_data *data;
2466 for (i = 0; i < THREAD_MAX; i++) {
2467 pthread_mutex_lock(&(th_manager[i].mutex));
2468 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2474 if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2475 pthread_mutex_unlock(&(th_manager[i].mutex));
2479 pthread_mutex_unlock(&(th_manager[i].mutex));
2485 static int block_init_from_udev_enumerate(void)
2488 struct udev_enumerate *enumerate;
2489 struct udev_list_entry *list_entry, *list_sub_entry;
2490 struct udev_device *dev;
2491 const char *syspath;
2492 const char *devnode;
2497 _E("fail to create udev library context");
2501 /* create a list of the devices in the 'usb' subsystem */
2502 enumerate = udev_enumerate_new(udev);
2504 _E("fail to create an enumeration context");
2508 if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2509 (is_emulator() && dev_internal_emul == '\0')) {
2510 r = get_internal_storage_number();
2515 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2516 udev_enumerate_add_match_property(enumerate,
2517 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2518 udev_enumerate_add_match_property(enumerate,
2519 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2520 udev_enumerate_scan_devices(enumerate);
2522 udev_list_entry_foreach(list_entry,
2523 udev_enumerate_get_list_entry(enumerate)) {
2524 syspath = udev_list_entry_get_name(list_entry);
2528 dev = udev_device_new_from_syspath(
2529 udev_enumerate_get_udev(enumerate),
2535 udev_list_entry_foreach(list_sub_entry,
2536 udev_device_get_devlinks_list_entry(dev)) {
2537 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2538 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2545 devnode = udev_device_get_devnode(dev);
2549 if (fnmatch(MMC_PATH, devnode, 0) &&
2550 fnmatch(SCSI_PATH, devnode, 0) &&
2551 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
2555 r = check_external_storage(devnode);
2559 r = check_already_handled(devnode);
2561 _I("%s is already handled", devnode);
2565 _I("%s device add", devnode);
2566 add_block_device(dev, devnode, false);
2568 udev_device_unref(dev);
2571 udev_enumerate_unref(enumerate);
2576 // Called by MainThread
2577 static void show_block_device_list(void)
2579 struct block_device *bdev;
2580 struct block_data *data;
2584 for (i = 0; i < THREAD_MAX; i++) {
2585 pthread_mutex_lock(&(th_manager[i].mutex));
2586 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2592 _D("%s:", data->devnode);
2593 _D("\tSyspath: %s", data->syspath);
2594 _D("\tBlock type: %d", data->block_type);
2595 _D("\tFs type: %s", data->fs_type);
2596 _D("\tFs usage: %s", data->fs_usage);
2597 _D("\tFs version: %s", data->fs_version);
2598 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2599 _D("\tReadonly: %s",
2600 (data->readonly ? "true" : "false"));
2601 _D("\tMount point: %s", data->mount_point);
2602 _D("\tMount state: %s",
2603 (data->state == BLOCK_MOUNT ?
2604 "mount" : "unmount"));
2606 (data->primary ? "true" : "false"));
2607 _D("\tID: %d", data->id);
2609 pthread_mutex_unlock(&(th_manager[i].mutex));
2613 // Called by MainThread
2614 static void remove_whole_block_device(void)
2616 struct block_device *bdev;
2622 for (i = 0; i < THREAD_MAX; i++) {
2624 pthread_mutex_lock(&(th_manager[i].mutex));
2625 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2626 if (bdev->removed == false)
2629 pthread_mutex_unlock(&(th_manager[i].mutex));
2631 if (bdev && bdev->removed == false) {
2632 bdev->removed = true;
2633 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2635 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2637 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2639 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2646 static void booting_done(const char *sender_name,
2647 const char *object_path, const char *interface_name,
2648 const char *signal_name, DBusMessage *msg,
2651 static int done = 0;
2656 /* if there is the attached device, try to mount */
2657 block_init_from_udev_enumerate();
2658 block_control = true;
2662 static void block_poweroff(const char *sender_name,
2663 const char *object_path, const char *interface_name,
2664 const char *signal_name, DBusMessage *msg,
2667 static int status = 0;
2672 /* unregister mmc uevent control routine */
2673 unregister_udev_uevent_control(&uh);
2674 remove_whole_block_device();
2677 static void uevent_block_handler(struct udev_device *dev)
2679 const char *devnode = NULL;
2681 struct udev_list_entry *list_entry;
2683 bool mapper = false;
2685 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2686 const char *devlink = udev_list_entry_get_name(list_entry);
2687 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2691 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2699 devnode = udev_device_get_devnode(dev);
2703 if (fnmatch(MMC_PATH, devnode, 0) &&
2704 fnmatch(SCSI_PATH, devnode, 0))
2708 r = check_external_storage(devnode);
2712 action = udev_device_get_action(dev);
2716 _I("%s device %s", devnode, action);
2717 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2718 (mapper && !strcmp(action, UDEV_CHANGE))) {
2719 r = check_already_handled(devnode);
2721 _I("%s is already handled", devnode);
2725 add_block_device(dev, devnode, mapper);
2726 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2727 remove_block_device(dev, devnode);
2728 } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2729 struct block_device *bdev;
2730 bdev = find_block_device(devnode);
2732 _E("fail to find block data for %s", devnode);
2735 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2738 r = update_block_data(bdev->data,
2739 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2740 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2741 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2742 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2743 udev_device_get_sysattr_value(dev, "ro"),
2746 _E("fail to update block data for %s", bdev->data->devnode);
2747 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
2748 _I("filesystem type is updated: crypto_LUKS");
2752 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2753 DBusMessage *msg, bool onprivate)
2755 struct block_device *bdev;
2760 if (!reply_handle || !msg)
2763 ret = dbus_message_get_args(msg, NULL,
2764 DBUS_TYPE_INT32, &id,
2765 DBUS_TYPE_STRING, &mount_point,
2770 bdev = find_block_device_by_id(id);
2772 _E("Failed to find (%d) in the device list", id);
2776 if (bdev->on_private_op != REQ_NORMAL) {
2781 if (bdev->data->state == BLOCK_MOUNT) {
2782 _I("%s is already mounted", bdev->data->devnode);
2788 bdev->on_private_op = REQ_PRIVATE;
2789 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2790 _D("Private operation state: %d", bdev->on_private_op);
2792 if (bdev->on_private_op != REQ_NORMAL) {
2793 _E("Failed to process mount operation");
2799 /* if requester want to use a specific mount point */
2800 if (mount_point && strncmp(mount_point, "", 1) != 0) {
2801 ret = change_mount_point(bdev, mount_point);
2807 /* Create /run/external-storage/id file */
2808 create_file(bdev->data->id, bdev->data->mount_point, false);
2810 /* Create file for block device /run/external-storage/id */
2811 create_file(bdev->data->id, bdev->data->mount_point, false);
2814 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2816 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2823 return make_dbus_reply_message_simple(reply_handle, ret);
2826 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2829 return request_mount_block(reply_handle, msg, false);
2832 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2835 return request_mount_block(reply_handle, msg, true);
2838 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2839 DBusMessage *msg, bool onprivate)
2841 struct block_device *bdev;
2847 if (!reply_handle || !msg)
2850 ret = dbus_message_get_args(msg, NULL,
2851 DBUS_TYPE_INT32, &id,
2852 DBUS_TYPE_INT32, &option,
2857 bdev = find_block_device_by_id(id);
2859 _E("Failed to find (%d) in the device list", id);
2865 pid = get_dbus_method_sender_pid(reply_handle);
2866 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2867 _E("Failed to process private unmount operation");
2872 if (bdev->on_private_op != REQ_NORMAL) {
2873 _E("Failed to process unmount operation");
2879 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2881 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2885 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2886 ret = add_operation(bdev, BLOCK_LUKS_CLOSE, NULL, NULL);
2888 _E("Failed to add operation (luks_close %s)", bdev->data->devnode);
2894 return make_dbus_reply_message_simple(reply_handle, ret);
2897 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2900 return request_unmount_block(reply_handle, msg, false);
2903 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2906 return request_unmount_block(reply_handle, msg, true);
2909 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2912 struct block_device *bdev;
2913 struct format_data *fdata;
2920 if (!reply_handle || !msg)
2923 ret = dbus_message_get_args(msg, NULL,
2924 DBUS_TYPE_INT32, &id,
2925 DBUS_TYPE_INT32, &option,
2930 bdev = find_block_device_by_id(id);
2932 _E("Failed to find (%d) in the device list", id);
2936 pid = get_dbus_method_sender_pid(reply_handle);
2937 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2938 _E("Failed to format on private state");
2943 fdata = get_format_data(NULL, option);
2945 _E("Failed to get format data");
2949 prev_state = bdev->data->state;
2950 if (prev_state == BLOCK_MOUNT) {
2951 if (bdev->on_private_op == REQ_PRIVATE) {
2952 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2953 _D("Private operation state: %d", bdev->on_private_op);
2955 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2957 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2958 release_format_data(fdata);
2963 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2965 _E("Failed to add operation (format %s)", bdev->data->devnode);
2966 release_format_data(fdata);
2969 /* Maintain previous state of mount/unmount */
2970 if (prev_state == BLOCK_MOUNT) {
2971 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2972 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2980 return make_dbus_reply_message_simple(reply_handle, ret);
2983 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2986 struct block_device *bdev;
2987 struct format_data *fdata;
2995 if (!reply_handle || !msg)
2998 ret = dbus_message_get_args(msg, NULL,
2999 DBUS_TYPE_INT32, &id,
3000 DBUS_TYPE_INT32, &option,
3001 DBUS_TYPE_STRING, &type,
3006 bdev = find_block_device_by_id(id);
3008 _E("Failed to find (%d) in the device list", id);
3012 pid = get_dbus_method_sender_pid(reply_handle);
3013 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3014 _E("Failed to format on private state");
3019 fdata = get_format_data(type, option);
3021 _E("Failed to get format data");
3025 prev_state = bdev->data->state;
3026 if (prev_state == BLOCK_MOUNT) {
3027 if (bdev->on_private_op == REQ_PRIVATE) {
3028 bdev->on_private_op = REQ_PRIVATE_FORMAT;
3029 _D("Private operation state: %d", bdev->on_private_op);
3031 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3033 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3034 release_format_data(fdata);
3039 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3041 _E("Failed to add operation (format %s)", bdev->data->devnode);
3042 release_format_data(fdata);
3045 /* Maintain previous state of mount/unmount */
3046 if (prev_state == BLOCK_MOUNT) {
3047 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3048 _E("Failed to add operation (mount %s)", bdev->data->devnode);
3056 return make_dbus_reply_message_simple(reply_handle, ret);
3059 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3061 char *str_null = "";
3063 if (!data || !piter)
3066 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3067 &(data->block_type));
3068 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3069 data->devnode ? &(data->devnode) : &str_null);
3070 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3071 data->syspath ? &(data->syspath) : &str_null);
3072 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3073 data->fs_usage ? &(data->fs_usage) : &str_null);
3074 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3075 data->fs_type ? &(data->fs_type) : &str_null);
3076 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3077 data->fs_version ? &(data->fs_version) : &str_null);
3078 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3079 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3080 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3082 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3083 data->mount_point ? &(data->mount_point) : &str_null);
3084 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3086 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3088 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3090 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3097 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3099 DBusMessageIter piter;
3104 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3105 add_device_to_iter(data, &piter);
3106 dbus_message_iter_close_container(iter, &piter);
3111 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3113 DBusMessageIter piter;
3114 char *str_null = "";
3119 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3120 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3121 &(data->block_type));
3122 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3123 data->devnode ? &(data->devnode) : &str_null);
3124 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3125 data->syspath ? &(data->syspath) : &str_null);
3126 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3127 data->fs_usage ? &(data->fs_usage) : &str_null);
3128 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3129 data->fs_type ? &(data->fs_type) : &str_null);
3130 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3131 data->fs_version ? &(data->fs_version) : &str_null);
3132 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3133 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3134 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3136 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3137 data->mount_point ? &(data->mount_point) : &str_null);
3138 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3140 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3142 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3144 dbus_message_iter_close_container(iter, &piter);
3149 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3152 DBusMessageIter iter;
3154 struct block_device *bdev;
3155 struct block_data *data;
3158 if (!reply_handle || !msg)
3161 reply = make_dbus_reply_message(reply_handle);
3165 ret = dbus_message_get_args(msg, NULL,
3166 DBUS_TYPE_INT32, &id,
3171 bdev = find_block_device_by_id(id);
3178 dbus_message_iter_init_append(reply, &iter);
3179 add_device_to_iter(data, &iter);
3185 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3188 show_block_device_list();
3189 return make_dbus_reply_message(reply_handle);
3192 // Called by MainThread
3193 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3196 DBusMessageIter iter;
3197 DBusMessageIter aiter;
3199 struct block_device *bdev;
3200 struct block_data *data;
3207 reply = make_dbus_reply_message(reply_handle);
3209 ret = dbus_message_get_args(msg, NULL,
3210 DBUS_TYPE_STRING, &type,
3213 _E("Failed to get args");
3218 _E("Delivered type is NULL");
3222 _D("Block (%s) device list is requested", type);
3224 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3225 block_type = BLOCK_SCSI_DEV;
3226 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3227 block_type = BLOCK_MMC_DEV;
3228 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3231 _E("Invalid type (%s) is requested", type);
3235 dbus_message_iter_init_append(reply, &iter);
3236 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3238 for (i = 0; i < THREAD_MAX; i++) {
3239 pthread_mutex_lock(&(th_manager[i].mutex));
3240 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3247 switch (block_type) {
3248 case BLOCK_SCSI_DEV:
3250 if (data->block_type != block_type)
3256 add_device_to_struct_iter(data, &aiter);
3258 pthread_mutex_unlock(&(th_manager[i].mutex));
3260 dbus_message_iter_close_container(&iter, &aiter);
3266 // Called by MainThread
3267 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3270 DBusMessageIter iter;
3271 DBusMessageIter aiter;
3273 struct block_device *bdev;
3274 struct block_data *data;
3281 reply = make_dbus_reply_message(reply_handle);
3283 ret = dbus_message_get_args(msg, NULL,
3284 DBUS_TYPE_STRING, &type,
3287 _E("Failed to get args");
3292 _E("Delivered type is NULL");
3296 _D("Block (%s) device list is requested", type);
3298 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3299 block_type = BLOCK_SCSI_DEV;
3300 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3301 block_type = BLOCK_MMC_DEV;
3302 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3305 _E("Invalid type (%s) is requested", type);
3309 dbus_message_iter_init_append(reply, &iter);
3310 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3312 for (i = 0; i < THREAD_MAX; i++) {
3313 pthread_mutex_lock(&(th_manager[i].mutex));
3314 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3321 switch (block_type) {
3322 case BLOCK_SCSI_DEV:
3324 if (data->block_type != block_type)
3331 add_device_to_iter_2(data, &aiter);
3333 pthread_mutex_unlock(&(th_manager[i].mutex));
3335 dbus_message_iter_close_container(&iter, &aiter);
3341 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3344 DBusMessageIter iter;
3346 struct block_device *bdev;
3347 struct block_data *data, nodata = {0,};
3352 if (!reply_handle || !msg)
3355 reply = make_dbus_reply_message(reply_handle);
3360 for (i = 0; i < THREAD_MAX; i++) {
3361 pthread_mutex_lock(&(th_manager[i].mutex));
3362 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3368 if (data->block_type != BLOCK_MMC_DEV &&
3369 data->block_type != BLOCK_EXTENDEDSD_DEV)
3373 // Return mapper node(/dev/mapper/extendedsd) for primary mmc (not /dev/mmcblk1p1(ex))
3374 if (!strncmp(data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
3379 pthread_mutex_unlock(&(th_manager[i].mutex));
3384 dbus_message_iter_init_append(reply, &iter);
3386 add_device_to_iter(data, &iter);
3388 nodata.id = -ENODEV;
3389 add_device_to_iter(&nodata, &iter);
3396 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3399 struct timespec start_time, end_time;
3400 DBusMessageIter iter;
3402 struct block_device *bdev;
3403 struct block_data *data;
3410 if (!reply_handle || !msg)
3413 ret = dbus_message_get_args(msg, NULL,
3414 DBUS_TYPE_INT32, &id,
3421 bdev = find_block_device_by_id(id);
3432 _D("speed check: %s", data->devnode);
3433 fd = open(data->devnode, O_RDWR | O_SYNC);
3434 buf = calloc(1, SPEEDCHECK << 20);
3436 _E("calloc() failed");
3441 clock_gettime(CLOCK_REALTIME, &start_time);
3442 _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3443 ret = write(fd, buf, SPEEDCHECK << 20);
3444 clock_gettime(CLOCK_REALTIME, &end_time);
3445 _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3449 time_diff = end_time.tv_sec - start_time.tv_sec;
3450 if (time_diff > 0 && (SPEEDCHECK / time_diff < 4)) {
3457 _E("write() failed %d", errno);
3464 reply = dbus_message_new_method_return(msg);
3465 dbus_message_iter_init_append(reply, &iter);
3466 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3471 static DBusMessage *request_control_block(dbus_method_reply_handle_h reply_handle,
3477 DBusMessageIter iter;
3479 ret = dbus_message_get_args(msg, NULL,
3480 DBUS_TYPE_INT32, &enable,
3488 _I("control block Enable");
3490 } else if (enable == 0) {
3491 _I("control block Disable");
3494 _E("control block : Wrong request by client");
3500 reply = dbus_message_new_method_return(msg);
3501 dbus_message_iter_init_append(reply, &iter);
3502 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3507 static DBusMessage *request_getcontrol_block(dbus_method_reply_handle_h reply_handle,
3512 DBusMessageIter iter;
3514 _I("getcontrol block");
3516 is_enabled = block_control;
3518 reply = dbus_message_new_method_return(msg);
3519 dbus_message_iter_init_append(reply, &iter);
3520 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &is_enabled);
3526 Method name Method call format string Reply format string
3527 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3528 { "GetDeviceList", "s", "a(issssssisibii)", request_get_device_list },
3529 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3530 { "Mount", "is", "i", request_public_mount_block },
3531 { "Unmoun, "ii", "i", request_public_unmount_block },
3532 { "Format", "ii", "i", request_format_block },
3533 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3534 { "GetMmcPrimary", NULL, "(issssssisibii)" , request_get_mmc_primary },
3535 { "PrivateMount", "is", "i", request_private_mount_block },
3536 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3539 static const dbus_method_s manager_methods[] = {
3540 { "ShowDeviceList", NULL, request_show_device_list },
3541 { "GetDeviceList" , "s", request_get_device_list },
3542 { "GetDeviceList2", "s", request_get_device_list_2 },
3543 { "Mount", "is", request_public_mount_block },
3544 { "Unmount", "ii", request_public_unmount_block },
3545 { "Format", "ii", request_format_block },
3546 { "FormatwithType", "iis", request_format_block_type },
3547 { "GetDeviceInfo", "i", request_get_device_info },
3548 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3549 { "PrivateMount", "is", request_private_mount_block },
3550 { "PrivateUnmount", "ii", request_private_unmount_block },
3551 { "CheckSpeed", "i", request_check_speed },
3552 { "Control", "i", request_control_block },
3553 { "GetControl", "i", request_getcontrol_block },
3556 static dbus_interface_s block_interface = {
3557 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3558 .methods = manager_methods,
3559 .nr_methods = ARRAY_SIZE(manager_methods),
3562 static int load_config(struct parse_result *result, void *user_data)
3566 if (MATCH(result->section, "Block"))
3569 if (MATCH(result->section, "SCSI"))
3570 index = BLOCK_SCSI_DEV;
3571 else if (MATCH(result->section, "MMC"))
3572 index = BLOCK_MMC_DEV;
3573 else if (MATCH(result->section, "Mapper"))
3574 index = BLOCK_EXTENDEDSD_DEV;
3578 if (MATCH(result->name, "Multimount"))
3579 block_conf[index].multimount =
3580 (MATCH(result->value, "yes") ? true : false);
3581 if (MATCH(result->name, "ExtendedInternalStorage"))
3582 block_conf[index].extendedinternal =
3583 (MATCH(result->value, "yes") ? true : false);
3589 static int mount_root_path_tmpfs(void)
3594 root = tzplatform_getenv(TZ_SYS_MEDIA);
3598 if (access(root, F_OK) != 0)
3601 if (mount_check(root))
3604 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3607 _E("tmpfs mount failed (%d)", ret);
3614 #define mount_root_path_tmpfs() 0
3617 static void block_init(void *data)
3622 dbus_handle_h handle;
3627 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3629 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3631 ret = mount_root_path_tmpfs();
3633 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3635 ret = dbus_get_connection(&handle);
3637 _E("Failed to get dbus connection(%d)", ret);
3639 /* register block manager object and interface */
3640 ret = register_dbus_methods(handle,
3641 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3644 _E("Failed to register block interface and methods (%d)", ret);
3649 _E("fail to init pipe");
3651 /* register mmc uevent control routine */
3652 ret = register_udev_uevent_control(&uh);
3654 _E("fail to register block uevent : %d", ret);
3656 /* System Session is loaded completely */
3657 register_dbus_signal(SYSTEMD_DBUS_PATH,
3658 SYSTEMD_DBUS_IFACE_MANAGER,
3659 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3660 booting_done, NULL, NULL);
3662 register_dbus_signal(DEVICED_PATH_POWEROFF,
3663 DEVICED_INTERFACE_POWEROFF,
3664 SIGNAL_POWEROFF_STATE,
3665 block_poweroff, NULL, NULL);
3667 for (i = 0; i < THREAD_MAX; i++) {
3668 th_manager[i].num_dev = 0;
3669 th_manager[i].op_len = 0;
3670 th_manager[i].start_th = true;
3671 th_manager[i].thread_id = i;
3672 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3673 pthread_cond_init(&(th_manager[i].cond), NULL);
3676 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3678 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3680 _E("Failed to make directory: %d", errno);
3681 } else if (!S_ISDIR(buf.st_mode)) {
3682 ret = remove(EXTERNAL_STORAGE_PATH);
3684 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3685 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3687 _E("Failed to make directory: %d", errno);
3689 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3691 _E("Fail to change permissions of a file");
3694 ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3696 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3698 _E("Failed to make directory: %d", errno);
3699 } else if (!S_ISDIR(buf.st_mode)) {
3700 ret = remove(EXTENDED_INTERNAL_PATH);
3702 _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3703 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3705 _E("Failed to make directory: %d", errno);
3707 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3709 _E("Fail to change permissions of a file");
3713 static void block_exit(void *data)
3715 dd_list *elem, *elem_next;
3721 /* unregister notifier for below each event */
3722 unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3723 SYSTEMD_DBUS_IFACE_MANAGER,
3724 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3727 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3728 DEVICED_INTERFACE_POWEROFF,
3729 SIGNAL_POWEROFF_STATE, block_poweroff);
3734 /* unregister mmc uevent control routine */
3735 ret = unregister_udev_uevent_control(&uh);
3737 _E("fail to unregister block uevent : %d", ret);
3739 /* remove remaining blocks */
3740 remove_whole_block_device();
3742 for (i = 0; i < THREAD_MAX; i++) {
3743 if (!th_manager[i].start_th)
3744 pthread_cancel(th_manager[i].th);
3745 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3746 DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3751 block_control = false;
3754 static int block_start(void *data)
3759 _E("Cannot be started. Booting is not ready");
3763 if (block_control) {
3764 _I("Already started");
3768 /* register mmc uevent control routine */
3769 ret = register_udev_uevent_control(&uh);
3771 _E("fail to register block uevent : %d", ret);
3773 block_init_from_udev_enumerate();
3775 block_control = true;
3781 static int block_stop(void *data)
3784 _E("Cannot be stopped. Booting is not ready");
3788 if (!block_control) {
3789 _I("Already stopped");
3793 /* unregister mmc uevent control routine */
3794 unregister_udev_uevent_control(&uh);
3796 /* remove the existing blocks */
3797 remove_whole_block_device();
3799 block_control = false;
3805 static storaged_module_interface block_module = {
3809 .start = block_start,
3813 __attribute__ ((visibility("default")))storaged_module_interface *
3814 storaged_get_module_interface(void)
3816 return &block_module;