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 "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"
98 #define EXTENDEDSD_STRING "ExtendedInternalSD"
100 #define EXT4_NAME "ext4"
101 #define LUKS_NAME "crypto_LUKS"
102 #define EXTENDEDSD_NAME "extendedsd"
104 /* Minimum value of block id */
105 #define BLOCK_ID_MIN 10
106 /* For 2.4 Backward Compatibility */
107 #define EXT_PRIMARY_SD_FIXID 1
109 /* Maximum number of thread */
112 #define SPEEDCHECK 16
114 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
115 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
116 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
118 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
120 enum block_dev_operation {
129 enum private_operation_state {
135 struct operation_queue {
136 enum block_dev_operation op;
137 dbus_method_reply_handle_h reply_handle;
142 struct block_device {
143 struct block_data *data;
145 int thread_id; /* Current thread ID */
146 bool removed; /* True when device is physically removed but operation is not precessed yet */
147 enum private_operation_state on_private_op;
148 bool mount_point_updated;
153 struct block_device *bdev;
155 enum unmount_operation option;
159 enum block_dev_operation op;
160 struct block_device *bdev;
164 static struct block_conf {
166 bool extendedinternal;
167 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
169 static struct manage_thread {
170 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
171 dd_list *block_dev_list; /* Use thread mutex */
173 pthread_mutex_t mutex;
175 int num_dev; /* Number of devices which thread holds. Only main thread access */
176 int op_len; /* Number of operation of thread. Use thread mutex */
177 int thread_id; /* Never changed */
179 } th_manager[THREAD_MAX];
181 static dd_list *fs_head;
182 static dd_list *block_ops_list;
185 static fd_handler_h phandler;
186 static bool block_control = false;
187 static bool block_boot = false;
188 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
190 /* Assume there is only one physical internal storage */
191 static int dev_internal = -1;
192 static char dev_internal_scsi = '\0';
193 static char dev_internal_emul = '\0';
195 static int add_operation(struct block_device *bdev,
196 enum block_dev_operation operation,
197 dbus_method_reply_handle_h reply_handle, void *data);
198 static void remove_operation(struct block_device *bdev);
199 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
200 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
201 static int change_mount_point(struct block_device *bdev, const char *mount_point);
203 static void uevent_block_handler(struct udev_device *dev);
204 static struct uevent_handler uh = {
205 .subsystem = BLOCK_SUBSYSTEM,
206 .uevent_func = uevent_block_handler,
209 static void __CONSTRUCTOR__ smack_check(void)
214 fp = fopen("/proc/filesystems", "r");
218 while (fgets(buf, sizeof(buf), fp) != NULL) {
219 if (strstr(buf, "smackfs")) {
228 void add_fs(const struct block_fs_ops *fs)
230 DD_LIST_APPEND(fs_head, (void *)fs);
233 void remove_fs(const struct block_fs_ops *fs)
235 DD_LIST_REMOVE(fs_head, (void *)fs);
238 const struct block_fs_ops *find_fs(enum block_fs_type type)
240 struct block_fs_ops *fs;
243 DD_LIST_FOREACH(fs_head, elem, fs) {
244 if (fs->type == type)
250 void add_block_dev(const struct block_dev_ops *ops)
252 DD_LIST_APPEND(block_ops_list, (void *)ops);
255 void remove_block_dev(const struct block_dev_ops *ops)
257 DD_LIST_REMOVE(block_ops_list, (void *)ops);
260 static void broadcast_block_info(enum block_dev_operation op,
261 struct block_data *data, int result)
263 struct block_dev_ops *ops;
266 if (data->primary != true)
269 DD_LIST_FOREACH(block_ops_list, elem, ops) {
270 if (ops->block_type != data->block_type)
272 // TODO What happend on extended internal storage case?
273 if (op == BLOCK_DEV_MOUNT) {
274 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
275 ops->mounted(data, result, true);
277 ops->mounted(data, result, false);
278 } else if (op == BLOCK_DEV_UNMOUNT) {
279 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
280 ops->unmounted(data, result, true);
282 ops->unmounted(data, result, false);
283 } else if (op == BLOCK_DEV_FORMAT) {
284 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
285 ops->formatted(data, result, true);
287 ops->formatted(data, result, false);
288 } else if (op == BLOCK_DEV_INSERT)
290 else if (op == BLOCK_DEV_REMOVE)
295 // Called by MainThread - Insert
296 static int block_get_new_id(void)
298 static int id = BLOCK_ID_MIN;
299 struct block_device *bdev;
304 for (i = 0 ; i < INT_MAX ; i++) {
306 for (j = 0; j < THREAD_MAX; j++) {
307 pthread_mutex_lock(&(th_manager[j].mutex));
308 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
309 if (bdev->data->id == id) {
314 pthread_mutex_unlock(&(th_manager[j].mutex));
329 static void remove_file(int id, bool extendedsd)
331 char file_name[PATH_LEN];
338 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
340 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
342 ret = remove(file_name);
344 _E("Fail to remove %s. errno: %d", file_name, errno);
347 static void create_file(int id, char *mount_point, bool extendedsd)
350 char file_name[PATH_LEN];
356 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
358 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
360 fp = fopen(file_name, "w+");
362 fprintf(fp, "%s", mount_point);
365 _E("Fail to open %s", file_name);
368 static void signal_device_blocked(struct block_device *bdev)
370 struct block_data *data;
372 char str_block_type[32];
373 char str_readonly[32];
375 char str_primary[32];
381 if (!bdev || !bdev->data)
387 /* Broadcast outside with BlockManager iface */
388 snprintf(str_block_type, sizeof(str_block_type),
389 "%d", data->block_type);
390 arr[0] = str_block_type;
391 arr[1] = (data->devnode ? data->devnode : str_null);
392 arr[2] = (data->syspath ? data->syspath : str_null);
393 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
394 arr[4] = (data->fs_type ? data->fs_type : str_null);
395 arr[5] = (data->fs_version ? data->fs_version : str_null);
396 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
397 snprintf(str_readonly, sizeof(str_readonly),
398 "%d", data->readonly);
399 arr[7] = str_readonly;
400 arr[8] = (data->mount_point ? data->mount_point : str_null);
401 snprintf(str_state, sizeof(str_state),
404 snprintf(str_primary, sizeof(str_primary),
405 "%d", data->primary);
406 arr[10] = str_primary;
407 snprintf(str_flags, sizeof(str_flags), "%d", flags);
409 snprintf(str_id, sizeof(str_id), "%d", data->id);
412 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
413 STORAGED_INTERFACE_BLOCK_MANAGER,
414 BLOCK_DEVICE_BLOCKED,
415 "issssssisibii", arr);
418 static void signal_device_changed(struct block_device *bdev,
419 enum block_dev_operation op)
421 struct block_data *data;
423 char str_block_type[32];
424 char str_readonly[32];
426 char str_primary[32];
432 if (!bdev || !bdev->data)
438 case BLOCK_DEV_MOUNT:
439 BLOCK_GET_MOUNT_FLAGS(data, flags);
441 case BLOCK_DEV_UNMOUNT:
442 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
444 case BLOCK_DEV_FORMAT:
445 BLOCK_GET_FORMAT_FLAGS(data, flags);
452 /* Broadcast outside with BlockManager iface */
453 snprintf(str_block_type, sizeof(str_block_type),
454 "%d", data->block_type);
455 arr[0] = str_block_type;
456 arr[1] = (data->devnode ? data->devnode : str_null);
457 arr[2] = (data->syspath ? data->syspath : str_null);
458 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
459 arr[4] = (data->fs_type ? data->fs_type : str_null);
460 arr[5] = (data->fs_version ? data->fs_version : str_null);
461 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
462 snprintf(str_readonly, sizeof(str_readonly),
463 "%d", data->readonly);
464 arr[7] = str_readonly;
465 arr[8] = (data->mount_point ? data->mount_point : str_null);
466 snprintf(str_state, sizeof(str_state),
469 snprintf(str_primary, sizeof(str_primary),
470 "%d", data->primary);
471 arr[10] = str_primary;
472 snprintf(str_flags, sizeof(str_flags), "%d", flags);
474 snprintf(str_id, sizeof(str_id), "%d", data->id);
477 if (op == BLOCK_DEV_INSERT)
478 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
479 STORAGED_INTERFACE_BLOCK_MANAGER,
481 "issssssisibii", arr);
482 else if (op == BLOCK_DEV_REMOVE)
483 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
484 STORAGED_INTERFACE_BLOCK_MANAGER,
485 BLOCK_DEVICE_REMOVED,
486 "issssssisibii", arr);
488 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
489 STORAGED_INTERFACE_BLOCK_MANAGER,
490 BLOCK_DEVICE_CHANGED,
491 "issssssisibii", arr);
492 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
493 STORAGED_INTERFACE_BLOCK_MANAGER,
494 BLOCK_DEVICE_CHANGED_2,
495 "issssssisibi", arr);
499 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
501 char *name = devnode;
502 int dev = -1, part = -1;
503 char emul[32] = { 0, };
510 sscanf(name, "mmcblk%dp%d", &dev, &part);
513 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
515 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
520 sscanf(name, "vd%31s", emul);
523 for (i = 0 ; i < strlen(emul) ; i++)
524 emul[i] = toupper(emul[i]);
525 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
529 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
537 snprintf(dev, sizeof(dev), "%s", devnode);
539 if (!strstr(dev, "sd"))
543 name += strlen("sd");
545 for (i = 0 ; i < strlen(name) ; i++)
546 name[i] = toupper(name[i]);
547 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
552 static char *generate_mount_path(struct block_data *data)
555 char *name, node[64];
558 if (!data || !data->devnode || !data->fs_usage || strcmp(data->fs_usage, FILESYSTEM))
561 name = strrchr(data->devnode, '/');
566 switch (data->block_type) {
568 ret = get_mmc_mount_node(name, node, sizeof(node));
571 ret = get_scsi_mount_node(name, node, sizeof(node));
573 case BLOCK_EXTENDEDSD_DEV:
574 return strdup(EXTENDEDSD_MOUNT_PATH);
576 _E("Invalid block type (%d)", data->block_type);
582 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
588 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
592 static bool check_primary_partition(const char *devnode)
594 struct block_fs_ops *fs;
597 const char *filesystem = NULL;
607 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
608 fnmatch(MMC_PATH, devnode, 0) &&
609 fnmatch(SCSI_PATH, devnode, 0) &&
610 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
613 temp = strrchr(devnode, '/');
616 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
617 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
620 /* Emulator support only one partition */
624 snprintf(str, sizeof(str), "%s", devnode);
629 for (i = 1; i <= 9; ++i) {
630 snprintf(str2, sizeof(str2), "%s%d", str, i);
631 if (access(str2, R_OK) != 0)
634 probe = blkid_new_probe_from_filename(str2);
637 if (blkid_do_probe(probe) != 0)
640 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
642 blkid_free_probe(probe);
645 DD_LIST_FOREACH(fs_head, elem, fs) {
646 if (!strncmp(fs->name, filesystem, fs_len)) {
651 blkid_free_probe(probe);
657 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
663 /* Whole data in struct block_data should be freed. */
664 static struct block_data *make_block_data(const char *devnode,
666 const char *fs_usage,
668 const char *fs_version,
669 const char *fs_uuid_enc,
670 const char *readonly)
672 struct block_data *data;
674 /* devnode is unique value so it should exist. */
679 _I("Unknown fs type");
681 data = calloc(1, sizeof(struct block_data));
683 _E("calloc() failed");
687 data->devnode = strdup(devnode);
689 data->syspath = strdup(syspath);
691 data->fs_usage = strdup(fs_usage);
693 data->fs_type = strdup(fs_type);
695 data->fs_version = strdup(fs_version);
697 data->fs_uuid_enc = strdup(fs_uuid_enc);
699 data->readonly = atoi(readonly);
700 data->primary = check_primary_partition(devnode);
702 /* TODO should we know block dev type? */
703 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
704 data->block_type = BLOCK_MMC_DEV;
705 else if (!fnmatch(MMC_PATH, devnode, 0))
706 data->block_type = BLOCK_MMC_DEV;
707 else if (!fnmatch(SCSI_PATH, devnode, 0))
708 data->block_type = BLOCK_SCSI_DEV;
709 else if (!fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
710 data->block_type = BLOCK_EXTENDEDSD_DEV;
712 data->block_type = -1;
714 data->mount_point = generate_mount_path(data);
715 BLOCK_FLAG_CLEAR_ALL(data);
717 /* for 2.4 backward compatibility */
718 // What if storage id 1 is existed? (multi sdcard case)
719 if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
720 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM))
721 data->id = EXT_PRIMARY_SD_FIXID;
723 data->id = block_get_new_id();
728 static void free_block_data(struct block_data *data)
734 free(data->fs_usage);
736 free(data->fs_version);
737 free(data->fs_uuid_enc);
738 free(data->mount_point);
742 static int update_block_data(struct block_data *data,
743 const char *fs_usage,
745 const char *fs_version,
746 const char *fs_uuid_enc,
747 const char *readonly,
748 bool mount_point_updated)
753 free(data->fs_usage);
754 data->fs_usage = NULL;
756 data->fs_usage = strdup(fs_usage);
759 data->fs_type = NULL;
761 data->fs_type = strdup(fs_type);
763 free(data->fs_version);
764 data->fs_version = NULL;
766 data->fs_version = strdup(fs_version);
768 free(data->fs_uuid_enc);
769 data->fs_uuid_enc = NULL;
771 data->fs_uuid_enc = strdup(fs_uuid_enc);
773 /* generate_mount_path function should be invoked
774 * after fs_uuid_enc is updated */
775 if (!mount_point_updated) {
776 free(data->mount_point);
777 data->mount_point = generate_mount_path(data);
780 data->readonly = false;
782 data->readonly = atoi(readonly);
784 BLOCK_FLAG_MOUNT_CLEAR(data);
789 static struct block_device *make_block_device(struct block_data *data)
791 struct block_device *bdev;
796 bdev = calloc(1, sizeof(struct block_device));
801 bdev->thread_id = -1;
802 bdev->removed = false;
803 bdev->on_private_op = REQ_NORMAL;
804 bdev->private_pid = 0;
805 bdev->mount_point_updated = false;
810 // Called by MainThread - Remove DevNode
811 static void free_block_device(struct block_device *bdev)
814 struct operation_queue *op;
820 thread_id = bdev->thread_id;
821 if (thread_id < 0 || thread_id >= THREAD_MAX)
824 pthread_mutex_lock(&(th_manager[thread_id].mutex));
826 th_manager[thread_id].num_dev--;
827 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
828 free_block_data(bdev->data);
830 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
832 th_manager[thread_id].op_len--;
833 DD_LIST_REMOVE(bdev->op_queue, op);
836 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
841 // Called By MainThread - Remove Device
842 static struct block_device *find_block_device(const char *devnode)
844 struct block_device *bdev;
849 len = strlen(devnode) + 1;
850 for (i = 0; i < THREAD_MAX; i++) {
851 pthread_mutex_lock(&(th_manager[i].mutex));
852 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
853 if (bdev->data && !bdev->removed &&
854 !strncmp(bdev->data->devnode, devnode, len)) {
855 pthread_mutex_unlock(&(th_manager[i].mutex));
859 pthread_mutex_unlock(&(th_manager[i].mutex));
865 // Called By MainThread - Remove Device
866 static struct block_device *find_block_device_path(const char *mount_point)
868 struct block_device *bdev;
873 len = strlen(mount_point) + 1;
874 for (i = 0; i < THREAD_MAX; i++) {
875 pthread_mutex_lock(&(th_manager[i].mutex));
876 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
877 if (bdev->data && !bdev->removed &&
878 !strncmp(bdev->data->mount_point, mount_point, len)) {
879 pthread_mutex_unlock(&(th_manager[i].mutex));
883 pthread_mutex_unlock(&(th_manager[i].mutex));
889 // Called By MainThread - Mount,Unmount,Format,GetInfo
890 static struct block_device *find_block_device_by_id(int id)
892 struct block_device *bdev;
896 for (i = 0; i < THREAD_MAX; i++) {
897 pthread_mutex_lock(&(th_manager[i].mutex));
898 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
903 if (bdev->data->id == id) {
904 pthread_mutex_unlock(&(th_manager[i].mutex));
908 pthread_mutex_unlock(&(th_manager[i].mutex));
914 static char *get_operation_char(enum block_dev_operation op,
915 char *name, unsigned int len)
917 char *str = "unknown";
923 case BLOCK_DEV_MOUNT:
926 case BLOCK_DEV_UNMOUNT:
929 case BLOCK_DEV_FORMAT:
932 case BLOCK_DEV_INSERT:
935 case BLOCK_DEV_REMOVE:
939 _E("invalid operation (%d)", op);
943 snprintf(name, len, "%s", str);
947 static void create_external_apps_directory(void)
951 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
952 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
953 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
955 _E("Fail to create external directory");
958 static int pipe_trigger(enum block_dev_operation op,
959 struct block_device *bdev, int result)
961 struct pipe_data pdata = { op, bdev, result };
965 _D("op : %s, bdev : %p, result : %d",
966 get_operation_char(pdata.op, name, sizeof(name)),
967 pdata.bdev, pdata.result);
969 // Multi thread should not write at the same time
970 pthread_mutex_lock(&pipe_mutex);
971 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
972 pthread_mutex_unlock(&pipe_mutex);
974 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
977 static bool pipe_cb(int fd, void *data)
979 struct pipe_data pdata = {0,};
985 n = read(fd, &pdata, sizeof(pdata));
986 if (n != sizeof(pdata) || !pdata.bdev) {
987 _E("fail to read struct pipe data");
991 _I("op : %s, bdev : %p, result : %d",
992 get_operation_char(pdata.op, name, sizeof(name)),
993 pdata.bdev, pdata.result);
995 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
996 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
997 ret = change_mount_point(pdata.bdev, "");
998 /* Modify /run/external-storage/id file */
1000 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
1001 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
1003 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
1008 if (pdata.op == BLOCK_DEV_MOUNT &&
1009 pdata.bdev->data->state == BLOCK_MOUNT &&
1010 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
1011 pdata.bdev->data->primary)
1012 create_external_apps_directory();
1013 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1014 /* Remove file for block device /run/xxxxxx/id */
1015 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
1018 /* Broadcast to mmc and usb storage module */
1019 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
1021 /* Broadcast outside with Block iface */
1022 if (pdata.bdev->on_private_op == REQ_NORMAL)
1023 signal_device_changed(pdata.bdev, pdata.op);
1024 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
1025 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1026 pdata.bdev->on_private_op = REQ_NORMAL;
1027 _D("Private operation state: %d", pdata.bdev->on_private_op);
1030 if (pdata.op == BLOCK_DEV_MOUNT) {
1031 pdata.bdev->on_private_op = REQ_PRIVATE;
1032 _D("Private operation state: %d", pdata.bdev->on_private_op);
1036 if (pdata.op == BLOCK_DEV_REMOVE) {
1037 thread_id = pdata.bdev->thread_id;
1038 if (thread_id < 0 || thread_id >= THREAD_MAX)
1040 free_block_device(pdata.bdev);
1047 static int pipe_init(void)
1051 ret = pipe2(pfds, O_CLOEXEC);
1055 ret = add_fd_read_handler(pfds[0], pipe_cb,
1056 NULL, NULL, &phandler);
1058 _E("Failed to add pipe handler (%d)", ret);
1065 static void pipe_exit(void)
1068 remove_fd_read_handler(&phandler);
1078 static int mmc_check_and_unmount(const char *path)
1086 while (mount_check(path)) {
1090 if (retry > UNMOUNT_RETRY)
1097 static bool check_rw_mount(const char *szPath)
1099 struct statvfs mount_stat;
1101 if (!statvfs(szPath, &mount_stat)) {
1102 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1108 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1111 struct udev_device *dev;
1118 for (wait = 0; wait < 10; wait++) {
1121 _E("fail to create udev library context");
1125 dev = udev_device_new_from_syspath(udev, data->syspath);
1127 _E("fail to create new udev device");
1132 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
1137 udev_device_unref(dev);
1141 r = update_block_data(data,
1142 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1143 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1144 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1145 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1146 udev_device_get_sysattr_value(dev, "ro"),
1147 mount_point_updated);
1149 _E("fail to update block data for %s", data->devnode);
1151 udev_device_unref(dev);
1156 static int block_mount(struct block_data *data)
1158 struct block_fs_ops *fs;
1163 if (!data || !data->devnode || !data->mount_point)
1166 /* check existing mounted */
1167 if (mount_check(data->mount_point))
1170 /* create mount point */
1171 if (access(data->mount_point, R_OK) != 0) {
1172 if (mkdir(data->mount_point, 0755) < 0)
1176 /* check matched file system */
1177 if (!data->fs_usage ||
1178 strncmp(data->fs_usage, FILESYSTEM,
1179 sizeof(FILESYSTEM)) != 0) {
1184 if (!data->fs_type) {
1185 _E("There is no file system");
1186 BLOCK_FLAG_SET(data, FS_EMPTY);
1192 len = strlen(data->fs_type) + 1;
1193 DD_LIST_FOREACH(fs_head, elem, fs) {
1194 if (!strncmp(fs->name, data->fs_type, len))
1199 _E("Not supported file system (%s)", data->fs_type);
1200 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1205 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1206 r = fs->mount(false, data->devnode, data->mount_point);
1208 r = fs->mount(smack, data->devnode, data->mount_point);
1211 BLOCK_FLAG_SET(data, FS_BROKEN);
1216 r = check_rw_mount(data->mount_point);
1223 rmdir(data->mount_point);
1227 static int mount_start(struct block_device *bdev)
1229 struct block_data *data;
1237 _I("Mount Start : (%s -> %s)",
1238 data->devnode, data->mount_point);
1240 /* mount operation */
1241 r = block_mount(data);
1242 if (r != -EROFS && r < 0) {
1243 _E("fail to mount %s device : %d", data->devnode, r);
1248 data->readonly = true;
1249 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1252 data->state = BLOCK_MOUNT;
1254 if (data->block_type == BLOCK_MMC_DEV) {
1255 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1256 ret = app2ext_migrate_legacy_all();
1258 _E("app2ext failed");
1262 if (r < 0 && r != -EROFS)
1263 data->state = BLOCK_UNMOUNT;
1265 _I("%s result : %s, %d", __func__, data->devnode, r);
1267 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1268 _E("fail to trigger pipe");
1273 static int change_mount_point(struct block_device *bdev,
1274 const char *mount_point)
1276 struct block_data *data;
1282 free(data->mount_point);
1284 /* If the mount path already exists, the path cannot be used */
1286 access(mount_point, F_OK) != 0) {
1287 data->mount_point = strdup(mount_point);
1288 bdev->mount_point_updated = true;
1290 data->mount_point = generate_mount_path(data);
1291 bdev->mount_point_updated = false;
1297 static int mount_block_device(struct block_device *bdev)
1299 struct block_data *data;
1302 if (!bdev || !bdev->data)
1306 if (data->state == BLOCK_MOUNT) {
1307 _I("%s is already mounted", data->devnode);
1311 if (!block_conf[data->block_type].multimount &&
1313 _I("Not support multi mount by config info");
1317 r = mount_start(bdev);
1319 _E("Failed to mount (%s)", data->devnode);
1326 static int block_unmount(struct block_device *bdev,
1327 enum unmount_operation option)
1329 struct block_data *data;
1331 struct timespec time = {0,};
1333 if (!bdev || !bdev->data || !bdev->data->mount_point)
1338 if (bdev->on_private_op == REQ_NORMAL)
1339 signal_device_blocked(bdev);
1341 /* it must called before unmounting mmc */
1342 r = mmc_check_and_unmount(data->mount_point);
1345 if (option == UNMOUNT_NORMAL) {
1346 _I("Failed to unmount with normal option : %d", r);
1350 _I("Execute force unmount!");
1351 /* Force Unmount Scenario */
1356 * should unmount the below vconf key. */
1357 if ((data->block_type == BLOCK_MMC_DEV ||
1358 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1360 /* At first, notify to other app
1361 * who already access sdcard */
1362 _I("Notify to other app who already access sdcard");
1363 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1364 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1368 /* Second, kill app with SIGTERM */
1369 _I("Kill app with SIGTERM");
1370 terminate_process(data->mount_point, false);
1373 /* Last time, kill app with SIGKILL */
1374 _I("Kill app with SIGKILL");
1375 terminate_process(data->mount_point, true);
1378 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1379 _I("Failed to unmount with lazy option : %d",
1386 /* it takes some seconds til other app completely clean up */
1387 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1388 nanosleep(&time, NULL);
1390 print_open_files(data->mount_point);
1392 r = mmc_check_and_unmount(data->mount_point);
1394 _D("Success to unmount (%s)", data->mount_point);
1400 data->state = BLOCK_UNMOUNT;
1402 if (rmdir(data->mount_point) < 0)
1403 _E("fail to remove %s directory", data->mount_point);
1408 static int unmount_block_device(struct block_device *bdev,
1409 enum unmount_operation option)
1411 struct block_data *data;
1414 if (!bdev || !bdev->data)
1418 if (data->state == BLOCK_UNMOUNT) {
1419 _I("%s is already unmounted", data->devnode);
1420 r = mmc_check_and_unmount(data->mount_point);
1422 _E("The path was existed, but could not delete it(%s)",
1427 _I("Unmount Start : (%s -> %s)",
1428 data->devnode, data->mount_point);
1430 r = block_unmount(bdev, option);
1432 _E("fail to unmount %s device : %d", data->devnode, r);
1436 BLOCK_FLAG_MOUNT_CLEAR(data);
1439 _I("%s result : %s, %d", __func__, data->devnode, r);
1441 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1442 _E("fail to trigger pipe");
1447 static int block_format(struct block_data *data,
1448 const char *fs_type, bool mount_point_updated)
1450 const struct block_fs_ops *fs;
1456 if (!data || !data->devnode || !data->mount_point)
1459 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1465 fstype = data->fs_type;
1471 len = strlen(fstype);
1472 DD_LIST_FOREACH(fs_head, elem, fs) {
1473 if (!strncmp(fs->name, fstype, len))
1478 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1479 _E("not supported file system(%s)", fstype);
1483 _I("format path : %s", data->devnode);
1484 fs->check(data->devnode);
1485 r = fs->format(data->devnode);
1487 _E("fail to format block data for %s", data->devnode);
1491 /* need to update the partition data.
1492 * It can be changed in doing format. */
1493 retrieve_udev_device(data, mount_point_updated);
1498 static int format_block_device(struct block_device *bdev,
1499 const char *fs_type,
1500 enum unmount_operation option)
1502 struct block_data *data;
1510 _I("Format Start : (%s -> %s)",
1511 data->devnode, data->mount_point);
1513 if (data->state == BLOCK_MOUNT) {
1514 r = block_unmount(bdev, option);
1516 _E("fail to unmount %s device : %d", data->devnode, r);
1521 r = block_format(data, fs_type, bdev->mount_point_updated);
1523 _E("fail to format %s device : %d", data->devnode, r);
1526 _I("%s result : %s, %d", __func__, data->devnode, r);
1528 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1530 _E("fail to trigger pipe");
1535 static struct format_data *get_format_data(
1536 const char *fs_type, enum unmount_operation option)
1538 struct format_data *fdata;
1540 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1542 _E("fail to allocate format data");
1547 fdata->fs_type = strdup(fs_type);
1549 fdata->fs_type = NULL;
1550 fdata->option = option;
1555 static void release_format_data(struct format_data *data)
1559 free(data->fs_type);
1564 // Called by BlockThread - Real Mount Op
1565 static int block_mount_device(struct block_device *bdev, void *data)
1574 thread_id = bdev->thread_id;
1575 if (thread_id < 0 || thread_id >= THREAD_MAX)
1577 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1578 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1579 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1581 _E("(%d) does not exist in the device list", bdev->data->devnode);
1585 /* mount automatically */
1586 ret = mount_block_device(bdev);
1588 _E("fail to mount block device for %s", bdev->data->devnode);
1593 // Called by BlockThread - Real Format Op
1594 static int block_format_device(struct block_device *bdev, void *data)
1599 struct format_data *fdata = (struct format_data *)data;
1601 if (!bdev || !fdata) {
1606 thread_id = bdev->thread_id;
1607 if (thread_id < 0 || thread_id >= THREAD_MAX)
1609 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1610 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1611 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1613 _E("(%d) does not exist in the device list", bdev->data->devnode);
1618 ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1620 _E("fail to mount block device for %s", bdev->data->devnode);
1623 release_format_data(fdata);
1628 // Called by BlockThread - Real Unmount Op
1629 static int block_unmount_device(struct block_device *bdev, void *data)
1632 long option = (long)data;
1637 ret = unmount_block_device(bdev, option);
1639 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1646 /* Called by BlockThread - Remove Operation
1647 Direct Call at BlockThread
1648 Previously this function was called by MainThread. However, it will increase complexity.
1649 Need thread lock before to call remove_operation
1651 static void remove_operation(struct block_device *bdev)
1653 struct operation_queue *op;
1660 thread_id = bdev->thread_id;
1661 if (thread_id < 0 || thread_id >= THREAD_MAX)
1664 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1666 _D("Remove operation (%s, %s)",
1667 get_operation_char(op->op, name, sizeof(name)),
1668 bdev->data->devnode);
1670 DD_LIST_REMOVE(bdev->op_queue, op);
1676 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1683 rep = make_dbus_reply_message_simple(reply_handle, result);
1684 reply_dbus_method_result(reply_handle, rep);
1687 // Called by BlockThread
1688 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1690 struct operation_queue *temp;
1703 thread_id = bdev->thread_id;
1704 if (thread_id < 0 || thread_id >= THREAD_MAX)
1707 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1709 DD_LIST_FOREACH(*queue, l, temp) {
1710 if (temp->op == BLOCK_DEV_REMOVE) {
1715 th_manager[thread_id].op_len--;
1716 block_send_dbus_reply((*op)->reply_handle, 0);
1719 remove_operation(bdev);
1720 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1723 // Called by BlockThread
1724 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1726 struct operation_queue *temp;
1729 bool unmounted = false;
1740 thread_id = bdev->thread_id;
1741 if (thread_id < 0 || thread_id >= THREAD_MAX)
1744 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1745 DD_LIST_FOREACH(*queue, l, temp) {
1746 if (temp->op == BLOCK_DEV_UNMOUNT) {
1748 _D("Operation queue has unmount operation");
1752 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1757 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1759 DD_LIST_FOREACH(*queue, l, temp) {
1760 if (temp->op == BLOCK_DEV_UNMOUNT) {
1765 th_manager[thread_id].op_len--;
1766 block_send_dbus_reply((*op)->reply_handle, 0);
1769 remove_operation(bdev);
1770 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1775 // Called by BlockThread
1776 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1780 char devnode[PATH_MAX];
1782 enum block_dev_operation operation;
1783 bool unmounted = false;
1790 thread_id = bdev->thread_id;
1791 if (thread_id < 0 || thread_id >= THREAD_MAX)
1794 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1804 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1805 get_operation_char(operation, name, sizeof(name)), devnode);
1808 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1809 check_removed(bdev, &queue, &op);
1811 _D("Trigger operation again (%s, %s)",
1812 get_operation_char(operation, name, sizeof(name)), devnode);
1814 if (operation == BLOCK_DEV_MOUNT) {
1815 unmounted = check_unmount(bdev, &queue, &op);
1818 _D("Trigger operation again (%s, %s)",
1819 get_operation_char(operation, name, sizeof(name)), devnode);
1823 switch (operation) {
1824 case BLOCK_DEV_INSERT:
1826 case BLOCK_DEV_MOUNT:
1827 ret = block_mount_device(bdev, op->data);
1828 _D("Mount (%s) result:(%d)", devnode, ret);
1830 case BLOCK_DEV_FORMAT:
1831 ret = block_format_device(bdev, op->data);
1832 _D("Format (%s) result:(%d)", devnode, ret);
1834 case BLOCK_DEV_UNMOUNT:
1835 ret = block_unmount_device(bdev, op->data);
1836 _D("Unmount (%s) result:(%d)", devnode, ret);
1838 case BLOCK_DEV_REMOVE:
1841 case BLOCK_LUKS_CLOSE:
1842 ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1844 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1847 _E("Operation type is invalid (%d)", op->op);
1853 * during checking the queue length */
1854 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1857 th_manager[thread_id].op_len--;
1859 block_send_dbus_reply(op->reply_handle, ret);
1861 queue = bdev->op_queue;
1862 if (queue != NULL) {
1863 queue = DD_LIST_NEXT(queue);
1865 op = DD_LIST_NTH(queue, 0);
1871 remove_operation(bdev);
1873 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1876 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1877 if (pipe_trigger(operation, bdev, 0) < 0)
1878 _E("fail to trigger pipe");
1885 // Called by BlockThread
1886 static void *block_th_start(void *arg)
1888 struct block_device *temp;
1889 struct manage_thread *th = (struct manage_thread *)arg;
1890 struct operation_queue *op = NULL;
1892 dd_list *queue = NULL;
1897 thread_id = th->thread_id;
1898 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1899 _E("Thread Number: %d", th->thread_id);
1904 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1905 if (th_manager[thread_id].op_len == 0) {
1906 _D("Operation queue of thread is empty");
1907 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1908 _D("Wake up %d", thread_id);
1911 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1912 queue = temp->op_queue;
1914 op = DD_LIST_NTH(queue, 0);
1916 _D("Operation queue for device %s is Empty", temp->data->devnode);
1920 queue = DD_LIST_NEXT(queue);
1928 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1930 if (op && !op->done)
1931 trigger_operation(temp, queue, op);
1936 // This function will be refactored later
1937 // Especially, we don't need to keep th_node_list.
1938 static int find_thread(char *devnode)
1945 int i, len, min, min_num;
1946 int dev_mmc = -1, part = -1, num;
1949 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1950 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1957 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1958 th_node = strdup(str);
1959 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1960 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1961 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1962 th_node = strdup(str);
1964 th_node = strdup(devnode);
1966 len = strlen(th_node) + 1;
1969 for (i = 0; i < THREAD_MAX; i++) {
1970 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1971 if (!strncmp(temp, th_node, len)) {
1976 if (th_manager[i].num_dev < min_num) {
1977 min_num = th_manager[i].num_dev;
1982 if (min >= 0 && min < THREAD_MAX) {
1983 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1987 _E("Finding thread is failed");
1988 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1992 /* Only Main thread is permmited */
1993 // Called by MainThread
1994 static int add_operation(struct block_device *bdev,
1995 enum block_dev_operation operation,
1996 dbus_method_reply_handle_h reply_handle, void *data)
1998 struct operation_queue *op;
2008 _I("Add operation (%s, %s)",
2009 get_operation_char(operation, name, sizeof(name)),
2010 bdev->data->devnode);
2012 thread_id = bdev->thread_id;
2013 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2014 _E("Fail to find thread to add");
2018 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2020 _E("malloc failed");
2026 op->reply_handle = reply_handle;
2029 * during adding queue and checking the queue length */
2030 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2032 /* Only modified between lock and unlock of mutex */
2035 start_th = th_manager[thread_id].start_th;
2036 DD_LIST_APPEND(bdev->op_queue, op);
2037 th_manager[thread_id].op_len++;
2039 if (th_manager[thread_id].op_len == 1 && !start_th)
2040 pthread_cond_signal(&(th_manager[thread_id].cond));
2042 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2045 /* Need to disble app2ext whenever unmounting mmc */
2046 if (op->op == BLOCK_DEV_UNMOUNT &&
2047 bdev->data->state == BLOCK_MOUNT &&
2048 bdev->data->block_type == BLOCK_MMC_DEV &&
2049 bdev->data->primary)
2050 if (app2ext_disable_all_external_pkgs() < 0)
2051 _E("app2ext_disable_all_external_pkgs() failed");
2055 _D("Start New thread for block device");
2056 th_manager[thread_id].start_th = false;
2057 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2059 _E("fail to create thread for %s", bdev->data->devnode);
2063 pthread_detach(th_manager[thread_id].th);
2069 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2072 struct dirent entry;
2074 const char *syspath;
2077 syspath = udev_device_get_syspath(dev);
2081 dp = opendir(syspath);
2083 _E("fail to open %s", syspath);
2087 /* TODO compare devname and d_name */
2088 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2089 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2090 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2102 static bool check_partition(struct udev_device *dev)
2104 const char *devtype;
2105 const char *part_table_type;
2106 const char *fs_usage;
2109 /* only consider disk type, never partitions */
2110 devtype = udev_device_get_devtype(dev);
2114 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2115 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2118 part_table_type = udev_device_get_property_value(dev,
2119 "ID_PART_TABLE_TYPE");
2120 if (part_table_type) {
2121 fs_usage = udev_device_get_property_value(dev,
2124 strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2125 if (!disk_is_partitioned_by_kernel(dev))
2132 if (disk_is_partitioned_by_kernel(dev)) {
2141 // Called by MainThread
2142 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2144 struct block_data *data;
2145 struct block_device *bdev;
2146 //char id_string[PATH_LEN];
2150 bool need_format = false;
2152 partition = check_partition(dev);
2154 /* if there is a partition, skip this request */
2155 _I("%s device has partitions, skip this time", devnode);
2159 if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2160 char syspath[128] = {0};
2163 r = rindex(udev_device_get_syspath(dev), '/');
2164 if (!r) return -ENODEV;
2166 sprintf(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)) {
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 _D("Need to unlock encrypted sdcard");
2240 // ---- ODE UI launch ----
2241 ret = launch_system_app(POPUP_DEFAULT
2244 , "unlockextendedsd"
2248 , bdev->data->devnode
2252 _E("Failed to launch popup");
2255 } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2256 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2257 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2260 free_block_device(bdev);
2265 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2267 _E("Failed to add operation (insert %s)", devnode);
2268 free_block_device(bdev);
2272 // Not a regular filesystem -> skip mounting
2273 if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM)) {
2274 _I("Not a filesystem. Not mounting");
2278 /* Create file for block device /run/external-storage/id */
2279 create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2280 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2282 _E("Failed to add operation (mount %s)", devnode);
2288 static int remove_block_device(struct udev_device *dev, const char *devnode)
2290 struct block_device *bdev;
2291 struct block_device *bdev_extended;
2294 bdev = find_block_device(devnode);
2296 _E("fail to find block data for %s", devnode);
2300 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2302 bdev->removed = true;
2303 if (bdev->on_private_op != REQ_NORMAL) {
2304 bdev->on_private_op = REQ_NORMAL;
2305 _D("Private operation state: %d", bdev->on_private_op);
2308 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2309 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2311 if (bdev_extended) {
2312 BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2314 bdev_extended->removed = true;
2315 if (bdev_extended->on_private_op != REQ_NORMAL) {
2316 bdev_extended->on_private_op = REQ_NORMAL;
2317 _D("Private operation state: %d", bdev_extended->on_private_op);
2320 ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2322 _E("Failed to add operation (unmount %s)", devnode);
2326 ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2328 _E("Failed to add operation (remove %s)", devnode);
2332 ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2334 _E("Failed to add operation (luks_close %s)", devnode);
2338 _E("fail to find block data for extended sd card");
2341 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2343 _E("Failed to add operation (unmount %s)", devnode);
2347 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2349 _E("Failed to add operation (remove %s)", devnode);
2356 static int get_internal_storage_number(void)
2358 struct libmnt_table *t = NULL;
2359 struct libmnt_fs *fs;
2362 int r = 0, dev_temp;
2364 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2365 (is_emulator() && dev_internal_emul != '\0'))
2368 t = mnt_new_table();
2372 r = mnt_table_parse_mtab(t, NULL);
2378 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2384 temp = mnt_fs_get_srcpath(fs);
2388 name = strrchr(temp, '/');
2392 /* Boot from USB is not handled */
2393 if (!is_emulator()) {
2394 if (!fnmatch(MMC_PATH, temp, 0))
2395 sscanf(name, "mmcblk%d", &dev_internal);
2396 else if (!fnmatch(SCSI_PATH, temp, 0))
2397 sscanf(name, "sd%c", &dev_internal_scsi);
2399 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2400 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2402 dev_internal_emul = '\0';
2410 static int check_external_storage(const char* devnode)
2412 char dev_scsi = '\0';
2415 int dev_num = -1, dev_temp;
2420 name = strrchr(devnode, '/');
2424 if (!is_emulator()) {
2425 if (!fnmatch(MMC_PATH, devnode, 0)) {
2426 sscanf(name, "mmcblk%d", &dev_num);
2427 if (dev_internal == dev_num) {
2428 _D("%s is internal storage", devnode);
2431 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2432 sscanf(name, "sd%c", &dev_scsi);
2433 if (dev_internal_scsi == dev_scsi) {
2434 _D("%s is internal storage", devnode);
2439 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2440 sscanf(name, "vd%c%d", &emul, &dev_temp);
2441 if (dev_internal_emul == emul) {
2442 _D("%s is internal storage", devnode);
2451 static int check_already_handled(const char* devnode)
2453 struct block_device *bdev;
2454 struct block_data *data;
2458 for (i = 0; i < THREAD_MAX; i++) {
2459 pthread_mutex_lock(&(th_manager[i].mutex));
2460 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2466 if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2467 pthread_mutex_unlock(&(th_manager[i].mutex));
2471 pthread_mutex_unlock(&(th_manager[i].mutex));
2477 static int block_init_from_udev_enumerate(void)
2480 struct udev_enumerate *enumerate;
2481 struct udev_list_entry *list_entry, *list_sub_entry;
2482 struct udev_device *dev;
2483 const char *syspath;
2484 const char *devnode;
2489 _E("fail to create udev library context");
2493 /* create a list of the devices in the 'usb' subsystem */
2494 enumerate = udev_enumerate_new(udev);
2496 _E("fail to create an enumeration context");
2500 if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2501 (is_emulator() && dev_internal_emul == '\0')) {
2502 r = get_internal_storage_number();
2507 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2508 udev_enumerate_add_match_property(enumerate,
2509 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2510 udev_enumerate_add_match_property(enumerate,
2511 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2512 udev_enumerate_scan_devices(enumerate);
2514 udev_list_entry_foreach(list_entry,
2515 udev_enumerate_get_list_entry(enumerate)) {
2516 syspath = udev_list_entry_get_name(list_entry);
2520 dev = udev_device_new_from_syspath(
2521 udev_enumerate_get_udev(enumerate),
2527 udev_list_entry_foreach(list_sub_entry,
2528 udev_device_get_devlinks_list_entry(dev)) {
2529 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2530 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2537 devnode = udev_device_get_devnode(dev);
2541 if (fnmatch(MMC_PATH, devnode, 0) &&
2542 fnmatch(SCSI_PATH, devnode, 0) &&
2543 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
2547 r = check_external_storage(devnode);
2551 r = check_already_handled(devnode);
2553 _I("%s is already handled", devnode);
2557 _I("%s device add", devnode);
2558 add_block_device(dev, devnode, false);
2560 udev_device_unref(dev);
2563 udev_enumerate_unref(enumerate);
2568 // Called by MainThread
2569 static void show_block_device_list(void)
2571 struct block_device *bdev;
2572 struct block_data *data;
2576 for (i = 0; i < THREAD_MAX; i++) {
2577 pthread_mutex_lock(&(th_manager[i].mutex));
2578 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2584 _D("%s:", data->devnode);
2585 _D("\tSyspath: %s", data->syspath);
2586 _D("\tBlock type: %d", data->block_type);
2587 _D("\tFs type: %s", data->fs_type);
2588 _D("\tFs usage: %s", data->fs_usage);
2589 _D("\tFs version: %s", data->fs_version);
2590 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2591 _D("\tReadonly: %s",
2592 (data->readonly ? "true" : "false"));
2593 _D("\tMount point: %s", data->mount_point);
2594 _D("\tMount state: %s",
2595 (data->state == BLOCK_MOUNT ?
2596 "mount" : "unmount"));
2598 (data->primary ? "true" : "false"));
2599 _D("\tID: %d", data->id);
2601 pthread_mutex_unlock(&(th_manager[i].mutex));
2605 // Called by MainThread
2606 static void remove_whole_block_device(void)
2608 struct block_device *bdev;
2614 for (i = 0; i < THREAD_MAX; i++) {
2616 pthread_mutex_lock(&(th_manager[i].mutex));
2617 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2618 if (bdev->removed == false)
2621 pthread_mutex_unlock(&(th_manager[i].mutex));
2623 if (bdev && bdev->removed == false) {
2624 bdev->removed = true;
2625 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2627 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2629 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2631 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2638 static void booting_done(const char *sender_name,
2639 const char *object_path, const char *interface_name,
2640 const char *signal_name, DBusMessage *msg,
2643 static int done = 0;
2648 /* if there is the attached device, try to mount */
2649 block_init_from_udev_enumerate();
2650 block_control = true;
2654 static void block_poweroff(const char *sender_name,
2655 const char *object_path, const char *interface_name,
2656 const char *signal_name, DBusMessage *msg,
2659 static int status = 0;
2664 /* unregister mmc uevent control routine */
2665 unregister_udev_uevent_control(&uh);
2666 remove_whole_block_device();
2669 static void uevent_block_handler(struct udev_device *dev)
2671 const char *devnode = NULL;
2673 struct udev_list_entry *list_entry;
2675 bool mapper = false;
2677 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2678 const char *devlink = udev_list_entry_get_name(list_entry);
2679 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2683 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2691 devnode = udev_device_get_devnode(dev);
2695 if (fnmatch(MMC_PATH, devnode, 0) &&
2696 fnmatch(SCSI_PATH, devnode, 0))
2700 r = check_external_storage(devnode);
2704 action = udev_device_get_action(dev);
2708 _I("%s device %s", devnode, action);
2709 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2710 (mapper && !strcmp(action, UDEV_CHANGE))) {
2711 r = check_already_handled(devnode);
2713 _I("%s is already handled", devnode);
2717 add_block_device(dev, devnode, mapper);
2718 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2719 remove_block_device(dev, devnode);
2720 } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2721 struct block_device *bdev;
2722 bdev = find_block_device(devnode);
2724 _E("fail to find block data for %s", devnode);
2727 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2730 r = update_block_data(bdev->data,
2731 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2732 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2733 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2734 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2735 udev_device_get_sysattr_value(dev, "ro"),
2738 _E("fail to update block data for %s", bdev->data->devnode);
2742 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2743 DBusMessage *msg, bool onprivate)
2745 struct block_device *bdev;
2750 if (!reply_handle || !msg)
2753 ret = dbus_message_get_args(msg, NULL,
2754 DBUS_TYPE_INT32, &id,
2755 DBUS_TYPE_STRING, &mount_point,
2760 bdev = find_block_device_by_id(id);
2762 _E("Failed to find (%d) in the device list", id);
2766 if (bdev->on_private_op != REQ_NORMAL) {
2771 if (bdev->data->state == BLOCK_MOUNT) {
2772 _I("%s is already mounted", bdev->data->devnode);
2778 bdev->on_private_op = REQ_PRIVATE;
2779 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2780 _D("Private operation state: %d", bdev->on_private_op);
2782 if (bdev->on_private_op != REQ_NORMAL) {
2783 _E("Failed to process mount operation");
2789 /* if requester want to use a specific mount point */
2791 !strncmp(mount_point, EXTENDEDSD_STRING, strlen(EXTENDEDSD_STRING) + 1) != 0) {
2792 if (!block_conf[bdev->data->block_type].extendedinternal ||
2793 !bdev->data->primary) {
2794 _E("Not support extended internal storage");
2798 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2799 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2805 create_file(bdev->data->id, bdev->data->mount_point, true);
2807 } else if (mount_point && strncmp(mount_point, "", 1) != 0) {
2808 ret = change_mount_point(bdev, mount_point);
2814 /* Create /run/external-storage/id file */
2815 create_file(bdev->data->id, bdev->data->mount_point, false);
2817 /* Create file for block device /run/external-storage/id */
2818 create_file(bdev->data->id, bdev->data->mount_point, false);
2821 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2823 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2830 return make_dbus_reply_message_simple(reply_handle, ret);
2833 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2836 return request_mount_block(reply_handle, msg, false);
2839 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2842 return request_mount_block(reply_handle, msg, true);
2845 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2846 DBusMessage *msg, bool onprivate)
2848 struct block_device *bdev;
2854 if (!reply_handle || !msg)
2857 ret = dbus_message_get_args(msg, NULL,
2858 DBUS_TYPE_INT32, &id,
2859 DBUS_TYPE_INT32, &option,
2864 bdev = find_block_device_by_id(id);
2866 _E("Failed to find (%d) in the device list", id);
2871 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2872 _I("Impossible to request unmount extended internal sdcard");
2878 pid = get_dbus_method_sender_pid(reply_handle);
2879 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2880 _E("Failed to process private unmount operation");
2885 if (bdev->on_private_op != REQ_NORMAL) {
2886 _E("Failed to process unmount operation");
2892 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2894 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2901 return make_dbus_reply_message_simple(reply_handle, ret);
2904 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2907 return request_unmount_block(reply_handle, msg, false);
2910 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2913 return request_unmount_block(reply_handle, msg, true);
2916 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2919 struct block_device *bdev;
2920 struct format_data *fdata;
2927 if (!reply_handle || !msg)
2930 ret = dbus_message_get_args(msg, NULL,
2931 DBUS_TYPE_INT32, &id,
2932 DBUS_TYPE_INT32, &option,
2937 bdev = find_block_device_by_id(id);
2939 _E("Failed to find (%d) in the device list", id);
2943 pid = get_dbus_method_sender_pid(reply_handle);
2944 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2945 _E("Failed to format on private state");
2950 fdata = get_format_data(NULL, option);
2952 _E("Failed to get format data");
2956 prev_state = bdev->data->state;
2957 if (prev_state == BLOCK_MOUNT) {
2958 if (bdev->on_private_op == REQ_PRIVATE) {
2959 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2960 _D("Private operation state: %d", bdev->on_private_op);
2962 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2964 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2965 release_format_data(fdata);
2970 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2972 _E("Failed to add operation (format %s)", bdev->data->devnode);
2973 release_format_data(fdata);
2976 /* Maintain previous state of mount/unmount */
2977 if (prev_state == BLOCK_MOUNT) {
2978 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2979 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2987 return make_dbus_reply_message_simple(reply_handle, ret);
2990 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2993 struct block_device *bdev;
2994 struct format_data *fdata;
3002 if (!reply_handle || !msg)
3005 ret = dbus_message_get_args(msg, NULL,
3006 DBUS_TYPE_INT32, &id,
3007 DBUS_TYPE_INT32, &option,
3008 DBUS_TYPE_STRING, &type,
3013 bdev = find_block_device_by_id(id);
3015 _E("Failed to find (%d) in the device list", id);
3019 pid = get_dbus_method_sender_pid(reply_handle);
3020 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3021 _E("Failed to format on private state");
3026 fdata = get_format_data(type, option);
3028 _E("Failed to get format data");
3032 prev_state = bdev->data->state;
3033 if (prev_state == BLOCK_MOUNT) {
3034 if (bdev->on_private_op == REQ_PRIVATE) {
3035 bdev->on_private_op = REQ_PRIVATE_FORMAT;
3036 _D("Private operation state: %d", bdev->on_private_op);
3038 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3040 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3041 release_format_data(fdata);
3046 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3048 _E("Failed to add operation (format %s)", bdev->data->devnode);
3049 release_format_data(fdata);
3052 /* Maintain previous state of mount/unmount */
3053 if (prev_state == BLOCK_MOUNT) {
3054 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3055 _E("Failed to add operation (mount %s)", bdev->data->devnode);
3063 return make_dbus_reply_message_simple(reply_handle, ret);
3066 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3068 char *str_null = "";
3070 if (!data || !piter)
3073 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3074 &(data->block_type));
3075 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3076 data->devnode ? &(data->devnode) : &str_null);
3077 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3078 data->syspath ? &(data->syspath) : &str_null);
3079 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3080 data->fs_usage ? &(data->fs_usage) : &str_null);
3081 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3082 data->fs_type ? &(data->fs_type) : &str_null);
3083 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3084 data->fs_version ? &(data->fs_version) : &str_null);
3085 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3086 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3087 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3089 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3090 data->mount_point ? &(data->mount_point) : &str_null);
3091 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3093 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3095 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3097 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3104 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3106 DBusMessageIter piter;
3111 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3112 add_device_to_iter(data, &piter);
3113 dbus_message_iter_close_container(iter, &piter);
3118 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3120 DBusMessageIter piter;
3121 char *str_null = "";
3126 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3127 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3128 &(data->block_type));
3129 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3130 data->devnode ? &(data->devnode) : &str_null);
3131 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3132 data->syspath ? &(data->syspath) : &str_null);
3133 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3134 data->fs_usage ? &(data->fs_usage) : &str_null);
3135 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3136 data->fs_type ? &(data->fs_type) : &str_null);
3137 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3138 data->fs_version ? &(data->fs_version) : &str_null);
3139 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3140 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3141 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3143 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3144 data->mount_point ? &(data->mount_point) : &str_null);
3145 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3147 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3149 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3151 dbus_message_iter_close_container(iter, &piter);
3156 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3159 DBusMessageIter iter;
3161 struct block_device *bdev;
3162 struct block_data *data;
3165 if (!reply_handle || !msg)
3168 reply = make_dbus_reply_message(reply_handle);
3172 ret = dbus_message_get_args(msg, NULL,
3173 DBUS_TYPE_INT32, &id,
3178 bdev = find_block_device_by_id(id);
3185 dbus_message_iter_init_append(reply, &iter);
3186 add_device_to_iter(data, &iter);
3192 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3195 show_block_device_list();
3196 return make_dbus_reply_message(reply_handle);
3199 // Called by MainThread
3200 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3203 DBusMessageIter iter;
3204 DBusMessageIter aiter;
3206 struct block_device *bdev;
3207 struct block_data *data;
3214 reply = make_dbus_reply_message(reply_handle);
3216 ret = dbus_message_get_args(msg, NULL,
3217 DBUS_TYPE_STRING, &type,
3220 _E("Failed to get args");
3225 _E("Delivered type is NULL");
3229 _D("Block (%s) device list is requested", type);
3231 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3232 block_type = BLOCK_SCSI_DEV;
3233 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3234 block_type = BLOCK_MMC_DEV;
3235 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3238 _E("Invalid type (%s) is requested", type);
3242 dbus_message_iter_init_append(reply, &iter);
3243 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3245 for (i = 0; i < THREAD_MAX; i++) {
3246 pthread_mutex_lock(&(th_manager[i].mutex));
3247 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3254 switch (block_type) {
3255 case BLOCK_SCSI_DEV:
3257 if (data->block_type != block_type)
3263 add_device_to_struct_iter(data, &aiter);
3265 pthread_mutex_unlock(&(th_manager[i].mutex));
3267 dbus_message_iter_close_container(&iter, &aiter);
3273 // Called by MainThread
3274 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3277 DBusMessageIter iter;
3278 DBusMessageIter aiter;
3280 struct block_device *bdev;
3281 struct block_data *data;
3288 reply = make_dbus_reply_message(reply_handle);
3290 ret = dbus_message_get_args(msg, NULL,
3291 DBUS_TYPE_STRING, &type,
3294 _E("Failed to get args");
3299 _E("Delivered type is NULL");
3303 _D("Block (%s) device list is requested", type);
3305 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3306 block_type = BLOCK_SCSI_DEV;
3307 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3308 block_type = BLOCK_MMC_DEV;
3309 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3312 _E("Invalid type (%s) is requested", type);
3316 dbus_message_iter_init_append(reply, &iter);
3317 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3319 for (i = 0; i < THREAD_MAX; i++) {
3320 pthread_mutex_lock(&(th_manager[i].mutex));
3321 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3328 switch (block_type) {
3329 case BLOCK_SCSI_DEV:
3331 if (data->block_type != block_type)
3338 add_device_to_iter_2(data, &aiter);
3340 pthread_mutex_unlock(&(th_manager[i].mutex));
3342 dbus_message_iter_close_container(&iter, &aiter);
3348 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3351 DBusMessageIter iter;
3353 struct block_device *bdev;
3354 struct block_data *data, nodata = {0,};
3359 if (!reply_handle || !msg)
3362 reply = make_dbus_reply_message(reply_handle);
3367 for (i = 0; i < THREAD_MAX; i++) {
3368 pthread_mutex_lock(&(th_manager[i].mutex));
3369 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3375 if (data->block_type != BLOCK_MMC_DEV &&
3376 data->block_type != BLOCK_EXTENDEDSD_DEV)
3383 pthread_mutex_unlock(&(th_manager[i].mutex));
3388 dbus_message_iter_init_append(reply, &iter);
3390 add_device_to_iter(data, &iter);
3392 nodata.id = -ENODEV;
3393 add_device_to_iter(&nodata, &iter);
3400 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3403 struct timespec start_time, end_time;
3404 DBusMessageIter iter;
3406 struct block_device *bdev;
3407 struct block_data *data;
3413 if (!reply_handle || !msg)
3416 ret = dbus_message_get_args(msg, NULL,
3417 DBUS_TYPE_INT32, &id,
3424 bdev = find_block_device_by_id(id);
3435 _D("speed check: %s", data->devnode);
3436 fd = open(data->devnode, O_RDWR | O_SYNC);
3437 buf = calloc(1, SPEEDCHECK * 1024 * 1024);
3439 _E("calloc() failed");
3444 clock_gettime(CLOCK_REALTIME, &start_time);
3445 _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3446 ret = write(fd, buf, SPEEDCHECK * 1024 * 1024);
3447 clock_gettime(CLOCK_REALTIME, &end_time);
3448 _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3452 if (SPEEDCHECK / (end_time.tv_sec - start_time.tv_sec) < 4) {
3459 _E("write() failed %d", errno);
3466 reply = dbus_message_new_method_return(msg);
3467 dbus_message_iter_init_append(reply, &iter);
3468 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3473 Method name Method call format string Reply format string
3474 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3475 { "GetDeviceList", "s", "a(issssssisibii)", request_get_device_list },
3476 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3477 { "Mount", "is", "i", request_public_mount_block },
3478 { "Unmoun, "ii", "i", request_public_unmount_block },
3479 { "Format", "ii", "i", request_format_block },
3480 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3481 { "GetMmcPrimary", NULL, "(issssssisibii)" , request_get_mmc_primary },
3482 { "PrivateMount", "is", "i", request_private_mount_block },
3483 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3486 static const dbus_method_s manager_methods[] = {
3487 { "ShowDeviceList", NULL, request_show_device_list },
3488 { "GetDeviceList" , "s", request_get_device_list },
3489 { "GetDeviceList2", "s", request_get_device_list_2 },
3490 { "Mount", "is", request_public_mount_block },
3491 { "Unmount", "ii", request_public_unmount_block },
3492 { "Format", "ii", request_format_block },
3493 { "FormatwithType", "iis", request_format_block_type },
3494 { "GetDeviceInfo", "i", request_get_device_info },
3495 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3496 { "PrivateMount", "is", request_private_mount_block },
3497 { "PrivateUnmount", "ii", request_private_unmount_block },
3498 { "CheckSpeed", "i", request_check_speed },
3501 static dbus_interface_s block_interface = {
3502 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3503 .methods = manager_methods,
3504 .nr_methods = ARRAY_SIZE(manager_methods),
3507 static int load_config(struct parse_result *result, void *user_data)
3511 if (MATCH(result->section, "Block"))
3514 if (MATCH(result->section, "SCSI"))
3515 index = BLOCK_SCSI_DEV;
3516 else if (MATCH(result->section, "MMC"))
3517 index = BLOCK_MMC_DEV;
3518 else if (MATCH(result->section, "Mapper"))
3519 index = BLOCK_EXTENDEDSD_DEV;
3523 if (MATCH(result->name, "Multimount"))
3524 block_conf[index].multimount =
3525 (MATCH(result->value, "yes") ? true : false);
3526 if (MATCH(result->name, "ExtendedInternalStorage"))
3527 block_conf[index].extendedinternal =
3528 (MATCH(result->value, "yes") ? true : false);
3534 static int mount_root_path_tmpfs(void)
3539 root = tzplatform_getenv(TZ_SYS_MEDIA);
3543 if (access(root, F_OK) != 0)
3546 if (mount_check(root))
3549 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3552 _E("tmpfs mount failed (%d)", ret);
3559 #define mount_root_path_tmpfs() 0
3562 static void block_init(void *data)
3567 dbus_handle_h handle;
3572 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3574 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3576 ret = mount_root_path_tmpfs();
3578 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3580 ret = dbus_get_connection(&handle);
3582 _E("Failed to get dbus connection(%d)", ret);
3584 /* register block manager object and interface */
3585 ret = register_dbus_methods(handle,
3586 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3589 _E("Failed to register block interface and methods (%d)", ret);
3594 _E("fail to init pipe");
3596 /* register mmc uevent control routine */
3597 ret = register_udev_uevent_control(&uh);
3599 _E("fail to register block uevent : %d", ret);
3601 /* System Session is loaded completely */
3602 register_dbus_signal(SYSTEMD_DBUS_PATH,
3603 SYSTEMD_DBUS_IFACE_MANAGER,
3604 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3605 booting_done, NULL, NULL);
3607 register_dbus_signal(DEVICED_PATH_POWEROFF,
3608 DEVICED_INTERFACE_POWEROFF,
3609 SIGNAL_POWEROFF_STATE,
3610 block_poweroff, NULL, NULL);
3612 for (i = 0; i < THREAD_MAX; i++) {
3613 th_manager[i].num_dev = 0;
3614 th_manager[i].op_len = 0;
3615 th_manager[i].start_th = true;
3616 th_manager[i].thread_id = i;
3617 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3618 pthread_cond_init(&(th_manager[i].cond), NULL);
3621 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3623 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3625 _E("Failed to make directory: %d", errno);
3626 } else if (!S_ISDIR(buf.st_mode)) {
3627 ret = remove(EXTERNAL_STORAGE_PATH);
3629 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3630 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3632 _E("Failed to make directory: %d", errno);
3634 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3636 _E("Fail to change permissions of a file");
3639 ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3641 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3643 _E("Failed to make directory: %d", errno);
3644 } else if (!S_ISDIR(buf.st_mode)) {
3645 ret = remove(EXTENDED_INTERNAL_PATH);
3647 _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3648 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3650 _E("Failed to make directory: %d", errno);
3652 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3654 _E("Fail to change permissions of a file");
3658 static void block_exit(void *data)
3660 dd_list *elem, *elem_next;
3666 /* unregister notifier for below each event */
3667 unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3668 SYSTEMD_DBUS_IFACE_MANAGER,
3669 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3672 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3673 DEVICED_INTERFACE_POWEROFF,
3674 SIGNAL_POWEROFF_STATE, block_poweroff);
3679 /* unregister mmc uevent control routine */
3680 ret = unregister_udev_uevent_control(&uh);
3682 _E("fail to unregister block uevent : %d", ret);
3684 /* remove remaining blocks */
3685 remove_whole_block_device();
3687 for (i = 0; i < THREAD_MAX; i++) {
3688 if (!th_manager[i].start_th)
3689 pthread_cancel(th_manager[i].th);
3690 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3691 DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3696 block_control = false;
3699 static int block_start(void *data)
3704 _E("Cannot be started. Booting is not ready");
3708 if (block_control) {
3709 _I("Already started");
3713 /* register mmc uevent control routine */
3714 ret = register_udev_uevent_control(&uh);
3716 _E("fail to register block uevent : %d", ret);
3718 block_init_from_udev_enumerate();
3720 block_control = true;
3726 static int block_stop(void *data)
3729 _E("Cannot be stopped. Booting is not ready");
3733 if (!block_control) {
3734 _I("Already stopped");
3738 /* unregister mmc uevent control routine */
3739 unregister_udev_uevent_control(&uh);
3741 /* remove the existing blocks */
3742 remove_whole_block_device();
3744 block_control = false;
3750 static storaged_module_interface block_module = {
3754 .start = block_start,
3758 __attribute__ ((visibility("default")))storaged_module_interface *
3759 storaged_get_module_interface(void)
3761 return &block_module;