| 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 9.4 |