diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-03-28 03:01:55 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-28 20:02:43 -0500 |
| commit | 1d1818316f0b61e0997a159680e1e631a23a407e (patch) | |
| tree | fe79294a13661c75f2c5e311dfa62b2ba5ac8f67 | |
| parent | f6c90b71a355a0a4a22e1cfee5748617adc25a53 (diff) | |
[ECONET]: Convert away from SOCKOPS_WRAPPED
Just use a local econet_mutex instead.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/econet/af_econet.c | 140 |
1 files changed, 85 insertions, 55 deletions
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 0c4c83bb2a59..868265619dbb 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/spinlock.h> | 42 | #include <linux/spinlock.h> |
| 43 | #include <linux/rcupdate.h> | 43 | #include <linux/rcupdate.h> |
| 44 | #include <linux/bitops.h> | 44 | #include <linux/bitops.h> |
| 45 | #include <linux/mutex.h> | ||
| 45 | 46 | ||
| 46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| 47 | #include <asm/system.h> | 48 | #include <asm/system.h> |
| @@ -49,6 +50,7 @@ | |||
| 49 | static const struct proto_ops econet_ops; | 50 | static const struct proto_ops econet_ops; |
| 50 | static struct hlist_head econet_sklist; | 51 | static struct hlist_head econet_sklist; |
| 51 | static DEFINE_RWLOCK(econet_lock); | 52 | static DEFINE_RWLOCK(econet_lock); |
| 53 | static DEFINE_MUTEX(econet_mutex); | ||
| 52 | 54 | ||
| 53 | /* Since there are only 256 possible network numbers (or fewer, depends | 55 | /* Since there are only 256 possible network numbers (or fewer, depends |
| 54 | how you count) it makes sense to use a simple lookup table. */ | 56 | how you count) it makes sense to use a simple lookup table. */ |
| @@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 124 | 126 | ||
| 125 | msg->msg_namelen = sizeof(struct sockaddr_ec); | 127 | msg->msg_namelen = sizeof(struct sockaddr_ec); |
| 126 | 128 | ||
| 129 | mutex_lock(&econet_mutex); | ||
| 130 | |||
| 127 | /* | 131 | /* |
| 128 | * Call the generic datagram receiver. This handles all sorts | 132 | * Call the generic datagram receiver. This handles all sorts |
| 129 | * of horrible races and re-entrancy so we can forget about it | 133 | * of horrible races and re-entrancy so we can forget about it |
| @@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 174 | out_free: | 178 | out_free: |
| 175 | skb_free_datagram(sk, skb); | 179 | skb_free_datagram(sk, skb); |
| 176 | out: | 180 | out: |
| 181 | mutex_unlock(&econet_mutex); | ||
| 177 | return err; | 182 | return err; |
| 178 | } | 183 | } |
| 179 | 184 | ||
| @@ -184,8 +189,8 @@ out: | |||
| 184 | static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 189 | static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) |
| 185 | { | 190 | { |
| 186 | struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; | 191 | struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; |
| 187 | struct sock *sk=sock->sk; | 192 | struct sock *sk; |
| 188 | struct econet_sock *eo = ec_sk(sk); | 193 | struct econet_sock *eo; |
| 189 | 194 | ||
| 190 | /* | 195 | /* |
| 191 | * Check legality | 196 | * Check legality |
| @@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len | |||
| 195 | sec->sec_family != AF_ECONET) | 200 | sec->sec_family != AF_ECONET) |
| 196 | return -EINVAL; | 201 | return -EINVAL; |
| 197 | 202 | ||
| 203 | mutex_lock(&econet_mutex); | ||
| 204 | |||
| 205 | sk = sock->sk; | ||
| 206 | eo = ec_sk(sk); | ||
| 207 | |||
| 198 | eo->cb = sec->cb; | 208 | eo->cb = sec->cb; |
| 199 | eo->port = sec->port; | 209 | eo->port = sec->port; |
| 200 | eo->station = sec->addr.station; | 210 | eo->station = sec->addr.station; |
| 201 | eo->net = sec->addr.net; | 211 | eo->net = sec->addr.net; |
| 202 | 212 | ||
| 213 | mutex_unlock(&econet_mutex); | ||
| 214 | |||
| 203 | return 0; | 215 | return 0; |
| 204 | } | 216 | } |
| 205 | 217 | ||
| @@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 284 | * Get and verify the address. | 296 | * Get and verify the address. |
| 285 | */ | 297 | */ |
| 286 | 298 | ||
| 299 | mutex_lock(&econet_mutex); | ||
| 300 | |||
| 287 | if (saddr == NULL) { | 301 | if (saddr == NULL) { |
| 288 | struct econet_sock *eo = ec_sk(sk); | 302 | struct econet_sock *eo = ec_sk(sk); |
| 289 | 303 | ||
| @@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 292 | port = eo->port; | 306 | port = eo->port; |
| 293 | cb = eo->cb; | 307 | cb = eo->cb; |
| 294 | } else { | 308 | } else { |
| 295 | if (msg->msg_namelen < sizeof(struct sockaddr_ec)) | 309 | if (msg->msg_namelen < sizeof(struct sockaddr_ec)) { |
| 310 | mutex_unlock(&econet_mutex); | ||
| 296 | return -EINVAL; | 311 | return -EINVAL; |
| 312 | } | ||
| 297 | addr.station = saddr->addr.station; | 313 | addr.station = saddr->addr.station; |
| 298 | addr.net = saddr->addr.net; | 314 | addr.net = saddr->addr.net; |
| 299 | port = saddr->port; | 315 | port = saddr->port; |
| @@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 304 | dev = net2dev_map[addr.net]; | 320 | dev = net2dev_map[addr.net]; |
| 305 | 321 | ||
| 306 | /* If not directly reachable, use some default */ | 322 | /* If not directly reachable, use some default */ |
| 307 | if (dev == NULL) | 323 | if (dev == NULL) { |
| 308 | { | ||
| 309 | dev = net2dev_map[0]; | 324 | dev = net2dev_map[0]; |
| 310 | /* No interfaces at all? */ | 325 | /* No interfaces at all? */ |
| 311 | if (dev == NULL) | 326 | if (dev == NULL) { |
| 327 | mutex_unlock(&econet_mutex); | ||
| 312 | return -ENETDOWN; | 328 | return -ENETDOWN; |
| 329 | } | ||
| 313 | } | 330 | } |
| 314 | 331 | ||
| 315 | if (len + 15 > dev->mtu) | 332 | if (len + 15 > dev->mtu) { |
| 333 | mutex_unlock(&econet_mutex); | ||
| 316 | return -EMSGSIZE; | 334 | return -EMSGSIZE; |
| 335 | } | ||
| 317 | 336 | ||
| 318 | if (dev->type == ARPHRD_ECONET) | 337 | if (dev->type == ARPHRD_ECONET) { |
| 319 | { | ||
| 320 | /* Real hardware Econet. We're not worthy etc. */ | 338 | /* Real hardware Econet. We're not worthy etc. */ |
| 321 | #ifdef CONFIG_ECONET_NATIVE | 339 | #ifdef CONFIG_ECONET_NATIVE |
| 322 | unsigned short proto = 0; | 340 | unsigned short proto = 0; |
| @@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 374 | 392 | ||
| 375 | dev_queue_xmit(skb); | 393 | dev_queue_xmit(skb); |
| 376 | dev_put(dev); | 394 | dev_put(dev); |
| 395 | mutex_unlock(&econet_mutex); | ||
| 377 | return(len); | 396 | return(len); |
| 378 | 397 | ||
| 379 | out_free: | 398 | out_free: |
| @@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 384 | #else | 403 | #else |
| 385 | err = -EPROTOTYPE; | 404 | err = -EPROTOTYPE; |
| 386 | #endif | 405 | #endif |
| 406 | mutex_unlock(&econet_mutex); | ||
| 407 | |||
| 387 | return err; | 408 | return err; |
| 388 | } | 409 | } |
| 389 | 410 | ||
| 390 | #ifdef CONFIG_ECONET_AUNUDP | 411 | #ifdef CONFIG_ECONET_AUNUDP |
| 391 | /* AUN virtual Econet. */ | 412 | /* AUN virtual Econet. */ |
| 392 | 413 | ||
| 393 | if (udpsock == NULL) | 414 | if (udpsock == NULL) { |
| 415 | mutex_unlock(&econet_mutex); | ||
| 394 | return -ENETDOWN; /* No socket - can't send */ | 416 | return -ENETDOWN; /* No socket - can't send */ |
| 417 | } | ||
| 395 | 418 | ||
| 396 | /* Make up a UDP datagram and hand it off to some higher intellect. */ | 419 | /* Make up a UDP datagram and hand it off to some higher intellect. */ |
| 397 | 420 | ||
| @@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 438 | void __user *base = msg->msg_iov[i].iov_base; | 461 | void __user *base = msg->msg_iov[i].iov_base; |
| 439 | size_t len = msg->msg_iov[i].iov_len; | 462 | size_t len = msg->msg_iov[i].iov_len; |
| 440 | /* Check it now since we switch to KERNEL_DS later. */ | 463 | /* Check it now since we switch to KERNEL_DS later. */ |
| 441 | if (!access_ok(VERIFY_READ, base, len)) | 464 | if (!access_ok(VERIFY_READ, base, len)) { |
| 465 | mutex_unlock(&econet_mutex); | ||
| 442 | return -EFAULT; | 466 | return -EFAULT; |
| 467 | } | ||
| 443 | iov[i+1].iov_base = base; | 468 | iov[i+1].iov_base = base; |
| 444 | iov[i+1].iov_len = len; | 469 | iov[i+1].iov_len = len; |
| 445 | size += len; | 470 | size += len; |
| @@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 447 | 472 | ||
| 448 | /* Get a skbuff (no data, just holds our cb information) */ | 473 | /* Get a skbuff (no data, just holds our cb information) */ |
| 449 | if ((skb = sock_alloc_send_skb(sk, 0, | 474 | if ((skb = sock_alloc_send_skb(sk, 0, |
| 450 | msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) | 475 | msg->msg_flags & MSG_DONTWAIT, |
| 476 | &err)) == NULL) { | ||
| 477 | mutex_unlock(&econet_mutex); | ||
| 451 | return err; | 478 | return err; |
| 479 | } | ||
| 452 | 480 | ||
| 453 | eb = (struct ec_cb *)&skb->cb; | 481 | eb = (struct ec_cb *)&skb->cb; |
| 454 | 482 | ||
| @@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 475 | #else | 503 | #else |
| 476 | err = -EPROTOTYPE; | 504 | err = -EPROTOTYPE; |
| 477 | #endif | 505 | #endif |
| 506 | mutex_unlock(&econet_mutex); | ||
| 507 | |||
| 478 | return err; | 508 | return err; |
| 479 | } | 509 | } |
| 480 | 510 | ||
| @@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 485 | static int econet_getname(struct socket *sock, struct sockaddr *uaddr, | 515 | static int econet_getname(struct socket *sock, struct sockaddr *uaddr, |
| 486 | int *uaddr_len, int peer) | 516 | int *uaddr_len, int peer) |
| 487 | { | 517 | { |
| 488 | struct sock *sk = sock->sk; | 518 | struct sock *sk; |
| 489 | struct econet_sock *eo = ec_sk(sk); | 519 | struct econet_sock *eo; |
| 490 | struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; | 520 | struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; |
| 491 | 521 | ||
| 492 | if (peer) | 522 | if (peer) |
| 493 | return -EOPNOTSUPP; | 523 | return -EOPNOTSUPP; |
| 494 | 524 | ||
| 525 | mutex_lock(&econet_mutex); | ||
| 526 | |||
| 527 | sk = sock->sk; | ||
| 528 | eo = ec_sk(sk); | ||
| 529 | |||
| 495 | sec->sec_family = AF_ECONET; | 530 | sec->sec_family = AF_ECONET; |
| 496 | sec->port = eo->port; | 531 | sec->port = eo->port; |
| 497 | sec->addr.station = eo->station; | 532 | sec->addr.station = eo->station; |
| 498 | sec->addr.net = eo->net; | 533 | sec->addr.net = eo->net; |
| 499 | 534 | ||
| 535 | mutex_unlock(&econet_mutex); | ||
| 536 | |||
| 500 | *uaddr_len = sizeof(*sec); | 537 | *uaddr_len = sizeof(*sec); |
| 501 | return 0; | 538 | return 0; |
| 502 | } | 539 | } |
| @@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data) | |||
| 522 | 559 | ||
| 523 | static int econet_release(struct socket *sock) | 560 | static int econet_release(struct socket *sock) |
| 524 | { | 561 | { |
| 525 | struct sock *sk = sock->sk; | 562 | struct sock *sk; |
| 526 | 563 | ||
| 564 | mutex_lock(&econet_mutex); | ||
| 565 | |||
| 566 | sk = sock->sk; | ||
| 527 | if (!sk) | 567 | if (!sk) |
| 528 | return 0; | 568 | goto out_unlock; |
| 529 | 569 | ||
| 530 | econet_remove_socket(&econet_sklist, sk); | 570 | econet_remove_socket(&econet_sklist, sk); |
| 531 | 571 | ||
| @@ -549,10 +589,14 @@ static int econet_release(struct socket *sock) | |||
| 549 | sk->sk_timer.expires = jiffies + HZ; | 589 | sk->sk_timer.expires = jiffies + HZ; |
| 550 | sk->sk_timer.function = econet_destroy_timer; | 590 | sk->sk_timer.function = econet_destroy_timer; |
| 551 | add_timer(&sk->sk_timer); | 591 | add_timer(&sk->sk_timer); |
| 552 | return 0; | 592 | |
| 593 | goto out_unlock; | ||
| 553 | } | 594 | } |
| 554 | 595 | ||
| 555 | sk_free(sk); | 596 | sk_free(sk); |
| 597 | |||
| 598 | out_unlock: | ||
| 599 | mutex_unlock(&econet_mutex); | ||
| 556 | return 0; | 600 | return 0; |
| 557 | } | 601 | } |
| 558 | 602 | ||
| @@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) | |||
| 608 | struct ec_device *edev; | 652 | struct ec_device *edev; |
| 609 | struct net_device *dev; | 653 | struct net_device *dev; |
| 610 | struct sockaddr_ec *sec; | 654 | struct sockaddr_ec *sec; |
| 655 | int err; | ||
| 611 | 656 | ||
| 612 | /* | 657 | /* |
| 613 | * Fetch the caller's info block into kernel space | 658 | * Fetch the caller's info block into kernel space |
| @@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) | |||
| 621 | 666 | ||
| 622 | sec = (struct sockaddr_ec *)&ifr.ifr_addr; | 667 | sec = (struct sockaddr_ec *)&ifr.ifr_addr; |
| 623 | 668 | ||
| 624 | switch (cmd) | 669 | mutex_lock(&econet_mutex); |
| 625 | { | 670 | |
| 671 | err = 0; | ||
| 672 | switch (cmd) { | ||
| 626 | case SIOCSIFADDR: | 673 | case SIOCSIFADDR: |
| 627 | edev = dev->ec_ptr; | 674 | edev = dev->ec_ptr; |
| 628 | if (edev == NULL) | 675 | if (edev == NULL) { |
| 629 | { | ||
| 630 | /* Magic up a new one. */ | 676 | /* Magic up a new one. */ |
| 631 | edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL); | 677 | edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL); |
| 632 | if (edev == NULL) { | 678 | if (edev == NULL) { |
| 633 | printk("af_ec: memory squeeze.\n"); | 679 | err = -ENOMEM; |
| 634 | dev_put(dev); | 680 | break; |
| 635 | return -ENOMEM; | ||
| 636 | } | 681 | } |
| 637 | memset(edev, 0, sizeof(struct ec_device)); | 682 | memset(edev, 0, sizeof(struct ec_device)); |
| 638 | dev->ec_ptr = edev; | 683 | dev->ec_ptr = edev; |
| 639 | } | 684 | } else |
| 640 | else | ||
| 641 | net2dev_map[edev->net] = NULL; | 685 | net2dev_map[edev->net] = NULL; |
| 642 | edev->station = sec->addr.station; | 686 | edev->station = sec->addr.station; |
| 643 | edev->net = sec->addr.net; | 687 | edev->net = sec->addr.net; |
| 644 | net2dev_map[sec->addr.net] = dev; | 688 | net2dev_map[sec->addr.net] = dev; |
| 645 | if (!net2dev_map[0]) | 689 | if (!net2dev_map[0]) |
| 646 | net2dev_map[0] = dev; | 690 | net2dev_map[0] = dev; |
| 647 | dev_put(dev); | 691 | break; |
| 648 | return 0; | ||
| 649 | 692 | ||
| 650 | case SIOCGIFADDR: | 693 | case SIOCGIFADDR: |
| 651 | edev = dev->ec_ptr; | 694 | edev = dev->ec_ptr; |
| 652 | if (edev == NULL) | 695 | if (edev == NULL) { |
| 653 | { | 696 | err = -ENODEV; |
| 654 | dev_put(dev); | 697 | break; |
| 655 | return -ENODEV; | ||
| 656 | } | 698 | } |
| 657 | memset(sec, 0, sizeof(struct sockaddr_ec)); | 699 | memset(sec, 0, sizeof(struct sockaddr_ec)); |
| 658 | sec->addr.station = edev->station; | 700 | sec->addr.station = edev->station; |
| @@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg) | |||
| 660 | sec->sec_family = AF_ECONET; | 702 | sec->sec_family = AF_ECONET; |
| 661 | dev_put(dev); | 703 | dev_put(dev); |
| 662 | if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) | 704 | if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) |
| 663 | return -EFAULT; | 705 | err = -EFAULT; |
| 664 | return 0; | 706 | break; |
| 707 | |||
| 708 | default: | ||
| 709 | err = -EINVAL; | ||
| 710 | break; | ||
| 665 | } | 711 | } |
| 666 | 712 | ||
| 713 | mutex_unlock(&econet_mutex); | ||
| 714 | |||
| 667 | dev_put(dev); | 715 | dev_put(dev); |
| 668 | return -EINVAL; | 716 | |
| 717 | return err; | ||
| 669 | } | 718 | } |
| 670 | 719 | ||
| 671 | /* | 720 | /* |
| @@ -693,26 +742,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg | |||
| 693 | return 0; | 742 | return 0; |
| 694 | } | 743 | } |
| 695 | 744 | ||
| 696 | #ifdef CONFIG_COMPAT | ||
| 697 | static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
| 698 | { | ||
| 699 | /* | ||
| 700 | * All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec | ||
| 701 | * differs between 32bit and 64bit. Fortunately nobody in kernel uses portion | ||
| 702 | * of sockaddr which differs between 32bit and 64bit, so we do not need special | ||
| 703 | * handling. | ||
| 704 | */ | ||
| 705 | return -ENOIOCTLCMD; | ||
| 706 | } | ||
| 707 | #endif | ||
| 708 | |||
| 709 | static struct net_proto_family econet_family_ops = { | 745 | static struct net_proto_family econet_family_ops = { |
| 710 | .family = PF_ECONET, | 746 | .family = PF_ECONET, |
| 711 | .create = econet_create, | 747 | .create = econet_create, |
| 712 | .owner = THIS_MODULE, | 748 | .owner = THIS_MODULE, |
| 713 | }; | 749 | }; |
| 714 | 750 | ||
| 715 | static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { | 751 | static const struct proto_ops econet_ops = { |
| 716 | .family = PF_ECONET, | 752 | .family = PF_ECONET, |
| 717 | .owner = THIS_MODULE, | 753 | .owner = THIS_MODULE, |
| 718 | .release = econet_release, | 754 | .release = econet_release, |
| @@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { | |||
| 723 | .getname = econet_getname, | 759 | .getname = econet_getname, |
| 724 | .poll = datagram_poll, | 760 | .poll = datagram_poll, |
| 725 | .ioctl = econet_ioctl, | 761 | .ioctl = econet_ioctl, |
| 726 | #ifdef CONFIG_COMPAT | ||
| 727 | .compat_ioctl = econet_compat_ioctl, | ||
| 728 | #endif | ||
| 729 | .listen = sock_no_listen, | 762 | .listen = sock_no_listen, |
| 730 | .shutdown = sock_no_shutdown, | 763 | .shutdown = sock_no_shutdown, |
| 731 | .setsockopt = sock_no_setsockopt, | 764 | .setsockopt = sock_no_setsockopt, |
| @@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { | |||
| 736 | .sendpage = sock_no_sendpage, | 769 | .sendpage = sock_no_sendpage, |
| 737 | }; | 770 | }; |
| 738 | 771 | ||
| 739 | #include <linux/smp_lock.h> | ||
| 740 | SOCKOPS_WRAP(econet, PF_ECONET); | ||
| 741 | |||
| 742 | #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) | 772 | #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE) |
| 743 | /* | 773 | /* |
| 744 | * Find the listening socket, if any, for the given data. | 774 | * Find the listening socket, if any, for the given data. |
