Skip to content

Commit ed0925d

Browse files
committed
Fix deletion of ReparsePoints that aren't mountpoints
rmdir of junctions should be allowed, but we do want to stop the mountpoints from being deleted (without unmounting) and that test was too coarse. Now we only prohibit removal of mountpoints. Signed-off-by: Jorgen Lundman <lundman@lundman.net>
1 parent 5632ca6 commit ed0925d

5 files changed

Lines changed: 41 additions & 4 deletions

File tree

include/os/windows/spl/sys/mount.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ void vfs_mount_iterate(int (*func)(void *, void *), void *);
176176
boolean_t vfs_mount_member(void *member);
177177
void vfs_set_mountedon(mount_t *mp, char *rootpath);
178178
const char *vfs_mountedon(mount_t *mp);
179+
mount_t *vfs_has_mount(const char *rpath);
179180

180181

181182
#endif /* SPL_MOUNT_H */

module/os/windows/spl/spl-mount.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,23 @@ vfs_mountedon(mount_t *mp)
296296
{
297297
return (mp->mounted_on ? mp->mounted_on : "\\");
298298
}
299+
300+
mount_t *
301+
vfs_has_mount(const char *rpath)
302+
{
303+
int count = 0;
304+
mount_t *node;
305+
306+
mutex_enter(&mount_list_lock);
307+
for (node = list_head(&mount_list);
308+
node;
309+
node = list_next(&mount_list, node)) {
310+
if (rpath && node->mounted_on &&
311+
strcmp(rpath, node->mounted_on) == 0) {
312+
mutex_exit(&mount_list_lock);
313+
return (node);
314+
}
315+
}
316+
mutex_exit(&mount_list_lock);
317+
return (NULL);
318+
}

module/os/windows/zfs/zfs_vnops_windows.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4237,6 +4237,17 @@ delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp,
42374237
return (STATUS_INVALID_PARAMETER);
42384238

42394239
znode_t *zp = VTOZ(vp);
4240+
zfs_ccb_t *zccb = FileObject->FsContext2;
4241+
4242+
// Is something mounted on here? We deny it, so that
4243+
// it has to be unmounted by us first. We will remove
4244+
// from list of mounts, before deleting reparse point
4245+
if (zccb &&
4246+
vfs_has_mount(zccb->z_name_cache)) {
4247+
dprintf("Denied due to being mountpoint\n");
4248+
VN_RELE(vp);
4249+
return (STATUS_CANNOT_DELETE);
4250+
}
42404251

42414252
if (zfsctl_is_node(zp)) {
42424253
VN_RELE(vp);

module/os/windows/zfs/zfs_vnops_windows_lib.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3447,10 +3447,10 @@ zfs_setunlink(FILE_OBJECT *fo, vnode_t *dvp)
34473447
goto out;
34483448
}
34493449

3450-
// Stopping reparsepoints in use, for now.
3451-
// Force them to call DELETE_REPARSE_POINT first
3452-
if ((zp->z_pflags & ZFS_REPARSE) /* && vnode_isinuse(vp, 0) */) {
3453-
Status = STATUS_CANNOT_DELETE;
3450+
// If it is a reparsepoint, deny if used as mountpoint
3451+
if ((zp->z_pflags & ZFS_REPARSE) && zccb &&
3452+
vfs_has_mount(zccb->z_name_cache)) {
3453+
Status = STATUS_ACCESS_DENIED;
34543454
goto out;
34553455
}
34563456

module/os/windows/zfs/zfs_vnops_windows_mount.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,11 @@ zfs_windows_unmount(zfs_cmd_t *zc)
22642264

22652265
} else {
22662266
// If mount uses reparsepoint (not driveletter)
2267+
// To let delete reparse point to succeed, the
2268+
// vfs_is_mountpoint() need to fail, so free the
2269+
// root mountpoint it uses.
2270+
vfs_set_mountedon(zmo, NULL);
2271+
22672272
OBJECT_ATTRIBUTES poa;
22682273

22692274
InitializeObjectAttributes(&poa,

0 commit comments

Comments
 (0)