aboutsummaryrefslogtreecommitdiff
path: root/tools/test/stress2/misc/ufssuspend.sh
blob: b4c86490fe259a177031298122bbadd664067586 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/sh

# ioctl(g_ufs_suspend_handle, UFSSUSPEND, &statfsp->f_fsid) test scenario.

# Bug 230220 - UFS: the freezing ioctl (i.e.UFSSUSPEND) causes panic or EBUSY
# "panic: devfs_set_cdevpriv failed" seen.
# Test scenario by Dexuan Cui <decui microsoft com>
# Fixed by r337055.

[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1
. ../default.cfg

cat > /tmp/ufssuspend.c <<EOF

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>

#include <ufs/ffs/fs.h>

#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <poll.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <syslog.h>
#include <unistd.h>

static int g_ufs_suspend_handle = -1;
static const char *dev = "/dev";

static int
freeze(void)
{
	struct statfs *mntbuf, *statfsp;
	int mntsize;
	int error = 0;
	int i;

	g_ufs_suspend_handle = open(_PATH_UFSSUSPEND, O_RDWR);
	if (g_ufs_suspend_handle == -1) {
		printf("unable to open %s", _PATH_UFSSUSPEND);
		return (errno);
	}

	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
	if (mntsize == 0) {
		printf("There is no mount information\n");
		return (EINVAL);
	}

	for (i = mntsize - 1; i >= 0; --i) {
		statfsp = &mntbuf[i];

		if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0)
			continue; /* skip to freeze '/dev' */

		if (statfsp->f_flags & MNT_RDONLY)
			continue; /* skip to freeze RDONLY partition */

		if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0)
			continue; /* so far, only UFS can be frozen */

		printf("suspending fs: %s\n",  statfsp->f_mntonname);
		error = ioctl(g_ufs_suspend_handle, UFSSUSPEND, &statfsp->f_fsid);
		if (error != 0) {
			printf("error: %d\n", errno);
			error = errno;
		} else {
			printf("Successfully suspend fs: %s\n",  statfsp->f_mntonname);
		}
	}

	return (error);
}

/**
 * closing the opened handle will thaw the FS.
 */
static int
thaw(void)
{
	int error = 0;

	if (g_ufs_suspend_handle != -1) {
		error = close(g_ufs_suspend_handle);
		if (!error) {
			g_ufs_suspend_handle = -1;
			printf("Successfully thaw the fs\n");
		} else {
			error = errno;
			printf("Fail to thaw the fs: "
					"%d %s\n", errno, strerror(errno));
		}
	} else {
		printf("The fs has already been thawed\n\n");
	}

	return (error);
}

int
main(void)
{
	int error;

	error = freeze();
	printf("freeze: err=%d\n", error);

	error = thaw();
	printf("thaw: err=%d\n", error);

	return 0;
}
EOF

mycc -o /tmp/ufssuspend -Wall -Wextra -O2 -g /tmp/ufssuspend.c || exit 1
rm /tmp/ufssuspend.c

cd /tmp
./ufssuspend > /dev/null
s=$?
rm /tmp/ufssuspend
exit $s