public inbox for util-linux@vger.kernel.org
 help / color / mirror / Atom feed
From: Alun <alun.linux@ty-penguin.org.uk>
To: kzak@redhat.com
Cc: util-linux@vger.kernel.org
Subject: [PATCH] Add option to fsfreeze to call syncfs() prior to freezing.
Date: Fri, 7 Dec 2012 10:14:00 +0000	[thread overview]
Message-ID: <20121207101400.5e46ba48@pcebbj.staff.aber.ac.uk> (raw)

Hi,

I've recently been looking into a problem on a heavily loaded fileserver.
Running fsfreeze on the filesystem causes the load average to go sky high.
Looking at the kernel sources, I discovered that the FIFREEZE ioctl suspends
writes, then syncs the filesystem. With a large amount of dirty data, this
can leave writes suspended for a significant time, even if your intent is to
have the filesystem frozen for a short time. I raised this on the kernel
list, suggesting an extra call to sync the filesystem prior to suspending
writes, but it was pointed out to me that this would change the semantics
of the ioctl.

Adding a call to syncfs() prior to freezing the filesystem will achieve
the same result, so I'm proposing the following patch which adds a "-s"
option to fsfreeze which, when specified, will cause it to call syncfs
on the filesystem. You can use it by itself to cause a filesystem sync,
or in combination with -f to sync, then freeze the filesystem.

Signed-off-by: Alun Jones <alun.linux@ty-penguin.org.uk>

diff --git a/sys-utils/fsfreeze.8 b/sys-utils/fsfreeze.8
index 7693861..0d73afe 100644
--- a/sys-utils/fsfreeze.8
+++ b/sys-utils/fsfreeze.8
@@ -1,5 +1,5 @@
 .\" -*- nroff -*-
-.TH FSFREEZE 8 "May 2010" "util-linux" "System Administration"
+.TH FSFREEZE 8 "December 2012" "util-linux" "System Administration"
 .SH NAME
 fsfreeze \- suspend access to a filesystem (Linux Ext3/4, ReiserFS, JFS, XFS)
 .SH SYNOPSIS
@@ -9,6 +9,9 @@ fsfreeze \- suspend access to a filesystem (Linux Ext3/4, ReiserFS, JFS, XFS)
 .B fsfreeze \-u
 .I mountpoint
 
+.B fsfreeze \-s
+.I mountpoint
+
 .SH DESCRIPTION
 .B fsfreeze
 suspends and resumes access to an filesystem
@@ -53,6 +56,14 @@ or a clean mount of the snapshot is complete.
 This option is used to un-freeze the filesystem and allow operations to
 continue.  Any filesystem modifications that were blocked by the freeze are
 unblocked and allowed to complete.
+.IP "\fB\-s, \-\-sync\fP
+This option, if specified, will cause fsfreeze to call syncfs() on the 
+filesystem. It can be combined with -f to force dirty data to be written prior
+to the freeze operation. On a filesystem with heavy write load, adding this
+option will very likely reduce the time during which writes are suspended,
+at the cost of a delay before suspending writes. Therefore, if it's critical
+to reduce the time for which the filesystem is frozen, use this option; if 
+it's critical to freeze the filesystem at a specific moment, don't use it.
 .SH AUTHOR
 .PP
 Written by Hajime Taira.
diff --git a/sys-utils/fsfreeze.c b/sys-utils/fsfreeze.c
index 7161442..5a473fd 100644
--- a/sys-utils/fsfreeze.c
+++ b/sys-utils/fsfreeze.c
@@ -44,6 +44,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
 
 	fputs(_("\nOptions:\n"), out);
 	fputs(_(" -h, --help        this help\n"
+		" -s, --sync        sync the filesystem\n"
 		" -f, --freeze      freeze the filesystem\n"
 		" -u, --unfreeze    unfreeze the filesystem\n"), out);
 
@@ -56,6 +57,7 @@ int main(int argc, char **argv)
 {
 	int fd = -1, c;
 	int freeze = -1, rc = EXIT_FAILURE;
+	int dosync = -1;
 	char *path;
 	struct stat sb;
 
@@ -63,6 +65,7 @@ int main(int argc, char **argv)
 	    { "help",      0, 0, 'h' },
 	    { "freeze",    0, 0, 'f' },
 	    { "unfreeze",  0, 0, 'u' },
+	    { "sync",      0, 0, 's' },
 	    { NULL,        0, 0, 0 }
 	};
 
@@ -71,7 +74,7 @@ int main(int argc, char **argv)
 	textdomain(PACKAGE);
 	atexit(close_stdout);
 
-	while ((c = getopt_long(argc, argv, "hfu", longopts, NULL)) != -1) {
+	while ((c = getopt_long(argc, argv, "hfus", longopts, NULL)) != -1) {
 		switch(c) {
 		case 'h':
 			usage(stdout);
@@ -82,13 +85,16 @@ int main(int argc, char **argv)
 		case 'u':
 			freeze = FALSE;
 			break;
+		case 's':
+			dosync = TRUE;
+			break;
 		default:
 			usage(stderr);
 			break;
 		}
 	}
 
-	if (freeze == -1)
+	if (freeze == -1 && dosync == -1)
 		errx(EXIT_FAILURE, _("no action specified"));
 	if (optind == argc)
 		errx(EXIT_FAILURE, _("no filename specified"));
@@ -113,12 +119,19 @@ int main(int argc, char **argv)
 		goto done;
 	}
 
-	if (freeze) {
+	if (dosync) {
+		if (syncfs(fd)) {
+			warn(_("%s: syncfs failed"), path);
+			goto done;
+		}
+	}
+
+	if (freeze == TRUE) {
 		if (freeze_f(fd)) {
 			warn(_("%s: freeze failed"), path);
 			goto done;
 		}
-	} else {
+	} else if (freeze == FALSE) {
 		if (unfreeze_f(fd)) {
 			warn(_("%s: unfreeze failed"), path);
 			goto done;

             reply	other threads:[~2012-12-07 11:09 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-07 10:14 Alun [this message]
2012-12-07 11:17 ` [PATCH] Add option to fsfreeze to call syncfs() prior to freezing Alun
2012-12-07 12:44 ` Christoph Hellwig
2012-12-07 12:50   ` Alun
2012-12-08 12:47     ` Christoph Hellwig
2012-12-08 19:46       ` Alun
2013-03-20 13:28         ` Karel Zak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121207101400.5e46ba48@pcebbj.staff.aber.ac.uk \
    --to=alun.linux@ty-penguin.org.uk \
    --cc=kzak@redhat.com \
    --cc=util-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox