Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Oct 2016 05:29:48 +0000
From:      Hongjiang Zhang <honzhan@microsoft.com>
To:        =?utf-8?B?RWR3YXJkIFRvbWFzeiBOYXBpZXJhxYJh?= <trasz@FreeBSD.org>
Cc:        "freebsd-fs@freebsd.org" <freebsd-fs@freebsd.org>, Mateusz Guzik <mjguzik@gmail.com>
Subject:   RE: ufs freeze does not work
Message-ID:  <CY1PR03MB151713BEF58B75BB4850F578B5DD0@CY1PR03MB1517.namprd03.prod.outlook.com>
In-Reply-To: <20160629043203.GA82400@brick>
References:  <CO2PR03MB2215FAA1AB86A669039B9540B5210@CO2PR03MB2215.namprd03.prod.outlook.com> <20160628065432.GA20716@brick> <SN2PR03MB2224903F61C7DD576EDDB05DB5220@SN2PR03MB2224.namprd03.prod.outlook.com> <20160628185523.GA82035@brick> <20160628195731.GA21323@dft-labs.eu> <20160629043203.GA82400@brick>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi Edward,

I have another question about UFS suspend. Shall I call "sync" before freezing the fs? See it in my code. 
Another question is do you think it is necessary for FreeBSD to provide a such tool? Is there any stat tool for user to know which file partition is freezed?

sync(); // Is this necessary?
error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid);

Thanks
Hongjiang Zhang

-----Original Message-----
From: Edward Tomasz Napierała [mailto:etnapierala@gmail.com] On Behalf Of Edward Tomasz Napierala
Sent: Wednesday, June 29, 2016 12:32 PM
To: Mateusz Guzik <mjguzik@gmail.com>
Cc: Hongjiang Zhang <honzhan@microsoft.com>; freebsd-fs@freebsd.org
Subject: Re: ufs freeze does not work

On 0628T2157, Mateusz Guzik wrote:
> On Tue, Jun 28, 2016 at 08:55:23PM +0200, Edward Tomasz Napierała wrote:
> > As I said, the suspension is released when the ufssuspend file 
> > descriptor gets closed - which is what happens when the calling 
> > process exits.  It's a protection mechanism, to avoid the situation 
> > where the process malfunction (eg a crash) would leave the system in unrecoverable (suspended) state.
> > 
> > You probably want your process to just execute another one, and wait 
> > until it exits.
> > 
> 
> The example with freeze -f strongly hints this is supposed to work as 
> a drop in replacement for linux scripts.
> 
> As such, maybe ufs should grow another operation which does not 
> automagically unfreeze.

I'm not sure it's a good idea to provide an inferior mechanism just for backward compatibility with Linux.  Especially given how easy it is to do it properly, modeling the utility after eg lockf(1).


[-- Attachment #2 --]
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <err.h>
#include <fcntl.h>
#include <ufs/ffs/fs.h>
#define	_PATH_UFSSUSPEND	"/dev/ufssuspend"
#define UNDEF_FREEZE_THAW    (0)
#define FREEZE               (1)
#define THAW                 (2)
#define SLEEP_TIME		(10)

static int
test_write_tmp(const char* p)
{
	int ret = 0;
	char data[] = "abcdefghij";
	char filename[64];
	const char *test_file = "test_freeze";
	if (p != NULL) {
		snprintf(filename, sizeof(filename), "%s/%s", p, test_file);
	} else {
		snprintf(filename, sizeof(filename), "/tmp/%s", test_file);
	}
	FILE *fp = fopen(filename, "rw+");
	if (!fp) {
		ret = 1;
		printf("Fail to open");
		goto error;
	}
	int len = 5;
	int writelen = fwrite(data, sizeof(char), len, fp);
	if (writelen != len) {
		ret = 2;
		printf("Fail to write the %d character\n", len);
		goto error;
	}
	fclose(fp);
	return 0;
error:
	printf("error in test_write_tmp\n");
	return ret;
}

static void freeze(const char* partition, int duration)
{
	struct statfs *mntbuf, *statfsp;
	int mntsize;
	int fso;
	int error = 0;
	int i;
	int write_test_rtn = 0;
	const char *dev = "/dev";

	fso = open(_PATH_UFSSUSPEND, O_RDWR);
	if (fso == -1)
		err(1, "unable to open %s", _PATH_UFSSUSPEND);	
	/*
	 * First check the mounted filesystems.
	 */
	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
	if (mntsize == 0)
		return;

	printf("mnt size: %d\n", mntsize);
	for(i = mntsize - 1; i >= 0; --i)
	{
		statfsp = &mntbuf[i];
		printf("fstype: %s, on '%s' from '%s'\n",
			statfsp->f_fstypename,
			statfsp->f_mntonname, statfsp->f_mntfromname);
		if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0) {
			continue; /* skip to freeze '/dev' */
		} else if (statfsp->f_flags & MNT_RDONLY) {
			continue; /* skip to freeze RDONLY partition */
		} else if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0) {
			continue; /* only UFS can be freezed */
		}
		sync();

		if ((partition == NULL && strcmp("/", statfsp->f_mntonname) == 0) ||
		    (partition != NULL && strncmp(statfsp->f_mntonname,
		    partition, strlen(partition)) == 0)) {
			if (partition == NULL) {
				partition = statfsp->f_mntonname;
			}
			printf("begin to suspend on '%s'\n", partition);
			
			error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid);
			if (error != 0) {
				printf("error: %d\n",errno);
			} else {
				printf("Successfully suspend filesystem\n");
			}
			break;
		}
	}
	if (error == 0) {
		sleep(duration); /* how long time to freeze */
		write_test_rtn = test_write_tmp(partition);
		if (!write_test_rtn) {
			printf("Successfully write something\n");
		}
	}
	close(fso); /* Stop freeze once the file handle is closed */
}

static void usage(const char* cmd) {
	fprintf(stderr, "%s -f : freeze the root filesystem\n"
		/* " -t : thaw the filesystem\n" */
		" -F <partition> : freeze the specified partition\n"
		" -d <duration> : specify the duration (s) for freezing\n",
		 cmd);
	exit(1);
}

int main(int argc, char* argv[]) {
	int ch;
	int freeze_thaw = UNDEF_FREEZE_THAW;
	const char* partition = NULL;
	int freeze_dur = SLEEP_TIME;
	while ((ch = getopt(argc, argv, "F:d:f")) != -1) {
		switch (ch) {
		case 'f':
			/* Run as regular process for debugging purpose. */
			freeze_thaw = FREEZE;
			break;
		case 'F':
			freeze_thaw = FREEZE;
			partition = optarg;
			break;
		case 'd':
			freeze_dur = (int)strtol(optarg, NULL, 10);
			break;
		default:
			break;
		}
	}
	if (freeze_thaw == FREEZE) {
		freeze(partition, freeze_dur);
	} else {
		usage(argv[0]);
	}
	return 0;
}

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CY1PR03MB151713BEF58B75BB4850F578B5DD0>