test veritas logo



fsckpt_intro - introduction to the Veritas File System Storage Checkpoint API




A file system Storage Checkpoint is a snapshot of all user files in a file system at a moment in time. Checkpoints are objects that are managed and controlled by the file system and are persistent through reboots and system crashes. As with most objects, Storage Checkpoints have a name and can be managed as independent entities. As such, Storage Checkpoints can be created, removed, and renamed.

Storage Checkpoints significantly reduce I/O overhead by identifying and maintaining only the file system blocks that have changed since the last Storage Checkpoint or backup via a copy-on-write technique. After a Storage Checkpoint is taken, files can continue to be created, removed or updated without affecting the logical image of the Storage Checkpoint. A Storage Checkpoint preserves not only the name space (directory hierarchy) of the file system, but also the user data as it was at the moment of its creation.

The Storage Checkpoint facility freezes the mounted file system (known as the primary fileset, initializes the Storage Checkpoint, and thaws the file system. Specifically, the file system is first brought to a stable state where all of its data is written to disk, and the freezing process momentarily blocks all I/O operations to the file system. A Storage Checkpoint is then created without any actual data; the Storage Checkpoint instead points to the block map of the primary fileset. The thawing process that follows restarts I/O operations to the file system.

Since Storage Checkpoint filesets are updated on demand by using copy-on-write, a map of all changed blocks is maintained by the Storage Checkpoint object. These changed blocks can be extremely valuable for backup applications and replication solutions since only the changed data may be retrieved. Access to this information may provide incredible advantages to these solutions by minimizing data movement many times. This information may additionally lead to higher availability and data integrity since the frequency of these backup/replication solutions may increase many times as well.

The Veritas File System Checkpointing API allows applications to completely manage all Storage Checkpoints in the file system. Additionally, the API provides all the necessary functions to view a Storage Checkpoint name space and retrieve all blocks changed. Finally, a set of functions is provided to gather information and statistics from Storage Checkpoint filesets and files to properly manage and tune these file systems.


Since Storage Checkpoints are a resource of the file system, they require additional disk space to maintain their image. Administrators should be aware of the demands placed on these file system and the types of operations that require added space due to the presence of Storage Checkpoints. This API provides space counters that can be monitored to best tune and control disk usage.

There are a couple of scenarios that may arise when Storage Checkpoints in file systems require updating and there is very limited disk space. These are:
1. When over-writing a file, the image of the Storage Checkpoint needs to be updated which then requires a disk allocation. A problem arises when the file system does not have enough disk space to accommodate the Storage Checkpoint update. When this occurs, the application gets an ENOSPC error and the Storage Checkpoint cannot be updated. If the Storage Checkpoint is not updated, the image is lost.
Database applications usually preallocate storage for their files and should not expect a write operation to fail. If a file system runs out of space, the kernel automatically removes Storage Checkpoints and attempts to complete the write operation after sufficient space becomes available. The kernel removes Storage Checkpoints to prevent commands, such as rm from failing in an out-of-space (ENOSPC) condition. See the rm(1) manual page).
When the kernel automatically removes the Storage Checkpoints, it applies the following policies:
- Remove as few Storage Checkpoints as possible to complete the operation.
- Never select a non-removable Storage Checkpoint.
- Select a nodata Storage Checkpoint only when data Storage Checkpoints no longer exist.
- Remove the oldest Storage Checkpoint first.
2. A similar situation occurs when a directory update is needed because a file being created or removed. Before the directory update is allowed, however, the Storage Checkpoint must also be updated. Again, this may result in an allocation failure due to lack of disk space.
The File System Checkpointing API does not intend to solve these problems. Instead, it provides the necessary information to tune and monitor the file system and the disk space demands from all Storage Checkpoints in the system. The API also provides a mechanism by which Storage Checkpoints can be disabled, making sure that applications never get ENOSPC errors. See the fsckpt_create() and fsckpt_cntl() man pages for more information.

EXAMPLE 1 Full Backup

The following code example shows how a consistent full backup may be taken from an online file system. This example may also leave a (nodata) Storage Checkpoint on the system so that a block level incremental may be taken at some point in the future.

To obtain a consistent full backup, perform the following example steps:
1. Create a Storage Checkpoint named full.
2. Set the Storage Checkpoint context to full.
3. Do a file system backup (read name-space and data from full).
4. Remove the Storage Checkpoint named full.
5. Rename full to incr1 and convert incr1 to nodata (optional)
Use step 4 to do a full backup. Use step 5 to do a full backup followed by a block incremental backup (BLI).

      char *mountpoint;
      void *chp, *ch[2];
      void *fhp;
      struct c_extent ce;
      off_t off;
      char *buf;
      int error;
      if (error = fsckpt_fsopen(mountpoint, FSCKPT_VERSION, &chp)) {
       return error;
      ch[0] = chp;
      ch[1] = NULL;
      fsckpt_create(&ch[0], "full", 0);
      fsckpt_setcontext(chp, "full");
      for (each file) {
       fd = open(file, O_RDONLY);
       fsckpt_fopen(chp, NULL, file, &fhp);
       for (off = 0; off < file.size; off += ce.ce_len) {
        fsckpt_fbmap(fhp, off, &ce);
                         * Skip holes in sparse files
        if (ce.ce_flags & CE_HOLE) {
        lseek(fd, off, SEEK_SET);
        buf = malloc(ce.ce_len);
        read(fd, *buf, ce.ce_len);
        backup(file, off, ce.ce_len, buf);
         * If an incremental will be needed then
      if (incremental needed) {
       fsckpt_rename(chp, "full", "incr1");
       fsckpt_cntl(chp, "incr1", CC_SET, CC_NODATA); } else {
       fsckpt_remove(chp, "full", 0);

EXAMPLE 2 Differential and Cumulative BLIs

The following procedure describes how to use the Storage Checkpoint API for block level incremental backups. After doing a full backup (as shown in Example 1, step 5), you should perform a BLI when the system is ready for an incremental backup as follows:
1. Create another Storage Checkpoint named tmp to stabilize the name space.
2. Set Storage Checkpoint context to tmp.
3. Do a BLI backup.
- Obtain blocks changed from incr1.
- Read stable name space and changed data from tmp.
4. For differential backups:
- Remove incr1.
- Rename tmp to incr2.
- Convert incr2 to nodata (optional).
5. For cumulative backups:
- Remove tmp.
- Rename incr1 to incr2.
      char *mountpoint;
      void *chp, *ch[2];
      void *fhp;
      struct c_extent ce;
      struct c_info cinfo;
      off_t off;
      int error;
      char *buf;

if (error = fsckpt_fsopen(mountpoint, FSCKPT_VERSION, &chp)) { return error; }

/*     * Make sure "incr1" still exists and is valid     */

if (error = fsckpt_info(chp, "incr1", 0, &cinfo)) { return error; }

ch[0] = chp; ch[1] = NULL; fsckpt_create(&ch, "tmp", 0); fsckpt_setcontext(chp, "tmp"); chdir(mountpoint); for (each changed file) { fd = open(file, O_RDONLY); fsckpt_fopen(chp, "incr1", file, &fhp); for (off = 0; off < file.size; off += ce.ce_len) { fsckpt_fbmap(fhp, off, &ce);

/*                     * If this file section has not changed or is                     * a hole in a sparse file, then skip                     */

if (!(ce.ce_flags & CE_CHANGED) || ce.ce_flags & CE_HOLE) { continue; } lseek(fd, off, SEEK_SET); buf = malloc(ce.ce_len); read(fd, *buf, ce.ce_len); backup(file, off, ce.ce_len, buf); free(buf); } fsckpt_fclose(fhp); close(fd); } fsckpt_clearcontext(chp);

/*     * leave Storage Checkpoints setup for next incremental     *     * at this point we may want the next block level incremental     * to be another differential or a cumulative incremental.     */

if (cumulative) { fsckpt_remove(chp, "tmp", 0); fsckpt_rename(chp, "incr1", "incr2"); } else { fsckpt_remove(chp, "incr1", 0); fsckpt_rename(chp, "tmp", "incr2"); fsckpt_cntl(chp, "incr2", CC_SET, CC_NODATA); } fsckpt_fclose(chp); }

EXAMPLE 3 List Checkpoints

The following snippet is an example of how to use the the API to list all Storage Checkpoints.
      char *mountpoint;
      void *chp;
      struct c_info cinfo;
      int error, index;

if (error = fsckpt_fsopen(argv[1], FSCKPT_VERSION, &chp)) { return error; }

for (index = 1; ; index++) { if (error = fsckpt_info(chp, "primary", index, &cinfo)) { break; } print_cinfo(&cinfo); }

if (error == ENOENT) { error = 0; } (void) fsckpt_fsclose(chp); return error;


fsckptadm(1M), fsckpt_clearcontext(3), fsckpt_cntl(3), fsckpt_create(3), fsckpt_createall(3), fsckpt_fbmap(3), fsckpt_fclose(3), fsckpt_finfo(3), fsckpt_fopen(3), fsckpt_fsclose(3), fsckpt_fsopen(3), fsckpt_info(3), fsckpt_remove(3), fsckpt_rename(3), fsckpt_setcontext(3)

VxFS 8.0 fsckpt_intro(3)