Re: zfs related panic

From: Bakul Shah <bakul_at_iitbombay.org>
Date: Sat, 16 Aug 2025 01:13:32 UTC
On Aug 15, 2025, at 5:57 PM, Konstantin Belousov <kostikbel@gmail.com> wrote:
> 
> Below is what I gathered so far.

I haven't tried this patch as yet but a previous patch kib@ sent to me
fixed the problem. Many thanks!

Incidentally the breakpoint I set on
	zfsctl_root_readdir(struct vop_readdir_args *ap)
was never triggered. Wrong thread?

> 
> diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
> index 61d0bb26d1e5..c191b2abf6cc 100644
> --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
> +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
> @@ -674,6 +674,7 @@ zfsctl_root_readdir(struct vop_readdir_args *ap)
> zfs_uio_t uio;
> int *eofp = ap->a_eofflag;
> off_t dots_offset;
> + ssize_t orig_resid;
> int error;
> 
> zfs_uio_init(&uio, ap->a_uio);
> @@ -688,14 +689,20 @@ zfsctl_root_readdir(struct vop_readdir_args *ap)
> * count to return is 0.
> */
> if (zfs_uio_offset(&uio) == 3 * sizeof (entry)) {
> + if (eofp != NULL)
> + *eofp = 1;
> return (0);
> }
> 
> + orig_resid = zfs_uio_resid(&uio);
> error = sfs_readdir_common(zfsvfs->z_root, ZFSCTL_INO_ROOT, ap, &uio,
>    &dots_offset);
> if (error != 0) {
> - if (error == ENAMETOOLONG) /* ran out of destination space */
> + if (error == ENAMETOOLONG) { /* ran out of destination space */
> error = 0;
> + if (orig_resid == zfs_uio_resid(&uio) && eofp != NULL)
> + *eofp = 1;
> + }
> return (error);
> }
> if (zfs_uio_offset(&uio) != dots_offset)
> @@ -710,8 +717,11 @@ zfsctl_root_readdir(struct vop_readdir_args *ap)
> entry.d_reclen = sizeof (entry);
> error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio));
> if (error != 0) {
> - if (error == ENAMETOOLONG)
> + if (error == ENAMETOOLONG) {
> error = 0;
> + if (orig_resid == zfs_uio_resid(&uio) && eofp != NULL)
> + *eofp = 1;
> + }
> return (SET_ERROR(error));
> }
> if (eofp != NULL)
> @@ -1056,17 +1066,22 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
> zfs_uio_t uio;
> int *eofp = ap->a_eofflag;
> off_t dots_offset;
> + ssize_t orig_resid;
> int error;
> 
> zfs_uio_init(&uio, ap->a_uio);
> + orig_resid = zfs_uio_resid(&uio);
> 
> ASSERT3S(vp->v_type, ==, VDIR);
> 
> error = sfs_readdir_common(ZFSCTL_INO_ROOT, ZFSCTL_INO_SNAPDIR, ap,
>    &uio, &dots_offset);
> if (error != 0) {
> - if (error == ENAMETOOLONG) /* ran out of destination space */
> + if (error == ENAMETOOLONG) { /* ran out of destination space */
> error = 0;
> + if (orig_resid == zfs_uio_resid(&uio) && eofp != NULL)
> + *eofp = 1;
> + }
> return (error);
> }
> 
> @@ -1084,7 +1099,8 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
> dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG);
> if (error != 0) {
> if (error == ENOENT) {
> - if (eofp != NULL)
> + if (orig_resid == zfs_uio_resid(&uio) &&
> +    eofp != NULL)
> *eofp = 1;
> error = 0;
> }
> @@ -1099,8 +1115,12 @@ zfsctl_snapdir_readdir(struct vop_readdir_args *ap)
> entry.d_reclen = sizeof (entry);
> error = vfs_read_dirent(ap, &entry, zfs_uio_offset(&uio));
> if (error != 0) {
> - if (error == ENAMETOOLONG)
> + if (error == ENAMETOOLONG) {
> error = 0;
> + if (orig_resid == zfs_uio_resid(&uio) &&
> +    eofp != NULL)
> + *eofp = 1;
> + }
> zfs_exit(zfsvfs, FTAG);
> return (SET_ERROR(error));
> }
> diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
> index 1813c411b013..79e808a3ab3d 100644
> --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
> +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
> @@ -1695,6 +1695,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
> objset_t *os;
> caddr_t outbuf;
> size_t bufsize;
> + ssize_t orig_resid;
> zap_cursor_t zc;
> zap_attribute_t *zap;
> uint_t bytes_wanted;
> @@ -1735,7 +1736,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
> /*
> * Quit if directory has been removed (posix)
> */
> - if ((*eofp = zp->z_unlinked) != 0) {
> + if ((*eofp = (zp->z_unlinked != 0)) != 0) {
> zfs_exit(zfsvfs, FTAG);
> return (0);
> }
> @@ -1743,6 +1744,7 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
> error = 0;
> os = zfsvfs->z_os;
> offset = zfs_uio_offset(uio);
> + orig_resid = zfs_uio_resid(uio);
> prefetch = zp->z_zn_prefetch;
> zap = zap_attribute_long_alloc();
> 
> @@ -1933,6 +1935,8 @@ zfs_readdir(vnode_t *vp, zfs_uio_t *uio, cred_t *cr, int *eofp,
> *cookies = NULL;
> *ncookies = 0;
> }
> + if (error == 0 && zfs_uio_resid(uio) != orig_resid)
> + *eofp = 1;
> return (error);
> }
>