1
/*********************************************************
2
* Copyright (C) 2011 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
20
* @file syncDriverLinux.c
22
* A sync driver backend that uses the Linux "FIFREEZE" and "FITHAW" ioctls
23
* to freeze and thaw file systems.
32
#include <sys/ioctl.h>
36
#include "syncDriverInt.h"
38
/* Out toolchain headers are somewhat outdated and don't define these. */
39
#if !defined(FIFREEZE)
40
# define FIFREEZE _IOWR('X', 119, int) /* Freeze */
41
# define FITHAW _IOWR('X', 120, int) /* Thaw */
45
typedef struct LinuxDriver {
53
*******************************************************************************
54
* LinuxFiThaw -- */ /**
56
* Thaws the file systems monitored by the given handle. Tries to thaw all the
57
* file systems even if an error occurs in one of them.
59
* @param[in] handle Handle returned by the freeze call.
61
* @return A SyncDriverErr.
63
*******************************************************************************
67
LinuxFiThaw(const SyncDriverHandle handle)
70
LinuxDriver *sync = (LinuxDriver *) handle;
71
SyncDriverErr err = SD_SUCCESS;
73
for (i = 0; i < sync->fdCnt; i++) {
74
if (ioctl(sync->fds[i], FITHAW) == -1) {
84
*******************************************************************************
85
* LinuxFiClose -- */ /**
87
* Closes the file descriptors used for freezing, and frees memory associated
90
* @param[in] handle Handle to close.
92
*******************************************************************************
96
LinuxFiClose(SyncDriverHandle handle)
98
LinuxDriver *sync = (LinuxDriver *) handle;
101
for (i = 0; i < sync->fdCnt; i++) {
110
*******************************************************************************
111
* LinuxDriver_Freeze -- */ /**
113
* Tries to freeze the filesystems using the Linux kernel's FIFREEZE ioctl.
115
* If the first attempt at using the ioctl fails, assume that it doesn't exist
116
* and return SD_UNAVAILABLE, so that other means of freezing are tried.
118
* @param[in] paths Paths to freeze (colon-separated).
119
* @param[out] handle Handle to use for thawing.
121
* @return A SyncDriverErr.
123
*******************************************************************************
127
LinuxDriver_Freeze(const char *paths,
128
SyncDriverHandle *handle)
133
unsigned int index = 0;
136
LinuxDriver *sync = NULL;
137
SyncDriverErr err = SD_SUCCESS;
141
Debug(LGPFX "Freezing using Linux ioctls...\n");
143
sync = calloc(1, sizeof *sync);
148
sync->driver.thaw = LinuxFiThaw;
149
sync->driver.close = LinuxFiClose;
152
* Iterate through the requested paths. If we get an error for the first
153
* path, and it's not EPERM, assume that the ioctls are not available in
154
* the current kernel.
156
while ((path = StrUtil_GetNextToken(&index, paths, ":")) != NULL) {
157
fd = open(path, O_RDONLY);
162
* We sometimes get access errors to virtual filesystems mounted
163
* as users with permission 700, so just ignore these.
165
Debug(LGPFX "cannot access mounted directory '%s'.\n", path);
171
* A mounted HGFS filesystem with the backend disabled will give
172
* us these; probably could use a better way to detect HFGS, but
173
* this should be enough. Just skip.
175
Debug(LGPFX "I/O error reading directory '%s'.\n", path);
180
Debug(LGPFX "failed to open '%s': %d (%s)\n",
181
path, errno, strerror(errno));
188
if (ioctl(fd, FIFREEZE) == -1) {
189
int ioctlerr = errno;
191
* If the ioctl does not exist, Linux will return ENOTTY. If it's not
192
* supported on the device, we get EOPNOTSUPP. Ignore the latter,
193
* since freezing does not make sense for all fs types, and some
194
* Linux fs drivers may not have been hooked up in the running kernel.
196
* Also ignore EBUSY since we may try to freeze the same superblock
197
* more than once depending on the OS configuration (e.g., usage of
201
if (ioctlerr != EBUSY && ioctlerr != EOPNOTSUPP) {
202
Debug(LGPFX "failed to freeze '%s': %d (%s)\n",
203
path, ioctlerr, strerror(ioctlerr));
204
err = first && ioctlerr == ENOTTY ? SD_UNAVAILABLE : SD_ERROR;
209
Debug(LGPFX "successfully froze '%s'.\n", path);
210
if (!DynBuf_Append(&fds, &fd, sizeof fd)) {
211
if (ioctl(fd, FITHAW) == -1) {
212
Warning(LGPFX "failed to thaw '%s': %d (%s)\n",
213
path, errno, strerror(errno));
228
sync->fds = DynBuf_Detach(&fds);
231
if (err != SD_SUCCESS) {
232
LinuxFiThaw(&sync->driver);
233
LinuxFiClose(&sync->driver);
235
*handle = &sync->driver;