X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fdevice-handler.c;h=cd9c41386ea07bdaa9762f75ac3ec81648c5b280;hp=251c517f884aaa0c2212898b2e71dd3ad37a8e9e;hb=b201464a18c990ea6df0f2878e532618d4936c53;hpb=ffc167572a9d56c52908aebefe62ba3e3e2a9cf8 diff --git a/discover/device-handler.c b/discover/device-handler.c index 251c517..cd9c413 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -1,9 +1,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -677,6 +679,58 @@ 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) { + pb_debug("%s: %s is already mounted at %s\n" + __func__, dev->device_path, + mnt->mnt_dir); + dev->mount_path = talloc_strdup(dev, mnt->mnt_dir); + dev->mounted = true; + dev->unmount = false; + break; + } + } + + fclose(fp); + + return mnt != NULL; +} + static int mount_device(struct discover_device *dev) { int rc; @@ -684,29 +738,44 @@ 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; + + dev->mount_path = join_paths(dev, mount_base(), + dev->device_path); - if (pb_mkdir_recursive(dev->mount_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->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->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 +783,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,6 +792,10 @@ static int umount_device(struct discover_device *dev) if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return -1; + dev->mounted = false; + talloc_free(dev->mount_path); + dev->mount_path = NULL; + pb_rmdir_recursive(mount_base(), dev->mount_path); return 0;