summaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-03-09 16:53:02 +0000
committerRichard W.M. Jones <rjones@redhat.com>2012-03-09 18:05:31 +0000
commit2fb545b840745f6d944d89872f1d7372821b30cc (patch)
tree1c40d7dd5d7e5976234c4c844ae010ecfd38a523 /daemon
parent4c9218658e4d4b769acaa41d999b4bce437fbc37 (diff)
downloadlibguestfs-2fb545b840745f6d944d89872f1d7372821b30cc.tar.gz
libguestfs-2fb545b840745f6d944d89872f1d7372821b30cc.tar.xz
libguestfs-2fb545b840745f6d944d89872f1d7372821b30cc.zip
resize2fs: Run 'e2fsck -f' automatically if filesystem is not mounted.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/daemon.h1
-rw-r--r--daemon/ext2.c37
-rw-r--r--daemon/mount.c43
3 files changed, 81 insertions, 0 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.