| FSTRANS(9) | Kernel Developer's Manual | FSTRANS(9) | 
fstrans, fstrans_setstate,
  fstrans_getstate,
  fstrans_start,
  fstrans_start_nowait,
  fstrans_start_lazy,
  fstrans_done,
  fstrans_is_owner,
  fscow_establish,
  fscow_disestablish, fscow_run
  —
#include <sys/mount.h>
#include <sys/fstrans.h>
void
  
  fstrans_start(struct
    mount *mp);
int
  
  fstrans_start_nowait(struct
    mount *mp);
void
  
  fstrans_start_lazy(struct
    mount *mp);
void
  
  fstrans_done(struct
    mount *mp);
int
  
  fstrans_setstate(struct
    mount *mp, enum
    fstrans_state new_state);
enum fstrans_state
  
  fstrans_getstate(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);
fstrans subsystem assists file system suspension and
  copy-on-write snapshots.
The file system's normal operations, such as its
    vnodeops(9), must be
    bracketed by fstrans_start() and
    fstrans_done() in a shared
    transaction, which is blocked by suspending the file system and while it is
    suspended.
Operations needed while suspending the file system must be
    bracketed by fstrans_start_lazy() and
    fstrans_done() in a lazy
    transaction, which is allowed while suspending the file system, but blocked
    while the file system is suspended.
Transactions are per-thread and nestable: if a thread is already
    in a transaction, it can enter another transaction without blocking. Each
    fstrans_start() must be paired with
    fstrans_done(). Transactions for multiple distinct
    mount points may not be nested.
The file system's
    VFS_SUSPENDCTL(9)
    method can use fstrans_setstate() to:
FSTRANS_SUSPENDING state to suspend all
      normal operations but allow lazy transactions,FSTRANS_SUSPENDED state to suspend all
      operations, andFSTRANS_NORMAL state to resume all
      operations.A file system supporting fstrans may
    establish a copy-on-write callback with
    fscow_establish(). The copy-on-write callback will
    be called every time a buffer is written to a block device with
    VOP_STRATEGY() and every time a buffer is read into
    the buffercache(9) with
    B_MODIFY set indicating the caller's intent to
    modify it. Anyone modifying a buffer may additionally use
    fscow_run() to explicitly invoke the established
    callback. The copy-on-write callback must be disestablished with
    fscow_disestablish() when the file system is done
    with it.
fstrans_start(mp)If the file system is suspended, wait until it is resumed.
However, if the current thread is already in a transaction on
        mp, fstrans_start() will
        enter a nested transaction and return immediately without waiting.
May sleep.
fstrans_start_nowait(mp)fstrans_start(), but return
      EBUSY immediately if transactions are blocked in
      its current state.
    May sleep nevertheless on internal locks.
fstrans_start_lazy(mp)fstrans_start(), but will not block while
      suspending.
    May sleep.
fstrans_done(mp)fstrans_getstate(mp)Must be called within a transaction for the answer to be stable.
fstrans_setstate(mp,
    new_state)FSTRANS_NORMALFSTRANS_SUSPENDINGFSTRANS_SHARED transactions but allow
          FSTRANS_LAZY transactions.FSTRANS_SUSPENDEDA thread that changes a file system to a state other than
        FSTRANS_NORMAL enters a transaction for the
        purposes of fstrans_getstate() until it changes
        state back to FSTRANS_NORMAL.
Additionally, a thread that changes a file system to a state
        other than FSTRANS_NORMAL acquires an exclusive
        lock on the file system state, so that
        fstrans_is_owner() will return true in that
        thread, and no other thread can change the file system's state until the
        owner restores it to FSTRANS_NORMAL.
May sleep, and may be interrupted by a signal. On success,
        return zero. On failure, restore the file system to the
        FSTRANS_NORMAL state and return an error code.
        fstrans_setstate() never fails if
        new_state is
        FSTRANS_NORMAL.
fstrans_is_owner(mp)true if the current thread is currently
      suspending the file system mp.fscow_establish(mp,
    func, cookie)func(cookie,
      bp, data_valid)May sleep.
fscow_disestablish(mp,
    func, cookie)fscow_establish().
    May sleep.
fscow_run(bp,
    data_valid)true the
      buffer data has not yet been modified.
    May sleep.
int
xxx_suspendctl(struct mount *mp, int cmd)
{
	int error;
	switch (cmd) {
	case SUSPEND_SUSPEND:
		error = fstrans_setstate(mp, FSTRANS_SUSPENDING);
		if (error)
			return error;
		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;
	fstrans_start(mp);
	/* Actually create the node. */
	fstrans_done(mp);
	return 0;
}
fstrans subsystem is implemented in the file
  sys/kern/vfs_trans.c.
fstrans subsystem appeared in
  NetBSD 5.0.
fstrans subsystem was written by
  Jürgen Hannken-Illjes
  ⟨hannken@NetBSD.org⟩.
fstrans is useful only for temporary suspension —
  it does not help to permanently block file system operations for unmounting,
  because fstrans_start() cannot fail.
| October 4, 2018 | NetBSD 10.0 |