Skip to content

Commit

Permalink
Acquire unmount rwlock in callbacks
Browse files Browse the repository at this point in the history
Ensure that AcquireLazyWriter(), AcquireReadAhead() and
AcquireForModWrite() hold the unmount lock, stopping
unmounting from happening before release calls.

Signed-off-by: Jorgen Lundman <[email protected]>
  • Loading branch information
lundman committed Oct 10, 2023
1 parent 1bc536d commit 30f59ca
Showing 1 changed file with 119 additions and 60 deletions.
179 changes: 119 additions & 60 deletions module/os/windows/zfs/zfs_vnops_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,51 +122,69 @@ BOOLEAN
zfs_AcquireForLazyWrite(void *Context, BOOLEAN Wait)
{
FILE_OBJECT *fo = Context;
BOOLEAN result = FALSE;

if (fo == NULL)
return (FALSE);

mount_t *zmo = fo->DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);
struct vnode *vp = fo->FsContext;
dprintf("%s:fo %p\n", __func__, fo);

if (vp == NULL)
/* Confirm we are mounted, and stop unmounting */
if ((zfsvfs->z_vfs == NULL) ||
zfsvfs->z_unmounted ||
zfs_enter(zfsvfs, FTAG) != 0)
return (FALSE);

if (VN_HOLD(vp) == 0) {

if (!ExAcquireResourceExclusiveLite(
vp->FileHeader.Resource, Wait)) {
dprintf("Failed\n");
VN_RELE(vp);
return (FALSE);
}
if (vp == NULL ||
VTOZ(vp) == NULL ||
VN_HOLD(vp) != 0) {
zfs_exit(zfsvfs, FTAG);
return (FALSE);
}

vnode_ref(vp);
VN_RELE(vp);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return (TRUE);
if (!ExAcquireResourceExclusiveLite(
vp->FileHeader.Resource, Wait)) {
dprintf("Failed\n");
goto out;
}

return (FALSE);
vnode_ref(vp);
result = TRUE;
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);

out:
VN_RELE(vp);

return (result);
}

void
zfs_ReleaseFromLazyWrite(void *Context)
{
FILE_OBJECT *fo = Context;

if (fo != NULL) {
struct vnode *vp = fo->FsContext;
dprintf("%s:\n", __func__);
if (vp != NULL && VN_HOLD(vp) == 0) {
ExReleaseResourceLite(vp->FileHeader.Resource);
vnode_rele(vp);
VN_RELE(vp);
if (IoGetTopLevelIrp() ==
(PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);
return;
}
if (fo == NULL)
return;

mount_t *zmo = fo->DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);
struct vnode *vp = fo->FsContext;

dprintf("%s:\n", __func__);

if (vp != NULL && VN_HOLD(vp) == 0) {
ExReleaseResourceLite(vp->FileHeader.Resource);
vnode_rele(vp);
VN_RELE(vp);
if (IoGetTopLevelIrp() ==
(PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);

zfs_exit(zfsvfs, FTAG);
return;
}
dprintf("%s WARNING FAILED\n", __func__);
}
Expand All @@ -175,51 +193,68 @@ BOOLEAN
zfs_AcquireForReadAhead(void *Context, BOOLEAN Wait)
{
FILE_OBJECT *fo = Context;
BOOLEAN result = FALSE;

if (fo == NULL)
return (FALSE);

mount_t *zmo = fo->DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);
struct vnode *vp = fo->FsContext;

dprintf("%s:\n", __func__);

if (vp == NULL)
if ((zfsvfs->z_vfs == NULL) ||
zfsvfs->z_unmounted ||
zfs_enter(zfsvfs, FTAG) != 0)
return (FALSE);

if (VN_HOLD(vp) == 0) {

if (!ExAcquireResourceSharedLite(vp->FileHeader.Resource,
Wait)) {
dprintf("Failed\n");
VN_RELE(vp);
return (FALSE);
}
if (vp == NULL ||
VTOZ(vp) == NULL ||
VN_HOLD(vp) != 0) {
zfs_exit(zfsvfs, FTAG);
return (FALSE);
}

vnode_ref(vp);
VN_RELE(vp);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return (TRUE);
if (!ExAcquireResourceSharedLite(vp->FileHeader.Resource,
Wait)) {
dprintf("Failed\n");
goto out;
}

return (FALSE);
vnode_ref(vp);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
result = TRUE;

out:
VN_RELE(vp);

return (result);
}

void
zfs_ReleaseFromReadAhead(void *Context)
{
FILE_OBJECT *fo = Context;

if (fo != NULL) {
struct vnode *vp = fo->FsContext;
dprintf("%s:\n", __func__);
if (vp != NULL && VN_HOLD(vp) == 0) {
ExReleaseResourceLite(vp->FileHeader.Resource);
vnode_rele(vp);
VN_RELE(vp);
if (IoGetTopLevelIrp() ==
(PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);
return;
}
if (fo == NULL)
return;

mount_t *zmo = fo->DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);

struct vnode *vp = fo->FsContext;
dprintf("%s:\n", __func__);
if (vp != NULL && VN_HOLD(vp) == 0) {
ExReleaseResourceLite(vp->FileHeader.Resource);
vnode_rele(vp);
VN_RELE(vp);
if (IoGetTopLevelIrp() ==
(PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);

zfs_exit(zfsvfs, FTAG);
return;
}
dprintf("%s WARNING FAILED\n", __func__);
}
Expand Down Expand Up @@ -7896,35 +7931,55 @@ fastio_acquire_for_mod_write(PFILE_OBJECT FileObject,
PLARGE_INTEGER EndingOffset, struct _ERESOURCE **ResourceToRelease,
PDEVICE_OBJECT DeviceObject)
{
vnode_t *vp;

vnode_t *vp = NULL;
mount_t *zmo = DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);
int error;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
dprintf("%s: \n", __func__);

if ((zfsvfs->z_vfs == NULL) ||
zfsvfs->z_unmounted ||
zfs_enter(zfsvfs, FTAG) != 0)
return (STATUS_INVALID_PARAMETER);

vp = FileObject->FsContext;

if (!vp || VN_HOLD(vp) != 0)
if (vp == NULL ||
VTOZ(vp) == NULL ||
VN_HOLD(vp) != 0) {
zfs_exit(zfsvfs, FTAG);
return (STATUS_INVALID_PARAMETER);
}

if (VTOZ(vp) == NULL ||
!ExAcquireResourceExclusiveLite(vp->FileHeader.Resource, FALSE)) {
znode_t *zp = VTOZ(vp);

if (!ExAcquireResourceExclusiveLite(vp->FileHeader.Resource, FALSE)) {
dprintf("%s: returning STATUS_CANT_WAIT\n", __func__);
VN_RELE(vp);
return (STATUS_CANT_WAIT);
Status = STATUS_CANT_WAIT;
goto out;
}

*ResourceToRelease = vp->FileHeader.Resource;
vnode_ref(vp);
Status = STATUS_SUCCESS;

out:
VN_RELE(vp);

// No zfs_exit(zfsvfs, FTAG) until below

dprintf("%s: returning STATUS_SUCCESS\n", __func__);

return (STATUS_SUCCESS);
return (Status);
}

static NTSTATUS __stdcall
fastio_release_for_mod_write(PFILE_OBJECT FileObject,
struct _ERESOURCE *ResourceToRelease, PDEVICE_OBJECT DeviceObject)
{
mount_t *zmo = DeviceObject->DeviceExtension;
zfsvfs_t *zfsvfs = vfs_fsprivate(zmo);
vnode_t *vp;

dprintf("%s:\n", __func__);
Expand All @@ -7933,13 +7988,17 @@ fastio_release_for_mod_write(PFILE_OBJECT FileObject,

vp = FileObject->FsContext;
if (vp && VN_HOLD(vp) == 0) {

VERIFY3P(ResourceToRelease, ==, vp->FileHeader.Resource);
vnode_rele(vp);
VN_RELE(vp);

zfs_exit(zfsvfs, FTAG);
return (STATUS_SUCCESS);
}

dprintf("%s WARNING FAILED\n", __func__);
zfs_exit(zfsvfs, FTAG);
return (STATUS_SUCCESS);
}

Expand Down

0 comments on commit 30f59ca

Please sign in to comment.