4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include <sys/mount.h>
28 #include <sys/statvfs.h>
32 #include <sys/statfs.h>
39 #include <tzplatform_config.h>
40 #include <app2ext_interface.h>
42 #include <blkid/blkid.h>
45 #include "config-parser.h"
46 #include "module-intf.h"
51 #include "fd_handler.h"
56 * TODO Assume root device is always mmcblk0*.
58 #define MMC_PATH "*/mmcblk[0-9]*"
59 #define MMC_PARTITION_PATH "mmcblk[0-9]p[0-9]"
60 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
61 #define MMC_LINK_PATH "*/sdcard/*"
62 #define SCSI_PATH "*/sd[a-z]*"
63 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
64 #define SCSI_PARTITION_LENGTH 9
65 #define EXTENDEDSD_PATH "/dev/mapper/extendedsd*"
67 #define FILESYSTEM "filesystem"
69 #define DEV_PREFIX "/dev/"
72 #define UNMOUNT_RETRY 5
73 #define TIMEOUT_MAKE_OBJECT 500 /* milliseconds */
75 #define SIGNAL_POWEROFF_STATE "ChangeState"
77 #define BLOCK_DEVICE_ADDED "DeviceAdded"
78 #define BLOCK_DEVICE_REMOVED "DeviceRemoved"
79 #define BLOCK_DEVICE_BLOCKED "DeviceBlocked"
80 #define BLOCK_DEVICE_CHANGED "DeviceChanged"
81 #define BLOCK_DEVICE_CHANGED_2 "DeviceChanged2"
83 #define BLOCK_TYPE_MMC "mmc"
84 #define BLOCK_TYPE_SCSI "scsi"
85 #define BLOCK_TYPE_ALL "all"
87 #define BLOCK_MMC_NODE_PREFIX "SDCard"
88 #define BLOCK_SCSI_NODE_PREFIX "USBDrive"
90 #define BLOCK_CONF_FILE "/etc/storaged/block.conf"
92 #define EXTERNAL_STORAGE_PATH "/run/external-storage"
93 #define EXTENDED_INTERNAL_PATH "/run/extended-internal-sd"
96 #define EXTENDED_SD_PATH "/opt/extendedsd"
97 #define EXTENDED_SD_STRING "ExtendedInternalSD"
99 #define EXT4_NAME "ext4"
100 #define LUKS_NAME "crypto_LUKS"
102 /* Minimum value of block id */
103 #define BLOCK_ID_MIN 10
104 /* For 2.4 Backward Compatibility */
105 #define EXT_PRIMARY_SD_FIXID 1
107 /* Maximum number of thread */
110 #define SPEEDCHECK 16
112 #define PKGDIR_BUS_NAME "org.tizen.pkgdir_tool"
113 #define PKGDIR_PATH "/org/tizen/pkgdir_tool"
114 #define PKGDIR_INTERFACE "org.tizen.pkgdir_tool"
116 #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
118 enum block_dev_operation {
126 enum private_operation_state {
132 struct operation_queue {
133 enum block_dev_operation op;
134 dbus_method_reply_handle_h reply_handle;
139 struct block_device {
140 struct block_data *data;
142 int thread_id; /* Current thread ID */
143 bool removed; /* True when device is physically removed but operation is not precessed yet */
144 enum private_operation_state on_private_op;
145 bool mount_point_updated;
150 struct block_device *bdev;
152 enum unmount_operation option;
157 enum block_dev_operation op;
158 struct block_device *bdev;
162 static struct block_conf {
164 bool extendedinternal;
165 } block_conf[BLOCK_EXTENDEDSD_DEV + 1];
167 static struct manage_thread {
168 dd_list *th_node_list; /* List of devnode which thread dealt with. Only main thread access */
169 dd_list *block_dev_list; /* Use thread mutex */
171 pthread_mutex_t mutex;
173 int num_dev; /* Number of devices which thread holds. Only main thread access */
174 int op_len; /* Number of operation of thread. Use thread mutex */
175 int thread_id; /* Never changed */
177 } th_manager[THREAD_MAX];
179 static dd_list *fs_head;
180 static dd_list *block_ops_list;
183 static fd_handler_h phandler;
184 static bool block_control = false;
185 static bool block_boot = false;
186 static pthread_mutex_t pipe_mutex = PTHREAD_MUTEX_INITIALIZER;
188 /* Assume there is only one physical internal storage */
189 static int dev_internal = -1;
190 static char dev_internal_scsi = '\0';
191 static char dev_internal_emul = '\0';
193 static int add_operation(struct block_device *bdev,
194 enum block_dev_operation operation,
195 dbus_method_reply_handle_h reply_handle, void *data);
196 static void remove_operation(struct block_device *bdev);
197 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
198 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op);
199 static int change_mount_point(struct block_device *bdev, const char *mount_point);
201 static void uevent_block_handler(struct udev_device *dev);
202 static struct uevent_handler uh = {
203 .subsystem = BLOCK_SUBSYSTEM,
204 .uevent_func = uevent_block_handler,
207 static void __CONSTRUCTOR__ smack_check(void)
212 fp = fopen("/proc/filesystems", "r");
216 while (fgets(buf, sizeof(buf), fp) != NULL) {
217 if (strstr(buf, "smackfs")) {
226 void add_fs(const struct block_fs_ops *fs)
228 DD_LIST_APPEND(fs_head, (void *)fs);
231 void remove_fs(const struct block_fs_ops *fs)
233 DD_LIST_REMOVE(fs_head, (void *)fs);
236 const struct block_fs_ops *find_fs(enum block_fs_type type)
238 struct block_fs_ops *fs;
241 DD_LIST_FOREACH(fs_head, elem, fs) {
242 if (fs->type == type)
248 void add_block_dev(const struct block_dev_ops *ops)
250 DD_LIST_APPEND(block_ops_list, (void *)ops);
253 void remove_block_dev(const struct block_dev_ops *ops)
255 DD_LIST_REMOVE(block_ops_list, (void *)ops);
258 static void broadcast_block_info(enum block_dev_operation op,
259 struct block_data *data, int result)
261 struct block_dev_ops *ops;
264 if (data->primary != true)
267 DD_LIST_FOREACH(block_ops_list, elem, ops) {
268 if (ops->block_type != data->block_type)
270 // TODO What happend on extended internal storage case?
271 if (op == BLOCK_DEV_MOUNT) {
272 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
273 ops->mounted(data, result, true);
275 ops->mounted(data, result, false);
276 } else if (op == BLOCK_DEV_UNMOUNT) {
277 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
278 ops->unmounted(data, result, true);
280 ops->unmounted(data, result, false);
281 } else if (op == BLOCK_DEV_FORMAT) {
282 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
283 ops->formatted(data, result, true);
285 ops->formatted(data, result, false);
286 } else if (op == BLOCK_DEV_INSERT)
288 else if (op == BLOCK_DEV_REMOVE)
293 // Called by MainThread - Insert
294 static int block_get_new_id(void)
296 static int id = BLOCK_ID_MIN;
297 struct block_device *bdev;
302 for (i = 0 ; i < INT_MAX ; i++) {
304 for (j = 0; j < THREAD_MAX; j++) {
305 pthread_mutex_lock(&(th_manager[j].mutex));
306 DD_LIST_FOREACH(th_manager[j].block_dev_list, elem, bdev) {
307 if (bdev->data->id == id) {
312 pthread_mutex_unlock(&(th_manager[j].mutex));
327 static void remove_file(int id, bool extendedsd)
329 char file_name[PATH_LEN];
336 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
338 snprintf(file_name, sizeof(file_name), EXTERNAL_STORAGE_PATH"/%d", id);
340 ret = remove(file_name);
342 _E("Fail to remove %s. errno: %d", file_name, errno);
345 static void create_file(int id, char *mount_point, bool extendedsd)
348 char file_name[PATH_LEN];
354 snprintf(file_name, PATH_LEN, EXTENDED_INTERNAL_PATH"/%d", id);
356 snprintf(file_name, PATH_LEN, EXTERNAL_STORAGE_PATH"/%d", id);
358 fp = fopen(file_name, "w+");
360 fprintf(fp, "%s", mount_point);
363 _E("Fail to open %s", file_name);
366 static void signal_device_blocked(struct block_device *bdev)
368 struct block_data *data;
370 char str_block_type[32];
371 char str_readonly[32];
373 char str_primary[32];
379 if (!bdev || !bdev->data)
385 /* Broadcast outside with BlockManager iface */
386 snprintf(str_block_type, sizeof(str_block_type),
387 "%d", data->block_type);
388 arr[0] = str_block_type;
389 arr[1] = (data->devnode ? data->devnode : str_null);
390 arr[2] = (data->syspath ? data->syspath : str_null);
391 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
392 arr[4] = (data->fs_type ? data->fs_type : str_null);
393 arr[5] = (data->fs_version ? data->fs_version : str_null);
394 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
395 snprintf(str_readonly, sizeof(str_readonly),
396 "%d", data->readonly);
397 arr[7] = str_readonly;
398 arr[8] = (data->mount_point ? data->mount_point : str_null);
399 snprintf(str_state, sizeof(str_state),
402 snprintf(str_primary, sizeof(str_primary),
403 "%d", data->primary);
404 arr[10] = str_primary;
405 snprintf(str_flags, sizeof(str_flags), "%d", flags);
407 snprintf(str_id, sizeof(str_id), "%d", data->id);
410 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
411 STORAGED_INTERFACE_BLOCK_MANAGER,
412 BLOCK_DEVICE_BLOCKED,
413 "issssssisibii", arr);
416 static void signal_device_changed(struct block_device *bdev,
417 enum block_dev_operation op)
419 struct block_data *data;
421 char str_block_type[32];
422 char str_readonly[32];
424 char str_primary[32];
430 if (!bdev || !bdev->data)
436 case BLOCK_DEV_MOUNT:
437 BLOCK_GET_MOUNT_FLAGS(data, flags);
439 case BLOCK_DEV_UNMOUNT:
440 BLOCK_GET_UNMOUNT_FLAGS(data, flags);
442 case BLOCK_DEV_FORMAT:
443 BLOCK_GET_FORMAT_FLAGS(data, flags);
450 /* Broadcast outside with BlockManager iface */
451 snprintf(str_block_type, sizeof(str_block_type),
452 "%d", data->block_type);
453 arr[0] = str_block_type;
454 arr[1] = (data->devnode ? data->devnode : str_null);
455 arr[2] = (data->syspath ? data->syspath : str_null);
456 arr[3] = (data->fs_usage ? data->fs_usage : str_null);
457 arr[4] = (data->fs_type ? data->fs_type : str_null);
458 arr[5] = (data->fs_version ? data->fs_version : str_null);
459 arr[6] = (data->fs_uuid_enc ? data->fs_uuid_enc : str_null);
460 snprintf(str_readonly, sizeof(str_readonly),
461 "%d", data->readonly);
462 arr[7] = str_readonly;
463 arr[8] = (data->mount_point ? data->mount_point : str_null);
464 snprintf(str_state, sizeof(str_state),
467 snprintf(str_primary, sizeof(str_primary),
468 "%d", data->primary);
469 arr[10] = str_primary;
470 snprintf(str_flags, sizeof(str_flags), "%d", flags);
472 snprintf(str_id, sizeof(str_id), "%d", data->id);
475 if (op == BLOCK_DEV_INSERT)
476 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
477 STORAGED_INTERFACE_BLOCK_MANAGER,
479 "issssssisibii", arr);
480 else if (op == BLOCK_DEV_REMOVE)
481 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
482 STORAGED_INTERFACE_BLOCK_MANAGER,
483 BLOCK_DEVICE_REMOVED,
484 "issssssisibii", arr);
486 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
487 STORAGED_INTERFACE_BLOCK_MANAGER,
488 BLOCK_DEVICE_CHANGED,
489 "issssssisibii", arr);
490 broadcast_dbus_signal(STORAGED_PATH_BLOCK_MANAGER,
491 STORAGED_INTERFACE_BLOCK_MANAGER,
492 BLOCK_DEVICE_CHANGED_2,
493 "issssssisibi", arr);
497 static int get_mmc_mount_node(char *devnode, char *node, size_t len)
499 char *name = devnode;
500 int dev = -1, part = -1;
501 char emul[32] = { 0, };
508 sscanf(name, "mmcblk%dp%d", &dev, &part);
511 snprintf(node, len, "%s%c", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1);
513 snprintf(node, len, "%s%c%d", BLOCK_MMC_NODE_PREFIX, dev + 'A' - 1, part);
518 sscanf(name, "vd%31s", emul);
521 for (i = 0 ; i < strlen(emul) ; i++)
522 emul[i] = toupper(emul[i]);
523 snprintf(node, len, "%s%s", BLOCK_MMC_NODE_PREFIX, emul);
527 static int get_scsi_mount_node(char *devnode, char *node, size_t len)
535 snprintf(dev, sizeof(dev), "%s", devnode);
537 if (!strstr(dev, "sd"))
541 name += strlen("sd");
543 for (i = 0 ; i < strlen(name) ; i++)
544 name[i] = toupper(name[i]);
545 snprintf(node, len, "%s%s", BLOCK_SCSI_NODE_PREFIX, name);
550 static char *generate_mount_path(struct block_data *data)
553 char *name, node[64];
556 if (!data || !data->devnode || !data->fs_usage || strcmp(data->fs_usage, FILESYSTEM))
559 name = strrchr(data->devnode, '/');
564 switch (data->block_type) {
566 ret = get_mmc_mount_node(name, node, sizeof(node));
569 ret = get_scsi_mount_node(name, node, sizeof(node));
571 case BLOCK_EXTENDEDSD_DEV:
572 return strdup(EXTENDED_SD_PATH);
574 _E("Invalid block type (%d)", data->block_type);
580 str = tzplatform_mkpath(TZ_SYS_MEDIA, node);
586 _E("Invalid devnode (%s)", data->devnode ? data->devnode : "NULL");
590 static bool check_primary_partition(const char *devnode)
592 struct block_fs_ops *fs;
595 const char *filesystem = NULL;
605 if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
606 fnmatch(MMC_PATH, devnode, 0) &&
607 fnmatch(SCSI_PATH, devnode, 0) &&
608 fnmatch(EXTENDEDSD_PATH, devnode, 0))
611 temp = strrchr(devnode, '/');
614 if (fnmatch("/"SCSI_PARTITION_PATH, temp, 0) &&
615 fnmatch("/"MMC_PARTITION_PATH, temp, 0))
618 /* Emulator support only one partition */
622 snprintf(str, sizeof(str), "%s", devnode);
627 for (i = 1; i <= 9; ++i) {
628 snprintf(str2, sizeof(str2), "%s%d", str, i);
629 if (access(str2, R_OK) != 0)
632 probe = blkid_new_probe_from_filename(str2);
635 if (blkid_do_probe(probe) != 0)
638 ret = blkid_probe_lookup_value(probe, "TYPE", &filesystem, &fs_len);
640 blkid_free_probe(probe);
643 DD_LIST_FOREACH(fs_head, elem, fs) {
644 if (!strncmp(fs->name, filesystem, fs_len)) {
649 blkid_free_probe(probe);
655 if (found && !strncmp(devnode, str2, strlen(str2) + 1))
661 /* Whole data in struct block_data should be freed. */
662 static struct block_data *make_block_data(const char *devnode,
664 const char *fs_usage,
666 const char *fs_version,
667 const char *fs_uuid_enc,
668 const char *readonly)
670 struct block_data *data;
672 /* devnode is unique value so it should exist. */
677 _I("Unknown fs type");
679 data = calloc(1, sizeof(struct block_data));
681 _E("calloc() failed");
685 data->devnode = strdup(devnode);
687 data->syspath = strdup(syspath);
689 data->fs_usage = strdup(fs_usage);
691 data->fs_type = strdup(fs_type);
693 data->fs_version = strdup(fs_version);
695 data->fs_uuid_enc = strdup(fs_uuid_enc);
697 data->readonly = atoi(readonly);
698 data->primary = check_primary_partition(devnode);
700 /* TODO should we know block dev type? */
701 if (!fnmatch(MMC_LINK_PATH, devnode, 0))
702 data->block_type = BLOCK_MMC_DEV;
703 else if (!fnmatch(MMC_PATH, devnode, 0))
704 data->block_type = BLOCK_MMC_DEV;
705 else if (!fnmatch(SCSI_PATH, devnode, 0))
706 data->block_type = BLOCK_SCSI_DEV;
707 else if (!fnmatch(EXTENDEDSD_PATH, devnode, 0))
708 data->block_type = BLOCK_EXTENDEDSD_DEV;
710 data->block_type = -1;
712 data->mount_point = generate_mount_path(data);
713 BLOCK_FLAG_CLEAR_ALL(data);
715 /* for 2.4 backward compatibility */
716 // What if storage id 1 is existed? (multi sdcard case)
717 if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
718 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM))
719 data->id = EXT_PRIMARY_SD_FIXID;
721 data->id = block_get_new_id();
726 static void free_block_data(struct block_data *data)
732 free(data->fs_usage);
734 free(data->fs_version);
735 free(data->fs_uuid_enc);
736 free(data->mount_point);
740 static int update_block_data(struct block_data *data,
741 const char *fs_usage,
743 const char *fs_version,
744 const char *fs_uuid_enc,
745 const char *readonly,
746 bool mount_point_updated)
751 free(data->fs_usage);
752 data->fs_usage = NULL;
754 data->fs_usage = strdup(fs_usage);
757 data->fs_type = NULL;
759 data->fs_type = strdup(fs_type);
761 free(data->fs_version);
762 data->fs_version = NULL;
764 data->fs_version = strdup(fs_version);
766 free(data->fs_uuid_enc);
767 data->fs_uuid_enc = NULL;
769 data->fs_uuid_enc = strdup(fs_uuid_enc);
771 /* generate_mount_path function should be invoked
772 * after fs_uuid_enc is updated */
773 if (!mount_point_updated) {
774 free(data->mount_point);
775 data->mount_point = generate_mount_path(data);
778 data->readonly = false;
780 data->readonly = atoi(readonly);
782 BLOCK_FLAG_MOUNT_CLEAR(data);
787 static struct block_device *make_block_device(struct block_data *data)
789 struct block_device *bdev;
794 bdev = calloc(1, sizeof(struct block_device));
799 bdev->thread_id = -1;
800 bdev->removed = false;
801 bdev->on_private_op = REQ_NORMAL;
802 bdev->private_pid = 0;
803 bdev->mount_point_updated = false;
808 // Called by MainThread - Remove DevNode
809 static void free_block_device(struct block_device *bdev)
812 struct operation_queue *op;
818 thread_id = bdev->thread_id;
819 if (thread_id < 0 || thread_id >= THREAD_MAX)
822 pthread_mutex_lock(&(th_manager[thread_id].mutex));
824 th_manager[thread_id].num_dev--;
825 DD_LIST_REMOVE(th_manager[thread_id].block_dev_list, bdev);
826 free_block_data(bdev->data);
828 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
830 th_manager[thread_id].op_len--;
831 DD_LIST_REMOVE(bdev->op_queue, op);
834 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
839 // Called By MainThread - Remove Device
840 static struct block_device *find_block_device(const char *devnode)
842 struct block_device *bdev;
847 len = strlen(devnode) + 1;
848 for (i = 0; i < THREAD_MAX; i++) {
849 pthread_mutex_lock(&(th_manager[i].mutex));
850 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
851 if (bdev->data && !bdev->removed &&
852 !strncmp(bdev->data->devnode, devnode, len)) {
853 pthread_mutex_unlock(&(th_manager[i].mutex));
857 pthread_mutex_unlock(&(th_manager[i].mutex));
863 // Called By MainThread - Mount,Unmount,Format,GetInfo
864 static struct block_device *find_block_device_by_id(int id)
866 struct block_device *bdev;
870 for (i = 0; i < THREAD_MAX; i++) {
871 pthread_mutex_lock(&(th_manager[i].mutex));
872 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
877 if (bdev->data->id == id) {
878 pthread_mutex_unlock(&(th_manager[i].mutex));
882 pthread_mutex_unlock(&(th_manager[i].mutex));
888 static char *get_operation_char(enum block_dev_operation op,
889 char *name, unsigned int len)
891 char *str = "unknown";
897 case BLOCK_DEV_MOUNT:
900 case BLOCK_DEV_UNMOUNT:
903 case BLOCK_DEV_FORMAT:
906 case BLOCK_DEV_INSERT:
909 case BLOCK_DEV_REMOVE:
913 _E("invalid operation (%d)", op);
917 snprintf(name, len, "%s", str);
921 static void create_external_apps_directory(void)
925 ret = call_dbus_method_async(PKGDIR_BUS_NAME, PKGDIR_PATH,
926 PKGDIR_INTERFACE, "CreateExternalDirsForAllPkgs",
927 NULL, NULL, NULL, DBUS_TIMEOUT_USE_DEFAULT, NULL);
929 _E("Fail to create external directory");
932 static int pipe_trigger(enum block_dev_operation op,
933 struct block_device *bdev, int result)
935 struct pipe_data pdata = { op, bdev, result };
939 _D("op : %s, bdev : %p, result : %d",
940 get_operation_char(pdata.op, name, sizeof(name)),
941 pdata.bdev, pdata.result);
943 // Multi thread should not write at the same time
944 pthread_mutex_lock(&pipe_mutex);
945 n = write(pfds[1], &pdata, sizeof(struct pipe_data));
946 pthread_mutex_unlock(&pipe_mutex);
948 return (n != sizeof(struct pipe_data)) ? -EPERM : 0;
951 static bool pipe_cb(int fd, void *data)
953 struct pipe_data pdata = {0,};
959 n = read(fd, &pdata, sizeof(pdata));
960 if (n != sizeof(pdata) || !pdata.bdev) {
961 _E("fail to read struct pipe data");
965 _I("op : %s, bdev : %p, result : %d",
966 get_operation_char(pdata.op, name, sizeof(name)),
967 pdata.bdev, pdata.result);
969 if (pdata.op == BLOCK_DEV_MOUNT && pdata.result < 0) {
970 if (pdata.bdev->data->state == BLOCK_UNMOUNT) {
971 ret = change_mount_point(pdata.bdev, "");
972 /* Modify /run/external-storage/id file */
974 if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
975 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
977 create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
982 if (pdata.op == BLOCK_DEV_MOUNT &&
983 pdata.bdev->data->state == BLOCK_MOUNT &&
984 pdata.bdev->data->block_type == BLOCK_MMC_DEV &&
985 pdata.bdev->data->primary)
986 create_external_apps_directory();
987 if (pdata.op == BLOCK_DEV_UNMOUNT) {
988 /* Remove file for block device /run/xxxxxx/id */
989 remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
992 /* Broadcast to mmc and usb storage module */
993 broadcast_block_info(pdata.op, pdata.bdev->data, pdata.result);
995 /* Broadcast outside with Block iface */
996 if (pdata.bdev->on_private_op == REQ_NORMAL)
997 signal_device_changed(pdata.bdev, pdata.op);
998 else if (pdata.bdev->on_private_op == REQ_PRIVATE) {
999 if (pdata.op == BLOCK_DEV_UNMOUNT) {
1000 pdata.bdev->on_private_op = REQ_NORMAL;
1001 _D("Private operation state: %d", pdata.bdev->on_private_op);
1004 if (pdata.op == BLOCK_DEV_MOUNT) {
1005 pdata.bdev->on_private_op = REQ_PRIVATE;
1006 _D("Private operation state: %d", pdata.bdev->on_private_op);
1010 if (pdata.op == BLOCK_DEV_REMOVE) {
1011 thread_id = pdata.bdev->thread_id;
1012 if (thread_id < 0 || thread_id >= THREAD_MAX)
1014 free_block_device(pdata.bdev);
1021 static int pipe_init(void)
1025 ret = pipe2(pfds, O_CLOEXEC);
1029 ret = add_fd_read_handler(pfds[0], pipe_cb,
1030 NULL, NULL, &phandler);
1032 _E("Failed to add pipe handler (%d)", ret);
1039 static void pipe_exit(void)
1042 remove_fd_read_handler(&phandler);
1052 static int mmc_check_and_unmount(const char *path)
1060 while (mount_check(path)) {
1064 if (retry > UNMOUNT_RETRY)
1071 static bool check_rw_mount(const char *szPath)
1073 struct statvfs mount_stat;
1075 if (!statvfs(szPath, &mount_stat)) {
1076 if ((mount_stat.f_flag & ST_RDONLY) == ST_RDONLY)
1082 static int retrieve_udev_device(struct block_data *data, bool mount_point_updated)
1085 struct udev_device *dev;
1094 _E("fail to create udev library context");
1098 dev = udev_device_new_from_syspath(udev, data->syspath);
1100 _E("fail to create new udev device");
1105 for (wait = 0; wait < 3; wait++) {
1106 if (!udev_device_get_property_value(dev, "ID_FS_TYPE"))
1112 r = update_block_data(data,
1113 udev_device_get_property_value(dev, "ID_FS_USAGE"),
1114 udev_device_get_property_value(dev, "ID_FS_TYPE"),
1115 udev_device_get_property_value(dev, "ID_FS_VERSION"),
1116 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
1117 udev_device_get_sysattr_value(dev, "ro"),
1118 mount_point_updated);
1120 _E("fail to update block data for %s", data->devnode);
1122 udev_device_unref(dev);
1127 static int block_mount(struct block_data *data)
1129 struct block_fs_ops *fs;
1134 if (!data || !data->devnode || !data->mount_point)
1137 /* check existing mounted */
1138 if (mount_check(data->mount_point))
1141 /* create mount point */
1142 if (access(data->mount_point, R_OK) != 0) {
1143 if (mkdir(data->mount_point, 0755) < 0)
1147 /* check matched file system */
1148 if (!data->fs_usage ||
1149 strncmp(data->fs_usage, FILESYSTEM,
1150 sizeof(FILESYSTEM)) != 0) {
1155 if (!data->fs_type) {
1156 _E("There is no file system");
1157 BLOCK_FLAG_SET(data, FS_EMPTY);
1163 len = strlen(data->fs_type) + 1;
1164 DD_LIST_FOREACH(fs_head, elem, fs) {
1165 if (!strncmp(fs->name, data->fs_type, len))
1170 _E("Not supported file system (%s)", data->fs_type);
1171 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1176 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1177 r = fs->mount(false, data->devnode, data->mount_point);
1179 r = fs->mount(smack, data->devnode, data->mount_point);
1182 BLOCK_FLAG_SET(data, FS_BROKEN);
1187 r = check_rw_mount(data->mount_point);
1194 rmdir(data->mount_point);
1198 static int mount_start(struct block_device *bdev)
1200 struct block_data *data;
1208 _I("Mount Start : (%s -> %s)",
1209 data->devnode, data->mount_point);
1211 /* mount operation */
1212 r = block_mount(data);
1213 if (r != -EROFS && r < 0) {
1214 _E("fail to mount %s device : %d", data->devnode, r);
1219 data->readonly = true;
1220 BLOCK_FLAG_SET(data, MOUNT_READONLY);
1223 data->state = BLOCK_MOUNT;
1225 if (data->block_type == BLOCK_MMC_DEV) {
1226 /* app2ext_migrate_legacy_all has dbus method call to deviced */
1227 ret = app2ext_migrate_legacy_all();
1229 _E("app2ext failed");
1233 if (r < 0 && r != -EROFS)
1234 data->state = BLOCK_UNMOUNT;
1236 _I("%s result : %s, %d", __func__, data->devnode, r);
1238 if (pipe_trigger(BLOCK_DEV_MOUNT, bdev, r) < 0)
1239 _E("fail to trigger pipe");
1244 static int change_mount_point(struct block_device *bdev,
1245 const char *mount_point)
1247 struct block_data *data;
1253 free(data->mount_point);
1255 /* If the mount path already exists, the path cannot be used */
1257 access(mount_point, F_OK) != 0) {
1258 data->mount_point = strdup(mount_point);
1259 bdev->mount_point_updated = true;
1261 data->mount_point = generate_mount_path(data);
1262 bdev->mount_point_updated = false;
1268 static int mount_block_device(struct block_device *bdev)
1270 struct block_data *data;
1273 if (!bdev || !bdev->data)
1277 if (data->state == BLOCK_MOUNT) {
1278 _I("%s is already mounted", data->devnode);
1282 if (!block_conf[data->block_type].multimount &&
1284 _I("Not support multi mount by config info");
1288 r = mount_start(bdev);
1290 _E("Failed to mount (%s)", data->devnode);
1297 static int block_unmount(struct block_device *bdev,
1298 enum unmount_operation option)
1300 struct block_data *data;
1302 struct timespec time = {0,};
1304 if (!bdev || !bdev->data || !bdev->data->mount_point)
1309 if (bdev->on_private_op == REQ_NORMAL)
1310 signal_device_blocked(bdev);
1312 /* it must called before unmounting mmc */
1313 r = mmc_check_and_unmount(data->mount_point);
1316 if (option == UNMOUNT_NORMAL) {
1317 _I("Failed to unmount with normal option : %d", r);
1321 _I("Execute force unmount!");
1322 /* Force Unmount Scenario */
1327 * should unmount the below vconf key. */
1328 if ((data->block_type == BLOCK_MMC_DEV ||
1329 data->block_type == BLOCK_EXTENDEDSD_DEV) &&
1331 /* At first, notify to other app
1332 * who already access sdcard */
1333 _I("Notify to other app who already access sdcard");
1334 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
1335 VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
1339 /* Second, kill app with SIGTERM */
1340 _I("Kill app with SIGTERM");
1341 terminate_process(data->mount_point, false);
1344 /* Last time, kill app with SIGKILL */
1345 _I("Kill app with SIGKILL");
1346 terminate_process(data->mount_point, true);
1349 if (umount2(data->mount_point, MNT_DETACH) != 0) {
1350 _I("Failed to unmount with lazy option : %d",
1357 /* it takes some seconds til other app completely clean up */
1358 time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
1359 nanosleep(&time, NULL);
1361 print_open_files(data->mount_point);
1363 r = mmc_check_and_unmount(data->mount_point);
1365 _D("Success to unmount (%s)", data->mount_point);
1371 data->state = BLOCK_UNMOUNT;
1373 if (rmdir(data->mount_point) < 0)
1374 _E("fail to remove %s directory", data->mount_point);
1379 static int unmount_block_device(struct block_device *bdev,
1380 enum unmount_operation option)
1382 struct block_data *data;
1385 if (!bdev || !bdev->data)
1389 if (data->state == BLOCK_UNMOUNT) {
1390 _I("%s is already unmounted", data->devnode);
1391 r = mmc_check_and_unmount(data->mount_point);
1393 _E("The path was existed, but could not delete it(%s)",
1398 _I("Unmount Start : (%s -> %s)",
1399 data->devnode, data->mount_point);
1401 r = block_unmount(bdev, option);
1403 _E("fail to unmount %s device : %d", data->devnode, r);
1407 BLOCK_FLAG_MOUNT_CLEAR(data);
1410 _I("%s result : %s, %d", __func__, data->devnode, r);
1412 if (pipe_trigger(BLOCK_DEV_UNMOUNT, bdev, r) < 0)
1413 _E("fail to trigger pipe");
1418 static int block_format(struct block_data *data,
1419 const char *fs_type, bool mount_point_updated, bool udev_update)
1421 const struct block_fs_ops *fs;
1427 if (!data || !data->devnode || !data->mount_point)
1430 if (data->block_type == BLOCK_EXTENDEDSD_DEV)
1436 fstype = data->fs_type;
1442 len = strlen(fstype);
1443 DD_LIST_FOREACH(fs_head, elem, fs) {
1444 if (!strncmp(fs->name, fstype, len))
1449 BLOCK_FLAG_SET(data, FS_NOT_SUPPORTED);
1450 _E("not supported file system(%s)", fstype);
1454 _I("format path : %s", data->devnode);
1455 fs->check(data->devnode);
1456 r = fs->format(data->devnode);
1458 _E("fail to format block data for %s", data->devnode);
1462 /* need to update the partition data.
1463 * It can be changed in doing format. */
1465 retrieve_udev_device(data, mount_point_updated);
1470 static int format_block_device(struct block_device *bdev,
1471 const char *fs_type,
1472 enum unmount_operation option, bool udev_update)
1474 struct block_data *data;
1482 _I("Format Start : (%s -> %s)",
1483 data->devnode, data->mount_point);
1485 if (data->state == BLOCK_MOUNT) {
1486 r = block_unmount(bdev, option);
1488 _E("fail to unmount %s device : %d", data->devnode, r);
1493 r = block_format(data, fs_type, bdev->mount_point_updated, udev_update);
1495 _E("fail to format %s device : %d", data->devnode, r);
1498 _I("%s result : %s, %d", __func__, data->devnode, r);
1500 r = pipe_trigger(BLOCK_DEV_FORMAT, bdev, r);
1502 _E("fail to trigger pipe");
1507 static struct format_data *get_format_data(
1508 const char *fs_type, enum unmount_operation option, bool udev_update)
1510 struct format_data *fdata;
1512 fdata = (struct format_data *)malloc(sizeof(struct format_data));
1514 _E("fail to allocate format data");
1519 fdata->fs_type = strdup(fs_type);
1521 fdata->fs_type = NULL;
1522 fdata->option = option;
1523 fdata->udev_update = udev_update;
1528 static void release_format_data(struct format_data *data)
1532 free(data->fs_type);
1537 // Called by BlockThread - Real Mount Op
1538 static int block_mount_device(struct block_device *bdev, void *data)
1547 thread_id = bdev->thread_id;
1548 if (thread_id < 0 || thread_id >= THREAD_MAX)
1550 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1551 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1552 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1554 _E("(%d) does not exist in the device list", bdev->data->devnode);
1558 /* mount automatically */
1559 ret = mount_block_device(bdev);
1561 _E("fail to mount block device for %s", bdev->data->devnode);
1566 // Called by BlockThread - Real Format Op
1567 static int block_format_device(struct block_device *bdev, void *data)
1572 struct format_data *fdata = (struct format_data *)data;
1574 if (!bdev || !fdata) {
1579 thread_id = bdev->thread_id;
1580 if (thread_id < 0 || thread_id >= THREAD_MAX)
1582 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1583 l = DD_LIST_FIND(th_manager[thread_id].block_dev_list, bdev);
1584 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1586 _E("(%d) does not exist in the device list", bdev->data->devnode);
1591 ret = format_block_device(bdev, fdata->fs_type, fdata->option, fdata->udev_update);
1593 _E("fail to mount block device for %s", bdev->data->devnode);
1596 release_format_data(fdata);
1601 // Called by BlockThread - Real Unmount Op
1602 static int block_unmount_device(struct block_device *bdev, void *data)
1605 long option = (long)data;
1610 ret = unmount_block_device(bdev, option);
1612 _E("Failed to unmount block device (%s)", bdev->data->devnode);
1619 /* Called by BlockThread - Remove Operation
1620 Direct Call at BlockThread
1621 Previously this function was called by MainThread. However, it will increase complexity.
1622 Need thread lock before to call remove_operation
1624 static void remove_operation(struct block_device *bdev)
1626 struct operation_queue *op;
1633 thread_id = bdev->thread_id;
1634 if (thread_id < 0 || thread_id >= THREAD_MAX)
1637 DD_LIST_FOREACH_SAFE(bdev->op_queue, l, next, op) {
1639 _D("Remove operation (%s, %s)",
1640 get_operation_char(op->op, name, sizeof(name)),
1641 bdev->data->devnode);
1643 DD_LIST_REMOVE(bdev->op_queue, op);
1649 static void block_send_dbus_reply(dbus_method_reply_handle_h reply_handle, int result)
1656 rep = make_dbus_reply_message_simple(reply_handle, result);
1657 reply_dbus_method_result(reply_handle, rep);
1660 // Called by BlockThread
1661 static void check_removed(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1663 struct operation_queue *temp;
1676 thread_id = bdev->thread_id;
1677 if (thread_id < 0 || thread_id >= THREAD_MAX)
1680 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1682 DD_LIST_FOREACH(*queue, l, temp) {
1683 if (temp->op == BLOCK_DEV_REMOVE) {
1688 th_manager[thread_id].op_len--;
1689 block_send_dbus_reply((*op)->reply_handle, 0);
1692 remove_operation(bdev);
1693 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1696 // Called by BlockThread
1697 static bool check_unmount(struct block_device *bdev, dd_list **queue, struct operation_queue **op)
1699 struct operation_queue *temp;
1702 bool unmounted = false;
1713 thread_id = bdev->thread_id;
1714 if (thread_id < 0 || thread_id >= THREAD_MAX)
1717 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1718 DD_LIST_FOREACH(*queue, l, temp) {
1719 if (temp->op == BLOCK_DEV_UNMOUNT) {
1721 _D("Operation queue has unmount operation");
1725 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1730 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1732 DD_LIST_FOREACH(*queue, l, temp) {
1733 if (temp->op == BLOCK_DEV_UNMOUNT) {
1738 th_manager[thread_id].op_len--;
1739 block_send_dbus_reply((*op)->reply_handle, 0);
1742 remove_operation(bdev);
1743 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1748 // Called by BlockThread
1749 static void trigger_operation(struct block_device *bdev, dd_list *queue, struct operation_queue *op)
1753 char devnode[PATH_MAX];
1755 enum block_dev_operation operation;
1756 bool unmounted = false;
1763 thread_id = bdev->thread_id;
1764 if (thread_id < 0 || thread_id >= THREAD_MAX)
1767 snprintf(devnode, sizeof(devnode), "%s", bdev->data->devnode);
1777 _D("Thread id %d Trigger operation (%s, %s)", thread_id,
1778 get_operation_char(operation, name, sizeof(name)), devnode);
1781 if (operation == BLOCK_DEV_INSERT && bdev->removed) {
1782 check_removed(bdev, &queue, &op);
1784 _D("Trigger operation again (%s, %s)",
1785 get_operation_char(operation, name, sizeof(name)), devnode);
1787 if (operation == BLOCK_DEV_MOUNT) {
1788 unmounted = check_unmount(bdev, &queue, &op);
1791 _D("Trigger operation again (%s, %s)",
1792 get_operation_char(operation, name, sizeof(name)), devnode);
1796 switch (operation) {
1797 case BLOCK_DEV_INSERT:
1799 case BLOCK_DEV_MOUNT:
1800 ret = block_mount_device(bdev, op->data);
1801 _D("Mount (%s) result:(%d)", devnode, ret);
1803 case BLOCK_DEV_FORMAT:
1804 ret = block_format_device(bdev, op->data);
1805 _D("Format (%s) result:(%d)", devnode, ret);
1807 case BLOCK_DEV_UNMOUNT:
1808 ret = block_unmount_device(bdev, op->data);
1809 _D("Unmount (%s) result:(%d)", devnode, ret);
1811 case BLOCK_DEV_REMOVE:
1815 _E("Operation type is invalid (%d)", op->op);
1821 * during checking the queue length */
1822 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1825 th_manager[thread_id].op_len--;
1827 block_send_dbus_reply(op->reply_handle, ret);
1829 queue = bdev->op_queue;
1830 if (queue != NULL) {
1831 queue = DD_LIST_NEXT(queue);
1833 op = DD_LIST_NTH(queue, 0);
1839 remove_operation(bdev);
1841 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1844 if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
1845 if (pipe_trigger(operation, bdev, 0) < 0)
1846 _E("fail to trigger pipe");
1853 // Called by BlockThread
1854 static void *block_th_start(void *arg)
1856 struct block_device *temp;
1857 struct manage_thread *th = (struct manage_thread *)arg;
1858 struct operation_queue *op = NULL;
1860 dd_list *queue = NULL;
1865 thread_id = th->thread_id;
1866 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1867 _E("Thread Number: %d", th->thread_id);
1872 pthread_mutex_lock(&(th_manager[thread_id].mutex));
1873 if (th_manager[thread_id].op_len == 0) {
1874 _D("Operation queue of thread is empty");
1875 pthread_cond_wait(&(th_manager[thread_id].cond), &(th_manager[thread_id].mutex));
1876 _D("Wake up %d", thread_id);
1879 DD_LIST_FOREACH(th_manager[thread_id].block_dev_list, elem, temp) {
1880 queue = temp->op_queue;
1882 op = DD_LIST_NTH(queue, 0);
1884 _D("Operation queue for device %s is Empty", temp->data->devnode);
1888 queue = DD_LIST_NEXT(queue);
1896 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
1898 if (op && !op->done)
1899 trigger_operation(temp, queue, op);
1904 // This function will be refactored later
1905 // Especially, we don't need to keep th_node_list.
1906 static int find_thread(char *devnode)
1913 int i, len, min, min_num;
1914 int dev_mmc = -1, part = -1, num;
1917 if (!fnmatch("*/"MMC_PARTITION_PATH, devnode, 0)) {
1918 sscanf(devnode, "/dev/mmcblk%dp%d", &dev_mmc, &part);
1925 snprintf(str, len, "/dev/mmcblk%d", dev_mmc);
1926 th_node = strdup(str);
1927 } else if (!fnmatch("*/"SCSI_PARTITION_PATH, devnode, 0)) {
1928 sscanf(devnode, "/dev/sd%c%d", &dev_scsi, &part);
1929 snprintf(str, SCSI_PARTITION_LENGTH, "/dev/sd%c", dev_scsi);
1930 th_node = strdup(str);
1932 th_node = strdup(devnode);
1934 len = strlen(th_node) + 1;
1937 for (i = 0; i < THREAD_MAX; i++) {
1938 DD_LIST_FOREACH(th_manager[i].th_node_list, elem, temp) {
1939 if (!strncmp(temp, th_node, len)) {
1944 if (th_manager[i].num_dev < min_num) {
1945 min_num = th_manager[i].num_dev;
1950 if (min >= 0 && min < THREAD_MAX) {
1951 DD_LIST_APPEND(th_manager[min].th_node_list, th_node);
1955 _E("Finding thread is failed");
1956 DD_LIST_APPEND(th_manager[0].th_node_list, th_node);
1960 /* Only Main thread is permmited */
1961 // Called by MainThread
1962 static int add_operation(struct block_device *bdev,
1963 enum block_dev_operation operation,
1964 dbus_method_reply_handle_h reply_handle, void *data)
1966 struct operation_queue *op;
1976 _I("Add operation (%s, %s)",
1977 get_operation_char(operation, name, sizeof(name)),
1978 bdev->data->devnode);
1980 thread_id = bdev->thread_id;
1981 if (thread_id < 0 || thread_id >= THREAD_MAX) {
1982 _E("Fail to find thread to add");
1986 op = (struct operation_queue *)malloc(sizeof(struct operation_queue));
1988 _E("malloc failed");
1994 op->reply_handle = reply_handle;
1997 * during adding queue and checking the queue length */
1998 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2000 /* Only modified between lock and unlock of mutex */
2003 start_th = th_manager[thread_id].start_th;
2004 DD_LIST_APPEND(bdev->op_queue, op);
2005 th_manager[thread_id].op_len++;
2007 if (th_manager[thread_id].op_len == 1 && !start_th)
2008 pthread_cond_signal(&(th_manager[thread_id].cond));
2010 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2013 /* Need to disble app2ext whenever unmounting mmc */
2014 if (op->op == BLOCK_DEV_UNMOUNT &&
2015 bdev->data->state == BLOCK_MOUNT &&
2016 bdev->data->block_type == BLOCK_MMC_DEV &&
2017 bdev->data->primary)
2018 if (app2ext_disable_all_external_pkgs() < 0)
2019 _E("app2ext_disable_all_external_pkgs() failed");
2023 _D("Start New thread for block device");
2024 th_manager[thread_id].start_th = false;
2025 ret = pthread_create(&(th_manager[thread_id].th), NULL, block_th_start, &th_manager[thread_id]);
2027 _E("fail to create thread for %s", bdev->data->devnode);
2031 pthread_detach(th_manager[thread_id].th);
2037 static bool disk_is_partitioned_by_kernel(struct udev_device *dev)
2040 struct dirent entry;
2042 const char *syspath;
2045 syspath = udev_device_get_syspath(dev);
2049 dp = opendir(syspath);
2051 _E("fail to open %s", syspath);
2055 /* TODO compare devname and d_name */
2056 while (readdir_r(dp, &entry, &dir) == 0 && dir != NULL) {
2057 if (!fnmatch(MMC_PARTITION_PATH, dir->d_name, 0) ||
2058 !fnmatch(SCSI_PARTITION_PATH, dir->d_name, 0)) {
2070 static bool check_partition(struct udev_device *dev)
2072 const char *devtype;
2073 const char *part_table_type;
2074 const char *fs_usage;
2077 /* only consider disk type, never partitions */
2078 devtype = udev_device_get_devtype(dev);
2082 if (strncmp(devtype, BLOCK_DEVTYPE_DISK,
2083 sizeof(BLOCK_DEVTYPE_DISK)) != 0)
2086 part_table_type = udev_device_get_property_value(dev,
2087 "ID_PART_TABLE_TYPE");
2088 if (part_table_type) {
2089 fs_usage = udev_device_get_property_value(dev,
2092 strncmp(fs_usage, FILESYSTEM, sizeof(FILESYSTEM)) == 0) {
2093 if (!disk_is_partitioned_by_kernel(dev))
2100 if (disk_is_partitioned_by_kernel(dev)) {
2109 // Called by MainThread
2110 static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
2112 struct block_data *data;
2113 struct block_device *bdev;
2114 //char id_string[PATH_LEN];
2118 bool need_format = false;
2120 partition = check_partition(dev);
2122 /* if there is a partition, skip this request */
2123 _I("%s device has partitions, skip this time", devnode);
2127 if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
2128 data = make_block_data(devnode,
2129 udev_device_get_syspath(dev),
2133 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2134 udev_device_get_sysattr_value(dev, "ro"));
2137 data = make_block_data(devnode,
2138 udev_device_get_syspath(dev),
2139 udev_device_get_property_value(dev, "ID_FS_USAGE"),
2140 udev_device_get_property_value(dev, "ID_FS_TYPE"),
2141 udev_device_get_property_value(dev, "ID_FS_VERSION"),
2142 udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
2143 udev_device_get_sysattr_value(dev, "ro"));
2147 _E("fail to make block data for %s", devnode);
2151 if (!block_conf[data->block_type].multimount && !data->primary &&
2152 data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM)) {
2153 _D("Not support multi mount by config info");
2154 free_block_data(data);
2158 bdev = make_block_device(data);
2160 _E("fail to make block device for %s", devnode);
2161 free_block_data(data);
2165 thread_id = find_thread(bdev->data->devnode);
2166 if (thread_id < 0 || thread_id >= THREAD_MAX) {
2167 _E("Fail to find thread to add");
2168 free_block_device(bdev);
2171 bdev->thread_id = thread_id;
2173 pthread_mutex_lock(&(th_manager[thread_id].mutex));
2174 th_manager[thread_id].num_dev++;
2175 DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
2176 pthread_mutex_unlock(&(th_manager[thread_id].mutex));
2179 struct format_data *fdata;
2181 fdata = get_format_data(NULL, 1, false);
2183 _E("Failed to get format data");
2187 ret = add_operation(bdev, BLOCK_DEV_FORMAT, NULL, (void *)fdata);
2189 _E("Failed to add operation (format %s)", bdev->data->devnode);
2190 release_format_data(fdata);
2194 if (!bdev->data->fs_type) {
2195 _E("Unformatted Storage");
2196 free_block_device(bdev);
2198 } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
2199 /* ---- ODE UI launch ----
2200 snprintf(id_string, PATH_LEN, "%d", bdev->data->id);
2201 ret = launch_system_app(POPUP_DEFAULT, 4, POPUP_KEY_CONTENT, "sdcardsetup", POPUP_SDCARD_ID, id_string);
2203 _E("Failed to launch popup");
2205 ode_luks_set_event_cb(CALLBACK)
2208 } else if (mapper && !strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
2209 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2210 ret = change_mount_point(bdev, EXTENDED_SD_PATH);
2213 free_block_device(bdev);
2218 ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
2220 _E("Failed to add operation (insert %s)", devnode);
2221 free_block_device(bdev);
2225 // Not a regular filesystem -> skip mounting
2226 if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM)) {
2227 _I("Not a filesystem. Not mounting");
2231 /* Create file for block device /run/external-storage/id */
2232 create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
2233 ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
2235 _E("Failed to add operation (mount %s)", devnode);
2241 static int remove_block_device(struct udev_device *dev, const char *devnode)
2243 struct block_device *bdev;
2246 bdev = find_block_device(devnode);
2248 _E("fail to find block data for %s", devnode);
2252 BLOCK_FLAG_SET(bdev->data, UNMOUNT_UNSAFE);
2254 bdev->removed = true;
2255 if (bdev->on_private_op != REQ_NORMAL) {
2256 bdev->on_private_op = REQ_NORMAL;
2257 _D("Private operation state: %d", bdev->on_private_op);
2260 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2262 _E("Failed to add operation (unmount %s)", devnode);
2266 ret = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2268 _E("Failed to add operation (remove %s)", devnode);
2275 static int get_internal_storage_number(void)
2277 struct libmnt_table *t = NULL;
2278 struct libmnt_fs *fs;
2281 int r = 0, dev_temp;
2283 if ((!is_emulator() && (dev_internal >= 0 || dev_internal_scsi != '\0')) ||
2284 (is_emulator() && dev_internal_emul != '\0'))
2287 t = mnt_new_table();
2291 r = mnt_table_parse_mtab(t, NULL);
2297 fs = mnt_table_find_target(t, ROOT_DIR, MNT_ITER_BACKWARD);
2303 temp = mnt_fs_get_srcpath(fs);
2307 name = strrchr(temp, '/');
2311 /* Boot from USB is not handled */
2312 if (!is_emulator()) {
2313 if (!fnmatch(MMC_PATH, temp, 0))
2314 sscanf(name, "mmcblk%d", &dev_internal);
2315 else if (!fnmatch(SCSI_PATH, temp, 0))
2316 sscanf(name, "sd%c", &dev_internal_scsi);
2318 if (!fnmatch(MMC_LINK_PATH, temp, 0))
2319 sscanf(name, "vd%c%d", &dev_internal_emul, &dev_temp);
2321 dev_internal_emul = '\0';
2329 static int check_external_storage(const char* devnode)
2331 char dev_scsi = '\0';
2334 int dev_num = -1, dev_temp;
2339 name = strrchr(devnode, '/');
2343 if (!is_emulator()) {
2344 if (!fnmatch(MMC_PATH, devnode, 0)) {
2345 sscanf(name, "mmcblk%d", &dev_num);
2346 if (dev_internal == dev_num) {
2347 _D("%s is internal storage", devnode);
2350 } else if (!fnmatch(SCSI_PATH, devnode, 0)) {
2351 sscanf(name, "sd%c", &dev_scsi);
2352 if (dev_internal_scsi == dev_scsi) {
2353 _D("%s is internal storage", devnode);
2358 if (!fnmatch(MMC_LINK_PATH, devnode, 0)) {
2359 sscanf(name, "vd%c%d", &emul, &dev_temp);
2360 if (dev_internal_emul == emul) {
2361 _D("%s is internal storage", devnode);
2370 static int check_already_handled(const char* devnode)
2372 struct block_device *bdev;
2373 struct block_data *data;
2377 for (i = 0; i < THREAD_MAX; i++) {
2378 pthread_mutex_lock(&(th_manager[i].mutex));
2379 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2385 if (!strncmp(data->devnode, devnode, strlen(devnode) + 1)) {
2386 pthread_mutex_unlock(&(th_manager[i].mutex));
2390 pthread_mutex_unlock(&(th_manager[i].mutex));
2396 static int block_init_from_udev_enumerate(void)
2399 struct udev_enumerate *enumerate;
2400 struct udev_list_entry *list_entry, *list_sub_entry;
2401 struct udev_device *dev;
2402 const char *syspath;
2403 const char *devnode;
2408 _E("fail to create udev library context");
2412 /* create a list of the devices in the 'usb' subsystem */
2413 enumerate = udev_enumerate_new(udev);
2415 _E("fail to create an enumeration context");
2419 if ((dev_internal < 0 && !is_emulator() && dev_internal_scsi == '\0') ||
2420 (is_emulator() && dev_internal_emul == '\0')) {
2421 r = get_internal_storage_number();
2426 udev_enumerate_add_match_subsystem(enumerate, BLOCK_SUBSYSTEM);
2427 udev_enumerate_add_match_property(enumerate,
2428 UDEV_DEVTYPE, BLOCK_DEVTYPE_DISK);
2429 udev_enumerate_add_match_property(enumerate,
2430 UDEV_DEVTYPE, BLOCK_DEVTYPE_PARTITION);
2431 udev_enumerate_scan_devices(enumerate);
2433 udev_list_entry_foreach(list_entry,
2434 udev_enumerate_get_list_entry(enumerate)) {
2435 syspath = udev_list_entry_get_name(list_entry);
2439 dev = udev_device_new_from_syspath(
2440 udev_enumerate_get_udev(enumerate),
2446 udev_list_entry_foreach(list_sub_entry,
2447 udev_device_get_devlinks_list_entry(dev)) {
2448 const char *devlink = udev_list_entry_get_name(list_sub_entry);
2449 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2456 devnode = udev_device_get_devnode(dev);
2460 if (fnmatch(MMC_PATH, devnode, 0) &&
2461 fnmatch(SCSI_PATH, devnode, 0) &&
2462 fnmatch(EXTENDEDSD_PATH, devnode, 0))
2466 r = check_external_storage(devnode);
2470 r = check_already_handled(devnode);
2472 _I("%s is already handled", devnode);
2476 _I("%s device add", devnode);
2477 add_block_device(dev, devnode, false);
2479 udev_device_unref(dev);
2482 udev_enumerate_unref(enumerate);
2487 // Called by MainThread
2488 static void show_block_device_list(void)
2490 struct block_device *bdev;
2491 struct block_data *data;
2495 for (i = 0; i < THREAD_MAX; i++) {
2496 pthread_mutex_lock(&(th_manager[i].mutex));
2497 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
2503 _D("%s:", data->devnode);
2504 _D("\tSyspath: %s", data->syspath);
2505 _D("\tBlock type: %d", data->block_type);
2506 _D("\tFs type: %s", data->fs_type);
2507 _D("\tFs usage: %s", data->fs_usage);
2508 _D("\tFs version: %s", data->fs_version);
2509 _D("\tFs uuid enc: %s", data->fs_uuid_enc);
2510 _D("\tReadonly: %s",
2511 (data->readonly ? "true" : "false"));
2512 _D("\tMount point: %s", data->mount_point);
2513 _D("\tMount state: %s",
2514 (data->state == BLOCK_MOUNT ?
2515 "mount" : "unmount"));
2517 (data->primary ? "true" : "false"));
2518 _D("\tID: %d", data->id);
2520 pthread_mutex_unlock(&(th_manager[i].mutex));
2524 // Called by MainThread
2525 static void remove_whole_block_device(void)
2527 struct block_device *bdev;
2533 for (i = 0; i < THREAD_MAX; i++) {
2535 pthread_mutex_lock(&(th_manager[i].mutex));
2536 DD_LIST_FOREACH_SAFE(th_manager[i].block_dev_list, elem, next, bdev) {
2537 if (bdev->removed == false)
2540 pthread_mutex_unlock(&(th_manager[i].mutex));
2542 if (bdev && bdev->removed == false) {
2543 bdev->removed = true;
2544 r = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_NORMAL);
2546 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2548 r = add_operation(bdev, BLOCK_DEV_REMOVE, NULL, NULL);
2550 _E("Failed to add operation (remove %s)", bdev->data->devnode);
2557 static void booting_done(const char *sender_name,
2558 const char *object_path, const char *interface_name,
2559 const char *signal_name, DBusMessage *msg,
2562 static int done = 0;
2567 /* if there is the attached device, try to mount */
2568 block_init_from_udev_enumerate();
2569 block_control = true;
2573 static void block_poweroff(const char *sender_name,
2574 const char *object_path, const char *interface_name,
2575 const char *signal_name, DBusMessage *msg,
2578 static int status = 0;
2583 /* unregister mmc uevent control routine */
2584 unregister_udev_uevent_control(&uh);
2585 remove_whole_block_device();
2588 static void uevent_block_handler(struct udev_device *dev)
2590 const char *devnode = NULL;
2592 struct udev_list_entry *list_entry;
2594 bool mapper = false;
2596 udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
2597 const char *devlink = udev_list_entry_get_name(list_entry);
2598 if (!fnmatch(MMC_LINK_PATH, devlink, 0)) {
2602 if (!fnmatch(EXTENDEDSD_PATH, devlink, 0)) {
2610 devnode = udev_device_get_devnode(dev);
2614 if (fnmatch(MMC_PATH, devnode, 0) &&
2615 fnmatch(SCSI_PATH, devnode, 0))
2619 r = check_external_storage(devnode);
2623 action = udev_device_get_action(dev);
2627 _I("%s device %s", devnode, action);
2628 if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
2629 (mapper && !strcmp(action, UDEV_CHANGE))) {
2630 r = check_already_handled(devnode);
2632 _I("%s is already handled", devnode);
2636 add_block_device(dev, devnode, mapper);
2637 } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
2638 remove_block_device(dev, devnode);
2642 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
2643 DBusMessage *msg, bool onprivate)
2645 struct block_device *bdev;
2650 if (!reply_handle || !msg)
2653 ret = dbus_message_get_args(msg, NULL,
2654 DBUS_TYPE_INT32, &id,
2655 DBUS_TYPE_STRING, &mount_point,
2660 bdev = find_block_device_by_id(id);
2662 _E("Failed to find (%d) in the device list", id);
2666 if (bdev->on_private_op != REQ_NORMAL) {
2671 if (bdev->data->state == BLOCK_MOUNT) {
2672 _I("%s is already mounted", bdev->data->devnode);
2678 bdev->on_private_op = REQ_PRIVATE;
2679 bdev->private_pid = get_dbus_method_sender_pid(reply_handle);
2680 _D("Private operation state: %d", bdev->on_private_op);
2682 if (bdev->on_private_op != REQ_NORMAL) {
2683 _E("Failed to process mount operation");
2689 /* if requester want to use a specific mount point */
2691 !strncmp(mount_point, EXTENDED_SD_STRING, strlen(EXTENDED_SD_STRING) + 1) != 0) {
2692 if (!block_conf[bdev->data->block_type].extendedinternal ||
2693 !bdev->data->primary) {
2694 _E("Not support extended internal storage");
2698 bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
2699 ret = change_mount_point(bdev, EXTENDED_SD_PATH);
2705 create_file(bdev->data->id, bdev->data->mount_point, true);
2707 } else if (mount_point && strncmp(mount_point, "", 1) != 0) {
2708 ret = change_mount_point(bdev, mount_point);
2714 /* Create /run/external-storage/id file */
2715 create_file(bdev->data->id, bdev->data->mount_point, false);
2717 /* Create file for block device /run/external-storage/id */
2718 create_file(bdev->data->id, bdev->data->mount_point, false);
2721 ret = add_operation(bdev, BLOCK_DEV_MOUNT, reply_handle, NULL);
2723 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2730 return make_dbus_reply_message_simple(reply_handle, ret);
2733 static DBusMessage *request_public_mount_block(dbus_method_reply_handle_h reply_handle,
2736 return request_mount_block(reply_handle, msg, false);
2739 static DBusMessage *request_private_mount_block(dbus_method_reply_handle_h reply_handle,
2742 return request_mount_block(reply_handle, msg, true);
2745 static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handle,
2746 DBusMessage *msg, bool onprivate)
2748 struct block_device *bdev;
2754 if (!reply_handle || !msg)
2757 ret = dbus_message_get_args(msg, NULL,
2758 DBUS_TYPE_INT32, &id,
2759 DBUS_TYPE_INT32, &option,
2764 bdev = find_block_device_by_id(id);
2766 _E("Failed to find (%d) in the device list", id);
2771 if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
2772 _I("Impossible to request unmount extended internal sdcard");
2778 pid = get_dbus_method_sender_pid(reply_handle);
2779 if (bdev->on_private_op == REQ_NORMAL || (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid)) {
2780 _E("Failed to process private unmount operation");
2785 if (bdev->on_private_op != REQ_NORMAL) {
2786 _E("Failed to process unmount operation");
2792 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, reply_handle, (void *)option);
2794 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2801 return make_dbus_reply_message_simple(reply_handle, ret);
2804 static DBusMessage *request_public_unmount_block(dbus_method_reply_handle_h reply_handle,
2807 return request_unmount_block(reply_handle, msg, false);
2810 static DBusMessage *request_private_unmount_block(dbus_method_reply_handle_h reply_handle,
2813 return request_unmount_block(reply_handle, msg, true);
2816 static DBusMessage *request_format_block(dbus_method_reply_handle_h reply_handle,
2819 struct block_device *bdev;
2820 struct format_data *fdata;
2827 if (!reply_handle || !msg)
2830 ret = dbus_message_get_args(msg, NULL,
2831 DBUS_TYPE_INT32, &id,
2832 DBUS_TYPE_INT32, &option,
2837 bdev = find_block_device_by_id(id);
2839 _E("Failed to find (%d) in the device list", id);
2843 pid = get_dbus_method_sender_pid(reply_handle);
2844 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2845 _E("Failed to format on private state");
2850 fdata = get_format_data(NULL, option, true);
2852 _E("Failed to get format data");
2856 prev_state = bdev->data->state;
2857 if (prev_state == BLOCK_MOUNT) {
2858 if (bdev->on_private_op == REQ_PRIVATE) {
2859 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2860 _D("Private operation state: %d", bdev->on_private_op);
2862 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2864 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2865 release_format_data(fdata);
2870 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2872 _E("Failed to add operation (format %s)", bdev->data->devnode);
2873 release_format_data(fdata);
2876 /* Maintain previous state of mount/unmount */
2877 if (prev_state == BLOCK_MOUNT) {
2878 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2879 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2887 return make_dbus_reply_message_simple(reply_handle, ret);
2890 static DBusMessage *request_format_block_type(dbus_method_reply_handle_h reply_handle,
2893 struct block_device *bdev;
2894 struct format_data *fdata;
2902 if (!reply_handle || !msg)
2905 ret = dbus_message_get_args(msg, NULL,
2906 DBUS_TYPE_INT32, &id,
2907 DBUS_TYPE_INT32, &option,
2908 DBUS_TYPE_STRING, &type,
2913 bdev = find_block_device_by_id(id);
2915 _E("Failed to find (%d) in the device list", id);
2919 pid = get_dbus_method_sender_pid(reply_handle);
2920 if (bdev->on_private_op != REQ_NORMAL && pid != bdev->private_pid) {
2921 _E("Failed to format on private state");
2926 fdata = get_format_data(type, option, true);
2928 _E("Failed to get format data");
2932 prev_state = bdev->data->state;
2933 if (prev_state == BLOCK_MOUNT) {
2934 if (bdev->on_private_op == REQ_PRIVATE) {
2935 bdev->on_private_op = REQ_PRIVATE_FORMAT;
2936 _D("Private operation state: %d", bdev->on_private_op);
2938 ret = add_operation(bdev, BLOCK_DEV_UNMOUNT, NULL, (void *)UNMOUNT_FORCE);
2940 _E("Failed to add operation (unmount %s)", bdev->data->devnode);
2941 release_format_data(fdata);
2946 ret = add_operation(bdev, BLOCK_DEV_FORMAT, reply_handle, (void *)fdata);
2948 _E("Failed to add operation (format %s)", bdev->data->devnode);
2949 release_format_data(fdata);
2952 /* Maintain previous state of mount/unmount */
2953 if (prev_state == BLOCK_MOUNT) {
2954 if (add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL) < 0) {
2955 _E("Failed to add operation (mount %s)", bdev->data->devnode);
2963 return make_dbus_reply_message_simple(reply_handle, ret);
2966 static int add_device_to_iter(struct block_data *data, DBusMessageIter *piter)
2968 char *str_null = "";
2970 if (!data || !piter)
2973 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2974 &(data->block_type));
2975 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2976 data->devnode ? &(data->devnode) : &str_null);
2977 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2978 data->syspath ? &(data->syspath) : &str_null);
2979 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2980 data->fs_usage ? &(data->fs_usage) : &str_null);
2981 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2982 data->fs_type ? &(data->fs_type) : &str_null);
2983 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2984 data->fs_version ? &(data->fs_version) : &str_null);
2985 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2986 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
2987 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2989 dbus_message_iter_append_basic(piter, DBUS_TYPE_STRING,
2990 data->mount_point ? &(data->mount_point) : &str_null);
2991 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2993 dbus_message_iter_append_basic(piter, DBUS_TYPE_BOOLEAN,
2995 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
2997 dbus_message_iter_append_basic(piter, DBUS_TYPE_INT32,
3004 static int add_device_to_struct_iter(struct block_data *data, DBusMessageIter *iter)
3006 DBusMessageIter piter;
3011 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3012 add_device_to_iter(data, &piter);
3013 dbus_message_iter_close_container(iter, &piter);
3018 static int add_device_to_iter_2(struct block_data *data, DBusMessageIter *iter)
3020 DBusMessageIter piter;
3021 char *str_null = "";
3026 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &piter);
3027 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3028 &(data->block_type));
3029 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3030 data->devnode ? &(data->devnode) : &str_null);
3031 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3032 data->syspath ? &(data->syspath) : &str_null);
3033 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3034 data->fs_usage ? &(data->fs_usage) : &str_null);
3035 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3036 data->fs_type ? &(data->fs_type) : &str_null);
3037 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3038 data->fs_version ? &(data->fs_version) : &str_null);
3039 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3040 data->fs_uuid_enc ? &(data->fs_uuid_enc) : &str_null);
3041 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3043 dbus_message_iter_append_basic(&piter, DBUS_TYPE_STRING,
3044 data->mount_point ? &(data->mount_point) : &str_null);
3045 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3047 dbus_message_iter_append_basic(&piter, DBUS_TYPE_BOOLEAN,
3049 dbus_message_iter_append_basic(&piter, DBUS_TYPE_INT32,
3051 dbus_message_iter_close_container(iter, &piter);
3056 static DBusMessage *request_get_device_info(dbus_method_reply_handle_h reply_handle,
3059 DBusMessageIter iter;
3061 struct block_device *bdev;
3062 struct block_data *data;
3065 if (!reply_handle || !msg)
3068 reply = make_dbus_reply_message(reply_handle);
3072 ret = dbus_message_get_args(msg, NULL,
3073 DBUS_TYPE_INT32, &id,
3078 bdev = find_block_device_by_id(id);
3085 dbus_message_iter_init_append(reply, &iter);
3086 add_device_to_iter(data, &iter);
3092 static DBusMessage *request_show_device_list(dbus_method_reply_handle_h reply_handle,
3095 show_block_device_list();
3096 return make_dbus_reply_message(reply_handle);
3099 // Called by MainThread
3100 static DBusMessage *request_get_device_list(dbus_method_reply_handle_h reply_handle,
3103 DBusMessageIter iter;
3104 DBusMessageIter aiter;
3106 struct block_device *bdev;
3107 struct block_data *data;
3114 reply = make_dbus_reply_message(reply_handle);
3116 ret = dbus_message_get_args(msg, NULL,
3117 DBUS_TYPE_STRING, &type,
3120 _E("Failed to get args");
3125 _E("Delivered type is NULL");
3129 _D("Block (%s) device list is requested", type);
3131 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3132 block_type = BLOCK_SCSI_DEV;
3133 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3134 block_type = BLOCK_MMC_DEV;
3135 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3138 _E("Invalid type (%s) is requested", type);
3142 dbus_message_iter_init_append(reply, &iter);
3143 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibii)", &aiter);
3145 for (i = 0; i < THREAD_MAX; i++) {
3146 pthread_mutex_lock(&(th_manager[i].mutex));
3147 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3154 switch (block_type) {
3155 case BLOCK_SCSI_DEV:
3157 if (data->block_type != block_type)
3163 add_device_to_struct_iter(data, &aiter);
3165 pthread_mutex_unlock(&(th_manager[i].mutex));
3167 dbus_message_iter_close_container(&iter, &aiter);
3173 // Called by MainThread
3174 static DBusMessage *request_get_device_list_2(dbus_method_reply_handle_h reply_handle,
3177 DBusMessageIter iter;
3178 DBusMessageIter aiter;
3180 struct block_device *bdev;
3181 struct block_data *data;
3188 reply = make_dbus_reply_message(reply_handle);
3190 ret = dbus_message_get_args(msg, NULL,
3191 DBUS_TYPE_STRING, &type,
3194 _E("Failed to get args");
3199 _E("Delivered type is NULL");
3203 _D("Block (%s) device list is requested", type);
3205 if (!strncmp(type, BLOCK_TYPE_SCSI, sizeof(BLOCK_TYPE_SCSI)))
3206 block_type = BLOCK_SCSI_DEV;
3207 else if (!strncmp(type, BLOCK_TYPE_MMC, sizeof(BLOCK_TYPE_MMC)))
3208 block_type = BLOCK_MMC_DEV;
3209 else if (!strncmp(type, BLOCK_TYPE_ALL, sizeof(BLOCK_TYPE_ALL)))
3212 _E("Invalid type (%s) is requested", type);
3216 dbus_message_iter_init_append(reply, &iter);
3217 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(issssssisibi)", &aiter);
3219 for (i = 0; i < THREAD_MAX; i++) {
3220 pthread_mutex_lock(&(th_manager[i].mutex));
3221 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3228 switch (block_type) {
3229 case BLOCK_SCSI_DEV:
3231 if (data->block_type != block_type)
3238 add_device_to_iter_2(data, &aiter);
3240 pthread_mutex_unlock(&(th_manager[i].mutex));
3242 dbus_message_iter_close_container(&iter, &aiter);
3248 static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_handle,
3251 DBusMessageIter iter;
3253 struct block_device *bdev;
3254 struct block_data *data, nodata = {0,};
3259 if (!reply_handle || !msg)
3262 reply = make_dbus_reply_message(reply_handle);
3267 for (i = 0; i < THREAD_MAX; i++) {
3268 pthread_mutex_lock(&(th_manager[i].mutex));
3269 DD_LIST_FOREACH(th_manager[i].block_dev_list, elem, bdev) {
3275 if (data->block_type != BLOCK_MMC_DEV &&
3276 data->block_type != BLOCK_EXTENDEDSD_DEV)
3283 pthread_mutex_unlock(&(th_manager[i].mutex));
3288 dbus_message_iter_init_append(reply, &iter);
3290 add_device_to_iter(data, &iter);
3292 nodata.id = -ENODEV;
3293 add_device_to_iter(&nodata, &iter);
3300 static DBusMessage *request_check_speed(dbus_method_reply_handle_h reply_handle,
3303 struct timespec start_time, end_time;
3304 DBusMessageIter iter;
3306 struct block_device *bdev;
3307 struct block_data *data;
3313 if (!reply_handle || !msg)
3316 ret = dbus_message_get_args(msg, NULL,
3317 DBUS_TYPE_INT32, &id,
3324 bdev = find_block_device_by_id(id);
3335 _D("speed check: %s", data->devnode);
3336 fd = open(data->devnode, O_RDWR | O_SYNC);
3337 buf = calloc(1, SPEEDCHECK * 1024 * 1024);
3339 _E("calloc() failed");
3344 clock_gettime(CLOCK_REALTIME, &start_time);
3345 _I("start time: %lu.%lu", start_time.tv_sec, start_time.tv_nsec);
3346 ret = write(fd, buf, SPEEDCHECK * 1024 * 1024);
3347 clock_gettime(CLOCK_REALTIME, &end_time);
3348 _I("end time %lu.%lu", end_time.tv_sec, end_time.tv_nsec);
3352 if (SPEEDCHECK / (end_time.tv_sec - start_time.tv_sec) < 4) {
3359 _E("write() failed %d", errno);
3366 reply = dbus_message_new_method_return(msg);
3367 dbus_message_iter_init_append(reply, &iter);
3368 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
3373 Method name Method call format string Reply format string
3374 { "ShowDeviceList", NULL, NULL, request_show_device_list },
3375 { "GetDeviceList", "s", "a(issssssisibii)", request_get_device_list },
3376 { "GetDeviceList2", "s", "a(issssssisibi)", request_get_device_list_2 },
3377 { "Mount", "is", "i", request_public_mount_block },
3378 { "Unmoun, "ii", "i", request_public_unmount_block },
3379 { "Format", "ii", "i", request_format_block },
3380 { "GetDeviceInfo", "i", "(issssssisibii)", request_get_device_info },
3381 { "GetMmcPrimary", NULL, "(issssssisibii)" , request_get_mmc_primary },
3382 { "PrivateMount", "is", "i", request_private_mount_block },
3383 { "PrivateUnmount", "ii", "i", request_private_unmount_block },
3386 static const dbus_method_s manager_methods[] = {
3387 { "ShowDeviceList", NULL, request_show_device_list },
3388 { "GetDeviceList" , "s", request_get_device_list },
3389 { "GetDeviceList2", "s", request_get_device_list_2 },
3390 { "Mount", "is", request_public_mount_block },
3391 { "Unmount", "ii", request_public_unmount_block },
3392 { "Format", "ii", request_format_block },
3393 { "FormatwithType", "iis", request_format_block_type },
3394 { "GetDeviceInfo", "i", request_get_device_info },
3395 { "GetMmcPrimary" , NULL, request_get_mmc_primary },
3396 { "PrivateMount", "is", request_private_mount_block },
3397 { "PrivateUnmount", "ii", request_private_unmount_block },
3398 { "CheckSpeed", "i", request_check_speed },
3401 static dbus_interface_s block_interface = {
3402 .name = STORAGED_INTERFACE_BLOCK_MANAGER,
3403 .methods = manager_methods,
3404 .nr_methods = ARRAY_SIZE(manager_methods),
3407 static int load_config(struct parse_result *result, void *user_data)
3411 if (MATCH(result->section, "Block"))
3414 if (MATCH(result->section, "SCSI"))
3415 index = BLOCK_SCSI_DEV;
3416 else if (MATCH(result->section, "MMC"))
3417 index = BLOCK_MMC_DEV;
3418 else if (MATCH(result->section, "Mapper"))
3419 index = BLOCK_EXTENDEDSD_DEV;
3423 if (MATCH(result->name, "Multimount"))
3424 block_conf[index].multimount =
3425 (MATCH(result->value, "yes") ? true : false);
3426 if (MATCH(result->name, "ExtendedInternalStorage"))
3427 block_conf[index].extendedinternal =
3428 (MATCH(result->value, "yes") ? true : false);
3434 static int mount_root_path_tmpfs(void)
3439 root = tzplatform_getenv(TZ_SYS_MEDIA);
3443 if (access(root, F_OK) != 0)
3446 if (mount_check(root))
3449 ret = mount("tmpfs", root, "tmpfs", 0, "smackfsroot=System::Shared");
3452 _E("tmpfs mount failed (%d)", ret);
3459 #define mount_root_path_tmpfs() 0
3462 static void block_init(void *data)
3467 dbus_handle_h handle;
3472 ret = config_parse(BLOCK_CONF_FILE, load_config, NULL);
3474 _E("fail to load %s, Use default value", BLOCK_CONF_FILE);
3476 ret = mount_root_path_tmpfs();
3478 _E("Failed to mount tmpfs to root mount path (%d)", ret);
3480 ret = dbus_get_connection(&handle);
3482 _E("Failed to get dbus connection(%d)", ret);
3484 /* register block manager object and interface */
3485 ret = register_dbus_methods(handle,
3486 STORAGED_PATH_BLOCK_MANAGER, &block_interface,
3489 _E("Failed to register block interface and methods (%d)", ret);
3494 _E("fail to init pipe");
3496 /* register mmc uevent control routine */
3497 ret = register_udev_uevent_control(&uh);
3499 _E("fail to register block uevent : %d", ret);
3501 /* System Session is loaded completely */
3502 register_dbus_signal(SYSTEMD_DBUS_PATH,
3503 SYSTEMD_DBUS_IFACE_MANAGER,
3504 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3505 booting_done, NULL, NULL);
3507 register_dbus_signal(DEVICED_PATH_POWEROFF,
3508 DEVICED_INTERFACE_POWEROFF,
3509 SIGNAL_POWEROFF_STATE,
3510 block_poweroff, NULL, NULL);
3512 for (i = 0; i < THREAD_MAX; i++) {
3513 th_manager[i].num_dev = 0;
3514 th_manager[i].op_len = 0;
3515 th_manager[i].start_th = true;
3516 th_manager[i].thread_id = i;
3517 pthread_mutex_init(&(th_manager[i].mutex), NULL);
3518 pthread_cond_init(&(th_manager[i].cond), NULL);
3521 ret = stat(EXTERNAL_STORAGE_PATH, &buf);
3523 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3525 _E("Failed to make directory: %d", errno);
3526 } else if (!S_ISDIR(buf.st_mode)) {
3527 ret = remove(EXTERNAL_STORAGE_PATH);
3529 _E("Fail to remove %s. errno: %d", EXTERNAL_STORAGE_PATH, errno);
3530 ret = mkdir(EXTERNAL_STORAGE_PATH, 0755);
3532 _E("Failed to make directory: %d", errno);
3534 ret = chmod(EXTERNAL_STORAGE_PATH, 0644);
3536 _E("Fail to change permissions of a file");
3539 ret = stat(EXTENDED_INTERNAL_PATH, &buf);
3541 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3543 _E("Failed to make directory: %d", errno);
3544 } else if (!S_ISDIR(buf.st_mode)) {
3545 ret = remove(EXTENDED_INTERNAL_PATH);
3547 _E("Fail to remove %s. errno: %d", EXTENDED_INTERNAL_PATH, errno);
3548 ret = mkdir(EXTENDED_INTERNAL_PATH, 0755);
3550 _E("Failed to make directory: %d", errno);
3552 ret = chmod(EXTENDED_INTERNAL_PATH, 0644);
3554 _E("Fail to change permissions of a file");
3558 static void block_exit(void *data)
3560 dd_list *elem, *elem_next;
3566 /* unregister notifier for below each event */
3567 unregister_dbus_signal(SYSTEMD_DBUS_PATH,
3568 SYSTEMD_DBUS_IFACE_MANAGER,
3569 SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
3572 unregister_dbus_signal(DEVICED_PATH_POWEROFF,
3573 DEVICED_INTERFACE_POWEROFF,
3574 SIGNAL_POWEROFF_STATE, block_poweroff);
3579 /* unregister mmc uevent control routine */
3580 ret = unregister_udev_uevent_control(&uh);
3582 _E("fail to unregister block uevent : %d", ret);
3584 /* remove remaining blocks */
3585 remove_whole_block_device();
3587 for (i = 0; i < THREAD_MAX; i++) {
3588 if (!th_manager[i].start_th)
3589 pthread_cancel(th_manager[i].th);
3590 DD_LIST_FOREACH_SAFE(th_manager[i].th_node_list, elem, elem_next, temp) {
3591 DD_LIST_REMOVE(th_manager[i].th_node_list, temp);
3596 block_control = false;
3599 static int block_start(void *data)
3604 _E("Cannot be started. Booting is not ready");
3608 if (block_control) {
3609 _I("Already started");
3613 /* register mmc uevent control routine */
3614 ret = register_udev_uevent_control(&uh);
3616 _E("fail to register block uevent : %d", ret);
3618 block_init_from_udev_enumerate();
3620 block_control = true;
3626 static int block_stop(void *data)
3629 _E("Cannot be stopped. Booting is not ready");
3633 if (!block_control) {
3634 _I("Already stopped");
3638 /* unregister mmc uevent control routine */
3639 unregister_udev_uevent_control(&uh);
3641 /* remove the existing blocks */
3642 remove_whole_block_device();
3644 block_control = false;
3650 static storaged_module_interface block_module = {
3654 .start = block_start,
3658 __attribute__ ((visibility("default")))storaged_module_interface *
3659 storaged_get_module_interface(void)
3661 return &block_module;