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"
55 * TODO Assume root device is always mmcblk0*.
57 #define MMC_PATH "*/mmcblk[0-9]*"
58 #define MMC_PARTITION_PATH "mmcblk[0-9]p[0-9]"
59 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
60 #define MMC_LINK_PATH "*/sdcard/*"
61 #define SCSI_PATH "*/sd[a-z]*"
62 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
63 #define SCSI_PARTITION_LENGTH 9
65 #define FILESYSTEM "filesystem"
67 #define DEV_PREFIX "/dev/"
70 #define UNMOUNT_RETRY 5
71 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
73 #define SIGNAL_BOOTING_DONE "BootingDone"
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"
94 /* Minimum value of block id */
95 #define BLOCK_ID_MIN 10
96 /* For 2.4 Backward Compatibility */
97 #define EXT_PRIMARY_SD_FIXID 1
99 /* Maximum number of thread */
102 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
103 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
104 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
106 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
108 enum block_dev_operation {
116 enum private_operation_state {
122 struct operation_queue {
123 enum block_dev_operation op;
124 dbus_method_reply_handle_h reply_handle;
129 struct block_device {
130 struct block_data *data;
132 int thread_id; /* Current thread ID */
133 bool removed; /* True when device is physically removed but operation is not precessed yet */
134 enum private_operation_state on_private_op;
135 bool mount_point_updated;
140 struct block_device *bdev;
142 enum unmount_operation option;
146 enum block_dev_operation op;
147 struct block_device *bdev;
151 static struct block_conf {
153 } block_conf[BLOCK_MMC_DEV + 1];
155 static struct manage_thread {
156 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
157 dd_list *block_dev_list; /* Use thread mutex */
159 pthread_mutex_t mutex;
161 int num_dev; /* Number of devices which thread holds. Only main thread access */
162 int op_len; /* Number of operation of thread. Use thread mutex */
163 int thread_id; /* Never changed */
165 } th_manager[THREAD_MAX];
167 static dd_list *fs_head;
168 static dd_list *block_ops_list;
171 static fd_handler_h phandler;
172 static bool block_control = false;
173 static bool block_boot = false;
175 /* Assume there is only one physical internal storage */
176 static int dev_internal = -1;
177 static char dev_internal_scsi = '\0';
178 static char dev_internal_emul = '\0';
180 static int add_operation(struct block_device *bdev,
181 enum block_dev_operation operation,
182 dbus_method_reply_handle_h reply_handle, void *data);
183 static void remove_operation(struct block_device *bdev);
184 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
185 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
186 static int change_mount_point(struct block_device *bdev, const char *mount_point);
188 static void uevent_block_handler(struct udev_device *dev);
189 static struct uevent_handler uh = {
190 .subsystem = BLOCK_SUBSYSTEM,
191 .uevent_func = uevent_block_handler,
194 static void __CONSTRUCTOR__ smack_check(void)
199 fp = fopen("/proc/filesystems", "r");
203 while (fgets(buf, sizeof(buf), fp) != NULL) {
204 if (strstr(buf, "smackfs")) {
213 void add_fs(const struct block_fs_ops *fs)
215 DD_LIST_APPEND(fs_head, (void *)fs);
218 void remove_fs(const struct block_fs_ops *fs)
220 DD_LIST_REMOVE(fs_head, (void *)fs);
223 const struct block_fs_ops *find_fs(enum block_fs_type type)
225 struct block_fs_ops *fs;
228 DD_LIST_FOREACH(fs_head, elem, fs) {
229 if (fs->type == type)
235 void add_block_dev(const struct block_dev_ops *ops)
237 DD_LIST_APPEND(block_ops_list, (void *)ops);
240 void remove_block_dev(const struct block_dev_ops *ops)
242 DD_LIST_REMOVE(block_ops_list, (void *)ops);
245 static void broadcast_block_info(enum block_dev_operation op,
246 struct block_data *data, int result)
248 struct block_dev_ops *ops;
251 DD_LIST_FOREACH(block_ops_list, elem, ops) {
252 if (ops->block_type != data->block_type)
254 if (op == BLOCK_DEV_MOUNT)
255 ops->mounted(data, result);
256 else if (op == BLOCK_DEV_UNMOUNT)
257 ops->unmounted(data, result);
258 else if (op == BLOCK_DEV_FORMAT)
259 ops->formatted(data, result);
260 else if (op == BLOCK_DEV_INSERT)
262 else if (op == BLOCK_DEV_REMOVE)
267 // Called by MainThread - Insert
268 static int block_get_new_id(void)
270 static int id = BLOCK_ID_MIN;
271 struct block_device *bdev;
276 for (i = 0 ; i < INT_MAX ; i++) {
278 for (j = 0; j < THREAD_MAX; j++) {
279 pthread_mutex_lock(&(th_manager[j].mutex));
280 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
281 if (bdev->data->id == id) {
286 pthread_mutex_unlock(&(th_manager[j].mutex));
301 static void remove_file(int id)
303 char file_name[PATH_LEN];
309 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
311 ret = remove(file_name);
313 _E("Fail to remove %s. errno: %d", file_name, errno);
316 static void create_file(int id, char *mount_point)
319 char file_name[PATH_LEN];
324 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
326 fp = fopen(file_name, "w+");
328 fprintf(fp, "%s", mount_point);
331 _E("Fail to open %s", file_name);
334 static void signal_device_blocked(struct block_device *bdev)
336 struct block_data *data;
338 char str_block_type[32];
339 char str_readonly[32];
341 char str_primary[32];
347 if (!bdev || !bdev->data)
353 /* Broadcast outside with BlockManager iface */
354 snprintf(str_block_type, sizeof(str_block_type),
355 "%d", data->block_type);
356 arr[0] = str_block_type;
357 arr[1] = (data->devnode ? data->devnode : str_null);
358 arr[2] = (data->syspath ? data->syspath : str_null);
359 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
360 arr[4] = (data->fs_type ? data->fs_type : str_null);
361 arr[5] = (data->fs_version ? data->fs_version : str_null);
362 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
363 snprintf(str_readonly, sizeof(str_readonly),
364 "%d", data->readonly);
365 arr[7] = str_readonly;
366 arr[8] = (data->mount_point ? data->mount_point : str_null);
367 snprintf(str_state, sizeof(str_state),
370 snprintf(str_primary, sizeof(str_primary),
371 "%d", data->primary);
372 arr[10] = str_primary;
373 snprintf(str_flags, sizeof(str_flags), "%d", flags);
375 snprintf(str_id, sizeof(str_id), "%d", data->id);
378 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
379 STORAGED_INTERFACE_BLOCK_MANAGER,
380 BLOCK_DEVICE_BLOCKED,
381 "issssssisibii", arr);
384 static void signal_device_changed(struct block_device *bdev,
385 enum block_dev_operation op)
387 struct block_data *data;
389 char str_block_type[32];
390 char str_readonly[32];
392 char str_primary[32];
398 if (!bdev || !bdev->data)
404 case BLOCK_DEV_MOUNT:
405 BLOCK_GET_MOUNT_FLAGS(data, flags);
407 case BLOCK_DEV_UNMOUNT:
408 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
410 case BLOCK_DEV_FORMAT:
411 BLOCK_GET_FORMAT_FLAGS(data, flags);
418 /* Broadcast outside with BlockManager iface */
419 snprintf(str_block_type, sizeof(str_block_type),
420 "%d", data->block_type);
421 arr[0] = str_block_type;
422 arr[1] = (data->devnode ? data->devnode : str_null);
423 arr[2] = (data->syspath ? data->syspath : str_null);
424 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
425 arr[4] = (data->fs_type ? data->fs_type : str_null);
426 arr[5] = (data->fs_version ? data->fs_version : str_null);
427 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
428 snprintf(str_readonly, sizeof(str_readonly),
429 "%d", data->readonly);
430 arr[7] = str_readonly;
431 arr[8] = (data->mount_point ? data->mount_point : str_null);
432 snprintf(str_state, sizeof(str_state),
435 snprintf(str_primary, sizeof(str_primary),
436 "%d", data->primary);
437 arr[10] = str_primary;
438 snprintf(str_flags, sizeof(str_flags), "%d", flags);
440 snprintf(str_id, sizeof(str_id), "%d", data->id);
443 if (op == BLOCK_DEV_INSERT)
444 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
445 STORAGED_INTERFACE_BLOCK_MANAGER,
447 "issssssisibii", arr);
448 else if (op == BLOCK_DEV_REMOVE)
449 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
450 STORAGED_INTERFACE_BLOCK_MANAGER,
451 BLOCK_DEVICE_REMOVED,
452 "issssssisibii", arr);
454 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
455 STORAGED_INTERFACE_BLOCK_MANAGER,
456 BLOCK_DEVICE_CHANGED,
457 "issssssisibii", arr);
458 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
459 STORAGED_INTERFACE_BLOCK_MANAGER,
460 BLOCK_DEVICE_CHANGED_2,
461 "issssssisibi", arr);
465 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
467 char *name = devnode;
468 int dev = -1, part = -1;
469 char emul[32] = { 0, };
476 sscanf(name, "mmcblk%dp%d", &dev, &part);
479 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
481 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
486 sscanf(name, "vd%s", emul);
489 for (i = 0 ; i < strlen(emul) ; i++)
490 emul[i] = toupper(emul[i]);
491 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
495 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
503 snprintf(dev, sizeof(dev), "%s", devnode);
505 if (!strstr(dev, "sd"))
509 name += strlen("sd");
511 for (i = 0 ; i < strlen(name) ; i++)
512 name[i] = toupper(name[i]);
513 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
518 static char *generate_mount_path(struct block_data *data)
521 char *name, node[64];
524 if (!data || !data->devnode)
527 name = strrchr(data->devnode, '/');
532 switch (data->block_type) {
534 ret = get_mmc_mount_node(name, node, sizeof(node));
537 ret = get_scsi_mount_node(name, node, sizeof(node));
540 _E("Invalid block type (%d)", data->block_type);
546 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
552 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
556 static bool check_primary_partition(const char *devnode)
558 struct block_fs_ops *fs;
561 const char *filesystem = NULL;
571 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
572 fnmatch(MMC_PATH, devnode, 0) &&
573 fnmatch(SCSI_PATH, devnode, 0))
576 temp = strrchr(devnode, '/');
579 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
580 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
583 /* Emulator support only one partition */
587 snprintf(str, sizeof(str), "%s", devnode);
592 for (i = 1; i <= 9; ++i) {
593 snprintf(str2, sizeof(str2), "%s%d", str, i);
594 if (access(str2, R_OK) != 0)
597 probe = blkid_new_probe_from_filename(str2);
600 if (blkid_do_probe(probe) != 0)
603 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
605 blkid_free_probe(probe);
608 DD_LIST_FOREACH(fs_head, elem, fs) {
609 if (!strncmp(fs->name, filesystem, fs_len)) {
614 blkid_free_probe(probe);
620 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
626 /* Whole data in struct block_data should be freed. */
627 static struct block_data *make_block_data(const char *devnode,
629 const char *fs_usage,
631 const char *fs_version,
632 const char *fs_uuid_enc,
633 const char *readonly)
635 struct block_data *data;
637 /* devnode is unique value so it should exist. */
642 _E("Not support extended partition");
646 data = calloc(1, sizeof(struct block_data));
648 _E("calloc() failed");
652 data->devnode = strdup(devnode);
654 data->syspath = strdup(syspath);
656 data->fs_usage = strdup(fs_usage);
658 data->fs_type = strdup(fs_type);
660 data->fs_version = strdup(fs_version);
662 data->fs_uuid_enc = strdup(fs_uuid_enc);
664 data->readonly = atoi(readonly);
665 data->primary = check_primary_partition(devnode);
667 /* TODO should we know block dev type? */
668 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
669 data->block_type = BLOCK_MMC_DEV;
670 else if (!fnmatch(MMC_PATH, devnode, 0))
671 data->block_type = BLOCK_MMC_DEV;
672 else if (!fnmatch(SCSI_PATH, devnode, 0))
673 data->block_type = BLOCK_SCSI_DEV;
675 data->block_type = -1;
677 data->mount_point = generate_mount_path(data);
678 BLOCK_FLAG_CLEAR_ALL(data);
680 /* for 2.4 backward compatibility */
681 if (data->primary == true && data->block_type == BLOCK_MMC_DEV)
682 data->id = EXT_PRIMARY_SD_FIXID;
684 data->id = block_get_new_id();
689 static void free_block_data(struct block_data *data)
695 free(data->fs_usage);
697 free(data->fs_version);
698 free(data->fs_uuid_enc);
699 free(data->mount_point);
703 static int update_block_data(struct block_data *data,
704 const char *fs_usage,
706 const char *fs_version,
707 const char *fs_uuid_enc,
708 const char *readonly,
709 bool mount_point_updated)
714 free(data->fs_usage);
715 data->fs_usage = NULL;
717 data->fs_usage = strdup(fs_usage);
720 data->fs_type = NULL;
722 data->fs_type = strdup(fs_type);
724 free(data->fs_version);
725 data->fs_version = NULL;
727 data->fs_version = strdup(fs_version);
729 free(data->fs_uuid_enc);
730 data->fs_uuid_enc = NULL;
732 data->fs_uuid_enc = strdup(fs_uuid_enc);
734 /* generate_mount_path function should be invoked
735 * after fs_uuid_enc is updated */
736 if (!mount_point_updated) {
737 free(data->mount_point);
738 data->mount_point = generate_mount_path(data);
741 data->readonly = false;
743 data->readonly = atoi(readonly);
745 BLOCK_FLAG_MOUNT_CLEAR(data);
750 static struct block_device *make_block_device(struct block_data *data)
752 struct block_device *bdev;
757 bdev = calloc(1, sizeof(struct block_device));
762 bdev->thread_id = -1;
763 bdev->removed = false;
764 bdev->on_private_op = REQ_NORMAL;
765 bdev->private_pid = 0;
766 bdev->mount_point_updated = false;
771 // Called by MainThread - Remove DevNode
772 static void free_block_device(struct block_device *bdev)
775 struct operation_queue *op;
781 thread_id = bdev->thread_id;
782 if (thread_id < 0 || thread_id >= THREAD_MAX)
785 /* Remove file for block device /run/external-storage/id */
786 remove_file(bdev->data->id);
788 pthread_mutex_lock(&(th_manager[thread_id].mutex));
790 th_manager[thread_id].num_dev--;
791 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
792 free_block_data(bdev->data);
794 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
796 th_manager[thread_id].op_len--;
797 DD_LIST_REMOVE(bdev->op_queue, op);
800 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
805 // Called By MainThread - Remove Device
806 static struct block_device *find_block_device(const char *devnode)
808 struct block_device *bdev;
813 len = strlen(devnode) + 1;
814 for (i = 0; i < THREAD_MAX; i++) {
815 pthread_mutex_lock(&(th_manager[i].mutex));
816 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
817 if (bdev->data && !bdev->removed &&
818 !strncmp(bdev->data->devnode, devnode, len)) {
819 pthread_mutex_unlock(&(th_manager[i].mutex));
823 pthread_mutex_unlock(&(th_manager[i].mutex));
829 // Called By MainThread - Mount,Unmount,Format,GetInfo
830 static struct block_device *find_block_device_by_id(int id)
832 struct block_device *bdev;
836 for (i = 0; i < THREAD_MAX; i++) {
837 pthread_mutex_lock(&(th_manager[i].mutex));
838 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
843 if (bdev->data->id == id) {
844 pthread_mutex_unlock(&(th_manager[i].mutex));
848 pthread_mutex_unlock(&(th_manager[i].mutex));
854 static char *get_operation_char(enum block_dev_operation op,
855 char *name, unsigned int len)
857 char *str = "unknown";
863 case BLOCK_DEV_MOUNT:
866 case BLOCK_DEV_UNMOUNT:
869 case BLOCK_DEV_FORMAT:
872 case BLOCK_DEV_INSERT:
875 case BLOCK_DEV_REMOVE:
879 _E("invalid operation (%d)", op);
883 snprintf(name, len, "%s", str);
887 static void create_external_apps_directory(void)
891 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
892 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
893 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
895 _E("Fail to create external directory");
898 static int pipe_trigger(enum block_dev_operation op,
899 struct block_device *bdev, int result)
901 struct pipe_data pdata = { op, bdev, result };
905 _D("op : %s, bdev : %p, result : %d",
906 get_operation_char(pdata.op, name, sizeof(name)),
907 pdata.bdev, pdata.result);
909 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
911 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
914 static bool pipe_cb(int fd, void *data)
916 struct pipe_data pdata = {0,};
922 n = read(fd, &pdata, sizeof(pdata));
923 if (n != sizeof(pdata) || !pdata.bdev) {
924 _E("fail to read struct pipe data");
928 _I("op : %s, bdev : %p, result : %d",
929 get_operation_char(pdata.op, name, sizeof(name)),
930 pdata.bdev, pdata.result);
932 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
933 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
934 ret = change_mount_point(pdata.bdev, "");
935 /* Modify /run/external-storage/id file */
937 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point);
941 if (pdata.op == BLOCK_DEV_MOUNT &&
942 pdata.bdev->data->state == BLOCK_MOUNT &&
943 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
944 pdata.bdev->data->primary)
945 create_external_apps_directory();
947 /* Broadcast to mmc and usb storage module */
948 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
950 /* Broadcast outside with Block iface */
951 if (pdata.bdev->on_private_op == REQ_NORMAL)
952 signal_device_changed(pdata.bdev, pdata.op);
953 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
954 if (pdata.op == BLOCK_DEV_UNMOUNT) {
955 pdata.bdev->on_private_op = REQ_NORMAL;
956 _D("Private operation state: %d", pdata.bdev->on_private_op);
959 if (pdata.op == BLOCK_DEV_MOUNT) {
960 pdata.bdev->on_private_op = REQ_PRIVATE;
961 _D("Private operation state: %d", pdata.bdev->on_private_op);
965 if (pdata.op == BLOCK_DEV_REMOVE) {
966 thread_id = pdata.bdev->thread_id;
967 if (thread_id < 0 || thread_id >= THREAD_MAX)
969 free_block_device(pdata.bdev);
976 static int pipe_init(void)
980 ret = pipe2(pfds, O_CLOEXEC);
984 ret = add_fd_read_handler(pfds[0], pipe_cb,
985 NULL, NULL, &phandler);
987 _E("Failed to add pipe handler (%d)", ret);
994 static void pipe_exit(void)
997 remove_fd_read_handler(&phandler);
1007 static int mmc_check_and_unmount(const char *path)
1015 while (mount_check(path)) {
1019 if (retry > UNMOUNT_RETRY)
1026 static bool check_rw_mount(const char *szPath)
1028 struct statvfs mount_stat;
1030 if (!statvfs(szPath, &mount_stat)) {
1031 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1037 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1040 struct udev_device *dev;
1048 _E("fail to create udev library context");
1052 dev = udev_device_new_from_syspath(udev, data->syspath);
1054 _E("fail to create new udev device");
1059 r = update_block_data(data,
1060 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1061 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1062 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1063 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1064 udev_device_get_sysattr_value(dev, "ro"),
1065 mount_point_updated);
1067 _E("fail to update block data for %s", data->devnode);
1069 udev_device_unref(dev);
1074 static int block_mount(struct block_data *data)
1076 struct block_fs_ops *fs;
1081 if (!data || !data->devnode || !data->mount_point)
1084 /* check existing mounted */
1085 if (mount_check(data->mount_point))
1088 /* create mount point */
1089 if (access(data->mount_point, R_OK) != 0) {
1090 if (mkdir(data->mount_point, 0755) < 0)
1094 /* check matched file system */
1095 if (!data->fs_usage ||
1096 strncmp(data->fs_usage, FILESYSTEM,
1097 sizeof(FILESYSTEM)) != 0) {
1102 if (!data->fs_type) {
1103 _E("There is no file system");
1104 BLOCK_FLAG_SET(data, FS_EMPTY);
1110 len = strlen(data->fs_type) + 1;
1111 DD_LIST_FOREACH(fs_head, elem, fs) {
1112 if (!strncmp(fs->name, data->fs_type, len))
1117 _E("Not supported file system (%s)", data->fs_type);
1118 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1123 r = fs->mount(smack, data->devnode, data->mount_point);
1126 BLOCK_FLAG_SET(data, FS_BROKEN);
1131 r = check_rw_mount(data->mount_point);
1138 rmdir(data->mount_point);
1142 static int mount_start(struct block_device *bdev)
1144 struct block_data *data;
1152 _I("Mount Start : (%s -> %s)",
1153 data->devnode, data->mount_point);
1155 /* mount operation */
1156 r = block_mount(data);
1157 if (r != -EROFS && r < 0) {
1158 _E("fail to mount %s device : %d", data->devnode, r);
1163 data->readonly = true;
1164 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1167 data->state = BLOCK_MOUNT;
1169 if (data->block_type == BLOCK_MMC_DEV) {
1170 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1171 ret = app2ext_migrate_legacy_all();
1173 _E("app2ext failed");
1177 if (r < 0 && r != -EROFS)
1178 data->state = BLOCK_UNMOUNT;
1180 _I("%s result : %s, %d", __func__, data->devnode, r);
1182 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1183 _E("fail to trigger pipe");
1188 static int change_mount_point(struct block_device *bdev,
1189 const char *mount_point)
1191 struct block_data *data;
1197 free(data->mount_point);
1199 /* If the mount path already exists, the path cannot be used */
1201 access(mount_point, F_OK) != 0) {
1202 data->mount_point = strdup(mount_point);
1203 bdev->mount_point_updated = true;
1205 data->mount_point = generate_mount_path(data);
1206 bdev->mount_point_updated = false;
1212 static int mount_block_device(struct block_device *bdev)
1214 struct block_data *data;
1217 if (!bdev || !bdev->data)
1221 if (data->state == BLOCK_MOUNT) {
1222 _I("%s is already mounted", data->devnode);
1226 if (!block_conf[data->block_type].multimount &&
1228 _I("Not support multi mount by config info");
1232 r = mount_start(bdev);
1234 _E("Failed to mount (%s)", data->devnode);
1241 static int block_unmount(struct block_device *bdev,
1242 enum unmount_operation option)
1244 struct block_data *data;
1246 struct timespec time = {0,};
1248 if (!bdev || !bdev->data || !bdev->data->mount_point)
1253 if (bdev->on_private_op == REQ_NORMAL)
1254 signal_device_blocked(bdev);
1256 /* it must called before unmounting mmc */
1257 r = mmc_check_and_unmount(data->mount_point);
1260 if (option == UNMOUNT_NORMAL) {
1261 _I("Failed to unmount with normal option : %d", r);
1265 _I("Execute force unmount!");
1266 /* Force Unmount Scenario */
1271 * should unmount the below vconf key. */
1272 if (data->block_type == BLOCK_MMC_DEV && data->primary) {
1273 /* At first, notify to other app
1274 * who already access sdcard */
1275 _I("Notify to other app who already access sdcard");
1276 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1277 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1281 /* Second, kill app with SIGTERM */
1282 _I("Kill app with SIGTERM");
1283 terminate_process(data->mount_point, false);
1286 /* Last time, kill app with SIGKILL */
1287 _I("Kill app with SIGKILL");
1288 terminate_process(data->mount_point, true);
1291 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1292 _I("Failed to unmount with lazy option : %d",
1299 /* it takes some seconds til other app completely clean up */
1300 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1301 nanosleep(&time, NULL);
1303 print_open_files(data->mount_point);
1305 r = mmc_check_and_unmount(data->mount_point);
1307 _D("Success to unmount (%s)", data->mount_point);
1313 data->state = BLOCK_UNMOUNT;
1315 if (rmdir(data->mount_point) < 0)
1316 _E("fail to remove %s directory", data->mount_point);
1321 static int unmount_block_device(struct block_device *bdev,
1322 enum unmount_operation option)
1324 struct block_data *data;
1327 if (!bdev || !bdev->data)
1331 if (data->state == BLOCK_UNMOUNT) {
1332 _I("%s is already unmounted", data->devnode);
1333 r = mmc_check_and_unmount(data->mount_point);
1335 _E("The path was existed, but could not delete it(%s)",
1340 _I("Unmount Start : (%s -> %s)",
1341 data->devnode, data->mount_point);
1343 r = block_unmount(bdev, option);
1345 _E("fail to unmount %s device : %d", data->devnode, r);
1349 BLOCK_FLAG_MOUNT_CLEAR(data);
1352 _I("%s result : %s, %d", __func__, data->devnode, r);
1354 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1355 _E("fail to trigger pipe");
1360 static int block_format(struct block_data *data,
1361 const char *fs_type, bool mount_point_updated)
1363 const struct block_fs_ops *fs;
1368 if (!data || !data->devnode || !data->mount_point)
1372 fs_type = data->fs_type;
1375 len = strlen(fs_type);
1376 DD_LIST_FOREACH(fs_head, elem, fs) {
1377 if (!strncmp(fs->name, fs_type, len))
1382 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1383 _E("not supported file system(%s)", fs_type);
1387 _I("format path : %s", data->devnode);
1388 fs->check(data->devnode);
1389 r = fs->format(data->devnode);
1391 _E("fail to format block data for %s", data->devnode);
1395 /* need to update the partition data.
1396 * It can be changed in doing format. */
1397 retrieve_udev_device(data, mount_point_updated);
1403 static int format_block_device(struct block_device *bdev,
1404 const char *fs_type,
1405 enum unmount_operation option)
1407 struct block_data *data;
1415 _I("Format Start : (%s -> %s)",
1416 data->devnode, data->mount_point);
1418 if (data->state == BLOCK_MOUNT) {
1419 r = block_unmount(bdev, option);
1421 _E("fail to unmount %s device : %d", data->devnode, r);
1426 r = block_format(data, fs_type, bdev->mount_point_updated);
1428 _E("fail to format %s device : %d", data->devnode, r);
1431 _I("%s result : %s, %d", __func__, data->devnode, r);
1433 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1435 _E("fail to trigger pipe");
1440 static struct format_data *get_format_data(
1441 const char *fs_type, enum unmount_operation option)
1443 struct format_data *fdata;
1445 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1447 _E("fail to allocate format data");
1452 fdata->fs_type = strdup(fs_type);
1454 fdata->fs_type = NULL;
1455 fdata->option = option;
1460 static void release_format_data(struct format_data *data)
1463 free(data->fs_type);
1468 // Called by BlockThread - Real Mount Op
1469 static int block_mount_device(struct block_device *bdev, void *data)
1478 thread_id = bdev->thread_id;
1479 if (thread_id < 0 || thread_id >= THREAD_MAX)
1481 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1482 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1483 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1485 _E("(%d) does not exist in the device list", bdev->data->devnode);
1489 /* mount automatically */
1490 ret = mount_block_device(bdev);
1492 _E("fail to mount block device for %s", bdev->data->devnode);
1497 // Called by BlockThread - Real Format Op
1498 static int block_format_device(struct block_device *bdev, void *data)
1503 struct format_data *fdata = (struct format_data *)data;
1505 if (!bdev || !fdata) {
1510 thread_id = bdev->thread_id;
1511 if (thread_id < 0 || thread_id >= THREAD_MAX)
1513 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1514 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1515 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1517 _E("(%d) does not exist in the device list", bdev->data->devnode);
1522 ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1524 _E("fail to mount block device for %s", bdev->data->devnode);
1527 release_format_data(fdata);
1532 // Called by BlockThread - Real Unmount Op
1533 static int block_unmount_device(struct block_device *bdev, void *data)
1536 long option = (long)data;
1541 ret = unmount_block_device(bdev, option);
1543 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1550 /* Called by BlockThread - Remove Operation
1551 Direct Call at BlockThread
1552 Previously this function was called by MainThread. However, it will increase complexity.
1553 Need thread lock before to call remove_operation
1555 static void remove_operation(struct block_device *bdev)
1557 struct operation_queue *op;
1564 thread_id = bdev->thread_id;
1565 if (thread_id < 0 || thread_id >= THREAD_MAX)
1568 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1570 _D("Remove operation (%s, %s)",
1571 get_operation_char(op->op, name, sizeof(name)),
1572 bdev->data->devnode);
1574 DD_LIST_REMOVE(bdev->op_queue, op);
1580 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1587 rep = make_dbus_reply_message_simple(reply_handle, result);
1588 reply_dbus_method_result(reply_handle, rep);
1591 // Called by BlockThread
1592 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1594 struct operation_queue *temp;
1607 thread_id = bdev->thread_id;
1608 if (thread_id < 0 || thread_id >= THREAD_MAX)
1611 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1613 DD_LIST_FOREACH(*queue, l, temp) {
1614 if (temp->op == BLOCK_DEV_REMOVE) {
1619 th_manager[thread_id].op_len--;
1620 block_send_dbus_reply((*op)->reply_handle, 0);
1623 remove_operation(bdev);
1624 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1627 // Called by BlockThread
1628 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1630 struct operation_queue *temp;
1633 bool unmounted = false;
1644 thread_id = bdev->thread_id;
1645 if (thread_id < 0 || thread_id >= THREAD_MAX)
1648 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1649 DD_LIST_FOREACH(*queue, l, temp) {
1650 if (temp->op == BLOCK_DEV_UNMOUNT) {
1652 _D("Operation queue has unmount operation");
1656 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1661 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1663 DD_LIST_FOREACH(*queue, l, temp) {
1664 if (temp->op == BLOCK_DEV_UNMOUNT) {
1669 th_manager[thread_id].op_len--;
1670 block_send_dbus_reply((*op)->reply_handle, 0);
1673 remove_operation(bdev);
1674 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1679 // Called by BlockThread
1680 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1684 char devnode[PATH_MAX];
1686 enum block_dev_operation operation;
1687 bool unmounted = false;
1694 thread_id = bdev->thread_id;
1695 if (thread_id < 0 || thread_id >= THREAD_MAX)
1698 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1708 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1709 get_operation_char(operation, name, sizeof(name)), devnode);
1712 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1713 check_removed(bdev, &queue, &op);
1715 _D("Trigger operation again (%s, %s)",
1716 get_operation_char(operation, name, sizeof(name)), devnode);
1718 if (operation == BLOCK_DEV_MOUNT) {
1719 unmounted = check_unmount(bdev, &queue, &op);
1722 _D("Trigger operation again (%s, %s)",
1723 get_operation_char(operation, name, sizeof(name)), devnode);
1727 switch (operation) {
1728 case BLOCK_DEV_INSERT:
1730 case BLOCK_DEV_MOUNT:
1731 ret = block_mount_device(bdev, op->data);
1732 _D("Mount (%s) result:(%d)", devnode, ret);
1734 case BLOCK_DEV_FORMAT:
1735 ret = block_format_device(bdev, op->data);
1736 _D("Format (%s) result:(%d)", devnode, ret);
1738 case BLOCK_DEV_UNMOUNT:
1739 ret = block_unmount_device(bdev, op->data);
1740 _D("Unmount (%s) result:(%d)", devnode, ret);
1742 case BLOCK_DEV_REMOVE:
1746 _E("Operation type is invalid (%d)", op->op);
1752 * during checking the queue length */
1753 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1756 th_manager[thread_id].op_len--;
1758 block_send_dbus_reply(op->reply_handle, ret);
1760 queue = bdev->op_queue;
1761 if (queue != NULL) {
1762 queue = DD_LIST_NEXT(queue);
1764 op = DD_LIST_NTH(queue, 0);
1770 remove_operation(bdev);
1772 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1776 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1777 if (pipe_trigger(operation, bdev, 0) < 0)
1778 _E("fail to trigger pipe");
1785 // Called by BlockThread
1786 static void *block_th_start(void *arg)
1788 struct block_device *temp;
1789 struct manage_thread *th = (struct manage_thread *)arg;
1790 struct operation_queue *op = NULL;
1792 dd_list *queue = NULL;
1797 thread_id = th->thread_id;
1798 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1799 _E("Thread Number: %d", th->thread_id);
1804 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1805 if (th_manager[thread_id].op_len == 0) {
1806 _D("Operation queue of thread is empty");
1807 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1808 _D("Wake up %d", thread_id);
1811 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1812 queue = temp->op_queue;
1814 op = DD_LIST_NTH(queue, 0);
1816 _D("Operation queue for device %s is Empty", temp->data->devnode);
1820 queue = DD_LIST_NEXT(queue);
1828 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1830 if (op && !op->done)
1831 trigger_operation(temp, queue, op);
1836 // This function will be refactored later
1837 // Especially, we don't need to keep th_node_list.
1838 static int find_thread(char *devnode)
1845 int i, len, min, min_num;
1846 int dev_mmc = -1, part = -1, num;
1849 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1850 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1857 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1858 th_node = strdup(str);
1859 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1860 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1861 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1862 th_node = strdup(str);
1866 len = strlen(th_node) + 1;
1869 for (i = 0; i < THREAD_MAX; i++) {
1870 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1871 if (!strncmp(temp, th_node, len))
1874 if (th_manager[i].num_dev < min_num) {
1875 min_num = th_manager[i].num_dev;
1880 if (min >= 0 && min < THREAD_MAX) {
1881 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1885 _E("Finding thread is failed");
1886 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1890 /* Only Main thread is permmited */
1891 // Called by MainThread
1892 static int add_operation(struct block_device *bdev,
1893 enum block_dev_operation operation,
1894 dbus_method_reply_handle_h reply_handle, void *data)
1896 struct operation_queue *op;
1906 _I("Add operation (%s, %s)",
1907 get_operation_char(operation, name, sizeof(name)),
1908 bdev->data->devnode);
1910 thread_id = bdev->thread_id;
1911 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1912 _E("Fail to find thread to add");
1916 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
1918 _E("malloc failed");
1924 op->reply_handle = reply_handle;
1927 * during adding queue and checking the queue length */
1928 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1930 /* Only modified between lock and unlock of mutex */
1933 start_th = th_manager[thread_id].start_th;
1934 DD_LIST_APPEND(bdev->op_queue, op);
1935 th_manager[thread_id].op_len++;
1937 if (th_manager[thread_id].op_len == 1 && !start_th)
1938 pthread_cond_signal(&(th_manager[thread_id].cond));
1940 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1943 /* Need to disble app2ext whenever unmounting mmc */
1944 if (op->op == BLOCK_DEV_UNMOUNT &&
1945 bdev->data->state == BLOCK_MOUNT &&
1946 bdev->data->block_type == BLOCK_MMC_DEV &&
1947 bdev->data->primary)
1948 if (app2ext_disable_all_external_pkgs() < 0)
1949 _E("app2ext_disable_all_external_pkgs() failed");
1953 _D("Start New thread for block device");
1954 th_manager[thread_id].start_th = false;
1955 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
1957 _E("fail to create thread for %s", bdev->data->devnode);
1961 pthread_detach(th_manager[thread_id].th);
1967 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
1970 struct dirent entry;
1972 const char *syspath;
1975 syspath = udev_device_get_syspath(dev);
1979 dp = opendir(syspath);
1981 _E("fail to open %s", syspath);
1985 /* TODO compare devname and d_name */
1986 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
1987 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
1988 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2000 static bool check_partition(struct udev_device *dev)
2002 const char *devtype;
2003 const char *part_table_type;
2004 const char *fs_usage;
2007 /* only consider disk type, never partitions */
2008 devtype = udev_device_get_devtype(dev);
2012 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2013 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2016 part_table_type = udev_device_get_property_value(dev,
2017 "ID_PART_TABLE_TYPE");
2018 if (part_table_type) {
2019 fs_usage = udev_device_get_property_value(dev,
2022 strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2023 if (!disk_is_partitioned_by_kernel(dev))
2030 if (disk_is_partitioned_by_kernel(dev)) {
2039 // Called by MainThread
2040 static int add_block_device(struct udev_device *dev, const char *devnode)
2042 struct block_data *data;
2043 struct block_device *bdev;
2048 partition = check_partition(dev);
2050 /* if there is a partition, skip this request */
2051 _I("%s device has partitions, skip this time", devnode);
2055 data = make_block_data(devnode,
2056 udev_device_get_syspath(dev),
2057 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2058 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2059 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2060 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2061 udev_device_get_sysattr_value(dev, "ro"));
2063 _E("fail to make block data for %s", devnode);
2067 if (!block_conf[data->block_type].multimount && !data->primary) {
2068 _D("Not support multi mount by config info");
2072 bdev = make_block_device(data);
2074 _E("fail to make block device for %s", devnode);
2075 free_block_data(data);
2079 thread_id = find_thread(bdev->data->devnode);
2080 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2081 _E("Fail to find thread to add");
2082 free_block_data(data);
2083 free_block_device(bdev);
2086 bdev->thread_id = thread_id;
2088 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2089 th_manager[thread_id].num_dev++;
2090 DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2092 /* Create file for block device /run/external-storage/id */
2093 create_file(bdev->data->id, bdev->data->mount_point);
2095 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2097 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2099 _E("Failed to add operation (insert %s)", devnode);
2100 free_block_data(data);
2101 free_block_device(bdev);
2105 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2107 _E("Failed to add operation (mount %s)", devnode);
2108 free_block_data(data);
2109 free_block_device(bdev);
2116 static int remove_block_device(struct udev_device *dev, const char *devnode)
2118 struct block_device *bdev;
2121 bdev = find_block_device(devnode);
2123 _E("fail to find block data for %s", devnode);
2127 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2129 bdev->removed = true;
2130 if (bdev->on_private_op != REQ_NORMAL) {
2131 bdev->on_private_op = REQ_NORMAL;
2132 _D("Private operation state: %d", bdev->on_private_op);
2135 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2137 _E("Failed to add operation (unmount %s)", devnode);
2141 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2143 _E("Failed to add operation (remove %s)", devnode);
2150 static int get_internal_storage_number(void)
2152 struct libmnt_table *t = NULL;
2153 struct libmnt_fs *fs;
2156 int r = 0, dev_temp;
2158 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2159 (is_emulator() && dev_internal_emul != '\0'))
2162 t = mnt_new_table();
2166 r = mnt_table_parse_mtab(t, NULL);
2172 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2178 temp = mnt_fs_get_srcpath(fs);
2179 name = strrchr(temp, '/');
2183 /* Boot from USB is not handled */
2184 if (!is_emulator()) {
2185 if (!fnmatch(MMC_PATH, temp, 0))
2186 sscanf(name, "mmcblk%d", &dev_internal);
2187 else if (!fnmatch(SCSI_PATH, temp, 0))
2188 sscanf(name, "sd%c", &dev_internal_scsi);
2190 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2191 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2193 dev_internal_emul = '\0';
2201 static int check_external_storage(const char* devnode)
2203 char dev_scsi = '\0';
2206 int dev_num = -1, dev_temp;
2211 name = strrchr(devnode, '/');
2215 if (!is_emulator()) {
2216 if (!fnmatch(MMC_PATH, devnode, 0)) {
2217 sscanf(name, "mmcblk%d", &dev_num);
2218 if (dev_internal == dev_num) {
2219 _D("%s is internal storage", devnode);
2222 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2223 sscanf(name, "sd%c", &dev_scsi);
2224 if (dev_internal_scsi == dev_scsi) {
2225 _D("%s is internal storage", devnode);
2230 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2231 sscanf(name, "vd%c%d", &emul, &dev_temp);
2232 if (dev_internal_emul == emul) {
2233 _D("%s is internal storage", devnode);
2242 static int check_already_handled(const char* devnode)
2244 struct block_device *bdev;
2245 struct block_data *data;
2249 for (i = 0; i < THREAD_MAX; i++) {
2250 pthread_mutex_lock(&(th_manager[i].mutex));
2251 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2257 if (!strncmp(data->devnode, devnode, sizeof(devnode) + 1)) {
2258 pthread_mutex_unlock(&(th_manager[i].mutex));
2262 pthread_mutex_unlock(&(th_manager[i].mutex));
2268 static int block_init_from_udev_enumerate(void)
2271 struct udev_enumerate *enumerate;
2272 struct udev_list_entry *list_entry, *list_sub_entry;
2273 struct udev_device *dev;
2274 const char *syspath;
2275 const char *devnode;
2280 _E("fail to create udev library context");
2284 /* create a list of the devices in the 'usb' subsystem */
2285 enumerate = udev_enumerate_new(udev);
2287 _E("fail to create an enumeration context");
2291 if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2292 (is_emulator() && dev_internal_emul == '\0')) {
2293 r = get_internal_storage_number();
2298 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2299 udev_enumerate_add_match_property(enumerate,
2300 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2301 udev_enumerate_add_match_property(enumerate,
2302 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2303 udev_enumerate_scan_devices(enumerate);
2305 udev_list_entry_foreach(list_entry,
2306 udev_enumerate_get_list_entry(enumerate)) {
2307 syspath = udev_list_entry_get_name(list_entry);
2311 dev = udev_device_new_from_syspath(
2312 udev_enumerate_get_udev(enumerate),
2318 udev_list_entry_foreach(list_sub_entry,
2319 udev_device_get_devlinks_list_entry(dev)) {
2320 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2321 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2328 devnode = udev_device_get_devnode(dev);
2332 if (fnmatch(MMC_PATH, devnode, 0) &&
2333 fnmatch(SCSI_PATH, devnode, 0))
2337 r = check_external_storage(devnode);
2341 r = check_already_handled(devnode);
2343 _I("%s is already handled", devnode);
2347 _I("%s device add", devnode);
2348 add_block_device(dev, devnode);
2350 udev_device_unref(dev);
2353 udev_enumerate_unref(enumerate);
2358 // Called by MainThread
2359 static void show_block_device_list(void)
2361 struct block_device *bdev;
2362 struct block_data *data;
2366 for (i = 0; i < THREAD_MAX; i++) {
2367 pthread_mutex_lock(&(th_manager[i].mutex));
2368 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2374 _D("%s:", data->devnode);
2375 _D("\tSyspath: %s", data->syspath);
2376 _D("\tBlock type: %s",
2377 (data->block_type == BLOCK_MMC_DEV ?
2378 BLOCK_TYPE_MMC : BLOCK_TYPE_SCSI));
2379 _D("\tFs type: %s", data->fs_type);
2380 _D("\tFs usage: %s", data->fs_usage);
2381 _D("\tFs version: %s", data->fs_version);
2382 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2383 _D("\tReadonly: %s",
2384 (data->readonly ? "true" : "false"));
2385 _D("\tMount point: %s", data->mount_point);
2386 _D("\tMount state: %s",
2387 (data->state == BLOCK_MOUNT ?
2388 "mount" : "unmount"));
2390 (data->primary ? "true" : "false"));
2391 _D("\tID: %d", data->id);
2393 pthread_mutex_unlock(&(th_manager[i].mutex));
2397 // Called by MainThread
2398 static void remove_whole_block_device(void)
2400 struct block_device *bdev;
2406 for (i = 0; i < THREAD_MAX; i++) {
2408 pthread_mutex_lock(&(th_manager[i].mutex));
2409 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2410 if (bdev->removed == false)
2413 pthread_mutex_unlock(&(th_manager[i].mutex));
2415 if (bdev && bdev->removed == false) {
2416 bdev->removed = true;
2417 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2419 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2421 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2423 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2430 static void booting_done(const char *sender_name,
2431 const char *object_path, const char *interface_name,
2432 const char *signal_name, DBusMessage *msg,
2435 static int done = 0;
2440 /* if there is the attached device, try to mount */
2441 block_init_from_udev_enumerate();
2442 block_control = true;
2446 static void block_poweroff(const char *sender_name,
2447 const char *object_path, const char *interface_name,
2448 const char *signal_name, DBusMessage *msg,
2451 static int status = 0;
2456 /* unregister mmc uevent control routine */
2457 unregister_udev_uevent_control(&uh);
2458 remove_whole_block_device();
2461 static void uevent_block_handler(struct udev_device *dev)
2463 const char *devnode = NULL;
2465 struct udev_list_entry *list_entry;
2468 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2469 const char *devlink = udev_list_entry_get_name(list_entry);
2470 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2477 devnode = udev_device_get_devnode(dev);
2481 if (fnmatch(MMC_PATH, devnode, 0) &&
2482 fnmatch(SCSI_PATH, devnode, 0))
2486 r = check_external_storage(devnode);
2490 action = udev_device_get_action(dev);
2494 _I("%s device %s", devnode, action);
2495 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD))) {
2496 r = check_already_handled(devnode);
2498 _I("%s is already handled", devnode);
2502 add_block_device(dev, devnode);
2503 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE)))
2504 remove_block_device(dev, devnode);
2507 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2508 DBusMessage *msg, bool onprivate)
2510 struct block_device *bdev;
2515 if (!reply_handle || !msg)
2518 ret = dbus_message_get_args(msg, NULL,
2519 DBUS_TYPE_INT32, &id,
2520 DBUS_TYPE_STRING, &mount_point,
2525 bdev = find_block_device_by_id(id);
2527 _E("Failed to find (%d) in the device list", id);
2531 if (bdev->on_private_op != REQ_NORMAL) {
2536 if (bdev->data->state == BLOCK_MOUNT) {
2537 _I("%s is already mounted", bdev->data->devnode);
2543 bdev->on_private_op = REQ_PRIVATE;
2544 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2545 _D("Private operation state: %d", bdev->on_private_op);
2547 if (bdev->on_private_op != REQ_NORMAL) {
2548 _E("Failed to process mount operation");
2554 /* if requester want to use a specific mount point */
2555 if (mount_point && strncmp(mount_point, "", 1) != 0) {
2556 ret = change_mount_point(bdev, mount_point);
2562 /* Modify /run/external-storage/id file */
2563 create_file(bdev->data->id, bdev->data->mount_point);
2566 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2568 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2575 return make_dbus_reply_message_simple(reply_handle, ret);
2578 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2581 return request_mount_block(reply_handle, msg, false);
2584 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2587 return request_mount_block(reply_handle, msg, true);
2590 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2591 DBusMessage *msg, bool onprivate)
2593 struct block_device *bdev;
2599 if (!reply_handle || !msg)
2602 ret = dbus_message_get_args(msg, NULL,
2603 DBUS_TYPE_INT32, &id,
2604 DBUS_TYPE_INT32, &option,
2609 bdev = find_block_device_by_id(id);
2611 _E("Failed to find (%d) in the device list", id);
2617 pid = get_dbus_method_sender_pid(reply_handle);
2618 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2619 _E("Failed to process private unmount operation");
2624 if (bdev->on_private_op != REQ_NORMAL) {
2625 _E("Failed to process unmount operation");
2631 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2633 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2640 return make_dbus_reply_message_simple(reply_handle, ret);
2643 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2646 return request_unmount_block(reply_handle, msg, false);
2649 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2652 return request_unmount_block(reply_handle, msg, true);
2655 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2658 struct block_device *bdev;
2659 struct format_data *fdata;
2666 if (!reply_handle || !msg)
2669 ret = dbus_message_get_args(msg, NULL,
2670 DBUS_TYPE_INT32, &id,
2671 DBUS_TYPE_INT32, &option,
2676 bdev = find_block_device_by_id(id);
2678 _E("Failed to find (%d) in the device list", id);
2682 pid = get_dbus_method_sender_pid(reply_handle);
2683 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2684 _E("Failed to format on private state");
2689 fdata = get_format_data(NULL, option);
2691 _E("Failed to get format data");
2695 prev_state = bdev->data->state;
2696 if (prev_state == BLOCK_MOUNT) {
2697 if (bdev->on_private_op == REQ_PRIVATE) {
2698 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2699 _D("Private operation state: %d", bdev->on_private_op);
2701 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2703 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2704 release_format_data(fdata);
2709 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2711 _E("Failed to add operation (format %s)", bdev->data->devnode);
2712 release_format_data(fdata);
2715 /* Maintain previous state of mount/unmount */
2716 if (prev_state == BLOCK_MOUNT) {
2717 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2718 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2726 return make_dbus_reply_message_simple(reply_handle, ret);
2729 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
2731 char *str_null = "";
2733 if (!data || !piter)
2736 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2737 &(data->block_type));
2738 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2739 data->devnode ? &(data->devnode) : &str_null);
2740 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2741 data->syspath ? &(data->syspath) : &str_null);
2742 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2743 data->fs_usage ? &(data->fs_usage) : &str_null);
2744 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2745 data->fs_type ? &(data->fs_type) : &str_null);
2746 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2747 data->fs_version ? &(data->fs_version) : &str_null);
2748 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2749 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2750 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2752 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2753 data->mount_point ? &(data->mount_point) : &str_null);
2754 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2756 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
2758 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2760 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2767 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
2769 DBusMessageIter piter;
2774 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2775 add_device_to_iter(data, &piter);
2776 dbus_message_iter_close_container(iter, &piter);
2781 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
2783 DBusMessageIter piter;
2784 char *str_null = "";
2789 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
2790 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2791 &(data->block_type));
2792 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2793 data->devnode ? &(data->devnode) : &str_null);
2794 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2795 data->syspath ? &(data->syspath) : &str_null);
2796 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2797 data->fs_usage ? &(data->fs_usage) : &str_null);
2798 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2799 data->fs_type ? &(data->fs_type) : &str_null);
2800 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2801 data->fs_version ? &(data->fs_version) : &str_null);
2802 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2803 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2804 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2806 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
2807 data->mount_point ? &(data->mount_point) : &str_null);
2808 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2810 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
2812 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
2814 dbus_message_iter_close_container(iter, &piter);
2819 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
2822 DBusMessageIter iter;
2824 struct block_device *bdev;
2825 struct block_data *data;
2828 if (!reply_handle || !msg)
2831 reply = make_dbus_reply_message(reply_handle);
2835 ret = dbus_message_get_args(msg, NULL,
2836 DBUS_TYPE_INT32, &id,
2841 bdev = find_block_device_by_id(id);
2848 dbus_message_iter_init_append(reply, &iter);
2849 add_device_to_iter(data, &iter);
2855 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
2858 show_block_device_list();
2859 return make_dbus_reply_message(reply_handle);
2862 // Called by MainThread
2863 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
2866 DBusMessageIter iter;
2867 DBusMessageIter aiter;
2869 struct block_device *bdev;
2870 struct block_data *data;
2877 reply = make_dbus_reply_message(reply_handle);
2879 ret = dbus_message_get_args(msg, NULL,
2880 DBUS_TYPE_STRING, &type,
2883 _E("Failed to get args");
2888 _E("Delivered type is NULL");
2892 _D("Block (%s) device list is requested", type);
2894 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
2895 block_type = BLOCK_SCSI_DEV;
2896 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
2897 block_type = BLOCK_MMC_DEV;
2898 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
2901 _E("Invalid type (%s) is requested", type);
2905 dbus_message_iter_init_append(reply, &iter);
2906 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
2908 for (i = 0; i < THREAD_MAX; i++) {
2909 pthread_mutex_lock(&(th_manager[i].mutex));
2910 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2917 switch (block_type) {
2918 case BLOCK_SCSI_DEV:
2920 if (data->block_type != block_type)
2926 add_device_to_struct_iter(data, &aiter);
2928 pthread_mutex_unlock(&(th_manager[i].mutex));
2930 dbus_message_iter_close_container(&iter, &aiter);
2936 // Called by MainThread
2937 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
2940 DBusMessageIter iter;
2941 DBusMessageIter aiter;
2943 struct block_device *bdev;
2944 struct block_data *data;
2951 reply = make_dbus_reply_message(reply_handle);
2953 ret = dbus_message_get_args(msg, NULL,
2954 DBUS_TYPE_STRING, &type,
2957 _E("Failed to get args");
2962 _E("Delivered type is NULL");
2966 _D("Block (%s) device list is requested", type);
2968 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
2969 block_type = BLOCK_SCSI_DEV;
2970 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
2971 block_type = BLOCK_MMC_DEV;
2972 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
2975 _E("Invalid type (%s) is requested", type);
2979 dbus_message_iter_init_append(reply, &iter);
2980 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
2982 for (i = 0; i < THREAD_MAX; i++) {
2983 pthread_mutex_lock(&(th_manager[i].mutex));
2984 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2991 switch (block_type) {
2992 case BLOCK_SCSI_DEV:
2994 if (data->block_type != block_type)
3001 add_device_to_iter_2(data, &aiter);
3003 pthread_mutex_unlock(&(th_manager[i].mutex));
3005 dbus_message_iter_close_container(&iter, &aiter);
3011 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3014 DBusMessageIter iter;
3016 struct block_device *bdev;
3017 struct block_data *data, nodata = {0,};
3022 if (!reply_handle || !msg)
3025 reply = make_dbus_reply_message(reply_handle);
3030 for (i = 0; i < THREAD_MAX; i++) {
3031 pthread_mutex_lock(&(th_manager[i].mutex));
3032 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3038 if (data->block_type != BLOCK_MMC_DEV)
3045 pthread_mutex_unlock(&(th_manager[i].mutex));
3050 dbus_message_iter_init_append(reply, &iter);
3052 add_device_to_iter(data, &iter);
3054 nodata.id = -ENODEV;
3055 add_device_to_iter(&nodata, &iter);
3063 Method name Method call format string Reply format string
3064 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3065 { "GetDeviceList" , "s", "a(issssssisibii)", request_get_device_list },
3066 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3067 { "Mount", "is", "i", request_public_mount_block },
3068 { "Unmount", "ii", "i", request_public_unmount_block },
3069 { "Format", "ii", "i", request_format_block },
3070 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3071 { "GetMmcPrimary" , NULL, "(issssssisibii)" , request_get_mmc_primary },
3072 { "PrivateMount", "is", "i", request_private_mount_block },
3073 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3076 static const dbus_method_s manager_methods[] = {
3077 { "ShowDeviceList", NULL, request_show_device_list },
3078 { "GetDeviceList" , "s", request_get_device_list },
3079 { "GetDeviceList2", "s", request_get_device_list_2 },
3080 { "Mount", "is", request_public_mount_block },
3081 { "Unmount", "ii", request_public_unmount_block },
3082 { "Format", "ii", request_format_block },
3083 { "GetDeviceInfo", "i", request_get_device_info },
3084 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3085 { "PrivateMount", "is", request_private_mount_block },
3086 { "PrivateUnmount", "ii", request_private_unmount_block },
3089 static dbus_interface_s block_interface = {
3090 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3091 .methods = manager_methods,
3092 .nr_methods = ARRAY_SIZE(manager_methods),
3095 static int load_config(struct parse_result *result, void *user_data)
3099 if (MATCH(result->section, "Block"))
3102 if (MATCH(result->section, "SCSI"))
3103 index = BLOCK_SCSI_DEV;
3104 else if (MATCH(result->section, "MMC"))
3105 index = BLOCK_MMC_DEV;
3109 if (MATCH(result->name, "Multimount"))
3110 block_conf[index].multimount =
3111 (MATCH(result->value, "yes") ? true : false);
3117 static int mount_root_path_tmpfs(void)
3122 root = tzplatform_getenv(TZ_SYS_MEDIA);
3126 if (access(root, F_OK) != 0)
3129 if (mount_check(root))
3132 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3135 _E("tmpfs mount failed (%d)", ret);
3142 #define mount_root_path_tmpfs() 0
3145 static void block_init(void *data)
3150 dbus_handle_h handle;
3155 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3157 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3159 ret = mount_root_path_tmpfs();
3161 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3163 ret = dbus_get_connection(&handle);
3165 _E("Failed to get dbus connection(%d)", ret);
3167 /* register block manager object and interface */
3168 ret = register_dbus_methods(handle,
3169 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3172 _E("Failed to register block interface and methods (%d)", ret);
3177 _E("fail to init pipe");
3179 /* register mmc uevent control routine */
3180 ret = register_udev_uevent_control(&uh);
3182 _E("fail to register block uevent : %d", ret);
3184 /* register notifier for below each event */
3185 register_dbus_signal(DEVICED_PATH_CORE,
3186 DEVICED_INTERFACE_CORE,
3187 SIGNAL_BOOTING_DONE,
3188 booting_done, NULL, NULL);
3190 register_dbus_signal(DEVICED_PATH_POWEROFF,
3191 DEVICED_INTERFACE_POWEROFF,
3192 SIGNAL_POWEROFF_STATE,
3193 block_poweroff, NULL, NULL);
3195 for (i = 0; i < THREAD_MAX; i++) {
3196 th_manager[i].num_dev = 0;
3197 th_manager[i].op_len = 0;
3198 th_manager[i].start_th = true;
3199 th_manager[i].thread_id = i;
3200 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3201 pthread_cond_init(&(th_manager[i].cond), NULL);
3204 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3206 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3208 _E("Failed to make directory: %d", errno);
3209 } else if (!S_ISDIR(buf.st_mode)) {
3210 ret = remove(EXTERNAL_STORAGE_PATH);
3212 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3213 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3215 _E("Failed to make directory: %d", errno);
3217 ret = chmod(EXTERNAL_STORAGE_PATH, 644);
3219 _E("Fail to change permissions of a file");
3223 static void block_exit(void *data)
3229 /* unregister notifier for below each event */
3230 unregister_dbus_signal(DEVICED_PATH_CORE,
3231 DEVICED_INTERFACE_CORE,
3232 SIGNAL_BOOTING_DONE, booting_done);
3234 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3235 DEVICED_INTERFACE_POWEROFF,
3236 SIGNAL_POWEROFF_STATE, block_poweroff);
3241 /* unregister mmc uevent control routine */
3242 ret = unregister_udev_uevent_control(&uh);
3244 _E("fail to unregister block uevent : %d", ret);
3246 /* remove remaining blocks */
3247 remove_whole_block_device();
3249 for (i = 0; i < THREAD_MAX; i++) {
3250 if (!th_manager[i].start_th)
3251 pthread_cancel(th_manager[i].th);
3254 block_control = false;
3257 static int block_start(void *data)
3262 _E("Cannot be started. Booting is not ready");
3266 if (block_control) {
3267 _I("Already started");
3271 /* register mmc uevent control routine */
3272 ret = register_udev_uevent_control(&uh);
3274 _E("fail to register block uevent : %d", ret);
3276 block_init_from_udev_enumerate();
3278 block_control = true;
3284 static int block_stop(void *data)
3287 _E("Cannot be stopped. Booting is not ready");
3291 if (!block_control) {
3292 _I("Already stopped");
3296 /* unregister mmc uevent control routine */
3297 unregister_udev_uevent_control(&uh);
3299 /* remove the existing blocks */
3300 remove_whole_block_device();
3302 block_control = false;
3308 static storaged_module_interface block_module = {
3312 .start = block_start,
3316 __attribute__ ((visibility("default")))storaged_module_interface *
3317 storaged_get_module_interface(void)
3319 return &block_module;