December 2, 2007 FSTRANS 9

### NAME

fstrans, fstrans_setstate, fstrans_getstate, fstrans_start, fstrans_start_nowait, fstrans_done, fstrans_is_owner, fscow_establish, fscow_disestablish, fscow_run - file system suspension helper subsystem

### SYNOPSIS

```int` fstrans_setstate(```struct mount *mp``, enum fstrans_state new_state`)
```enum fstrans_state` fstrans_getstate(```struct mount *mp`)
```void` fstrans_start(```struct mount *mp``, enum fstrans_lock_type lock_type`)
```int` fstrans_start_nowait(```struct mount *mp``, enum fstrans_lock_type lock_type`)
```void` fstrans_done(```struct mount *mp`)
```int` fstrans_is_owner(```struct mount *mp`)
```int` fscow_establish(```struct mount *mp``, int (*func)(void *, struct buf *, bool)``, void *cookie`)
```int` fscow_disestablish(```struct mount *mp``, int (*func)(void *, struct buf *, bool)``, void *cookie`)
```int` fscow_run(```struct buf *bp``, bool data_valid`)

### DESCRIPTION

The fstrans subsystem is a set of operations to assist file system suspension. These operations must not be used outside of file systems.

File systems supporting this subsystem must set the flag ```IMNT_HAS_TRANS` in ```mnt_iflag`.

File systems are always in one of these states:

```FSTRANS_NORMAL`
  normal operations.
```FSTRANS_SUSPENDING`
  preparing a suspension.
```FSTRANS_SUSPENDED`
  suspended.

This state is represented by

fstrans_getstate(```mp`)
  returns the current state of the file system ```mp`.

fstrans_setstate(```mp``, new_state`)
  changes the state of the file system ```mp` to ```new_state`.

All file system operations use a fstrans lock. This lock is recursive. A thread already owning a lock will always get another lock. The lock has two variants:

```FSTRANS_SHARED`
  this lock will be granted if the file system is in state ```FSTRANS_NORMAL`.
```FSTRANS_LAZY`
  this lock will be granted if the file system is in state ```FSTRANS_NORMAL` or ```FSTRANS_SUSPENDING`. It needs special care because operations using this variant will not block while the file system prepares suspension.

The lock variant is represented by

fstrans_start(```mp``, lock_type`)
  sets a lock of type ```lock_type` on the file system ```mp`.

fstrans_start_nowait(```mp``, lock_type`)
  will not wait for a state change of the file system when attempting to aquire the lock. The thread may still sleep while attempting to aquire the lock.

fstrans_done(```mp`)
  releases a lock on the file system ```mp`.

fstrans_is_owner(```mp`)
  returns ```true` if this thread is currently suspending the file system ```mp`.

fscow_establish(```mp``, func``, cookie`)
  Establish a copy-on-write callback for the file system ```mp`. ```func` will be called for every buffer written through this file system.

fscow_disestablish(```mp``, func``, cookie`)
  Disestablish a copy-on-write callback registered with fscow_establish(``).

fscow_run(```bp``, data_valid`)
  Run all copy-on-write callbacks established for the file system this buffer belongs to. If ```data_valid` is ```true` the buffer data has not yet been modified.

### RETURN VALUES

The functions fstrans_setstate(``) and fstrans_start_nowait(``) return zero on success and an error value on failure.

### EXAMPLES

The following is an example of a file system suspend operation. `

    int
    xxx_suspendctl(struct mount *mp, int cmd)
    {
            int error;

            switch (cmd) {
            case SUSPEND_SUSPEND:
                    error = fstrans_setstate(mp, FSTRANS_SUSPENDING);
                    if (error != 0)
                            return error;

                    /* Sync file system state to disk. */

                    return fstrans_setstate(mp, FSTRANS_SUSPENDED);

            case SUSPEND_RESUME:
                    return fstrans_setstate(mp, FSTRANS_NORMAL);

            default:
                    return EINVAL;
            }
    }

`

This is an example of a file system operation. ``

    int
    xxx_create(void *v)
    {
            struct vop_create_args *ap = v;
            struct mount *mp = ap->a_dvp->v_mount;
            int error;

            if ((error = fstrans_start(mp, FSTRANS_SHARED)) != 0)
                    return error;

            /* Actually create the node. */

            fstrans_done(mp);

            return 0;
    }

### SEE ALSO

vfs_resume(9), vfs_suspend(9)

### CODE REFERENCES

The actual code implementing this subsystem can be found in the file ```sys/kern/vfs_trans.c`.

### HISTORY

The fstrans subsystem appeared in NetBSD5.0.

### AUTHORS

The fstrans subsystem was written by Juergen Hannken-Illjes
<hannken@NetBSD.org>.