Commit 5d1931fc authored by Steven Whitehouse's avatar Steven Whitehouse Committed by David S. Miller

[DECNET]: Update to support timeouts.

parent 69dda393
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
* when required. * when required.
* Patrick Caulfield: /proc/net/decnet now has object name/number * Patrick Caulfield: /proc/net/decnet now has object name/number
* Steve Whitehouse: Fixed local port allocation, hashed sk list * Steve Whitehouse: Fixed local port allocation, hashed sk list
* Matthew Wilcox: Fixes for dn_ioctl()
* Steve Whitehouse: New connect/accept logic to allow timeouts and
* prepare for sendpage etc.
*/ */
...@@ -482,7 +485,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp) ...@@ -482,7 +485,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp)
if (sock) { if (sock) {
sock->ops = &dn_proto_ops; sock->ops = &dn_proto_ops;
} }
sock_init_data(sock,sk); sock_init_data(sock, sk);
sk->backlog_rcv = dn_nsp_backlog_rcv; sk->backlog_rcv = dn_nsp_backlog_rcv;
sk->destruct = dn_destruct; sk->destruct = dn_destruct;
...@@ -871,95 +874,177 @@ static int dn_auto_bind(struct socket *sock) ...@@ -871,95 +874,177 @@ static int dn_auto_bind(struct socket *sock)
return rv; return rv;
} }
static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation)
{
struct dn_scp *scp = DN_SK(sk);
DECLARE_WAITQUEUE(wait, current);
int err;
static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) if (scp->state != DN_CR)
return -EINVAL;
scp->state = DN_CC;
dn_send_conn_conf(sk, allocation);
add_wait_queue(sk->sleep, &wait);
for(;;) {
set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
lock_sock(sk);
err = 0;
if (scp->state == DN_RUN)
break;
err = sock_error(sk);
if (err)
break;
err = sock_intr_errno(*timeo);
if (signal_pending(current))
break;
err = -EAGAIN;
if (!*timeo)
break;
}
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
return err;
}
static int dn_wait_run(struct sock *sk, long *timeo)
{ {
struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk); struct dn_scp *scp = DN_SK(sk);
int err = -EISCONN; DECLARE_WAITQUEUE(wait, current);
int err = 0;
lock_sock(sk); if (scp->state == DN_RUN)
goto out;
if (sock->state == SS_CONNECTED) if (!*timeo)
return -EALREADY;
add_wait_queue(sk->sleep, &wait);
for(;;) {
set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CI || scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
lock_sock(sk);
err = 0;
if (scp->state == DN_RUN)
break;
err = sock_error(sk);
if (err)
break;
err = sock_intr_errno(*timeo);
if (signal_pending(current))
break;
err = -ETIMEDOUT;
if (!*timeo)
break;
}
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
out:
if (err == 0) {
sk->socket->state = SS_CONNECTED;
}
return err;
}
static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
{
struct socket *sock = sk->socket;
struct dn_scp *scp = DN_SK(sk);
int err = -EISCONN;
if (sock->state == SS_CONNECTED)
goto out; goto out;
if (sock->state == SS_CONNECTING) { if (sock->state == SS_CONNECTING) {
err = 0; err = 0;
if (sk->state == TCP_ESTABLISHED) if (scp->state == DN_RUN) {
sock->state = SS_CONNECTED;
goto out; goto out;
}
err = -ECONNREFUSED; err = -ECONNREFUSED;
if (sk->state == TCP_CLOSE) if (scp->state != DN_CI && scp->state != DN_CC) {
sock->state = SS_UNCONNECTED;
goto out; goto out;
}
return dn_wait_run(sk, timeo);
} }
err = -EINVAL; err = -EINVAL;
if (DN_SK(sk)->state != DN_O) if (scp->state != DN_O)
goto out; goto out;
if (addr_len != sizeof(struct sockaddr_dn)) if (addr == NULL || addrlen != sizeof(struct sockaddr_dn))
goto out; goto out;
if (addr->sdn_family != AF_DECnet) if (addr->sdn_family != AF_DECnet)
goto out; goto out;
if (addr->sdn_flags & SDF_WILD) if (addr->sdn_flags & SDF_WILD)
goto out; goto out;
err = -EADDRNOTAVAIL; if (sk->zapped) {
if (sk->zapped && (err = dn_auto_bind(sock))) err = dn_auto_bind(sk->socket);
goto out; if (err)
goto out;
}
memcpy(&scp->peer, addr, addr_len); memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
err = -EHOSTUNREACH; err = -EHOSTUNREACH;
if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) < 0) if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer),
dn_saddr2dn(&scp->addr), flags & MSG_TRYHARD) < 0)
goto out; goto out;
sk->state = TCP_SYN_SENT;
sock->state = SS_CONNECTING; sock->state = SS_CONNECTING;
DN_SK(sk)->state = DN_CI; scp->state = DN_CI;
dn_nsp_send_conninit(sk, NSP_CI); dn_nsp_send_conninit(sk, NSP_CI);
err = -EINPROGRESS; err = -EINPROGRESS;
if ((sk->state == TCP_SYN_SENT) && (flags & O_NONBLOCK)) if (*timeo) {
goto out; err = dn_wait_run(sk, timeo);
}
while(sk->state == TCP_SYN_SENT) { out:
return err;
err = -ERESTARTSYS; }
if (signal_pending(current))
goto out;
if ((err = sock_error(sk)) != 0) { static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addrlen, int flags)
sock->state = SS_UNCONNECTED; {
goto out; struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
} struct sock *sk = sock->sk;
int err;
long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
SOCK_SLEEP_PRE(sk); lock_sock(sk);
err = __dn_connect(sk, addr, addrlen, &timeo, 0);
release_sock(sk);
if (sk->state == TCP_SYN_SENT) return err;
schedule(); }
SOCK_SLEEP_POST(sk); static inline int dn_check_state(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
} {
struct dn_scp *scp = DN_SK(sk);
if (sk->state != TCP_ESTABLISHED) { switch(scp->state) {
sock->state = SS_UNCONNECTED; case DN_RUN:
err = sock_error(sk); return 0;
goto out; case DN_CR:
return dn_confirm_accept(sk, timeo, sk->allocation);
case DN_CI:
case DN_CC:
return dn_wait_run(sk, timeo);
case DN_O:
return __dn_connect(sk, addr, addrlen, timeo, flags);
} }
err = 0; return -EINVAL;
sock->state = SS_CONNECTED;
out:
release_sock(sk);
return err;
} }
static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc) static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
{ {
unsigned char *ptr = skb->data; unsigned char *ptr = skb->data;
...@@ -990,42 +1075,39 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt) ...@@ -990,42 +1075,39 @@ static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
} }
static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
/*
* This is here for use in the sockopt() call as well as
* in accept(). Must be called with a locked socket.
*/
static int dn_wait_accept(struct socket *sock, int flags)
{ {
struct sock *sk = sock->sk; DECLARE_WAITQUEUE(wait, current);
struct sk_buff *skb = NULL;
while(sk->state == TCP_LISTEN) { int err = 0;
if (flags & O_NONBLOCK) {
return -EAGAIN;
}
SOCK_SLEEP_PRE(sk)
if (sk->state == TCP_LISTEN)
schedule();
SOCK_SLEEP_POST(sk)
if (signal_pending(current))
return -ERESTARTSYS; /* But of course you don't! */
}
if ((DN_SK(sk)->state != DN_RUN) && (DN_SK(sk)->state != DN_DRC)) {
sock->state = SS_UNCONNECTED;
return sock_error(sk);
}
sock->state = SS_CONNECTED;
return 0; add_wait_queue_exclusive(sk->sleep, &wait);
for(;;) {
set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
skb = skb_dequeue(&sk->receive_queue);
if (skb == NULL) {
*timeo = schedule_timeout(*timeo);
skb = skb_dequeue(&sk->receive_queue);
}
lock_sock(sk);
if (skb != NULL)
break;
err = -EINVAL;
if (sk->state != TCP_LISTEN)
break;
err = sock_intr_errno(*timeo);
if (signal_pending(current))
break;
err = -EAGAIN;
if (!*timeo)
break;
}
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
return skb == NULL ? ERR_PTR(err) : skb;
} }
static int dn_accept(struct socket *sock, struct socket *newsock, int flags) static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
{ {
struct sock *sk = sock->sk, *newsk; struct sock *sk = sock->sk, *newsk;
...@@ -1034,52 +1116,32 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1034,52 +1116,32 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
unsigned char menuver; unsigned char menuver;
int err = 0; int err = 0;
unsigned char type; unsigned char type;
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
lock_sock(sk); lock_sock(sk);
if (sk->state != TCP_LISTEN) { if (sk->state != TCP_LISTEN || DN_SK(sk)->state != DN_O) {
release_sock(sk); release_sock(sk);
return -EINVAL; return -EINVAL;
} }
if (DN_SK(sk)->state != DN_O) { skb = skb_dequeue(&sk->receive_queue);
release_sock(sk); if (skb == NULL) {
return -EINVAL; skb = dn_wait_for_connect(sk, &timeo);
if (IS_ERR(skb)) {
release_sock(sk);
return PTR_ERR(sk);
}
} }
do
{
if ((skb = skb_dequeue(&sk->receive_queue)) == NULL)
{
if (flags & O_NONBLOCK)
{
release_sock(sk);
return -EAGAIN;
}
SOCK_SLEEP_PRE(sk);
if (!skb_peek(&sk->receive_queue))
schedule();
SOCK_SLEEP_POST(sk);
if (signal_pending(current))
{
release_sock(sk);
return -ERESTARTSYS;
}
}
} while (skb == NULL);
cb = DN_SKB_CB(skb); cb = DN_SKB_CB(skb);
sk->ack_backlog--;
if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) { newsk = dn_alloc_sock(newsock, sk->allocation);
if (newsk == NULL) {
release_sock(sk); release_sock(sk);
kfree_skb(skb); kfree_skb(skb);
return -ENOBUFS; return -ENOBUFS;
} }
sk->ack_backlog--;
release_sock(sk); release_sock(sk);
dst_release(xchg(&newsk->dst_cache, skb->dst)); dst_release(xchg(&newsk->dst_cache, skb->dst));
...@@ -1099,8 +1161,6 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1099,8 +1161,6 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
DN_SK(newsk)->max_window = decnet_no_fc_max_cwnd; DN_SK(newsk)->max_window = decnet_no_fc_max_cwnd;
newsk->state = TCP_LISTEN; newsk->state = TCP_LISTEN;
newsk->zapped = 0;
memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn)); memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn));
/* /*
...@@ -1137,23 +1197,18 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1137,23 +1197,18 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
sizeof(struct optdata_dn)); sizeof(struct optdata_dn));
lock_sock(newsk); lock_sock(newsk);
/* err = dn_hash_sock(newsk);
* FIXME: This can fail if we've run out of local ports.... if (err == 0) {
*/ newsk->zapped = 0;
dn_hash_sock(newsk); dn_send_conn_ack(newsk);
dn_send_conn_ack(newsk);
/* /*
* Here we use sk->allocation since although the conn conf is * Here we use sk->allocation since although the conn conf is
* for the newsk, the context is the old socket. * for the newsk, the context is the old socket.
*/ */
if (DN_SK(newsk)->accept_mode == ACC_IMMED) { if (DN_SK(newsk)->accept_mode == ACC_IMMED)
DN_SK(newsk)->state = DN_CC; err = dn_confirm_accept(newsk, &timeo, sk->allocation);
dn_send_conn_conf(newsk, sk->allocation);
err = dn_wait_accept(newsock, flags);
} }
release_sock(newsk); release_sock(newsk);
return err; return err;
} }
...@@ -1227,30 +1282,6 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1227,30 +1282,6 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return dn_fib_ioctl(sock, cmd, arg); return dn_fib_ioctl(sock, cmd, arg);
#endif /* CONFIG_DECNET_ROUTER */ #endif /* CONFIG_DECNET_ROUTER */
#if 0
case OSIOCSNETADDR:
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
break;
}
dn_dev_devices_off();
decnet_address = (unsigned short)arg;
dn_dev_devices_on();
err = 0;
break;
case OSIOCGNETADDR:
err = put_user(decnet_address, (unsigned short *)arg);
break;
#endif
case SIOCGIFCONF:
case SIOCGIFFLAGS:
case SIOCGIFBRDADDR:
return dev_ioctl(cmd,(void *)arg);
case TIOCOUTQ: case TIOCOUTQ:
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0) if (amount < 0)
...@@ -1274,6 +1305,10 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1274,6 +1305,10 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
release_sock(sk); release_sock(sk);
err = put_user(amount, (int *)arg); err = put_user(amount, (int *)arg);
break; break;
default:
err = dev_ioctl(cmd, (void *)arg);
break;
} }
return err; return err;
...@@ -1327,7 +1362,6 @@ static int dn_shutdown(struct socket *sock, int how) ...@@ -1327,7 +1362,6 @@ static int dn_shutdown(struct socket *sock, int how)
if (how != SHUTDOWN_MASK) if (how != SHUTDOWN_MASK)
goto out; goto out;
sk->shutdown = how; sk->shutdown = how;
dn_destroy_sock(sk); dn_destroy_sock(sk);
err = 0; err = 0;
...@@ -1354,6 +1388,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt ...@@ -1354,6 +1388,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk); struct dn_scp *scp = DN_SK(sk);
long timeo;
union { union {
struct optdata_dn opt; struct optdata_dn opt;
struct accessdata_dn acc; struct accessdata_dn acc;
...@@ -1439,10 +1474,8 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt ...@@ -1439,10 +1474,8 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
if (scp->state != DN_CR) if (scp->state != DN_CR)
return -EINVAL; return -EINVAL;
timeo = sock_rcvtimeo(sk, 0);
scp->state = DN_CC; err = dn_confirm_accept(sk, &timeo, sk->allocation);
dn_send_conn_conf(sk, sk->allocation);
err = dn_wait_accept(sock, sock->file->f_flags);
return err; return err;
case DSO_CONREJECT: case DSO_CONREJECT:
...@@ -1652,55 +1685,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt ...@@ -1652,55 +1685,6 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt
} }
/*
* Used by send/recvmsg to wait until the socket is connected
* before passing data.
*/
static int dn_wait_run(struct sock *sk, int flags)
{
struct dn_scp *scp = DN_SK(sk);
int err = 0;
switch(scp->state) {
case DN_RUN:
return 0;
case DN_CR:
scp->state = DN_CC;
dn_send_conn_conf(sk, sk->allocation);
return dn_wait_accept(sk->socket, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0);
case DN_CI:
case DN_CC:
break;
default:
return -ENOTCONN;
}
if (flags & MSG_DONTWAIT)
return -EWOULDBLOCK;
do {
if ((err = sock_error(sk)) != 0)
break;
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}
SOCK_SLEEP_PRE(sk)
if (scp->state != DN_RUN)
schedule();
SOCK_SLEEP_POST(sk)
} while(scp->state != DN_RUN);
return 0;
}
static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target) static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target)
{ {
struct sk_buff *skb = q->next; struct sk_buff *skb = q->next;
...@@ -1745,6 +1729,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1745,6 +1729,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb, *nskb; struct sk_buff *skb, *nskb;
struct dn_skb_cb *cb = NULL; struct dn_skb_cb *cb = NULL;
unsigned char eor = 0; unsigned char eor = 0;
long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
lock_sock(sk); lock_sock(sk);
...@@ -1753,16 +1738,18 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1753,16 +1738,18 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
goto out; goto out;
} }
if ((rv = dn_wait_run(sk, flags)) != 0) rv = dn_check_state(sk, NULL, 0, &timeo, flags);
if (rv)
goto out; goto out;
if (sk->shutdown & RCV_SHUTDOWN) { if (sk->shutdown & RCV_SHUTDOWN) {
send_sig(SIGPIPE, current, 0); if (!(flags & MSG_NOSIGNAL))
send_sig(SIGPIPE, current, 0);
rv = -EPIPE; rv = -EPIPE;
goto out; goto out;
} }
if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT)) { if (flags & ~(MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT|MSG_NOSIGNAL)) {
rv = -EOPNOTSUPP; rv = -EOPNOTSUPP;
goto out; goto out;
} }
...@@ -1920,35 +1907,23 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1920,35 +1907,23 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
unsigned short ack; unsigned short ack;
int len; int len;
unsigned char fctype; unsigned char fctype;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR)) if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (addr_len && (addr_len != sizeof(struct sockaddr_dn))) if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
return -EINVAL; return -EINVAL;
if (sk->zapped && dn_auto_bind(sock)) {
err = -EADDRNOTAVAIL;
goto out;
}
if (scp->state == DN_O) {
if (!addr_len || !addr) {
err = -ENOTCONN;
goto out;
}
if ((err = dn_connect(sock, (struct sockaddr *)addr, addr_len, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0)) < 0)
goto out;
}
lock_sock(sk); lock_sock(sk);
if ((err = dn_wait_run(sk, flags)) < 0) err = dn_check_state(sk, addr, addr_len, &timeo, flags);
if (err)
goto out; goto out;
if (sk->shutdown & SEND_SHUTDOWN) { if (sk->shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0); if (!(flags & MSG_NOSIGNAL))
send_sig(SIGPIPE, current, 0);
err = -EPIPE; err = -EPIPE;
goto out; goto out;
} }
...@@ -2117,7 +2092,7 @@ static int dn_device_event(struct notifier_block *this, unsigned long event, ...@@ -2117,7 +2092,7 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
} }
static struct notifier_block dn_dev_notifier = { static struct notifier_block dn_dev_notifier = {
.notifier_call =dn_device_event, .notifier_call = dn_device_event,
}; };
extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *); extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
......
...@@ -181,30 +181,74 @@ static struct dn_dev_sysctl_table { ...@@ -181,30 +181,74 @@ static struct dn_dev_sysctl_table {
} dn_dev_sysctl = { } dn_dev_sysctl = {
NULL, NULL,
{ {
{NET_DECNET_CONF_DEV_FORWARDING, "forwarding", {
(void *)DN_DEV_PARMS_OFFSET(forwarding), .ctl_name = NET_DECNET_CONF_DEV_FORWARDING,
sizeof(int), 0644, NULL, .procname = "forwarding",
dn_forwarding_proc, dn_forwarding_sysctl, .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
NULL, NULL, NULL}, .maxlen = sizeof(int),
{NET_DECNET_CONF_DEV_PRIORITY, "priority", .mode = 0644,
(void *)DN_DEV_PARMS_OFFSET(priority), .proc_handler = dn_forwarding_proc,
sizeof(int), 0644, NULL, .strategy = dn_forwarding_sysctl,
proc_dointvec_minmax, sysctl_intvec, },
NULL, &min_priority, &max_priority}, {
{NET_DECNET_CONF_DEV_T2, "t2", (void *)DN_DEV_PARMS_OFFSET(t2), .ctl_name = NET_DECNET_CONF_DEV_PRIORITY,
sizeof(int), 0644, NULL, .procname = "priority",
proc_dointvec_minmax, sysctl_intvec, .data = (void *)DN_DEV_PARMS_OFFSET(priority),
NULL, &min_t2, &max_t2}, .maxlen = sizeof(int),
{NET_DECNET_CONF_DEV_T3, "t3", (void *)DN_DEV_PARMS_OFFSET(t3), .mode = 0644,
sizeof(int), 0644, NULL, .proc_handler = proc_dointvec_minmax,
proc_dointvec_minmax, sysctl_intvec, .strategy = sysctl_intvec,
NULL, &min_t3, &max_t3}, .extra1 = &min_priority,
.extra2 = &max_priority
},
{
.ctl_name = NET_DECNET_CONF_DEV_T2,
.procname = "t2",
.data = (void *)DN_DEV_PARMS_OFFSET(t2),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.strategy = sysctl_intvec,
.extra1 = &min_t2,
.extra2 = &max_t2
},
{
.ctl_name = NET_DECNET_CONF_DEV_T3,
.procname = "t3",
.data = (void *)DN_DEV_PARMS_OFFSET(t3),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.strategy = sysctl_intvec,
.extra1 = &min_t3,
.extra2 = &max_t3
},
{0} {0}
}, },
{{0, "", NULL, 0, 0555, dn_dev_sysctl.dn_dev_vars}, {0}}, {{
{{NET_DECNET_CONF, "conf", NULL, 0, 0555, dn_dev_sysctl.dn_dev_dev}, {0}}, .ctl_name = 0,
{{NET_DECNET, "decnet", NULL, 0, 0555, dn_dev_sysctl.dn_dev_conf_dir}, {0}}, .procname = "",
{{CTL_NET, "net", NULL, 0, 0555, dn_dev_sysctl.dn_dev_proto_dir}, {0}} .mode = 0555,
.child = dn_dev_sysctl.dn_dev_vars
}, {0}},
{{
.ctl_name = NET_DECNET_CONF,
.procname = "conf",
.mode = 0555,
.child = dn_dev_sysctl.dn_dev_dev
}, {0}},
{{
.ctl_name = NET_DECNET,
.procname = "decnet",
.mode = 0555,
.child = dn_dev_sysctl.dn_dev_conf_dir
}, {0}},
{{
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = dn_dev_sysctl.dn_dev_proto_dir
}, {0}}
}; };
static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms) static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
...@@ -1211,8 +1255,10 @@ void dn_dev_devices_off(void) ...@@ -1211,8 +1255,10 @@ void dn_dev_devices_off(void)
{ {
struct net_device *dev; struct net_device *dev;
rtnl_lock();
for(dev = dev_base; dev; dev = dev->next) for(dev = dev_base; dev; dev = dev->next)
dn_dev_down(dev); dn_dev_down(dev);
rtnl_unlock();
} }
...@@ -1220,10 +1266,12 @@ void dn_dev_devices_on(void) ...@@ -1220,10 +1266,12 @@ void dn_dev_devices_on(void)
{ {
struct net_device *dev; struct net_device *dev;
rtnl_lock();
for(dev = dev_base; dev; dev = dev->next) { for(dev = dev_base; dev; dev = dev->next) {
if (dev->flags & IFF_UP) if (dev->flags & IFF_UP)
dn_dev_up(dev); dn_dev_up(dev);
} }
rtnl_unlock();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment