NAME
fstrans,
fstrans_setstate,
fstrans_getstate,
fstrans_start,
fstrans_start_nowait,
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_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.
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_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 return
EBUSY
immediately if transactions are blocked in
its current state.
May sleep nevertheless on internal locks.
-
-
- 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_SUSPENDED
- Block all transactions.
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)
- 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
func(
cookie,
bp,
data_valid)
where data_valid is true if and only if the buffer
bp has not yet been modified.
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:
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
vfs_resume(9),
vfs_suspend(9)
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.