diff options
-rw-r--r-- | daemon/daemon.h | 1 | ||||
-rw-r--r-- | daemon/ext2.c | 37 | ||||
-rw-r--r-- | daemon/mount.c | 43 | ||||
-rw-r--r-- | generator/generator_actions.ml | 13 | ||||
-rw-r--r-- | resize/resize.ml | 4 |
5 files changed, 84 insertions, 14 deletions
diff --git a/daemon/daemon.h b/daemon/daemon.h index c45a7fe1..b515fe4f 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -111,6 +111,7 @@ extern uint64_t optargs_bitmask; /*-- in mount.c --*/ extern int is_root_mounted (void); +extern int is_device_mounted (const char *device); /*-- in stubs.c (auto-generated) --*/ extern void dispatch_incoming_message (XDR *); diff --git a/daemon/ext2.c b/daemon/ext2.c index a427d7a1..09037fb1 100644 --- a/daemon/ext2.c +++ b/daemon/ext2.c @@ -187,6 +187,34 @@ do_get_e2uuid (const char *device) return do_vfs_uuid (device); } +/* If the filesystem is not mounted, run e2fsck -f on it unconditionally. */ +static int +if_not_mounted_run_e2fsck (const char *device) +{ + char *err; + int r, mounted; + char prog[] = "e2fsck"; + + if (e2prog (prog) == -1) + return -1; + + mounted = is_device_mounted (device); + if (mounted == -1) + return -1; + + if (!mounted) { + r = command (NULL, &err, prog, "-fy", device, NULL); + if (r == -1) { + reply_with_error ("%s", err); + free (err); + return -1; + } + free (err); + } + + return 0; +} + int do_resize2fs (const char *device) { @@ -197,6 +225,9 @@ do_resize2fs (const char *device) if (e2prog (prog) == -1) return -1; + if (if_not_mounted_run_e2fsck (device) == -1) + return -1; + r = command (NULL, &err, prog, device, NULL); if (r == -1) { reply_with_error ("%s", err); @@ -229,6 +260,9 @@ do_resize2fs_size (const char *device, int64_t size) } size /= 1024; + if (if_not_mounted_run_e2fsck (device) == -1) + return -1; + char buf[32]; snprintf (buf, sizeof buf, "%" PRIi64 "K", size); @@ -253,6 +287,9 @@ do_resize2fs_M (const char *device) if (e2prog (prog) == -1) return -1; + if (if_not_mounted_run_e2fsck (device) == -1) + return -1; + r = command (NULL, &err, prog, "-M", device, NULL); if (r == -1) { reply_with_error ("%s", err); diff --git a/daemon/mount.c b/daemon/mount.c index 98b94889..0c393f7a 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -65,6 +65,49 @@ is_root_mounted (void) return 0; } +/* Return true iff 'device' is mounted under /sysroot. + * 1 : true, device is mounted + * 0 : false, device is not mounted + * -1 : error, reply_with_* has been called + */ +int +is_device_mounted (const char *device) +{ + FILE *fp; + struct mntent *m; + struct stat stat1, stat2; + + if (stat (device, &stat1) == -1) { + reply_with_perror ("stat: %s", device); + return -1; + } + + /* NB: Eventually we should aim to parse /proc/self/mountinfo, but + * that requires custom parsing code. + */ + fp = setmntent ("/proc/mounts", "r"); + if (fp == NULL) { + perror ("/proc/mounts"); + exit (EXIT_FAILURE); + } + + while ((m = getmntent (fp)) != NULL) { + if ((sysroot_len > 0 && STREQ (m->mnt_dir, sysroot)) || + (STRPREFIX (m->mnt_dir, sysroot) && m->mnt_dir[sysroot_len] == '/')) { + if (stat (m->mnt_fsname, &stat2) == 0) { + if (stat1.st_rdev == stat2.st_rdev) { + /* found it */ + endmntent (fp); + return 1; + } + } + } + } + + endmntent (fp); + return 0; +} + /* The "simple mount" call offers no complex options, you can just * mount a device on a mountpoint. The variations like mount_ro, * mount_options and mount_vfs let you set progressively more things. diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml index b859e5fe..3c87d6db 100644 --- a/generator/generator_actions.ml +++ b/generator/generator_actions.ml @@ -3502,13 +3502,7 @@ is lost."); "resize an ext2, ext3 or ext4 filesystem", "\ This resizes an ext2, ext3 or ext4 filesystem to match the size of -the underlying device. - -I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f> -on the C<device> before calling this command. For unknown reasons -C<resize2fs> sometimes gives an error about this and sometimes not. -In any case, it is always safe to call C<guestfs_e2fsck_f> before -calling this function."); +the underlying device."); ("find", (RStringList "names", [Pathname "directory"], []), 107, [ProtocolLimitWarning], [InitBasicFS, Always, TestOutputList ( @@ -3557,10 +3551,7 @@ See also C<guestfs_find0>."); "\ This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3 filesystem checker on C<device>, noninteractively (I<-p>), -even if the filesystem appears to be clean (I<-f>). - -This command is only needed because of C<guestfs_resize2fs> -(q.v.). Normally you should use C<guestfs_fsck>."); +even if the filesystem appears to be clean (I<-f>)."); ("sleep", (RErr, [Int "secs"], []), 109, [], [InitNone, Always, TestRun ( diff --git a/resize/resize.ml b/resize/resize.ml index 675a6e1c..407d80f3 100644 --- a/resize/resize.ml +++ b/resize/resize.ml @@ -1120,9 +1120,7 @@ let () = (* Helper function to expand partition or LV content. *) let do_expand_content target = function | PVResize -> g#pvresize target - | Resize2fs -> - g#e2fsck_f target; - g#resize2fs target + | Resize2fs -> g#resize2fs target | NTFSResize -> g#ntfsresize_opts ~force:ntfsresize_force target | BtrfsFilesystemResize -> (* Complicated ... Btrfs forces us to mount the filesystem |