aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/nfs')
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c84
-rw-r--r--sys/fs/nfs/nfs_var.h1
2 files changed, 73 insertions, 12 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index b810096e73a9..9da9f7f5bbdc 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -832,22 +832,38 @@ nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
bytesize = NFSX_UNSIGNED + siz + rem;
m2 = nd->nd_mb;
cp2 = nd->nd_bpos;
- left = M_TRAILINGSPACE(m2);
+ if ((nd->nd_flag & ND_EXTPG) != 0)
+ left = nd->nd_bextpgsiz;
+ else
+ left = M_TRAILINGSPACE(m2);
+ KASSERT(((m2->m_flags & (M_EXT | M_EXTPG)) ==
+ (M_EXT | M_EXTPG) && (nd->nd_flag & ND_EXTPG) != 0) ||
+ ((m2->m_flags & (M_EXT | M_EXTPG)) !=
+ (M_EXT | M_EXTPG) && (nd->nd_flag & ND_EXTPG) == 0),
+ ("nfsm_strtom: ext_pgs and non-ext_pgs mbufs mixed"));
/*
* Loop around copying the string to mbuf(s).
*/
while (siz > 0) {
if (left == 0) {
- if (siz > ncl_mbuf_mlen)
- NFSMCLGET(m1, M_WAITOK);
- else
- NFSMGET(m1);
- m1->m_len = 0;
- m2->m_next = m1;
- m2 = m1;
- cp2 = mtod(m2, caddr_t);
- left = M_TRAILINGSPACE(m2);
+ if ((nd->nd_flag & ND_EXTPG) != 0) {
+ m2 = nfsm_add_ext_pgs(m2,
+ nd->nd_maxextsiz, &nd->nd_bextpg);
+ cp2 = (char *)(void *)PHYS_TO_DMAP(
+ m2->m_epg_pa[nd->nd_bextpg]);
+ nd->nd_bextpgsiz = left = PAGE_SIZE;
+ } else {
+ if (siz > ncl_mbuf_mlen)
+ NFSMCLGET(m1, M_WAITOK);
+ else
+ NFSMGET(m1);
+ m1->m_len = 0;
+ cp2 = mtod(m1, char *);
+ left = M_TRAILINGSPACE(m1);
+ m2->m_next = m1;
+ m2 = m1;
+ }
}
if (left >= siz)
xfer = siz;
@@ -855,18 +871,31 @@ nfsm_strtom(struct nfsrv_descript *nd, const char *cp, int siz)
xfer = left;
NFSBCOPY(cp, cp2, xfer);
cp += xfer;
+ cp2 += xfer;
m2->m_len += xfer;
siz -= xfer;
left -= xfer;
+ if ((nd->nd_flag & ND_EXTPG) != 0) {
+ nd->nd_bextpgsiz -= xfer;
+ m2->m_epg_last_len += xfer;
+ }
if (siz == 0 && rem) {
if (left < rem)
panic("nfsm_strtom");
- NFSBZERO(cp2 + xfer, rem);
+ NFSBZERO(cp2, rem);
m2->m_len += rem;
+ cp2 += rem;
+ if ((nd->nd_flag & ND_EXTPG) != 0) {
+ nd->nd_bextpgsiz -= rem;
+ m2->m_epg_last_len += rem;
+ }
}
}
nd->nd_mb = m2;
- nd->nd_bpos = mtod(m2, caddr_t) + m2->m_len;
+ if ((nd->nd_flag & ND_EXTPG) != 0)
+ nd->nd_bpos = cp2;
+ else
+ nd->nd_bpos = mtod(m2, char *) + m2->m_len;
return (bytesize);
}
@@ -4845,3 +4874,34 @@ nfsm_set(struct nfsrv_descript *nd, u_int offs)
} else
nd->nd_bpos = mtod(m, char *) + offs;
}
+
+/*
+ * Grow a ext_pgs mbuf list. Either allocate another page or add
+ * an mbuf to the list.
+ */
+struct mbuf *
+nfsm_add_ext_pgs(struct mbuf *m, int maxextsiz, int *bextpg)
+{
+ struct mbuf *mp;
+ vm_page_t pg;
+
+ if ((m->m_epg_npgs + 1) * PAGE_SIZE > maxextsiz) {
+ mp = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK);
+ *bextpg = 0;
+ m->m_next = mp;
+ } else {
+ do {
+ pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP |
+ VM_ALLOC_WIRED);
+ if (pg == NULL)
+ vm_wait(NULL);
+ } while (pg == NULL);
+ m->m_epg_pa[m->m_epg_npgs] = VM_PAGE_TO_PHYS(pg);
+ *bextpg = m->m_epg_npgs;
+ m->m_epg_npgs++;
+ m->m_epg_last_len = 0;
+ mp = m;
+ }
+ return (mp);
+}
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 5efa054af82c..e92a6859d0de 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -361,6 +361,7 @@ void nfsv4_freeslot(struct nfsclsession *, int);
struct ucred *nfsrv_getgrpscred(struct ucred *);
struct nfsdevice *nfsv4_findmirror(struct nfsmount *);
void nfsm_set(struct nfsrv_descript *, u_int);
+struct mbuf *nfsm_add_ext_pgs(struct mbuf *, int, int *);
/* nfs_clcomsubs.c */
void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);