Date: Fri, 26 Aug 2005 00:35:18 -0400 From: Craig Rodrigues <rodrigc@crodrigues.org> To: freebsd-current@freebsd.org Subject: [PATCH] Eliminate witness warning in linux_ioctl.c Message-ID: <20050826043518.GA2090@crodrigues.org>
next in thread | raw e-mail | index | archive | help
--CE+1k2dSO48ffgeK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
If I run the following test:
(1) Make sure that the linux_base-8 port is installed.
(2) kldload linux.ko
(3) Download and run the ifconfig program from Fedora:
http://people.freebsd.org/~rodrigc/linux-test/ifconfig.bz2
I get this following WITNESS warning (not a LOR!!):
Calling uiomove() with the following non-sleepable locks held:
exclusive sleep mutex ifnet r = 0 (0xc096dd60) locked @ /usr/src/sys/modules/lin
ux/../../compat/linux/linux_ioctl.c:2170
KDB: stack backtrace:
kdb_backtrace(1,c17fe900,400,d165bc50,d165bbfc) at kdb_backtrace+0x29
witness_warn(5,0,c0856813,c064b97d,0) at witness_warn+0x18e
uiomove(d165bc70,20,d165bc50,1,bfbfddb0) at uiomove+0x56
linux_ioctl_socket(c1b94000,d165bd04,c181e120,0,c1b94000) at linux_ioctl_socket+
0x7dc
linux_ioctl(c1b94000,d165bd04,3,3,246) at linux_ioctl+0x99
syscall(3b,3b,3b,b,bfbfe208) at syscall+0x22f
Xint0x80_syscall() at Xint0x80_syscall+0x1f
--- syscall (54, Linux ELF, linux_ioctl), eip = 0x283252a4, esp = 0xbfbfdd90, eb
p = 0xbfbfe1e0 ---
In order to eliminate this WITNESS warning,
I modified linux_ifconf() to not use uiomove(). I
based my changes on the logic used in ifconf() in net/if.c.
Can someone provide feedback on this patch?
Thanks.
--
Craig Rodrigues
rodrigc@crodrigues.org
--CE+1k2dSO48ffgeK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="linux_ioctl.c.diff.txt"
Index: linux_ioctl.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_ioctl.c,v
retrieving revision 1.128
diff -u -u -r1.128 linux_ioctl.c
--- linux_ioctl.c 9 Aug 2005 10:19:41 -0000 1.128
+++ linux_ioctl.c 26 Aug 2005 04:33:38 -0000
@@ -46,6 +46,7 @@
#include <sys/linker_set.h>
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/soundcard.h>
@@ -2130,14 +2131,15 @@
struct l_ifreq ifr;
struct ifnet *ifp;
struct ifaddr *ifa;
- struct iovec iov;
- struct uio uio;
- int error, ethno;
+ struct sbuf *sb;
+ int error, ethno, full = 0, valid_len, max_len;
error = copyin(uifc, &ifc, sizeof(ifc));
if (error != 0)
return (error);
+ max_len = MAXPHYS - 1;
+
/* handle the 'request buffer size' case */
if (ifc.ifc_buf == PTROUT(NULL)) {
ifc.ifc_len = 0;
@@ -2152,25 +2154,24 @@
return (error);
}
- /* much easier to use uiomove than keep track ourselves */
- iov.iov_base = PTRIN(ifc.ifc_buf);
- iov.iov_len = ifc.ifc_len;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = 0;
- uio.uio_resid = ifc.ifc_len;
- uio.uio_segflg = UIO_USERSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = td;
+ if (ifc.ifc_len <= 0)
+ return (EINVAL);
+again:
/* Keep track of eth interfaces */
ethno = 0;
+ if (ifc.ifc_len <= max_len) {
+ max_len = ifc.ifc_len;
+ full = 1;
+ }
+ sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN);
+ max_len = 0;
+ valid_len = 0;
/* Return all AF_INET addresses of all interfaces */
IFNET_RLOCK(); /* could sleep XXX */
TAILQ_FOREACH(ifp, &ifnet, if_link) {
- if (uio.uio_resid <= 0)
- break;
+ int addrs = 0;
bzero(&ifr, sizeof(ifr));
if (IFP_IS_ETH(ifp))
@@ -2183,26 +2184,39 @@
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
struct sockaddr *sa = ifa->ifa_addr;
- if (uio.uio_resid <= 0)
- break;
-
if (sa->sa_family == AF_INET) {
ifr.ifr_addr.sa_family = LINUX_AF_INET;
memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
sizeof(ifr.ifr_addr.sa_data));
-
- error = uiomove(&ifr, sizeof(ifr), &uio);
- if (error != 0) {
- IFNET_RUNLOCK();
- return (error);
- }
+ sbuf_bcat(sb, &ifr, sizeof(ifr));
+ max_len += sizeof(ifr);
+ addrs++;
}
+
+ if (!sbuf_overflowed(sb))
+ valid_len = sbuf_len(sb);
+ }
+ if (addrs == 0) {
+ bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
+ sbuf_bcat(sb, &ifr, sizeof(ifr));
+ max_len += sizeof(ifr);
+
+ if (!sbuf_overflowed(sb))
+ valid_len = sbuf_len(sb);
}
}
IFNET_RUNLOCK();
- ifc.ifc_len -= uio.uio_resid;
+ if (valid_len != max_len && !full) {
+ sbuf_delete(sb);
+ goto again;
+ }
+
+ ifc.ifc_len = valid_len;
+ sbuf_finish(sb);
+ memcpy(ifc.ifc_buf, sbuf_data(sb), ifc.ifc_len);
error = copyout(&ifc, uifc, sizeof(ifc));
+ sbuf_delete(sb);
return (error);
}
--CE+1k2dSO48ffgeK--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050826043518.GA2090>
