--- fs/nfsclient/nfs_clrpcops.c.sav 2013-05-11 20:02:24.000000000 -0400 +++ fs/nfsclient/nfs_clrpcops.c 2013-05-11 20:46:28.000000000 -0400 @@ -2604,31 +2604,6 @@ nfsrpc_rmdir(vnode_t dvp, char *name, in /* * Readdir rpc. - * Always returns with either uio_resid unchanged, if you are at the - * end of the directory, or uio_resid == 0, with all DIRBLKSIZ chunks - * filled in. - * I felt this would allow caching of directory blocks more easily - * than returning a pertially filled block. - * Directory offset cookies: - * Oh my, what to do with them... - * I can think of three ways to deal with them: - * 1 - have the layer above these RPCs maintain a map between logical - * directory byte offsets and the NFS directory offset cookies - * 2 - pass the opaque directory offset cookies up into userland - * and let the libc functions deal with them, via the system call - * 3 - return them to userland in the "struct dirent", so future versions - * of libc can use them and do whatever is necessary to amke things work - * above these rpc calls, in the meantime - * For now, I do #3 by "hiding" the directory offset cookies after the - * d_name field in struct dirent. This is space inside d_reclen that - * will be ignored by anything that doesn't know about them. - * The directory offset cookies are filled in as the last 8 bytes of - * each directory entry, after d_name. Someday, the userland libc - * functions may be able to use these. In the meantime, it satisfies - * OpenBSD's requirements for cookies being returned. - * If expects the directory offset cookie for the read to be in uio_offset - * and returns the one for the next entry after this directory block in - * there, as well. */ APPLESTATIC int nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep, @@ -2649,12 +2624,12 @@ nfsrpc_readdir(vnode_t vp, struct uio *u u_int32_t fakefileno = 0xffffffff, rderr; char *cp; nfsattrbit_t attrbits, dattrbits; - u_int32_t *tl2 = NULL; - size_t tresid; + ssize_t tresid; KASSERT(uiop->uio_iovcnt == 1 && - (uio_uio_resid(uiop) & (DIRBLKSIZ - 1)) == 0, - ("nfs readdirrpc bad uio")); + (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 && + (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0, + ("nfsrpc_readdir bad uio")); /* * There is no point in reading a lot more than uio_resid, however @@ -2663,13 +2638,13 @@ nfsrpc_readdir(vnode_t vp, struct uio *u * will never make readsize > nm_readdirsize. */ readsize = nmp->nm_readdirsize; - if (readsize > uio_uio_resid(uiop)) - readsize = uio_uio_resid(uiop) + DIRBLKSIZ; + if (readsize > uiop->uio_resid) + readsize = uiop->uio_resid + DIRBLKSIZ; *attrflagp = 0; if (eofp) *eofp = 0; - tresid = uio_uio_resid(uiop); + tresid = uiop->uio_resid; cookie.lval[0] = cookiep->nfsuquad[0]; cookie.lval[1] = cookiep->nfsuquad[1]; nd->nd_mrep = NULL; @@ -2765,43 +2740,33 @@ 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->d_type = DT_DIR; + dp = (struct dirent *)uiop->uio_iov->iov_base; dp->d_fileno = dotfileid; dp->d_namlen = 1; 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 = 4 + DIRHDSIZ; + dp->d_type = DT_DIR; 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->d_type = DT_DIR; + uiop->uio_resid -= dp->d_reclen; + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + dp->d_reclen; + uiop->uio_iov->iov_len -= dp->d_reclen; + dp = (struct dirent *)uiop->uio_iov->iov_base; dp->d_fileno = dotdotfileid; dp->d_namlen = 2; 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 = 4 + DIRHDSIZ; + dp->d_type = DT_DIR; 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)); + uiop->uio_resid -= dp->d_reclen; + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + dp->d_reclen; + uiop->uio_iov->iov_len -= dp->d_reclen; } NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_RDATTRERROR); } else { @@ -2895,40 +2860,41 @@ nfsrpc_readdir(vnode_t vp, struct uio *u if (tlen == len) tlen += 4; /* To ensure null termination */ left = DIRBLKSIZ - blksiz; - if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > left) { + if ((tlen + DIRHDSIZ) > left) { dp->d_reclen += left; - uio_iov_base_add(uiop, left); - uio_iov_len_add(uiop, -(left)); - uio_uio_resid_add(uiop, -(left)); + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + left; + uiop->uio_iov->iov_len -= left; uiop->uio_offset += left; + uiop->uio_resid -= left; blksiz = 0; } - if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > uio_uio_resid(uiop)) + if ((tlen + DIRHDSIZ) > uiop->uio_resid) bigenough = 0; if (bigenough) { - dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop)); + dp = (struct dirent *)uiop->uio_iov->iov_base; dp->d_namlen = len; - dp->d_reclen = tlen + DIRHDSIZ + NFSX_HYPER; + dp->d_reclen = tlen + DIRHDSIZ; dp->d_type = DT_UNKNOWN; blksiz += dp->d_reclen; if (blksiz == DIRBLKSIZ) blksiz = 0; - uio_uio_resid_add(uiop, -(DIRHDSIZ)); uiop->uio_offset += DIRHDSIZ; - uio_iov_base_add(uiop, DIRHDSIZ); - uio_iov_len_add(uiop, -(DIRHDSIZ)); + uiop->uio_resid -= DIRHDSIZ; + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + DIRHDSIZ; + uiop->uio_iov->iov_len -= DIRHDSIZ; error = nfsm_mbufuio(nd, uiop, len); if (error) goto nfsmout; - cp = CAST_DOWN(caddr_t, uio_iov_base(uiop)); + cp = uiop->uio_iov->iov_base; 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); + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + tlen; + uiop->uio_iov->iov_len -= tlen; + uiop->uio_offset += tlen; + uiop->uio_resid -= tlen; } else { error = nfsm_advance(nd, NFSM_RNDUP(len), -1); if (error) @@ -2979,9 +2945,9 @@ 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]; } more_dirs = fxdr_unsigned(int, *tl); @@ -3011,10 +2977,11 @@ nfsrpc_readdir(vnode_t vp, struct uio *u if (blksiz > 0) { left = DIRBLKSIZ - blksiz; dp->d_reclen += left; - uio_iov_base_add(uiop, left); - uio_iov_len_add(uiop, -(left)); - uio_uio_resid_add(uiop, -(left)); + uiop->uio_iov->iov_base = + (char *)uiop->uio_iov->iov_base + left; + uiop->uio_iov->iov_len -= left; uiop->uio_offset += left; + uiop->uio_resid -= left; } /* @@ -3024,7 +2991,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *u * Otherwise, return the eof flag from the server. */ if (eofp) { - if (tresid == ((size_t)(uio_uio_resid(uiop)))) + if (tresid == uiop->uio_resid) *eofp = 1; else if (!bigenough) *eofp = 0; @@ -3032,25 +2999,6 @@ 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);