| 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 — file system
suspension helper subsystem
#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);
The 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_validMay 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.
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)
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;
}
The fstrans subsystem is implemented in
the file sys/kern/vfs_trans.c.
The fstrans subsystem appeared in
NetBSD 5.0.
The 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 11.0 |