Hartmut Brandt wrote:
> Hi,
> 
> I've updated one of my -current machines this week (previous update
> was in
> february). Now I see a strange effect (it seems only on NFS mounts):
> ls or
> even echo * will list only some files (strange enough the first files
> from
> the normal, alphabetically ordered list). If I change something in the
> directory (delete a file or create a new one) for some time the
> complete
> listing will appear but after sime time (seconds to a minute or so)
> again
> only part of the files is listed.
> 
> A ktrace on ls /usr/src/lib/libc/gen shows that getdirentries is
> called
> only once (returning 4096). For a full listing getdirentries is called
> 5
> times with the last returning 0.
> 
> I can still open files that are not listed if I know their name,
> though.
> 
> The NFS server is a Windows 2008 server with an OpenText NFS Server
> which
> works without problems to all the other FreeBSD machines.
> 
> So what could that be?
> 
I've attached a patch that might be worth trying. It is a "shot in the dark",
but brings the new NFS client's readdir closer to the old one (which you
mentioned still works ok).

Please let me know how it goes, if you have a chance to test it, rick

> Regards,
> harti
> _______________________________________________
> freebsd-current@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to
> "freebsd-current-unsubscr...@freebsd.org"
--- 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);
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to