Add vfs_trybusy() and mountlist_iterator_trynext() and use it for the syncer.

This commit is contained in:
hannken 2017-04-17 08:34:27 +00:00
parent 8c6f10d105
commit bd152b56b5
3 changed files with 51 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_mount.c,v 1.57 2017/04/17 08:32:55 hannken Exp $ */
/* $NetBSD: vfs_mount.c,v 1.58 2017/04/17 08:34:27 hannken Exp $ */
/*-
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.57 2017/04/17 08:32:55 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.58 2017/04/17 08:34:27 hannken Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -311,13 +311,17 @@ vfs_rele(struct mount *mp)
* => The caller must hold a pre-existing reference to the mount.
* => Will fail if the file system is being unmounted, or is unmounted.
*/
int
vfs_busy(struct mount *mp)
static inline int
_vfs_busy(struct mount *mp, bool wait)
{
KASSERT(mp->mnt_refcnt > 0);
if (wait) {
mutex_enter(&mp->mnt_unmounting);
} else if (!mutex_tryenter(&mp->mnt_unmounting)) {
return EBUSY;
}
if (__predict_false((mp->mnt_iflag & IMNT_GONE) != 0)) {
mutex_exit(&mp->mnt_unmounting);
return ENOENT;
@ -329,6 +333,20 @@ vfs_busy(struct mount *mp)
return 0;
}
int
vfs_busy(struct mount *mp)
{
return _vfs_busy(mp, true);
}
int
vfs_trybusy(struct mount *mp)
{
return _vfs_busy(mp, false);
}
/*
* Unbusy a busy filesystem.
*
@ -1524,11 +1542,12 @@ mountlist_iterator_destroy(mount_iterator_t *mi)
* Return the next mount or NULL for this iterator.
* Mark it busy on success.
*/
struct mount *
mountlist_iterator_next(mount_iterator_t *mi)
static inline struct mount *
_mountlist_iterator_next(mount_iterator_t *mi, bool wait)
{
struct mountlist_entry *me, *marker = &mi->mi_entry;
struct mount *mp;
int error;
if (marker->me_mount != NULL) {
vfs_unbusy(marker->me_mount);
@ -1559,7 +1578,11 @@ mountlist_iterator_next(mount_iterator_t *mi)
mutex_exit(&mountlist_lock);
/* Try to mark this mount busy and return on success. */
if (vfs_busy(mp) == 0) {
if (wait)
error = vfs_busy(mp);
else
error = vfs_trybusy(mp);
if (error == 0) {
vfs_rele(mp);
marker->me_mount = mp;
return mp;
@ -1569,6 +1592,20 @@ mountlist_iterator_next(mount_iterator_t *mi)
}
}
struct mount *
mountlist_iterator_next(mount_iterator_t *mi)
{
return _mountlist_iterator_next(mi, true);
}
struct mount *
mountlist_iterator_trynext(mount_iterator_t *mi)
{
return _mountlist_iterator_next(mi, false);
}
/*
* Attach new mount to the end of the mount list.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_subr.c,v 1.462 2017/04/12 10:26:33 hannken Exp $ */
/* $NetBSD: vfs_subr.c,v 1.463 2017/04/17 08:34:27 hannken Exp $ */
/*-
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.462 2017/04/12 10:26:33 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.463 2017/04/17 08:34:27 hannken Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@ -775,7 +775,7 @@ sched_sync(void *arg)
* Sync mounts whose dirty time has expired.
*/
mountlist_iterator_init(&iter);
while ((mp = mountlist_iterator_next(iter)) != NULL) {
while ((mp = mountlist_iterator_trynext(iter)) != NULL) {
if ((mp->mnt_iflag & IMNT_ONWORKLIST) == 0 ||
mp->mnt_synclist_slot != syncer_delayno) {
continue;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mount.h,v 1.225 2017/04/17 08:32:01 hannken Exp $ */
/* $NetBSD: mount.h,v 1.226 2017/04/17 08:34:27 hannken Exp $ */
/*
* Copyright (c) 1989, 1991, 1993
@ -417,6 +417,7 @@ bool vfs_unmountall(struct lwp *); /* unmount file systems */
bool vfs_unmountall1(struct lwp *, bool, bool);
bool vfs_unmount_forceone(struct lwp *);
int vfs_busy(struct mount *);
int vfs_trybusy(struct mount *);
int vfs_rootmountalloc(const char *, const char *, struct mount **);
void vfs_unbusy(struct mount *);
int vfs_attach(struct vfsops *);
@ -496,6 +497,7 @@ typedef struct mount_iterator mount_iterator_t; /* Opaque. */
void mountlist_iterator_init(mount_iterator_t **);
void mountlist_iterator_destroy(mount_iterator_t *);
struct mount *mountlist_iterator_next(mount_iterator_t *);
struct mount *mountlist_iterator_trynext(mount_iterator_t *);
struct mount *_mountlist_next(struct mount *);
void mountlist_append(struct mount *);
void mountlist_remove(struct mount *);