4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include <sys/mount.h>
28 #include <sys/statvfs.h>
32 #include <sys/statfs.h>
39 #include <tzplatform_config.h>
40 #include <app2ext_interface.h>
42 #include <blkid/blkid.h>
46 #include "config-parser.h"
47 #include "module-intf.h"
52 #include "fd_handler.h"
57 * TODO Assume root device is always mmcblk0*.
59 #define MMC_PATH "*/mmcblk[0-9]*"
60 #define MMC_PARTITION_PATH "mmcblk[0-9]p[0-9]"
61 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
62 #define MMC_LINK_PATH "*/sdcard/*"
63 #define SCSI_PATH "*/sd[a-z]*"
64 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
65 #define SCSI_PARTITION_LENGTH 9
66 #define EXTENDEDSD_NODE_PATH "/dev/mapper/extendedsd"
68 #define FILESYSTEM_NAME "filesystem"
70 #define DEV_PREFIX "/dev/"
73 #define UNMOUNT_RETRY 5
74 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
76 #define SIGNAL_POWEROFF_STATE "ChangeState"
78 #define BLOCK_DEVICE_ADDED "DeviceAdded"
79 #define BLOCK_DEVICE_REMOVED "DeviceRemoved"
80 #define BLOCK_DEVICE_BLOCKED "DeviceBlocked"
81 #define BLOCK_DEVICE_CHANGED "DeviceChanged"
82 #define BLOCK_DEVICE_CHANGED_2 "DeviceChanged2"
84 #define BLOCK_TYPE_MMC "mmc"
85 #define BLOCK_TYPE_SCSI "scsi"
86 #define BLOCK_TYPE_ALL "all"
88 #define BLOCK_MMC_NODE_PREFIX "SDCard"
89 #define BLOCK_SCSI_NODE_PREFIX "USBDrive"
91 #define BLOCK_CONF_FILE "/etc/storaged/block.conf"
93 #define EXTERNAL_STORAGE_PATH "/run/external-storage"
94 #define EXTENDED_INTERNAL_PATH "/run/extended-internal-sd"
97 #define EXTENDEDSD_MOUNT_PATH "/opt/extendedsd"
99 #define VFAT_NAME "vfat"
100 #define EXT4_NAME "ext4"
101 #define LUKS_NAME "crypto_LUKS"
102 #define EXTENDEDSD_NAME "extendedsd"
104 /* Minimum value of block id */
105 #define BLOCK_ID_MIN 10
106 /* For 2.4 Backward Compatibility */
107 #define EXT_PRIMARY_SD_FIXID 1
109 /* Maximum number of thread */
112 #define SPEEDCHECK 16
114 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
115 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
116 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
118 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
120 enum block_dev_operation {
129 enum private_operation_state {
135 struct operation_queue {
136 enum block_dev_operation op;
137 dbus_method_reply_handle_h reply_handle;
142 struct block_device {
143 struct block_data *data;
145 int thread_id; /* Current thread ID */
146 bool removed; /* True when device is physically removed but operation is not precessed yet */
147 enum private_operation_state on_private_op;
148 bool mount_point_updated;
153 struct block_device *bdev;
155 enum unmount_operation option;
159 enum block_dev_operation op;
160 struct block_device *bdev;
164 static struct block_conf {
166 bool extendedinternal;
167 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
169 static struct manage_thread {
170 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
171 dd_list *block_dev_list; /* Use thread mutex */
173 pthread_mutex_t mutex;
175 int num_dev; /* Number of devices which thread holds. Only main thread access */
176 int op_len; /* Number of operation of thread. Use thread mutex */
177 int thread_id; /* Never changed */
179 } th_manager[THREAD_MAX];
181 static dd_list *fs_head;
182 static dd_list *block_ops_list;
185 static fd_handler_h phandler;
186 static bool block_control = false;
187 static bool block_boot = false;
188 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
190 /* Assume there is only one physical internal storage */
191 static int dev_internal = -1;
192 static char dev_internal_scsi = '\0';
193 static char dev_internal_emul = '\0';
195 static int block_start(void *data);
196 static int block_stop(void *data);
198 static int add_operation(struct block_device *bdev,
199 enum block_dev_operation operation,
200 dbus_method_reply_handle_h reply_handle, void *data);
201 static void remove_operation(struct block_device *bdev);
202 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
203 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
204 static int change_mount_point(struct block_device *bdev, const char *mount_point);
206 static void uevent_block_handler(struct udev_device *dev);
207 static struct uevent_handler uh = {
208 .subsystem = BLOCK_SUBSYSTEM,
209 .uevent_func = uevent_block_handler,
212 static void __CONSTRUCTOR__ smack_check(void)
217 fp = fopen("/proc/filesystems", "r");
221 while (fgets(buf, sizeof(buf), fp) != NULL) {
222 if (strstr(buf, "smackfs")) {
231 void add_fs(const struct block_fs_ops *fs)
233 DD_LIST_APPEND(fs_head, (void *)fs);
236 void remove_fs(const struct block_fs_ops *fs)
238 DD_LIST_REMOVE(fs_head, (void *)fs);
241 const struct block_fs_ops *find_fs(enum block_fs_type type)
243 struct block_fs_ops *fs;
246 DD_LIST_FOREACH(fs_head, elem, fs) {
247 if (fs->type == type)
253 void add_block_dev(const struct block_dev_ops *ops)
255 DD_LIST_APPEND(block_ops_list, (void *)ops);
258 void remove_block_dev(const struct block_dev_ops *ops)
260 DD_LIST_REMOVE(block_ops_list, (void *)ops);
263 static void broadcast_block_info(enum block_dev_operation op,
264 struct block_data *data, int result)
266 struct block_dev_ops *ops;
269 if (data->primary != true)
272 DD_LIST_FOREACH(block_ops_list, elem, ops) {
273 int data_block_type = (data->block_type == BLOCK_EXTENDEDSD_DEV)
274 ? BLOCK_MMC_DEV : data->block_type;
276 if (ops->block_type != data_block_type)
278 // TODO What happend on extended internal storage case?
279 if (op == BLOCK_DEV_MOUNT) {
280 ops->mounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
281 } else if (op == BLOCK_DEV_UNMOUNT) {
282 ops->unmounted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
283 } else if (op == BLOCK_DEV_FORMAT) {
284 ops->formatted(data, result, data->block_type == BLOCK_EXTENDEDSD_DEV);
285 } else if (op == BLOCK_DEV_INSERT)
287 else if (op == BLOCK_DEV_REMOVE)
292 // Called by MainThread - Insert
293 static int block_get_new_id(void)
295 static int id = BLOCK_ID_MIN;
296 struct block_device *bdev;
301 for (i = 0 ; i < INT_MAX ; i++) {
303 for (j = 0; j < THREAD_MAX; j++) {
304 pthread_mutex_lock(&(th_manager[j].mutex));
305 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
306 if (bdev->data->id == id) {
311 pthread_mutex_unlock(&(th_manager[j].mutex));
326 static void remove_file(int id, bool extendedsd)
328 char file_name[PATH_LEN];
335 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
337 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
339 ret = remove(file_name);
341 _E("Fail to remove %s. errno: %d", file_name, errno);
344 static void create_file(int id, char *mount_point, bool extendedsd)
347 char file_name[PATH_LEN];
353 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
355 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
357 fp = fopen(file_name, "w+");
359 fprintf(fp, "%s", mount_point);
362 _E("Fail to open %s", file_name);
365 static void signal_device_blocked(struct block_device *bdev)
367 struct block_data *data;
369 char str_block_type[32];
370 char str_readonly[32];
372 char str_primary[32];
378 if (!bdev || !bdev->data)
384 /* Broadcast outside with BlockManager iface */
385 snprintf(str_block_type, sizeof(str_block_type),
386 "%d", data->block_type);
387 arr[0] = str_block_type;
388 arr[1] = (data->devnode ? data->devnode : str_null);
389 arr[2] = (data->syspath ? data->syspath : str_null);
390 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
391 arr[4] = (data->fs_type ? data->fs_type : str_null);
392 arr[5] = (data->fs_version ? data->fs_version : str_null);
393 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
394 snprintf(str_readonly, sizeof(str_readonly),
395 "%d", data->readonly);
396 arr[7] = str_readonly;
397 arr[8] = (data->mount_point ? data->mount_point : str_null);
398 snprintf(str_state, sizeof(str_state),
401 snprintf(str_primary, sizeof(str_primary),
402 "%d", data->primary);
403 arr[10] = str_primary;
404 snprintf(str_flags, sizeof(str_flags), "%d", flags);
406 snprintf(str_id, sizeof(str_id), "%d", data->id);
409 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
410 STORAGED_INTERFACE_BLOCK_MANAGER,
411 BLOCK_DEVICE_BLOCKED,
412 "issssssisibii", arr);
415 static void signal_device_changed(struct block_device *bdev,
416 enum block_dev_operation op)
418 struct block_data *data;
420 char str_block_type[32];
421 char str_readonly[32];
423 char str_primary[32];
429 if (!bdev || !bdev->data)
435 case BLOCK_DEV_MOUNT:
436 BLOCK_GET_MOUNT_FLAGS(data, flags);
438 case BLOCK_DEV_UNMOUNT:
439 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
441 case BLOCK_DEV_FORMAT:
442 BLOCK_GET_FORMAT_FLAGS(data, flags);
449 /* Broadcast outside with BlockManager iface */
450 snprintf(str_block_type, sizeof(str_block_type),
451 "%d", data->block_type);
452 arr[0] = str_block_type;
453 arr[1] = (data->devnode ? data->devnode : str_null);
454 arr[2] = (data->syspath ? data->syspath : str_null);
455 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
456 arr[4] = (data->fs_type ? data->fs_type : str_null);
457 arr[5] = (data->fs_version ? data->fs_version : str_null);
458 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
459 snprintf(str_readonly, sizeof(str_readonly),
460 "%d", data->readonly);
461 arr[7] = str_readonly;
462 arr[8] = (data->mount_point ? data->mount_point : str_null);
463 snprintf(str_state, sizeof(str_state),
466 snprintf(str_primary, sizeof(str_primary),
467 "%d", data->primary);
468 arr[10] = str_primary;
469 snprintf(str_flags, sizeof(str_flags), "%d", flags);
471 snprintf(str_id, sizeof(str_id), "%d", data->id);
474 if (op == BLOCK_DEV_INSERT)
475 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
476 STORAGED_INTERFACE_BLOCK_MANAGER,
478 "issssssisibii", arr);
479 else if (op == BLOCK_DEV_REMOVE)
480 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
481 STORAGED_INTERFACE_BLOCK_MANAGER,
482 BLOCK_DEVICE_REMOVED,
483 "issssssisibii", arr);
485 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
486 STORAGED_INTERFACE_BLOCK_MANAGER,
487 BLOCK_DEVICE_CHANGED,
488 "issssssisibii", arr);
489 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
490 STORAGED_INTERFACE_BLOCK_MANAGER,
491 BLOCK_DEVICE_CHANGED_2,
492 "issssssisibi", arr);
496 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
498 char *name = devnode;
499 int dev = -1, part = -1;
500 char emul[32] = { 0, };
507 sscanf(name, "mmcblk%dp%d", &dev, &part);
510 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
512 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
517 sscanf(name, "vd%31s", emul);
520 for (i = 0 ; i < strlen(emul) ; i++)
521 emul[i] = toupper(emul[i]);
522 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
526 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
534 snprintf(dev, sizeof(dev), "%s", devnode);
536 if (!strstr(dev, "sd"))
540 name += strlen("sd");
542 for (i = 0 ; i < strlen(name) ; i++)
543 name[i] = toupper(name[i]);
544 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
549 static char *generate_mount_path(struct block_data *data)
552 char *name, node[64];
555 if (!data || !data->devnode || !data->fs_usage || (strcmp(data->fs_usage, FILESYSTEM_NAME) && strncmp(data->fs_usage, "crypto", strlen("crypto"))))
558 name = strrchr(data->devnode, '/');
563 switch (data->block_type) {
565 ret = get_mmc_mount_node(name, node, sizeof(node));
568 ret = get_scsi_mount_node(name, node, sizeof(node));
570 case BLOCK_EXTENDEDSD_DEV:
571 return strdup(EXTENDEDSD_MOUNT_PATH);
573 _E("Invalid block type (%d)", data->block_type);
579 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
585 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
589 static bool check_primary_partition(const char *devnode)
591 struct block_fs_ops *fs;
594 const char *filesystem = NULL;
604 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
605 fnmatch(MMC_PATH, devnode, 0) &&
606 fnmatch(SCSI_PATH, devnode, 0) &&
607 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
610 temp = strrchr(devnode, '/');
613 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
614 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
617 /* Emulator support only one partition */
621 snprintf(str, sizeof(str), "%s", devnode);
626 for (i = 1; i <= 9; ++i) {
627 snprintf(str2, sizeof(str2), "%s%d", str, i);
628 if (access(str2, R_OK) != 0)
631 probe = blkid_new_probe_from_filename(str2);
634 if (blkid_do_probe(probe) != 0)
637 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
639 blkid_free_probe(probe);
642 DD_LIST_FOREACH(fs_head, elem, fs) {
643 if (!strncmp(fs->name, filesystem, fs_len)) {
648 blkid_free_probe(probe);
654 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
660 /* Whole data in struct block_data should be freed. */
661 static struct block_data *make_block_data(const char *devnode,
663 const char *fs_usage,
665 const char *fs_version,
666 const char *fs_uuid_enc,
667 const char *readonly)
669 struct block_data *data;
671 /* devnode is unique value so it should exist. */
676 _I("Unknown fs type");
678 data = calloc(1, sizeof(struct block_data));
680 _E("calloc() failed");
684 data->devnode = strdup(devnode);
686 data->syspath = strdup(syspath);
688 data->fs_usage = strdup(fs_usage);
690 data->fs_type = strdup(fs_type);
692 data->fs_version = strdup(fs_version);
694 data->fs_uuid_enc = strdup(fs_uuid_enc);
696 data->readonly = atoi(readonly);
697 data->primary = check_primary_partition(devnode);
699 /* TODO should we know block dev type? */
700 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
701 data->block_type = BLOCK_MMC_DEV;
702 else if (!fnmatch(MMC_PATH, devnode, 0))
703 data->block_type = BLOCK_MMC_DEV;
704 else if (!fnmatch(SCSI_PATH, devnode, 0))
705 data->block_type = BLOCK_SCSI_DEV;
706 else if (!fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0))
707 data->block_type = BLOCK_EXTENDEDSD_DEV;
709 data->block_type = -1;
711 data->mount_point = generate_mount_path(data);
712 BLOCK_FLAG_CLEAR_ALL(data);
714 /* for 2.4 backward compatibility */
715 // What if storage id 1 is existed? (multi sdcard case)
716 if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
717 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME))
718 data->id = EXT_PRIMARY_SD_FIXID;
720 data->id = block_get_new_id();
725 static void free_block_data(struct block_data *data)
731 free(data->fs_usage);
733 free(data->fs_version);
734 free(data->fs_uuid_enc);
735 free(data->mount_point);
739 static int update_block_data(struct block_data *data,
740 const char *fs_usage,
742 const char *fs_version,
743 const char *fs_uuid_enc,
744 const char *readonly,
745 bool mount_point_updated)
750 free(data->fs_usage);
751 data->fs_usage = NULL;
753 data->fs_usage = strdup(fs_usage);
756 data->fs_type = NULL;
758 data->fs_type = strdup(fs_type);
760 free(data->fs_version);
761 data->fs_version = NULL;
763 data->fs_version = strdup(fs_version);
765 free(data->fs_uuid_enc);
766 data->fs_uuid_enc = NULL;
768 data->fs_uuid_enc = strdup(fs_uuid_enc);
770 /* generate_mount_path function should be invoked
771 * after fs_uuid_enc is updated */
772 if (!mount_point_updated) {
773 free(data->mount_point);
774 data->mount_point = generate_mount_path(data);
777 data->readonly = false;
779 data->readonly = atoi(readonly);
781 BLOCK_FLAG_MOUNT_CLEAR(data);
786 static struct block_device *make_block_device(struct block_data *data)
788 struct block_device *bdev;
793 bdev = calloc(1, sizeof(struct block_device));
798 bdev->thread_id = -1;
799 bdev->removed = false;
800 bdev->on_private_op = REQ_NORMAL;
801 bdev->private_pid = 0;
802 bdev->mount_point_updated = false;
807 // Called by MainThread - Remove DevNode
808 static void free_block_device(struct block_device *bdev)
811 struct operation_queue *op;
817 thread_id = bdev->thread_id;
818 if (thread_id < 0 || thread_id >= THREAD_MAX)
821 pthread_mutex_lock(&(th_manager[thread_id].mutex));
823 th_manager[thread_id].num_dev--;
824 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
825 free_block_data(bdev->data);
827 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
829 th_manager[thread_id].op_len--;
830 DD_LIST_REMOVE(bdev->op_queue, op);
833 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
838 // Called By MainThread - Remove Device
839 static struct block_device *find_block_device(const char *devnode)
841 struct block_device *bdev;
846 len = strlen(devnode) + 1;
847 for (i = 0; i < THREAD_MAX; i++) {
848 pthread_mutex_lock(&(th_manager[i].mutex));
849 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
850 if (bdev->data && !bdev->removed &&
851 !strncmp(bdev->data->devnode, devnode, len)) {
852 pthread_mutex_unlock(&(th_manager[i].mutex));
856 pthread_mutex_unlock(&(th_manager[i].mutex));
862 // Called By MainThread - Remove Device
863 static struct block_device *find_block_device_path(const char *mount_point)
865 struct block_device *bdev;
870 len = strlen(mount_point) + 1;
871 for (i = 0; i < THREAD_MAX; i++) {
872 pthread_mutex_lock(&(th_manager[i].mutex));
873 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
874 if (bdev->data && !bdev->removed &&
875 (bdev->data->mount_point != NULL && !strncmp(bdev->data->mount_point, mount_point, len))) {
876 pthread_mutex_unlock(&(th_manager[i].mutex));
880 pthread_mutex_unlock(&(th_manager[i].mutex));
886 // Called By MainThread - Mount,Unmount,Format,GetInfo
887 static struct block_device *find_block_device_by_id(int id)
889 struct block_device *bdev;
893 for (i = 0; i < THREAD_MAX; i++) {
894 pthread_mutex_lock(&(th_manager[i].mutex));
895 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
900 if (bdev->data->id == id) {
901 pthread_mutex_unlock(&(th_manager[i].mutex));
905 pthread_mutex_unlock(&(th_manager[i].mutex));
911 static const char *get_operation_char(enum block_dev_operation op)
914 case BLOCK_DEV_MOUNT:
917 case BLOCK_DEV_UNMOUNT:
920 case BLOCK_DEV_FORMAT:
923 case BLOCK_DEV_INSERT:
926 case BLOCK_DEV_REMOVE:
929 case BLOCK_LUKS_CLOSE:
933 _E("invalid operation (%d)", op);
937 static void create_external_apps_directory(void)
941 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
942 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
943 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
945 _E("Fail to create external directory");
948 static int pipe_trigger(enum block_dev_operation op,
949 struct block_device *bdev, int result)
951 struct pipe_data pdata = { op, bdev, result };
954 _D("op : %s, bdev : %p, result : %d",
955 get_operation_char(pdata.op),
956 pdata.bdev, pdata.result);
958 // Multi thread should not write at the same time
959 pthread_mutex_lock(&pipe_mutex);
960 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
961 pthread_mutex_unlock(&pipe_mutex);
963 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
966 static bool pipe_cb(int fd, void *data)
968 struct pipe_data pdata = {0,};
973 n = read(fd, &pdata, sizeof(pdata));
974 if (n != sizeof(pdata) || !pdata.bdev) {
975 _E("fail to read struct pipe data");
979 _I("op : %s, bdev : %p, result : %d",
980 get_operation_char(pdata.op),
981 pdata.bdev, pdata.result);
983 if (pdata.op == BLOCK_LUKS_CLOSE)
986 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
987 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
988 ret = change_mount_point(pdata.bdev, "");
989 /* Modify /run/external-storage/id file */
991 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
992 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
994 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
999 if (pdata.op == BLOCK_DEV_MOUNT &&
1000 pdata.bdev->data->state == BLOCK_MOUNT &&
1001 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
1002 pdata.bdev->data->primary)
1003 create_external_apps_directory();
1004 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1005 /* Remove file for block device /run/xxxxxx/id */
1006 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
1009 /* Broadcast to mmc and usb storage module */
1010 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
1012 /* Broadcast outside with Block iface */
1013 if (pdata.bdev->on_private_op == REQ_NORMAL)
1014 signal_device_changed(pdata.bdev, pdata.op);
1015 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
1016 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1017 pdata.bdev->on_private_op = REQ_NORMAL;
1018 _D("Private operation state: %d", pdata.bdev->on_private_op);
1021 if (pdata.op == BLOCK_DEV_MOUNT) {
1022 pdata.bdev->on_private_op = REQ_PRIVATE;
1023 _D("Private operation state: %d", pdata.bdev->on_private_op);
1027 if (pdata.op == BLOCK_DEV_REMOVE) {
1028 thread_id = pdata.bdev->thread_id;
1029 if (thread_id < 0 || thread_id >= THREAD_MAX)
1031 free_block_device(pdata.bdev);
1038 static int pipe_init(void)
1042 ret = pipe2(pfds, O_CLOEXEC);
1046 ret = add_fd_read_handler(pfds[0], pipe_cb,
1047 NULL, NULL, &phandler);
1049 _E("Failed to add pipe handler (%d)", ret);
1056 static void pipe_exit(void)
1059 remove_fd_read_handler(&phandler);
1069 static int mmc_check_and_unmount(const char *path)
1077 while (mount_check(path)) {
1081 if (retry > UNMOUNT_RETRY)
1088 static bool check_rw_mount(const char *szPath)
1090 struct statvfs mount_stat;
1092 if (!statvfs(szPath, &mount_stat)) {
1093 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1099 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1102 struct udev_device *dev;
1103 const char *fs_type;
1104 const char *fs_usage;
1111 for (wait = 0; wait < 10; wait++) {
1114 _E("fail to create udev library context");
1118 dev = udev_device_new_from_syspath(udev, data->syspath);
1120 _E("fail to create new udev device");
1125 fs_type = udev_device_get_property_value(dev, "ID_FS_TYPE");
1126 fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE");
1127 /* fs_usage for crpto_LUKS is crypto */
1128 if (!fs_type || (strncmp(fs_type, VFAT_NAME, strlen(VFAT_NAME)) && strncmp(fs_type, EXT4_NAME, strlen(EXT4_NAME))))
1130 else if (!fs_usage || strncmp(FILESYSTEM_NAME, fs_usage, strlen(FILESYSTEM_NAME)))
1135 udev_device_unref(dev);
1139 r = update_block_data(data,
1140 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1141 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1142 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1143 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1144 udev_device_get_sysattr_value(dev, "ro"),
1145 mount_point_updated);
1147 _E("fail to update block data for %s", data->devnode);
1149 udev_device_unref(dev);
1154 static int block_mount(struct block_data *data)
1156 struct block_fs_ops *fs;
1161 if (!data || !data->devnode || !data->mount_point)
1164 /* check existing mounted */
1165 if (mount_check(data->mount_point))
1168 /* create mount point */
1169 if (access(data->mount_point, R_OK) != 0) {
1170 if (mkdir(data->mount_point, 0755) < 0)
1174 /* check matched file system */
1175 if (!data->fs_usage ||
1176 strncmp(data->fs_usage, FILESYSTEM_NAME,
1177 sizeof(FILESYSTEM_NAME)) != 0) {
1182 if (!data->fs_type) {
1183 _E("There is no file system");
1184 BLOCK_FLAG_SET(data, FS_EMPTY);
1190 len = strlen(data->fs_type) + 1;
1191 DD_LIST_FOREACH(fs_head, elem, fs) {
1192 if (!strncmp(fs->name, data->fs_type, len))
1197 _E("Not supported file system (%s)", data->fs_type);
1198 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1203 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1204 r = fs->mount(false, data->devnode, data->mount_point);
1206 r = fs->mount(smack, data->devnode, data->mount_point);
1209 BLOCK_FLAG_SET(data, FS_BROKEN);
1214 r = check_rw_mount(data->mount_point);
1221 rmdir(data->mount_point);
1225 static int mount_start(struct block_device *bdev)
1227 struct block_data *data;
1235 _I("Mount Start : (%s -> %s)",
1236 data->devnode, data->mount_point);
1238 /* mount operation */
1239 r = block_mount(data);
1240 if (r != -EROFS && r < 0) {
1241 _E("fail to mount %s device : %d", data->devnode, r);
1246 data->readonly = true;
1247 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1250 data->state = BLOCK_MOUNT;
1252 if (data->block_type == BLOCK_MMC_DEV) {
1253 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1254 ret = app2ext_migrate_legacy_all();
1256 _E("app2ext failed");
1260 if (r < 0 && r != -EROFS)
1261 data->state = BLOCK_UNMOUNT;
1263 _I("%s result : %s, %d", __func__, data->devnode, r);
1265 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1266 _E("fail to trigger pipe");
1271 static int change_mount_point(struct block_device *bdev,
1272 const char *mount_point)
1274 struct block_data *data;
1280 free(data->mount_point);
1282 /* If the mount path already exists, the path cannot be used */
1284 access(mount_point, F_OK) != 0) {
1285 data->mount_point = strdup(mount_point);
1286 bdev->mount_point_updated = true;
1288 data->mount_point = generate_mount_path(data);
1289 bdev->mount_point_updated = false;
1295 static int mount_block_device(struct block_device *bdev)
1297 struct block_data *data;
1300 if (!bdev || !bdev->data)
1304 if (data->state == BLOCK_MOUNT) {
1305 _I("%s is already mounted", data->devnode);
1309 if (!block_conf[data->block_type].multimount &&
1311 _I("Not support multi mount by config info");
1315 r = mount_start(bdev);
1317 _E("Failed to mount (%s)", data->devnode);
1324 static int block_unmount(struct block_device *bdev,
1325 enum unmount_operation option)
1327 struct block_data *data;
1329 struct timespec time = {0,};
1331 if (!bdev || !bdev->data || !bdev->data->mount_point)
1336 if (bdev->on_private_op == REQ_NORMAL)
1337 signal_device_blocked(bdev);
1339 /* it must called before unmounting mmc */
1340 r = mmc_check_and_unmount(data->mount_point);
1343 if (option == UNMOUNT_NORMAL) {
1344 _I("Failed to unmount with normal option : %d", r);
1348 _I("Execute force unmount!");
1349 /* Force Unmount Scenario */
1354 * should unmount the below vconf key. */
1355 if ((data->block_type == BLOCK_MMC_DEV ||
1356 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1358 /* At first, notify to other app
1359 * who already access sdcard */
1360 _I("Notify to other app who already access sdcard");
1361 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1362 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1366 /* Second, kill app with SIGTERM */
1367 _I("Kill app with SIGTERM");
1368 terminate_process(data->mount_point, false);
1371 /* Last time, kill app with SIGKILL */
1372 _I("Kill app with SIGKILL");
1373 terminate_process(data->mount_point, true);
1376 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1377 _I("Failed to unmount with lazy option : %d",
1384 /* it takes some seconds til other app completely clean up */
1385 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1386 nanosleep(&time, NULL);
1388 print_open_files(data->mount_point);
1390 r = mmc_check_and_unmount(data->mount_point);
1392 _D("Success to unmount (%s)", data->mount_point);
1398 data->state = BLOCK_UNMOUNT;
1400 if (rmdir(data->mount_point) < 0)
1401 _E("fail to remove %s directory", data->mount_point);
1406 static int unmount_block_device(struct block_device *bdev,
1407 enum unmount_operation option)
1409 struct block_data *data;
1412 if (!bdev || !bdev->data)
1416 if (data->state == BLOCK_UNMOUNT) {
1417 _I("%s is already unmounted", data->devnode);
1418 r = mmc_check_and_unmount(data->mount_point);
1420 _E("The path was existed, but could not delete it(%s)",
1425 _I("Unmount Start : (%s -> %s)",
1426 data->devnode, data->mount_point);
1428 r = block_unmount(bdev, option);
1430 _E("fail to unmount %s device : %d", data->devnode, r);
1434 BLOCK_FLAG_MOUNT_CLEAR(data);
1437 _I("%s result : %s, %d", __func__, data->devnode, r);
1439 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1440 _E("fail to trigger pipe");
1445 static int block_format(struct block_data *data,
1446 const char *fs_type, bool mount_point_updated)
1448 const struct block_fs_ops *fs;
1454 if (!data || !data->devnode || !data->mount_point)
1457 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1463 fstype = data->fs_type;
1469 len = strlen(fstype);
1470 DD_LIST_FOREACH(fs_head, elem, fs) {
1471 if (!strncmp(fs->name, fstype, len))
1476 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1477 _E("not supported file system(%s)", fstype);
1481 _I("format path : %s", data->devnode);
1482 fs->check(data->devnode);
1483 r = fs->format(data->devnode);
1485 _E("fail to format block data for %s", data->devnode);
1489 /* need to update the partition data.
1490 * It can be changed in doing format. */
1491 retrieve_udev_device(data, mount_point_updated);
1496 static int format_block_device(struct block_device *bdev,
1497 const char *fs_type,
1498 enum unmount_operation option)
1500 struct block_data *data;
1508 _I("Format Start : (%s -> %s)",
1509 data->devnode, data->mount_point);
1511 if (data->state == BLOCK_MOUNT) {
1512 r = block_unmount(bdev, option);
1514 _E("fail to unmount %s device : %d", data->devnode, r);
1519 r = block_format(data, fs_type, bdev->mount_point_updated);
1521 _E("fail to format %s device : %d", data->devnode, r);
1524 _I("%s result : %s, %d", __func__, data->devnode, r);
1526 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1528 _E("fail to trigger pipe");
1533 static struct format_data *get_format_data(
1534 const char *fs_type, enum unmount_operation option)
1536 struct format_data *fdata;
1538 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1540 _E("fail to allocate format data");
1545 fdata->fs_type = strdup(fs_type);
1547 fdata->fs_type = NULL;
1548 fdata->option = option;
1553 static void release_format_data(struct format_data *data)
1557 free(data->fs_type);
1562 // Called by BlockThread - Real Mount Op
1563 static int block_mount_device(struct block_device *bdev, void *data)
1572 thread_id = bdev->thread_id;
1573 if (thread_id < 0 || thread_id >= THREAD_MAX)
1575 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1576 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1577 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1579 _E("(%d) does not exist in the device list", bdev->data->devnode);
1583 /* mount automatically */
1584 ret = mount_block_device(bdev);
1586 _E("fail to mount block device for %s", bdev->data->devnode);
1591 // Called by BlockThread - Real Format Op
1592 static int block_format_device(struct block_device *bdev, void *data)
1597 struct format_data *fdata = (struct format_data *)data;
1599 if (!bdev || !fdata) {
1604 thread_id = bdev->thread_id;
1605 if (thread_id < 0 || thread_id >= THREAD_MAX)
1607 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1608 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1609 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1611 _E("(%d) does not exist in the device list", bdev->data->devnode);
1616 ret = format_block_device(bdev, fdata->fs_type, fdata->option);
1618 _E("fail to format block device for %s", bdev->data->devnode);
1621 release_format_data(fdata);
1626 // Called by BlockThread - Real Unmount Op
1627 static int block_unmount_device(struct block_device *bdev, void *data)
1630 long option = (long)data;
1635 ret = unmount_block_device(bdev, option);
1637 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1644 /* Called by BlockThread - Remove Operation
1645 Direct Call at BlockThread
1646 Previously this function was called by MainThread. However, it will increase complexity.
1647 Need thread lock before to call remove_operation
1649 static void remove_operation(struct block_device *bdev)
1651 struct operation_queue *op;
1657 thread_id = bdev->thread_id;
1658 if (thread_id < 0 || thread_id >= THREAD_MAX)
1661 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1663 _D("Remove operation (%s, %s)",
1664 get_operation_char(op->op),
1665 bdev->data->devnode);
1667 DD_LIST_REMOVE(bdev->op_queue, op);
1673 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1680 rep = make_dbus_reply_message_simple(reply_handle, result);
1681 reply_dbus_method_result(reply_handle, rep);
1684 // Called by BlockThread
1685 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1687 struct operation_queue *temp;
1700 thread_id = bdev->thread_id;
1701 if (thread_id < 0 || thread_id >= THREAD_MAX)
1704 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1706 DD_LIST_FOREACH(*queue, l, temp) {
1707 if (temp->op == BLOCK_DEV_REMOVE) {
1712 th_manager[thread_id].op_len--;
1713 block_send_dbus_reply((*op)->reply_handle, 0);
1716 remove_operation(bdev);
1717 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1720 // Called by BlockThread
1721 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1723 struct operation_queue *temp;
1726 bool unmounted = false;
1737 thread_id = bdev->thread_id;
1738 if (thread_id < 0 || thread_id >= THREAD_MAX)
1741 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1742 DD_LIST_FOREACH(*queue, l, temp) {
1743 if (temp->op == BLOCK_DEV_UNMOUNT) {
1745 _D("Operation queue has unmount operation");
1749 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1754 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1756 DD_LIST_FOREACH(*queue, l, temp) {
1757 if (temp->op == BLOCK_DEV_UNMOUNT) {
1762 th_manager[thread_id].op_len--;
1763 block_send_dbus_reply((*op)->reply_handle, 0);
1766 remove_operation(bdev);
1767 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1772 // Called by BlockThread
1773 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1777 char devnode[PATH_MAX];
1778 enum block_dev_operation operation;
1779 bool unmounted = false;
1786 thread_id = bdev->thread_id;
1787 if (thread_id < 0 || thread_id >= THREAD_MAX)
1790 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1800 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1801 get_operation_char(operation), devnode);
1804 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1805 check_removed(bdev, &queue, &op);
1807 _D("Trigger operation again (%s, %s)",
1808 get_operation_char(operation), devnode);
1810 if (operation == BLOCK_DEV_MOUNT) {
1811 unmounted = check_unmount(bdev, &queue, &op);
1814 _D("Trigger operation again (%s, %s)",
1815 get_operation_char(operation), devnode);
1819 switch (operation) {
1820 case BLOCK_DEV_INSERT:
1822 case BLOCK_DEV_MOUNT:
1823 ret = block_mount_device(bdev, op->data);
1824 _D("Mount (%s) result:(%d)", devnode, ret);
1826 case BLOCK_DEV_FORMAT:
1827 ret = block_format_device(bdev, op->data);
1828 _D("Format (%s) result:(%d)", devnode, ret);
1830 case BLOCK_DEV_UNMOUNT:
1831 ret = block_unmount_device(bdev, op->data);
1832 _D("Unmount (%s) result:(%d)", devnode, ret);
1834 case BLOCK_DEV_REMOVE:
1837 case BLOCK_LUKS_CLOSE:
1838 ret = ode_luks_close_sync(EXTENDEDSD_NAME);
1840 _E("Failed on ode_luks_close(%s)", EXTENDEDSD_NAME);
1843 _E("Operation type is invalid (%d)", op->op);
1849 * during checking the queue length */
1850 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1853 th_manager[thread_id].op_len--;
1855 block_send_dbus_reply(op->reply_handle, ret);
1857 queue = bdev->op_queue;
1858 if (queue != NULL) {
1859 queue = DD_LIST_NEXT(queue);
1861 op = DD_LIST_NTH(queue, 0);
1867 remove_operation(bdev);
1869 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1872 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE || operation == BLOCK_LUKS_CLOSE) {
1873 if (pipe_trigger(operation, bdev, 0) < 0)
1874 _E("fail to trigger pipe");
1881 // Called by BlockThread
1882 static void *block_th_start(void *arg)
1884 struct block_device *temp;
1885 struct manage_thread *th = (struct manage_thread *)arg;
1886 struct operation_queue *op = NULL;
1888 dd_list *queue = NULL;
1893 thread_id = th->thread_id;
1894 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1895 _E("Thread Number: %d", th->thread_id);
1900 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1901 if (th_manager[thread_id].op_len == 0) {
1902 _D("Operation queue of thread is empty");
1903 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1904 _D("Wake up %d", thread_id);
1907 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1908 queue = temp->op_queue;
1910 op = DD_LIST_NTH(queue, 0);
1912 _D("Operation queue for device %s is Empty", temp->data->devnode);
1916 queue = DD_LIST_NEXT(queue);
1924 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1926 if (op && !op->done)
1927 trigger_operation(temp, queue, op);
1932 // This function will be refactored later
1933 // Especially, we don't need to keep th_node_list.
1934 static int find_thread(char *devnode)
1941 int i, len, min, min_num;
1942 int dev_mmc = -1, part = -1, num;
1945 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1946 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1953 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1954 th_node = strdup(str);
1955 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1956 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1957 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1958 th_node = strdup(str);
1960 th_node = strdup(devnode);
1962 len = strlen(th_node) + 1;
1965 for (i = 0; i < THREAD_MAX; i++) {
1966 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1967 if (!strncmp(temp, th_node, len)) {
1972 if (th_manager[i].num_dev < min_num) {
1973 min_num = th_manager[i].num_dev;
1978 if (min >= 0 && min < THREAD_MAX) {
1979 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1983 _E("Finding thread is failed");
1984 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1988 /* Only Main thread is permmited */
1989 // Called by MainThread
1990 static int add_operation(struct block_device *bdev,
1991 enum block_dev_operation operation,
1992 dbus_method_reply_handle_h reply_handle, void *data)
1994 struct operation_queue *op;
2003 _I("Add operation (%s, %s)",
2004 get_operation_char(operation),
2005 bdev->data->devnode);
2007 thread_id = bdev->thread_id;
2008 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2009 _E("Fail to find thread to add");
2013 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
2015 _E("malloc failed");
2021 op->reply_handle = reply_handle;
2024 * during adding queue and checking the queue length */
2025 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2027 /* Only modified between lock and unlock of mutex */
2030 start_th = th_manager[thread_id].start_th;
2031 DD_LIST_APPEND(bdev->op_queue, op);
2032 th_manager[thread_id].op_len++;
2034 if (th_manager[thread_id].op_len == 1 && !start_th)
2035 pthread_cond_signal(&(th_manager[thread_id].cond));
2037 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2040 /* Need to disble app2ext whenever unmounting mmc */
2041 if (op->op == BLOCK_DEV_UNMOUNT &&
2042 bdev->data->state == BLOCK_MOUNT &&
2043 bdev->data->block_type == BLOCK_MMC_DEV &&
2044 bdev->data->primary)
2045 if (app2ext_disable_all_external_pkgs() < 0)
2046 _E("app2ext_disable_all_external_pkgs() failed");
2050 _D("Start New thread for block device");
2051 th_manager[thread_id].start_th = false;
2052 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2054 _E("fail to create thread for %s", bdev->data->devnode);
2058 pthread_detach(th_manager[thread_id].th);
2064 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2067 struct dirent entry;
2069 const char *syspath;
2072 syspath = udev_device_get_syspath(dev);
2076 dp = opendir(syspath);
2078 _E("fail to open %s", syspath);
2082 /* TODO compare devname and d_name */
2083 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2084 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2085 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2097 static bool check_partition(struct udev_device *dev)
2099 const char *devtype;
2100 const char *part_table_type;
2101 const char *fs_usage;
2104 /* only consider disk type, never partitions */
2105 devtype = udev_device_get_devtype(dev);
2109 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2110 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2113 part_table_type = udev_device_get_property_value(dev,
2114 "ID_PART_TABLE_TYPE");
2115 if (part_table_type) {
2116 fs_usage = udev_device_get_property_value(dev,
2119 strncmp(fs_usage, FILESYSTEM_NAME, sizeof(FILESYSTEM_NAME)) == 0) {
2120 if (!disk_is_partitioned_by_kernel(dev))
2127 if (disk_is_partitioned_by_kernel(dev)) {
2136 // Called by MainThread
2137 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2139 struct block_data *data;
2140 struct block_device *bdev;
2141 //char id_string[PATH_LEN];
2145 bool need_format = false;
2147 partition = check_partition(dev);
2149 /* if there is a partition, skip this request */
2150 _I("%s device has partitions, skip this time", devnode);
2154 if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2155 char syspath[128] = {0};
2158 r = rindex(udev_device_get_syspath(dev), '/');
2159 if (!r) return -ENODEV;
2161 snprintf(syspath, sizeof(syspath), "/sys/block%s", r);
2163 data = make_block_data(devnode,
2168 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2169 udev_device_get_sysattr_value(dev, "ro"));
2172 data = make_block_data(devnode,
2173 udev_device_get_syspath(dev),
2174 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2175 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2176 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2177 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2178 udev_device_get_sysattr_value(dev, "ro"));
2182 _E("fail to make block data for %s", devnode);
2186 if (!block_conf[data->block_type].multimount && !data->primary &&
2187 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM_NAME)) {
2188 _D("Not support multi mount by config info");
2189 free_block_data(data);
2193 if (!block_control) {
2194 if (!mapper && strncmp(data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2195 _D("Block module is disabled");
2196 free_block_data(data);
2202 bdev = make_block_device(data);
2204 _E("fail to make block device for %s", devnode);
2205 free_block_data(data);
2209 thread_id = find_thread(bdev->data->devnode);
2210 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2211 _E("Fail to find thread to add");
2212 free_block_device(bdev);
2215 bdev->thread_id = thread_id;
2217 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2218 th_manager[thread_id].num_dev++;
2219 DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2220 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2223 struct format_data *fdata;
2225 fdata = get_format_data(NULL, UNMOUNT_FORCE);
2227 _E("Failed to get format data");
2231 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2233 _E("Failed to add operation (format %s)", bdev->data->devnode);
2234 release_format_data(fdata);
2238 if (!bdev->data->fs_type) {
2239 _E("Unformatted Storage");
2240 free_block_device(bdev);
2242 } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2243 // bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2244 bdev->data->primary = true;
2245 _D("Need to unlock encrypted sdcard");
2246 // ---- ODE UI launch ----
2247 ret = launch_system_app(POPUP_DEFAULT
2250 , "unlockextendedsd"
2254 , bdev->data->devnode
2258 _E("Failed to launch popup");
2260 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2262 _E("Failed to add operation (insert %s)", devnode);
2263 free_block_device(bdev);
2268 } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2269 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2270 ret = change_mount_point(bdev, EXTENDEDSD_MOUNT_PATH);
2273 free_block_device(bdev);
2278 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2280 _E("Failed to add operation (insert %s)", devnode);
2281 free_block_device(bdev);
2285 // Not a regular filesystem -> skip mounting
2286 if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM_NAME)) {
2287 _I("Not a filesystem. Not mounting");
2291 /* Create file for block device /run/external-storage/id */
2292 create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2293 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2295 _E("Failed to add operation (mount %s)", devnode);
2301 static int remove_block_device(struct udev_device *dev, const char *devnode)
2303 struct block_device *bdev;
2304 struct block_device *bdev_extended;
2307 bdev = find_block_device(devnode);
2309 _E("fail to find block data for %s", devnode);
2313 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2315 bdev->removed = true;
2316 if (bdev->on_private_op != REQ_NORMAL) {
2317 bdev->on_private_op = REQ_NORMAL;
2318 _D("Private operation state: %d", bdev->on_private_op);
2321 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2322 bdev_extended = find_block_device_path(EXTENDEDSD_MOUNT_PATH);
2324 if (bdev_extended) {
2325 BLOCK_FLAG_SET(bdev_extended->data, UNMOUNT_UNSAFE);
2327 bdev_extended->removed = true;
2328 if (bdev_extended->on_private_op != REQ_NORMAL) {
2329 bdev_extended->on_private_op = REQ_NORMAL;
2330 _D("Private operation state: %d", bdev_extended->on_private_op);
2333 ret = add_operation(bdev_extended, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2335 _E("Failed to add operation (unmount %s)", devnode);
2339 ret = add_operation(bdev_extended, BLOCK_LUKS_CLOSE, NULL, NULL);
2341 _E("Failed to add operation (luks_close %s)", devnode);
2345 ret = add_operation(bdev_extended, BLOCK_DEV_REMOVE, NULL, NULL);
2347 _E("Failed to add operation (remove %s)", devnode);
2351 _E("fail to find block data for extended sd card");
2354 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2356 _E("Failed to add operation (unmount %s)", devnode);
2360 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2362 _E("Failed to add operation (remove %s)", devnode);
2369 static int get_internal_storage_number(void)
2371 struct libmnt_table *t = NULL;
2372 struct libmnt_fs *fs;
2375 int r = 0, dev_temp;
2377 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2378 (is_emulator() && dev_internal_emul != '\0'))
2381 t = mnt_new_table();
2385 r = mnt_table_parse_mtab(t, NULL);
2391 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2397 temp = mnt_fs_get_srcpath(fs);
2401 name = strrchr(temp, '/');
2405 /* Boot from USB is not handled */
2406 if (!is_emulator()) {
2407 if (!fnmatch(MMC_PATH, temp, 0))
2408 sscanf(name, "mmcblk%d", &dev_internal);
2409 else if (!fnmatch(SCSI_PATH, temp, 0))
2410 sscanf(name, "sd%c", &dev_internal_scsi);
2412 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2413 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2415 dev_internal_emul = '\0';
2423 static int check_external_storage(const char* devnode)
2425 char dev_scsi = '\0';
2428 int dev_num = -1, dev_temp;
2433 name = strrchr(devnode, '/');
2437 if (!is_emulator()) {
2438 if (!fnmatch(MMC_PATH, devnode, 0)) {
2439 sscanf(name, "mmcblk%d", &dev_num);
2440 if (dev_internal == dev_num) {
2441 _D("%s is internal storage", devnode);
2444 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2445 sscanf(name, "sd%c", &dev_scsi);
2446 if (dev_internal_scsi == dev_scsi) {
2447 _D("%s is internal storage", devnode);
2452 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2453 sscanf(name, "vd%c%d", &emul, &dev_temp);
2454 if (dev_internal_emul == emul) {
2455 _D("%s is internal storage", devnode);
2464 static int check_already_handled(const char* devnode)
2466 struct block_device *bdev;
2467 struct block_data *data;
2471 for (i = 0; i < THREAD_MAX; i++) {
2472 pthread_mutex_lock(&(th_manager[i].mutex));
2473 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2479 if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2480 pthread_mutex_unlock(&(th_manager[i].mutex));
2484 pthread_mutex_unlock(&(th_manager[i].mutex));
2490 static int block_init_from_udev_enumerate(void)
2493 struct udev_enumerate *enumerate;
2494 struct udev_list_entry *list_entry, *list_sub_entry;
2495 struct udev_device *dev;
2496 const char *syspath;
2497 const char *devnode;
2502 _E("fail to create udev library context");
2506 /* create a list of the devices in the 'usb' subsystem */
2507 enumerate = udev_enumerate_new(udev);
2509 _E("fail to create an enumeration context");
2513 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2514 udev_enumerate_add_match_property(enumerate,
2515 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2516 udev_enumerate_add_match_property(enumerate,
2517 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2518 udev_enumerate_scan_devices(enumerate);
2520 udev_list_entry_foreach(list_entry,
2521 udev_enumerate_get_list_entry(enumerate)) {
2522 syspath = udev_list_entry_get_name(list_entry);
2526 dev = udev_device_new_from_syspath(
2527 udev_enumerate_get_udev(enumerate),
2533 udev_list_entry_foreach(list_sub_entry,
2534 udev_device_get_devlinks_list_entry(dev)) {
2535 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2536 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2543 devnode = udev_device_get_devnode(dev);
2545 udev_device_unref(dev);
2549 if (fnmatch(MMC_PATH, devnode, 0) &&
2550 fnmatch(SCSI_PATH, devnode, 0) &&
2551 fnmatch(EXTENDEDSD_NODE_PATH, devnode, 0)) {
2552 udev_device_unref(dev);
2557 r = check_external_storage(devnode);
2559 udev_device_unref(dev);
2563 r = check_already_handled(devnode);
2565 _I("%s is already handled", devnode);
2566 udev_device_unref(dev);
2570 _I("%s device add", devnode);
2571 add_block_device(dev, devnode, false);
2573 udev_device_unref(dev);
2576 udev_enumerate_unref(enumerate);
2581 // Called by MainThread
2582 static void show_block_device_list(void)
2584 struct block_device *bdev;
2585 struct block_data *data;
2589 for (i = 0; i < THREAD_MAX; i++) {
2590 pthread_mutex_lock(&(th_manager[i].mutex));
2591 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2597 _D("%s:", data->devnode);
2598 _D("\tSyspath: %s", data->syspath);
2599 _D("\tBlock type: %d", data->block_type);
2600 _D("\tFs type: %s", data->fs_type);
2601 _D("\tFs usage: %s", data->fs_usage);
2602 _D("\tFs version: %s", data->fs_version);
2603 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2604 _D("\tReadonly: %s",
2605 (data->readonly ? "true" : "false"));
2606 _D("\tMount point: %s", data->mount_point);
2607 _D("\tMount state: %s",
2608 (data->state == BLOCK_MOUNT ?
2609 "mount" : "unmount"));
2611 (data->primary ? "true" : "false"));
2612 _D("\tID: %d", data->id);
2614 pthread_mutex_unlock(&(th_manager[i].mutex));
2618 // Called by MainThread
2619 static void remove_whole_block_device(void)
2621 struct block_device *bdev;
2627 for (i = 0; i < THREAD_MAX; i++) {
2629 pthread_mutex_lock(&(th_manager[i].mutex));
2630 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2631 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV ||
2632 !strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
2634 if (bdev->removed == false)
2637 pthread_mutex_unlock(&(th_manager[i].mutex));
2639 if (bdev && bdev->removed == false) {
2640 bdev->removed = true;
2641 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2643 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2645 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2647 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2654 static void booting_done(const char *sender_name,
2655 const char *object_path, const char *interface_name,
2656 const char *signal_name, DBusMessage *msg,
2659 static int done = 0;
2667 /* register mmc uevent control routine */
2668 ret = register_udev_uevent_control(&uh);
2670 _E("fail to register block uevent : %d", ret);
2672 block_control = true;
2673 /* if there is the attached device, try to mount */
2674 block_init_from_udev_enumerate();
2679 static void block_poweroff(const char *sender_name,
2680 const char *object_path, const char *interface_name,
2681 const char *signal_name, DBusMessage *msg,
2684 static int status = 0;
2689 /* unregister mmc uevent control routine */
2690 unregister_udev_uevent_control(&uh);
2691 remove_whole_block_device();
2694 static void uevent_block_handler(struct udev_device *dev)
2696 const char *devnode = NULL;
2698 struct udev_list_entry *list_entry;
2700 bool mapper = false;
2702 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2703 const char *devlink = udev_list_entry_get_name(list_entry);
2704 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2708 if (!fnmatch(EXTENDEDSD_NODE_PATH, devlink, 0)) {
2716 devnode = udev_device_get_devnode(dev);
2720 if (fnmatch(MMC_PATH, devnode, 0) &&
2721 fnmatch(SCSI_PATH, devnode, 0))
2725 r = check_external_storage(devnode);
2729 action = udev_device_get_action(dev);
2733 _I("%s device %s", devnode, action);
2734 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2735 (mapper && !strcmp(action, UDEV_CHANGE))) {
2736 r = check_already_handled(devnode);
2738 _I("%s is already handled", devnode);
2742 add_block_device(dev, devnode, mapper);
2743 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2744 remove_block_device(dev, devnode);
2745 } else if (!strncmp(action, UDEV_CHANGE, sizeof(UDEV_CHANGE))) {
2746 struct block_device *bdev;
2747 bdev = find_block_device(devnode);
2749 _E("fail to find block data for %s", devnode);
2752 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
2755 r = update_block_data(bdev->data,
2756 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2757 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2758 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2759 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2760 udev_device_get_sysattr_value(dev, "ro"),
2763 _E("fail to update block data for %s", bdev->data->devnode);
2764 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
2765 _I("filesystem type is updated: crypto_LUKS");
2766 if (bdev->data->fs_usage)
2767 _I("fs_usage: %s", bdev->data->fs_usage);
2771 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2772 DBusMessage *msg, bool onprivate)
2774 struct block_device *bdev;
2779 if (!block_control) {
2780 _D("Block module is disabled");
2785 if (!reply_handle || !msg)
2788 ret = dbus_message_get_args(msg, NULL,
2789 DBUS_TYPE_INT32, &id,
2790 DBUS_TYPE_STRING, &mount_point,
2795 bdev = find_block_device_by_id(id);
2797 _E("Failed to find (%d) in the device list", id);
2802 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV ||
2803 !strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2804 _D("Mount dbus request for extended internal storage is blocked");
2809 if (bdev->on_private_op != REQ_NORMAL) {
2814 if (bdev->data->state == BLOCK_MOUNT) {
2815 _I("%s is already mounted", bdev->data->devnode);
2821 bdev->on_private_op = REQ_PRIVATE;
2822 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2823 _D("Private operation state: %d", bdev->on_private_op);
2825 if (bdev->on_private_op != REQ_NORMAL) {
2826 _E("Failed to process mount operation");
2832 /* if requester want to use a specific mount point */
2833 if (mount_point && strncmp(mount_point, "", 1) != 0) {
2834 ret = change_mount_point(bdev, mount_point);
2840 /* Create /run/external-storage/id file */
2841 create_file(bdev->data->id, bdev->data->mount_point, false);
2843 /* Create file for block device /run/external-storage/id */
2844 create_file(bdev->data->id, bdev->data->mount_point, false);
2847 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2849 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2856 return make_dbus_reply_message_simple(reply_handle, ret);
2859 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2862 return request_mount_block(reply_handle, msg, false);
2865 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2868 return request_mount_block(reply_handle, msg, true);
2871 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2872 DBusMessage *msg, bool onprivate)
2874 struct block_device *bdev;
2880 if (!block_control) {
2881 _D("Block module is disabled");
2886 if (!reply_handle || !msg)
2889 ret = dbus_message_get_args(msg, NULL,
2890 DBUS_TYPE_INT32, &id,
2891 DBUS_TYPE_INT32, &option,
2896 bdev = find_block_device_by_id(id);
2898 _E("Failed to find (%d) in the device list", id);
2903 /* Unmount dbus call is needed when app proceeds extended internal -> portable storage */
2904 if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2905 _D("Unmount dbus request for extended internal storage is blocked");
2911 pid = get_dbus_method_sender_pid(reply_handle);
2912 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2913 _E("Failed to process private unmount operation");
2918 if (bdev->on_private_op != REQ_NORMAL) {
2919 _E("Failed to process unmount operation");
2925 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2927 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2931 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2932 ret = add_operation(bdev, BLOCK_LUKS_CLOSE, NULL, NULL);
2934 _E("Failed to add operation (luks_close %s)", bdev->data->devnode);
2940 return make_dbus_reply_message_simple(reply_handle, ret);
2943 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2946 return request_unmount_block(reply_handle, msg, false);
2949 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2952 return request_unmount_block(reply_handle, msg, true);
2955 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2958 struct block_device *bdev;
2959 struct format_data *fdata;
2966 if (!block_control) {
2967 _D("Block module is disabled");
2972 if (!reply_handle || !msg)
2975 ret = dbus_message_get_args(msg, NULL,
2976 DBUS_TYPE_INT32, &id,
2977 DBUS_TYPE_INT32, &option,
2982 bdev = find_block_device_by_id(id);
2984 _E("Failed to find (%d) in the device list", id);
2988 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV ||
2989 !strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2990 _D("Format dbus request for extended internal storage is blocked");
2995 pid = get_dbus_method_sender_pid(reply_handle);
2996 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2997 _E("Failed to format on private state");
3002 fdata = get_format_data(NULL, option);
3004 _E("Failed to get format data");
3008 prev_state = bdev->data->state;
3009 if (prev_state == BLOCK_MOUNT) {
3010 if (bdev->on_private_op == REQ_PRIVATE) {
3011 bdev->on_private_op = REQ_PRIVATE_FORMAT;
3012 _D("Private operation state: %d", bdev->on_private_op);
3014 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3016 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3017 release_format_data(fdata);
3022 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3024 _E("Failed to add operation (format %s)", bdev->data->devnode);
3025 release_format_data(fdata);
3028 /* Maintain previous state of mount/unmount */
3029 if (prev_state == BLOCK_MOUNT) {
3030 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3031 _E("Failed to add operation (mount %s)", bdev->data->devnode);
3039 return make_dbus_reply_message_simple(reply_handle, ret);
3042 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
3045 struct block_device *bdev;
3046 struct format_data *fdata;
3054 if (!block_control) {
3055 _D("Block module is disabled");
3060 if (!reply_handle || !msg)
3063 ret = dbus_message_get_args(msg, NULL,
3064 DBUS_TYPE_INT32, &id,
3065 DBUS_TYPE_INT32, &option,
3066 DBUS_TYPE_STRING, &type,
3071 bdev = find_block_device_by_id(id);
3073 _E("Failed to find (%d) in the device list", id);
3077 /* FormatwithType dbus call is needed when app proceeds extended internal -> portable storage */
3078 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
3079 _D("FormatwithType dbus request for extended internal storage is blocked");
3084 pid = get_dbus_method_sender_pid(reply_handle);
3085 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
3086 _E("Failed to format on private state");
3091 fdata = get_format_data(type, option);
3093 _E("Failed to get format data");
3097 prev_state = bdev->data->state;
3098 if (prev_state == BLOCK_MOUNT) {
3099 if (bdev->on_private_op == REQ_PRIVATE) {
3100 bdev->on_private_op = REQ_PRIVATE_FORMAT;
3101 _D("Private operation state: %d", bdev->on_private_op);
3103 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
3105 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
3106 release_format_data(fdata);
3111 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
3113 _E("Failed to add operation (format %s)", bdev->data->devnode);
3114 release_format_data(fdata);
3117 /* Maintain previous state of mount/unmount */
3118 if (prev_state == BLOCK_MOUNT) {
3119 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
3120 _E("Failed to add operation (mount %s)", bdev->data->devnode);
3128 return make_dbus_reply_message_simple(reply_handle, ret);
3131 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
3133 char *str_null = "";
3135 if (!data || !piter)
3138 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3139 &(data->block_type));
3140 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3141 data->devnode ? &(data->devnode) : &str_null);
3142 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3143 data->syspath ? &(data->syspath) : &str_null);
3144 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3145 data->fs_usage ? &(data->fs_usage) : &str_null);
3146 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3147 data->fs_type ? &(data->fs_type) : &str_null);
3148 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3149 data->fs_version ? &(data->fs_version) : &str_null);
3150 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3151 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3152 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3154 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
3155 data->mount_point ? &(data->mount_point) : &str_null);
3156 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3158 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
3160 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3162 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3169 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3171 DBusMessageIter piter;
3176 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3177 add_device_to_iter(data, &piter);
3178 dbus_message_iter_close_container(iter, &piter);
3183 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3185 DBusMessageIter piter;
3186 char *str_null = "";
3191 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3192 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3193 &(data->block_type));
3194 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3195 data->devnode ? &(data->devnode) : &str_null);
3196 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3197 data->syspath ? &(data->syspath) : &str_null);
3198 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3199 data->fs_usage ? &(data->fs_usage) : &str_null);
3200 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3201 data->fs_type ? &(data->fs_type) : &str_null);
3202 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3203 data->fs_version ? &(data->fs_version) : &str_null);
3204 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3205 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3206 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3208 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3209 data->mount_point ? &(data->mount_point) : &str_null);
3210 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3212 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3214 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3216 dbus_message_iter_close_container(iter, &piter);
3221 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3224 DBusMessageIter iter;
3226 struct block_device *bdev;
3227 struct block_data *data;
3230 if (!reply_handle || !msg)
3233 reply = make_dbus_reply_message(reply_handle);
3237 ret = dbus_message_get_args(msg, NULL,
3238 DBUS_TYPE_INT32, &id,
3243 bdev = find_block_device_by_id(id);
3250 dbus_message_iter_init_append(reply, &iter);
3251 add_device_to_iter(data, &iter);
3257 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3260 show_block_device_list();
3261 return make_dbus_reply_message(reply_handle);
3264 // Called by MainThread
3265 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3268 DBusMessageIter iter;
3269 DBusMessageIter aiter;
3271 struct block_device *bdev;
3272 struct block_data *data;
3279 reply = make_dbus_reply_message(reply_handle);
3281 ret = dbus_message_get_args(msg, NULL,
3282 DBUS_TYPE_STRING, &type,
3285 _E("Failed to get args");
3290 _E("Delivered type is NULL");
3294 _D("Block (%s) device list is requested", type);
3296 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3297 block_type = BLOCK_SCSI_DEV;
3298 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3299 block_type = BLOCK_MMC_DEV;
3300 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3303 _E("Invalid type (%s) is requested", type);
3307 dbus_message_iter_init_append(reply, &iter);
3308 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3310 for (i = 0; i < THREAD_MAX; i++) {
3311 pthread_mutex_lock(&(th_manager[i].mutex));
3312 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3319 switch (block_type) {
3320 case BLOCK_SCSI_DEV:
3322 if (data->block_type != block_type)
3328 add_device_to_struct_iter(data, &aiter);
3330 pthread_mutex_unlock(&(th_manager[i].mutex));
3332 dbus_message_iter_close_container(&iter, &aiter);
3338 // Called by MainThread
3339 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3342 DBusMessageIter iter;
3343 DBusMessageIter aiter;
3345 struct block_device *bdev;
3346 struct block_data *data;
3353 reply = make_dbus_reply_message(reply_handle);
3355 ret = dbus_message_get_args(msg, NULL,
3356 DBUS_TYPE_STRING, &type,
3359 _E("Failed to get args");
3364 _E("Delivered type is NULL");
3368 _D("Block (%s) device list is requested", type);
3370 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3371 block_type = BLOCK_SCSI_DEV;
3372 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3373 block_type = BLOCK_MMC_DEV;
3374 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3377 _E("Invalid type (%s) is requested", type);
3381 dbus_message_iter_init_append(reply, &iter);
3382 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3384 for (i = 0; i < THREAD_MAX; i++) {
3385 pthread_mutex_lock(&(th_manager[i].mutex));
3386 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3393 switch (block_type) {
3394 case BLOCK_SCSI_DEV:
3396 if (data->block_type != block_type)
3403 add_device_to_iter_2(data, &aiter);
3405 pthread_mutex_unlock(&(th_manager[i].mutex));
3407 dbus_message_iter_close_container(&iter, &aiter);
3413 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3416 DBusMessageIter iter;
3418 struct block_device *bdev;
3419 struct block_data *data, nodata = {0,};
3424 if (!reply_handle || !msg)
3427 reply = make_dbus_reply_message(reply_handle);
3432 for (i = 0; i < THREAD_MAX; i++) {
3433 pthread_mutex_lock(&(th_manager[i].mutex));
3434 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3440 if (data->block_type != BLOCK_MMC_DEV &&
3441 data->block_type != BLOCK_EXTENDEDSD_DEV)
3445 // Return mapper node(/dev/mapper/extendedsd) for primary mmc (not /dev/mmcblk1p1(ex))
3446 if (!strncmp(data->fs_type, LUKS_NAME, strlen(LUKS_NAME)))
3451 pthread_mutex_unlock(&(th_manager[i].mutex));
3456 dbus_message_iter_init_append(reply, &iter);
3458 add_device_to_iter(data, &iter);
3460 nodata.id = -ENODEV;
3461 add_device_to_iter(&nodata, &iter);
3468 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3471 struct timespec start_time, end_time;
3472 DBusMessageIter iter;
3474 struct block_device *bdev;
3475 struct block_data *data;
3482 if (!reply_handle || !msg)
3485 ret = dbus_message_get_args(msg, NULL,
3486 DBUS_TYPE_INT32, &id,
3493 bdev = find_block_device_by_id(id);
3504 _D("speed check: %s", data->devnode);
3505 fd = open(data->devnode, O_RDWR | O_SYNC);
3506 buf = calloc(1, SPEEDCHECK << 20);
3508 _E("calloc() failed");
3513 clock_gettime(CLOCK_REALTIME, &start_time);
3514 _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3515 ret = write(fd, buf, SPEEDCHECK << 20);
3516 clock_gettime(CLOCK_REALTIME, &end_time);
3517 _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3521 time_diff = end_time.tv_sec - start_time.tv_sec;
3522 if (time_diff > 0 && (SPEEDCHECK / time_diff < 4)) {
3529 _E("write() failed %d", errno);
3536 reply = dbus_message_new_method_return(msg);
3537 dbus_message_iter_init_append(reply, &iter);
3538 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3543 static DBusMessage *request_control_block(dbus_method_reply_handle_h reply_handle,
3549 DBusMessageIter iter;
3551 ret = dbus_message_get_args(msg, NULL,
3552 DBUS_TYPE_INT32, &enable,
3561 _I("control block Enable");
3563 } else if (enable == 0) {
3564 _I("control block Disable");
3567 _E("control block : Wrong request by client");
3573 reply = dbus_message_new_method_return(msg);
3574 dbus_message_iter_init_append(reply, &iter);
3575 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3580 static DBusMessage *request_getcontrol_block(dbus_method_reply_handle_h reply_handle,
3585 DBusMessageIter iter;
3587 _I("getcontrol block");
3589 is_enabled = block_control;
3591 reply = dbus_message_new_method_return(msg);
3592 dbus_message_iter_init_append(reply, &iter);
3593 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &is_enabled);
3599 Method name Method call format string Reply format string
3600 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3601 { "GetDeviceList", "s", "a(issssssisibii)", request_get_device_list },
3602 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3603 { "Mount", "is", "i", request_public_mount_block },
3604 { "Unmoun, "ii", "i", request_public_unmount_block },
3605 { "Format", "ii", "i", request_format_block },
3606 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3607 { "GetMmcPrimary", NULL, "(issssssisibii)" , request_get_mmc_primary },
3608 { "PrivateMount", "is", "i", request_private_mount_block },
3609 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3612 static const dbus_method_s manager_methods[] = {
3613 { "ShowDeviceList", NULL, request_show_device_list },
3614 { "GetDeviceList" , "s", request_get_device_list },
3615 { "GetDeviceList2", "s", request_get_device_list_2 },
3616 { "Mount", "is", request_public_mount_block },
3617 { "Unmount", "ii", request_public_unmount_block },
3618 { "Format", "ii", request_format_block },
3619 { "FormatwithType", "iis", request_format_block_type },
3620 { "GetDeviceInfo", "i", request_get_device_info },
3621 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3622 { "PrivateMount", "is", request_private_mount_block },
3623 { "PrivateUnmount", "ii", request_private_unmount_block },
3624 { "CheckSpeed", "i", request_check_speed },
3625 { "Control", "i", request_control_block },
3626 { "GetControl", "i", request_getcontrol_block },
3629 static dbus_interface_s block_interface = {
3630 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3631 .methods = manager_methods,
3632 .nr_methods = ARRAY_SIZE(manager_methods),
3635 static int load_config(struct parse_result *result, void *user_data)
3639 if (MATCH(result->section, "Block"))
3642 if (MATCH(result->section, "SCSI"))
3643 index = BLOCK_SCSI_DEV;
3644 else if (MATCH(result->section, "MMC"))
3645 index = BLOCK_MMC_DEV;
3646 else if (MATCH(result->section, "Mapper"))
3647 index = BLOCK_EXTENDEDSD_DEV;
3651 if (MATCH(result->name, "Multimount"))
3652 block_conf[index].multimount =
3653 (MATCH(result->value, "yes") ? true : false);
3654 if (MATCH(result->name, "ExtendedInternalStorage"))
3655 block_conf[index].extendedinternal =
3656 (MATCH(result->value, "yes") ? true : false);
3662 static int mount_root_path_tmpfs(void)
3667 root = tzplatform_getenv(TZ_SYS_MEDIA);
3671 if (access(root, F_OK) != 0)
3674 if (mount_check(root))
3677 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3680 _E("tmpfs mount failed (%d)", ret);
3687 #define mount_root_path_tmpfs() 0
3690 static void block_init(void *data)
3695 dbus_handle_h handle;
3700 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3702 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3704 ret = mount_root_path_tmpfs();
3706 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3708 ret = dbus_get_connection(&handle);
3710 _E("Failed to get dbus connection(%d)", ret);
3712 /* register block manager object and interface */
3713 ret = register_dbus_methods(handle,
3714 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3717 _E("Failed to register block interface and methods (%d)", ret);
3722 _E("fail to init pipe");
3724 /* System Session is loaded completely */
3725 register_dbus_signal(SYSTEMD_DBUS_PATH,
3726 SYSTEMD_DBUS_IFACE_MANAGER,
3727 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3728 booting_done, NULL, NULL);
3730 register_dbus_signal(DEVICED_PATH_POWEROFF,
3731 DEVICED_INTERFACE_POWEROFF,
3732 SIGNAL_POWEROFF_STATE,
3733 block_poweroff, NULL, NULL);
3735 for (i = 0; i < THREAD_MAX; i++) {
3736 th_manager[i].num_dev = 0;
3737 th_manager[i].op_len = 0;
3738 th_manager[i].start_th = true;
3739 th_manager[i].thread_id = i;
3740 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3741 pthread_cond_init(&(th_manager[i].cond), NULL);
3744 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3746 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3748 _E("Failed to make directory: %d", errno);
3749 } else if (!S_ISDIR(buf.st_mode)) {
3750 ret = remove(EXTERNAL_STORAGE_PATH);
3752 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3753 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3755 _E("Failed to make directory: %d", errno);
3757 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3759 _E("Fail to change permissions of a file");
3762 ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3764 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3766 _E("Failed to make directory: %d", errno);
3767 } else if (!S_ISDIR(buf.st_mode)) {
3768 ret = remove(EXTENDED_INTERNAL_PATH);
3770 _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3771 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3773 _E("Failed to make directory: %d", errno);
3775 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3777 _E("Fail to change permissions of a file");
3780 ret = get_internal_storage_number();
3782 _E("Failed to get internal storage number");
3785 static void block_exit(void *data)
3787 dd_list *elem, *elem_next;
3793 /* unregister notifier for below each event */
3794 unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3795 SYSTEMD_DBUS_IFACE_MANAGER,
3796 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3799 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3800 DEVICED_INTERFACE_POWEROFF,
3801 SIGNAL_POWEROFF_STATE, block_poweroff);
3803 /* unregister mmc uevent control routine */
3804 ret = unregister_udev_uevent_control(&uh);
3806 _E("fail to unregister block uevent : %d", ret);
3808 /* remove remaining blocks */
3809 remove_whole_block_device();
3811 for (i = 0; i < THREAD_MAX; i++) {
3812 if (!th_manager[i].start_th)
3813 pthread_cancel(th_manager[i].th);
3814 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3815 DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3823 block_control = false;
3826 static int block_start(void *data)
3829 _E("Cannot be started. Booting is not ready");
3833 if (block_control) {
3834 _I("Already started");
3838 block_control = true;
3840 block_init_from_udev_enumerate();
3846 static int block_stop(void *data)
3849 _E("Cannot be stopped. Booting is not ready");
3853 if (!block_control) {
3854 _I("Already stopped");
3858 /* remove the existing blocks */
3859 remove_whole_block_device();
3861 block_control = false;
3867 static storaged_module_interface block_module = {
3871 .start = block_start,
3875 __attribute__ ((visibility("default")))storaged_module_interface *
3876 storaged_get_module_interface(void)
3878 return &block_module;