This is the first of three diffs intended to make me want to gouge out
my eyes when reading NFS code.
Legibility is good, because if nobody can read it, nobody will fix it.
Please make sure that these don't asplode your setups. Thanks.
- Bert
Index: nfs/nfs_serv.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_serv.c,v
retrieving revision 1.58
diff -u -p -r1.58 nfs_serv.c
--- nfs/nfs_serv.c 6 Jul 2008 16:54:48 -0000 1.58
+++ nfs/nfs_serv.c 24 Oct 2008 11:14:28 -0000
@@ -411,59 +411,28 @@ nfsrv_readlink(nfsd, slp, procp, mrq)
struct mbuf *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
- struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
- struct iovec *ivp = iv;
- struct mbuf *mp;
+ struct iovec iv;
u_int32_t *tl;
int32_t t1;
- int error = 0, rdonly, i, tlen, len, getret;
+ int error = 0, rdonly, pad, getret;
int v3 = (nfsd->nd_flag & ND_NFSV3);
char *cp2;
- struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq;
+ struct mbuf *mb, *mp, *mreq;
struct vnode *vp;
struct vattr attr;
nfsfh_t nfh;
fhandle_t *fhp;
- struct uio io, *uiop = &io;
+ struct uio io;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
- len = 0;
- i = 0;
- while (len < NFS_MAXPATHLEN) {
- MGET(mp, M_WAIT, MT_DATA);
- MCLGET(mp, M_WAIT);
- mp->m_len = NFSMSIZ(mp);
- if (len == 0)
- mp3 = mp2 = mp;
- else {
- mp2->m_next = mp;
- mp2 = mp;
- }
- if ((len+mp->m_len) > NFS_MAXPATHLEN) {
- mp->m_len = NFS_MAXPATHLEN-len;
- len = NFS_MAXPATHLEN;
- } else
- len += mp->m_len;
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- i++;
- ivp++;
- }
- uiop->uio_iov = iv;
- uiop->uio_iovcnt = i;
- uiop->uio_offset = 0;
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_READ;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_procp = (struct proc *)0;
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
if (error) {
- m_freem(mp3);
nfsm_reply(2 * NFSX_UNSIGNED);
nfsm_srvpostop_attr(nfsd, 1, NULL, &mb);
return (0);
}
+
if (vp->v_type != VLNK) {
if (v3)
error = EINVAL;
@@ -471,26 +440,43 @@ nfsrv_readlink(nfsd, slp, procp, mrq)
error = ENXIO;
goto out;
}
- error = VOP_READLINK(vp, uiop, cred);
+
+ MGET(mp, M_WAIT, MT_DATA);
+ MCLGET(mp, M_WAIT); /* MLEN < NFS_MAXPATHLEN < MCLBYTES */
+
+ iv.iov_base = mtod(mp, caddr_t);
+ iv.iov_len = NFS_MAXPATHLEN;
+
+ io.uio_iov = &iv;
+ io.uio_iovcnt = 1;
+ io.uio_offset = 0;
+ io.uio_resid = NFS_MAXPATHLEN;
+ io.uio_rw = UIO_READ;
+ io.uio_segflg = UIO_SYSSPACE;
+ io.uio_procp = NULL;
+
+ error = VOP_READLINK(vp, &io, cred);
+ if (error)
+ m_freem(mp);
+ else
+ mp->m_len = io.uio_offset;
out:
getret = VOP_GETATTR(vp, &attr, cred, procp);
vput(vp);
- if (error)
- m_freem(mp3);
+
nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
if (v3) {
nfsm_srvpostop_attr(nfsd, getret, &attr, &mb);
if (error)
return (0);
}
- if (uiop->uio_resid > 0) {
- len -= uiop->uio_resid;
- tlen = nfsm_rndup(len);
- nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
+ if ((pad = nfsm_padlen(mp->m_len)) > 0) {
+ bzero(mb_offset(mp), pad);
+ mp->m_len += pad;
}
tl = nfsm_build(&mb, NFSX_UNSIGNED);
- *tl = txdr_unsigned(len);
- mb->m_next = mp3;
+ *tl = txdr_unsigned(mp->m_len);
+ mb->m_next = mp;
nfsmout:
return(error);
}