-
Notifications
You must be signed in to change notification settings - Fork 9
Open
Labels
Description
fsfreeze(8):
fsfreeze suspends or resumes access to a filesystem.
fsfreeze halts any new access to the filesystem and creates a
stable image on disk. fsfreeze is intended to be used with
hardware RAID devices that support the creation of snapshots.
Filesystem freeze and unfreeze allows backup systems to snapshot a consistent state.
Behavior:
- Suspend writes
- Including all vfs I/O submission APIs and mmap I/O (the latter only since Linux 3.0)
- We need to get the metadata and journal out, so there are several special cases for them
- Sync filesystem
- Call filesystem specific freeze function
- Used to be a xfs specific ioctl but is now a VFS interface
VFS API
- Freeze:
ioctl(fd, FIFREEZE, 0)
- Thaw:
ioctl(fd, FITHAW, 0)
New filesystem freeze API
- FIISFROZEN: vfs ioctl to check freeze state
- BLKISFROZEN: add block device ioctl to check freeze state
- Useful to thaw unmounted frozen filesystems
- Might get rid of this if returning EBUSY when trying to unmount a frozen filesystem is acceptable
- FIGETFREEZEFD: freezes the indicated filesystem and returns a file descriptor; as long as that file descriptor is held open, the filesystem remains open
- Since the filesytem is automatically thawed when the file descriptor is closed, if the agent goes away the filesystem will be automagically thawed by kernel
- Filesystem freeze fs ioctls: FS_FREEZE_FD, FS_THAW_FD, FS_ISFROZEN_FD
- Added new parameter to FIGETFREEZEFD ioctl to indicate whether the filesystem should be frozen on fd open
- Useful when you are trying to restart the agent
See New Filesystem Freeze API (PDF)
if (fstat(fd, &sb) == -1) {
warn(_("stat of %s failed"), path);
goto done;
}
if (!S_ISDIR(sb.st_mode)) {
warnx(_("%s: is not a directory"), path);
goto done;
}
switch (action) {
case FREEZE:
if (ioctl(fd, FIFREEZE, 0)) {
warn(_("%s: freeze failed"), path);
goto done;
}
break;
case UNFREEZE:
if (ioctl(fd, FITHAW, 0)) {
warn(_("%s: unfreeze failed"), path);
goto done;
}
break;
https://github.com/qemu/qemu/blob/master/qga/commands-posix.c
/* we try to cull filesystems we know won't work in advance, but other
* filesystems may not implement fsfreeze for less obvious reasons.
* these will report EOPNOTSUPP. we simply ignore these when tallying
* the number of frozen filesystems.
* if a filesystem is mounted more than once (aka bind mount) a
* consecutive attempt to freeze an already frozen filesystem will
* return EBUSY.
*
* any other error means a failure to freeze a filesystem we
* expect to be freezable, so return an error in those cases
* and return system to thawed state.
*/
ret = ioctl(fd, FIFREEZE);
if (ret == -1) {
if (errno != EOPNOTSUPP && errno != EBUSY) {
error_setg_errno(errp, errno, "failed to freeze %s",
mount->dirname);
close(fd);
goto error;
}
} else {
i++;
}
close(fd);
...
/* we have no way of knowing whether a filesystem was actually unfrozen
* as a result of a successful call to FITHAW, only that if an error
* was returned the filesystem was *not* unfrozen by that particular
* call.
*
* since multiple preceding FIFREEZEs require multiple calls to FITHAW
* to unfreeze, continuing issuing FITHAW until an error is returned,
* in which case either the filesystem is in an unfreezable state, or,
* more likely, it was thawed previously (and remains so afterward).
*
* also, since the most recent successful call is the one that did
* the actual unfreeze, we can use this to provide an accurate count
* of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
* may * be useful for determining whether a filesystem was unfrozen
* during the freeze/thaw phase by a process other than qemu-ga.
*/
do {
ret = ioctl(fd, FITHAW);
if (ret == 0 && !logged) {
i++;
logged = true;
}
} while (ret == 0);
close(fd);