forked from Minki/linux
A bunch of updates and cleanup within the transport layer,
particularly with a focus on RDMA. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) Comment: GPGTools - http://gpgtools.org iQIcBAABAgAGBQJTRXV1AAoJEDZk62b0Tg6xYWAP/0Kfp9/8Z05SQ1fnJveySw1O nKK//1/GBmquntqFAVHI6yJRLzPJ+Z/Y4u4a0qriwfgpPQvUJQrL77tY/VfEBUPB VoJG1tj7lpdLrO3p4YyPkPjymyC7YOoFNjGEstWFg7HetwnnqqZL2LB+5yJzyqjx y9nv1HzsrbAE7j8C4hQ1Nmds5muUb5VhnTtPhjrx4tP1sWWh8XTVJbsVDiEqx6cu uJXFFTbkONr9jKfv+Ki3H2pZej2yD7w4tU4lkdcGNyij/Q4Xn1iERqroW2/GT6Cl AXxlIKN24ASjWo4VqW0Wf8gO8vbUtHRChoiZ69DvzNTkbWmAIWSFHyQJ4cinwuyr UbOQZuccO59QtpNVpBvG/vjnbI54rg+VGLy+xE0vcrBDlyoptc56IAFSg8zJY5UN ysbyHCGME//9VZ1zeeZvkMjm8z5Enp6x4zmtnUHmufO7DVMTFUePED6U1u9WIyP5 FFy5EboXMSh97yB8REvbIlY2MgBJWYdnyzLKFMeRpzC8fOXJqBoCX8i3Z5SkMYWJ 1FS/pGr7ec/VX1iHXSYi9hhzTJ6o9mEmOIhaO4UcqAuK8Rk2jbCp1Lx0iDhmJtdT zjofGDe57ro7nOZf8A/TI5z+6BZq8KYVfZrXtYaPqC4rXOzJAox/yHlz9FmAJYgv ssOIKXX0ujLwqrMBVatj =yzy/ -----END PGP SIGNATURE----- Merge tag 'for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs Pull 9p changes from Eric Van Hensbergen: "A bunch of updates and cleanup within the transport layer, particularly with a focus on RDMA" * tag 'for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9pnet_rdma: check token type before int conversion 9pnet: trans_fd : allocate struct p9_trans_fd and struct p9_conn together. 9pnet: p9_client->conn field is unused. Remove it. 9P: Get rid of REQ_STATUS_FLSH 9pnet_rdma: add cancelled() 9pnet_rdma: update request status during send 9P: Add cancelled() to the transport functions. net: Mark function as static in 9p/client.c 9P: Add memory barriers to protect request fields over cb/rpc threads handoff
This commit is contained in:
commit
582076ab16
@ -67,7 +67,6 @@ enum p9_trans_status {
|
||||
* @REQ_STATUS_ALLOC: request has been allocated but not sent
|
||||
* @REQ_STATUS_UNSENT: request waiting to be sent
|
||||
* @REQ_STATUS_SENT: request sent to server
|
||||
* @REQ_STATUS_FLSH: a flush has been sent for this request
|
||||
* @REQ_STATUS_RCVD: response received from server
|
||||
* @REQ_STATUS_FLSHD: request has been flushed
|
||||
* @REQ_STATUS_ERROR: request encountered an error on the client side
|
||||
@ -83,7 +82,6 @@ enum p9_req_status_t {
|
||||
REQ_STATUS_ALLOC,
|
||||
REQ_STATUS_UNSENT,
|
||||
REQ_STATUS_SENT,
|
||||
REQ_STATUS_FLSH,
|
||||
REQ_STATUS_RCVD,
|
||||
REQ_STATUS_FLSHD,
|
||||
REQ_STATUS_ERROR,
|
||||
@ -130,7 +128,6 @@ struct p9_req_t {
|
||||
* @proto_version: 9P protocol version to use
|
||||
* @trans_mod: module API instantiated with this client
|
||||
* @trans: tranport instance state and API
|
||||
* @conn: connection state information used by trans_fd
|
||||
* @fidpool: fid handle accounting for session
|
||||
* @fidlist: List of active fid handles
|
||||
* @tagpool - transaction id accounting for session
|
||||
@ -159,7 +156,6 @@ struct p9_client {
|
||||
struct p9_trans_module *trans_mod;
|
||||
enum p9_trans_status status;
|
||||
void *trans;
|
||||
struct p9_conn *conn;
|
||||
|
||||
struct p9_idpool *fidpool;
|
||||
struct list_head fidlist;
|
||||
@ -261,7 +257,7 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
|
||||
int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status);
|
||||
int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl);
|
||||
struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
|
||||
void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
|
||||
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
|
||||
|
||||
int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
|
||||
int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *);
|
||||
|
@ -40,6 +40,8 @@
|
||||
* @close: member function to discard a connection on this transport
|
||||
* @request: member function to issue a request to the transport
|
||||
* @cancel: member function to cancel a request (if it hasn't been sent)
|
||||
* @cancelled: member function to notify that a cancelled request will not
|
||||
* not receive a reply
|
||||
*
|
||||
* This is the basic API for a transport module which is registered by the
|
||||
* transport module with the 9P core network module and used by the client
|
||||
@ -58,6 +60,7 @@ struct p9_trans_module {
|
||||
void (*close) (struct p9_client *);
|
||||
int (*request) (struct p9_client *, struct p9_req_t *req);
|
||||
int (*cancel) (struct p9_client *, struct p9_req_t *req);
|
||||
int (*cancelled)(struct p9_client *, struct p9_req_t *req);
|
||||
int (*zc_request)(struct p9_client *, struct p9_req_t *,
|
||||
char *, char *, int , int, int, int);
|
||||
};
|
||||
|
@ -415,9 +415,17 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
|
||||
* req: request received
|
||||
*
|
||||
*/
|
||||
void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
|
||||
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
|
||||
{
|
||||
p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
|
||||
|
||||
/*
|
||||
* This barrier is needed to make sure any change made to req before
|
||||
* the other thread wakes up will indeed be seen by the waiting side.
|
||||
*/
|
||||
smp_wmb();
|
||||
req->status = status;
|
||||
|
||||
wake_up(req->wq);
|
||||
p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
|
||||
}
|
||||
@ -655,16 +663,13 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
|
||||
if (IS_ERR(req))
|
||||
return PTR_ERR(req);
|
||||
|
||||
|
||||
/*
|
||||
* if we haven't received a response for oldreq,
|
||||
* remove it from the list
|
||||
*/
|
||||
if (oldreq->status == REQ_STATUS_FLSH) {
|
||||
spin_lock(&c->lock);
|
||||
list_del(&oldreq->req_list);
|
||||
spin_unlock(&c->lock);
|
||||
}
|
||||
if (oldreq->status == REQ_STATUS_SENT)
|
||||
if (c->trans_mod->cancelled)
|
||||
c->trans_mod->cancelled(c, oldreq);
|
||||
|
||||
p9_free_req(c, req);
|
||||
return 0;
|
||||
@ -751,6 +756,12 @@ again:
|
||||
err = wait_event_interruptible(*req->wq,
|
||||
req->status >= REQ_STATUS_RCVD);
|
||||
|
||||
/*
|
||||
* Make sure our req is coherent with regard to updates in other
|
||||
* threads - echoes to wmb() in the callback
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
if ((err == -ERESTARTSYS) && (c->status == Connected)
|
||||
&& (type == P9_TFLUSH)) {
|
||||
sigpending = 1;
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -193,6 +193,8 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
|
||||
if (!*p)
|
||||
continue;
|
||||
token = match_token(p, tokens, args);
|
||||
if (token == Opt_err)
|
||||
continue;
|
||||
r = match_int(&args[0], &option);
|
||||
if (r < 0) {
|
||||
p9_debug(P9_DEBUG_ERROR,
|
||||
@ -305,8 +307,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma,
|
||||
}
|
||||
|
||||
req->rc = c->rc;
|
||||
req->status = REQ_STATUS_RCVD;
|
||||
p9_client_cb(client, req);
|
||||
p9_client_cb(client, req, REQ_STATUS_RCVD);
|
||||
|
||||
return;
|
||||
|
||||
@ -511,6 +512,11 @@ dont_need_post_recv:
|
||||
goto send_error;
|
||||
}
|
||||
|
||||
/* Mark request as `sent' *before* we actually send it,
|
||||
* because doing if after could erase the REQ_STATUS_RCVD
|
||||
* status in case of a very fast reply.
|
||||
*/
|
||||
req->status = REQ_STATUS_SENT;
|
||||
err = ib_post_send(rdma->qp, &wr, &bad_wr);
|
||||
if (err)
|
||||
goto send_error;
|
||||
@ -520,6 +526,7 @@ dont_need_post_recv:
|
||||
|
||||
/* Handle errors that happened during or while preparing the send: */
|
||||
send_error:
|
||||
req->status = REQ_STATUS_ERROR;
|
||||
kfree(c);
|
||||
p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err);
|
||||
|
||||
@ -582,12 +589,24 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts)
|
||||
return rdma;
|
||||
}
|
||||
|
||||
/* its not clear to me we can do anything after send has been posted */
|
||||
static int rdma_cancel(struct p9_client *client, struct p9_req_t *req)
|
||||
{
|
||||
/* Nothing to do here.
|
||||
* We will take care of it (if we have to) in rdma_cancelled()
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A request has been fully flushed without a reply.
|
||||
* That means we have posted one buffer in excess.
|
||||
*/
|
||||
static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req)
|
||||
{
|
||||
struct p9_trans_rdma *rdma = client->trans;
|
||||
atomic_inc(&rdma->excess_rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* trans_create_rdma - Transport method for creating atransport instance
|
||||
* @client: client instance
|
||||
@ -721,6 +740,7 @@ static struct p9_trans_module p9_rdma_trans = {
|
||||
.close = rdma_close,
|
||||
.request = rdma_request,
|
||||
.cancel = rdma_cancel,
|
||||
.cancelled = rdma_cancelled,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,8 +164,7 @@ static void req_done(struct virtqueue *vq)
|
||||
p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc);
|
||||
p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
|
||||
req = p9_tag_lookup(chan->client, rc->tag);
|
||||
req->status = REQ_STATUS_RCVD;
|
||||
p9_client_cb(chan->client, req);
|
||||
p9_client_cb(chan->client, req, REQ_STATUS_RCVD);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user