svn commit: r192686 - head/sys/nfsclient
Doug Rabson
dfr at rabson.org
Sun May 24 14:01:09 UTC 2009
Also, this problem appears to be there in the new experimental NFS
client code as well. I haven't tried to fix that.
On 24 May 2009, at 14:22, Doug Rabson wrote:
> Author: dfr
> Date: Sun May 24 13:22:00 2009
> New Revision: 192686
> URL: http://svn.freebsd.org/changeset/base/192686
>
> Log:
> Make sure we feed 32bit align memory to nfsm_dissect otherwise we
> will fault
> on platforms with strict alignment requirements. In particular,
> this fixes the
> problems with the new RPC transport on the arm platform.
>
> Note: this adds yet another copy of nfs_realign(). I will attempt
> to refactor
> after NFS_LEGACYRPC is removed.
>
> Submitted by: sam
>
> Modified:
> head/sys/nfsclient/nfs_krpc.c
>
> Modified: head/sys/nfsclient/nfs_krpc.c
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- head/sys/nfsclient/nfs_krpc.c Sun May 24 12:39:38 2009 (r192685)
> +++ head/sys/nfsclient/nfs_krpc.c Sun May 24 13:22:00 2009 (r192686)
> @@ -407,6 +407,65 @@ nfs_feedback(int type, int proc, void *a
> }
>
> /*
> + * 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
> @@ -525,12 +584,25 @@ tryagain:
> } else {
> error = EACCES;
> }
> - md = mrep;
> if (error)
> goto nfsmout;
>
> KASSERT(mrep != NULL, ("mrep shouldn't be NULL if no error\n"));
>
> + /*
> + * Search for any mbufs that are not a multiple of 4 bytes long
> + * or with m_data not longword aligned.
> + * These could cause pointer alignment problems, so copy them to
> + * well aligned mbufs.
> + */
> + error = nfs_realign(&mrep, 2 * NFSX_UNSIGNED);
> + if (error == ENOMEM) {
> + m_freem(mrep);
> + AUTH_DESTROY(auth);
> + return (error);
> + }
> +
> + md = mrep;
> dpos = mtod(mrep, caddr_t);
> tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
> if (*tl != 0) {
More information about the svn-src-all
mailing list