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_NORMAL
FSTRANS_SUSPENDING
FSTRANS_SHARED
transactions but allow
FSTRANS_LAZY
transactions.FSTRANS_SUSPENDED
A 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.2 |