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>
45 #include "config-parser.h"
46 #include "module-intf.h"
51 #include "fd_handler.h"
56 * TODO Assume root device is always mmcblk0*.
58 #define MMC_PATH "*/mmcblk[0-9]*"
59 #define MMC_PARTITION_PATH "mmcblk[0-9]p[0-9]"
60 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
61 #define MMC_LINK_PATH "*/sdcard/*"
62 #define SCSI_PATH "*/sd[a-z]*"
63 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
64 #define SCSI_PARTITION_LENGTH 9
66 #define FILESYSTEM "filesystem"
68 #define DEV_PREFIX "/dev/"
71 #define UNMOUNT_RETRY 5
72 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
74 #define SIGNAL_POWEROFF_STATE "ChangeState"
76 #define BLOCK_DEVICE_ADDED "DeviceAdded"
77 #define BLOCK_DEVICE_REMOVED "DeviceRemoved"
78 #define BLOCK_DEVICE_BLOCKED "DeviceBlocked"
79 #define BLOCK_DEVICE_CHANGED "DeviceChanged"
80 #define BLOCK_DEVICE_CHANGED_2 "DeviceChanged2"
82 #define BLOCK_TYPE_MMC "mmc"
83 #define BLOCK_TYPE_SCSI "scsi"
84 #define BLOCK_TYPE_ALL "all"
86 #define BLOCK_MMC_NODE_PREFIX "SDCard"
87 #define BLOCK_SCSI_NODE_PREFIX "USBDrive"
89 #define BLOCK_CONF_FILE "/etc/storaged/block.conf"
91 #define EXTERNAL_STORAGE_PATH "/run/external-storage"
92 #define EXTENDED_INTERNAL_PATH "/run/extended-internal-sd"
95 #define EXTENDED_SD_PATH "/opt/extendedsd"
96 #define EXTENDED_SD_STRING "ExtendedInternalSD"
98 #define EXT4_NAME "ext4"
99 #define LUKS_NAME "crypto_LUKS"
101 /* Minimum value of block id */
102 #define BLOCK_ID_MIN 10
103 /* For 2.4 Backward Compatibility */
104 #define EXT_PRIMARY_SD_FIXID 1
106 /* Maximum number of thread */
109 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
110 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
111 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
113 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
115 enum block_dev_operation {
123 enum private_operation_state {
129 struct operation_queue {
130 enum block_dev_operation op;
131 dbus_method_reply_handle_h reply_handle;
136 struct block_device {
137 struct block_data *data;
139 int thread_id; /* Current thread ID */
140 bool removed; /* True when device is physically removed but operation is not precessed yet */
141 enum private_operation_state on_private_op;
142 bool mount_point_updated;
147 struct block_device *bdev;
149 enum unmount_operation option;
153 enum block_dev_operation op;
154 struct block_device *bdev;
158 static struct block_conf {
160 bool extendedinternal;
161 } block_conf[BLOCK_MMC_EXTENDED_INTERNAL_DEV + 1];
163 static struct manage_thread {
164 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
165 dd_list *block_dev_list; /* Use thread mutex */
167 pthread_mutex_t mutex;
169 int num_dev; /* Number of devices which thread holds. Only main thread access */
170 int op_len; /* Number of operation of thread. Use thread mutex */
171 int thread_id; /* Never changed */
173 } th_manager[THREAD_MAX];
175 static dd_list *fs_head;
176 static dd_list *block_ops_list;
179 static fd_handler_h phandler;
180 static bool block_control = false;
181 static bool block_boot = false;
183 /* Assume there is only one physical internal storage */
184 static int dev_internal = -1;
185 static char dev_internal_scsi = '\0';
186 static char dev_internal_emul = '\0';
188 static int add_operation(struct block_device *bdev,
189 enum block_dev_operation operation,
190 dbus_method_reply_handle_h reply_handle, void *data);
191 static void remove_operation(struct block_device *bdev);
192 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
193 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
194 static int change_mount_point(struct block_device *bdev, const char *mount_point);
196 static void uevent_block_handler(struct udev_device *dev);
197 static struct uevent_handler uh = {
198 .subsystem = BLOCK_SUBSYSTEM,
199 .uevent_func = uevent_block_handler,
202 static void __CONSTRUCTOR__ smack_check(void)
207 fp = fopen("/proc/filesystems", "r");
211 while (fgets(buf, sizeof(buf), fp) != NULL) {
212 if (strstr(buf, "smackfs")) {
221 void add_fs(const struct block_fs_ops *fs)
223 DD_LIST_APPEND(fs_head, (void *)fs);
226 void remove_fs(const struct block_fs_ops *fs)
228 DD_LIST_REMOVE(fs_head, (void *)fs);
231 const struct block_fs_ops *find_fs(enum block_fs_type type)
233 struct block_fs_ops *fs;
236 DD_LIST_FOREACH(fs_head, elem, fs) {
237 if (fs->type == type)
243 void add_block_dev(const struct block_dev_ops *ops)
245 DD_LIST_APPEND(block_ops_list, (void *)ops);
248 void remove_block_dev(const struct block_dev_ops *ops)
250 DD_LIST_REMOVE(block_ops_list, (void *)ops);
253 static void broadcast_block_info(enum block_dev_operation op,
254 struct block_data *data, int result)
256 struct block_dev_ops *ops;
259 if (data->primary != true)
262 DD_LIST_FOREACH(block_ops_list, elem, ops) {
263 if (ops->block_type != data->block_type)
265 // TODO What happend on extended internal storage case?
266 if (op == BLOCK_DEV_MOUNT) {
267 if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
268 ops->mounted(data, result, true);
270 ops->mounted(data, result, false);
271 } else if (op == BLOCK_DEV_UNMOUNT) {
272 if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
273 ops->unmounted(data, result, true);
275 ops->unmounted(data, result, false);
276 } else if (op == BLOCK_DEV_FORMAT) {
277 if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
278 ops->formatted(data, result, true);
280 ops->formatted(data, result, false);
281 } else if (op == BLOCK_DEV_INSERT)
283 else if (op == BLOCK_DEV_REMOVE)
288 // Called by MainThread - Insert
289 static int block_get_new_id(void)
291 static int id = BLOCK_ID_MIN;
292 struct block_device *bdev;
297 for (i = 0 ; i < INT_MAX ; i++) {
299 for (j = 0; j < THREAD_MAX; j++) {
300 pthread_mutex_lock(&(th_manager[j].mutex));
301 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
302 if (bdev->data->id == id) {
307 pthread_mutex_unlock(&(th_manager[j].mutex));
322 static void remove_file(int id, bool extendedsd)
324 char file_name[PATH_LEN];
331 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
333 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
335 ret = remove(file_name);
337 _E("Fail to remove %s. errno: %d", file_name, errno);
340 static void create_file(int id, char *mount_point, bool extendedsd)
343 char file_name[PATH_LEN];
349 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
351 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
353 fp = fopen(file_name, "w+");
355 fprintf(fp, "%s", mount_point);
358 _E("Fail to open %s", file_name);
361 static void signal_device_blocked(struct block_device *bdev)
363 struct block_data *data;
365 char str_block_type[32];
366 char str_readonly[32];
368 char str_primary[32];
374 if (!bdev || !bdev->data)
380 /* Broadcast outside with BlockManager iface */
381 snprintf(str_block_type, sizeof(str_block_type),
382 "%d", data->block_type);
383 arr[0] = str_block_type;
384 arr[1] = (data->devnode ? data->devnode : str_null);
385 arr[2] = (data->syspath ? data->syspath : str_null);
386 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
387 arr[4] = (data->fs_type ? data->fs_type : str_null);
388 arr[5] = (data->fs_version ? data->fs_version : str_null);
389 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
390 snprintf(str_readonly, sizeof(str_readonly),
391 "%d", data->readonly);
392 arr[7] = str_readonly;
393 arr[8] = (data->mount_point ? data->mount_point : str_null);
394 snprintf(str_state, sizeof(str_state),
397 snprintf(str_primary, sizeof(str_primary),
398 "%d", data->primary);
399 arr[10] = str_primary;
400 snprintf(str_flags, sizeof(str_flags), "%d", flags);
402 snprintf(str_id, sizeof(str_id), "%d", data->id);
405 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
406 STORAGED_INTERFACE_BLOCK_MANAGER,
407 BLOCK_DEVICE_BLOCKED,
408 "issssssisibii", arr);
411 static void signal_device_changed(struct block_device *bdev,
412 enum block_dev_operation op)
414 struct block_data *data;
416 char str_block_type[32];
417 char str_readonly[32];
419 char str_primary[32];
425 if (!bdev || !bdev->data)
431 case BLOCK_DEV_MOUNT:
432 BLOCK_GET_MOUNT_FLAGS(data, flags);
434 case BLOCK_DEV_UNMOUNT:
435 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
437 case BLOCK_DEV_FORMAT:
438 BLOCK_GET_FORMAT_FLAGS(data, flags);
445 /* Broadcast outside with BlockManager iface */
446 snprintf(str_block_type, sizeof(str_block_type),
447 "%d", data->block_type);
448 arr[0] = str_block_type;
449 arr[1] = (data->devnode ? data->devnode : str_null);
450 arr[2] = (data->syspath ? data->syspath : str_null);
451 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
452 arr[4] = (data->fs_type ? data->fs_type : str_null);
453 arr[5] = (data->fs_version ? data->fs_version : str_null);
454 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
455 snprintf(str_readonly, sizeof(str_readonly),
456 "%d", data->readonly);
457 arr[7] = str_readonly;
458 arr[8] = (data->mount_point ? data->mount_point : str_null);
459 snprintf(str_state, sizeof(str_state),
462 snprintf(str_primary, sizeof(str_primary),
463 "%d", data->primary);
464 arr[10] = str_primary;
465 snprintf(str_flags, sizeof(str_flags), "%d", flags);
467 snprintf(str_id, sizeof(str_id), "%d", data->id);
470 if (op == BLOCK_DEV_INSERT)
471 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
472 STORAGED_INTERFACE_BLOCK_MANAGER,
474 "issssssisibii", arr);
475 else if (op == BLOCK_DEV_REMOVE)
476 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
477 STORAGED_INTERFACE_BLOCK_MANAGER,
478 BLOCK_DEVICE_REMOVED,
479 "issssssisibii", arr);
481 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
482 STORAGED_INTERFACE_BLOCK_MANAGER,
483 BLOCK_DEVICE_CHANGED,
484 "issssssisibii", arr);
485 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
486 STORAGED_INTERFACE_BLOCK_MANAGER,
487 BLOCK_DEVICE_CHANGED_2,
488 "issssssisibi", arr);
492 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
494 char *name = devnode;
495 int dev = -1, part = -1;
496 char emul[32] = { 0, };
503 sscanf(name, "mmcblk%dp%d", &dev, &part);
506 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
508 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
513 sscanf(name, "vd%31s", emul);
516 for (i = 0 ; i < strlen(emul) ; i++)
517 emul[i] = toupper(emul[i]);
518 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
522 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
530 snprintf(dev, sizeof(dev), "%s", devnode);
532 if (!strstr(dev, "sd"))
536 name += strlen("sd");
538 for (i = 0 ; i < strlen(name) ; i++)
539 name[i] = toupper(name[i]);
540 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
545 static char *generate_mount_path(struct block_data *data)
548 char *name, node[64];
551 if (!data || !data->devnode)
554 name = strrchr(data->devnode, '/');
559 switch (data->block_type) {
561 ret = get_mmc_mount_node(name, node, sizeof(node));
564 ret = get_scsi_mount_node(name, node, sizeof(node));
566 case BLOCK_MMC_EXTENDED_INTERNAL_DEV:
567 return strdup(EXTENDED_SD_PATH);
569 _E("Invalid block type (%d)", data->block_type);
575 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
581 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
585 static bool check_primary_partition(const char *devnode)
587 struct block_fs_ops *fs;
590 const char *filesystem = NULL;
600 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
601 fnmatch(MMC_PATH, devnode, 0) &&
602 fnmatch(SCSI_PATH, devnode, 0))
605 temp = strrchr(devnode, '/');
608 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
609 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
612 /* Emulator support only one partition */
616 snprintf(str, sizeof(str), "%s", devnode);
621 for (i = 1; i <= 9; ++i) {
622 snprintf(str2, sizeof(str2), "%s%d", str, i);
623 if (access(str2, R_OK) != 0)
626 probe = blkid_new_probe_from_filename(str2);
629 if (blkid_do_probe(probe) != 0)
632 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
634 blkid_free_probe(probe);
637 DD_LIST_FOREACH(fs_head, elem, fs) {
638 if (!strncmp(fs->name, filesystem, fs_len)) {
643 blkid_free_probe(probe);
649 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
655 /* Whole data in struct block_data should be freed. */
656 static struct block_data *make_block_data(const char *devnode,
658 const char *fs_usage,
660 const char *fs_version,
661 const char *fs_uuid_enc,
662 const char *readonly)
664 struct block_data *data;
666 /* devnode is unique value so it should exist. */
671 _E("Not support extended partition");
673 data = calloc(1, sizeof(struct block_data));
675 _E("calloc() failed");
679 data->devnode = strdup(devnode);
681 data->syspath = strdup(syspath);
683 data->fs_usage = strdup(fs_usage);
685 data->fs_type = strdup(fs_type);
687 data->fs_version = strdup(fs_version);
689 data->fs_uuid_enc = strdup(fs_uuid_enc);
691 data->readonly = atoi(readonly);
692 data->primary = check_primary_partition(devnode);
694 /* TODO should we know block dev type? */
695 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
696 data->block_type = BLOCK_MMC_DEV;
697 else if (!fnmatch(MMC_PATH, devnode, 0))
698 data->block_type = BLOCK_MMC_DEV;
699 else if (!fnmatch(SCSI_PATH, devnode, 0))
700 data->block_type = BLOCK_SCSI_DEV;
702 data->block_type = -1;
704 data->mount_point = generate_mount_path(data);
705 BLOCK_FLAG_CLEAR_ALL(data);
707 /* for 2.4 backward compatibility */
708 // What if storage id 1 is existed? (multi sdcard case)
709 if (data->primary == true && data->block_type == BLOCK_MMC_DEV)
710 data->id = EXT_PRIMARY_SD_FIXID;
712 data->id = block_get_new_id();
717 static void free_block_data(struct block_data *data)
723 free(data->fs_usage);
725 free(data->fs_version);
726 free(data->fs_uuid_enc);
727 free(data->mount_point);
731 static int update_block_data(struct block_data *data,
732 const char *fs_usage,
734 const char *fs_version,
735 const char *fs_uuid_enc,
736 const char *readonly,
737 bool mount_point_updated)
742 free(data->fs_usage);
743 data->fs_usage = NULL;
745 data->fs_usage = strdup(fs_usage);
748 data->fs_type = NULL;
750 data->fs_type = strdup(fs_type);
752 free(data->fs_version);
753 data->fs_version = NULL;
755 data->fs_version = strdup(fs_version);
757 free(data->fs_uuid_enc);
758 data->fs_uuid_enc = NULL;
760 data->fs_uuid_enc = strdup(fs_uuid_enc);
762 /* generate_mount_path function should be invoked
763 * after fs_uuid_enc is updated */
764 if (!mount_point_updated) {
765 free(data->mount_point);
766 data->mount_point = generate_mount_path(data);
769 data->readonly = false;
771 data->readonly = atoi(readonly);
773 BLOCK_FLAG_MOUNT_CLEAR(data);
778 static struct block_device *make_block_device(struct block_data *data)
780 struct block_device *bdev;
785 bdev = calloc(1, sizeof(struct block_device));
790 bdev->thread_id = -1;
791 bdev->removed = false;
792 bdev->on_private_op = REQ_NORMAL;
793 bdev->private_pid = 0;
794 bdev->mount_point_updated = false;
799 // Called by MainThread - Remove DevNode
800 static void free_block_device(struct block_device *bdev)
803 struct operation_queue *op;
809 thread_id = bdev->thread_id;
810 if (thread_id < 0 || thread_id >= THREAD_MAX)
813 pthread_mutex_lock(&(th_manager[thread_id].mutex));
815 th_manager[thread_id].num_dev--;
816 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
817 free_block_data(bdev->data);
819 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
821 th_manager[thread_id].op_len--;
822 DD_LIST_REMOVE(bdev->op_queue, op);
825 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
830 // Called By MainThread - Remove Device
831 static struct block_device *find_block_device(const char *devnode)
833 struct block_device *bdev;
838 len = strlen(devnode) + 1;
839 for (i = 0; i < THREAD_MAX; i++) {
840 pthread_mutex_lock(&(th_manager[i].mutex));
841 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
842 if (bdev->data && !bdev->removed &&
843 !strncmp(bdev->data->devnode, devnode, len)) {
844 pthread_mutex_unlock(&(th_manager[i].mutex));
848 pthread_mutex_unlock(&(th_manager[i].mutex));
854 // Called By MainThread - Mount,Unmount,Format,GetInfo
855 static struct block_device *find_block_device_by_id(int id)
857 struct block_device *bdev;
861 for (i = 0; i < THREAD_MAX; i++) {
862 pthread_mutex_lock(&(th_manager[i].mutex));
863 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
868 if (bdev->data->id == id) {
869 pthread_mutex_unlock(&(th_manager[i].mutex));
873 pthread_mutex_unlock(&(th_manager[i].mutex));
879 static char *get_operation_char(enum block_dev_operation op,
880 char *name, unsigned int len)
882 char *str = "unknown";
888 case BLOCK_DEV_MOUNT:
891 case BLOCK_DEV_UNMOUNT:
894 case BLOCK_DEV_FORMAT:
897 case BLOCK_DEV_INSERT:
900 case BLOCK_DEV_REMOVE:
904 _E("invalid operation (%d)", op);
908 snprintf(name, len, "%s", str);
912 static void create_external_apps_directory(void)
916 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
917 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
918 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
920 _E("Fail to create external directory");
923 static int pipe_trigger(enum block_dev_operation op,
924 struct block_device *bdev, int result)
926 struct pipe_data pdata = { op, bdev, result };
930 _D("op : %s, bdev : %p, result : %d",
931 get_operation_char(pdata.op, name, sizeof(name)),
932 pdata.bdev, pdata.result);
934 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
936 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
939 static bool pipe_cb(int fd, void *data)
941 struct pipe_data pdata = {0,};
947 n = read(fd, &pdata, sizeof(pdata));
948 if (n != sizeof(pdata) || !pdata.bdev) {
949 _E("fail to read struct pipe data");
953 _I("op : %s, bdev : %p, result : %d",
954 get_operation_char(pdata.op, name, sizeof(name)),
955 pdata.bdev, pdata.result);
957 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
958 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
959 ret = change_mount_point(pdata.bdev, "");
960 /* Modify /run/external-storage/id file */
962 if (pdata.bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
963 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
965 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
970 if (pdata.op == BLOCK_DEV_MOUNT &&
971 pdata.bdev->data->state == BLOCK_MOUNT &&
972 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
973 pdata.bdev->data->primary)
974 create_external_apps_directory();
975 if (pdata.op == BLOCK_DEV_UNMOUNT) {
976 /* Remove file for block device /run/xxxxxx/id */
977 if (pdata.bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
978 remove_file(pdata.bdev->data->id, true);
980 remove_file(pdata.bdev->data->id, false);
983 /* Broadcast to mmc and usb storage module */
984 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
986 /* Broadcast outside with Block iface */
987 if (pdata.bdev->on_private_op == REQ_NORMAL)
988 signal_device_changed(pdata.bdev, pdata.op);
989 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
990 if (pdata.op == BLOCK_DEV_UNMOUNT) {
991 pdata.bdev->on_private_op = REQ_NORMAL;
992 _D("Private operation state: %d", pdata.bdev->on_private_op);
995 if (pdata.op == BLOCK_DEV_MOUNT) {
996 pdata.bdev->on_private_op = REQ_PRIVATE;
997 _D("Private operation state: %d", pdata.bdev->on_private_op);
1001 if (pdata.op == BLOCK_DEV_REMOVE) {
1002 thread_id = pdata.bdev->thread_id;
1003 if (thread_id < 0 || thread_id >= THREAD_MAX)
1005 free_block_device(pdata.bdev);
1012 static int pipe_init(void)
1016 ret = pipe2(pfds, O_CLOEXEC);
1020 ret = add_fd_read_handler(pfds[0], pipe_cb,
1021 NULL, NULL, &phandler);
1023 _E("Failed to add pipe handler (%d)", ret);
1030 static void pipe_exit(void)
1033 remove_fd_read_handler(&phandler);
1043 static int mmc_check_and_unmount(const char *path)
1051 while (mount_check(path)) {
1055 if (retry > UNMOUNT_RETRY)
1062 static bool check_rw_mount(const char *szPath)
1064 struct statvfs mount_stat;
1066 if (!statvfs(szPath, &mount_stat)) {
1067 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1073 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1076 struct udev_device *dev;
1084 _E("fail to create udev library context");
1088 dev = udev_device_new_from_syspath(udev, data->syspath);
1090 _E("fail to create new udev device");
1095 r = update_block_data(data,
1096 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1097 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1098 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1099 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1100 udev_device_get_sysattr_value(dev, "ro"),
1101 mount_point_updated);
1103 _E("fail to update block data for %s", data->devnode);
1105 udev_device_unref(dev);
1110 static int block_mount(struct block_data *data)
1112 struct block_fs_ops *fs;
1117 if (!data || !data->devnode || !data->mount_point)
1120 /* check existing mounted */
1121 if (mount_check(data->mount_point))
1124 /* create mount point */
1125 if (access(data->mount_point, R_OK) != 0) {
1126 if (mkdir(data->mount_point, 0755) < 0)
1130 /* check matched file system */
1131 if (!data->fs_usage ||
1132 strncmp(data->fs_usage, FILESYSTEM,
1133 sizeof(FILESYSTEM)) != 0) {
1138 if (!data->fs_type) {
1139 _E("There is no file system");
1140 BLOCK_FLAG_SET(data, FS_EMPTY);
1146 len = strlen(data->fs_type) + 1;
1147 DD_LIST_FOREACH(fs_head, elem, fs) {
1148 if (!strncmp(fs->name, data->fs_type, len))
1153 _E("Not supported file system (%s)", data->fs_type);
1154 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1159 if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
1160 r = fs->mount(false, data->devnode, data->mount_point);
1162 r = fs->mount(smack, data->devnode, data->mount_point);
1165 BLOCK_FLAG_SET(data, FS_BROKEN);
1170 r = check_rw_mount(data->mount_point);
1177 rmdir(data->mount_point);
1181 static int mount_start(struct block_device *bdev)
1183 struct block_data *data;
1191 _I("Mount Start : (%s -> %s)",
1192 data->devnode, data->mount_point);
1194 /* mount operation */
1195 r = block_mount(data);
1196 if (r != -EROFS && r < 0) {
1197 _E("fail to mount %s device : %d", data->devnode, r);
1202 data->readonly = true;
1203 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1206 data->state = BLOCK_MOUNT;
1208 if (data->block_type == BLOCK_MMC_DEV) {
1209 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1210 ret = app2ext_migrate_legacy_all();
1212 _E("app2ext failed");
1216 if (r < 0 && r != -EROFS)
1217 data->state = BLOCK_UNMOUNT;
1219 _I("%s result : %s, %d", __func__, data->devnode, r);
1221 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1222 _E("fail to trigger pipe");
1227 static int change_mount_point(struct block_device *bdev,
1228 const char *mount_point)
1230 struct block_data *data;
1236 free(data->mount_point);
1238 /* If the mount path already exists, the path cannot be used */
1240 access(mount_point, F_OK) != 0) {
1241 data->mount_point = strdup(mount_point);
1242 bdev->mount_point_updated = true;
1244 data->mount_point = generate_mount_path(data);
1245 bdev->mount_point_updated = false;
1251 static int mount_block_device(struct block_device *bdev)
1253 struct block_data *data;
1256 if (!bdev || !bdev->data)
1260 if (data->state == BLOCK_MOUNT) {
1261 _I("%s is already mounted", data->devnode);
1265 if (!block_conf[data->block_type].multimount &&
1267 _I("Not support multi mount by config info");
1271 r = mount_start(bdev);
1273 _E("Failed to mount (%s)", data->devnode);
1280 static int block_unmount(struct block_device *bdev,
1281 enum unmount_operation option)
1283 struct block_data *data;
1285 struct timespec time = {0,};
1287 if (!bdev || !bdev->data || !bdev->data->mount_point)
1292 if (bdev->on_private_op == REQ_NORMAL)
1293 signal_device_blocked(bdev);
1295 /* it must called before unmounting mmc */
1296 r = mmc_check_and_unmount(data->mount_point);
1299 if (option == UNMOUNT_NORMAL) {
1300 _I("Failed to unmount with normal option : %d", r);
1304 _I("Execute force unmount!");
1305 /* Force Unmount Scenario */
1310 * should unmount the below vconf key. */
1311 if ((data->block_type == BLOCK_MMC_DEV ||
1312 data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV) &&
1314 /* At first, notify to other app
1315 * who already access sdcard */
1316 _I("Notify to other app who already access sdcard");
1317 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1318 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1322 /* Second, kill app with SIGTERM */
1323 _I("Kill app with SIGTERM");
1324 terminate_process(data->mount_point, false);
1327 /* Last time, kill app with SIGKILL */
1328 _I("Kill app with SIGKILL");
1329 terminate_process(data->mount_point, true);
1332 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1333 _I("Failed to unmount with lazy option : %d",
1340 /* it takes some seconds til other app completely clean up */
1341 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1342 nanosleep(&time, NULL);
1344 print_open_files(data->mount_point);
1346 r = mmc_check_and_unmount(data->mount_point);
1348 _D("Success to unmount (%s)", data->mount_point);
1354 data->state = BLOCK_UNMOUNT;
1356 if (rmdir(data->mount_point) < 0)
1357 _E("fail to remove %s directory", data->mount_point);
1362 static int unmount_block_device(struct block_device *bdev,
1363 enum unmount_operation option)
1365 struct block_data *data;
1368 if (!bdev || !bdev->data)
1372 if (data->state == BLOCK_UNMOUNT) {
1373 _I("%s is already unmounted", data->devnode);
1374 r = mmc_check_and_unmount(data->mount_point);
1376 _E("The path was existed, but could not delete it(%s)",
1381 _I("Unmount Start : (%s -> %s)",
1382 data->devnode, data->mount_point);
1384 r = block_unmount(bdev, option);
1386 _E("fail to unmount %s device : %d", data->devnode, r);
1390 BLOCK_FLAG_MOUNT_CLEAR(data);
1393 _I("%s result : %s, %d", __func__, data->devnode, r);
1395 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1396 _E("fail to trigger pipe");
1401 static int block_format(struct block_data *data,
1402 const char *fs_type, bool mount_point_updated)
1404 const struct block_fs_ops *fs;
1410 if (!data || !data->devnode || !data->mount_point)
1413 if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
1419 fstype = data->fs_type;
1425 len = strlen(fstype);
1426 DD_LIST_FOREACH(fs_head, elem, fs) {
1427 if (!strncmp(fs->name, fstype, len))
1432 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1433 _E("not supported file system(%s)", fstype);
1437 _I("format path : %s", data->devnode);
1438 fs->check(data->devnode);
1439 r = fs->format(data->devnode);
1441 _E("fail to format block data for %s", data->devnode);
1445 /* it takes some seconds til kernel set udev property */
1448 /* need to update the partition data.
1449 * It can be changed in doing format. */
1450 retrieve_udev_device(data, mount_point_updated);
1456 static int format_block_device(struct block_device *bdev,
1457 const char *fs_type,
1458 enum unmount_operation option)
1460 struct block_data *data;
1468 _I("Format Start : (%s -> %s)",
1469 data->devnode, data->mount_point);
1471 if (data->state == BLOCK_MOUNT) {
1472 r = block_unmount(bdev, option);
1474 _E("fail to unmount %s device : %d", data->devnode, r);
1479 r = block_format(data, fs_type, bdev->mount_point_updated);
1481 _E("fail to format %s device : %d", data->devnode, r);
1484 _I("%s result : %s, %d", __func__, data->devnode, r);
1486 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1488 _E("fail to trigger pipe");
1493 static struct format_data *get_format_data(
1494 const char *fs_type, enum unmount_operation option)
1496 struct format_data *fdata;
1498 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1500 _E("fail to allocate format data");
1505 fdata->fs_type = strdup(fs_type);
1507 fdata->fs_type = NULL;
1508 fdata->option = option;
1513 static void release_format_data(struct format_data *data)
1517 free(data->fs_type);
1522 // Called by BlockThread - Real Mount Op
1523 static int block_mount_device(struct block_device *bdev, void *data)
1532 thread_id = bdev->thread_id;
1533 if (thread_id < 0 || thread_id >= THREAD_MAX)
1535 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1536 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1537 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1539 _E("(%d) does not exist in the device list", bdev->data->devnode);
1543 /* mount automatically */
1544 ret = mount_block_device(bdev);
1546 _E("fail to mount block device for %s", bdev->data->devnode);
1551 // Called by BlockThread - Real Format Op
1552 static int block_format_device(struct block_device *bdev, void *data)
1557 struct format_data *fdata = (struct format_data *)data;
1559 if (!bdev || !fdata) {
1564 thread_id = bdev->thread_id;
1565 if (thread_id < 0 || thread_id >= THREAD_MAX)
1567 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1568 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1569 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1571 _E("(%d) does not exist in the device list", bdev->data->devnode);
1576 ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1578 _E("fail to mount block device for %s", bdev->data->devnode);
1581 release_format_data(fdata);
1586 // Called by BlockThread - Real Unmount Op
1587 static int block_unmount_device(struct block_device *bdev, void *data)
1590 long option = (long)data;
1595 ret = unmount_block_device(bdev, option);
1597 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1604 /* Called by BlockThread - Remove Operation
1605 Direct Call at BlockThread
1606 Previously this function was called by MainThread. However, it will increase complexity.
1607 Need thread lock before to call remove_operation
1609 static void remove_operation(struct block_device *bdev)
1611 struct operation_queue *op;
1618 thread_id = bdev->thread_id;
1619 if (thread_id < 0 || thread_id >= THREAD_MAX)
1622 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1624 _D("Remove operation (%s, %s)",
1625 get_operation_char(op->op, name, sizeof(name)),
1626 bdev->data->devnode);
1628 DD_LIST_REMOVE(bdev->op_queue, op);
1634 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1641 rep = make_dbus_reply_message_simple(reply_handle, result);
1642 reply_dbus_method_result(reply_handle, rep);
1645 // Called by BlockThread
1646 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1648 struct operation_queue *temp;
1661 thread_id = bdev->thread_id;
1662 if (thread_id < 0 || thread_id >= THREAD_MAX)
1665 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1667 DD_LIST_FOREACH(*queue, l, temp) {
1668 if (temp->op == BLOCK_DEV_REMOVE) {
1673 th_manager[thread_id].op_len--;
1674 block_send_dbus_reply((*op)->reply_handle, 0);
1677 remove_operation(bdev);
1678 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1681 // Called by BlockThread
1682 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1684 struct operation_queue *temp;
1687 bool unmounted = false;
1698 thread_id = bdev->thread_id;
1699 if (thread_id < 0 || thread_id >= THREAD_MAX)
1702 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1703 DD_LIST_FOREACH(*queue, l, temp) {
1704 if (temp->op == BLOCK_DEV_UNMOUNT) {
1706 _D("Operation queue has unmount operation");
1710 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1715 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1717 DD_LIST_FOREACH(*queue, l, temp) {
1718 if (temp->op == BLOCK_DEV_UNMOUNT) {
1723 th_manager[thread_id].op_len--;
1724 block_send_dbus_reply((*op)->reply_handle, 0);
1727 remove_operation(bdev);
1728 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1733 // Called by BlockThread
1734 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1738 char devnode[PATH_MAX];
1740 enum block_dev_operation operation;
1741 bool unmounted = false;
1748 thread_id = bdev->thread_id;
1749 if (thread_id < 0 || thread_id >= THREAD_MAX)
1752 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1762 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1763 get_operation_char(operation, name, sizeof(name)), devnode);
1766 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1767 check_removed(bdev, &queue, &op);
1769 _D("Trigger operation again (%s, %s)",
1770 get_operation_char(operation, name, sizeof(name)), devnode);
1772 if (operation == BLOCK_DEV_MOUNT) {
1773 unmounted = check_unmount(bdev, &queue, &op);
1776 _D("Trigger operation again (%s, %s)",
1777 get_operation_char(operation, name, sizeof(name)), devnode);
1781 switch (operation) {
1782 case BLOCK_DEV_INSERT:
1784 case BLOCK_DEV_MOUNT:
1785 ret = block_mount_device(bdev, op->data);
1786 _D("Mount (%s) result:(%d)", devnode, ret);
1788 case BLOCK_DEV_FORMAT:
1789 ret = block_format_device(bdev, op->data);
1790 _D("Format (%s) result:(%d)", devnode, ret);
1792 case BLOCK_DEV_UNMOUNT:
1793 ret = block_unmount_device(bdev, op->data);
1794 _D("Unmount (%s) result:(%d)", devnode, ret);
1796 case BLOCK_DEV_REMOVE:
1800 _E("Operation type is invalid (%d)", op->op);
1806 * during checking the queue length */
1807 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1810 th_manager[thread_id].op_len--;
1812 block_send_dbus_reply(op->reply_handle, ret);
1814 queue = bdev->op_queue;
1815 if (queue != NULL) {
1816 queue = DD_LIST_NEXT(queue);
1818 op = DD_LIST_NTH(queue, 0);
1824 remove_operation(bdev);
1826 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1830 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1831 if (pipe_trigger(operation, bdev, 0) < 0)
1832 _E("fail to trigger pipe");
1839 // Called by BlockThread
1840 static void *block_th_start(void *arg)
1842 struct block_device *temp;
1843 struct manage_thread *th = (struct manage_thread *)arg;
1844 struct operation_queue *op = NULL;
1846 dd_list *queue = NULL;
1851 thread_id = th->thread_id;
1852 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1853 _E("Thread Number: %d", th->thread_id);
1858 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1859 if (th_manager[thread_id].op_len == 0) {
1860 _D("Operation queue of thread is empty");
1861 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1862 _D("Wake up %d", thread_id);
1865 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1866 queue = temp->op_queue;
1868 op = DD_LIST_NTH(queue, 0);
1870 _D("Operation queue for device %s is Empty", temp->data->devnode);
1874 queue = DD_LIST_NEXT(queue);
1882 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1884 if (op && !op->done)
1885 trigger_operation(temp, queue, op);
1890 // This function will be refactored later
1891 // Especially, we don't need to keep th_node_list.
1892 static int find_thread(char *devnode)
1899 int i, len, min, min_num;
1900 int dev_mmc = -1, part = -1, num;
1903 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1904 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1911 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1912 th_node = strdup(str);
1913 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1914 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1915 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1916 th_node = strdup(str);
1920 len = strlen(th_node) + 1;
1923 for (i = 0; i < THREAD_MAX; i++) {
1924 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1925 if (!strncmp(temp, th_node, len))
1928 if (th_manager[i].num_dev < min_num) {
1929 min_num = th_manager[i].num_dev;
1934 if (min >= 0 && min < THREAD_MAX) {
1935 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1939 _E("Finding thread is failed");
1940 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1944 /* Only Main thread is permmited */
1945 // Called by MainThread
1946 static int add_operation(struct block_device *bdev,
1947 enum block_dev_operation operation,
1948 dbus_method_reply_handle_h reply_handle, void *data)
1950 struct operation_queue *op;
1960 _I("Add operation (%s, %s)",
1961 get_operation_char(operation, name, sizeof(name)),
1962 bdev->data->devnode);
1964 thread_id = bdev->thread_id;
1965 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1966 _E("Fail to find thread to add");
1970 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
1972 _E("malloc failed");
1978 op->reply_handle = reply_handle;
1981 * during adding queue and checking the queue length */
1982 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1984 /* Only modified between lock and unlock of mutex */
1987 start_th = th_manager[thread_id].start_th;
1988 DD_LIST_APPEND(bdev->op_queue, op);
1989 th_manager[thread_id].op_len++;
1991 if (th_manager[thread_id].op_len == 1 && !start_th)
1992 pthread_cond_signal(&(th_manager[thread_id].cond));
1994 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1997 /* Need to disble app2ext whenever unmounting mmc */
1998 if (op->op == BLOCK_DEV_UNMOUNT &&
1999 bdev->data->state == BLOCK_MOUNT &&
2000 bdev->data->block_type == BLOCK_MMC_DEV &&
2001 bdev->data->primary)
2002 if (app2ext_disable_all_external_pkgs() < 0)
2003 _E("app2ext_disable_all_external_pkgs() failed");
2007 _D("Start New thread for block device");
2008 th_manager[thread_id].start_th = false;
2009 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2011 _E("fail to create thread for %s", bdev->data->devnode);
2015 pthread_detach(th_manager[thread_id].th);
2021 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2024 struct dirent entry;
2026 const char *syspath;
2029 syspath = udev_device_get_syspath(dev);
2033 dp = opendir(syspath);
2035 _E("fail to open %s", syspath);
2039 /* TODO compare devname and d_name */
2040 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2041 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2042 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2054 static bool check_partition(struct udev_device *dev)
2056 const char *devtype;
2057 const char *part_table_type;
2058 const char *fs_usage;
2061 /* only consider disk type, never partitions */
2062 devtype = udev_device_get_devtype(dev);
2066 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2067 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2070 part_table_type = udev_device_get_property_value(dev,
2071 "ID_PART_TABLE_TYPE");
2072 if (part_table_type) {
2073 fs_usage = udev_device_get_property_value(dev,
2076 strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2077 if (!disk_is_partitioned_by_kernel(dev))
2084 if (disk_is_partitioned_by_kernel(dev)) {
2093 // Called by MainThread
2094 static int add_block_device(struct udev_device *dev, const char *devnode, bool init)
2096 struct block_data *data;
2097 struct block_device *bdev;
2098 char id_string[PATH_LEN];
2103 partition = check_partition(dev);
2105 /* if there is a partition, skip this request */
2106 _I("%s device has partitions, skip this time", devnode);
2110 data = make_block_data(devnode,
2111 udev_device_get_syspath(dev),
2112 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2113 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2114 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2115 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2116 udev_device_get_sysattr_value(dev, "ro"));
2118 _E("fail to make block data for %s", devnode);
2122 if (!block_conf[data->block_type].multimount && !data->primary) {
2123 _D("Not support multi mount by config info");
2127 bdev = make_block_device(data);
2129 _E("fail to make block device for %s", devnode);
2130 free_block_data(data);
2134 thread_id = find_thread(bdev->data->devnode);
2135 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2136 _E("Fail to find thread to add");
2137 free_block_device(bdev);
2140 bdev->thread_id = thread_id;
2142 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2143 th_manager[thread_id].num_dev++;
2144 DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2146 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2148 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2150 _E("Failed to add operation (insert %s)", devnode);
2151 free_block_device(bdev);
2155 /* Check this sdcard is already formatted for extended internal sdcard */
2156 if (block_conf[bdev->data->block_type].extendedinternal &&
2157 bdev->data->block_type == BLOCK_MMC_DEV &&
2158 bdev->data->primary) {
2159 _I("Check whether sdcard will be used as extended internal storage");
2161 if (!init) { // after booting is done
2162 snprintf(id_string, PATH_LEN, "%d", bdev->data->id);
2163 ret = launch_system_app(POPUP_DEFAULT, 4, POPUP_KEY_CONTENT, "sdcardsetup", POPUP_SDCARD_ID, id_string);
2165 _E("Failed to launch popup");
2167 } else { // at booting time
2168 if (!bdev->data->fs_type) {
2169 _E("Unformatted Storage");
2170 free_block_device(bdev);
2174 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2175 bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
2176 ret = change_mount_point(bdev, EXTENDED_SD_PATH);
2185 if (!bdev->data->fs_type) {
2186 _E("Unformatted Storage");
2187 free_block_device(bdev);
2192 /* Create file for block device /run/external-storage/id */
2193 if (bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
2194 create_file(bdev->data->id, bdev->data->mount_point, true);
2196 create_file(bdev->data->id, bdev->data->mount_point, false);
2197 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2199 _E("Failed to add operation (mount %s)", devnode);
2205 static int remove_block_device(struct udev_device *dev, const char *devnode)
2207 struct block_device *bdev;
2210 bdev = find_block_device(devnode);
2212 _E("fail to find block data for %s", devnode);
2216 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2218 bdev->removed = true;
2219 if (bdev->on_private_op != REQ_NORMAL) {
2220 bdev->on_private_op = REQ_NORMAL;
2221 _D("Private operation state: %d", bdev->on_private_op);
2224 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2226 _E("Failed to add operation (unmount %s)", devnode);
2230 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2232 _E("Failed to add operation (remove %s)", devnode);
2239 static int get_internal_storage_number(void)
2241 struct libmnt_table *t = NULL;
2242 struct libmnt_fs *fs;
2245 int r = 0, dev_temp;
2247 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2248 (is_emulator() && dev_internal_emul != '\0'))
2251 t = mnt_new_table();
2255 r = mnt_table_parse_mtab(t, NULL);
2261 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2267 temp = mnt_fs_get_srcpath(fs);
2271 name = strrchr(temp, '/');
2275 /* Boot from USB is not handled */
2276 if (!is_emulator()) {
2277 if (!fnmatch(MMC_PATH, temp, 0))
2278 sscanf(name, "mmcblk%d", &dev_internal);
2279 else if (!fnmatch(SCSI_PATH, temp, 0))
2280 sscanf(name, "sd%c", &dev_internal_scsi);
2282 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2283 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2285 dev_internal_emul = '\0';
2293 static int check_external_storage(const char* devnode)
2295 char dev_scsi = '\0';
2298 int dev_num = -1, dev_temp;
2303 name = strrchr(devnode, '/');
2307 if (!is_emulator()) {
2308 if (!fnmatch(MMC_PATH, devnode, 0)) {
2309 sscanf(name, "mmcblk%d", &dev_num);
2310 if (dev_internal == dev_num) {
2311 _D("%s is internal storage", devnode);
2314 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2315 sscanf(name, "sd%c", &dev_scsi);
2316 if (dev_internal_scsi == dev_scsi) {
2317 _D("%s is internal storage", devnode);
2322 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2323 sscanf(name, "vd%c%d", &emul, &dev_temp);
2324 if (dev_internal_emul == emul) {
2325 _D("%s is internal storage", devnode);
2334 static int check_already_handled(const char* devnode)
2336 struct block_device *bdev;
2337 struct block_data *data;
2341 for (i = 0; i < THREAD_MAX; i++) {
2342 pthread_mutex_lock(&(th_manager[i].mutex));
2343 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2349 if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2350 pthread_mutex_unlock(&(th_manager[i].mutex));
2354 pthread_mutex_unlock(&(th_manager[i].mutex));
2360 static int block_init_from_udev_enumerate(void)
2363 struct udev_enumerate *enumerate;
2364 struct udev_list_entry *list_entry, *list_sub_entry;
2365 struct udev_device *dev;
2366 const char *syspath;
2367 const char *devnode;
2372 _E("fail to create udev library context");
2376 /* create a list of the devices in the 'usb' subsystem */
2377 enumerate = udev_enumerate_new(udev);
2379 _E("fail to create an enumeration context");
2383 if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2384 (is_emulator() && dev_internal_emul == '\0')) {
2385 r = get_internal_storage_number();
2390 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2391 udev_enumerate_add_match_property(enumerate,
2392 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2393 udev_enumerate_add_match_property(enumerate,
2394 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2395 udev_enumerate_scan_devices(enumerate);
2397 udev_list_entry_foreach(list_entry,
2398 udev_enumerate_get_list_entry(enumerate)) {
2399 syspath = udev_list_entry_get_name(list_entry);
2403 dev = udev_device_new_from_syspath(
2404 udev_enumerate_get_udev(enumerate),
2410 udev_list_entry_foreach(list_sub_entry,
2411 udev_device_get_devlinks_list_entry(dev)) {
2412 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2413 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2420 devnode = udev_device_get_devnode(dev);
2424 if (fnmatch(MMC_PATH, devnode, 0) &&
2425 fnmatch(SCSI_PATH, devnode, 0))
2429 r = check_external_storage(devnode);
2433 r = check_already_handled(devnode);
2435 _I("%s is already handled", devnode);
2439 _I("%s device add", devnode);
2440 add_block_device(dev, devnode, true);
2442 udev_device_unref(dev);
2445 udev_enumerate_unref(enumerate);
2450 // Called by MainThread
2451 static void show_block_device_list(void)
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 _D("%s:", data->devnode);
2467 _D("\tSyspath: %s", data->syspath);
2468 _D("\tBlock type: %d", data->block_type);
2469 _D("\tFs type: %s", data->fs_type);
2470 _D("\tFs usage: %s", data->fs_usage);
2471 _D("\tFs version: %s", data->fs_version);
2472 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2473 _D("\tReadonly: %s",
2474 (data->readonly ? "true" : "false"));
2475 _D("\tMount point: %s", data->mount_point);
2476 _D("\tMount state: %s",
2477 (data->state == BLOCK_MOUNT ?
2478 "mount" : "unmount"));
2480 (data->primary ? "true" : "false"));
2481 _D("\tID: %d", data->id);
2483 pthread_mutex_unlock(&(th_manager[i].mutex));
2487 // Called by MainThread
2488 static void remove_whole_block_device(void)
2490 struct block_device *bdev;
2496 for (i = 0; i < THREAD_MAX; i++) {
2498 pthread_mutex_lock(&(th_manager[i].mutex));
2499 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2500 if (bdev->removed == false)
2503 pthread_mutex_unlock(&(th_manager[i].mutex));
2505 if (bdev && bdev->removed == false) {
2506 bdev->removed = true;
2507 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2509 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2511 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2513 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2520 static void booting_done(const char *sender_name,
2521 const char *object_path, const char *interface_name,
2522 const char *signal_name, DBusMessage *msg,
2525 static int done = 0;
2530 /* if there is the attached device, try to mount */
2531 block_init_from_udev_enumerate();
2532 block_control = true;
2536 static void block_poweroff(const char *sender_name,
2537 const char *object_path, const char *interface_name,
2538 const char *signal_name, DBusMessage *msg,
2541 static int status = 0;
2546 /* unregister mmc uevent control routine */
2547 unregister_udev_uevent_control(&uh);
2548 remove_whole_block_device();
2551 static void uevent_block_handler(struct udev_device *dev)
2553 const char *devnode = NULL;
2555 struct udev_list_entry *list_entry;
2558 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2559 const char *devlink = udev_list_entry_get_name(list_entry);
2560 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2567 devnode = udev_device_get_devnode(dev);
2571 if (fnmatch(MMC_PATH, devnode, 0) &&
2572 fnmatch(SCSI_PATH, devnode, 0))
2576 r = check_external_storage(devnode);
2580 action = udev_device_get_action(dev);
2584 _I("%s device %s", devnode, action);
2585 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD))) {
2586 r = check_already_handled(devnode);
2588 _I("%s is already handled", devnode);
2592 add_block_device(dev, devnode, false);
2593 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE)))
2594 remove_block_device(dev, devnode);
2597 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2598 DBusMessage *msg, bool onprivate)
2600 struct block_device *bdev;
2605 if (!reply_handle || !msg)
2608 ret = dbus_message_get_args(msg, NULL,
2609 DBUS_TYPE_INT32, &id,
2610 DBUS_TYPE_STRING, &mount_point,
2615 bdev = find_block_device_by_id(id);
2617 _E("Failed to find (%d) in the device list", id);
2621 if (bdev->on_private_op != REQ_NORMAL) {
2626 if (bdev->data->state == BLOCK_MOUNT) {
2627 _I("%s is already mounted", bdev->data->devnode);
2633 bdev->on_private_op = REQ_PRIVATE;
2634 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2635 _D("Private operation state: %d", bdev->on_private_op);
2637 if (bdev->on_private_op != REQ_NORMAL) {
2638 _E("Failed to process mount operation");
2644 /* if requester want to use a specific mount point */
2646 !strncmp(mount_point, EXTENDED_SD_STRING, strlen(EXTENDED_SD_STRING) + 1) != 0) {
2647 if (!block_conf[bdev->data->block_type].extendedinternal ||
2648 !bdev->data->primary) {
2649 _E("Not support extended internal storage");
2653 bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
2654 ret = change_mount_point(bdev, EXTENDED_SD_PATH);
2660 create_file(bdev->data->id, bdev->data->mount_point, true);
2662 } else if (mount_point && strncmp(mount_point, "", 1) != 0) {
2663 ret = change_mount_point(bdev, mount_point);
2669 /* Create /run/external-storage/id file */
2670 create_file(bdev->data->id, bdev->data->mount_point, false);
2672 /* Create file for block device /run/external-storage/id */
2673 create_file(bdev->data->id, bdev->data->mount_point, false);
2676 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2678 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2685 return make_dbus_reply_message_simple(reply_handle, ret);
2688 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2691 return request_mount_block(reply_handle, msg, false);
2694 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2697 return request_mount_block(reply_handle, msg, true);
2700 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2701 DBusMessage *msg, bool onprivate)
2703 struct block_device *bdev;
2709 if (!reply_handle || !msg)
2712 ret = dbus_message_get_args(msg, NULL,
2713 DBUS_TYPE_INT32, &id,
2714 DBUS_TYPE_INT32, &option,
2719 bdev = find_block_device_by_id(id);
2721 _E("Failed to find (%d) in the device list", id);
2725 if (bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV) {
2726 _I("Impossible to request unmount extended internal sdcard");
2732 pid = get_dbus_method_sender_pid(reply_handle);
2733 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2734 _E("Failed to process private unmount operation");
2739 if (bdev->on_private_op != REQ_NORMAL) {
2740 _E("Failed to process unmount operation");
2746 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2748 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2755 return make_dbus_reply_message_simple(reply_handle, ret);
2758 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2761 return request_unmount_block(reply_handle, msg, false);
2764 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2767 return request_unmount_block(reply_handle, msg, true);
2770 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2773 struct block_device *bdev;
2774 struct format_data *fdata;
2781 if (!reply_handle || !msg)
2784 ret = dbus_message_get_args(msg, NULL,
2785 DBUS_TYPE_INT32, &id,
2786 DBUS_TYPE_INT32, &option,
2791 bdev = find_block_device_by_id(id);
2793 _E("Failed to find (%d) in the device list", id);
2797 pid = get_dbus_method_sender_pid(reply_handle);
2798 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2799 _E("Failed to format on private state");
2804 fdata = get_format_data(NULL, option);
2806 _E("Failed to get format data");
2810 prev_state = bdev->data->state;
2811 if (prev_state == BLOCK_MOUNT) {
2812 if (bdev->on_private_op == REQ_PRIVATE) {
2813 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2814 _D("Private operation state: %d", bdev->on_private_op);
2816 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2818 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2819 release_format_data(fdata);
2824 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2826 _E("Failed to add operation (format %s)", bdev->data->devnode);
2827 release_format_data(fdata);
2830 /* Maintain previous state of mount/unmount */
2831 if (prev_state == BLOCK_MOUNT) {
2832 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2833 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2841 return make_dbus_reply_message_simple(reply_handle, ret);
2844 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2847 struct block_device *bdev;
2848 struct format_data *fdata;
2856 if (!reply_handle || !msg)
2859 ret = dbus_message_get_args(msg, NULL,
2860 DBUS_TYPE_INT32, &id,
2861 DBUS_TYPE_INT32, &option,
2862 DBUS_TYPE_STRING, &type,
2867 bdev = find_block_device_by_id(id);
2869 _E("Failed to find (%d) in the device list", id);
2873 pid = get_dbus_method_sender_pid(reply_handle);
2874 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2875 _E("Failed to format on private state");
2880 fdata = get_format_data(type, option);
2882 _E("Failed to get format data");
2886 prev_state = bdev->data->state;
2887 if (prev_state == BLOCK_MOUNT) {
2888 if (bdev->on_private_op == REQ_PRIVATE) {
2889 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2890 _D("Private operation state: %d", bdev->on_private_op);
2892 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2894 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2895 release_format_data(fdata);
2900 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2902 _E("Failed to add operation (format %s)", bdev->data->devnode);
2903 release_format_data(fdata);
2906 /* Maintain previous state of mount/unmount */
2907 if (prev_state == BLOCK_MOUNT) {
2908 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2909 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2917 return make_dbus_reply_message_simple(reply_handle, ret);
2920 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
2922 char *str_null = "";
2924 if (!data || !piter)
2927 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2928 &(data->block_type));
2929 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2930 data->devnode ? &(data->devnode) : &str_null);
2931 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2932 data->syspath ? &(data->syspath) : &str_null);
2933 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2934 data->fs_usage ? &(data->fs_usage) : &str_null);
2935 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2936 data->fs_type ? &(data->fs_type) : &str_null);
2937 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2938 data->fs_version ? &(data->fs_version) : &str_null);
2939 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2940 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2941 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2943 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2944 data->mount_point ? &(data->mount_point) : &str_null);
2945 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2947 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
2949 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2951 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2958 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
2960 DBusMessageIter piter;
2965 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2966 add_device_to_iter(data, &piter);
2967 dbus_message_iter_close_container(iter, &piter);
2972 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
2974 DBusMessageIter piter;
2975 char *str_null = "";
2980 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2981 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2982 &(data->block_type));
2983 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2984 data->devnode ? &(data->devnode) : &str_null);
2985 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2986 data->syspath ? &(data->syspath) : &str_null);
2987 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2988 data->fs_usage ? &(data->fs_usage) : &str_null);
2989 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2990 data->fs_type ? &(data->fs_type) : &str_null);
2991 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2992 data->fs_version ? &(data->fs_version) : &str_null);
2993 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2994 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2995 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2997 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2998 data->mount_point ? &(data->mount_point) : &str_null);
2999 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3001 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3003 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3005 dbus_message_iter_close_container(iter, &piter);
3010 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3013 DBusMessageIter iter;
3015 struct block_device *bdev;
3016 struct block_data *data;
3019 if (!reply_handle || !msg)
3022 reply = make_dbus_reply_message(reply_handle);
3026 ret = dbus_message_get_args(msg, NULL,
3027 DBUS_TYPE_INT32, &id,
3032 bdev = find_block_device_by_id(id);
3039 dbus_message_iter_init_append(reply, &iter);
3040 add_device_to_iter(data, &iter);
3046 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3049 show_block_device_list();
3050 return make_dbus_reply_message(reply_handle);
3053 // Called by MainThread
3054 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3057 DBusMessageIter iter;
3058 DBusMessageIter aiter;
3060 struct block_device *bdev;
3061 struct block_data *data;
3068 reply = make_dbus_reply_message(reply_handle);
3070 ret = dbus_message_get_args(msg, NULL,
3071 DBUS_TYPE_STRING, &type,
3074 _E("Failed to get args");
3079 _E("Delivered type is NULL");
3083 _D("Block (%s) device list is requested", type);
3085 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3086 block_type = BLOCK_SCSI_DEV;
3087 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3088 block_type = BLOCK_MMC_DEV;
3089 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3092 _E("Invalid type (%s) is requested", type);
3096 dbus_message_iter_init_append(reply, &iter);
3097 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3099 for (i = 0; i < THREAD_MAX; i++) {
3100 pthread_mutex_lock(&(th_manager[i].mutex));
3101 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3108 switch (block_type) {
3109 case BLOCK_SCSI_DEV:
3111 if (data->block_type != block_type)
3117 add_device_to_struct_iter(data, &aiter);
3119 pthread_mutex_unlock(&(th_manager[i].mutex));
3121 dbus_message_iter_close_container(&iter, &aiter);
3127 // Called by MainThread
3128 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3131 DBusMessageIter iter;
3132 DBusMessageIter aiter;
3134 struct block_device *bdev;
3135 struct block_data *data;
3142 reply = make_dbus_reply_message(reply_handle);
3144 ret = dbus_message_get_args(msg, NULL,
3145 DBUS_TYPE_STRING, &type,
3148 _E("Failed to get args");
3153 _E("Delivered type is NULL");
3157 _D("Block (%s) device list is requested", type);
3159 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3160 block_type = BLOCK_SCSI_DEV;
3161 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3162 block_type = BLOCK_MMC_DEV;
3163 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3166 _E("Invalid type (%s) is requested", type);
3170 dbus_message_iter_init_append(reply, &iter);
3171 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3173 for (i = 0; i < THREAD_MAX; i++) {
3174 pthread_mutex_lock(&(th_manager[i].mutex));
3175 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3182 switch (block_type) {
3183 case BLOCK_SCSI_DEV:
3185 if (data->block_type != block_type)
3192 add_device_to_iter_2(data, &aiter);
3194 pthread_mutex_unlock(&(th_manager[i].mutex));
3196 dbus_message_iter_close_container(&iter, &aiter);
3202 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3205 DBusMessageIter iter;
3207 struct block_device *bdev;
3208 struct block_data *data, nodata = {0,};
3213 if (!reply_handle || !msg)
3216 reply = make_dbus_reply_message(reply_handle);
3221 for (i = 0; i < THREAD_MAX; i++) {
3222 pthread_mutex_lock(&(th_manager[i].mutex));
3223 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3229 if (data->block_type != BLOCK_MMC_DEV)
3236 pthread_mutex_unlock(&(th_manager[i].mutex));
3241 dbus_message_iter_init_append(reply, &iter);
3243 add_device_to_iter(data, &iter);
3245 nodata.id = -ENODEV;
3246 add_device_to_iter(&nodata, &iter);
3254 Method name Method call format string Reply format string
3255 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3256 { "GetDeviceList", "s", "a(issssssisibii)", request_get_device_list },
3257 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3258 { "Mount", "is", "i", request_public_mount_block },
3259 { "Unmoun, "ii", "i", request_public_unmount_block },
3260 { "Format", "ii", "i", request_format_block },
3261 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3262 { "GetMmcPrimary", NULL, "(issssssisibii)" , request_get_mmc_primary },
3263 { "PrivateMount", "is", "i", request_private_mount_block },
3264 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3267 static const dbus_method_s manager_methods[] = {
3268 { "ShowDeviceList", NULL, request_show_device_list },
3269 { "GetDeviceList" , "s", request_get_device_list },
3270 { "GetDeviceList2", "s", request_get_device_list_2 },
3271 { "Mount", "is", request_public_mount_block },
3272 { "Unmount", "ii", request_public_unmount_block },
3273 { "Format", "ii", request_format_block },
3274 { "FormatwithType", "iis", request_format_block_type },
3275 { "GetDeviceInfo", "i", request_get_device_info },
3276 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3277 { "PrivateMount", "is", request_private_mount_block },
3278 { "PrivateUnmount", "ii", request_private_unmount_block },
3281 static dbus_interface_s block_interface = {
3282 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3283 .methods = manager_methods,
3284 .nr_methods = ARRAY_SIZE(manager_methods),
3287 static int load_config(struct parse_result *result, void *user_data)
3291 if (MATCH(result->section, "Block"))
3294 if (MATCH(result->section, "SCSI"))
3295 index = BLOCK_SCSI_DEV;
3296 else if (MATCH(result->section, "MMC"))
3297 index = BLOCK_MMC_DEV;
3301 if (MATCH(result->name, "Multimount"))
3302 block_conf[index].multimount =
3303 (MATCH(result->value, "yes") ? true : false);
3304 if (MATCH(result->name, "ExtendedInternalStorage"))
3305 block_conf[index].extendedinternal =
3306 (MATCH(result->value, "yes") ? true : false);
3308 if (index == BLOCK_MMC_DEV) {
3309 block_conf[index + 1].multimount = block_conf[index].multimount;
3310 block_conf[index + 1].extendedinternal = block_conf[index].extendedinternal;
3317 static int mount_root_path_tmpfs(void)
3322 root = tzplatform_getenv(TZ_SYS_MEDIA);
3326 if (access(root, F_OK) != 0)
3329 if (mount_check(root))
3332 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3335 _E("tmpfs mount failed (%d)", ret);
3342 #define mount_root_path_tmpfs() 0
3345 static void block_init(void *data)
3350 dbus_handle_h handle;
3355 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3357 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3359 ret = mount_root_path_tmpfs();
3361 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3363 ret = dbus_get_connection(&handle);
3365 _E("Failed to get dbus connection(%d)", ret);
3367 /* register block manager object and interface */
3368 ret = register_dbus_methods(handle,
3369 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3372 _E("Failed to register block interface and methods (%d)", ret);
3377 _E("fail to init pipe");
3379 /* register mmc uevent control routine */
3380 ret = register_udev_uevent_control(&uh);
3382 _E("fail to register block uevent : %d", ret);
3384 /* System Session is loaded completely */
3385 register_dbus_signal(SYSTEMD_DBUS_PATH,
3386 SYSTEMD_DBUS_IFACE_MANAGER,
3387 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3388 booting_done, NULL, NULL);
3390 register_dbus_signal(DEVICED_PATH_POWEROFF,
3391 DEVICED_INTERFACE_POWEROFF,
3392 SIGNAL_POWEROFF_STATE,
3393 block_poweroff, NULL, NULL);
3395 for (i = 0; i < THREAD_MAX; i++) {
3396 th_manager[i].num_dev = 0;
3397 th_manager[i].op_len = 0;
3398 th_manager[i].start_th = true;
3399 th_manager[i].thread_id = i;
3400 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3401 pthread_cond_init(&(th_manager[i].cond), NULL);
3404 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3406 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3408 _E("Failed to make directory: %d", errno);
3409 } else if (!S_ISDIR(buf.st_mode)) {
3410 ret = remove(EXTERNAL_STORAGE_PATH);
3412 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3413 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3415 _E("Failed to make directory: %d", errno);
3417 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3419 _E("Fail to change permissions of a file");
3422 ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3424 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3426 _E("Failed to make directory: %d", errno);
3427 } else if (!S_ISDIR(buf.st_mode)) {
3428 ret = remove(EXTENDED_INTERNAL_PATH);
3430 _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3431 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3433 _E("Failed to make directory: %d", errno);
3435 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3437 _E("Fail to change permissions of a file");
3441 static void block_exit(void *data)
3447 /* unregister notifier for below each event */
3448 unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3449 SYSTEMD_DBUS_IFACE_MANAGER,
3450 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3453 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3454 DEVICED_INTERFACE_POWEROFF,
3455 SIGNAL_POWEROFF_STATE, block_poweroff);
3460 /* unregister mmc uevent control routine */
3461 ret = unregister_udev_uevent_control(&uh);
3463 _E("fail to unregister block uevent : %d", ret);
3465 /* remove remaining blocks */
3466 remove_whole_block_device();
3468 for (i = 0; i < THREAD_MAX; i++) {
3469 if (!th_manager[i].start_th)
3470 pthread_cancel(th_manager[i].th);
3473 block_control = false;
3476 static int block_start(void *data)
3481 _E("Cannot be started. Booting is not ready");
3485 if (block_control) {
3486 _I("Already started");
3490 /* register mmc uevent control routine */
3491 ret = register_udev_uevent_control(&uh);
3493 _E("fail to register block uevent : %d", ret);
3495 block_init_from_udev_enumerate();
3497 block_control = true;
3503 static int block_stop(void *data)
3506 _E("Cannot be stopped. Booting is not ready");
3510 if (!block_control) {
3511 _I("Already stopped");
3515 /* unregister mmc uevent control routine */
3516 unregister_udev_uevent_control(&uh);
3518 /* remove the existing blocks */
3519 remove_whole_block_device();
3521 block_control = false;
3527 static storaged_module_interface block_module = {
3531 .start = block_start,
3535 __attribute__ ((visibility("default")))storaged_module_interface *
3536 storaged_get_module_interface(void)
3538 return &block_module;