diff --git a/include/os/windows/spl/sys/mount.h b/include/os/windows/spl/sys/mount.h index c37973a0402e..2c44c9548d09 100644 --- a/include/os/windows/spl/sys/mount.h +++ b/include/os/windows/spl/sys/mount.h @@ -56,6 +56,8 @@ #define MNT_FORCE 0x00080000 /* force unmount or readonly change */ #define MNT_CMDFLAGS (MNT_UPDATE|MNT_NOBLOCK|MNT_RELOAD|MNT_FORCE) +#define MNT_UNMOUNTING 0x80000000 /* process of unmounting */ + #define MNT_UNKNOWNPERMISSIONS MNT_IGNORE_OWNERSHIP #define MFSTYPENAMELEN 16 @@ -125,6 +127,8 @@ struct mount uint64_t mountflags; + KEVENT volume_removed_event; + // Linked list of mounts list_node_t mount_node; @@ -163,5 +167,6 @@ void vfs_mount_add(mount_t *mp); void vfs_mount_remove(mount_t *mp); int vfs_mount_count(void); void vfs_mount_setarray(void **array, int max); +void vfs_mount_iterate(int (*func)(void *, void *), void *); #endif /* SPL_MOUNT_H */ diff --git a/include/os/windows/zfs/sys/zfs_windows.h b/include/os/windows/zfs/sys/zfs_windows.h index bd6e29fa46e1..a3ee3e55d395 100644 --- a/include/os/windows/zfs/sys/zfs_windows.h +++ b/include/os/windows/zfs/sys/zfs_windows.h @@ -172,6 +172,8 @@ extern void zfs_save_ntsecurity(struct vnode *vp); void zfs_load_ntsecurity(struct vnode *vp); struct vnode *zfs_parent(struct vnode *); extern PVOID MapUserBuffer(IN OUT PIRP Irp); +extern NTSTATUS volume_create(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, + USHORT ShareAccess, uint64_t AllocationSize, ACCESS_MASK DesiredAccess); /* IRP_MJ_SET_INFORMATION helpers */ diff --git a/module/os/windows/driver.c b/module/os/windows/driver.c index 8d3f4e2511e1..ce7482e3a788 100644 --- a/module/os/windows/driver.c +++ b/module/os/windows/driver.c @@ -79,7 +79,7 @@ void OpenZFS_Fini(PDRIVER_OBJECT DriverObject) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "OpenZFS_Fini\n")); - DbgBreakPoint(); + zfs_vfsops_fini(); if (STOR_DriverUnload != NULL) { diff --git a/module/os/windows/spl/spl-mount.c b/module/os/windows/spl/spl-mount.c index b1db6ae3b93e..4720fdbfc9fe 100644 --- a/module/os/windows/spl/spl-mount.c +++ b/module/os/windows/spl/spl-mount.c @@ -116,6 +116,23 @@ vfs_mount_setarray(void **array, int max) mutex_exit(&mount_list_lock); } +void +vfs_mount_iterate(int (*func)(void *, void *), void *priv) +{ + mount_t *node; + + mutex_enter(&mount_list_lock); + for (node = list_head(&mount_list); + node; + node = list_next(&mount_list, node)) { + + // call func, stop if not zero + if (func(node, priv) != 0) + break; + } + mutex_exit(&mount_list_lock); +} + int vfs_busy(mount_t *mp, int flags) { @@ -221,7 +238,7 @@ vfs_getnewfsid(struct mount *mp) int vfs_isunmount(mount_t *mp) { - return (0); + return (vfs_flags(mp) & MNT_UNMOUNTING); } int diff --git a/module/os/windows/spl/spl-vnode.c b/module/os/windows/spl/spl-vnode.c index 818515176937..2b87bdb800e9 100644 --- a/module/os/windows/spl/spl-vnode.c +++ b/module/os/windows/spl/spl-vnode.c @@ -450,6 +450,27 @@ dnlc_lookup(struct vnode *dvp, char *name) int dnlc_purge_vfsp(struct mount *mp, int flags) { + struct vnode *rvp; + IO_STATUS_BLOCK ioStatus; + + mutex_enter(&vnode_all_list_lock); + for (rvp = list_head(&vnode_all_list); + rvp; + rvp = list_next(&vnode_all_list, rvp)) { + + if (rvp->v_mount != mp) + continue; + + if (vnode_isdir(rvp)) + continue; + /* + if (vnode_isunlink(rvp)) + continue; + */ + CcFlushCache(&rvp->SectionObjectPointers, NULL, NULL, &ioStatus); + } + mutex_exit(&vnode_all_list_lock); + return (0); } @@ -465,6 +486,7 @@ dnlc_remove(struct vnode *vp, char *name) void dnlc_update(struct vnode *vp, char *name, struct vnode *tp) { + } static int @@ -1700,7 +1722,8 @@ vflush(struct mount *mp, struct vnode *skipvp, int flags) mutex_enter(&rvp->v_mutex); - flush_file_objects(rvp); + // this hack is no longer needed + // flush_file_objects(rvp); // vnode_recycle_int() will exit v_mutex // re-check flags, due to releasing locks @@ -1761,7 +1784,7 @@ vflush(struct mount *mp, struct vnode *skipvp, int flags) dprintf("vflush end: deadlisted %d nodes\n", deadlist); - return (0); + return (reclaims > 0 ? EBUSY : 0); } int @@ -1995,6 +2018,8 @@ vnode_decouplefileobject(vnode_t *vp, FILE_OBJECT *fileobject) if (fileobject && fileobject->FsContext) { dprintf("%s: fo %p -X-> %p\n", __func__, fileobject, vp); + vnode_fileobject_remove(vp, fileobject); + // If we are flushing, we do nothing here. if (vp->v_flags & VNODE_FLUSHING) { dprintf("Already flushing; FS re-entry\n"); @@ -2002,7 +2027,6 @@ vnode_decouplefileobject(vnode_t *vp, FILE_OBJECT *fileobject) } // if (vnode_flushcache(vp, fileobject, FALSE)) - vnode_fileobject_remove(vp, fileobject); // fileobject->FsContext = NULL; } diff --git a/module/os/windows/zfs/zfs_ioctl_os.c b/module/os/windows/zfs/zfs_ioctl_os.c index f8bf7a79791c..f1a3f3775006 100644 --- a/module/os/windows/zfs/zfs_ioctl_os.c +++ b/module/os/windows/zfs/zfs_ioctl_os.c @@ -973,7 +973,7 @@ zfs_ioc_unregister_fs(void) OpenZFS_Driver_Extension *DriverExtension = (OpenZFS_Driver_Extension *)IoGetDriverObjectExtension(WIN_DriverObject, WIN_DriverObject); - DbgBreakPoint(); + if (DriverExtension->fsDiskDeviceObject != NULL) { IoUnregisterFsRegistrationChange(WIN_DriverObject, DriverNotificationRoutine); @@ -1025,6 +1025,9 @@ static DEVPROPKEY DEVPKEY_Device_HardwareIds = #undef INITGUID #endif +extern void +zfs_windows_unmount_free(PUNICODE_STRING symlink_name); + _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context) @@ -1034,8 +1037,10 @@ volume_notification(PVOID NotificationStructure, PVOID Context) if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID)) xprintf("%s arrival: %wZ\n", __func__, dicn->SymbolicLinkName); - else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID)) + else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID)) { xprintf("%s removal: %wZ\n", __func__, dicn->SymbolicLinkName); + zfs_windows_unmount_free(dicn->SymbolicLinkName); + } return (STATUS_SUCCESS); } @@ -1084,18 +1089,21 @@ OpenZFS_AddDevice( ) { NTSTATUS status; + UNICODE_STRING ntUnicodeString; // NT Device Name + UNICODE_STRING ntWin32NameString; // Win32 Name + int err; + static UNICODE_STRING sddl = RTL_CONSTANT_STRING( + L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)" + "(A;;GRGWGX;;;WD)(A;;GRGX;;;RC)"); + // Or use &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R if (PhysicalDeviceObject == NULL) { - DbgBreakPoint(); return (STATUS_NO_MORE_ENTRIES); } ZFS_DRIVER_EXTENSION(DriverObject, DriverExtension); - xprintf("%s called: PhysicalDeviceObject %p\n", __func__, PhysicalDeviceObject); - // DbgBreakPoint(); - if (DriverExtension == NULL) { dprintf("No DriverExtension? Help!\n"); return (STATUS_INVALID_PARAMETER); @@ -1128,37 +1136,14 @@ OpenZFS_AddDevice( zmo_bus->FunctionalDeviceObject = DriverExtension->FunctionalDeviceObject; zmo_bus->PhysicalDeviceObject = PhysicalDeviceObject; - - // status = IoReportDetectedDevice(WIN_DriverObject, InterfaceTypeUndefined, 0xFFFFFFFF, 0xFFFFFFFF, - // NULL, NULL, 0, &zmo_bus->PNPDeviceObject); - - // xprintf("%s called: PhysicalDeviceObject %p\n", __func__, zmo_bus->PhysicalDeviceObject); - // status = IoRegisterDeviceInterface(zmo_bus->PhysicalDeviceObject, &BtrfsBusInterface, NULL, - // &zmo_bus->deviceInterfaceName); - zmo_bus->AttachedDevice = IoAttachDeviceToDeviceStack(DriverExtension->FunctionalDeviceObject, zmo_bus->PhysicalDeviceObject); DriverExtension->LowerDeviceObject = zmo_bus->AttachedDevice; DriverExtension->FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - // status = IoSetDeviceInterfaceState(&zmo_bus->deviceInterfaceName, TRUE); - - // IoInvalidateDeviceRelations(zmo_bus->PhysicalDeviceObject, BusRelations); - -#if 1 - NTSTATUS ntStatus; - UNICODE_STRING ntUnicodeString; // NT Device Name - UNICODE_STRING ntWin32NameString; // Win32 Name - int err; - - static UNICODE_STRING sddl = RTL_CONSTANT_STRING( - L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)" - "(A;;GRGWGX;;;WD)(A;;GRGX;;;RC)"); - // Or use &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R - RtlInitUnicodeString(&ntUnicodeString, ZFS_DEV_KERNEL); - ntStatus = IoCreateDeviceSecure( + status = IoCreateDeviceSecure( WIN_DriverObject, sizeof (mount_t), &ntUnicodeString, // Device name "\Device\SIOCTL" @@ -1169,15 +1154,11 @@ OpenZFS_AddDevice( NULL, &DriverExtension->ioctlDeviceObject); // Returned ptr to Device Object - if (!NT_SUCCESS(ntStatus)) { + if (!NT_SUCCESS(status)) { dprintf("ZFS: Couldn't create the device object " "/dev/zfs (%S)\n", ZFS_DEV_KERNEL); - return (ntStatus); + return (status); } - // dprintf("ZFS: created kernel device node: %p: name %S\n", - // DriverExtension->ioctlDeviceObject, ZFS_DEV_KERNEL); - - // ObReferenceObject(ioctlDeviceObject); mount_t *dgl; dgl = DriverExtension->ioctlDeviceObject->DeviceExtension; @@ -1186,29 +1167,21 @@ OpenZFS_AddDevice( // Initialize a Unicode String containing the Win32 name // for our device. -#if 1 + RtlInitUnicodeString(&ntWin32NameString, ZFS_DEV_DOS); - // RtlInitUnicodeString(&ntWin32NameString, L"\\DosDevices\\Global\\OpenZFS"); // Create a symbolic link between our device name and the Win32 name - ntStatus = IoCreateSymbolicLink( + status = IoCreateSymbolicLink( &ntWin32NameString, &ntUnicodeString); - if (!NT_SUCCESS(ntStatus)) { + if (!NT_SUCCESS(status)) { dprintf("ZFS: Couldn't create userland symbolic link to " "/dev/zfs (%wZ)\n", ZFS_DEV); - // ObDereferenceObject(ioctlDeviceObject); IoDeleteDevice(DriverExtension->ioctlDeviceObject); return (-1); } -#endif - // dprintf("ZFS: created userland device symlink\n"); DriverExtension->ioctlDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; -#endif - - - xprintf("bus is up and running\n"); return (STATUS_SUCCESS); } diff --git a/module/os/windows/zfs/zfs_vnops_windows.c b/module/os/windows/zfs/zfs_vnops_windows.c index f9475d6c1ff6..db313eda3605 100644 --- a/module/os/windows/zfs/zfs_vnops_windows.c +++ b/module/os/windows/zfs/zfs_vnops_windows.c @@ -386,7 +386,7 @@ zfs_couplefileobject(vnode_t *vp, vnode_t *dvp, FILE_OBJECT *fileobject, } static void -zfs_decouplefileobject(vnode_t *vp, FILE_OBJECT *fileobject) +zfs_decouplefileobject(vnode_t *vp, FILE_OBJECT *fileobject, boolean_t SkipCache) { // We release FsContext2 at CLEANUP, but fastfat releases it in // CLOSE. Does this matter? @@ -404,16 +404,13 @@ zfs_decouplefileobject(vnode_t *vp, FILE_OBJECT *fileobject) if (zccb->z_name_cache != NULL) kmem_free(zccb->z_name_cache, zccb->z_name_len); zccb->z_name_cache = NULL; -#if DBG - zccb->z_name_len = 0x12345678; // DBG: show we freed -#else zccb->z_name_len = 0; -#endif kmem_free(zccb, sizeof (zfs_ccb_t)); fileobject->FsContext2 = NULL; } - CcUninitializeCacheMap(fileobject, NULL, NULL); + if (!SkipCache) + CcUninitializeCacheMap(fileobject, NULL, NULL); vnode_decouplefileobject(vp, fileobject); } @@ -832,6 +829,9 @@ zfs_vnop_lookup_impl(PIRP Irp, PIO_STACK_LOCATION IrpSp, mount_t *zmo, if (zfsvfs == NULL) return (STATUS_OBJECT_PATH_NOT_FOUND); + if (vfs_isunmount(zmo)) + return (STATUS_DEVICE_NOT_READY); + FileObject = IrpSp->FileObject; Options = IrpSp->Parameters.Create.Options; @@ -934,6 +934,10 @@ zfs_vnop_lookup_impl(PIRP Irp, PIO_STACK_LOCATION IrpSp, mount_t *zmo, if (FileObject->FileName.Length == 0 && FileObject->RelatedFileObject == NULL) { + // don't allow root to be opened on unmounted FS + if (!(zmo->vpb->Flags & VPB_MOUNTED)) + return (STATUS_DEVICE_NOT_READY); + dprintf("Started NULL open, returning root of mount\n"); error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp); if (error != 0) @@ -2296,6 +2300,9 @@ pnp_device_state(PDEVICE_OBJECT DeviceObject, PIRP Irp, PPNP_DEVICE_STATE pDeviceState = (PPNP_DEVICE_STATE)&Irp->IoStatus.Information; pDeviceState = 0; + + if (vfs_isunmount(DeviceObject->DeviceExtension)) + Irp->IoStatus.Information |= PNP_DEVICE_REMOVED; // Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; return (STATUS_SUCCESS); @@ -4027,7 +4034,6 @@ user_fs_request(PDEVICE_OBJECT DeviceObject, PIRP *PIrp, break; case FSCTL_DISMOUNT_VOLUME: dprintf(" FSCTL_DISMOUNT_VOLUME\n"); - DbgBreakPoint(); break; case FSCTL_MARK_VOLUME_DIRTY: dprintf(" FSCTL_MARK_VOLUME_DIRTY\n"); @@ -6116,34 +6122,19 @@ ioctl_volume_get_volume_disk_extents(PDEVICE_OBJECT DeviceObject, } NTSTATUS -volume_create(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) +volume_create(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, + USHORT ShareAccess, uint64_t AllocationSize, ACCESS_MASK DesiredAccess) { mount_t *zmo = DeviceObject->DeviceExtension; - // This is also called from fsContext when IRP_MJ_CREATE - // FileName is NULL - /* VERIFY(zmo->type == MOUNT_TYPE_DCB); */ #if 1 if (zmo->vpb != NULL) - IrpSp->FileObject->Vpb = zmo->vpb; + FileObject->Vpb = zmo->vpb; else - IrpSp->FileObject->Vpb = DeviceObject->Vpb; + FileObject->Vpb = DeviceObject->Vpb; #endif - // dprintf("Setting FileObject->Vpb to %p\n", IrpSp->FileObject->Vpb); - // SetFileObjectForVCB(IrpSp->FileObject, zmo); - // IrpSp->FileObject->SectionObjectPointer = - // &zmo->SectionObjectPointers; - // IrpSp->FileObject->FsContext = &zmo->VolumeFileHeader; - -/* - * Check the ShareAccess requested: - * 0 : exclusive - * FILE_SHARE_READ : The file can be opened for read access by other threads - * FILE_SHARE_WRITE : The file can be opened for write access by other threads - * FILE_SHARE_DELETE : The file can be opened for del access by other threads - */ - if ((IrpSp->Parameters.Create.ShareAccess == 0) && + if ((ShareAccess == 0) && zmo->volume_opens != 0) { dprintf("%s: sharing violation\n", __func__); return (STATUS_SHARING_VIOLATION); @@ -6153,28 +6144,37 @@ volume_create(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) zfsvfs_t *zfsvfs; znode_t *zp; struct vnode *vp; - PFILE_OBJECT FileObject; zfs_ccb_t *zccb = NULL; + NTSTATUS status = STATUS_VOLUME_DISMOUNTED; - FileObject = IrpSp->FileObject; zfsvfs = (zfsvfs_t *) vfs_fsprivate(zmo); + + if ((error = zfs_enter(zfsvfs, FTAG)) != 0) + return (error); + error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp); if (error == 0) { vp = ZTOV(zp); + + if (vp == NULL) + goto out; + + dprintf("%s increasing %p\n", __func__, vp); zfs_couplefileobject(vp, NULL, FileObject, zp->z_size, &zccb, - Irp-> - Overlay.AllocationSize.QuadPart, - IrpSp->Parameters.Create.SecurityContext->DesiredAccess, + AllocationSize, + DesiredAccess, NULL); VN_RELE(vp); - Irp->IoStatus.Information = FILE_OPENED; - return (STATUS_SUCCESS); + status = STATUS_SUCCESS; } - return (STATUS_SUCCESS); +out: + zfs_exit(zfsvfs, FTAG); + + return (status); } NTSTATUS @@ -6199,10 +6199,10 @@ volume_close(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) if (error == 0) { vp = ZTOV(zp); - zfs_decouplefileobject(vp, FileObject); + zfs_decouplefileobject(vp, FileObject, B_TRUE); + dprintf("%s decreasing %p\n", __func__, vp); vnode_rele(vp); VN_RELE(vp); - return (STATUS_SUCCESS); } @@ -6436,7 +6436,7 @@ zfs_fileobject_close(PDEVICE_OBJECT DeviceObject, PIRP Irp, // FileObject should/could no longer point to vp. // this also frees zccb - zfs_decouplefileobject(vp, IrpSp->FileObject); + zfs_decouplefileobject(vp, IrpSp->FileObject, B_FALSE); zccb = NULL; // vnode_fileobject_remove(vp, IrpSp->FileObject); @@ -6671,7 +6671,6 @@ _Function_class_(DRIVER_DISPATCH) default: dprintf("**** unknown pnp IRP_MJ_PNP: 0x%lx\n", IrpSp->MinorFunction); //0x0b - DbgBreakPoint(); break; } break; @@ -6701,7 +6700,6 @@ _Function_class_(DRIVER_DISPATCH) default: dprintf("**** unknown pnp IRP_MJ_: 0x%lx\n", IrpSp->MajorFunction); // 0x0e - DbgBreakPoint(); // minor 00 } return (Status); @@ -6882,7 +6880,6 @@ _Function_class_(DRIVER_DISPATCH) default: dprintf("**** unknown Windows IOCTL: 0x%lx\n", cmd); - DbgBreakPoint(); } } @@ -6940,7 +6937,6 @@ _Function_class_(DRIVER_DISPATCH) case IRP_MN_START_DEVICE: dprintf("IRP_MN_START_DEVICE\n"); Status = STATUS_SUCCESS; - DbgBreakPoint(); break; case IRP_MN_CANCEL_REMOVE_DEVICE: dprintf("IRP_MN_CANCEL_REMOVE_DEVICE\n"); @@ -6995,7 +6991,13 @@ _Function_class_(DRIVER_DISPATCH) IrpSp->FileObject->RelatedFileObject : NULL, IrpSp->FileObject->FileName, IrpSp->Flags); - Status = volume_create(DeviceObject, Irp, IrpSp); + Status = volume_create(DeviceObject, IrpSp->FileObject, + IrpSp->Parameters.Create.ShareAccess, + Irp->Overlay.AllocationSize.QuadPart, + IrpSp->Parameters.Create.SecurityContext->DesiredAccess + ); + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = FILE_OPENED; break; case IRP_MJ_CLOSE: Status = volume_close(DeviceObject, Irp, IrpSp); @@ -7044,7 +7046,10 @@ _Function_class_(DRIVER_DISPATCH) break; case IOCTL_VOLUME_ONLINE: dprintf("IOCTL_VOLUME_ONLINE\n"); - Status = STATUS_SUCCESS; + if (vfs_isunmount(DeviceObject->DeviceExtension)) + Status = STATUS_VOLUME_DISMOUNTED; + else + Status = STATUS_SUCCESS; break; case IOCTL_VOLUME_OFFLINE: case IOCTL_VOLUME_IS_OFFLINE: @@ -7177,7 +7182,6 @@ _Function_class_(DRIVER_DISPATCH) case IRP_MJ_WRITE: dprintf("disk fake write\n"); - DbgBreakPoint(); Irp->IoStatus.Information = IrpSp->Parameters.Write.Length; Status = STATUS_SUCCESS; break; @@ -7671,7 +7675,6 @@ _Function_class_(DRIVER_DISPATCH) default: dprintf("Unknown IRP_MJ_PNP(fs): 0x%x\n", IrpSp->MinorFunction); - DbgBreakPoint(); break; } break; @@ -7915,6 +7918,17 @@ _Function_class_(DRIVER_DISPATCH) dprintf("Lower Bus Device said 0x%0x %s\n", Status, common_status_str(Status)); + } else if ((Status == STATUS_INVALID_DEVICE_REQUEST) && + zmo != NULL && // vcb->parent_device = dcb + zmo->parent_device != NULL) { + dprintf("Passing request %s down bus\n", + major2str(IrpSp->MajorFunction, IrpSp->MinorFunction)); + + zmo = zmo->parent_device; // We are now dcb + Status = diskDispatcher(zmo->FunctionalDeviceObject, &Irp, IrpSp); + dprintf("Direct DDCB said 0x%0x %s\n", Status, + common_status_str(Status)); + } else if (Status != STATUS_PENDING && Irp != NULL) { // IOCTL_STORAGE_GET_HOTPLUG_INFO // IOCTL_DISK_CHECK_VERIFY diff --git a/module/os/windows/zfs/zfs_vnops_windows_lib.c b/module/os/windows/zfs/zfs_vnops_windows_lib.c index fe0e82c4ee5b..9e56d4cd2f42 100644 --- a/module/os/windows/zfs/zfs_vnops_windows_lib.c +++ b/module/os/windows/zfs/zfs_vnops_windows_lib.c @@ -386,6 +386,8 @@ common_status_str(NTSTATUS Status) return ("STATUS_VOLUME_MOUNTED"); case STATUS_VOLUME_DISMOUNTED: return ("STATUS_VOLUME_DISMOUNTED"); + case STATUS_DEVICE_NOT_READY: + return ("STATUS_DEVICE_NOT_READY"); default: return ("<*****>"); } @@ -5535,7 +5537,6 @@ QueryDeviceRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp, ReturnDevice = zmo_dcb->PhysicalDeviceObject; else { ReturnDevice = DeviceObject; // wrong - DbgBreakPoint(); } ObReferenceObject(ReturnDevice); @@ -5592,7 +5593,6 @@ QueryDeviceRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp, break; } default: - DbgBreakPoint(); } out: @@ -6045,7 +6045,7 @@ ioctl_storage_query_property(PDEVICE_OBJECT DeviceObject, PIRP Irp, case StorageDeviceUniqueIdProperty: dprintf(" PropertyExistsQuery " "StorageDeviceUniqueIdProperty\n"); - DbgBreakPoint(); + if (spq->QueryType == PropertyExistsQuery) return (STATUS_SUCCESS); dprintf(" PropertyStandardQuery " @@ -6189,7 +6189,7 @@ ioctl_query_unique_id(PDEVICE_OBJECT DeviceObject, PIRP Irp, return (STATUS_BUFFER_TOO_SMALL); } -#if 0 +#if 1 RtlUnicodeToUTF8N(osname, MAXPATHLEN - 1, &len, zmo->name.Buffer, zmo->name.Length); osname[len] = 0; diff --git a/module/os/windows/zfs/zfs_vnops_windows_mount.c b/module/os/windows/zfs/zfs_vnops_windows_mount.c index b73f123c9905..6da90e695d69 100644 --- a/module/os/windows/zfs/zfs_vnops_windows_mount.c +++ b/module/os/windows/zfs/zfs_vnops_windows_mount.c @@ -59,7 +59,7 @@ extern int getzfsvfs(const char *dsname, zfsvfs_t **zfvp); -uint64_t zfs_disable_removablemedia = 0; +uint64_t zfs_disable_removablemedia = 1; ZFS_MODULE_RAW(zfs, disable_removablemedia, zfs_disable_removablemedia, U64, ZMOD_RW, 0, "Disable Removable Media"); @@ -615,25 +615,6 @@ RegisterDeviceInterface(__in PDRIVER_OBJECT DriverObject, return (status); } -#if 0 - status = IoRegisterDeviceInterface( - pnpDeviceObject, - &GUID_DEVINTERFACE_VOLUME, - NULL, - &Dcb->volumeInterfaceName - ); - - if (!NT_SUCCESS(status)) { - dprintf("Failed to register GUID_DEVINTERFACE_VOLUME: %08x\n", status); - } - - // Enable the device interface - status = IoSetDeviceInterfaceState(&Dcb->volumeInterfaceName, TRUE); - if (!NT_SUCCESS(status)) { - KdPrint(("Failed to enable GUID_DEVINTERFACE_VOLUME: %08x\n", status)); - } -#endif - return (status); } @@ -690,8 +671,8 @@ SendVolumeCreatePoint(__in PUNICODE_STRING DeviceName, NTSTATUS NotifyMountMgr( - PUNICODE_STRING unicodeSourceVolumeName, // "\??\E:\ntfs\" - PUNICODE_STRING unicodeTargetVolumeName, // "\??\Volume{xxxxxx-xxxx-xxxx-xxxx-xxxxxxx}\" + PUNICODE_STRING unicodeSourceVolumeName, // "\??\E:\ntfs" + PUNICODE_STRING unicodeTargetVolumeName, // "\??\Volume{xxxxxx-xxxx-xxxx-xxxx-xxxxxxx}" boolean_t IsPointCreated ) { @@ -740,7 +721,8 @@ NotifyMountMgr( dprintf(" TargetVolumeName: %wZ\n", unicodeTargetVolumeName); status = SendIoctlToMountManager( - IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED, + IsPointCreated ? IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED : + IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED, input, inputSize, NULL, 0); if (NT_SUCCESS(status)) { @@ -835,6 +817,9 @@ SendVolumeDeletePoints(__in PUNICODE_STRING MountPoint, void zfs_release_mount(mount_t *zmo) { + dprintf("Releasing mount %p\n", zmo); + FreeUnicodeString(&zmo->name); + FreeUnicodeString(&zmo->arc_name); FreeUnicodeString(&zmo->symlink_name); FreeUnicodeString(&zmo->device_name); FreeUnicodeString(&zmo->fs_name); @@ -918,31 +903,13 @@ zfs_windows_mount(zfs_cmd_t *zc) status = RtlAnsiStringToUnicodeString(&diskDeviceName, &pants, TRUE); dprintf("%s: new devstring '%wZ'\n", __func__, &diskDeviceName); -#if 0 - /* This creates the FDO - Functional Device Object */ - status = IoCreateDeviceSecure(WIN_DriverObject, - sizeof (mount_t), - &diskDeviceName, - FILE_DEVICE_DISK, - deviceCharacteristics | FILE_DEVICE_IS_MOUNTED, - FALSE, - &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R, - NULL, - &diskDeviceObject); - - if (status != STATUS_SUCCESS) { - dprintf("IoCreateDeviceSecure returned %08lx\n", status); - return (status); - } - -#else // Autogen gives a name like \Device\00000a9 status = IoCreateDevice(WIN_DriverObject, sizeof (mount_t), &diskDeviceName, FILE_DEVICE_DISK, deviceCharacteristics | FILE_DEVICE_SECURE_OPEN, FALSE, &diskDeviceObject); xprintf("Created ChildDeviceObject %p\n", diskDeviceObject); -#endif + if (status != STATUS_SUCCESS) { dprintf("IoCreateDeviceSecure returned %08lx\n", status); return (status); @@ -969,8 +936,6 @@ zfs_windows_mount(zfs_cmd_t *zc) zmo_dcb->FunctionalDeviceObject = diskDeviceObject; zmo_dcb->PhysicalDeviceObject = DriverExtension->PhysicalDeviceObject; - // So DeviceRelations can return it - DriverExtension->ChildDeviceObject = diskDeviceObject; // So AddDevice can match us DriverExtension->AddDeviceObject = diskDeviceObject; @@ -1009,15 +974,9 @@ zfs_windows_mount(zfs_cmd_t *zc) diskDeviceObject->Flags |= DO_DIRECT_IO; diskDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE; - DbgBreakPoint(); - // diskDeviceObject->Flags |= DO_POWER_PAGABLE; diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; -// zmo_dcb->AttachedDevice = IoAttachDeviceToDeviceStack(diskDeviceObject, -// DriverExtension->PhysicalDeviceObject); - // zmo_dcb->AttachedDevice = IoAttachDeviceToDeviceStack(diskDeviceObject, - // DriverExtension->FunctionalDeviceObject); status = IoCreateSymbolicLink(&zmo_dcb->symlink_name, &zmo_dcb->device_name); status = IoCreateSymbolicLink(&zmo_dcb->arc_name, &zmo_dcb->device_name); @@ -1053,29 +1012,6 @@ zfs_windows_mount(zfs_cmd_t *zc) return (status); } - // VERIFY3P(zmo_dcb->fsprivate->z_zil, !=, NULL); - -#if 0 - status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0, FileObject, - WIN_DriverObject, pnp_removal, pdode, &zmo_dcb->notification_entry); - if (!NT_SUCCESS(status)) - dprintf("IoRegisterPlugPlayNotification returned %08lx\n", status); -// #else - - status = RegisterDeviceInterface(WIN_DriverObject, - diskDeviceObject, zmo_dcb); - - status = IoCreateSymbolicLink(&symbolicLinkTarget, &diskDeviceName); - // status = IoCreateSymbolicLink(&zmo_dcb->deviceInterfaceName, &diskDeviceName); - - if (!NT_SUCCESS(status)) { - IoDeleteDevice(diskDeviceObject); - dprintf(" IoCreateSymbolicLink returned 0x%lx\n", status); - return (status); - } -#else - -#endif // Check if we are to mount with driveletter, or path // We already check that path is "\\??\\" above, and // at least 6 chars. Seventh char can be zero, or "/" @@ -1088,10 +1024,6 @@ zfs_windows_mount(zfs_cmd_t *zc) zmo_dcb->justDriveLetter = B_FALSE; } - // Remember mountpoint path - // if (zmo_dcb->mountpoint.Buffer) - // FreeUnicodeString(&zmo_dcb->mountpoint); - AsciiStringToUnicodeString(zc->zc_value, &zmo_dcb->mountpoint); dprintf("%s: driveletter %d '%wZ'\n", @@ -1129,11 +1061,6 @@ zfs_windows_mount(zfs_cmd_t *zc) xprintf("Bumping bus after creating disk\n"); dprintf("Bumping bus after creating disk\n"); -// status = IoRegisterDeviceInterface(DriverExtension->PhysicalDeviceObject, &GUID_DEVINTERFACE_VOLUME, NULL, -// &zmo->deviceInterfaceName); - -// status = IoSetDeviceInterfaceState(&zmo->deviceInterfaceName, TRUE); - // Add to list for BusRelations vfs_mount_add(zmo_dcb); @@ -1238,7 +1165,7 @@ NotifyMountMgr_impl(void *arg1) "volume '%wZ'\n", &dcb->mountpoint, &volStr); - DbgBreakPoint(); + delay(hz); status = CreateReparsePoint(&poa, &volStr, &volStr); @@ -1652,8 +1579,6 @@ mount_volume_impl(mount_t *dcb, mount_t *vcb) { NTSTATUS status; - DbgBreakPoint(); - dprintf("MOUNT starts here\n"); UNICODE_STRING name; @@ -1760,7 +1685,8 @@ mount_volume_impl(mount_t *dcb, mount_t *vcb) } } else { - RtlInitUnicodeString(&dcb->mountpoint, L"\\??\\E:\\dataset"); + + // RtlInitUnicodeString(&dcb->mountpoint, L"\\??\\E:\\dataset"); // Fire off the announce taskq_dispatch(system_taskq, NotifyMountMgr_impl, @@ -1791,6 +1717,8 @@ mount_volume_impl(mount_t *dcb, mount_t *vcb) } +extern int zfs_init_cache(FILE_OBJECT *fo, struct vnode *vp, CC_FILE_SIZES *ccfs); + NTSTATUS matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t *dcb, PVPB vpb) { @@ -1806,27 +1734,21 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t return (STATUS_UNRECOGNIZED_VOLUME); } - xprintf("%s\n", __func__); - - // ZFS Dataset being mounted: - // dprintf("%s: mounting '%wZ'\n", __func__, dcb->name); - // We created a DISK before, now we create a VOLUME ULONG deviceCharacteristics; deviceCharacteristics = 0; // FILE_DEVICE_IS_MOUNTED; + /* Allow $recycle.bin - don't set removable. */ -// if (!zfs_disable_removablemedia) -// deviceCharacteristics |= FILE_REMOVABLE_MEDIA; + if (!zfs_disable_removablemedia) + deviceCharacteristics |= FILE_REMOVABLE_MEDIA; if (dcb->mountflags & MNT_RDONLY) deviceCharacteristics |= FILE_READ_ONLY_DEVICE; - DbgBreakPoint(); /* This creates the VDO - VolumeDeviceObject */ status = IoCreateDevice(WIN_DriverObject, sizeof (mount_t), &dcb->fs_name, -// FILE_DEVICE_DISK, FILE_DEVICE_DISK_FILE_SYSTEM, deviceCharacteristics/*|FILE_DEVICE_IS_MOUNTED*/, FALSE, @@ -1834,6 +1756,7 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t if (!NT_SUCCESS(status)) { dprintf("%s: IoCreateDevice failed: 0x%lx\n", __func__, status); + return (STATUS_UNRECOGNIZED_VOLUME); } mount_t *vcb = volDeviceObject->DeviceExtension; @@ -1874,6 +1797,7 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t // RtlDuplicateUnicodeString(0, &dcb->device_name, &vcb->device_name); RtlDuplicateUnicodeString(0, &dcb->fs_name, &vcb->device_name); RtlDuplicateUnicodeString(0, &dcb->symlink_name, &vcb->symlink_name); + RtlDuplicateUnicodeString(0, &dcb->arc_name, &vcb->arc_name); RtlDuplicateUnicodeString(0, &dcb->uuid, &vcb->uuid); memcpy(vcb->rawuuid, dcb->rawuuid, sizeof (vcb->rawuuid)); // RtlDuplicateUnicodeString(0, &dcb->mountpoint, &vcb->mountpoint); @@ -1886,28 +1810,24 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t InitializeListHead(&vcb->DirNotifyList); FsRtlNotifyInitializeSync(&vcb->NotifySync); - dcb->root_file = IoCreateStreamFileObject(NULL, DeviceToMount); - if (dcb->root_file != NULL) { + vcb->root_file = IoCreateStreamFileObject(NULL, DeviceToMount); + if (vcb->root_file != NULL) { struct vnode *vp; struct znode *zp; zfs_ccb_t *zccb; - - dcb->root_file->Vpb = vpb; - vnode_create(dcb, NULL, NULL, VDIR, VNODE_MARKROOT, &vp); - dcb->root_file->FsContext = vp; - vnode_ref(vp); - vnode_couplefileobject(vp, dcb->root_file, 0); - zp = kmem_cache_alloc(znode_cache, KM_SLEEP); - zp->z_vnode = vp; - vp->v_data = zp; - zccb = kmem_zalloc(sizeof (zfs_ccb_t), KM_SLEEP); - zccb->magic = ZFS_CCB_MAGIC; - dcb->root_file->FsContext2 = zccb; - zccb->z_name_len = 2; - zccb->z_name_cache = kmem_zalloc(zccb->z_name_len, KM_SLEEP); - zccb->z_name_cache[0] = '/'; - zccb->z_name_cache[1] = 0; - zccb->z_name_offset = 0; + dprintf("root_file is %p\n", vcb->root_file); + // Attach vp/zp to it. They call volume_close() when released. + status = volume_create(dcb->PhysicalDeviceObject, vcb->root_file, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0ULL, + FILE_READ_ATTRIBUTES); + vp = vcb->root_file->FsContext; + if (VN_HOLD(vp) == 0) { + vnode_ref(vp); + VN_RELE(vp); + } + /* This open needs to point to the real root zp */ + vcb->root_file->Vpb = vpb; } KIRQL OldIrql; @@ -1917,9 +1837,9 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t volDeviceObject->Vpb = vpb; vcb->vpb = vpb; vpb->ReferenceCount++; - vpb->ReferenceCount++; - vpb->ReferenceCount++; - vpb->ReferenceCount+=50; +// vpb->ReferenceCount++; +// vpb->ReferenceCount++; +// vpb->ReferenceCount+=50; xprintf("%p ReferenceCount is %d\n", vpb, vpb->ReferenceCount); // So we can reply to FileFsVolumeInformation @@ -1941,12 +1861,11 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t // Ntfs does not even call IoAttachDeviceToDeviceStack(). // However, we attach, so we can relay the IRP down to our // disk device easily. -#if 1 - DbgBreakPoint(); - +#if 0 + // This deadlocks between fltmgr and mountmgr PDEVICE_OBJECT attachedDevice; attachedDevice = IoAttachDeviceToDeviceStack(volDeviceObject, - DeviceObject); // DeviceToMount); + DeviceObject); // DeviceToMount); // definitely deadlocks // DeviceToMount); // DeviceToMount); if (attachedDevice == NULL) { IoDeleteDevice(volDeviceObject); @@ -1958,8 +1877,6 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t #endif volDeviceObject->StackSize = DeviceObject->StackSize + 1; - // ObReferenceObject(volDeviceObject); - status = STATUS_SUCCESS; @@ -1980,9 +1897,6 @@ matched_mount(PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT DeviceToMount, mount_t return (status); } -static void *fudgeptr = NULL; -static void *fudgepdo = NULL; - int zfs_vnop_mount(PDEVICE_OBJECT DiskDevice, PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -2001,8 +1915,6 @@ zfs_vnop_mount(PDEVICE_OBJECT DiskDevice, PIRP Irp, PIO_STACK_LOCATION IrpSp) if (DiskDevice != DriverExtension->fsDiskDeviceObject) return (STATUS_INVALID_DEVICE_REQUEST); - - DeviceToMount = IrpSp->Parameters.MountVolume.DeviceObject; @@ -2019,65 +1931,10 @@ zfs_vnop_mount(PDEVICE_OBJECT DiskDevice, PIRP Irp, PIO_STACK_LOCATION IrpSp) // DeviceToMount must be released from here down mount_t *dcb = NULL; -// if (IrpSp->Parameters.MountVolume.DeviceObject->Vpb == NULL) -// return (STATUS_UNRECOGNIZED_VOLUME); - -// dcb = IrpSp->Parameters.MountVolume.DeviceObject->Vpb->RealDevice->DeviceExtension; - dcb = DeviceToMount->DeviceExtension; - if (dcb == NULL || dcb->type != MOUNT_TYPE_DCB) { - ObDereferenceObject(DeviceToMount); - return (STATUS_UNRECOGNIZED_VOLUME); - } - - DbgBreakPoint(); - status = matched_mount(IrpSp->Parameters.MountVolume.DeviceObject, - DeviceToMount, - dcb, IrpSp->Parameters.MountVolume.Vpb); - ObDereferenceObject(DeviceToMount); - return (status); - - - - DeviceToMount = IoGetDeviceAttachmentBaseRef(IrpSp-> - Parameters.MountVolume.DeviceObject); - dprintf("*** mount request for %p : minor\n", DeviceToMount); - - if (DeviceToMount == NULL) { - dprintf("%s: DeviceToMount is NULL\n", __func__); - return (STATUS_UNRECOGNIZED_VOLUME); - } - - if (DeviceToMount->DriverObject == WIN_DriverObject) { - dprintf("*** The device belong to us\n"); - dcb = DeviceToMount->DeviceExtension; - } else { - dprintf("*** The device does NOT belong to us\n"); - status = STATUS_UNRECOGNIZED_VOLUME; -// goto out; - } - - // If it comes from "\Driver\PnpManager" - if (DeviceToMount->AttachedDevice != NULL && - DeviceToMount->AttachedDevice->DriverObject == WIN_DriverObject) { - dprintf("*** The device belong to us after all\n"); - dcb = DeviceToMount->AttachedDevice->DeviceExtension; - status = 0; - } - - if (dcb == NULL) { - dprintf("%s: Not a ZFS dataset -- ignoring\n", __func__); - status = STATUS_UNRECOGNIZED_VOLUME; - goto out; - } - - if ((dcb->type != MOUNT_TYPE_DCB) || - (dcb->size != sizeof (mount_t))) { - dprintf("%s: Not a ZFS dataset -- dcb %p ignoring: " - "type 0x%x != 0x%x, size %lu != %llu\n", - __func__, dcb, - dcb->type, MOUNT_TYPE_DCB, dcb->size, sizeof (mount_t)); + if (dcb == NULL || dcb->type != MOUNT_TYPE_DCB || + vfs_isunmount(dcb)) { status = STATUS_UNRECOGNIZED_VOLUME; goto out; } @@ -2086,8 +1943,7 @@ zfs_vnop_mount(PDEVICE_OBJECT DiskDevice, PIRP Irp, PIO_STACK_LOCATION IrpSp) DeviceToMount, dcb, IrpSp->Parameters.MountVolume.Vpb); - out: - // match IoGetDeviceAttachmentBaseRef() +out: ObDereferenceObject(DeviceToMount); dprintf("%s: exit: 0x%lx\n", __func__, status); @@ -2102,17 +1958,8 @@ mount_add_device(PDEVICE_OBJECT DriverObject, mount_t *zmo = (mount_t *)AddDeviceObject->DeviceExtension; ZFS_DRIVER_EXTENSION(DriverObject, DriverExtension); - xprintf("%s\n", __func__); - DbgBreakPoint(); - - // status = IoCreateDevice(DriverObject, sizeof(mount_t), - // &zmo->device_name, FILE_DEVICE_DISK, - // 0, FALSE, &zmo->VolumeDeviceObject); - zmo->PhysicalDeviceObject = PhysicalDeviceObject; - -#if 1 dprintf("register GUID_DEVINTERFACE_VOLUME\n"); status = IoRegisterDeviceInterface(PhysicalDeviceObject, &GUID_DEVINTERFACE_VOLUME, NULL, @@ -2129,16 +1976,6 @@ mount_add_device(PDEVICE_OBJECT DriverObject, status = IoRegisterDeviceInterface(PhysicalDeviceObject, &MOUNTDEV_MOUNTED_DEVICE_GUID, NULL, &zmo->fsInterfaceName); status = IoSetDeviceInterfaceState(&zmo->fsInterfaceName, TRUE); - -#endif - - - dprintf("AttachedToDevice of DISK PhysicalDeviceObject %p = zmo %p\n", - PhysicalDeviceObject, zmo); - xprintf("AttachedToDevice of DISK PhysicalDeviceObject %p = zmo %p\n", - PhysicalDeviceObject, zmo); - fudgeptr = zmo; - fudgepdo = PhysicalDeviceObject; } int @@ -2201,22 +2038,37 @@ zfs_remove_driveletter(mount_t *zmo) return (Status); } +static int +unmount_find_volume(void *arg, void *priv) +{ + mount_t *zmo_dcb = (mount_t *)arg; + UNICODE_STRING *symlink_name = (UNICODE_STRING *)priv; + + if ((zmo_dcb->deviceInterfaceName.Length == symlink_name->Length) && + RtlCompareMemory(zmo_dcb->deviceInterfaceName.Buffer, symlink_name->Buffer, symlink_name->Length) == symlink_name->Length) { + + // Let unmount continue below... + KeSetEvent((PRKEVENT)&zmo_dcb->volume_removed_event, SEMAPHORE_INCREMENT, FALSE); + return (1); + } + return (0); +} + +void +zfs_windows_unmount_free(PUNICODE_STRING symlink_name) +{ + dprintf("%s: looking for %wZ\n", __func__, symlink_name); + + vfs_mount_iterate(unmount_find_volume, symlink_name); +} + int zfs_windows_unmount(zfs_cmd_t *zc) { - // IRP_MN_QUERY_REMOVE_DEVICE - // IRP_MN_REMOVE_DEVICE - // FsRtlNotifyVolumeEvent(, FSRTL_VOLUME_DISMOUNT); - - // Use name, lookup zfsvfs - // use zfsvfs to get mount_t - // mount_t has deviceObject, names etc. mount_t *zmo; mount_t *zmo_dcb = NULL; zfsvfs_t *zfsvfs; int error = EBUSY; - // znode_t *zp; - // int rdonly; if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) { @@ -2232,19 +2084,12 @@ zfs_windows_unmount(zfs_cmd_t *zc) return (SET_ERROR(EBUSY)); } + // Has to be called before upgrading vfs lock + CcWaitForCurrentLazyWriterActivity(); + // getzfsvfs() grabs a READER lock, // convert it to WRITER, and wait for it. vfs_busy(zmo, LK_UPGRADE); - // All readers are no punted until properly unmounted. - - // Try issuing DISMOUNT ... this wont work unless - // "attached" in RegisterDeviceInterface() -// FILE_OBJECT *root_file; -// root_file = IoCreateStreamFileObject(NULL, -// zmo->VolumeDeviceObject); - ntstatus = FsRtlNotifyVolumeEvent(zmo->root_file, - FSRTL_VOLUME_DISMOUNT); -// ObDereferenceObject(root_file); UNICODE_STRING name; PFILE_OBJECT fileObject; @@ -2257,10 +2102,24 @@ zfs_windows_unmount(zfs_cmd_t *zc) DECLARE_UNICODE_STRING_SIZE(mountpath, PATH_MAX); status = mountmgr_get_drive_letter(mountmgr, &zmo->device_name, &mountpath); + // We used to loop here and keep deleting anything we find, + // but we are only allowed to remove symlinks, anything + // else and MountMgr ignores the device. + ObDereferenceObject(fileObject); // Save the parent device zmo_dcb = zmo->parent_device; + // Get ready to wait for the volume removed notification + KeInitializeEvent((PRKEVENT)&zmo_dcb->volume_removed_event, SynchronizationEvent, TRUE); + + dprintf("Set UNMOUNTING\n"); + vfs_setflags(zmo, MNT_UNMOUNTING); + vfs_setflags(zmo_dcb, MNT_UNMOUNTING); + + if (zmo->root_file) + ntstatus = FsRtlNotifyVolumeEvent(zmo->root_file, + FSRTL_VOLUME_DISMOUNT); // Flush volume // rdonly = !spa_writeable(dmu_objset_spa(zfsvfs->z_os)); @@ -2273,10 +2132,6 @@ zfs_windows_unmount(zfs_cmd_t *zc) // mount and create points manually (if necessary), // that should be ok hopefully - // We used to loop here and keep deleting anything we find, - // but we are only allowed to remove symlinks, anything - // else and MountMgr ignores the device. - ObDereferenceObject(fileObject); if (MOUNTMGR_IS_DRIVE_LETTER(&mountpath)) { @@ -2295,6 +2150,10 @@ zfs_windows_unmount(zfs_cmd_t *zc) // Remove directory, only for !driveletter ZwDeleteFile(&poa); + + status = NotifyMountMgr(&zmo_dcb->mountpoint, + &zmo_dcb->MountMgr_name, B_FALSE); + } KIRQL irql; @@ -2302,18 +2161,68 @@ zfs_windows_unmount(zfs_cmd_t *zc) zmo->vpb->Flags &= ~VPB_MOUNTED; // zmo_dcb->vpb->Flags &= ~VPB_MOUNTED; zmo->vpb->Flags |= VPB_DIRECT_WRITES_ALLOWED; - zmo->vpb->DeviceObject = NULL; + zmo->vpb->Flags |= VPB_REMOVE_PENDING; IoReleaseVpbSpinLock(irql); // Release any notifications -#if (NTDDI_VERSION >= NTDDI_VISTA) +//#if (NTDDI_VERSION >= NTDDI_VISTA) FsRtlNotifyCleanupAll(zmo->NotifySync, &zmo->DirNotifyList); -#endif +//#endif // This will make it try to mount again, so make sure we dont - status = SendVolumeRemovalNotification(&zmo_dcb->device_name); + // status = SendVolumeRemovalNotification(&zmo_dcb->device_name); + status = SendVolumeRemovalNotification(&zmo_dcb->MountMgr_name); + if (zmo->root_file) { + struct vnode *vp = zmo->root_file->FsContext; +#if 0 + if (vp && VN_HOLD(vp) == 0) { + znode_t *zp = VTOZ(vp); + vnode_fileobject_remove(vp, zmo->root_file); + dprintf("%s decreasing %p\n", __func__, vp); + VN_RELE(vp); + } +#endif + // this calls volumeclose, but stop any new volumeopen + ObDereferenceObject(zmo->root_file); + + zmo->root_file = NULL; + } + + IoInvalidateDeviceRelations(zmo_dcb->PhysicalDeviceObject, RemovalRelations); + + dnlc_purge_vfsp(zmo, 0); + + // Wait for LazyWrite to finish. + while (vnode_umount_preflight(zmo, NULL, + SKIPROOT|SKIPSYSTEM|SKIPSWAP) != 0) + delay(hz >> 2); + + // Release devices + IoDeleteSymbolicLink(&zmo->symlink_name); + + // zmo has Volume, and Attached + // IoSetDeviceInterfaceState(&zmo_dcb->volumeInterfaceName, FALSE); + IoSetDeviceInterfaceState(&zmo_dcb->fsInterfaceName, FALSE); + IoSetDeviceInterfaceState(&zmo_dcb->deviceInterfaceName, FALSE); + if (zmo->AttachedDevice) + IoDetachDevice(zmo->AttachedDevice); + zmo->AttachedDevice = NULL; + + // Deleting DeviceObject will free ->DeviceExtension, ie zmo, so last. + + delay(hz); + + + IoInvalidateDeviceState(zmo_dcb->FunctionalDeviceObject); + + // This time wait for root as well (volume_close) + while (vnode_umount_preflight(zmo, NULL, + 0) != 0) + delay(hz >> 2); + + dprintf("Calling unmount\n"); /* * We call mount on DCB, but shouldn't it be VCB? We * match unmount on DCB here so vflush can compare. @@ -2325,73 +2234,68 @@ zfs_windows_unmount(zfs_cmd_t *zc) if (error) goto out_unlock; - // Add to list for BusRelations - vfs_mount_remove(zmo_dcb); + // wait for volume removal notification + LARGE_INTEGER timeout; + timeout.QuadPart = -100000 * 10; + status = KeWaitForSingleObject(&zmo_dcb->volume_removed_event, Executive, + KernelMode, TRUE, &timeout); + // If we timeout, lets just continue unmount and hope for the best? - // Release devices - IoDeleteSymbolicLink(&zmo->symlink_name); - RtlFreeUnicodeString(&zmo->symlink_name); +#if 1 - DbgBreakPoint(); - if (zmo->root_file) { - struct vnode *vp = zmo->root_file->FsContext; - if (vp) { - kmem_cache_free(znode_cache, VTOZ(vp)); - vnode_rele(vp); - vnode_decouplefileobject(zmo->root_file->FsContext, zmo->root_file); - vnode_recycle(vp); - } - zfs_ccb_t *zccb = zmo->root_file->FsContext2; - if (zccb) { - if (zccb->z_name_cache != NULL) - kmem_free(zccb->z_name_cache, zccb->z_name_len); - kmem_free(zccb, sizeof (zfs_ccb_t)); - } + zmo->fsprivate = NULL; - ObDereferenceObject(zmo->root_file); - zmo->root_file = NULL; - } - - // zmo has Volume, and Attached - IoSetDeviceInterfaceState(&zmo_dcb->volumeInterfaceName, FALSE); - IoSetDeviceInterfaceState(&zmo_dcb->fsInterfaceName, FALSE); - IoSetDeviceInterfaceState(&zmo_dcb->deviceInterfaceName, FALSE); - IoDetachDevice(zmo->AttachedDevice); - zmo->AttachedDevice = NULL; - - // fsDeviceObject - if (zmo->VolumeDeviceObject) { - IoDeleteDevice(zmo->VolumeDeviceObject); - zmo->VolumeDeviceObject = NULL; - } - - zfs_release_mount(zmo); - zmo = NULL; // dcb has physical and functional // There should also be a diskDevice above us to release. if (zmo_dcb != NULL) { - if (zmo_dcb->PhysicalDeviceObject) - IoDeleteDevice(zmo_dcb->PhysicalDeviceObject); - zmo_dcb->PhysicalDeviceObject = NULL; - if (zmo_dcb->FunctionalDeviceObject) { + vfs_mount_remove(zmo_dcb); + + if (zmo_dcb->AttachedDevice) { IoDetachDevice(zmo_dcb->AttachedDevice); - IoDeleteDevice(zmo_dcb->FunctionalDeviceObject); + zmo_dcb->AttachedDevice = NULL; } - zmo_dcb->FunctionalDeviceObject = NULL; + + // Release strings in zmo, then zmo by calling IoDeleteDevice() zfs_release_mount(zmo_dcb); + + // Physical and Functional are same for DCB + if (zmo_dcb->PhysicalDeviceObject != zmo_dcb->FunctionalDeviceObject) + IoDeleteDevice(zmo_dcb->FunctionalDeviceObject); + + if (zmo_dcb->PhysicalDeviceObject) { + zmo_dcb->PhysicalDeviceObject->Vpb = NULL; + IoDeleteDevice(zmo_dcb->PhysicalDeviceObject); + } + zmo_dcb = NULL; } + IoAcquireVpbSpinLock(&irql); + zmo->vpb->ReferenceCount--; + zmo->vpb->DeviceObject = NULL; + IoReleaseVpbSpinLock(irql); + + // Release strings in zmo, then zmo by calling IoDeleteDevice() + if (zmo->VolumeDeviceObject) { + zfs_release_mount(zmo); + zmo->VolumeDeviceObject->Vpb = NULL; + IoDeleteDevice(zmo->VolumeDeviceObject); + zmo = NULL; + } + + ZFS_DRIVER_EXTENSION(WIN_DriverObject, DriverExtension); + IoInvalidateDeviceRelations(DriverExtension->PhysicalDeviceObject, RemovalRelations); +#endif error = 0; out_unlock: // counter to getzfvfs zfsvfs->z_vfs = NULL; - vfs_unbusy(zmo); + vfs_unbusy(NULL); } return (error); diff --git a/module/os/windows/zfs/zfs_vnops_windows_xattr.c b/module/os/windows/zfs/zfs_vnops_windows_xattr.c index b98caab3f1c2..2d92bd19c8c3 100644 --- a/module/os/windows/zfs/zfs_vnops_windows_xattr.c +++ b/module/os/windows/zfs/zfs_vnops_windows_xattr.c @@ -542,8 +542,11 @@ zpl_xattr_get_dir(struct vnode *ip, const char *name, zfs_uio_t *uio, if (xzp) zrele(xzp); - if (dxzp) - zrele(dxzp); + if (dxzp) { + vnode_t *vp = ZTOV(dxzp); + if (vp) + VN_RELE(vp); + } return (error); }