Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern Avoid using m_clget() on a mbuf already in use, esp...
details: https://anonhg.NetBSD.org/src/rev/7cb85c1980d5
branches: trunk
changeset: 556902:7cb85c1980d5
user: martin <martin%NetBSD.org@localhost>
date: Mon Dec 29 22:08:02 2003 +0000
description:
Avoid using m_clget() on a mbuf already in use, especially when we
need the data in the mbuf later and m_clget() changes some fields
overlaid to regular mbuf data. Instead, rearange code a bit, create
data into a new allocated buffer and and use MEXTADD to attach it to
the mbuf, if the mbuf internal space is not sufficient.
This fixes a crash on sparc64 (and probably all other archs where
sizeof(int) != sizeof(struct file *)) when running
regress/sys/kern/unfdpass.
Idea for solution from Matt Thomas, with additional input from YAMAMOTO
Takashi.
diffstat:
sys/kern/uipc_usrreq.c | 54 ++++++++++++++++++++++++++++---------------------
1 files changed, 31 insertions(+), 23 deletions(-)
diffs (101 lines):
diff -r bc7adbd1b55d -r 7cb85c1980d5 sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c Mon Dec 29 21:21:25 2003 +0000
+++ b/sys/kern/uipc_usrreq.c Mon Dec 29 22:08:02 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_usrreq.c,v 1.72 2003/11/29 10:02:42 matt Exp $ */
+/* $NetBSD: uipc_usrreq.c,v 1.73 2003/12/29 22:08:02 martin Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -103,7 +103,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.72 2003/11/29 10:02:42 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.73 2003/12/29 22:08:02 martin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -974,8 +974,8 @@
struct proc *p;
{
struct filedesc *fdescp = p->p_fd;
- struct cmsghdr *cm = mtod(control, struct cmsghdr *);
- struct file **rp;
+ struct cmsghdr *newcm, *cm = mtod(control, struct cmsghdr *);
+ struct file **rp, **files;
struct file *fp;
int i, fd, *fdp;
int nfds;
@@ -997,37 +997,31 @@
}
/* Make sure we have room for the struct file pointers */
- morespace:
neededspace = CMSG_SPACE(nfds * sizeof(struct file *)) -
control->m_len;
if (neededspace > M_TRAILINGSPACE(control)) {
- /* if we already have a cluster, the message is just too big */
- if (control->m_flags & M_EXT)
+ /* allocate new space and copy header into it */
+ newcm = malloc(
+ CMSG_SPACE(nfds * sizeof(struct file *)),
+ M_MBUF, M_WAITOK);
+ if (newcm == NULL)
return (E2BIG);
-
- /* allocate a cluster and try again */
- m_clget(control, M_WAIT);
- if ((control->m_flags & M_EXT) == 0)
- return (ENOBUFS); /* allocation failed */
-
- /* copy the data to the cluster */
- memcpy(mtod(control, char *), cm, cm->cmsg_len);
- cm = mtod(control, struct cmsghdr *);
- goto morespace;
+ memcpy(newcm, cm, sizeof(struct cmsghdr));
+ files = (struct file **)CMSG_DATA(newcm);
+ } else {
+ /* we can convert in-place */
+ newcm = NULL;
+ files = (struct file **)CMSG_DATA(cm);
}
- /* adjust message & mbuf to note amount of space actually used. */
- cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct file *));
- control->m_len = CMSG_SPACE(nfds * sizeof(struct file *));
-
/*
* Transform the file descriptors into struct file pointers, in
* reverse order so that if pointers are bigger than ints, the
* int won't get until we're done.
*/
- fdp = ((int *)CMSG_DATA(cm)) + nfds - 1;
- rp = ((struct file **)CMSG_DATA(cm)) + nfds - 1;
+ fdp = (int *)CMSG_DATA(cm) + nfds - 1;
+ rp = files + nfds - 1;
for (i = 0; i < nfds; i++) {
fp = fdescp->fd_ofiles[*fdp--];
simple_lock(&fp->f_slock);
@@ -1041,6 +1035,20 @@
simple_unlock(&fp->f_slock);
unp_rights++;
}
+
+ if (newcm) {
+ if (control->m_flags & M_EXT)
+ MEXTREMOVE(control);
+ MEXTADD(control, newcm,
+ CMSG_SPACE(nfds * sizeof(struct file *)),
+ M_MBUF, NULL, NULL);
+ cm = newcm;
+ }
+
+ /* adjust message & mbuf to note amount of space actually used. */
+ cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct file *));
+ control->m_len = CMSG_SPACE(nfds * sizeof(struct file *));
+
return (0);
}
Home |
Main Index |
Thread Index |
Old Index