Your message dated Fri, 17 Jun 2011 02:01:04 +0200
with message-id <[email protected]>
and subject line Fixed in 2.19.1-1
has caused the Debian Bug report #608120,
regarding Please backport support for fsck -l (whole disk lock)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
608120: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608120
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: util-linux
Version: 2.17.2-5
Severity: wishlist
Tags: patch
User: [email protected]
Usertags: fsck

Hi LaMont,

we'd like to use the new fsck -l (whole disk locking) option in systemd.

Please consider packaging a Git snapshot containing [1] or a cherry-pick
of that commit for the current version in unstable.

I've attached a patch based on [2] for your convenience.

Strictly speaking fsck/base_device.c is no longer necessary, so the
fedora patch removes that file from fsck/Makefile.am and regenerates the
build system.

I decided against that but if you prefer that I can provide and updated
patch for 2.17.2.

Cheers,
Michael



[1] 
http://git.kernel.org/?p=utils/util-linux/util-linux.git;a=commit;h=dd0bd943f94392d165c5903e271c966afb0d7b75
[2]
http://pkgs.fedoraproject.org/gitweb/?p=util-linux-ng.git;a=blob;f=util-linux-ng-2.18-fsck-wholedisk.patch;h=3718255c338f39f00208d3fb4eaceef6dbeb3fcf;hb=refs/heads/master

-- System Information:
Debian Release: 6.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (200, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.32-5-686 (SMP w/1 CPU core)
Locale: LANG=de_DE.utf8, LC_CTYPE=de_DE.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages util-linux depends on:
ii  debconf [debconf-2.0]   1.5.37           Debian configuration management sy
ii  dpkg                    1.15.8.7         Debian package management system
ii  initscripts             2.88dsf-13       scripts for initializing and shutt
ii  install-info            4.13a.dfsg.1-6   Manage installed documentation in 
ii  libblkid1               2.17.2-5         block device id library
ii  libc6                   2.11.2-7         Embedded GNU C Library: Shared lib
ii  libncurses5             5.7+20100313-4   shared libraries for terminal hand
ii  libselinux1             2.0.96-1         SELinux runtime shared libraries
ii  libslang2               2.2.2-4          The S-Lang programming library - r
ii  libuuid1                2.17.2-5         Universally Unique ID library
ii  lsb-base                3.2-26           Linux Standard Base 3.2 init scrip
ii  tzdata                  2010o-1          time zone and daylight-saving time
ii  zlib1g                  1:1.2.3.4.dfsg-3 compression library - runtime

util-linux recommends no packages.

Versions of packages util-linux suggests:
ii  dosfstools                    3.0.9-1    utilities for making and checking 
ii  kbd                           1.15.2-2   Linux console font and keytable ut
pn  util-linux-locales            <none>     (no description available)

-- debconf information excluded
diff -up util-linux-ng-2.18/fsck/fsck.8.kzak util-linux-ng-2.18/fsck/fsck.8
--- util-linux-ng-2.18/fsck/fsck.8.kzak	2010-06-30 12:51:35.000000000 +0200
+++ util-linux-ng-2.18/fsck/fsck.8	2010-10-26 23:55:30.000000000 +0200
@@ -7,7 +7,7 @@
 fsck \- check and repair a Linux file system
 .SH SYNOPSIS
 .B fsck
-.RB [ \-sAVRTMNP ]
+.RB [ \-lsAVRTMNP ]
 .RB [ \-C
 .RI [ fd ]]
 .RB [ \-t
@@ -80,6 +80,17 @@ variable.  Please see the file system-sp
 further details.
 .SH OPTIONS
 .TP
+.B \-l
+Lock whole-disk device by exclusive
+.BR flock (2).
+This option can be used with one device only (e.g. -A and -l are mutually
+exclusive). This option is recommended when more
+.B fsck (8)
+instances are executed in the same time. The option is ignored when used for
+multiple devices or for non-rotating disk. The fsck does not lock underlying
+devices if executed to check stacked devices (e.g. MD or DM) -- this feature is
+not implemented yet.
+.TP
 .B \-s
 Serialize
 .B fsck
@@ -200,6 +211,11 @@ If there are multiple filesystems with t
 fsck will attempt to check them in parallel, although it will avoid running
 multiple filesystem checks on the same physical disk.
 .sp
+.B fsck
+does not check stacked devices (RAIDs, dm-crypt, ...) in parallel with any other
+device. See below for FSCK_FORCE_ALL_PARALLEL setting. The /sys filesystem is
+used to detemine dependencies between devices.
+.sp
 Hence, a very common configuration in
 .I /etc/fstab
 files is to set the root filesystem to have a
@@ -366,10 +382,10 @@ program's behavior is affected by the fo
 .B FSCK_FORCE_ALL_PARALLEL
 If this environment variable is set,
 .B fsck
-will attempt to run all of the specified filesystems in parallel,
-regardless of whether the filesystems appear to be on the same
-device.  (This is useful for RAID systems or high-end storage systems
-such as those sold by companies such as IBM or EMC.)
+will attempt to run all of the specified filesystems in parallel, regardless of
+whether the filesystems appear to be on the same device.  (This is useful for
+RAID systems or high-end storage systems such as those sold by companies such
+as IBM or EMC.) Note that the fs_passno value is still used.
 .TP
 .B FSCK_MAX_INST
 This environment variable will limit the maximum number of file system
diff -up util-linux-ng-2.18/fsck/fsck.c.kzak util-linux-ng-2.18/fsck/fsck.c
--- util-linux-ng-2.18/fsck/fsck.c.kzak	2010-05-19 23:36:23.000000000 +0200
+++ util-linux-ng-2.18/fsck/fsck.c	2010-10-26 23:55:30.000000000 +0200
@@ -31,6 +31,8 @@
 #include <sys/wait.h>
 #include <sys/signal.h>
 #include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -42,6 +44,8 @@
 #include <errno.h>
 #include <malloc.h>
 #include <signal.h>
+#include <dirent.h>
+#include <blkid.h>
 
 #include "fsprobe.h"
 
@@ -85,6 +89,7 @@ char *devices[MAX_DEVICES];
 char *args[MAX_ARGS];
 int num_devices, num_args;
 
+int lockdisk = 0;
 int verbose = 0;
 int doall = 0;
 int noexecute = 0;
@@ -214,11 +219,97 @@ static void parse_escape(char *word)
 	*q = 0;
 }
 
+static dev_t get_disk(const char *device)
+{
+	struct stat st;
+	dev_t disk;
+
+	if (!stat(device, &st) &&
+	    !blkid_devno_to_wholedisk(st.st_rdev, NULL, 0, &disk))
+		return disk;
+
+	return 0;
+}
+
+static int is_irrotational_disk(dev_t disk)
+{
+	char path[PATH_MAX];
+	FILE *f;
+	int rc, x;
+
+	rc = snprintf(path, sizeof(path),
+			"/sys/dev/block/%d:%d/queue/rotational",
+			major(disk), minor(disk));
+
+	if (rc < 0 || rc + 1 > sizeof(path))
+		return 0;
+
+	f = fopen(path, "r");
+	if (!f)
+		return 0;
+
+	rc = fscanf(f, "%u", &x);
+	fclose(f);
+
+	return rc == 1 ? !x : 0;
+}
+
+static void lock_disk(struct fsck_instance *inst)
+{
+	dev_t disk = inst->fs->disk ? : get_disk(inst->fs->device);
+	char *diskname;
+
+	if (!disk || is_irrotational_disk(disk))
+		return;
+
+	diskname = blkid_devno_to_devname(disk);
+	if (!diskname)
+		return;
+
+	if (verbose)
+		printf(_("Locking disk %s ... "), diskname);
+
+	inst->lock = open(diskname, O_CLOEXEC | O_RDONLY);
+	if (inst->lock >= 0) {
+		int rc = -1;
+
+		/* inform users that we're waiting on the lock */
+		if (verbose &&
+		    (rc = flock(inst->lock, LOCK_EX | LOCK_NB)) != 0 &&
+		    errno == EWOULDBLOCK)
+			printf(_("(waiting) "));
+
+		if (rc != 0 && flock(inst->lock, LOCK_EX) != 0) {
+			close(inst->lock);			/* failed */
+			inst->lock = -1;
+		}
+	}
+
+	if (verbose)
+		printf("%s.\n", inst->lock >= 0 ? _("success") : _("failed"));
+
+	free(diskname);
+	return;
+}
+
+static void unlock_disk(struct fsck_instance *inst)
+{
+	if (inst->lock >= 0) {
+		/* explicitly unlock, don't rely on close(), maybe some library
+		 * (e.g. liblkid) has still open the device.
+		 */
+		flock(inst->lock, LOCK_UN);
+		close(inst->lock);
+	}
+}
+
+
+
 static void free_instance(struct fsck_instance *i)
 {
+	if (lockdisk)
+		unlock_disk(i);
 	free(i->prog);
-	free(i->device);
-	free(i->base_device);
 	free(i);
 	return;
 }
@@ -240,6 +331,8 @@ static struct fs_info *create_fs_device(
 	fs->passno = passno;
 	fs->flags = 0;
 	fs->next = NULL;
+	fs->disk = 0;
+	fs->stacked = 0;
 
 	if (!filesys_info)
 		filesys_info = fs;
@@ -414,8 +507,7 @@ static int progress_active(NOARGS)
  * Execute a particular fsck program, and link it into the list of
  * child processes we are waiting for.
  */
-static int execute(const char *type, const char *device, const char *mntpt,
-		   int interactive)
+static int execute(const char *type, struct fs_info *fs, int interactive)
 {
 	char *s, *argv[80], prog[80];
 	int  argc, i;
@@ -452,7 +544,7 @@ static int execute(const char *type, con
 		}
 	}
 
-	argv[argc++] = string_copy(device);
+	argv[argc++] = string_copy(fs->device);
 	argv[argc] = 0;
 
 	s = find_fsck(prog);
@@ -464,12 +556,19 @@ static int execute(const char *type, con
 
 	if (verbose || noexecute) {
 		printf("[%s (%d) -- %s] ", s, num_running,
-		       mntpt ? mntpt : device);
+		       fs->mountpt ? fs->mountpt : fs->device);
 		for (i=0; i < argc; i++)
 			printf("%s ", argv[i]);
 		printf("\n");
 	}
 
+
+	inst->fs = fs;
+	inst->lock = -1;
+
+	if (lockdisk)
+		lock_disk(inst);
+
 	/* Fork and execute the correct program. */
 	if (noexecute)
 		pid = -1;
@@ -492,8 +591,6 @@ static int execute(const char *type, con
 	inst->pid = pid;
 	inst->prog = string_copy(prog);
 	inst->type = string_copy(type);
-	inst->device = string_copy(device);
-	inst->base_device = base_device(device);
 	inst->start_time = time(0);
 	inst->next = NULL;
 
@@ -597,12 +694,12 @@ static struct fsck_instance *wait_one(in
 		} else {
 			printf(_("Warning... %s for device %s exited "
 			       "with signal %d.\n"),
-			       inst->prog, inst->device, sig);
+			       inst->prog, inst->fs->device, sig);
 			status = EXIT_ERROR;
 		}
 	} else {
 		printf(_("%s %s: status is %x, should never happen.\n"),
-		       inst->prog, inst->device, status);
+		       inst->prog, inst->fs->device, status);
 		status = EXIT_ERROR;
 	}
 	inst->exit_status = status;
@@ -641,7 +738,7 @@ ret_inst:
 		instance_list = inst->next;
 	if (verbose > 1)
 		printf(_("Finished with %s (exit status %d)\n"),
-		       inst->device, inst->exit_status);
+		       inst->fs->device, inst->exit_status);
 	num_running--;
 	return inst;
 }
@@ -698,7 +795,7 @@ static void fsck_device(struct fs_info *
 		type = DEFAULT_FSTYPE;
 
 	num_running++;
-	retval = execute(type, fs->device, fs->mountpt, interactive);
+	retval = execute(type, fs, interactive);
 	if (retval) {
 		fprintf(stderr, _("%s: Error %d while executing fsck.%s "
 			"for %s\n"), progname, retval, type, fs->device);
@@ -924,40 +1021,70 @@ static int ignore(struct fs_info *fs)
 	return 0;
 }
 
+static int count_slaves(dev_t disk)
+{
+	DIR *dir;
+	struct dirent *dp;
+	char dirname[PATH_MAX];
+	int count = 0;
+
+	snprintf(dirname, sizeof(dirname),
+			"/sys/dev/block/%u:%u/slaves/",
+			major(disk), minor(disk));
+
+	if (!(dir = opendir(dirname)))
+		return -1;
+
+	while ((dp = readdir(dir)) != 0) {
+#ifdef _DIRENT_HAVE_D_TYPE
+		if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
+			continue;
+#endif
+		if (dp->d_name[0] == '.' &&
+		    ((dp->d_name[1] == 0) ||
+		     ((dp->d_name[1] == '.') && (dp->d_name[2] == 0))))
+			continue;
+
+		count++;
+	}
+	closedir(dir);
+	return count;
+}
+
 /*
  * Returns TRUE if a partition on the same disk is already being
  * checked.
  */
-static int device_already_active(char *device)
+static int disk_already_active(struct fs_info *fs)
 {
 	struct fsck_instance *inst;
-	char *base;
 
 	if (force_all_parallel)
 		return 0;
 
-#ifdef BASE_MD
-	/* Don't check a soft raid disk with any other disk */
-	if (instance_list &&
-	    (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
-	     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
+	if (instance_list && instance_list->fs->stacked)
+		/* any instance for a stacked device is already running */
 		return 1;
-#endif
 
-	base = base_device(device);
+	if (!fs->disk) {
+		fs->disk = get_disk(fs->device);
+		if (fs->disk)
+			fs->stacked = count_slaves(fs->disk);
+	}
+
 	/*
 	 * If we don't know the base device, assume that the device is
 	 * already active if there are any fsck instances running.
+	 *
+	 * Don't check a stacked device with any other disk too.
 	 */
-	if (!base)
+	if (!fs->disk || fs->stacked)
 		return (instance_list != 0);
+
 	for (inst = instance_list; inst; inst = inst->next) {
-		if (!inst->base_device || !strcmp(base, inst->base_device)) {
-			free(base);
+		if (!inst->fs->disk || fs->disk == inst->fs->disk)
 			return 1;
-		}
 	}
-	free(base);
 	return 0;
 }
 
@@ -1038,7 +1165,7 @@ static int check_all(NOARGS)
 			 * already been spawned, then we need to defer
 			 * this to another pass.
 			 */
-			if (device_already_active(fs->device)) {
+			if (disk_already_active(fs)) {
 				pass_done = 0;
 				continue;
 			}
@@ -1188,6 +1315,9 @@ static void PRS(int argc, char *argv[])
 					}
 				}
 				break;
+			case 'l':
+				lockdisk++;
+				break;
 			case 'V':
 				verbose++;
 				break;
@@ -1298,6 +1428,12 @@ int main(int argc, char *argv[])
 	if ((num_devices == 1) || (serialize))
 		interactive = 1;
 
+	if (lockdisk && (doall || num_devices > 1)) {
+		fprintf(stderr, _("%s: the -l option can be used with one "
+				  "device only -- ignore\n"), progname);
+		lockdisk = 0;
+	}
+
 	/* If -A was specified ("check all"), do that! */
 	if (doall)
 		return check_all();
diff -up util-linux-ng-2.18/fsck/fsck.h.kzak util-linux-ng-2.18/fsck/fsck.h
--- util-linux-ng-2.18/fsck/fsck.h.kzak	2010-03-18 23:11:23.000000000 +0100
+++ util-linux-ng-2.18/fsck/fsck.h	2010-10-26 23:55:30.000000000 +0200
@@ -44,6 +44,8 @@ struct fs_info {
 	int   freq;
 	int   passno;
 	int   flags;
+	dev_t disk;
+	int   stacked;
 	struct fs_info *next;
 };
 
@@ -56,12 +58,12 @@ struct fs_info {
 struct fsck_instance {
 	int	pid;
 	int	flags;
+	int	lock;		/* flock()ed whole disk file descriptor or -1 */
 	int	exit_status;
 	time_t	start_time;
 	char *	prog;
 	char *	type;
-	char *	device;
-	char *	base_device;
+	struct fs_info *fs;
 	struct fsck_instance *next;
 };
 

--- End Message ---
--- Begin Message ---
Version: Fixed in 2.19.1-1
-- 
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?

Attachment: signature.asc
Description: OpenPGP digital signature


--- End Message ---

Reply via email to