summaryrefslogtreecommitdiff
path: root/sys/compat/linux/common/linux_socket.c
diff options
context:
space:
mode:
authorozaki-r <ozaki-r@NetBSD.org>2016-08-01 03:15:30 +0000
committerozaki-r <ozaki-r@NetBSD.org>2016-08-01 03:15:30 +0000
commit3ad55fb68c1edf4027b2cd2414db23acfe702adc (patch)
tree75f635c51460af8d6dc6eac38313ec79b10a716e /sys/compat/linux/common/linux_socket.c
parent83eb0e1565b3577874158686b32a9bc8bca7b547 (diff)
Apply pserialize and psref to struct ifaddr and its variants
This change makes struct ifaddr and its variants (in_ifaddr and in6_ifaddr) MP-safe by using pserialize and psref. At this moment, pserialize_perform and psref_target_destroy are disabled because (1) we don't need them because of softnet_lock (2) they cause a deadlock because of softnet_lock. So we'll enable them when we remove softnet_lock in the future.
Diffstat (limited to 'sys/compat/linux/common/linux_socket.c')
-rw-r--r--sys/compat/linux/common/linux_socket.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/sys/compat/linux/common/linux_socket.c b/sys/compat/linux/common/linux_socket.c
index dc410345f97..69aced65db1 100644
--- a/sys/compat/linux/common/linux_socket.c
+++ b/sys/compat/linux/common/linux_socket.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.c,v 1.131 2016/07/07 09:32:02 ozaki-r Exp $ */
+/* $NetBSD: linux_socket.c,v 1.132 2016/08/01 03:15:30 ozaki-r Exp $ */
/*-
* Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.131 2016/07/07 09:32:02 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.132 2016/08/01 03:15:30 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -1117,7 +1117,6 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
struct linux_ifreq ifr, *ifrp = NULL;
struct linux_ifconf ifc;
struct ifnet *ifp;
- struct ifaddr *ifa;
struct sockaddr *sa;
struct osockaddr *osa;
int space = 0, error;
@@ -1140,8 +1139,8 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
bound = curlwp_bind();
s = pserialize_read_enter();
IFNET_READER_FOREACH(ifp) {
+ struct ifaddr *ifa;
psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class);
- pserialize_read_exit(s);
(void)strncpy(ifr.ifr_name, ifp->if_xname,
sizeof(ifr.ifr_name));
@@ -1151,23 +1150,32 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
}
IFADDR_READER_FOREACH(ifa, ifp) {
+ struct psref psref_ifa;
+ ifa_acquire(ifa, &psref_ifa);
+ pserialize_read_exit(s);
+
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET ||
sa->sa_len > sizeof(*osa))
- continue;
+ goto next;
memcpy(&ifr.ifr_addr, sa, sa->sa_len);
osa = (struct osockaddr *)&ifr.ifr_addr;
osa->sa_family = sa->sa_family;
if (space >= sz) {
error = copyout(&ifr, ifrp, sz);
- if (error != 0)
+ if (error != 0) {
+ s = pserialize_read_enter();
+ ifa_release(ifa, &psref_ifa);
goto release_exit;
+ }
ifrp++;
}
space -= sz;
+ next:
+ s = pserialize_read_enter();
+ ifa_release(ifa, &psref_ifa);
}
- s = pserialize_read_enter();
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
}
pserialize_read_exit(s);
@@ -1181,6 +1189,7 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
return copyout(&ifc, data, sizeof(ifc));
release_exit:
+ pserialize_read_exit(s);
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
curlwp_bindx(bound);
return error;