NAME
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
SYNOPSIS
#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);
DESCRIPTION
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:
- enter the
FSTRANS_SUSPENDING
state to suspend all normal operations but allow lazy transactions, - enter the
FSTRANS_SUSPENDED
state to suspend all operations, and - restore to the
FSTRANS_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.
FUNCTIONS
fstrans_start
(mp)- Enter a transaction on the file system mp in the
current thread. If the file system is in a state that blocks such
transactions, wait until it changes state to one that does not.
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)- Like
fstrans_start
(), but returnEBUSY
immediately if transactions are blocked in its current state.May sleep nevertheless on internal locks.
fstrans_start_lazy
(mp)- Like
fstrans_start
(), but will not block while suspending.May sleep.
fstrans_done
(mp)- End the current transaction on mp.
fstrans_getstate
(mp)- Return the current state of the file system mp.
Must be called within a transaction for the answer to be stable.
fstrans_setstate
(mp, new_state)- Change the state of the file system mp to
new_state, and wait for all transactions not allowed
in new_state to complete.
FSTRANS_NORMAL
- Allow all transactions.
FSTRANS_SUSPENDING
- Block
FSTRANS_SHARED
transactions but allowFSTRANS_LAZY
transactions. FSTRANS_SUSPENDED
- Block all transactions.
A thread that changes a file system to a state other than
FSTRANS_NORMAL
enters a transaction for the purposes offstrans_getstate
() until it changes state back toFSTRANS_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 thatfstrans_is_owner
() will return true in that thread, and no other thread can change the file system's state until the owner restores it toFSTRANS_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 isFSTRANS_NORMAL
. fstrans_is_owner
(mp)- Return
true
if the current thread is currently suspending the file system mp. fscow_establish
(mp, func, cookie)- Establish a copy-on-write callback for the file system
mp. The function func will be
called for every buffer bp written through this file
system as
) where data_valid is true if and only if the buffer bp has not yet been modified.
func(cookie, bp, data_valid
May sleep.
fscow_disestablish
(mp, func, cookie)- Disestablish a copy-on-write callback established with
fscow_establish
().May sleep.
fscow_run
(bp, data_valid)- Run all copy-on-write callbacks established for the file system this
buffer belongs to, if they have not already been run for this buffer. If
data_valid is
true
the buffer data has not yet been modified.May sleep.
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) 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; }
CODE REFERENCES
The fstrans
subsystem is implemented in
the file sys/kern/vfs_trans.c.
SEE ALSO
HISTORY
The fstrans
subsystem appeared in
NetBSD 5.0.
AUTHORS
The fstrans
subsystem was written by
Jürgen Hannken-Illjes
⟨hannken@NetBSD.org⟩.
BUGS
fstrans
is useful only for temporary
suspension — it does not help to permanently block file system
operations for unmounting, because fstrans_start
()
cannot fail.