aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/trans_virtio.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2008-10-13 19:45:23 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2008-10-17 12:04:42 -0400
commitfea511a644fb0fb938309c6ab286725ac31b87e2 (patch)
treefc9cdf7af5ad05435ea85fd52070a487930f824c /net/9p/trans_virtio.c
parent044c7768841f1ef39f951972d3c1e6537a535030 (diff)
9p: move request management to client code
The virtio transport uses a simplified request management system that I want to use for all transports. This patch adapts and moves the exisiting code for managing requests to the client common code. Later patches will apply these mechanisms to the other transports. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'net/9p/trans_virtio.c')
-rw-r--r--net/9p/trans_virtio.c136
1 files changed, 9 insertions, 127 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 72493f04a76d..36bce45e4e44 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -1,12 +1,10 @@
1/* 1/*
2 * The Guest 9p transport driver 2 * The Virtio 9p transport driver
3 * 3 *
4 * This is a block based transport driver based on the lguest block driver 4 * This is a block based transport driver based on the lguest block driver
5 * code. 5 * code.
6 * 6 *
7 */ 7 * Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation
8/*
9 * Copyright (C) 2007 Eric Van Hensbergen, IBM Corporation
10 * 8 *
11 * Based on virtio console driver 9 * Based on virtio console driver
12 * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation 10 * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation
@@ -54,49 +52,6 @@ static DEFINE_MUTEX(virtio_9p_lock);
54/* global which tracks highest initialized channel */ 52/* global which tracks highest initialized channel */
55static int chan_index; 53static int chan_index;
56 54
57#define P9_INIT_MAXTAG 16
58
59/**
60 * enum p9_req_status_t - virtio request status
61 * @REQ_STATUS_IDLE: request slot unused
62 * @REQ_STATUS_SENT: request sent to server
63 * @REQ_STATUS_RCVD: response received from server
64 * @REQ_STATUS_FLSH: request has been flushed
65 *
66 * The @REQ_STATUS_IDLE state is used to mark a request slot as unused
67 * but use is actually tracked by the idpool structure which handles tag
68 * id allocation.
69 *
70 */
71
72enum p9_req_status_t {
73 REQ_STATUS_IDLE,
74 REQ_STATUS_SENT,
75 REQ_STATUS_RCVD,
76 REQ_STATUS_FLSH,
77};
78
79/**
80 * struct p9_req_t - virtio request slots
81 * @status: status of this request slot
82 * @wq: wait_queue for the client to block on for this request
83 *
84 * The virtio transport uses an array to track outstanding requests
85 * instead of a list. While this may incurr overhead during initial
86 * allocation or expansion, it makes request lookup much easier as the
87 * tag id is a index into an array. (We use tag+1 so that we can accomodate
88 * the -1 tag for the T_VERSION request).
89 * This also has the nice effect of only having to allocate wait_queues
90 * once, instead of constantly allocating and freeing them. Its possible
91 * other resources could benefit from this scheme as well.
92 *
93 */
94
95struct p9_req_t {
96 int status;
97 wait_queue_head_t *wq;
98};
99
100/** 55/**
101 * struct virtio_chan - per-instance transport information 56 * struct virtio_chan - per-instance transport information
102 * @initialized: whether the channel is initialized 57 * @initialized: whether the channel is initialized
@@ -121,67 +76,14 @@ static struct virtio_chan {
121 76
122 spinlock_t lock; 77 spinlock_t lock;
123 78
79 struct p9_client *client;
124 struct virtio_device *vdev; 80 struct virtio_device *vdev;
125 struct virtqueue *vq; 81 struct virtqueue *vq;
126 82
127 struct p9_idpool *tagpool;
128 struct p9_req_t *reqs;
129 int max_tag;
130
131 /* Scatterlist: can be too big for stack. */ 83 /* Scatterlist: can be too big for stack. */
132 struct scatterlist sg[VIRTQUEUE_NUM]; 84 struct scatterlist sg[VIRTQUEUE_NUM];
133} channels[MAX_9P_CHAN]; 85} channels[MAX_9P_CHAN];
134 86
135/**
136 * p9_lookup_tag - Lookup requests by tag
137 * @c: virtio channel to lookup tag within
138 * @tag: numeric id for transaction
139 *
140 * this is a simple array lookup, but will grow the
141 * request_slots as necessary to accomodate transaction
142 * ids which did not previously have a slot.
143 *
144 * Bugs: there is currently no upper limit on request slots set
145 * here, but that should be constrained by the id accounting.
146 */
147
148static struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag)
149{
150 /* This looks up the original request by tag so we know which
151 * buffer to read the data into */
152 tag++;
153
154 while (tag >= c->max_tag) {
155 int old_max = c->max_tag;
156 int count;
157
158 if (c->max_tag)
159 c->max_tag *= 2;
160 else
161 c->max_tag = P9_INIT_MAXTAG;
162
163 c->reqs = krealloc(c->reqs, sizeof(struct p9_req_t)*c->max_tag,
164 GFP_ATOMIC);
165 if (!c->reqs) {
166 printk(KERN_ERR "Couldn't grow tag array\n");
167 BUG();
168 }
169 for (count = old_max; count < c->max_tag; count++) {
170 c->reqs[count].status = REQ_STATUS_IDLE;
171 c->reqs[count].wq = kmalloc(sizeof(wait_queue_head_t),
172 GFP_ATOMIC);
173 if (!c->reqs[count].wq) {
174 printk(KERN_ERR "Couldn't grow tag array\n");
175 BUG();
176 }
177 init_waitqueue_head(c->reqs[count].wq);
178 }
179 }
180
181 return &c->reqs[tag];
182}
183
184
185/* How many bytes left in this page. */ 87/* How many bytes left in this page. */
186static unsigned int rest_of_page(void *data) 88static unsigned int rest_of_page(void *data)
187{ 89{
@@ -200,22 +102,10 @@ static unsigned int rest_of_page(void *data)
200static void p9_virtio_close(struct p9_client *client) 102static void p9_virtio_close(struct p9_client *client)
201{ 103{
202 struct virtio_chan *chan = client->trans; 104 struct virtio_chan *chan = client->trans;
203 int count;
204 unsigned long flags;
205
206 spin_lock_irqsave(&chan->lock, flags);
207 p9_idpool_destroy(chan->tagpool);
208 for (count = 0; count < chan->max_tag; count++)
209 kfree(chan->reqs[count].wq);
210 kfree(chan->reqs);
211 chan->max_tag = 0;
212 spin_unlock_irqrestore(&chan->lock, flags);
213 105
214 mutex_lock(&virtio_9p_lock); 106 mutex_lock(&virtio_9p_lock);
215 chan->inuse = false; 107 chan->inuse = false;
216 mutex_unlock(&virtio_9p_lock); 108 mutex_unlock(&virtio_9p_lock);
217
218 client->trans = NULL;
219} 109}
220 110
221/** 111/**
@@ -241,7 +131,7 @@ static void req_done(struct virtqueue *vq)
241 131
242 spin_lock_irqsave(&chan->lock, flags); 132 spin_lock_irqsave(&chan->lock, flags);
243 while ((rc = chan->vq->vq_ops->get_buf(chan->vq, &len)) != NULL) { 133 while ((rc = chan->vq->vq_ops->get_buf(chan->vq, &len)) != NULL) {
244 req = p9_lookup_tag(chan, rc->tag); 134 req = p9_tag_lookup(chan->client, rc->tag);
245 req->status = REQ_STATUS_RCVD; 135 req->status = REQ_STATUS_RCVD;
246 wake_up(req->wq); 136 wake_up(req->wq);
247 } 137 }
@@ -311,13 +201,13 @@ p9_virtio_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
311 201
312 n = P9_NOTAG; 202 n = P9_NOTAG;
313 if (tc->id != P9_TVERSION) { 203 if (tc->id != P9_TVERSION) {
314 n = p9_idpool_get(chan->tagpool); 204 n = p9_idpool_get(c->tagpool);
315 if (n < 0) 205 if (n < 0)
316 return -ENOMEM; 206 return -ENOMEM;
317 } 207 }
318 208
319 spin_lock_irqsave(&chan->lock, flags); 209 spin_lock_irqsave(&chan->lock, flags);
320 req = p9_lookup_tag(chan, n); 210 req = p9_tag_alloc(c, n);
321 spin_unlock_irqrestore(&chan->lock, flags); 211 spin_unlock_irqrestore(&chan->lock, flags);
322 212
323 p9_set_tag(tc, n); 213 p9_set_tag(tc, n);
@@ -357,8 +247,8 @@ p9_virtio_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
357 } 247 }
358#endif 248#endif
359 249
360 if (n != P9_NOTAG && p9_idpool_check(n, chan->tagpool)) 250 if (n != P9_NOTAG && p9_idpool_check(n, c->tagpool))
361 p9_idpool_put(n, chan->tagpool); 251 p9_idpool_put(n, c->tagpool);
362 252
363 req->status = REQ_STATUS_IDLE; 253 req->status = REQ_STATUS_IDLE;
364 254
@@ -463,16 +353,8 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
463 return -ENODEV; 353 return -ENODEV;
464 } 354 }
465 355
466 chan->tagpool = p9_idpool_create();
467 if (IS_ERR(chan->tagpool)) {
468 printk(KERN_ERR "9p: couldn't allocate tagpool\n");
469 return -ENOMEM;
470 }
471 p9_idpool_get(chan->tagpool); /* reserve tag 0 */
472 chan->max_tag = 0;
473 chan->reqs = NULL;
474
475 client->trans = (void *)chan; 356 client->trans = (void *)chan;
357 chan->client = client;
476 358
477 return 0; 359 return 0;
478} 360}