Support for encrypted internal memory extension 93/152793/6
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Fri, 22 Sep 2017 12:01:58 +0000 (14:01 +0200)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Mon, 16 Oct 2017 11:24:19 +0000 (11:24 +0000)
- Support device mapper devices. Necessary because dmcrypt uses device mapper.
  It also requires proper udev rules for device mapper. Device mapper devices
  will be marked as BLOCK_MAPPER_DEV (previously
  BLOCK_MMC_EXTENDED_INTERNAL_DEV). Update block.conf file and related logic.

- Support different/unknown filesystems. We don't know what kind of data will
  be on sd card, but we have to be able to detect it. All sdcards are marked as
  BLOCK_MMC_DEV. Listener can distinguish cards by fs_type if needed.

- For devices with non-filesystem FS_USAGE (for example "crypto") we don't need
  2.4 backward compatibility and fixed id.

- Don't generate mount path for devices with non-filesystem FS_USAGE.

- Don't check for primary partition on device mapper devices.

- Don't check multimount for unknown filesystems.

- Trigger card setup UI for cards without LUKS or with garbage on them. Don't
  treat unformatted cards as an error.

- For internal memory extension assign the mountpoint in make_block_data() as
  in case of other types of storage.

- Don't try to mount unknown filesystems.

- In case of device mapper udev events treat "change" as "add" (perhaps this
  can be avoided by providing proper udev rules).

- Update device data when udev "change" event occurs. Formatting partition
  externally (LUKS case) requires manual udev read so that both udev and
  storaged have the actual device state. Also notify listeners about this
  change.

- Allow unmounting internal memory extension card. Not sure why it was disabled.

Change-Id: I26f98b31a24936f0b4524fc5c081163f9c9e4878
Signed-off-by: Hyotaek Shim <hyotaek.shim@samsung.com>
(cherry picked from commit 906c1fc5c63aa13849e9a0c629999ac4faca2e66)

src/block/block.c
src/block/block.conf
src/block/block.h

index 082eeb3..24f1a79 100644 (file)
@@ -62,6 +62,7 @@
 #define SCSI_PATH           "*/sd[a-z]*"
 #define SCSI_PARTITION_PATH "sd[a-z][0-9]"
 #define SCSI_PARTITION_LENGTH 9
+#define EXTENDEDSD_PATH     "/dev/mapper/extendedsd*"
 
 #define FILESYSTEM          "filesystem"
 
@@ -160,7 +161,7 @@ struct pipe_data {
 static struct block_conf {
        bool multimount;
        bool extendedinternal;
-} block_conf[BLOCK_MMC_EXTENDED_INTERNAL_DEV + 1];
+} block_conf[BLOCK_EXTENDEDSD_DEV + 1];
 
 static struct manage_thread {
        dd_list *th_node_list;  /* List of devnode which thread dealt with. Only main thread access */
@@ -267,17 +268,17 @@ static void broadcast_block_info(enum block_dev_operation op,
                        continue;
                // TODO What happend on extended internal storage case?
                if (op == BLOCK_DEV_MOUNT) {
-                       if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+                       if (data->block_type == BLOCK_EXTENDEDSD_DEV)
                                ops->mounted(data, result, true);
                        else
                                ops->mounted(data, result, false);
                } else if (op == BLOCK_DEV_UNMOUNT) {
-                       if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+                       if (data->block_type == BLOCK_EXTENDEDSD_DEV)
                                ops->unmounted(data, result, true);
                        else
                                ops->unmounted(data, result, false);
                } else if (op == BLOCK_DEV_FORMAT) {
-                       if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+                       if (data->block_type == BLOCK_EXTENDEDSD_DEV)
                                ops->formatted(data, result, true);
                        else
                                ops->formatted(data, result, false);
@@ -551,7 +552,7 @@ static char *generate_mount_path(struct block_data *data)
        char *name, node[64];
        int ret;
 
-       if (!data || !data->devnode)
+       if (!data || !data->devnode || !data->fs_usage || strcmp(data->fs_usage, FILESYSTEM))
                return NULL;
 
        name = strrchr(data->devnode, '/');
@@ -566,7 +567,7 @@ static char *generate_mount_path(struct block_data *data)
        case BLOCK_SCSI_DEV:
                ret = get_scsi_mount_node(name, node, sizeof(node));
                break;
-       case BLOCK_MMC_EXTENDED_INTERNAL_DEV:
+       case BLOCK_EXTENDEDSD_DEV:
                return strdup(EXTENDED_SD_PATH);
        default:
                _E("Invalid block type (%d)", data->block_type);
@@ -602,7 +603,8 @@ static bool check_primary_partition(const char *devnode)
 
        if (fnmatch(MMC_LINK_PATH, devnode, 0) &&
                fnmatch(MMC_PATH, devnode, 0) &&
-               fnmatch(SCSI_PATH, devnode, 0))
+               fnmatch(SCSI_PATH, devnode, 0) &&
+               fnmatch(EXTENDEDSD_PATH, devnode, 0))
                return false;
 
        temp = strrchr(devnode, '/');
@@ -671,7 +673,7 @@ static struct block_data *make_block_data(const char *devnode,
                return NULL;
 
        if (!fs_type)
-               _E("Not support extended partition");
+               _I("Unknown fs type");
 
        data = calloc(1, sizeof(struct block_data));
        if (!data) {
@@ -701,6 +703,8 @@ static struct block_data *make_block_data(const char *devnode,
                data->block_type = BLOCK_MMC_DEV;
        else if (!fnmatch(SCSI_PATH, devnode, 0))
                data->block_type = BLOCK_SCSI_DEV;
+       else if (!fnmatch(EXTENDEDSD_PATH, devnode, 0))
+               data->block_type = BLOCK_EXTENDEDSD_DEV;
        else
                data->block_type = -1;
 
@@ -709,7 +713,8 @@ static struct block_data *make_block_data(const char *devnode,
 
        /* for 2.4 backward compatibility */
        // What if storage id 1 is existed? (multi sdcard case)
-       if (data->primary == true && data->block_type == BLOCK_MMC_DEV)
+       if (data->primary == true && data->block_type == BLOCK_MMC_DEV &&
+           data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM))
                data->id = EXT_PRIMARY_SD_FIXID;
        else
                data->id = block_get_new_id();
@@ -965,7 +970,7 @@ static bool pipe_cb(int fd, void *data)
                        ret = change_mount_point(pdata.bdev, "");
                        /* Modify /run/external-storage/id file */
                        if (ret == 0) {
-                               if (pdata.bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+                               if (pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV)
                                        create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, true);
                                else
                                        create_file(pdata.bdev->data->id, pdata.bdev->data->mount_point, false);
@@ -980,10 +985,7 @@ static bool pipe_cb(int fd, void *data)
                create_external_apps_directory();
        if (pdata.op == BLOCK_DEV_UNMOUNT) {
                /* Remove file for block device /run/xxxxxx/id */
-               if (pdata.bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
-                       remove_file(pdata.bdev->data->id, true);
-               else
-                       remove_file(pdata.bdev->data->id, false);
+               remove_file(pdata.bdev->data->id, pdata.bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
        }
 
        /* Broadcast to mmc and usb storage module */
@@ -1162,7 +1164,7 @@ static int block_mount(struct block_data *data)
                goto out;
        }
 
-       if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+       if (data->block_type == BLOCK_EXTENDEDSD_DEV)
                r = fs->mount(false, data->devnode, data->mount_point);
        else
                r = fs->mount(smack, data->devnode, data->mount_point);
@@ -1315,7 +1317,7 @@ static int block_unmount(struct block_device *bdev,
                        /* Mobile specific:
                         * should unmount the below vconf key. */
                        if ((data->block_type == BLOCK_MMC_DEV ||
-                               data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV) &&
+                               data->block_type == BLOCK_EXTENDEDSD_DEV) &&
                                data->primary) {
                                /* At first, notify to other app
                                 * who already access sdcard */
@@ -1405,7 +1407,7 @@ out:
 }
 
 static int block_format(struct block_data *data,
-               const char *fs_type, bool mount_point_updated)
+               const char *fs_type, bool mount_point_updated, bool udev_update)
 {
        const struct block_fs_ops *fs;
        dd_list *elem;
@@ -1416,7 +1418,7 @@ static int block_format(struct block_data *data,
        if (!data || !data->devnode || !data->mount_point)
                return -EINVAL;
 
-       if (data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
+       if (data->block_type == BLOCK_EXTENDEDSD_DEV)
                fstype = EXT4_NAME;
        else {
                if (!fs_type) {
@@ -1453,8 +1455,8 @@ static int block_format(struct block_data *data,
 
        /* need to update the partition data.
         * It can be changed in doing format. */
-       retrieve_udev_device(data, mount_point_updated);
-
+       if (udev_update)
+               retrieve_udev_device(data, mount_point_updated);
 out:
        return r;
 }
@@ -1482,7 +1484,7 @@ static int format_block_device(struct block_device *bdev,
                }
        }
 
-       r = block_format(data, fs_type, bdev->mount_point_updated);
+       r = block_format(data, fs_type, bdev->mount_point_updated, false);
        if (r < 0)
                _E("fail to format %s device : %d", data->devnode, r);
 
@@ -1832,7 +1834,6 @@ static void trigger_operation(struct block_device *bdev, dd_list *queue, struct
                pthread_mutex_unlock(&(th_manager[thread_id].mutex));
                /* UNLOCK */
 
-
                if (operation == BLOCK_DEV_INSERT || operation == BLOCK_DEV_REMOVE) {
                        if (pipe_trigger(operation, bdev, 0) < 0)
                                _E("fail to trigger pipe");
@@ -2099,7 +2100,7 @@ out:
 }
 
 // Called by MainThread
-static int add_block_device(struct udev_device *dev, const char *devnode, bool init)
+static int add_block_device(struct udev_device *dev, const char *devnode, bool mapper)
 {
        struct block_data *data;
        struct block_device *bdev;
@@ -2107,6 +2108,7 @@ static int add_block_device(struct udev_device *dev, const char *devnode, bool i
        bool partition;
        int ret;
        int thread_id;
+       bool need_format = false;
 
        partition = check_partition(dev);
        if (partition) {
@@ -2115,19 +2117,32 @@ static int add_block_device(struct udev_device *dev, const char *devnode, bool i
                return 0;
        }
 
-       data = make_block_data(devnode,
-                       udev_device_get_syspath(dev),
-                       udev_device_get_property_value(dev, "ID_FS_USAGE"),
-                       udev_device_get_property_value(dev, "ID_FS_TYPE"),
-                       udev_device_get_property_value(dev, "ID_FS_VERSION"),
-                       udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
-                       udev_device_get_sysattr_value(dev, "ro"));
+       if (mapper && !udev_device_get_property_value(dev, "ID_FS_TYPE")) {
+               data = make_block_data(devnode,
+                               udev_device_get_syspath(dev),
+                               FILESYSTEM,
+                               EXT4_NAME,
+                               "1.0",
+                               udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
+                               udev_device_get_sysattr_value(dev, "ro"));
+               need_format = true;
+       } else {
+               data = make_block_data(devnode,
+                               udev_device_get_syspath(dev),
+                               udev_device_get_property_value(dev, "ID_FS_USAGE"),
+                               udev_device_get_property_value(dev, "ID_FS_TYPE"),
+                               udev_device_get_property_value(dev, "ID_FS_VERSION"),
+                               udev_device_get_property_value(dev, "ID_FS_UUID_ENC"),
+                               udev_device_get_sysattr_value(dev, "ro"));
+       }
+
        if (!data) {
                _E("fail to make block data for %s", devnode);
                return -EPERM;
        }
 
-       if (!block_conf[data->block_type].multimount && !data->primary) {
+       if (!block_conf[data->block_type].multimount && !data->primary &&
+           data->fs_usage && !strcmp(data->fs_usage, FILESYSTEM)) {
                _D("Not support multi mount by config info");
                free_block_data(data);
                return -EPERM;
@@ -2153,8 +2168,19 @@ static int add_block_device(struct udev_device *dev, const char *devnode, bool i
        DD_LIST_APPEND(th_manager[thread_id].block_dev_list, bdev);
        pthread_mutex_unlock(&(th_manager[thread_id].mutex));
 
-       if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
-               bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
+       if (need_format) {
+               ret = block_format(bdev->data, EXT4_NAME, false, false);
+               if (ret < 0) {
+                       _E("Failed to add operation (format %s)", bdev->data->devnode);
+               }
+       }
+
+       if (!bdev->data->fs_type) {
+               _E("Unformatted Storage");
+               free_block_device(bdev);
+               return -EPERM;
+       } else if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
+               bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
                ret = change_mount_point(bdev, EXTENDED_SD_PATH);
                if (ret < 0) {
                        ret = -EPERM;
@@ -2173,64 +2199,15 @@ static int add_block_device(struct udev_device *dev, const char *devnode, bool i
 
                return 0;
        } else if (!strncmp(bdev->data->fs_type, EXT4_NAME, strlen(EXT4_NAME))) {
-               bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
+               bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
                ret = change_mount_point(bdev, EXTENDED_SD_PATH);
                if (ret < 0) {
                        ret = -EPERM;
                        free_block_device(bdev);
                        return ret;
                }
-       } else if (!bdev->data->fs_type) {
-               _E("Unformatted Storage");
-               free_block_device(bdev);
-               return -EPERM;
        }
 
-#if 0
-       /* Check this sdcard is already formatted for extended internal sdcard */
-       if (block_conf[bdev->data->block_type].extendedinternal &&
-               bdev->data->block_type == BLOCK_MMC_DEV &&
-               bdev->data->primary) { // sdcard primary partition and extended internal option is on
-               _I("Check whether sdcard will be used as extended internal storage");
-
-               if (!init) { // after booting is done launch popup for setting
-                       ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
-                       if (ret < 0) {
-                               _E("Failed to add operation (insert %s)", devnode);
-                               free_block_device(bdev);
-                               return ret;
-                       }
-
-                       snprintf(id_string, PATH_LEN, "%d", bdev->data->id);
-                       ret = launch_system_app(POPUP_DEFAULT, 4, POPUP_KEY_CONTENT, "sdcardsetup", POPUP_SDCARD_ID, id_string);
-                       if (ret < 0)
-                               _E("Failed to launch popup");
-                       return 0;
-               } else { // at booting time
-                       if (!bdev->data->fs_type) {
-                               _E("Unformatted Storage");
-                               free_block_device(bdev);
-                               return -EPERM;
-                       }
-
-                       if (!strncmp(bdev->data->fs_type, LUKS_NAME, strlen(LUKS_NAME))) {
-                               bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
-                               ret = change_mount_point(bdev, EXTENDED_SD_PATH);
-                               if (ret < 0) {
-                                       ret = -EPERM;
-                                       free_block_device(bdev);
-                                       return ret;
-                               }
-                       }
-               }
-       } else {
-               if (!bdev->data->fs_type) {
-                       _E("Unformatted Storage");
-                       free_block_device(bdev);
-                       return -EPERM;
-               }
-       }
-#endif
        ret = add_operation(bdev, BLOCK_DEV_INSERT, NULL, (void *)data);
        if (ret < 0) {
                _E("Failed to add operation (insert %s)", devnode);
@@ -2238,11 +2215,14 @@ static int add_block_device(struct udev_device *dev, const char *devnode, bool i
                return ret;
        }
 
+       // Not a regular filesystem -> skip mounting
+       if (!bdev->data->fs_usage || strcmp(bdev->data->fs_usage, FILESYSTEM)) {
+               _I("Not a filesystem. Not mounting");
+               return 0;
+       }
+
        /* Create file for block device /run/external-storage/id */
-       if (bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV)
-               create_file(bdev->data->id, bdev->data->mount_point, true);
-       else
-               create_file(bdev->data->id, bdev->data->mount_point, false);
+       create_file(bdev->data->id, bdev->data->mount_point, bdev->data->block_type == BLOCK_EXTENDEDSD_DEV);
        ret = add_operation(bdev, BLOCK_DEV_MOUNT, NULL, NULL);
        if (ret < 0) {
                _E("Failed to add operation (mount %s)", devnode);
@@ -2471,7 +2451,8 @@ static int block_init_from_udev_enumerate(void)
                                continue;
 
                        if (fnmatch(MMC_PATH, devnode, 0) &&
-                           fnmatch(SCSI_PATH, devnode, 0))
+                           fnmatch(SCSI_PATH, devnode, 0) &&
+                           fnmatch(EXTENDEDSD_PATH, devnode, 0))
                                continue;
                }
 
@@ -2486,7 +2467,7 @@ static int block_init_from_udev_enumerate(void)
                }
 
                _I("%s device add", devnode);
-               add_block_device(dev, devnode, true);
+               add_block_device(dev, devnode, false);
 
                udev_device_unref(dev);
        }
@@ -2603,6 +2584,7 @@ static void uevent_block_handler(struct udev_device *dev)
        const char *action;
        struct udev_list_entry *list_entry;
        int r;
+       bool mapper = false;
 
        udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
                const char *devlink = udev_list_entry_get_name(list_entry);
@@ -2610,6 +2592,11 @@ static void uevent_block_handler(struct udev_device *dev)
                        devnode = devlink;
                        break;
                }
+               if (!fnmatch(EXTENDEDSD_PATH, devlink, 0)) {
+                       mapper = true;
+                       devnode = devlink;
+                       break;
+               }
        }
 
        if (!devnode) {
@@ -2631,16 +2618,18 @@ static void uevent_block_handler(struct udev_device *dev)
                return;
 
        _I("%s device %s", devnode, action);
-       if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD))) {
+       if (!strncmp(action, UDEV_ADD, sizeof(UDEV_ADD)) ||
+          (mapper && !strcmp(action, UDEV_CHANGE))) {
                r = check_already_handled(devnode);
                if (r < 0) {
                        _I("%s is already handled", devnode);
                        return;
                }
 
-               add_block_device(dev, devnode, false);
-       } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE)))
+               add_block_device(dev, devnode, mapper);
+       } else if (!strncmp(action, UDEV_REMOVE, sizeof(UDEV_REMOVE))) {
                remove_block_device(dev, devnode);
+       }
 }
 
 static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
@@ -2699,7 +2688,7 @@ static DBusMessage *request_mount_block(dbus_method_reply_handle_h reply_handle,
                        ret = -EPERM;
                        goto out;
                } else {
-                       bdev->data->block_type = BLOCK_MMC_EXTENDED_INTERNAL_DEV;
+                       bdev->data->block_type = BLOCK_EXTENDEDSD_DEV;
                        ret = change_mount_point(bdev, EXTENDED_SD_PATH);
                        if (ret < 0) {
                                ret = -EPERM;
@@ -2771,7 +2760,8 @@ static DBusMessage *request_unmount_block(dbus_method_reply_handle_h reply_handl
                ret = -ENOENT;
                goto out;
        }
-       if (bdev->data->block_type == BLOCK_MMC_EXTENDED_INTERNAL_DEV) {
+
+       if (bdev->data->block_type == BLOCK_EXTENDEDSD_DEV) {
                _I("Impossible to request unmount extended internal sdcard");
                ret = -EPERM;
                goto out;
@@ -3275,7 +3265,8 @@ static DBusMessage *request_get_mmc_primary(dbus_method_reply_handle_h reply_han
                                continue;
                        if (bdev->removed)
                                continue;
-                       if (data->block_type != BLOCK_MMC_DEV)
+                       if (data->block_type != BLOCK_MMC_DEV &&
+                           data->block_type != BLOCK_EXTENDEDSD_DEV)
                                continue;
                        if (!data->primary)
                                continue;
@@ -3417,6 +3408,8 @@ static int load_config(struct parse_result *result, void *user_data)
                index = BLOCK_SCSI_DEV;
        else if (MATCH(result->section, "MMC"))
                index = BLOCK_MMC_DEV;
+       else if (MATCH(result->section, "Mapper"))
+               index = BLOCK_EXTENDEDSD_DEV;
        else
                return -EINVAL;
 
@@ -3427,11 +3420,6 @@ static int load_config(struct parse_result *result, void *user_data)
                block_conf[index].extendedinternal =
                        (MATCH(result->value, "yes") ? true : false);
 
-       if (index == BLOCK_MMC_DEV) {
-               block_conf[index + 1].multimount = block_conf[index].multimount;
-               block_conf[index + 1].extendedinternal = block_conf[index].extendedinternal;
-       }
-
        return 0;
 }
 
index a022cf7..d27c779 100644 (file)
@@ -6,3 +6,7 @@ ExtendedInternalStorage=yes # yes or no
 
 [SCSI]
 Multimount=yes # yes or no
+
+[Mapper]
+Multimount=no
+ExtendedInternalStorage=yes
\ No newline at end of file
index 57b02b5..32a071d 100644 (file)
@@ -55,7 +55,7 @@ void remove_fs(const struct block_fs_ops *fs);
 enum block_device_type {
        BLOCK_SCSI_DEV,
        BLOCK_MMC_DEV,
-       BLOCK_MMC_EXTENDED_INTERNAL_DEV,
+       BLOCK_EXTENDEDSD_DEV,
 };
 
 enum mount_state {