int
fstrans_setstate(
struct mount *mp
, enum fstrans_state new_state
)
enum fstrans_state
fstrans_getstate(
struct mount *mp
)
void
fstrans_start(
struct mount *mp
, enum fstrans_lock_type lock_type
)
int
fstrans_start_nowait(
struct mount *mp
, enum fstrans_lock_type lock_type
)
void
fstrans_done(
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
)
File systems supporting this subsystem must set the flag
IMNT_HAS_TRANS
in
mnt_iflag
.
File systems are always in one of these states:
FSTRANS_NORMAL
FSTRANS_SUSPENDING
FSTRANS_SUSPENDED
mp
)
mp
.
mp
, new_state
)
mp
to
new_state
.
All file system operations use a fstrans lock. This lock is recursive. A thread already owning a lock will always get another lock. The lock has two variants:
FSTRANS_SHARED
FSTRANS_NORMAL
.
FSTRANS_LAZY
FSTRANS_NORMAL
or
FSTRANS_SUSPENDING
.
It needs special care because operations using this variant will not block
while the file system prepares suspension.
mp
, lock_type
)
lock_type
on the file system
mp
.
mp
, lock_type
)
mp
)
mp
.
mp
)
true
if this thread is currently suspending the file system
mp
.
mp
, func
, cookie
)
mp
.
func
will be called for every buffer written through this file system.
mp
, func
, cookie
)
).
bp
, data_valid
)
data_valid
is
true
the buffer data has not yet been modified.
)
and
fstrans_start_nowait(
)
return zero on success and an error value on failure.
int
xxx_suspendctl(struct mount *mp, int cmd)
{
int error;
switch (cmd) {
case SUSPEND_SUSPEND:
error = fstrans_setstate(mp, FSTRANS_SUSPENDING);
if (error != 0)
return error;
/* Sync file system state to disk. */
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.
if ((error = fstrans_start(mp, FSTRANS_SHARED)) != 0)
return error;
/* Actually create the node. */
fstrans_done(mp);
return 0;
}
int
xxx_create(void *v)
{
struct vop_create_args *ap = v;
struct mount *mp = ap->a_dvp->v_mount;
int error;
sys/kern/vfs_trans.c
.