summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/nfs/nfs_common.c67
-rw-r--r--sys/nfs/nfs_common.h1
-rw-r--r--sys/nfsclient/nfs_krpc.c67
-rw-r--r--sys/nfsserver/nfs.h1
-rw-r--r--sys/nfsserver/nfs_fha.c4
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c59
6 files changed, 73 insertions, 126 deletions
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index 6f42645..abf575f 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/sysent.h>
#include <sys/syscall.h>
+#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
@@ -78,6 +79,16 @@ nfstype nfsv3_type[9] = {
static void *nfsm_dissect_xx_sub(int s, struct mbuf **md, caddr_t *dpos,
int how);
+SYSCTL_DECL(_vfs_nfs);
+
+static int nfs_realign_test;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RD, &nfs_realign_test,
+ 0, "Number of realign tests done");
+
+static int nfs_realign_count;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RD, &nfs_realign_count,
+ 0, "Number of mbuf realignments done");
+
u_quad_t
nfs_curusec(void)
{
@@ -337,3 +348,59 @@ nfsm_adv_xx(int s, struct mbuf **md, caddr_t *dpos)
return (t1);
return (0);
}
+
+/*
+ * Check for badly aligned mbuf data and realign by copying the unaligned
+ * portion of the data into a new mbuf chain and freeing the portions of the
+ * old chain that were replaced.
+ *
+ * We cannot simply realign the data within the existing mbuf chain because
+ * the underlying buffers may contain other rpc commands and we cannot afford
+ * to overwrite them.
+ *
+ * We would prefer to avoid this situation entirely. The situation does not
+ * occur with NFS/UDP and is supposed to only occassionally occur with TCP.
+ * Use vfs.nfs.realign_count and realign_test to check this.
+ */
+int
+nfs_realign(struct mbuf **pm, int how)
+{
+ struct mbuf *m, *n;
+ int off;
+
+ ++nfs_realign_test;
+ while ((m = *pm) != NULL) {
+ if (!nfsm_aligned(m->m_len, u_int32_t) ||
+ !nfsm_aligned(mtod(m, intptr_t), u_int32_t)) {
+ /*
+ * NB: we can't depend on m_pkthdr.len to help us
+ * decide what to do here. May not be worth doing
+ * the m_length calculation as m_copyback will
+ * expand the mbuf chain below as needed.
+ */
+ if (m_length(m, NULL) >= MINCLSIZE) {
+ /* NB: m_copyback handles space > MCLBYTES */
+ n = m_getcl(how, MT_DATA, 0);
+ } else
+ n = m_get(how, MT_DATA);
+ if (n == NULL)
+ return (ENOMEM);
+ /*
+ * Align the remainder of the mbuf chain.
+ */
+ n->m_len = 0;
+ off = 0;
+ while (m != NULL) {
+ m_copyback(n, off, m->m_len, mtod(m, caddr_t));
+ off += m->m_len;
+ m = m->m_next;
+ }
+ m_freem(*pm);
+ *pm = n;
+ ++nfs_realign_count;
+ break;
+ }
+ pm = &m->m_next;
+ }
+ return (0);
+}
diff --git a/sys/nfs/nfs_common.h b/sys/nfs/nfs_common.h
index 9ad1c11..1c0b315 100644
--- a/sys/nfs/nfs_common.h
+++ b/sys/nfs/nfs_common.h
@@ -48,6 +48,7 @@ extern nfstype nfsv3_type[];
int nfs_adv(struct mbuf **, caddr_t *, int, int);
u_quad_t nfs_curusec(void);
void *nfsm_disct(struct mbuf **, caddr_t *, int, int, int);
+int nfs_realign(struct mbuf **, int);
/* ****************************** */
/* Build request/reply phase macros */
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
index 8b23682..bfb1ea1 100644
--- a/sys/nfsclient/nfs_krpc.c
+++ b/sys/nfsclient/nfs_krpc.c
@@ -87,8 +87,6 @@ uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS];
uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS];
#endif
-static int nfs_realign_test;
-static int nfs_realign_count;
static int nfs_bufpackets = 4;
static int nfs_reconnects;
static int nfs3_jukebox_delay = 10;
@@ -97,10 +95,6 @@ static int fake_wchan;
SYSCTL_DECL(_vfs_nfs);
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0,
- "Number of realign tests done");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0,
- "Number of mbuf realignments done");
SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0,
"Buffer reservation size 2 < x < 64");
SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
@@ -403,65 +397,6 @@ nfs_feedback(int type, int proc, void *arg)
}
/*
- * nfs_realign:
- *
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions
- * of the old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain
- * because the underlying buffers may contain other rpc commands and
- * we cannot afford to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does
- * not occur with NFS/UDP and is supposed to only occassionally occur
- * with TCP. Use vfs.nfs.realign_count and realign_test to check this.
- *
- */
-static int
-nfs_realign(struct mbuf **pm, int hsiz)
-{
- struct mbuf *m, *n;
- int off, space;
-
- ++nfs_realign_test;
- while ((m = *pm) != NULL) {
- if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
- /*
- * NB: we can't depend on m_pkthdr.len to help us
- * decide what to do here. May not be worth doing
- * the m_length calculation as m_copyback will
- * expand the mbuf chain below as needed.
- */
- space = m_length(m, NULL);
- if (space >= MINCLSIZE) {
- /* NB: m_copyback handles space > MCLBYTES */
- n = m_getcl(M_DONTWAIT, MT_DATA, 0);
- } else
- n = m_get(M_DONTWAIT, MT_DATA);
- if (n == NULL)
- return (ENOMEM);
- /*
- * Align the remainder of the mbuf chain.
- */
- n->m_len = 0;
- off = 0;
- while (m != NULL) {
- m_copyback(n, off, m->m_len, mtod(m, caddr_t));
- off += m->m_len;
- m = m->m_next;
- }
- m_freem(*pm);
- *pm = n;
- ++nfs_realign_count;
- break;
- }
- pm = &m->m_next;
- }
- return (0);
-}
-
-/*
* nfs_request - goes something like this
* - fill in request struct
* - links it into list
@@ -589,7 +524,7 @@ tryagain:
* These could cause pointer alignment problems, so copy them to
* well aligned mbufs.
*/
- error = nfs_realign(&mrep, 2 * NFSX_UNSIGNED);
+ error = nfs_realign(&mrep, M_DONTWAIT);
if (error == ENOMEM) {
m_freem(mrep);
AUTH_DESTROY(auth);
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 00dbe5b..bb1893e 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -239,7 +239,6 @@ extern int nfs_debug;
#endif
-void nfs_realign(struct mbuf **);
struct mbuf *nfs_rephead(int, struct nfsrv_descript *, int, struct mbuf **,
caddr_t *);
void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *,
diff --git a/sys/nfsserver/nfs_fha.c b/sys/nfsserver/nfs_fha.c
index 25e930f..76537d7 100644
--- a/sys/nfsserver/nfs_fha.c
+++ b/sys/nfsserver/nfs_fha.c
@@ -202,7 +202,9 @@ fha_extract_info(struct svc_req *req, struct fha_info *i)
procnum == NFSPROC_NULL)
goto out;
- nfs_realign(&req->rq_args);
+ error = nfs_realign(&req->rq_args, M_DONTWAIT);
+ if (error)
+ goto out;
md = req->rq_args;
dpos = mtod(md, caddr_t);
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
index bdfe424..512373b 100644
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ b/sys/nfsserver/nfs_srvkrpc.c
@@ -96,8 +96,6 @@ SYSCTL_DECL(_vfs_nfsrv);
SVCPOOL *nfsrv_pool;
int nfsd_waiting = 0;
int nfsrv_numnfsd = 0;
-static int nfs_realign_test;
-static int nfs_realign_count;
struct callout nfsrv_callout;
static eventhandler_tag nfsrv_nmbclusters_tag;
@@ -111,10 +109,6 @@ SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay, CTLFLAG_RW,
SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay_v3, CTLFLAG_RW,
&nfsrvw_procrastinate_v3, 0,
"Delay in seconds for NFSv3 write gathering");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_test, CTLFLAG_RW,
- &nfs_realign_test, 0, "");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_count, CTLFLAG_RW,
- &nfs_realign_count, 0, "");
static int nfssvc_addsock(struct file *, struct thread *);
static int nfssvc_nfsd(struct thread *, struct nfsd_nfsd_args *);
@@ -250,57 +244,6 @@ nfs_rephead(int siz, struct nfsrv_descript *nd, int err,
return (mreq);
}
-/*
- * nfs_realign:
- *
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions
- * of the old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain
- * because the underlying buffers may contain other rpc commands and
- * we cannot afford to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does
- * not occur with NFS/UDP and is supposed to only occassionally occur
- * with TCP. Use vfs.nfs.realign_count and realign_test to check this.
- */
-void
-nfs_realign(struct mbuf **pm) /* XXX COMMON */
-{
- struct mbuf *m;
- struct mbuf *n = NULL;
- int off = 0;
-
- ++nfs_realign_test;
- while ((m = *pm) != NULL) {
- if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
- MGET(n, M_WAIT, MT_DATA);
- if (m->m_len >= MINCLSIZE) {
- MCLGET(n, M_WAIT);
- }
- n->m_len = 0;
- break;
- }
- pm = &m->m_next;
- }
-
- /*
- * If n is non-NULL, loop on m copying data, then replace the
- * portion of the chain that had to be realigned.
- */
- if (n != NULL) {
- ++nfs_realign_count;
- while (m) {
- m_copyback(n, off, m->m_len, mtod(m, caddr_t));
- off += m->m_len;
- m = m->m_next;
- }
- m_freem(*pm);
- *pm = n;
- }
-}
-
static void
nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
{
@@ -334,7 +277,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
mreq = mrep = NULL;
mreq = rqst->rq_args;
rqst->rq_args = NULL;
- nfs_realign(&mreq);
+ (void)nfs_realign(&mreq, M_WAIT);
/*
* Note: we want rq_addr, not svc_getrpccaller for nd_nam2 -
OpenPOWER on IntegriCloud