Skip to content

Commit

Permalink
Fix lower dataset mounts and reparse point parsing
Browse files Browse the repository at this point in the history
Additionally, correct the reparse point ID
returned by directory listings.

Signed-off-by: Jorgen Lundman <[email protected]>
  • Loading branch information
lundman committed Jul 27, 2023
1 parent db1a2c9 commit f25ade0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
49 changes: 31 additions & 18 deletions module/os/windows/zfs/zfs_vnops_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,19 @@ stream_parse(char *filename, char **streamname)
* - HOLD on dvp
* - HOLD on vp
* - final parsed filename part in 'lastname' (in the case of creating an entry)
*
* IRP_MJ_CREATE calls
*
* zfsvfs Filename
* --------------------------------------------------------
* IRP_MJ_CREATE(pool, "/lower/today.txt")
* : lookup "lower", return STATUS_REPARSE
* : Set unparsed length rdp->Reserved = 10 ("/today.txt") * 2
* --------------------------------------------------------
* IRP_MJ_CREATE(lower, "/today.txt")
* : lookup "today.txt", return SUCCESS
*/

int
zfs_find_dvp_vp(zfsvfs_t *zfsvfs, char *filename, int finalpartmaynotexist,
int finalpartmustnotexist, char **lastname, struct vnode **dvpp,
Expand Down Expand Up @@ -506,29 +518,29 @@ zfs_find_dvp_vp(zfsvfs_t *zfsvfs, char *filename, int finalpartmaynotexist,
vp = ZTOV(zp);
ASSERT(zp != NULL);


/*
* If we come across a REPARSE, we stop processing here
* and pass the "zp" back for caller to do more processing,
* which might include returning "zp" (FILE_OPEN_REPARSE_POINT)
* and ReparseTag.
* But, if IRP->zfsvfs is the same as zp->zfsvfs, the lookup
* was already requested for "us" specifically, so keep going.
* This could fail with nested dirmounts? Only check lowest
* directory to bail.
* If they requested FileOpenReparsePoint, AND we are at the
* final-part, we open it normally.
* Other cases we need to ask for redriving the query
*/
if ((zp->z_pflags & ZFS_REPARSE) &&
(zfsvfs != zp->z_zfsvfs)) {

// Indicate if reparse was final part
if (zp->z_pflags & ZFS_REPARSE) {
/*
* Indicate if reparse was final part,
* caller will handle this case
*/
if (lastname)
*lastname = brkt;

if (dvpp != NULL)
*dvpp = dvp;
if (vpp != NULL)
*vpp = vp;
// VN_RELE(dvp);

return (STATUS_REPARSE);
}

Expand Down Expand Up @@ -968,9 +980,6 @@ zfs_vnop_lookup_impl(PIRP Irp, PIO_STACK_LOCATION IrpSp, mount_t *zmo,
(!finalname || !*finalname))
error = STATUS_SUCCESS;

if (error == STATUS_REPARSE && !FileOpenReparsePoint)
error = STATUS_IO_REPARSE_TAG_NOT_HANDLED;

if (error) {

/*
Expand Down Expand Up @@ -1002,12 +1011,16 @@ zfs_vnop_lookup_impl(PIRP Irp, PIO_STACK_LOCATION IrpSp, mount_t *zmo,
size, '!FSZ');
get_reparse_point_impl(zp, rpb, size);

// Return in Reserved the amount of path
// that was parsed.
/* FileObject->FileName.Length - parsed */
rpb->Reserved = (outlen -
((finalname - filename) +
strlen(finalname))) * sizeof (WCHAR);
/*
* Length, in bytes, of the unparsed portion of the
* file name pointed to by the FileName member of the
* associated file object.
* Should include the leading "/", when finalname
* here would be "lower".
*/
rpb->Reserved = strlen(finalname) * sizeof (WCHAR);
if (rpb->Reserved != 0)
rpb->Reserved += sizeof (WCHAR); // the slash

dprintf("%s: returning REPARSE\n", __func__);
Irp->IoStatus.Information = rpb->ReparseTag;
Expand Down
21 changes: 10 additions & 11 deletions module/os/windows/zfs/zfs_vnops_windows_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,10 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
// Is it worth warning about failed lookup here?
}

ULONG reparse_tag = 0;
if (tzp->z_pflags & ZFS_REPARSE)
reparse_tag = get_reparse_tag(tzp);

structsize = 0; /* size of win struct desired */
/* bufptr : output memory area, incrementing */
/* outcount : amount written to output, incrementing */
Expand Down Expand Up @@ -883,7 +887,7 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
// Magic code to change dir icon to link
eodp->EaSize =
tzp->z_pflags & ZFS_REPARSE ?
0xa0000003 :
reparse_tag :
xattr_getsize(ZTOV(tzp));
eodp->FileAttributes =
zfs_getwinflags(tzp);
Expand Down Expand Up @@ -921,7 +925,7 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
fibdi->LastAccessTime.QuadPart);
fibdi->EaSize =
tzp->z_pflags & ZFS_REPARSE ?
0xa0000003 :
reparse_tag :
xattr_getsize(ZTOV(tzp));
fibdi->FileAttributes =
zfs_getwinflags(tzp);
Expand Down Expand Up @@ -961,7 +965,7 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
fbdi->LastAccessTime.QuadPart);
fbdi->EaSize =
tzp->z_pflags & ZFS_REPARSE ?
0xa0000003 :
reparse_tag :
xattr_getsize(ZTOV(tzp));
fbdi->FileAttributes =
zfs_getwinflags(tzp);
Expand Down Expand Up @@ -1052,7 +1056,7 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
fifdi->LastAccessTime.QuadPart);
fifdi->EaSize =
tzp->z_pflags & ZFS_REPARSE ?
0xa0000003 :
reparse_tag :
xattr_getsize(ZTOV(tzp));
fifdi->FileAttributes =
zfs_getwinflags(tzp);
Expand Down Expand Up @@ -1090,11 +1094,8 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
TIME_UNIX_TO_WINDOWS(tzp->z_atime,
fiedi->LastAccessTime.QuadPart);
fiedi->EaSize =
tzp->z_pflags & ZFS_REPARSE ?
0xa0000003 :
xattr_getsize(ZTOV(tzp));
fiedi->FileAttributes =
zfs_getwinflags(tzp);
fiedi->ReparsePointTag = reparse_tag;
RtlCopyMemory(&fiedi->FileId.Identifier[0], &tzp->z_id,
sizeof (UINT64));
guid = dmu_objset_fsid_guid(zfsvfs->z_os);
Expand Down Expand Up @@ -1134,9 +1135,7 @@ zfs_readdir_emitdir(zfsvfs_t *zfsvfs, const char *name, emitdir_ptr_t *ctx,
fiebdi->LastAccessTime.QuadPart);
fiebdi->EaSize =
xattr_getsize(ZTOV(tzp));
fiebdi->ReparsePointTag =
tzp->z_pflags & ZFS_REPARSE ?
get_reparse_tag(tzp) : 0;
fiebdi->ReparsePointTag = reparse_tag;
fiebdi->FileAttributes =
zfs_getwinflags(tzp);
fiebdi->ShortNameLength = 0;
Expand Down

0 comments on commit f25ade0

Please sign in to comment.