X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fdevice-handler.c;h=94abb514ab02f4ecd7c6f53aca81a94f7b8afb2f;hp=251c517f884aaa0c2212898b2e71dd3ad37a8e9e;hb=96eedc649c8c0909a564787afebcfbe0588fd651;hpb=995e08e3de9aaff81e72227587ffcb4cc78175d0 diff --git a/discover/device-handler.c b/discover/device-handler.c index 251c517..94abb51 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -1,9 +1,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -518,6 +520,7 @@ struct discover_context *device_handler_discover_context_create( ctx = talloc(handler, struct discover_context); ctx->device = device; ctx->conf_url = NULL; + ctx->test_data = NULL; list_init(&ctx->boot_options); return ctx; @@ -584,13 +587,16 @@ int device_handler_discover(struct device_handler *handler, struct discover_device *dev, enum conf_method method) { struct discover_context *ctx; + int rc; process_boot_option_queue(handler); /* create our context */ ctx = device_handler_discover_context_create(handler, dev); - mount_device(dev); + rc = mount_device(dev); + if (rc) + goto out; /* run the parsers. This will populate the ctx's boot_option list. */ iterate_parsers(ctx, method); @@ -598,6 +604,7 @@ int device_handler_discover(struct device_handler *handler, /* add discovered stuff to the handler */ device_handler_discover_context_commit(handler, ctx); +out: talloc_free(ctx); return 0; @@ -677,6 +684,61 @@ void device_handler_cancel_default(struct device_handler *handler) } #ifndef PETITBOOT_TEST +static bool check_existing_mount(struct discover_device *dev) +{ + struct stat devstat, mntstat; + struct mntent *mnt; + FILE *fp; + int rc; + + rc = stat(dev->device_path, &devstat); + if (rc) { + pb_debug("%s: stat failed: %s\n", __func__, strerror(errno)); + return false; + } + + if (!S_ISBLK(devstat.st_mode)) { + pb_debug("%s: %s isn't a block device?\n", __func__, + dev->device_path); + return false; + } + + fp = fopen("/proc/self/mounts", "r"); + + for (;;) { + mnt = getmntent(fp); + if (!mnt) + break; + + if (!mnt->mnt_fsname || mnt->mnt_fsname[0] != '/') + continue; + + rc = stat(mnt->mnt_fsname, &mntstat); + if (rc) + continue; + + if (!S_ISBLK(mntstat.st_mode)) + continue; + + if (mntstat.st_rdev == devstat.st_rdev) { + dev->mount_path = talloc_strdup(dev, mnt->mnt_dir); + dev->mounted_rw = !!hasmntopt(mnt, "rw"); + dev->mounted = true; + dev->unmount = false; + + pb_debug("%s: %s is already mounted (r%c) at %s\n", + __func__, dev->device_path, + dev->mounted_rw ? 'w' : 'o', + mnt->mnt_dir); + break; + } + } + + fclose(fp); + + return mnt != NULL; +} + static int mount_device(struct discover_device *dev) { int rc; @@ -684,29 +746,46 @@ static int mount_device(struct discover_device *dev) if (!dev->device_path) return -1; - if (!dev->mount_path) - dev->mount_path = join_paths(dev, mount_base(), - dev->device_path); + if (dev->mounted) + return 0; + + if (check_existing_mount(dev)) + return 0; - if (pb_mkdir_recursive(dev->mount_path)) + dev->mount_path = join_paths(dev, mount_base(), + dev->device_path); + + if (pb_mkdir_recursive(dev->mount_path)) { pb_log("couldn't create mount directory %s: %s\n", dev->mount_path, strerror(errno)); + goto err_free; + } rc = process_run_simple(dev, pb_system_apps.mount, dev->device_path, dev->mount_path, "-o", "ro", NULL); - - if (!rc) + if (!rc) { + dev->mounted = true; + dev->mounted_rw = false; + dev->unmount = true; return 0; + } /* Retry mount without ro option. */ rc = process_run_simple(dev, pb_system_apps.mount, dev->device_path, dev->mount_path, NULL); - if (!rc) + if (!rc) { + dev->mounted = true; + dev->mounted_rw = true; + dev->unmount = true; return 0; + } pb_rmdir_recursive(mount_base(), dev->mount_path); +err_free: + talloc_free(dev->mount_path); + dev->mount_path = NULL; return -1; } @@ -714,7 +793,7 @@ static int umount_device(struct discover_device *dev) { int status; - if (!dev->mount_path) + if (!dev->mounted || !dev->unmount) return 0; status = process_run_simple(dev, pb_system_apps.umount, @@ -723,10 +802,48 @@ static int umount_device(struct discover_device *dev) if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return -1; + dev->mounted = false; + pb_rmdir_recursive(mount_base(), dev->mount_path); + talloc_free(dev->mount_path); + dev->mount_path = NULL; + + return 0; +} + +int device_request_write(struct discover_device *dev, bool *release) +{ + int rc; + + *release = false; + + if (!dev->mounted) + return -1; + + if (dev->mounted_rw) + return 0; + + rc = process_run_simple(dev, pb_system_apps.mount, dev->mount_path, + "-o", "remount,rw", NULL); + if (rc) + return -1; + + dev->mounted_rw = true; + *release = true; return 0; } + +void device_release_write(struct discover_device *dev, bool release) +{ + if (!release) + return; + + process_run_simple(dev, pb_system_apps.mount, dev->mount_path, + "-o", "remount,ro", NULL); + dev->mounted_rw = false; +} + #else static int umount_device(struct discover_device *dev __attribute__((unused))) @@ -740,5 +857,17 @@ static int __attribute__((unused)) mount_device( return 0; } +int device_request_write(struct discover_device *dev __attribute__((unused)), + bool *release) +{ + *release = true; + return 0; +} + +void device_release_write(struct discover_device *dev __attribute__((unused)), + bool release __attribute__((unused))) +{ +} + #endif