dlm: initialize file_lock struct in GETLK before copying conflicting lock
[safe/jmp/linux-2.6] / fs / dlm / lowcomms.c
index 5772844..103a5eb 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/pagemap.h>
 #include <linux/idr.h>
 #include <linux/file.h>
+#include <linux/mutex.h>
 #include <linux/sctp.h>
 #include <net/sctp/user.h>
 
@@ -138,7 +139,7 @@ static struct workqueue_struct *recv_workqueue;
 static struct workqueue_struct *send_workqueue;
 
 static DEFINE_IDR(connections_idr);
-static DECLARE_MUTEX(connections_lock);
+static DEFINE_MUTEX(connections_lock);
 static int max_nodeid;
 static struct kmem_cache *con_cache;
 
@@ -205,9 +206,9 @@ static struct connection *nodeid2con(int nodeid, gfp_t allocation)
 {
        struct connection *con;
 
-       down(&connections_lock);
+       mutex_lock(&connections_lock);
        con = __nodeid2con(nodeid, allocation);
-       up(&connections_lock);
+       mutex_unlock(&connections_lock);
 
        return con;
 }
@@ -218,15 +219,15 @@ static struct connection *assoc2con(int assoc_id)
        int i;
        struct connection *con;
 
-       down(&connections_lock);
+       mutex_lock(&connections_lock);
        for (i=0; i<=max_nodeid; i++) {
                con = __nodeid2con(i, 0);
                if (con && con->sctp_assoc == assoc_id) {
-                       up(&connections_lock);
+                       mutex_unlock(&connections_lock);
                        return con;
                }
        }
-       up(&connections_lock);
+       mutex_unlock(&connections_lock);
        return NULL;
 }
 
@@ -294,6 +295,7 @@ static int add_sock(struct socket *sock, struct connection *con)
        con->sock->sk->sk_write_space = lowcomms_write_space;
        con->sock->sk->sk_state_change = lowcomms_state_change;
        con->sock->sk->sk_user_data = con;
+       con->sock->sk->sk_allocation = GFP_NOFS;
        return 0;
 }
 
@@ -381,7 +383,7 @@ static void sctp_init_failed(void)
        int i;
        struct connection *con;
 
-       down(&connections_lock);
+       mutex_lock(&connections_lock);
        for (i=1; i<=max_nodeid; i++) {
                con = __nodeid2con(i, 0);
                if (!con)
@@ -393,7 +395,7 @@ static void sctp_init_failed(void)
                        }
                }
        }
-       up(&connections_lock);
+       mutex_unlock(&connections_lock);
 }
 
 /* Something happened to an association */
@@ -822,7 +824,6 @@ static void sctp_init_assoc(struct connection *con)
        len = e->len;
        offset = e->offset;
        spin_unlock(&con->writequeue_lock);
-       kmap(e->page);
 
        /* Send the first block off the write queue */
        iov[0].iov_base = page_address(e->page)+offset;
@@ -853,7 +854,6 @@ static void sctp_init_assoc(struct connection *con)
 
                if (e->len == 0 && e->users == 0) {
                        list_del(&e->list);
-                       kunmap(e->page);
                        free_entry(e);
                }
                spin_unlock(&con->writequeue_lock);
@@ -890,8 +890,10 @@ static void tcp_connect_to_sock(struct connection *con)
                goto out_err;
 
        memset(&saddr, 0, sizeof(saddr));
-       if (dlm_nodeid_to_addr(con->nodeid, &saddr))
+       if (dlm_nodeid_to_addr(con->nodeid, &saddr)) {
+               sock_release(sock);
                goto out_err;
+       }
 
        sock->sk->sk_user_data = con;
        con->rx_action = receive_from_sock;
@@ -930,7 +932,7 @@ out_err:
         * errors we try again until the max number of retries is reached.
         */
        if (result != -EHOSTUNREACH && result != -ENETUNREACH &&
-           result != -ENETDOWN && result != EINVAL
+           result != -ENETDOWN && result != -EINVAL
            && result != -EPROTONOSUPPORT) {
                lowcomms_connect_sock(con);
                result = 0;
@@ -1200,8 +1202,6 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 
        if (e) {
        got_one:
-               if (users == 0)
-                       kmap(e->page);
                *ppc = page_address(e->page) + offset;
                return e;
        }
@@ -1230,7 +1230,6 @@ void dlm_lowcomms_commit_buffer(void *mh)
        if (users)
                goto out;
        e->len = e->end - e->offset;
-       kunmap(e->page);
        spin_unlock(&con->writequeue_lock);
 
        if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) {
@@ -1269,7 +1268,6 @@ static void send_to_sock(struct connection *con)
                offset = e->offset;
                BUG_ON(len == 0 && e->users == 0);
                spin_unlock(&con->writequeue_lock);
-               kmap(e->page);
 
                ret = 0;
                if (len) {
@@ -1291,7 +1289,6 @@ static void send_to_sock(struct connection *con)
 
                if (e->len == 0 && e->users == 0) {
                        list_del(&e->list);
-                       kunmap(e->page);
                        free_entry(e);
                        continue;
                }
@@ -1417,7 +1414,7 @@ void dlm_lowcomms_stop(void)
        /* Set all the flags to prevent any
           socket activity.
        */
-       down(&connections_lock);
+       mutex_lock(&connections_lock);
        for (i = 0; i <= max_nodeid; i++) {
                con = __nodeid2con(i, 0);
                if (con) {
@@ -1426,22 +1423,24 @@ void dlm_lowcomms_stop(void)
                                con->sock->sk->sk_user_data = NULL;
                }
        }
-       up(&connections_lock);
+       mutex_unlock(&connections_lock);
 
        work_stop();
 
-       down(&connections_lock);
+       mutex_lock(&connections_lock);
        clean_writequeues();
 
        for (i = 0; i <= max_nodeid; i++) {
                con = __nodeid2con(i, 0);
                if (con) {
                        close_connection(con, true);
+                       if (con->othercon)
+                               kmem_cache_free(con_cache, con->othercon);
                        kmem_cache_free(con_cache, con);
                }
        }
        max_nodeid = 0;
-       up(&connections_lock);
+       mutex_unlock(&connections_lock);
        kmem_cache_destroy(con_cache);
        idr_init(&connections_idr);
 }