sata_sil24: kill unused local variable idx in sil24_fill_sg()
[powerpc.git] / fs / dlm / lowcomms-tcp.c
index 86e5f81..07e0a12 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -96,10 +96,7 @@ static bool cbuf_empty(struct cbuf *cb)
 struct connection {
        struct socket *sock;    /* NULL if not connected */
        uint32_t nodeid;        /* So we know who we are in the list */
-       struct rw_semaphore sock_sem; /* Stop connect races */
-       struct list_head read_list;   /* On this list when ready for reading */
-       struct list_head write_list;  /* On this list when ready for writing */
-       struct list_head state_list;  /* On this list when ready to connect */
+       struct mutex sock_mutex;
        unsigned long flags;    /* bit 1,2 = We are on the read/write lists */
 #define CF_READ_PENDING 1
 #define CF_WRITE_PENDING 2
@@ -112,7 +109,6 @@ struct connection {
        struct page *rx_page;
        struct cbuf cb;
        int retries;
-       atomic_t waiting_requests;
 #define MAX_CONNECT_RETRIES 3
        struct connection *othercon;
        struct work_struct rwork; /* Receive workqueue */
@@ -174,7 +170,7 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation)
                        goto finish;
 
                con->nodeid = nodeid;
-               init_rwsem(&con->sock_sem);
+               mutex_init(&con->sock_mutex);
                INIT_LIST_HEAD(&con->writequeue);
                spin_lock_init(&con->writequeue_lock);
                INIT_WORK(&con->swork, process_send_sockets);
@@ -250,7 +246,7 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
 /* Close a remote connection and tidy up */
 static void close_connection(struct connection *con, bool and_other)
 {
-       down_write(&con->sock_sem);
+       mutex_lock(&con->sock_mutex);
 
        if (con->sock) {
                sock_release(con->sock);
@@ -265,24 +261,27 @@ static void close_connection(struct connection *con, bool and_other)
                con->rx_page = NULL;
        }
        con->retries = 0;
-       up_write(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
 }
 
 /* Data received from remote end */
 static int receive_from_sock(struct connection *con)
 {
        int ret = 0;
-       struct msghdr msg;
-       struct iovec iov[2];
-       mm_segment_t fs;
+       struct msghdr msg = {};
+       struct kvec iov[2];
        unsigned len;
        int r;
        int call_again_soon = 0;
+       int nvec;
 
-       down_read(&con->sock_sem);
+       mutex_lock(&con->sock_mutex);
+
+       if (con->sock == NULL) {
+               ret = -EAGAIN;
+               goto out_close;
+       }
 
-       if (con->sock == NULL)
-               goto out;
        if (con->rx_page == NULL) {
                /*
                 * This doesn't need to be atomic, but I think it should
@@ -294,21 +293,13 @@ static int receive_from_sock(struct connection *con)
                cbuf_init(&con->cb, PAGE_CACHE_SIZE);
        }
 
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_iovlen = 1;
-       msg.msg_iov = iov;
-       msg.msg_name = NULL;
-       msg.msg_namelen = 0;
-       msg.msg_flags = 0;
-
        /*
         * iov[0] is the bit of the circular buffer between the current end
         * point (cb.base + cb.len) and the end of the buffer.
         */
        iov[0].iov_len = con->cb.base - cbuf_data(&con->cb);
        iov[0].iov_base = page_address(con->rx_page) + cbuf_data(&con->cb);
-       iov[1].iov_len = 0;
+       nvec = 1;
 
        /*
         * iov[1] is the bit of the circular buffer between the start of the
@@ -318,18 +309,18 @@ static int receive_from_sock(struct connection *con)
                iov[0].iov_len = PAGE_CACHE_SIZE - cbuf_data(&con->cb);
                iov[1].iov_len = con->cb.base;
                iov[1].iov_base = page_address(con->rx_page);
-               msg.msg_iovlen = 2;
+               nvec = 2;
        }
        len = iov[0].iov_len + iov[1].iov_len;
 
-       fs = get_fs();
-       set_fs(get_ds());
-       r = ret = sock_recvmsg(con->sock, &msg, len,
+       r = ret = kernel_recvmsg(con->sock, &msg, iov, nvec, len,
                               MSG_DONTWAIT | MSG_NOSIGNAL);
-       set_fs(fs);
 
        if (ret <= 0)
                goto out_close;
+       if (ret == -EAGAIN)
+               goto out_resched;
+
        if (ret == len)
                call_again_soon = 1;
        cbuf_add(&con->cb, ret);
@@ -352,25 +343,26 @@ static int receive_from_sock(struct connection *con)
                con->rx_page = NULL;
        }
 
-out:
        if (call_again_soon)
                goto out_resched;
-       up_read(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        return 0;
 
 out_resched:
        if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
                queue_work(recv_workqueue, &con->rwork);
-       up_read(&con->sock_sem);
-       cond_resched();
-       return 0;
+       mutex_unlock(&con->sock_mutex);
+       return -EAGAIN;
 
 out_close:
-       up_read(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        if (ret != -EAGAIN && !test_bit(CF_IS_OTHERCON, &con->flags)) {
                close_connection(con, false);
                /* Reconnect when there is something to send */
        }
+       /* Don't return success if we really got EOF */
+       if (ret == 0)
+               ret = -EAGAIN;
 
        return ret;
 }
@@ -384,6 +376,7 @@ static int accept_from_sock(struct connection *con)
        int len;
        int nodeid;
        struct connection *newcon;
+       struct connection *addcon;
 
        memset(&peeraddr, 0, sizeof(peeraddr));
        result = sock_create_kern(dlm_local_addr.ss_family, SOCK_STREAM,
@@ -391,7 +384,7 @@ static int accept_from_sock(struct connection *con)
        if (result < 0)
                return -ENOMEM;
 
-       down_read(&con->sock_sem);
+       mutex_lock_nested(&con->sock_mutex, 0);
 
        result = -ENOTCONN;
        if (con->sock == NULL)
@@ -417,7 +410,7 @@ static int accept_from_sock(struct connection *con)
        if (dlm_addr_to_nodeid(&peeraddr, &nodeid)) {
                printk("dlm: connect from non cluster node\n");
                sock_release(newsock);
-               up_read(&con->sock_sem);
+               mutex_unlock(&con->sock_mutex);
                return -1;
        }
 
@@ -434,7 +427,7 @@ static int accept_from_sock(struct connection *con)
                result = -ENOMEM;
                goto accept_err;
        }
-       down_write(&newcon->sock_sem);
+       mutex_lock_nested(&newcon->sock_mutex, 1);
        if (newcon->sock) {
                struct connection *othercon = newcon->othercon;
 
@@ -442,13 +435,13 @@ static int accept_from_sock(struct connection *con)
                        othercon = kmem_cache_zalloc(con_cache, GFP_KERNEL);
                        if (!othercon) {
                                printk("dlm: failed to allocate incoming socket\n");
-                               up_write(&newcon->sock_sem);
+                               mutex_unlock(&newcon->sock_mutex);
                                result = -ENOMEM;
                                goto accept_err;
                        }
                        othercon->nodeid = nodeid;
                        othercon->rx_action = receive_from_sock;
-                       init_rwsem(&othercon->sock_sem);
+                       mutex_init(&othercon->sock_mutex);
                        INIT_WORK(&othercon->swork, process_send_sockets);
                        INIT_WORK(&othercon->rwork, process_recv_sockets);
                        set_bit(CF_IS_OTHERCON, &othercon->flags);
@@ -457,29 +450,30 @@ static int accept_from_sock(struct connection *con)
                othercon->sock = newsock;
                newsock->sk->sk_user_data = othercon;
                add_sock(newsock, othercon);
+               addcon = othercon;
        }
        else {
                newsock->sk->sk_user_data = newcon;
                newcon->rx_action = receive_from_sock;
                add_sock(newsock, newcon);
-
+               addcon = newcon;
        }
 
-       up_write(&newcon->sock_sem);
+       mutex_unlock(&newcon->sock_mutex);
 
        /*
         * Add it to the active queue in case we got data
         * beween processing the accept adding the socket
         * to the read_sockets list
         */
-       if (!test_and_set_bit(CF_READ_PENDING, &newcon->flags))
-               queue_work(recv_workqueue, &newcon->rwork);
-       up_read(&con->sock_sem);
+       if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
+               queue_work(recv_workqueue, &addcon->rwork);
+       mutex_unlock(&con->sock_mutex);
 
        return 0;
 
 accept_err:
-       up_read(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        sock_release(newsock);
 
        if (result != -EAGAIN)
@@ -500,7 +494,7 @@ static void connect_to_sock(struct connection *con)
                return;
        }
 
-       down_write(&con->sock_sem);
+       mutex_lock(&con->sock_mutex);
        if (con->retries++ > MAX_CONNECT_RETRIES)
                goto out;
 
@@ -552,7 +546,7 @@ out_err:
                result = 0;
        }
 out:
-       up_write(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        return;
 }
 
@@ -613,8 +607,7 @@ static struct socket *create_listen_sock(struct connection *con,
 
        result = sock->ops->listen(sock, 5);
        if (result < 0) {
-               printk("dlm: Can't listen on port %d\n",
-                      dlm_config.ci_tcp_port);
+               printk("dlm: Can't listen on port %d\n", dlm_config.ci_tcp_port);
                sock_release(sock);
                sock = NULL;
                goto create_out;
@@ -757,7 +750,7 @@ static void send_to_sock(struct connection *con)
        struct writequeue_entry *e;
        int len, offset;
 
-       down_read(&con->sock_sem);
+       mutex_lock(&con->sock_mutex);
        if (con->sock == NULL)
                goto out_connect;
 
@@ -803,18 +796,18 @@ static void send_to_sock(struct connection *con)
        }
        spin_unlock(&con->writequeue_lock);
 out:
-       up_read(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        return;
 
 send_error:
-       up_read(&con->sock_sem);
+       mutex_unlock(&con->sock_mutex);
        close_connection(con, false);
        lowcomms_connect_sock(con);
        return;
 
 out_connect:
-       up_read(&con->sock_sem);
-       lowcomms_connect_sock(con);
+       mutex_unlock(&con->sock_mutex);
+       connect_to_sock(con);
        return;
 }
 
@@ -847,7 +840,6 @@ int dlm_lowcomms_close(int nodeid)
        if (con) {
                clean_one_writequeue(con);
                close_connection(con, true);
-               atomic_set(&con->waiting_requests, 0);
        }
        return 0;
 
@@ -876,9 +868,8 @@ static void process_send_sockets(struct work_struct *work)
                connect_to_sock(con);
        }
 
-       if (test_and_clear_bit(CF_WRITE_PENDING, &con->flags)) {
-               send_to_sock(con);
-       }
+       clear_bit(CF_WRITE_PENDING, &con->flags);
+       send_to_sock(con);
 }