--- kern/vfs_syscalls.c.orig 2014-12-22 20:12:12.000000000 -0500 +++ kern/vfs_syscalls.c 2014-12-26 19:47:38.000000000 -0500 @@ -103,6 +103,7 @@ static int setutimes(struct thread *td, const struct timespec *, int, int); static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred, struct thread *td); +static void copy_dirent32(char *buf, u_int len); /* * The module initialization routine for POSIX asynchronous I/O will @@ -3749,7 +3750,7 @@ kern_ogetdirentries(struct thread *td, s struct file *fp; struct uio auio, kuio; struct iovec aiov, kiov; - struct dirent *dp, *edp; + struct dirent32 *dp, *edp; cap_rights_t rights; caddr_t dirbuf; int error, eofflag, readcnt; @@ -3794,11 +3795,22 @@ unionread: return (error); } #endif + dirbuf = NULL; + readcnt = 0; # if (BYTE_ORDER != LITTLE_ENDIAN) if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, - NULL, NULL); - foffset = auio.uio_offset; + kuio = auio; + kuio.uio_iov = &kiov; + kuio.uio_segflg = UIO_SYSSPACE; + kiov.iov_len = uap->count; + dirbuf = malloc(uap->count, M_TEMP, M_WAITOK); + kiov.iov_base = dirbuf; + error = VOP_READDIR(vp, &kuio, fp->f_cred, + &eofflag, NULL, NULL); + foffset = kuio.uio_offset; + readcnt = uap->count - kuio.uio_resid; + if (error == 0 && readcnt > 0) + copy_dirent32(dirbuf, readcnt); } else # endif { @@ -3813,8 +3825,10 @@ unionread: foffset = kuio.uio_offset; if (error == 0) { readcnt = uap->count - kuio.uio_resid; - edp = (struct dirent *)&dirbuf[readcnt]; - for (dp = (struct dirent *)dirbuf; dp < edp; ) { + if (readcnt > 0) + copy_dirent32(dirbuf, readcnt); + edp = (struct dirent32 *)&dirbuf[readcnt]; + for (dp = (struct dirent32 *)dirbuf; dp < edp; ) { # if (BYTE_ORDER == LITTLE_ENDIAN) /* * The expected low byte of @@ -3833,18 +3847,19 @@ unionread: dp->d_type = 0; # endif if (dp->d_reclen > 0) { - dp = (struct dirent *) + dp = (struct dirent32 *) ((char *)dp + dp->d_reclen); } else { error = EIO; break; } } - if (dp >= edp) - error = uiomove(dirbuf, readcnt, &auio); } - free(dirbuf, M_TEMP); } + if (error == 0 && readcnt > 0) + error = uiomove(dirbuf, readcnt, &auio); + if (dirbuf != NULL) + free(dirbuf, M_TEMP); if (error != 0) { VOP_UNLOCK(vp, 0); foffset_unlock(fp, foffset, 0); @@ -3918,6 +3933,7 @@ kern_getdirentries(struct thread *td, in long loff; int error, eofflag; off_t foffset; + char *tbuf = NULL; AUDIT_ARG_FD(fd); if (count > IOSIZE_MAX) @@ -3938,12 +3954,17 @@ unionread: error = EINVAL; goto fail; } - aiov.iov_base = buf; + if (bufseg == UIO_USERSPACE) { + if (tbuf == NULL) + tbuf = malloc(count, M_TEMP, M_WAITOK); + aiov.iov_base = tbuf; + } else + aiov.iov_base = buf; aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; - auio.uio_segflg = bufseg; + auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = td; vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG_VNODE1(vp); @@ -3973,6 +3994,15 @@ unionread: goto unionread; } VOP_UNLOCK(vp, 0); + if (count - auio.uio_resid > 0) { + if (bufseg == UIO_USERSPACE) { + copy_dirent32(tbuf, count - auio.uio_resid); + error = copyout(tbuf, buf, count - auio.uio_resid); + if (error != 0) + goto fail; + } else + copy_dirent32(buf, count - auio.uio_resid); + } *basep = loff; if (residp != NULL) *residp = auio.uio_resid; @@ -3980,9 +4010,35 @@ unionread: fail: foffset_unlock(fp, foffset, 0); fdrop(fp, td); + if (tbuf != NULL) + free(tbuf, M_TEMP); return (error); } +CTASSERT(sizeof(struct dirent) == 24 + MAXNAMLEN + 1); + +/* + * Copy the new struct dirent to the old struct dirent32 format. + */ +static void +copy_dirent32(char *buf, u_int len) +{ + struct dirent *dp; + struct dirent32 *dp32; + + while (len > 0) { + dp = (struct dirent *)buf; + dp32 = (struct dirent32 *)buf; + dp32->d_fileno = dp->d_fileno; + dp32->d_reclen = dp->d_reclen; + dp32->d_type = dp->d_type; + dp32->d_namlen = dp->d_namlen; + bcopy(dp->d_name, dp32->d_name, dp32->d_namlen + 1); + buf += dp32->d_reclen; + len -= dp32->d_reclen; + } +} + #ifndef _SYS_SYSPROTO_H_ struct getdents_args { int fd; --- fs/fuse/fuse_internal.h.orig 2014-12-22 20:13:05.000000000 -0500 +++ fs/fuse/fuse_internal.h 2014-12-26 19:35:37.000000000 -0500 @@ -210,7 +210,7 @@ fuse_internal_attr_fat2vat(struct mount vattr_null(vap); vap->va_fsid = mp->mnt_stat.f_fsid.val[0]; - vap->va_fileid = fat->ino; /* XXX cast from 64 bits to 32 */ + vap->va_fileid = fat->ino; vap->va_mode = fat->mode & ~S_IFMT; vap->va_nlink = fat->nlink; vap->va_uid = fat->uid; @@ -254,10 +254,6 @@ fuse_internal_fsync_callback(struct fuse /* readdir */ -struct pseudo_dirent { - uint32_t d_namlen; -}; - int fuse_internal_readdir(struct vnode *vp, struct uio *uio, --- fs/fuse/fuse_internal.c.orig 2014-12-22 20:13:05.000000000 -0500 +++ fs/fuse/fuse_internal.c 2014-12-26 19:35:37.000000000 -0500 @@ -337,8 +337,7 @@ fuse_internal_readdir_processdata(struct err = EINVAL; break; } - bytesavail = GENERIC_DIRSIZ((struct pseudo_dirent *) - &fudge->namelen); + bytesavail = _GENERIC_DIRLEN(fudge->namelen); if (bytesavail > uio_resid(uio)) { err = -1; @@ -348,14 +347,17 @@ fuse_internal_readdir_processdata(struct fiov_adjust(cookediov, bytesavail); de = (struct dirent *)cookediov->base; - de->d_fileno = fudge->ino; /* XXX: truncation */ + de->d_cookie = fudge->off; + de->d_fileno = fudge->ino; de->d_reclen = bytesavail; de->d_type = fudge->type; de->d_namlen = fudge->namelen; - memcpy((char *)cookediov->base + sizeof(struct dirent) - - MAXNAMLEN - 1, - (char *)buf + FUSE_NAME_OFFSET, fudge->namelen); - ((char *)cookediov->base)[bytesavail] = '\0'; + memcpy(de->d_name, (char *)buf + FUSE_NAME_OFFSET, + fudge->namelen); + /* + * Since the above fiov_adjust() call bzero()s the entire + * buffer, the name will always be null terminated. + */ err = uiomove(cookediov->base, cookediov->len, uio); if (err) { --- fs/fuse/fuse_vnops.c.orig 2014-12-22 20:13:05.000000000 -0500 +++ fs/fuse/fuse_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -1221,7 +1221,7 @@ fuse_vnop_readdir(struct vop_readdir_arg if (err) { return (err); } -#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1) +#define DIRCOOKEDSIZE sizeof(struct dirent) fiov_init(&cookediov, DIRCOOKEDSIZE); err = fuse_internal_readdir(vp, uio, fufh, &cookediov); --- fs/devfs/devfs_vnops.c.orig 2014-12-22 20:13:05.000000000 -0500 +++ fs/devfs/devfs_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -730,7 +730,7 @@ devfs_getattr(struct vop_getattr_args *a vap->va_flags = 0; vap->va_filerev = 0; vap->va_nlink = de->de_links; - vap->va_fileid = de->de_inode; + vap->va_fileid = (u_int)de->de_inode; return (error); } @@ -1284,7 +1284,8 @@ devfs_readdir(struct vop_readdir_args *a dp = dd->de_dirent; if (dp->d_reclen > uio->uio_resid) break; - dp->d_fileno = de->de_inode; + dp->d_fileno = (u_int)de->de_inode; + dp->d_cookie = off + dp->d_reclen; if (off >= uio->uio_offset) { error = vfs_read_dirent(ap, dp, off); if (error) --- fs/nandfs/nandfs_vnops.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/nandfs/nandfs_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -1228,6 +1228,7 @@ nandfs_readdir(struct vop_readdir_args * memset(&dirent, 0, sizeof(struct dirent)); dirent.d_fileno = ndirent->inode; if (dirent.d_fileno) { + dirent.d_cookie = diroffset + ndirent->rec_len; dirent.d_type = ndirent->file_type; dirent.d_namlen = name_len; strncpy(dirent.d_name, ndirent->name, name_len); --- fs/smbfs/smbfs_node.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/smbfs/smbfs_node.c 2014-12-26 19:35:37.000000000 -0500 @@ -386,7 +386,11 @@ smbfs_attr_cachelookup(struct vnode *vp, va->va_uid = smp->sm_uid; /* owner user id */ va->va_gid = smp->sm_gid; /* owner group id */ va->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; - va->va_fileid = np->n_ino; /* file id */ + /* + * Cast to u_long to make sure that sign extension doesn't occur + * for arches where long is 32bit signed. + */ + va->va_fileid = (u_long)np->n_ino; /* file id */ if (va->va_fileid == 0) va->va_fileid = 2; va->va_blocksize = SSTOVC(smp->sm_share)->vc_txmax; --- fs/smbfs/smbfs_io.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/smbfs/smbfs_io.c 2014-12-26 19:35:37.000000000 -0500 @@ -96,9 +96,10 @@ smbfs_readvdir(struct vnode *vp, struct while (limit && offset < 2) { limit--; bzero((caddr_t)&de, DE_SIZE); + de.d_cookie = (offset + 1) * DE_SIZE; de.d_reclen = DE_SIZE; - de.d_fileno = (offset == 0) ? np->n_ino : - (np->n_parent ? np->n_parentino : 2); + de.d_fileno = (u_long)((offset == 0) ? np->n_ino : + (np->n_parent ? np->n_parentino : 2)); if (de.d_fileno == 0) de.d_fileno = 0x7ffffffd + offset; de.d_namlen = offset + 1; @@ -149,8 +150,13 @@ smbfs_readvdir(struct vnode *vp, struct break; np->n_dirofs++; bzero((caddr_t)&de, DE_SIZE); + de.d_cookie = (offset + 1) * DE_SIZE; de.d_reclen = DE_SIZE; - de.d_fileno = ctx->f_attr.fa_ino; + /* + * Cast to a u_long so that it won't sign extend for arches + * where long is signed 32bit. + */ + de.d_fileno = (u_long)ctx->f_attr.fa_ino; de.d_type = (ctx->f_attr.fa_attr & SMB_FA_DIR) ? DT_DIR : DT_REG; de.d_namlen = ctx->f_nmlen; bcopy(ctx->f_name, de.d_name, de.d_namlen); --- fs/cd9660/cd9660_vnops.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/cd9660/cd9660_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -380,6 +380,7 @@ iso_uiodir(idp,dp,off) dp->d_name[dp->d_namlen] = 0; dp->d_reclen = GENERIC_DIRSIZ(dp); + dp->d_cookie = off; if (idp->uio->uio_resid < dp->d_reclen) { idp->eofflag = 0; @@ -481,6 +482,7 @@ cd9660_readdir(ap) u_short namelen; int ncookies = 0; u_long *cookies = NULL; + ino_t tmp_ino; dp = VTOI(vdp); imp = dp->i_mnt; @@ -576,8 +578,10 @@ cd9660_readdir(ap) switch (imp->iso_ftype) { case ISO_FTYPE_RRIP: + tmp_ino = idp->current.d_fileno; cd9660_rrip_getname(ep,idp->current.d_name, &namelen, - &idp->current.d_fileno,imp); + &tmp_ino, imp); + idp->current.d_fileno = tmp_ino; idp->current.d_namlen = (u_char)namelen; if (idp->current.d_namlen) error = iso_uiodir(idp,&idp->current,idp->curroff); --- fs/ext2fs/ext2_lookup.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/ext2fs/ext2_lookup.c 2014-12-26 19:35:37.000000000 -0500 @@ -214,6 +214,7 @@ ext2_readdir(struct vop_readdir_args *ap if (offset < startoffset || dp->e2d_ino == 0) goto nextentry; dstdp.d_fileno = dp->e2d_ino; + dstdp.d_cookie = offset + dp->e2d_reclen; dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen); dstdp.d_name[dstdp.d_namlen] = '\0'; --- fs/nfsserver/nfs_nfsdport.c.orig 2014-12-24 20:55:30.000000000 -0500 +++ fs/nfsserver/nfs_nfsdport.c 2014-12-26 20:00:31.000000000 -0500 @@ -1517,8 +1517,9 @@ nfsvno_fillattr(struct nfsrv_descript *n } /* Since the Readdir vnode ops vary, put the entire functions in here. */ + /* - * nfs readdir service + * nfs readdir service for the new 64bit struct dirent * - mallocs what it thinks is enough to read * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR * - calls VOP_READDIR() @@ -1550,9 +1551,8 @@ nfsrvd_readdir(struct nfsrv_descript *nd char *cpos, *cend, *rbuf; struct nfsvattr at; int nlen, error = 0, getret = 1; - int siz, cnt, fullsiz, eofflag, ncookies; + int siz, cnt, fullsiz, eofflag; u_int64_t off, toff, verf; - u_long *cookies = NULL, *cookiep; struct uio io; struct iovec iv; int is_ufs; @@ -1614,10 +1614,6 @@ nfsrvd_readdir(struct nfsrv_descript *nd MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); again: eofflag = 0; - if (cookies) { - free((caddr_t)cookies, M_TEMP); - cookies = NULL; - } iv.iov_base = rbuf; iv.iov_len = siz; @@ -1628,14 +1624,12 @@ again: io.uio_segflg = UIO_SYSSPACE; io.uio_rw = UIO_READ; io.uio_td = NULL; - nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, - &cookies); + nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, NULL, + NULL); off = (u_int64_t)io.uio_offset; if (io.uio_resid) siz -= io.uio_resid; - if (!cookies && !nd->nd_repstat) - nd->nd_repstat = NFSERR_PERM; if (nd->nd_flag & ND_NFSV3) { getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); if (!nd->nd_repstat) @@ -1648,8 +1642,6 @@ again: if (nd->nd_repstat) { vput(vp); free((caddr_t)rbuf, M_TEMP); - if (cookies) - free((caddr_t)cookies, M_TEMP); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); goto out; @@ -1671,7 +1663,6 @@ again: *tl++ = newnfs_false; *tl = newnfs_true; FREE((caddr_t)rbuf, M_TEMP); - FREE((caddr_t)cookies, M_TEMP); goto out; } @@ -1682,7 +1673,6 @@ again: cpos = rbuf; cend = rbuf + siz; dp = (struct dirent *)cpos; - cookiep = cookies; /* * For some reason FreeBSD's ufs_readdir() chooses to back the @@ -1691,15 +1681,13 @@ again: * requires the assumption that file offset cookies monotonically * increase. */ - while (cpos < cend && ncookies > 0 && + while (cpos < cend && (dp->d_fileno == 0 || dp->d_type == DT_WHT || - (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) { + (is_ufs == 1 && dp->d_cookie <= toff))) { cpos += dp->d_reclen; dp = (struct dirent *)cpos; - cookiep++; - ncookies--; } - if (cpos >= cend || ncookies == 0) { + if (cpos >= cend) { siz = fullsiz; toff = off; goto again; @@ -1722,7 +1710,7 @@ again: } /* Loop through the records and build reply */ - while (cpos < cend && ncookies > 0) { + while (cpos < cend) { nlen = dp->d_namlen; if (dp->d_fileno != 0 && dp->d_type != DT_WHT && nlen <= NFS_MAXNAMLEN) { @@ -1742,24 +1730,23 @@ again: if (nd->nd_flag & ND_NFSV3) { NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); *tl++ = newnfs_true; - *tl++ = 0; + txdr_hyper(dp->d_fileno, tl); } else { NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); *tl++ = newnfs_true; + *tl = txdr_unsigned(dp->d_fileno); } - *tl = txdr_unsigned(dp->d_fileno); (void) nfsm_strtom(nd, dp->d_name, nlen); if (nd->nd_flag & ND_NFSV3) { NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); - *tl++ = 0; - } else + txdr_hyper(dp->d_cookie, tl); + } else { NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); - *tl = txdr_unsigned(*cookiep); + *tl = txdr_unsigned(dp->d_cookie); + } } cpos += dp->d_reclen; dp = (struct dirent *)cpos; - cookiep++; - ncookies--; } if (cpos < cend) eofflag = 0; @@ -1770,7 +1757,6 @@ again: else *tl = newnfs_false; FREE((caddr_t)rbuf, M_TEMP); - FREE((caddr_t)cookies, M_TEMP); out: NFSEXITCODE2(0, nd); @@ -1782,7 +1768,7 @@ nfsmout: } /* - * Readdirplus for V3 and Readdir for V4. + * Readdirplus for V3 and Readdir for V4 for the new 64 bit struct dirent. */ int nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, @@ -1798,10 +1784,9 @@ nfsrvd_readdirplus(struct nfsrv_descript struct mbuf *mb0, *mb1; struct nfsreferral *refp; int nlen, r, error = 0, getret = 1, usevget = 1; - int siz, cnt, fullsiz, eofflag, ncookies, entrycnt; + int siz, cnt, fullsiz, eofflag, entrycnt; caddr_t bpos0, bpos1; u_int64_t off, toff, verf; - u_long *cookies = NULL, *cookiep; nfsattrbit_t attrbits, rderrbits, savbits; struct uio io; struct iovec iv; @@ -1892,10 +1877,6 @@ nfsrvd_readdirplus(struct nfsrv_descript MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); again: eofflag = 0; - if (cookies) { - free((caddr_t)cookies, M_TEMP); - cookies = NULL; - } iv.iov_base = rbuf; iv.iov_len = siz; @@ -1906,22 +1887,18 @@ again: io.uio_segflg = UIO_SYSSPACE; io.uio_rw = UIO_READ; io.uio_td = NULL; - nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies, - &cookies); + nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, NULL, + NULL); off = (u_int64_t)io.uio_offset; if (io.uio_resid) siz -= io.uio_resid; getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1); - if (!cookies && !nd->nd_repstat) - nd->nd_repstat = NFSERR_PERM; if (!nd->nd_repstat) nd->nd_repstat = getret; if (nd->nd_repstat) { vput(vp); - if (cookies) - free((caddr_t)cookies, M_TEMP); free((caddr_t)rbuf, M_TEMP); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); @@ -1940,7 +1917,6 @@ again: tl += 2; *tl++ = newnfs_false; *tl = newnfs_true; - free((caddr_t)cookies, M_TEMP); free((caddr_t)rbuf, M_TEMP); goto out; } @@ -1952,7 +1928,6 @@ again: cpos = rbuf; cend = rbuf + siz; dp = (struct dirent *)cpos; - cookiep = cookies; /* * For some reason FreeBSD's ufs_readdir() chooses to back the @@ -1961,18 +1936,16 @@ again: * requires the assumption that file offset cookies monotonically * increase. */ - while (cpos < cend && ncookies > 0 && + while (cpos < cend && (dp->d_fileno == 0 || dp->d_type == DT_WHT || - (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff) || + (is_ufs == 1 && dp->d_cookie <= toff) || ((nd->nd_flag & ND_NFSV4) && ((dp->d_namlen == 1 && dp->d_name[0] == '.') || (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.'))))) { cpos += dp->d_reclen; dp = (struct dirent *)cpos; - cookiep++; - ncookies--; } - if (cpos >= cend || ncookies == 0) { + if (cpos >= cend) { siz = fullsiz; toff = off; goto again; @@ -1989,7 +1962,6 @@ again: vfs_rel(mp); if (nd->nd_repstat != 0) { vrele(vp); - free(cookies, M_TEMP); free(rbuf, M_TEMP); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); @@ -2047,7 +2019,7 @@ again: /* Loop through the records and build reply */ entrycnt = 0; - while (cpos < cend && ncookies > 0 && dirlen < cnt) { + while (cpos < cend && dirlen < cnt) { nlen = dp->d_namlen; if (dp->d_fileno != 0 && dp->d_type != DT_WHT && nlen <= NFS_MAXNAMLEN && @@ -2071,7 +2043,7 @@ again: at_root = 0; needs_unbusy = 0; new_mp = mp; - mounted_on_fileno = (uint64_t)dp->d_fileno; + mounted_on_fileno = dp->d_fileno; if ((nd->nd_flag & ND_NFSV3) || NFSNONZERO_ATTRBIT(&savbits)) { if (nd->nd_flag & ND_NFSV4) @@ -2193,12 +2165,10 @@ again: if (nd->nd_flag & ND_NFSV3) { NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); *tl++ = newnfs_true; - *tl++ = 0; - *tl = txdr_unsigned(dp->d_fileno); + txdr_hyper(dp->d_fileno, tl); dirlen += nfsm_strtom(nd, dp->d_name, nlen); NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); - *tl++ = 0; - *tl = txdr_unsigned(*cookiep); + txdr_hyper(dp->d_cookie, tl); nfsrv_postopattr(nd, 0, nvap); dirlen += nfsm_fhtom(nd,(u_int8_t *)&nfh,0,1); dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR); @@ -2207,8 +2177,7 @@ again: } else { NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); *tl++ = newnfs_true; - *tl++ = 0; - *tl = txdr_unsigned(*cookiep); + txdr_hyper(dp->d_cookie, tl); dirlen += nfsm_strtom(nd, dp->d_name, nlen); if (nvp != NULL) { supports_nfsv4acls = @@ -2251,8 +2220,6 @@ again: } cpos += dp->d_reclen; dp = (struct dirent *)cpos; - cookiep++; - ncookies--; } vrele(vp); vfs_unbusy(mp); @@ -2281,7 +2248,6 @@ again: else *tl = newnfs_false; } - FREE((caddr_t)cookies, M_TEMP); FREE((caddr_t)rbuf, M_TEMP); out: --- fs/nfsserver/nfs_nfsdsubs.c.orig 2014-12-22 20:13:06.000000000 -0500 +++ fs/nfsserver/nfs_nfsdsubs.c 2014-12-26 19:35:37.000000000 -0500 @@ -1394,8 +1394,7 @@ nfsrv_fillattr(struct nfsrv_descript *nd fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev)); fp->fa3_fsid.nfsuquad[0] = 0; fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid); - fp->fa3_fileid.nfsuquad[0] = 0; - fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(nvap->na_fileid); + txdr_hyper(nvap->na_fileid, &fp->fa3_fileid); txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime); txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime); txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime); --- fs/fdescfs/fdesc_vnops.c.orig 2014-12-22 20:13:07.000000000 -0500 +++ fs/fdescfs/fdesc_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -487,7 +487,11 @@ fdesc_setattr(ap) return (error); } -#define UIO_MX 16 +/* + * This is offsetof(dirent, d_name) + 8. I think it also must divide exactly + * into 512. + */ +#define UIO_MX 32 static int fdesc_readdir(ap) @@ -544,6 +548,7 @@ fdesc_readdir(ap) dp->d_fileno = i + FD_DESC; break; } + dp->d_cookie = (i + 1) * UIO_MX; if (dp->d_namlen != 0) { /* * And ship to userland --- fs/msdosfs/msdosfs_vnops.c.orig 2014-12-22 20:13:07.000000000 -0500 +++ fs/msdosfs/msdosfs_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -1665,6 +1665,8 @@ msdosfs_readdir(ap) strcpy(dirbuf.d_name, ".."); break; } + dirbuf.d_cookie = offset + + sizeof(struct direntry); dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf); if (uio->uio_resid < dirbuf.d_reclen) goto out; @@ -1795,6 +1797,7 @@ msdosfs_readdir(ap) } else mbnambuf_flush(&nb, &dirbuf); chksum = -1; + dirbuf.d_cookie = offset + sizeof(struct direntry); dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf); if (uio->uio_resid < dirbuf.d_reclen) { brelse(bp); --- fs/udf/udf_vnops.c.orig 2014-12-22 20:13:07.000000000 -0500 +++ fs/udf/udf_vnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -827,6 +827,7 @@ udf_readdir(struct vop_readdir_args *a) * used for the cookies since the offset here is * usually zero, and NFS doesn't like that value */ + dir.d_cookie = 2; dir.d_fileno = node->hash_id; dir.d_type = DT_DIR; dir.d_name[0] = '.'; @@ -838,6 +839,7 @@ udf_readdir(struct vop_readdir_args *a) if (error) break; + dir.d_cookie = ds->offset + ds->off; dir.d_fileno = udf_getid(&fid->icb); dir.d_type = DT_DIR; dir.d_name[0] = '.'; @@ -850,6 +852,7 @@ udf_readdir(struct vop_readdir_args *a) } else { dir.d_namlen = udf_transname(&fid->data[fid->l_iu], &dir.d_name[0], fid->l_fi, udfmp); + dir.d_cookie = ds->offset + ds->off; dir.d_fileno = udf_getid(&fid->icb); dir.d_type = (fid->file_char & UDF_FILE_CHAR_DIR) ? DT_DIR : DT_UNKNOWN; --- fs/nfsclient/nfs_clrpcops.c.orig 2014-12-22 20:13:08.000000000 -0500 +++ fs/nfsclient/nfs_clrpcops.c 2014-12-26 19:35:37.000000000 -0500 @@ -65,7 +65,7 @@ short nfsv4_cbport = NFSV4_CBPORT; int nfstest_openallsetattr = 0; #endif /* !APPLEKEXT */ -#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) +#define DIRHDSIZ offsetof(struct dirent, d_name) /* * nfscl_getsameserver() can return one of three values: @@ -2682,11 +2682,10 @@ nfsrpc_readdir(vnode_t vp, struct uio *u struct nfsrv_descript nfsd, *nd = &nfsd; int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; int reqsize, tryformoredirs = 1, readsize, eof = 0, gotmnton = 0; - long dotfileid, dotdotfileid = 0; - u_int32_t fakefileno = 0xffffffff, rderr; + uint64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX; + u_int32_t rderr; char *cp; nfsattrbit_t attrbits, dattrbits; - u_int32_t *tl2 = NULL; size_t tresid; KASSERT(uiop->uio_iovcnt == 1 && @@ -2763,14 +2762,14 @@ nfsrpc_readdir(vnode_t vp, struct uio *u error = EPERM; if (!error) { NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED); - nfsva.na_mntonfileno = 0xffffffff; + nfsva.na_mntonfileno = UINT64_MAX; error = nfsv4_loadattr(nd, NULL, &nfsva, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, p, cred); if (error) { dotdotfileid = dotfileid; } else if (gotmnton) { - if (nfsva.na_mntonfileno != 0xffffffff) + if (nfsva.na_mntonfileno != UINT64_MAX) dotdotfileid = nfsva.na_mntonfileno; else dotdotfileid = nfsva.na_fileid; @@ -2801,38 +2800,28 @@ nfsrpc_readdir(vnode_t vp, struct uio *u if (error) return (error); nd->nd_mrep = NULL; - dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop)); + dp = (struct dirent *)uio_iov_base(uiop); + dp->d_cookie = 0; dp->d_type = DT_DIR; dp->d_fileno = dotfileid; dp->d_namlen = 1; + *((uint64_t *)dp->d_name) = 0; /* Zero pad it. */ dp->d_name[0] = '.'; - dp->d_name[1] = '\0'; - dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER; - /* - * Just make these offset cookie 0. - */ - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = 0; - *tl = 0; + dp->d_reclen = _GENERIC_DIRSIZ(dp); blksiz += dp->d_reclen; uio_uio_resid_add(uiop, -(dp->d_reclen)); uiop->uio_offset += dp->d_reclen; uio_iov_base_add(uiop, dp->d_reclen); uio_iov_len_add(uiop, -(dp->d_reclen)); - dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop)); + dp = (struct dirent *)uio_iov_base(uiop); + dp->d_cookie = 0; dp->d_type = DT_DIR; dp->d_fileno = dotdotfileid; dp->d_namlen = 2; + *((uint64_t *)dp->d_name) = 0; dp->d_name[0] = '.'; dp->d_name[1] = '.'; - dp->d_name[2] = '\0'; - dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER; - /* - * Just make these offset cookie 0. - */ - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = 0; - *tl = 0; + dp->d_reclen = _GENERIC_DIRSIZ(dp); blksiz += dp->d_reclen; uio_uio_resid_add(uiop, -(dp->d_reclen)); uiop->uio_offset += dp->d_reclen; @@ -2920,18 +2909,19 @@ nfsrpc_readdir(vnode_t vp, struct uio *u } else { NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED); nfsva.na_fileid = - fxdr_unsigned(long, *tl++); + fxdr_unsigned(uint64_t, *tl++); len = fxdr_unsigned(int, *tl); } if (len <= 0 || len > NFS_MAXNAMLEN) { error = EBADRPC; goto nfsmout; } - tlen = NFSM_RNDUP(len); + /* Round up to an 8 byte boundary. */ + tlen = (len + 7) & ~7; if (tlen == len) - tlen += 4; /* To ensure null termination */ + tlen += 8; /* To ensure null termination. */ left = DIRBLKSIZ - blksiz; - if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > left) { + if (_GENERIC_DIRLEN(len) > left) { dp->d_reclen += left; uio_iov_base_add(uiop, left); uio_iov_len_add(uiop, -(left)); @@ -2939,12 +2929,12 @@ nfsrpc_readdir(vnode_t vp, struct uio *u uiop->uio_offset += left; blksiz = 0; } - if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > uio_uio_resid(uiop)) + if (_GENERIC_DIRLEN(len) > uio_uio_resid(uiop)) bigenough = 0; if (bigenough) { - dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop)); + dp = (struct dirent *)uio_iov_base(uiop); dp->d_namlen = len; - dp->d_reclen = tlen + DIRHDSIZ + NFSX_HYPER; + dp->d_reclen = _GENERIC_DIRLEN(len); dp->d_type = DT_UNKNOWN; blksiz += dp->d_reclen; if (blksiz == DIRBLKSIZ) @@ -2956,15 +2946,13 @@ nfsrpc_readdir(vnode_t vp, struct uio *u error = nfsm_mbufuio(nd, uiop, len); if (error) goto nfsmout; - cp = CAST_DOWN(caddr_t, uio_iov_base(uiop)); + cp = uio_iov_base(uiop); tlen -= len; - *cp = '\0'; /* null terminate */ - cp += tlen; /* points to cookie storage */ - tl2 = (u_int32_t *)cp; - uio_iov_base_add(uiop, (tlen + NFSX_HYPER)); - uio_iov_len_add(uiop, -(tlen + NFSX_HYPER)); - uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER)); - uiop->uio_offset += (tlen + NFSX_HYPER); + *cp = '\0'; /* Null termination. */ + uio_iov_base_add(uiop, tlen); + uio_iov_len_add(uiop, -(tlen)); + uio_uio_resid_add(uiop, -(tlen)); + uiop->uio_offset += tlen; } else { error = nfsm_advance(nd, NFSM_RNDUP(len), -1); if (error) @@ -2972,7 +2960,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *u } if (nd->nd_flag & ND_NFSV4) { rderr = 0; - nfsva.na_mntonfileno = 0xffffffff; + nfsva.na_mntonfileno = UINT64_MAX; error = nfsv4_loadattr(nd, NULL, &nfsva, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, &rderr, p, cred); @@ -2994,7 +2982,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *u dp->d_fileno = 0; } else { if (gotmnton) { - if (nfsva.na_mntonfileno != 0xffffffff) + if (nfsva.na_mntonfileno != UINT64_MAX) dp->d_fileno = nfsva.na_mntonfileno; else dp->d_fileno = nfsva.na_fileid; @@ -3015,10 +3003,11 @@ nfsrpc_readdir(vnode_t vp, struct uio *u } else { dp->d_fileno = nfsva.na_fileid; } - *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] = + cookiep->nfsuquad[0] = cookie.lval[0] = ncookie.lval[0]; - *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] = + cookiep->nfsuquad[1] = cookie.lval[1] = ncookie.lval[1]; + dp->d_cookie = ncookie.qval; } more_dirs = fxdr_unsigned(int, *tl); } @@ -3068,32 +3057,12 @@ nfsrpc_readdir(vnode_t vp, struct uio *u *eofp = eof; } - /* - * Add extra empty records to any remaining DIRBLKSIZ chunks. - */ - while (uio_uio_resid(uiop) > 0 && ((size_t)(uio_uio_resid(uiop))) != tresid) { - dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop)); - dp->d_type = DT_UNKNOWN; - dp->d_fileno = 0; - dp->d_namlen = 0; - dp->d_name[0] = '\0'; - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = cookie.lval[0]; - *tl = cookie.lval[1]; - dp->d_reclen = DIRBLKSIZ; - uio_iov_base_add(uiop, DIRBLKSIZ); - uio_iov_len_add(uiop, -(DIRBLKSIZ)); - uio_uio_resid_add(uiop, -(DIRBLKSIZ)); - uiop->uio_offset += DIRBLKSIZ; - } - nfsmout: if (nd->nd_mrep != NULL) mbuf_freem(nd->nd_mrep); return (error); } -#ifndef APPLE /* * NFS V3 readdir plus RPC. Used in place of nfsrpc_readdir(). * (Also used for NFS V4 when mount flag set.) @@ -3119,11 +3088,12 @@ nfsrpc_readdirplus(vnode_t vp, struct ui int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; int attrflag, tryformoredirs = 1, eof = 0, gotmnton = 0; int isdotdot = 0, unlocknewvp = 0; - long dotfileid, dotdotfileid = 0, fileno = 0; + uint64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX; + uint64_t fileno = 0; char *cp; nfsattrbit_t attrbits, dattrbits; size_t tresid; - u_int32_t *tl2 = NULL, fakefileno = 0xffffffff, rderr; + u_int32_t rderr; struct timespec dctime; KASSERT(uiop->uio_iovcnt == 1 && @@ -3190,14 +3160,14 @@ nfsrpc_readdirplus(vnode_t vp, struct ui error = EPERM; if (!error) { NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED); - nfsva.na_mntonfileno = 0xffffffff; + nfsva.na_mntonfileno = UINT64_MAX; error = nfsv4_loadattr(nd, NULL, &nfsva, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, p, cred); if (error) { dotdotfileid = dotfileid; } else if (gotmnton) { - if (nfsva.na_mntonfileno != 0xffffffff) + if (nfsva.na_mntonfileno != UINT64_MAX) dotdotfileid = nfsva.na_mntonfileno; else dotdotfileid = nfsva.na_fileid; @@ -3229,37 +3199,27 @@ nfsrpc_readdirplus(vnode_t vp, struct ui return (error); nd->nd_mrep = NULL; dp = (struct dirent *)uio_iov_base(uiop); + dp->d_cookie = 0; dp->d_type = DT_DIR; dp->d_fileno = dotfileid; dp->d_namlen = 1; + *((uint64_t *)dp->d_name) = 0; /* Zero pad it. */ dp->d_name[0] = '.'; - dp->d_name[1] = '\0'; - dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER; - /* - * Just make these offset cookie 0. - */ - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = 0; - *tl = 0; + dp->d_reclen = _GENERIC_DIRSIZ(dp); blksiz += dp->d_reclen; uio_uio_resid_add(uiop, -(dp->d_reclen)); uiop->uio_offset += dp->d_reclen; uio_iov_base_add(uiop, dp->d_reclen); uio_iov_len_add(uiop, -(dp->d_reclen)); dp = (struct dirent *)uio_iov_base(uiop); + dp->d_cookie = 0; dp->d_type = DT_DIR; dp->d_fileno = dotdotfileid; dp->d_namlen = 2; + *((uint64_t *)dp->d_name) = 0; dp->d_name[0] = '.'; dp->d_name[1] = '.'; - dp->d_name[2] = '\0'; - dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER; - /* - * Just make these offset cookie 0. - */ - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = 0; - *tl = 0; + dp->d_reclen = _GENERIC_DIRSIZ(dp); blksiz += dp->d_reclen; uio_uio_resid_add(uiop, -(dp->d_reclen)); uiop->uio_offset += dp->d_reclen; @@ -3327,19 +3287,20 @@ nfsrpc_readdirplus(vnode_t vp, struct ui ncookie.lval[0] = *tl++; ncookie.lval[1] = *tl++; } else { - fileno = fxdr_unsigned(long, *++tl); - tl++; + fileno = fxdr_hyper(tl); + tl += 2; } len = fxdr_unsigned(int, *tl); if (len <= 0 || len > NFS_MAXNAMLEN) { error = EBADRPC; goto nfsmout; } - tlen = NFSM_RNDUP(len); + /* Round up to an 8 byte boundary. */ + tlen = (len + 7) & ~7; if (tlen == len) - tlen += 4; /* To ensure null termination */ + tlen += 8; /* To ensure null termination. */ left = DIRBLKSIZ - blksiz; - if ((tlen + DIRHDSIZ + NFSX_HYPER) > left) { + if (_GENERIC_DIRLEN(len) > left) { dp->d_reclen += left; uio_iov_base_add(uiop, left); uio_iov_len_add(uiop, -(left)); @@ -3347,12 +3308,12 @@ nfsrpc_readdirplus(vnode_t vp, struct ui uiop->uio_offset += left; blksiz = 0; } - if ((tlen + DIRHDSIZ + NFSX_HYPER) > uio_uio_resid(uiop)) + if (_GENERIC_DIRLEN(len) > uio_uio_resid(uiop)) bigenough = 0; if (bigenough) { dp = (struct dirent *)uio_iov_base(uiop); dp->d_namlen = len; - dp->d_reclen = tlen + DIRHDSIZ + NFSX_HYPER; + dp->d_reclen = _GENERIC_DIRLEN(len); dp->d_type = DT_UNKNOWN; blksiz += dp->d_reclen; if (blksiz == DIRBLKSIZ) @@ -3370,17 +3331,15 @@ nfsrpc_readdirplus(vnode_t vp, struct ui cp = uio_iov_base(uiop); tlen -= len; *cp = '\0'; - cp += tlen; /* points to cookie storage */ - tl2 = (u_int32_t *)cp; if (len == 2 && cnp->cn_nameptr[0] == '.' && cnp->cn_nameptr[1] == '.') isdotdot = 1; else isdotdot = 0; - uio_iov_base_add(uiop, (tlen + NFSX_HYPER)); - uio_iov_len_add(uiop, -(tlen + NFSX_HYPER)); - uio_uio_resid_add(uiop, -(tlen + NFSX_HYPER)); - uiop->uio_offset += (tlen + NFSX_HYPER); + uio_iov_base_add(uiop, tlen); + uio_iov_len_add(uiop, -(tlen)); + uio_uio_resid_add(uiop, -(tlen)); + uiop->uio_offset += tlen; } else { error = nfsm_advance(nd, NFSM_RNDUP(len), -1); if (error) @@ -3409,7 +3368,7 @@ nfsrpc_readdirplus(vnode_t vp, struct ui } } else { rderr = 0; - nfsva.na_mntonfileno = 0xffffffff; + nfsva.na_mntonfileno = UINT64_MAX; error = nfsv4_loadattr(nd, NULL, &nfsva, &nfhp, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, &rderr, p, cred); @@ -3422,7 +3381,7 @@ nfsrpc_readdirplus(vnode_t vp, struct ui if (rderr) { dp->d_fileno = 0; } else if (gotmnton) { - if (nfsva.na_mntonfileno != 0xffffffff) + if (nfsva.na_mntonfileno != UINT64_MAX) dp->d_fileno = nfsva.na_mntonfileno; else dp->d_fileno = nfsva.na_fileid; @@ -3441,10 +3400,11 @@ nfsrpc_readdirplus(vnode_t vp, struct ui } else { dp->d_fileno = fileno; } - *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] = + cookiep->nfsuquad[0] = cookie.lval[0] = ncookie.lval[0]; - *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] = + cookiep->nfsuquad[1] = cookie.lval[1] = ncookie.lval[1]; + dp->d_cookie = ncookie.qval; if (nfhp != NULL) { if (NFSRV_CMPFH(nfhp->nfh_fh, nfhp->nfh_len, @@ -3561,31 +3521,11 @@ nfsrpc_readdirplus(vnode_t vp, struct ui *eofp = eof; } - /* - * Add extra empty records to any remaining DIRBLKSIZ chunks. - */ - while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) { - dp = (struct dirent *)uio_iov_base(uiop); - dp->d_type = DT_UNKNOWN; - dp->d_fileno = 0; - dp->d_namlen = 0; - dp->d_name[0] = '\0'; - tl = (u_int32_t *)&dp->d_name[4]; - *tl++ = cookie.lval[0]; - *tl = cookie.lval[1]; - dp->d_reclen = DIRBLKSIZ; - uio_iov_base_add(uiop, DIRBLKSIZ); - uio_iov_len_add(uiop, -(DIRBLKSIZ)); - uio_uio_resid_add(uiop, -(DIRBLKSIZ)); - uiop->uio_offset += DIRBLKSIZ; - } - nfsmout: if (nd->nd_mrep != NULL) mbuf_freem(nd->nd_mrep); return (error); } -#endif /* !APPLE */ /* * Nfs commit rpc --- fs/nfsclient/nfs_clvnops.c.orig 2014-12-25 17:29:50.000000000 -0500 +++ fs/nfsclient/nfs_clvnops.c 2014-12-26 19:35:37.000000000 -0500 @@ -216,8 +216,6 @@ static int nfs_renameit(struct vnode *sd /* * Global variables */ -#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) - SYSCTL_DECL(_vfs_nfs); static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO; @@ -3129,8 +3127,8 @@ nfs_print(struct vop_print_args *ap) struct vnode *vp = ap->a_vp; struct nfsnode *np = VTONFS(vp); - ncl_printf("\tfileid %ld fsid 0x%x", - np->n_vattr.na_fileid, np->n_vattr.na_fsid); + ncl_printf("\tfileid %jd fsid 0x%x", + (uintmax_t)np->n_vattr.na_fileid, np->n_vattr.na_fsid); if (vp->v_type == VFIFO) fifo_printinfo(vp); printf("\n"); --- fs/nfs/nfsport.h.orig 2014-12-23 09:24:48.000000000 -0500 +++ fs/nfs/nfsport.h 2014-12-26 19:35:37.000000000 -0500 @@ -452,8 +452,8 @@ struct nfs_vattr { struct nfsvattr { struct vattr na_vattr; nfsattrbit_t na_suppattr; - u_int32_t na_mntonfileno; - u_int64_t na_filesid[2]; + uint64_t na_mntonfileno; + uint64_t na_filesid[2]; }; #define na_type na_vattr.va_type @@ -664,12 +664,6 @@ int nfsmsleep(void *, void *, int, const #define NFSMINOR(d) minor(d) /* - * Define this to be the macro that returns the minimum size required - * for a directory entry. - */ -#define DIRENT_SIZE(dp) GENERIC_DIRSIZ(dp) - -/* * The vnode tag for nfsv4root. */ #define VT_NFSV4ROOT "nfsv4root" --- fs/nfs/nfs_var.h.orig 2014-12-22 20:13:08.000000000 -0500 +++ fs/nfs/nfs_var.h 2014-12-27 18:50:47.000000000 -0500 @@ -364,10 +364,10 @@ void newnfs_portinit(void); struct ucred *newnfs_getcred(void); void newnfs_setroot(struct ucred *); int nfs_catnap(int, int, const char *); -struct nfsreferral *nfsv4root_getreferral(vnode_t, vnode_t, u_int32_t); +struct nfsreferral *nfsv4root_getreferral(vnode_t, vnode_t, uint64_t); int nfsvno_pathconf(vnode_t, int, register_t *, struct ucred *, NFSPROC_T *); -int nfsrv_atroot(vnode_t, long *); +int nfsrv_atroot(vnode_t, uint64_t *); void newnfs_timer(void *); int nfs_supportsnfsv4acls(vnode_t); --- fs/nfs/nfs_commonport.c.orig 2014-12-22 20:13:08.000000000 -0500 +++ fs/nfs/nfs_commonport.c 2014-12-26 19:35:37.000000000 -0500 @@ -343,7 +343,7 @@ nfsvno_pathconf(struct vnode *vp, int fl /* Fake nfsrv_atroot. Just return 0 */ int -nfsrv_atroot(struct vnode *vp, long *retp) +nfsrv_atroot(struct vnode *vp, uint64_t *retp) { return (0); @@ -424,7 +424,7 @@ nfs_catnap(int prio, int errval, const c * Get referral. For now, just fail. */ struct nfsreferral * -nfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno) +nfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, uint64_t fileno) { return (NULL); --- fs/nfs/nfs_commonsubs.c.orig 2014-12-22 20:13:08.000000000 -0500 +++ fs/nfs/nfs_commonsubs.c 2014-12-26 19:35:37.000000000 -0500 @@ -814,9 +814,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd struct timespec temptime; uid_t uid; gid_t gid; - long fid; u_int32_t freenum = 0, tuint; - u_int64_t uquad = 0, thyp, thyp2; + u_int64_t fid, uquad = 0, thyp, thyp2; #ifdef QUOTA struct dqblk dqb; uid_t savuid; @@ -1192,7 +1191,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd thyp = fxdr_hyper(tl); if (compare) { if (!(*retcmpp)) { - if ((u_int64_t)nap->na_fileid != thyp) + if (nap->na_fileid != thyp) *retcmpp = NFSERR_NOTSAME; } } else if (nap != NULL) { @@ -1729,7 +1728,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd } else { if (!vp || !nfsrv_atroot(vp, &fid)) fid = nap->na_fileid; - if ((u_int64_t)fid != thyp) + if (fid != thyp) *retcmpp = NFSERR_NOTSAME; } } @@ -2224,8 +2223,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd break; case NFSATTRBIT_FILEID: NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER); - *tl++ = 0; - *tl = txdr_unsigned(vap->va_fileid); + txdr_hyper(vap->va_fileid, tl); retnum += NFSX_HYPER; break; case NFSATTRBIT_FILESAVAIL: @@ -2490,7 +2488,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd if (at_root != 0) uquad = mounted_on_fileno; else - uquad = (u_int64_t)vap->va_fileid; + uquad = vap->va_fileid; txdr_hyper(uquad, tl); retnum += NFSX_HYPER; break; --- fs/tmpfs/tmpfs_subr.c.orig 2014-12-22 20:13:09.000000000 -0500 +++ fs/tmpfs/tmpfs_subr.c 2014-12-26 19:53:10.000000000 -0500 @@ -1169,18 +1169,18 @@ tmpfs_dir_getdents(struct tmpfs_node *no error = tmpfs_dir_getdotdent(node, uio); if (error != 0) return (error); - uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; + off = uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; if (cookies != NULL) - cookies[(*ncookies)++] = off = uio->uio_offset; + cookies[(*ncookies)++] = off; /* FALLTHROUGH */ case TMPFS_DIRCOOKIE_DOTDOT: error = tmpfs_dir_getdotdotdent(node, uio); if (error != 0) return (error); de = tmpfs_dir_first(node, &dc); - uio->uio_offset = tmpfs_dirent_cookie(de); + off = uio->uio_offset = tmpfs_dirent_cookie(de); if (cookies != NULL) - cookies[(*ncookies)++] = off = uio->uio_offset; + cookies[(*ncookies)++] = off; /* EOF. */ if (de == NULL) return (0); @@ -1191,8 +1191,7 @@ tmpfs_dir_getdents(struct tmpfs_node *no de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc); if (de == NULL) return (EINVAL); - if (cookies != NULL) - off = tmpfs_dirent_cookie(de); + off = tmpfs_dirent_cookie(de); } /* Read as much entries as possible; i.e., until we reach the end of @@ -1241,6 +1240,7 @@ tmpfs_dir_getdents(struct tmpfs_node *no de->td_node, (int)de->td_node->tn_type); } } + d.d_cookie = off; d.d_namlen = de->td_namelen; MPASS(de->td_namelen < sizeof(d.d_name)); (void)memcpy(d.d_name, de->ud.td_name, de->td_namelen); @@ -1259,18 +1259,14 @@ tmpfs_dir_getdents(struct tmpfs_node *no error = uiomove(&d, d.d_reclen, uio); if (error == 0) { de = tmpfs_dir_next(node, &dc); + off = tmpfs_dirent_cookie(de); if (cookies != NULL) { - off = tmpfs_dirent_cookie(de); MPASS(*ncookies < maxcookies); cookies[(*ncookies)++] = off; } } } while (error == 0 && uio->uio_resid > 0 && de != NULL); - /* 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; --- sys/vnode.h.orig 2014-12-22 20:13:21.000000000 -0500 +++ sys/vnode.h 2014-12-26 19:35:37.000000000 -0500 @@ -265,7 +265,7 @@ struct vattr { uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ dev_t va_fsid; /* filesystem id */ - long va_fileid; /* file id */ + uint64_t va_fileid; /* file id */ u_quad_t va_size; /* file size in bytes */ long va_blocksize; /* blocksize preferred for i/o */ struct timespec va_atime; /* time of last access */ --- sys/dirent.h.orig 2014-12-22 20:13:21.000000000 -0500 +++ sys/dirent.h 2014-12-26 19:35:37.000000000 -0500 @@ -38,16 +38,33 @@ /* * The dirent structure defines the format of directory entries returned by - * the getdirentries(2) system call. + * the getdirentries(2) system call and dirent32 for the getdirentries32(2) + * system call. * - * A directory entry has a struct dirent at the front of it, containing its + * A directory entry has a struct dirent(32) at the front of it, containing its * inode number, the length of the entry, and the length of the name - * contained in the entry. These are followed by the name padded to a 4 + * contained in the entry. These are followed by the name padded to a 8(4) * byte boundary with null bytes. All names are guaranteed null terminated. * The maximum length of a name in a directory is MAXNAMLEN. */ struct dirent { + __uint64_t d_cookie; /* cookie for next fs dir entry */ + __uint64_t d_fileno; /* file number of entry */ + __uint16_t d_reclen; /* length of this record */ + __uint16_t d_namlen; /* length of string in d_name */ + __uint8_t d_type; /* file type, see below */ + __uint8_t d_unused1; /* align d_name to an 8 byte boundary */ + __uint16_t d_unused2; +#if __BSD_VISIBLE +#define MAXNAMLEN 255 + char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ +#else + char d_name[255 + 1]; /* name must be no longer than this */ +#endif +}; + +struct dirent32 { __uint32_t d_fileno; /* file number of entry */ __uint16_t d_reclen; /* length of this record */ __uint8_t d_type; /* file type, see below */ @@ -81,15 +98,20 @@ struct dirent { #define DTTOIF(dirtype) ((dirtype) << 12) /* - * The _GENERIC_DIRSIZ macro gives the minimum record length which will hold - * the directory entry. This returns the amount of space in struct direct - * without the d_name field, plus enough space for the name with a terminating - * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + * The _GENERIC_xxx macros gives the minimum record length which will + * hold the directory entry. They return the amount of space in struct + * dirent(32) without the d_name field, plus enough space for the name with a + * terminating null byte (dp->d_namlen+1), rounded up to a 8(4) byte boundary. + * The _GENERIC_DIRLEN() case takes the name length instead of dp as the + * argument. * * XXX although this macro is in the implementation namespace, it requires * a manifest constant that is not. */ -#define _GENERIC_DIRSIZ(dp) \ +#define _GENERIC_DIRLEN(namlen) \ + ((offsetof(struct dirent, d_name) + (namlen) + 1 + 7) & ~7) +#define _GENERIC_DIRSIZ(dp) _GENERIC_DIRLEN((dp)->d_namlen) +#define _GENERIC_DIRSIZ32(dp) \ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) #endif /* __BSD_VISIBLE */ --- ufs/ufs/ufs_vnops.c.orig 2014-12-22 20:14:13.000000000 -0500 +++ ufs/ufs/ufs_vnops.c 2014-12-26 19:35:36.000000000 -0500 @@ -2209,6 +2209,7 @@ ufs_readdir(ap) } if (offset < startoffset || dp->d_ino == 0) goto nextentry; + dstdp.d_cookie = offset + dp->d_reclen; dstdp.d_fileno = dp->d_ino; dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen); --- cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c.orig 2014-12-22 20:14:27.000000000 -0500 +++ cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2014-12-26 19:35:36.000000000 -0500 @@ -2667,6 +2667,8 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cre odp->d_namlen = strlen(zap.za_name); (void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1); odp->d_type = type; + /* d_cookie is the offset for the next entry. */ + next = &(odp->d_cookie); odp = (dirent64_t *)((intptr_t)odp + reclen); } outcount += reclen; @@ -2688,6 +2690,8 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cre offset += 1; } + if (next != NULL) + *next = offset; if (cooks != NULL) { *cooks++ = offset; ncooks--; --- cddl/contrib/opensolaris/uts/common/fs/gfs.c.orig 2014-12-22 20:14:26.000000000 -0500 +++ cddl/contrib/opensolaris/uts/common/fs/gfs.c 2014-12-26 19:35:36.000000000 -0500 @@ -292,6 +292,7 @@ gfs_readdir_emit_int(gfs_readdir_state_t dp->d_reclen = (ushort_t)reclen; dp->d_type = DT_DIR; dp->d_namlen = namlen; + dp->d_cookie = next; } if (uiomove((caddr_t)st->grd_dirent, reclen, UIO_READ, uiop)) --- cddl/compat/opensolaris/sys/dirent.h.orig 2014-12-22 20:14:31.000000000 -0500 +++ cddl/compat/opensolaris/sys/dirent.h 2014-12-26 19:35:36.000000000 -0500 @@ -40,8 +40,7 @@ typedef ino_t ino64_t; #define d_ino d_fileno -#define DIRENT64_RECLEN(len) ((sizeof(struct dirent) - \ - sizeof(((struct dirent *)NULL)->d_name) + \ - (len) + 1 + 3) & ~3) +#define DIRENT64_RECLEN(len) \ + ((offsetof(struct dirent, d_name) + (len) + 1 + 7) & ~7) #endif /* !_OPENSOLARIS_SYS_DIRENT_H_ */