aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.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/client.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/client.c')
-rw-r--r--net/9p/client.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 712d4f336adc..867031934f75 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -120,6 +120,154 @@ static int parse_opts(char *opts, struct p9_client *clnt)
120 return ret; 120 return ret;
121} 121}
122 122
123/**
124 * p9_tag_alloc - lookup/allocate a request by tag
125 * @c: client session to lookup tag within
126 * @tag: numeric id for transaction
127 *
128 * this is a simple array lookup, but will grow the
129 * request_slots as necessary to accomodate transaction
130 * ids which did not previously have a slot.
131 *
132 * this code relies on the client spinlock to manage locks, its
133 * possible we should switch to something else, but I'd rather
134 * stick with something low-overhead for the common case.
135 *
136 */
137
138struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
139{
140 unsigned long flags;
141 int row, col;
142
143 /* This looks up the original request by tag so we know which
144 * buffer to read the data into */
145 tag++;
146
147 if (tag >= c->max_tag) {
148 spin_lock_irqsave(&c->lock, flags);
149 /* check again since original check was outside of lock */
150 while (tag >= c->max_tag) {
151 row = (tag / P9_ROW_MAXTAG);
152 c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
153 sizeof(struct p9_req_t), GFP_ATOMIC);
154
155 if (!c->reqs[row]) {
156 printk(KERN_ERR "Couldn't grow tag array\n");
157 BUG();
158 }
159 for (col = 0; col < P9_ROW_MAXTAG; col++) {
160 c->reqs[row][col].status = REQ_STATUS_IDLE;
161 c->reqs[row][col].flush_tag = P9_NOTAG;
162 c->reqs[row][col].wq = kmalloc(
163 sizeof(wait_queue_head_t), GFP_ATOMIC);
164 if (!c->reqs[row][col].wq) {
165 printk(KERN_ERR
166 "Couldn't grow tag array\n");
167 BUG();
168 }
169 init_waitqueue_head(c->reqs[row][col].wq);
170 }
171 c->max_tag += P9_ROW_MAXTAG;
172 }
173 spin_unlock_irqrestore(&c->lock, flags);
174 }
175 row = tag / P9_ROW_MAXTAG;
176 col = tag % P9_ROW_MAXTAG;
177
178 c->reqs[row][col].status = REQ_STATUS_ALLOC;
179 c->reqs[row][col].flush_tag = P9_NOTAG;
180
181 return &c->reqs[row][col];
182}
183EXPORT_SYMBOL(p9_tag_alloc);
184
185/**
186 * p9_tag_lookup - lookup a request by tag
187 * @c: client session to lookup tag within
188 * @tag: numeric id for transaction
189 *
190 */
191
192struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
193{
194 int row, col;
195
196 /* This looks up the original request by tag so we know which
197 * buffer to read the data into */
198 tag++;
199
200 BUG_ON(tag >= c->max_tag);
201
202 row = tag / P9_ROW_MAXTAG;
203 col = tag % P9_ROW_MAXTAG;
204
205 return &c->reqs[row][col];
206}
207EXPORT_SYMBOL(p9_tag_lookup);
208
209/**
210 * p9_tag_init - setup tags structure and contents
211 * @tags: tags structure from the client struct
212 *
213 * This initializes the tags structure for each client instance.
214 *
215 */
216
217static int p9_tag_init(struct p9_client *c)
218{
219 int err = 0;
220
221 c->tagpool = p9_idpool_create();
222 if (IS_ERR(c->tagpool)) {
223 err = PTR_ERR(c->tagpool);
224 c->tagpool = NULL;
225 goto error;
226 }
227
228 p9_idpool_get(c->tagpool); /* reserve tag 0 */
229
230 c->max_tag = 0;
231error:
232 return err;
233}
234
235/**
236 * p9_tag_cleanup - cleans up tags structure and reclaims resources
237 * @tags: tags structure from the client struct
238 *
239 * This frees resources associated with the tags structure
240 *
241 */
242static void p9_tag_cleanup(struct p9_client *c)
243{
244 int row, col;
245
246 /* check to insure all requests are idle */
247 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
248 for (col = 0; col < P9_ROW_MAXTAG; col++) {
249 if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
250 P9_DPRINTK(P9_DEBUG_MUX,
251 "Attempting to cleanup non-free tag %d,%d\n",
252 row, col);
253 /* TODO: delay execution of cleanup */
254 return;
255 }
256 }
257 }
258
259 if (c->tagpool)
260 p9_idpool_destroy(c->tagpool);
261
262 /* free requests associated with tags */
263 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
264 for (col = 0; col < P9_ROW_MAXTAG; col++)
265 kfree(c->reqs[row][col].wq);
266 kfree(c->reqs[row]);
267 }
268 c->max_tag = 0;
269}
270
123static struct p9_fid *p9_fid_create(struct p9_client *clnt) 271static struct p9_fid *p9_fid_create(struct p9_client *clnt)
124{ 272{
125 int err; 273 int err;
@@ -209,6 +357,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
209 goto error; 357 goto error;
210 } 358 }
211 359
360 p9_tag_init(clnt);
361
212 err = parse_opts(options, clnt); 362 err = parse_opts(options, clnt);
213 if (err < 0) 363 if (err < 0)
214 goto error; 364 goto error;
@@ -285,6 +435,8 @@ void p9_client_destroy(struct p9_client *clnt)
285 if (clnt->fidpool) 435 if (clnt->fidpool)
286 p9_idpool_destroy(clnt->fidpool); 436 p9_idpool_destroy(clnt->fidpool);
287 437
438 p9_tag_cleanup(clnt);
439
288 kfree(clnt); 440 kfree(clnt);
289} 441}
290EXPORT_SYMBOL(p9_client_destroy); 442EXPORT_SYMBOL(p9_client_destroy);