Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux.git] / net / 9p / trans_fd.c
index b7bd7f2961bf60f49258bd60a702eadd8d651773..80d08f6664cbb5611eef291b959facd5332a61ef 100644 (file)
@@ -66,20 +66,6 @@ struct p9_fd_opts {
        int privport;
 };
 
-/**
- * struct p9_trans_fd - transport state
- * @rd: reference to file to read from
- * @wr: reference of file to write to
- * @conn: connection state reference
- *
- */
-
-struct p9_trans_fd {
-       struct file *rd;
-       struct file *wr;
-       struct p9_conn *conn;
-};
-
 /*
   * Option Parsing (code inspired by NFS code)
   *  - a little lazy - parse all fd-transport options
@@ -159,6 +145,20 @@ struct p9_conn {
        unsigned long wsched;
 };
 
+/**
+ * struct p9_trans_fd - transport state
+ * @rd: reference to file to read from
+ * @wr: reference of file to write to
+ * @conn: connection state reference
+ *
+ */
+
+struct p9_trans_fd {
+       struct file *rd;
+       struct file *wr;
+       struct p9_conn conn;
+};
+
 static void p9_poll_workfn(struct work_struct *work);
 
 static DEFINE_SPINLOCK(p9_poll_lock);
@@ -212,15 +212,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
        m->err = err;
 
        list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
-               req->status = REQ_STATUS_ERROR;
-               if (!req->t_err)
-                       req->t_err = err;
                list_move(&req->req_list, &cancel_list);
        }
        list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) {
-               req->status = REQ_STATUS_ERROR;
-               if (!req->t_err)
-                       req->t_err = err;
                list_move(&req->req_list, &cancel_list);
        }
        spin_unlock_irqrestore(&m->client->lock, flags);
@@ -228,7 +222,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
        list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
                p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req);
                list_del(&req->req_list);
-               p9_client_cb(m->client, req);
+               if (!req->t_err)
+                       req->t_err = err;
+               p9_client_cb(m->client, req, REQ_STATUS_ERROR);
        }
 }
 
@@ -302,6 +298,7 @@ static void p9_read_work(struct work_struct *work)
 {
        int n, err;
        struct p9_conn *m;
+       int status = REQ_STATUS_ERROR;
 
        m = container_of(work, struct p9_conn, rq);
 
@@ -348,8 +345,7 @@ static void p9_read_work(struct work_struct *work)
                         "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
 
                m->req = p9_tag_lookup(m->client, tag);
-               if (!m->req || (m->req->status != REQ_STATUS_SENT &&
-                                       m->req->status != REQ_STATUS_FLSH)) {
+               if (!m->req || (m->req->status != REQ_STATUS_SENT)) {
                        p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
                                 tag);
                        err = -EIO;
@@ -375,10 +371,10 @@ static void p9_read_work(struct work_struct *work)
                p9_debug(P9_DEBUG_TRANS, "got new packet\n");
                spin_lock(&m->client->lock);
                if (m->req->status != REQ_STATUS_ERROR)
-                       m->req->status = REQ_STATUS_RCVD;
+                       status = REQ_STATUS_RCVD;
                list_del(&m->req->req_list);
                spin_unlock(&m->client->lock);
-               p9_client_cb(m->client, m->req);
+               p9_client_cb(m->client, m->req, status);
                m->rbuf = NULL;
                m->rpos = 0;
                m->rsize = 0;
@@ -573,21 +569,19 @@ p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
 }
 
 /**
- * p9_conn_create - allocate and initialize the per-session mux data
+ * p9_conn_create - initialize the per-session mux data
  * @client: client instance
  *
  * Note: Creates the polling task if this is the first session.
  */
 
-static struct p9_conn *p9_conn_create(struct p9_client *client)
+static void p9_conn_create(struct p9_client *client)
 {
        int n;
-       struct p9_conn *m;
+       struct p9_trans_fd *ts = client->trans;
+       struct p9_conn *m = &ts->conn;
 
        p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize);
-       m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
-       if (!m)
-               return ERR_PTR(-ENOMEM);
 
        INIT_LIST_HEAD(&m->mux_list);
        m->client = client;
@@ -609,8 +603,6 @@ static struct p9_conn *p9_conn_create(struct p9_client *client)
                p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m);
                set_bit(Wpending, &m->wsched);
        }
-
-       return m;
 }
 
 /**
@@ -669,7 +661,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
 {
        int n;
        struct p9_trans_fd *ts = client->trans;
-       struct p9_conn *m = ts->conn;
+       struct p9_conn *m = &ts->conn;
 
        p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n",
                 m, current, req->tc, req->tc->id);
@@ -704,14 +696,26 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
                list_del(&req->req_list);
                req->status = REQ_STATUS_FLSHD;
                ret = 0;
-       } else if (req->status == REQ_STATUS_SENT)
-               req->status = REQ_STATUS_FLSH;
-
+       }
        spin_unlock(&client->lock);
 
        return ret;
 }
 
+static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
+{
+       p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
+
+       /* we haven't received a response for oldreq,
+        * remove it from the list.
+        */
+       spin_lock(&client->lock);
+       list_del(&req->req_list);
+       spin_unlock(&client->lock);
+
+       return 0;
+}
+
 /**
  * parse_opts - parse mount options into p9_fd_opts structure
  * @params: options string passed from mount
@@ -780,7 +784,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
 
 static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
 {
-       struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
+       struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd),
                                           GFP_KERNEL);
        if (!ts)
                return -ENOMEM;
@@ -806,9 +810,8 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 {
        struct p9_trans_fd *p;
        struct file *file;
-       int ret;
 
-       p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
+       p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
 
@@ -829,20 +832,12 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 
        p->rd->f_flags |= O_NONBLOCK;
 
-       p->conn = p9_conn_create(client);
-       if (IS_ERR(p->conn)) {
-               ret = PTR_ERR(p->conn);
-               p->conn = NULL;
-               kfree(p);
-               sockfd_put(csocket);
-               sockfd_put(csocket);
-               return ret;
-       }
+       p9_conn_create(client);
        return 0;
 }
 
 /**
- * p9_mux_destroy - cancels all pending requests and frees mux resources
+ * p9_mux_destroy - cancels all pending requests of mux
  * @m: mux to destroy
  *
  */
@@ -859,7 +854,6 @@ static void p9_conn_destroy(struct p9_conn *m)
        p9_conn_cancel(m, -ECONNRESET);
 
        m->client = NULL;
-       kfree(m);
 }
 
 /**
@@ -881,7 +875,7 @@ static void p9_fd_close(struct p9_client *client)
 
        client->status = Disconnected;
 
-       p9_conn_destroy(ts->conn);
+       p9_conn_destroy(&ts->conn);
 
        if (ts->rd)
                fput(ts->rd);
@@ -1033,14 +1027,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
                return err;
 
        p = (struct p9_trans_fd *) client->trans;
-       p->conn = p9_conn_create(client);
-       if (IS_ERR(p->conn)) {
-               err = PTR_ERR(p->conn);
-               p->conn = NULL;
-               fput(p->rd);
-               fput(p->wr);
-               return err;
-       }
+       p9_conn_create(client);
 
        return 0;
 }
@@ -1053,6 +1040,7 @@ static struct p9_trans_module p9_tcp_trans = {
        .close = p9_fd_close,
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
+       .cancelled = p9_fd_cancelled,
        .owner = THIS_MODULE,
 };
 
@@ -1064,6 +1052,7 @@ static struct p9_trans_module p9_unix_trans = {
        .close = p9_fd_close,
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
+       .cancelled = p9_fd_cancelled,
        .owner = THIS_MODULE,
 };
 
@@ -1075,6 +1064,7 @@ static struct p9_trans_module p9_fd_trans = {
        .close = p9_fd_close,
        .request = p9_fd_request,
        .cancel = p9_fd_cancel,
+       .cancelled = p9_fd_cancelled,
        .owner = THIS_MODULE,
 };