diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/9p/trans_fd.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/9p/trans_fd.c')
-rw-r--r-- | net/9p/trans_fd.c | 127 |
1 files changed, 55 insertions, 72 deletions
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 8d934dd7fd54..98ce9bcb0e15 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -38,10 +38,13 @@ | |||
38 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
39 | #include <linux/file.h> | 39 | #include <linux/file.h> |
40 | #include <linux/parser.h> | 40 | #include <linux/parser.h> |
41 | #include <linux/slab.h> | ||
41 | #include <net/9p/9p.h> | 42 | #include <net/9p/9p.h> |
42 | #include <net/9p/client.h> | 43 | #include <net/9p/client.h> |
43 | #include <net/9p/transport.h> | 44 | #include <net/9p/transport.h> |
44 | 45 | ||
46 | #include <linux/syscalls.h> /* killme */ | ||
47 | |||
45 | #define P9_PORT 564 | 48 | #define P9_PORT 564 |
46 | #define MAX_SOCK_BUF (64*1024) | 49 | #define MAX_SOCK_BUF (64*1024) |
47 | #define MAXPOLLWADDR 2 | 50 | #define MAXPOLLWADDR 2 |
@@ -633,8 +636,8 @@ static void p9_poll_mux(struct p9_conn *m) | |||
633 | if (n & POLLOUT) { | 636 | if (n & POLLOUT) { |
634 | set_bit(Wpending, &m->wsched); | 637 | set_bit(Wpending, &m->wsched); |
635 | P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m); | 638 | P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can write\n", m); |
636 | if ((m->wsize || !list_empty(&m->unsent_req_list)) | 639 | if ((m->wsize || !list_empty(&m->unsent_req_list)) && |
637 | && !test_and_set_bit(Wworksched, &m->wsched)) { | 640 | !test_and_set_bit(Wworksched, &m->wsched)) { |
638 | P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m); | 641 | P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m); |
639 | queue_work(p9_mux_wq, &m->wq); | 642 | queue_work(p9_mux_wq, &m->wq); |
640 | } | 643 | } |
@@ -712,7 +715,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
712 | char *p; | 715 | char *p; |
713 | substring_t args[MAX_OPT_ARGS]; | 716 | substring_t args[MAX_OPT_ARGS]; |
714 | int option; | 717 | int option; |
715 | char *options; | 718 | char *options, *tmp_options; |
716 | int ret; | 719 | int ret; |
717 | 720 | ||
718 | opts->port = P9_PORT; | 721 | opts->port = P9_PORT; |
@@ -722,12 +725,13 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
722 | if (!params) | 725 | if (!params) |
723 | return 0; | 726 | return 0; |
724 | 727 | ||
725 | options = kstrdup(params, GFP_KERNEL); | 728 | tmp_options = kstrdup(params, GFP_KERNEL); |
726 | if (!options) { | 729 | if (!tmp_options) { |
727 | P9_DPRINTK(P9_DEBUG_ERROR, | 730 | P9_DPRINTK(P9_DEBUG_ERROR, |
728 | "failed to allocate copy of option string\n"); | 731 | "failed to allocate copy of option string\n"); |
729 | return -ENOMEM; | 732 | return -ENOMEM; |
730 | } | 733 | } |
734 | options = tmp_options; | ||
731 | 735 | ||
732 | while ((p = strsep(&options, ",")) != NULL) { | 736 | while ((p = strsep(&options, ",")) != NULL) { |
733 | int token; | 737 | int token; |
@@ -758,7 +762,8 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
758 | continue; | 762 | continue; |
759 | } | 763 | } |
760 | } | 764 | } |
761 | kfree(options); | 765 | |
766 | kfree(tmp_options); | ||
762 | return 0; | 767 | return 0; |
763 | } | 768 | } |
764 | 769 | ||
@@ -788,24 +793,41 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd) | |||
788 | 793 | ||
789 | static int p9_socket_open(struct p9_client *client, struct socket *csocket) | 794 | static int p9_socket_open(struct p9_client *client, struct socket *csocket) |
790 | { | 795 | { |
791 | int fd, ret; | 796 | struct p9_trans_fd *p; |
797 | int ret, fd; | ||
798 | |||
799 | p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); | ||
800 | if (!p) | ||
801 | return -ENOMEM; | ||
792 | 802 | ||
793 | csocket->sk->sk_allocation = GFP_NOIO; | 803 | csocket->sk->sk_allocation = GFP_NOIO; |
794 | fd = sock_map_fd(csocket, 0); | 804 | fd = sock_map_fd(csocket, 0); |
795 | if (fd < 0) { | 805 | if (fd < 0) { |
796 | P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); | 806 | P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n"); |
807 | sock_release(csocket); | ||
808 | kfree(p); | ||
797 | return fd; | 809 | return fd; |
798 | } | 810 | } |
799 | 811 | ||
800 | ret = p9_fd_open(client, fd, fd); | 812 | get_file(csocket->file); |
801 | if (ret < 0) { | 813 | get_file(csocket->file); |
802 | P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); | 814 | p->wr = p->rd = csocket->file; |
815 | client->trans = p; | ||
816 | client->status = Connected; | ||
817 | |||
818 | sys_close(fd); /* still racy */ | ||
819 | |||
820 | p->rd->f_flags |= O_NONBLOCK; | ||
821 | |||
822 | p->conn = p9_conn_create(client); | ||
823 | if (IS_ERR(p->conn)) { | ||
824 | ret = PTR_ERR(p->conn); | ||
825 | p->conn = NULL; | ||
826 | kfree(p); | ||
827 | sockfd_put(csocket); | ||
803 | sockfd_put(csocket); | 828 | sockfd_put(csocket); |
804 | return ret; | 829 | return ret; |
805 | } | 830 | } |
806 | |||
807 | ((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK; | ||
808 | |||
809 | return 0; | 831 | return 0; |
810 | } | 832 | } |
811 | 833 | ||
@@ -883,7 +905,6 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) | |||
883 | struct socket *csocket; | 905 | struct socket *csocket; |
884 | struct sockaddr_in sin_server; | 906 | struct sockaddr_in sin_server; |
885 | struct p9_fd_opts opts; | 907 | struct p9_fd_opts opts; |
886 | struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */ | ||
887 | 908 | ||
888 | err = parse_opts(args, &opts); | 909 | err = parse_opts(args, &opts); |
889 | if (err < 0) | 910 | if (err < 0) |
@@ -897,12 +918,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) | |||
897 | sin_server.sin_family = AF_INET; | 918 | sin_server.sin_family = AF_INET; |
898 | sin_server.sin_addr.s_addr = in_aton(addr); | 919 | sin_server.sin_addr.s_addr = in_aton(addr); |
899 | sin_server.sin_port = htons(opts.port); | 920 | sin_server.sin_port = htons(opts.port); |
900 | sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); | 921 | err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket); |
901 | 922 | ||
902 | if (!csocket) { | 923 | if (err) { |
903 | P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); | 924 | P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n"); |
904 | err = -EIO; | 925 | return err; |
905 | goto error; | ||
906 | } | 926 | } |
907 | 927 | ||
908 | err = csocket->ops->connect(csocket, | 928 | err = csocket->ops->connect(csocket, |
@@ -912,30 +932,11 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) | |||
912 | P9_EPRINTK(KERN_ERR, | 932 | P9_EPRINTK(KERN_ERR, |
913 | "p9_trans_tcp: problem connecting socket to %s\n", | 933 | "p9_trans_tcp: problem connecting socket to %s\n", |
914 | addr); | 934 | addr); |
915 | goto error; | ||
916 | } | ||
917 | |||
918 | err = p9_socket_open(client, csocket); | ||
919 | if (err < 0) | ||
920 | goto error; | ||
921 | |||
922 | p = (struct p9_trans_fd *) client->trans; | ||
923 | p->conn = p9_conn_create(client); | ||
924 | if (IS_ERR(p->conn)) { | ||
925 | err = PTR_ERR(p->conn); | ||
926 | p->conn = NULL; | ||
927 | goto error; | ||
928 | } | ||
929 | |||
930 | return 0; | ||
931 | |||
932 | error: | ||
933 | if (csocket) | ||
934 | sock_release(csocket); | 935 | sock_release(csocket); |
936 | return err; | ||
937 | } | ||
935 | 938 | ||
936 | kfree(p); | 939 | return p9_socket_open(client, csocket); |
937 | |||
938 | return err; | ||
939 | } | 940 | } |
940 | 941 | ||
941 | static int | 942 | static int |
@@ -944,49 +945,33 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) | |||
944 | int err; | 945 | int err; |
945 | struct socket *csocket; | 946 | struct socket *csocket; |
946 | struct sockaddr_un sun_server; | 947 | struct sockaddr_un sun_server; |
947 | struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */ | ||
948 | 948 | ||
949 | csocket = NULL; | 949 | csocket = NULL; |
950 | 950 | ||
951 | if (strlen(addr) > UNIX_PATH_MAX) { | 951 | if (strlen(addr) > UNIX_PATH_MAX) { |
952 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", | 952 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", |
953 | addr); | 953 | addr); |
954 | err = -ENAMETOOLONG; | 954 | return -ENAMETOOLONG; |
955 | goto error; | ||
956 | } | 955 | } |
957 | 956 | ||
958 | sun_server.sun_family = PF_UNIX; | 957 | sun_server.sun_family = PF_UNIX; |
959 | strcpy(sun_server.sun_path, addr); | 958 | strcpy(sun_server.sun_path, addr); |
960 | sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); | 959 | err = sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket); |
960 | if (err < 0) { | ||
961 | P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem creating socket\n"); | ||
962 | return err; | ||
963 | } | ||
961 | err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, | 964 | err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, |
962 | sizeof(struct sockaddr_un) - 1, 0); | 965 | sizeof(struct sockaddr_un) - 1, 0); |
963 | if (err < 0) { | 966 | if (err < 0) { |
964 | P9_EPRINTK(KERN_ERR, | 967 | P9_EPRINTK(KERN_ERR, |
965 | "p9_trans_unix: problem connecting socket: %s: %d\n", | 968 | "p9_trans_unix: problem connecting socket: %s: %d\n", |
966 | addr, err); | 969 | addr, err); |
967 | goto error; | ||
968 | } | ||
969 | |||
970 | err = p9_socket_open(client, csocket); | ||
971 | if (err < 0) | ||
972 | goto error; | ||
973 | |||
974 | p = (struct p9_trans_fd *) client->trans; | ||
975 | p->conn = p9_conn_create(client); | ||
976 | if (IS_ERR(p->conn)) { | ||
977 | err = PTR_ERR(p->conn); | ||
978 | p->conn = NULL; | ||
979 | goto error; | ||
980 | } | ||
981 | |||
982 | return 0; | ||
983 | |||
984 | error: | ||
985 | if (csocket) | ||
986 | sock_release(csocket); | 970 | sock_release(csocket); |
971 | return err; | ||
972 | } | ||
987 | 973 | ||
988 | kfree(p); | 974 | return p9_socket_open(client, csocket); |
989 | return err; | ||
990 | } | 975 | } |
991 | 976 | ||
992 | static int | 977 | static int |
@@ -994,7 +979,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args) | |||
994 | { | 979 | { |
995 | int err; | 980 | int err; |
996 | struct p9_fd_opts opts; | 981 | struct p9_fd_opts opts; |
997 | struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */ | 982 | struct p9_trans_fd *p; |
998 | 983 | ||
999 | parse_opts(args, &opts); | 984 | parse_opts(args, &opts); |
1000 | 985 | ||
@@ -1005,21 +990,19 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args) | |||
1005 | 990 | ||
1006 | err = p9_fd_open(client, opts.rfd, opts.wfd); | 991 | err = p9_fd_open(client, opts.rfd, opts.wfd); |
1007 | if (err < 0) | 992 | if (err < 0) |
1008 | goto error; | 993 | return err; |
1009 | 994 | ||
1010 | p = (struct p9_trans_fd *) client->trans; | 995 | p = (struct p9_trans_fd *) client->trans; |
1011 | p->conn = p9_conn_create(client); | 996 | p->conn = p9_conn_create(client); |
1012 | if (IS_ERR(p->conn)) { | 997 | if (IS_ERR(p->conn)) { |
1013 | err = PTR_ERR(p->conn); | 998 | err = PTR_ERR(p->conn); |
1014 | p->conn = NULL; | 999 | p->conn = NULL; |
1015 | goto error; | 1000 | fput(p->rd); |
1001 | fput(p->wr); | ||
1002 | return err; | ||
1016 | } | 1003 | } |
1017 | 1004 | ||
1018 | return 0; | 1005 | return 0; |
1019 | |||
1020 | error: | ||
1021 | kfree(p); | ||
1022 | return err; | ||
1023 | } | 1006 | } |
1024 | 1007 | ||
1025 | static struct p9_trans_module p9_tcp_trans = { | 1008 | static struct p9_trans_module p9_tcp_trans = { |