diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 727fbe4f088..13083776ef4 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1147,7 +1147,7 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio) * error code if another error happens. */ int -tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt, +tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int maxcookies, u_long *cookies, int *ncookies) { struct tmpfs_dir_cursor dc; @@ -1173,7 +1173,7 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt, if (error != 0) return (error); uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; - if (cnt != 0) + if (cookies != NULL) cookies[(*ncookies)++] = off = uio->uio_offset; case TMPFS_DIRCOOKIE_DOTDOT: error = tmpfs_dir_getdotdotdent(node, uio); @@ -1181,7 +1181,7 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt, return (error); de = tmpfs_dir_first(node, &dc); uio->uio_offset = tmpfs_dirent_cookie(de); - if (cnt != 0) + if (cookies != NULL) cookies[(*ncookies)++] = off = uio->uio_offset; /* EOF. */ if (de == NULL) @@ -1193,7 +1193,7 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt, de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc); if (de == NULL) return (EINVAL); - if (cnt != 0) + if (cookies != NULL) off = tmpfs_dirent_cookie(de); } @@ -1261,18 +1261,19 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt, error = uiomove(&d, d.d_reclen, uio); if (error == 0) { de = tmpfs_dir_next(node, &dc); - if (cnt != 0) { + if (cookies != NULL) { off = tmpfs_dirent_cookie(de); - MPASS(*ncookies < cnt); + MPASS(*ncookies < maxcookies); cookies[(*ncookies)++] = off; } } } while (error == 0 && uio->uio_resid > 0 && de != NULL); - /* Update the offset and cache. */ - if (cnt == 0) + /* Skip setting off when using cookies as it is already done above. */ + if (cookies == NULL) off = tmpfs_dirent_cookie(de); + /* Update the offset and cache. */ uio->uio_offset = off; node->tn_dir.tn_readdir_lastn = off; node->tn_dir.tn_readdir_lastp = de; diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 073a9fe98bc..7f74f205870 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -1199,32 +1199,38 @@ tmpfs_readdir(struct vop_readdir_args *v) int error; ssize_t startresid; - int cnt = 0; + int maxcookies; struct tmpfs_node *node; /* This operation only makes sense on directory nodes. */ if (vp->v_type != VDIR) return ENOTDIR; + maxcookies = 0; node = VP_TO_TMPFS_DIR(vp); startresid = uio->uio_resid; + /* Allocate cookies for NFS and compat modules. */ if (cookies != NULL && ncookies != NULL) { - cnt = howmany(node->tn_size, sizeof(struct tmpfs_dirent)) + 2; - *cookies = malloc(cnt * sizeof(**cookies), M_TEMP, M_WAITOK); + maxcookies = howmany(node->tn_size, + sizeof(struct tmpfs_dirent)) + 2; + *cookies = malloc(maxcookies * sizeof(**cookies), M_TEMP, + M_WAITOK); *ncookies = 0; } - if (cnt == 0) + if (cookies == NULL) error = tmpfs_dir_getdents(node, uio, 0, NULL, NULL); else - error = tmpfs_dir_getdents(node, uio, cnt, *cookies, ncookies); + error = tmpfs_dir_getdents(node, uio, maxcookies, *cookies, + ncookies); + /* Buffer was filled without hitting EOF. */ if (error == EJUSTRETURN) error = (uio->uio_resid != startresid) ? 0 : EINVAL; - if (error != 0 && cnt != 0) + if (error != 0 && cookies != NULL) free(*cookies, M_TEMP); if (eofflag != NULL)