diff options
Diffstat (limited to 'sys/fs/nfsserver/nfs_nfsdserv.c')
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdserv.c | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index 1b34cb27dd01..d2fe9e60a0ea 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -667,6 +667,7 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram, int getret = 1, len; struct nfsvattr nva; struct thread *p = curthread; + uint16_t off; if (nd->nd_repstat) { nfsrv_postopattr(nd, getret, &nva); @@ -678,9 +679,14 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram, else nd->nd_repstat = EINVAL; } - if (!nd->nd_repstat) - nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, p, - &mp, &mpend, &len); + if (nd->nd_repstat == 0) { + if ((nd->nd_flag & ND_EXTPG) != 0) + nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, + nd->nd_maxextsiz, p, &mp, &mpend, &len); + else + nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, + 0, p, &mp, &mpend, &len); + } if (nd->nd_flag & ND_NFSV3) getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); vput(vp); @@ -693,7 +699,16 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram, if (mp != NULL) { nd->nd_mb->m_next = mp; nd->nd_mb = mpend; - nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len; + if ((mpend->m_flags & M_EXTPG) != 0) { + nd->nd_bextpg = mpend->m_epg_npgs - 1; + nd->nd_bpos = (char *)(void *) + PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]); + off = (nd->nd_bextpg == 0) ? mpend->m_epg_1st_off : 0; + nd->nd_bpos += off + mpend->m_epg_last_len; + nd->nd_bextpgsiz = PAGE_SIZE - mpend->m_epg_last_len - + off; + } else + nd->nd_bpos = mtod(mpend, char *) + mpend->m_len; } out: @@ -718,6 +733,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, nfsv4stateid_t stateid; nfsquad_t clientid; struct thread *p = curthread; + uint16_t poff; if (nd->nd_repstat) { nfsrv_postopattr(nd, getret, &nva); @@ -839,8 +855,21 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, cnt = reqlen; m3 = NULL; if (cnt > 0) { - nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p, - &m3, &m2); + /* + * If cnt > MCLBYTES and the reply will not be saved, use + * ext_pgs mbufs for TLS. + * For NFSv4.0, we do not know for sure if the reply will + * be saved, so do not use ext_pgs mbufs for NFSv4.0. + * Always use ext_pgs mbufs if ND_EXTPG is set. + */ + if ((nd->nd_flag & ND_EXTPG) != 0 || (cnt > MCLBYTES && + (nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS && + (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4)) + nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, + nd->nd_maxextsiz, p, &m3, &m2); + else + nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, + 0, p, &m3, &m2); if (!(nd->nd_flag & ND_NFSV4)) { getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL); if (!nd->nd_repstat) @@ -875,7 +904,17 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, if (m3) { nd->nd_mb->m_next = m3; nd->nd_mb = m2; - nd->nd_bpos = mtod(m2, caddr_t) + m2->m_len; + if ((m2->m_flags & M_EXTPG) != 0) { + nd->nd_flag |= ND_EXTPG; + nd->nd_bextpg = m2->m_epg_npgs - 1; + nd->nd_bpos = (char *)(void *) + PHYS_TO_DMAP(m2->m_epg_pa[nd->nd_bextpg]); + poff = (nd->nd_bextpg == 0) ? m2->m_epg_1st_off : 0; + nd->nd_bpos += poff + m2->m_epg_last_len; + nd->nd_bextpgsiz = PAGE_SIZE - m2->m_epg_last_len - + poff; + } else + nd->nd_bpos = mtod(m2, char *) + m2->m_len; } out: @@ -5536,6 +5575,7 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram, int error, len; char *name; struct thread *p = curthread; + uint16_t off; error = 0; if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { @@ -5555,8 +5595,9 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram, name = malloc(len + 1, M_TEMP, M_WAITOK); nd->nd_repstat = nfsrv_mtostr(nd, name, len); if (nd->nd_repstat == 0) - nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_maxresp, - nd->nd_cred, p, &mp, &mpend, &len); + nd->nd_repstat = nfsvno_getxattr(vp, name, + nd->nd_maxresp, nd->nd_cred, nd->nd_flag, + nd->nd_maxextsiz, p, &mp, &mpend, &len); if (nd->nd_repstat == ENOATTR) nd->nd_repstat = NFSERR_NOXATTR; else if (nd->nd_repstat == EOPNOTSUPP) @@ -5567,7 +5608,19 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram, if (len > 0) { nd->nd_mb->m_next = mp; nd->nd_mb = mpend; - nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len; + if ((mpend->m_flags & M_EXTPG) != 0) { + nd->nd_flag |= ND_EXTPG; + nd->nd_bextpg = mpend->m_epg_npgs - 1; + nd->nd_bpos = (char *)(void *) + PHYS_TO_DMAP(mpend->m_epg_pa[nd->nd_bextpg]); + off = (nd->nd_bextpg == 0) ? + mpend->m_epg_1st_off : 0; + nd->nd_bpos += off + mpend->m_epg_last_len; + nd->nd_bextpgsiz = PAGE_SIZE - + mpend->m_epg_last_len - off; + } else + nd->nd_bpos = mtod(mpend, char *) + + mpend->m_len; } } free(name, M_TEMP); |