17 #include <ufs/ffs/fs.h>
21 #include "hv_snapshot.h"
23 #define UNDEF_FREEZE_THAW (0)
27 #define VSS_LOG(priority, format, args...) do { \
28 if (is_debugging == 1) { \
30 syslog(priority, format, ## args); \
32 printf(format, ## args); \
34 if (priority < LOG_DEBUG) { \
36 syslog(priority, format, ## args); \
38 printf(format, ## args); \
43 static int is_daemon = 1;
44 static int is_debugging = 0;
45 static int g_ufs_suspend_handle = -1;
47 static const char *dev = "/dev";
52 struct statfs *mntbuf, *statfsp;
56 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
58 VSS_LOG(LOG_ERR, "There is no mount information\n");
61 for (i = mntsize - 1; i >= 0; --i)
65 if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0) {
66 continue; /* skip to freeze '/dev' */
67 } else if (statfsp->f_flags & MNT_RDONLY) {
68 continue; /* skip to freeze RDONLY partition */
69 } else if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0) {
70 return (EPERM); /* only UFS can be freezed */
80 struct statfs *mntbuf, *statfsp;
85 g_ufs_suspend_handle = open(_PATH_UFSSUSPEND, O_RDWR);
86 if (g_ufs_suspend_handle == -1) {
87 VSS_LOG(LOG_ERR, "unable to open %s", _PATH_UFSSUSPEND);
91 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
93 VSS_LOG(LOG_ERR, "There is no mount information\n");
96 for (i = mntsize - 1; i >= 0; --i)
100 if (strncmp(statfsp->f_mntonname, dev, strlen(dev)) == 0) {
101 continue; /* skip to freeze '/dev' */
102 } else if (statfsp->f_flags & MNT_RDONLY) {
103 continue; /* skip to freeze RDONLY partition */
104 } else if (strncmp(statfsp->f_fstypename, "ufs", 3) != 0) {
105 continue; /* only UFS can be freezed */
107 error = ioctl(g_ufs_suspend_handle, UFSSUSPEND, &statfsp->f_fsid);
109 VSS_LOG(LOG_ERR, "error: %d\n", errno);
112 VSS_LOG(LOG_INFO, "Successfully suspend fs: %s\n",
113 statfsp->f_mntonname);
121 * close the opened handle will thaw the FS.
127 if (g_ufs_suspend_handle != -1) {
128 error = close(g_ufs_suspend_handle);
130 g_ufs_suspend_handle = -1;
131 VSS_LOG(LOG_INFO, "Successfully thaw the fs\n");
134 VSS_LOG(LOG_ERR, "Fail to thaw the fs: "
135 "%d %s\n", errno, strerror(errno));
138 VSS_LOG(LOG_INFO, "The fs has already been thawed\n");
145 usage(const char* cmd)
147 fprintf(stderr, "%s: daemon for UFS file system freeze/thaw\n"
148 " -d : enable debug log printing. Default is disabled.\n"
149 " -n : run as a regular process instead of a daemon. Default is a daemon.\n"
150 " -h : print usage.\n", cmd);
155 main(int argc, char* argv[])
157 struct hv_vss_opt_msg userdata;
159 struct pollfd hv_vss_poll_fd[1];
164 while ((ch = getopt(argc, argv, "dnh")) != -1) {
167 /* Run as regular process for debugging purpose. */
171 /* Generate debugging output */
181 openlog("HV_VSS", 0, LOG_USER);
183 /* Become daemon first. */
187 VSS_LOG(LOG_DEBUG, "Run as regular process.\n");
189 VSS_LOG(LOG_INFO, "HV_VSS starting; pid is: %d\n", getpid());
191 memset(&userdata, 0, sizeof(struct hv_vss_opt_msg));
192 /* register the daemon */
193 hv_vss_dev_fd = open(VSS_DEV(FS_VSS_DEV_NAME), O_RDWR);
195 if (hv_vss_dev_fd < 0) {
196 VSS_LOG(LOG_ERR, "Fail to open %s, error: %d %s\n",
197 VSS_DEV(FS_VSS_DEV_NAME), errno, strerror(errno));
200 hv_vss_poll_fd[0].fd = hv_vss_dev_fd;
201 hv_vss_poll_fd[0].events = POLLIN | POLLRDNORM;
204 r = poll(hv_vss_poll_fd, 1, INFTIM);
206 VSS_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n",
207 r, hv_vss_poll_fd[0].revents);
209 if (r == 0 || (r < 0 && errno == EAGAIN) ||
210 (r < 0 && errno == EINTR)) {
211 /* Nothing to read */
217 * For poll return failure other than EAGAIN,
220 VSS_LOG(LOG_ERR, "Poll failed.\n");
225 /* Read from character device */
226 error = ioctl(hv_vss_dev_fd, IOCHVVSSREAD, &userdata);
228 VSS_LOG(LOG_ERR, "Read failed.\n");
233 if (userdata.status != 0) {
234 VSS_LOG(LOG_ERR, "data read error\n");
239 * We will use the KVP header information to pass back
240 * the error from this daemon. So, first save the op
241 * and pool info to local variables.
257 VSS_LOG(LOG_ERR, "Illegal operation: %d\n", op);
261 userdata.status = VSS_FAIL;
263 userdata.status = VSS_SUCCESS;
264 error = ioctl(hv_vss_dev_fd, IOCHVVSSWRITE, &userdata);
266 VSS_LOG(LOG_ERR, "Fail to write to device\n");
269 VSS_LOG(LOG_INFO, "Send response %d for %s to kernel\n",
270 userdata.status, op == HV_VSS_FREEZE ? "Freeze" :
271 (op == HV_VSS_THAW ? "Thaw" : "Check"));