1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *              An implementation of a loadable kernel mode driver providing
5  *              multiple kernel/user space bidirectional communications links.
6  *
7  *              Author:         Alan Cox <alan@cymru.net>
8  *
9  *              This program is free software; you can redistribute it and/or
10  *              modify it under the terms of the GNU General Public License
11  *              version 2 as published by the Free Software Foundation.
12  *
13  *              Adapted to become the Linux 2.0 Coda pseudo device
14  *              Peter  Braam  <braam@maths.ox.ac.uk>
15  *              Michael Callahan <mjc@emmy.smith.edu>
16  *
17  *              Changes for Linux 2.1
18  *              Copyright (c) 1997 Carnegie-Mellon University
19  *
20  *              Redone again for InterMezzo
21  *              Copyright (c) 1998 Peter J. Braam
22  *              Copyright (c) 2000 Mountain View Data, Inc.
23  *              Copyright (c) 2000 Tacitus Systems, Inc.
24  *              Copyright (c) 2001 Cluster File Systems, Inc.
25  *
26  */
27 
28 #include <linux/module.h>
29 #include <linux/errno.h>
30 #include <linux/kernel.h>
31 #include <linux/major.h>
32 #include <linux/sched.h>
33 #include <linux/lp.h>
34 #include <linux/slab.h>
35 #include <linux/ioport.h>
36 #include <linux/fcntl.h>
37 #include <linux/delay.h>
38 #include <linux/skbuff.h>
39 #include <linux/proc_fs.h>
40 #include <linux/vmalloc.h>
41 #include <linux/fs.h>
42 #include <linux/file.h>
43 #include <linux/poll.h>
44 #include <linux/init.h>
45 #include <linux/list.h>
46 #include <linux/devfs_fs_kernel.h>
47 #include <asm/io.h>
48 #include <asm/segment.h>
49 #include <asm/system.h>
50 #include <asm/poll.h>
51 #include <asm/uaccess.h>
52 #include <linux/miscdevice.h>
53 
54 #include <linux/intermezzo_fs.h>
55 #include <linux/intermezzo_psdev.h>
56 
57 
58 #ifdef PRESTO_DEVEL
59 int  presto_print_entry = 1;
60 int  presto_debug = 4095;
61 #else
62 int  presto_print_entry = 0;
63 int  presto_debug = 0;
64 #endif
65 
66 /* Like inode.c (presto_sym_iops), the initializer is just to prevent
67    izo_channels from appearing as a COMMON symbol (and therefore
68    interfering with other modules that use the same variable name). */
69 struct upc_channel izo_channels[MAX_CHANNEL] = {{0}};
70 
izo_psdev_get_free_channel(void)71 int izo_psdev_get_free_channel(void)
72 {
73         int i, result = -1;
74 
75         for (i = 0 ; i < MAX_CHANNEL ; i++ ) {
76                 if (list_empty(&(izo_channels[i].uc_cache_list))) {
77                     result = i;
78                     break;
79                 }
80         }
81         return result;
82 }
83 
84 
izo_psdev_setpid(int minor)85 int izo_psdev_setpid(int minor)
86 {
87         struct upc_channel *channel;
88         if (minor < 0 || minor >= MAX_CHANNEL) {
89                 return -EINVAL;
90         }
91 
92         channel = &(izo_channels[minor]);
93         /*
94          * This ioctl is performed by each Lento that starts up
95          * and wants to do further communication with presto.
96          */
97         CDEBUG(D_PSDEV, "Setting current pid to %d channel %d\n",
98                current->pid, minor);
99         channel->uc_pid = current->pid;
100         spin_lock(&channel->uc_lock);
101         if ( !list_empty(&channel->uc_processing) ) {
102                 struct list_head *lh;
103                 struct upc_req *req;
104                 CERROR("WARNING: setpid & processing not empty!\n");
105 		list_for_each(lh, &channel->uc_processing) {
106                         req = list_entry(lh, struct upc_req, rq_chain);
107                         /* freeing of req and data is done by the sleeper */
108                         wake_up(&req->rq_sleep);
109                 }
110         }
111         if ( !list_empty(&channel->uc_processing) ) {
112                 CERROR("BAD: FAILDED TO CLEAN PROCESSING LIST!\n");
113         }
114         spin_unlock(&channel->uc_lock);
115         EXIT;
116         return 0;
117 }
118 
izo_psdev_setchannel(struct file * file,int fd)119 int izo_psdev_setchannel(struct file *file, int fd)
120 {
121 
122         struct file *psdev_file = fget(fd);
123         struct presto_cache *cache = presto_get_cache(file->f_dentry->d_inode);
124 
125         if (!psdev_file) {
126                 CERROR("%s: no psdev_file!\n", __FUNCTION__);
127                 return -EINVAL;
128         }
129 
130         if (!cache) {
131                 CERROR("%s: no cache!\n", __FUNCTION__);
132                 fput(psdev_file);
133                 return -EINVAL;
134         }
135 
136         if (psdev_file->private_data) {
137                 CERROR("%s: channel already set!\n", __FUNCTION__);
138                 fput(psdev_file);
139                 return -EINVAL;
140         }
141 
142         psdev_file->private_data = cache->cache_psdev;
143         fput(psdev_file);
144         EXIT;
145         return 0;
146 }
147 
presto_lento_up(int minor)148 inline int presto_lento_up(int minor)
149 {
150         return izo_channels[minor].uc_pid;
151 }
152 
presto_psdev_poll(struct file * file,poll_table * wait)153 static unsigned int presto_psdev_poll(struct file *file, poll_table * wait)
154  {
155         struct upc_channel *channel = (struct upc_channel *)file->private_data;
156         unsigned int mask = POLLOUT | POLLWRNORM;
157 
158         /* ENTRY; this will flood you */
159         if ( ! channel ) {
160                 CERROR("%s: bad psdev file\n", __FUNCTION__);
161                 return -EBADF;
162         }
163 
164         poll_wait(file, &(channel->uc_waitq), wait);
165 
166         spin_lock(&channel->uc_lock);
167         if (!list_empty(&channel->uc_pending)) {
168                 CDEBUG(D_PSDEV, "Non-empty pending list.\n");
169                 mask |= POLLIN | POLLRDNORM;
170         }
171         spin_unlock(&channel->uc_lock);
172 
173         /* EXIT; will flood you */
174         return mask;
175 }
176 
177 /*
178  *      Receive a message written by Lento to the psdev
179  */
presto_psdev_write(struct file * file,const char * buf,size_t count,loff_t * off)180 static ssize_t presto_psdev_write(struct file *file, const char *buf,
181                                   size_t count, loff_t *off)
182 {
183         struct upc_channel *channel = (struct upc_channel *)file->private_data;
184         struct upc_req *req = NULL;
185         struct upc_req *tmp;
186         struct list_head *lh;
187         struct izo_upcall_resp hdr;
188         int error;
189 
190         if ( ! channel ) {
191                 CERROR("%s: bad psdev file\n", __FUNCTION__);
192                 return -EBADF;
193         }
194 
195         /* Peek at the opcode, uniquefier */
196         if ( count < sizeof(hdr) ) {
197               CERROR("presto_psdev_write: Lento didn't write full hdr.\n");
198                 return -EINVAL;
199         }
200 
201         error = copy_from_user(&hdr, buf, sizeof(hdr));
202         if ( error )
203                 return -EFAULT;
204 
205         CDEBUG(D_PSDEV, "(process,opc,uniq)=(%d,%d,%d)\n",
206                current->pid, hdr.opcode, hdr.unique);
207 
208         spin_lock(&channel->uc_lock);
209         /* Look for the message on the processing queue. */
210 	list_for_each(lh, &channel->uc_processing) {
211                 tmp = list_entry(lh, struct upc_req , rq_chain);
212                 if (tmp->rq_unique == hdr.unique) {
213                         req = tmp;
214                         /* unlink here: keeps search length minimal */
215                         list_del_init(&req->rq_chain);
216                         CDEBUG(D_PSDEV,"Eureka opc %d uniq %d!\n",
217                                hdr.opcode, hdr.unique);
218                         break;
219                 }
220         }
221         spin_unlock(&channel->uc_lock);
222         if (!req) {
223                 CERROR("psdev_write: msg (%d, %d) not found\n",
224                        hdr.opcode, hdr.unique);
225                 return(-ESRCH);
226         }
227 
228         /* move data into response buffer. */
229         if (req->rq_bufsize < count) {
230                 CERROR("psdev_write: too much cnt: %d, cnt: %d, "
231                        "opc: %d, uniq: %d.\n",
232                        req->rq_bufsize, count, hdr.opcode, hdr.unique);
233                 count = req->rq_bufsize; /* don't have more space! */
234         }
235         error = copy_from_user(req->rq_data, buf, count);
236         if ( error )
237                 return -EFAULT;
238 
239         /* adjust outsize: good upcalls can be aware of this */
240         req->rq_rep_size = count;
241         req->rq_flags |= REQ_WRITE;
242 
243         wake_up(&req->rq_sleep);
244         return(count);
245 }
246 
247 /*
248  *      Read a message from the kernel to Lento
249  */
presto_psdev_read(struct file * file,char * buf,size_t count,loff_t * off)250 static ssize_t presto_psdev_read(struct file * file, char * buf,
251                                  size_t count, loff_t *off)
252 {
253         struct upc_channel *channel = (struct upc_channel *)file->private_data;
254         struct upc_req *req;
255         int result = count;
256 
257         if ( ! channel ) {
258                 CERROR("%s: bad psdev file\n", __FUNCTION__);
259                 return -EBADF;
260         }
261 
262         spin_lock(&channel->uc_lock);
263         if (list_empty(&(channel->uc_pending))) {
264                 CDEBUG(D_UPCALL, "Empty pending list in read, not good\n");
265                 spin_unlock(&channel->uc_lock);
266                 return -EINVAL;
267         }
268         req = list_entry((channel->uc_pending.next), struct upc_req, rq_chain);
269         list_del(&(req->rq_chain));
270         if (! (req->rq_flags & REQ_ASYNC) ) {
271                 list_add(&(req->rq_chain), channel->uc_processing.prev);
272         }
273         spin_unlock(&channel->uc_lock);
274 
275         req->rq_flags |= REQ_READ;
276 
277         /* Move the input args into userspace */
278         CDEBUG(D_PSDEV, "\n");
279         if (req->rq_bufsize <= count) {
280                 result = req->rq_bufsize;
281         }
282 
283         if (count < req->rq_bufsize) {
284                 CERROR ("psdev_read: buffer too small, read %d of %d bytes\n",
285                         count, req->rq_bufsize);
286         }
287 
288         if ( copy_to_user(buf, req->rq_data, result) ) {
289                 BUG();
290                 return -EFAULT;
291         }
292 
293         /* If request was asynchronous don't enqueue, but free */
294         if (req->rq_flags & REQ_ASYNC) {
295                 CDEBUG(D_PSDEV, "psdev_read: async msg (%d, %d), result %d\n",
296                        req->rq_opcode, req->rq_unique, result);
297                 PRESTO_FREE(req->rq_data, req->rq_bufsize);
298                 PRESTO_FREE(req, sizeof(*req));
299                 return result;
300         }
301 
302         return result;
303 }
304 
305 
presto_psdev_open(struct inode * inode,struct file * file)306 static int presto_psdev_open(struct inode * inode, struct file * file)
307 {
308         ENTRY;
309 
310         file->private_data = NULL;
311 
312         MOD_INC_USE_COUNT;
313 
314         CDEBUG(D_PSDEV, "Psdev_open: caller: %d, flags: %d\n", current->pid, file->f_flags);
315 
316         EXIT;
317         return 0;
318 }
319 
320 
321 
presto_psdev_release(struct inode * inode,struct file * file)322 static int presto_psdev_release(struct inode * inode, struct file * file)
323 {
324         struct upc_channel *channel = (struct upc_channel *)file->private_data;
325         struct upc_req *req;
326         struct list_head *lh;
327         ENTRY;
328 
329         if ( ! channel ) {
330                 CERROR("%s: bad psdev file\n", __FUNCTION__);
331                 return -EBADF;
332         }
333 
334         MOD_DEC_USE_COUNT;
335         CDEBUG(D_PSDEV, "Lento: pid %d\n", current->pid);
336         channel->uc_pid = 0;
337 
338         /* Wake up clients so they can return. */
339         CDEBUG(D_PSDEV, "Wake up clients sleeping for pending.\n");
340         spin_lock(&channel->uc_lock);
341 	list_for_each(lh, &channel->uc_pending) {
342                 req = list_entry(lh, struct upc_req, rq_chain);
343 
344                 /* Async requests stay around for a new lento */
345                 if (req->rq_flags & REQ_ASYNC) {
346                         continue;
347                 }
348                 /* the sleeper will free the req and data */
349                 req->rq_flags |= REQ_DEAD;
350                 wake_up(&req->rq_sleep);
351         }
352 
353         CDEBUG(D_PSDEV, "Wake up clients sleeping for processing\n");
354 	list_for_each(lh, &channel->uc_processing) {
355                 req = list_entry(lh, struct upc_req, rq_chain);
356                 /* freeing of req and data is done by the sleeper */
357                 req->rq_flags |= REQ_DEAD;
358                 wake_up(&req->rq_sleep);
359         }
360         spin_unlock(&channel->uc_lock);
361         CDEBUG(D_PSDEV, "Done.\n");
362 
363         EXIT;
364         return 0;
365 }
366 
367 static struct file_operations presto_psdev_fops = {
368         .read    = presto_psdev_read,
369         .write   = presto_psdev_write,
370         .poll    = presto_psdev_poll,
371         .open    = presto_psdev_open,
372         .release = presto_psdev_release
373 };
374 
375 /* modules setup */
376 static struct miscdevice intermezzo_psdev = {
377         INTERMEZZO_MINOR,
378         "intermezzo",
379         &presto_psdev_fops
380 };
381 
presto_psdev_init(void)382 int  presto_psdev_init(void)
383 {
384         int i;
385         int err;
386 
387         if ( (err = misc_register(&intermezzo_psdev)) ) {
388                 CERROR("%s: cannot register %d err %d\n",
389                        __FUNCTION__, INTERMEZZO_MINOR, err);
390                 return -EIO;
391         }
392 
393         memset(&izo_channels, 0, sizeof(izo_channels));
394         for ( i = 0 ; i < MAX_CHANNEL ; i++ ) {
395                 struct upc_channel *channel = &(izo_channels[i]);
396                 INIT_LIST_HEAD(&channel->uc_pending);
397                 INIT_LIST_HEAD(&channel->uc_processing);
398                 INIT_LIST_HEAD(&channel->uc_cache_list);
399                 init_waitqueue_head(&channel->uc_waitq);
400                 channel->uc_lock = SPIN_LOCK_UNLOCKED;
401                 channel->uc_hard = 0;
402                 channel->uc_no_filter = 0;
403                 channel->uc_no_journal = 0;
404                 channel->uc_no_upcall = 0;
405                 channel->uc_timeout = 30;
406                 channel->uc_errorval = 0;
407                 channel->uc_minor = i;
408         }
409         return 0;
410 }
411 
presto_psdev_cleanup(void)412 void presto_psdev_cleanup(void)
413 {
414         int i;
415 
416         misc_deregister(&intermezzo_psdev);
417 
418         for ( i = 0 ; i < MAX_CHANNEL ; i++ ) {
419                 struct upc_channel *channel = &(izo_channels[i]);
420                 struct list_head *lh, *next;
421 
422                 spin_lock(&channel->uc_lock);
423                 if ( ! list_empty(&channel->uc_pending)) {
424                         CERROR("Weird, tell Peter: module cleanup and pending list not empty dev %d\n", i);
425                 }
426                 if ( ! list_empty(&channel->uc_processing)) {
427                         CERROR("Weird, tell Peter: module cleanup and processing list not empty dev %d\n", i);
428                 }
429                 if ( ! list_empty(&channel->uc_cache_list)) {
430                         CERROR("Weird, tell Peter: module cleanup and cache listnot empty dev %d\n", i);
431                 }
432 		list_for_each_safe(lh, next, &channel->uc_pending) {
433                         struct upc_req *req;
434 
435                         req = list_entry(lh, struct upc_req, rq_chain);
436                         if ( req->rq_flags & REQ_ASYNC ) {
437                                 list_del(&(req->rq_chain));
438                                 CDEBUG(D_UPCALL, "free pending upcall type %d\n",
439                                        req->rq_opcode);
440                                 PRESTO_FREE(req->rq_data, req->rq_bufsize);
441                                 PRESTO_FREE(req, sizeof(struct upc_req));
442                         } else {
443                                 req->rq_flags |= REQ_DEAD;
444                                 wake_up(&req->rq_sleep);
445                         }
446                 }
447 		list_for_each(lh, &channel->uc_processing) {
448                         struct upc_req *req;
449                         req = list_entry(lh, struct upc_req, rq_chain);
450                         list_del(&(req->rq_chain));
451                         req->rq_flags |= REQ_DEAD;
452                         wake_up(&req->rq_sleep);
453                 }
454                 spin_unlock(&channel->uc_lock);
455         }
456 }
457 
458 /*
459  * lento_upcall and lento_downcall routines
460  */
lento_waitfor_upcall(struct upc_channel * channel,struct upc_req * req,int minor)461 static inline unsigned long lento_waitfor_upcall
462             (struct upc_channel *channel, struct upc_req *req, int minor)
463 {
464         DECLARE_WAITQUEUE(wait, current);
465         unsigned long posttime;
466 
467         req->rq_posttime = posttime = jiffies;
468 
469         add_wait_queue(&req->rq_sleep, &wait);
470         for (;;) {
471                 if ( izo_channels[minor].uc_hard == 0 )
472                         set_current_state(TASK_INTERRUPTIBLE);
473                 else
474                         set_current_state(TASK_UNINTERRUPTIBLE);
475 
476                 /* got a reply */
477                 if ( req->rq_flags & (REQ_WRITE | REQ_DEAD) )
478                         break;
479 
480                 /* these cases only apply when TASK_INTERRUPTIBLE */
481                 if ( !izo_channels[minor].uc_hard && signal_pending(current) ) {
482                         /* if this process really wants to die, let it go */
483                         if (sigismember(&(current->pending.signal), SIGKILL)||
484                             sigismember(&(current->pending.signal), SIGINT) )
485                                 break;
486                         /* signal is present: after timeout always return
487                            really smart idea, probably useless ... */
488                         if ( time_after(jiffies, req->rq_posttime +
489                              izo_channels[minor].uc_timeout * HZ) )
490                                 break;
491                 }
492                 schedule();
493         }
494 
495         spin_lock(&channel->uc_lock);
496         list_del_init(&req->rq_chain);
497         spin_unlock(&channel->uc_lock);
498         remove_wait_queue(&req->rq_sleep, &wait);
499         set_current_state(TASK_RUNNING);
500 
501         CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n",
502                posttime, jiffies-posttime);
503         return  (jiffies - posttime);
504 }
505 
506 /*
507  * lento_upcall will return an error in the case of
508  * failed communication with Lento _or_ will peek at Lento
509  * reply and return Lento's error.
510  *
511  * As lento has 2 types of errors, normal errors (positive) and internal
512  * errors (negative), normal errors are negated, while internal errors
513  * are all mapped to -EINTR, while showing a nice warning message. (jh)
514  *
515  * lento_upcall will always free buffer, either directly, when an upcall
516  * is read (in presto_psdev_read), when the filesystem is unmounted, or
517  * when the module is unloaded.
518  */
izo_upc_upcall(int minor,int * size,struct izo_upcall_hdr * buffer,int async)519 int izo_upc_upcall(int minor, int *size, struct izo_upcall_hdr *buffer,
520                    int async)
521 {
522         unsigned long runtime;
523         struct upc_channel *channel;
524         struct izo_upcall_resp *out;
525         struct upc_req *req;
526         int error = 0;
527 
528         ENTRY;
529         channel = &(izo_channels[minor]);
530 
531         if (channel->uc_no_upcall) {
532                 EXIT;
533                 goto exit_buf;
534         }
535         if (!channel->uc_pid && !async) {
536                 EXIT;
537                 error = -ENXIO;
538                 goto exit_buf;
539         }
540 
541         /* Format the request message. */
542         PRESTO_ALLOC(req, sizeof(struct upc_req));
543         if ( !req ) {
544                 EXIT;
545                 error = -ENOMEM;
546                 goto exit_buf;
547         }
548         req->rq_data = (void *)buffer;
549         req->rq_flags = 0;
550         req->rq_bufsize = *size;
551         req->rq_rep_size = 0;
552         req->rq_opcode = buffer->u_opc;
553         req->rq_unique = ++channel->uc_seq;
554         init_waitqueue_head(&req->rq_sleep);
555 
556         /* Fill in the common input args. */
557         buffer->u_uniq = req->rq_unique;
558         buffer->u_async = async;
559 
560         /* Remove potential datarace possibility*/
561         if ( async )
562                 req->rq_flags = REQ_ASYNC;
563 
564         spin_lock(&channel->uc_lock);
565         /* Append msg to pending queue and poke Lento. */
566         list_add(&req->rq_chain, channel->uc_pending.prev);
567         spin_unlock(&channel->uc_lock);
568         CDEBUG(D_UPCALL,
569                "Proc %d waking Lento %d for(opc,uniq) =(%d,%d) msg at %p.\n",
570                current->pid, channel->uc_pid, req->rq_opcode,
571                req->rq_unique, req);
572         wake_up_interruptible(&channel->uc_waitq);
573 
574         if ( async ) {
575                 /* req, rq_data are freed in presto_psdev_read for async */
576                 /* req->rq_flags = REQ_ASYNC;*/
577                 EXIT;
578                 return 0;
579         }
580 
581         /* We can be interrupted while we wait for Lento to process
582          * our request.  If the interrupt occurs before Lento has read
583          * the request, we dequeue and return. If it occurs after the
584          * read but before the reply, we dequeue, send a signal
585          * message, and return. If it occurs after the reply we ignore
586          * it. In no case do we want to restart the syscall.  If it
587          * was interrupted by a lento shutdown (psdev_close), return
588          * ENODEV.  */
589 
590         /* Go to sleep.  Wake up on signals only after the timeout. */
591         runtime = lento_waitfor_upcall(channel, req, minor);
592 
593         CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",
594                req->rq_opcode, jiffies - req->rq_posttime,
595                req->rq_unique, req->rq_rep_size);
596         CDEBUG(D_UPCALL,
597                "..process %d woken up by Lento for req at 0x%x, data at %x\n",
598                current->pid, (int)req, (int)req->rq_data);
599 
600         if (channel->uc_pid) {      /* i.e. Lento is still alive */
601           /* Op went through, interrupt or not we go on */
602             if (req->rq_flags & REQ_WRITE) {
603                     out = (struct izo_upcall_resp *)req->rq_data;
604                     /* here we map positive Lento errors to kernel errors */
605                     if ( out->result < 0 ) {
606                             CERROR("Tell Peter: Lento returns negative error %d, for oc %d!\n",
607                                    out->result, out->opcode);
608                           out->result = EINVAL;
609                     }
610                     error = -out->result;
611                     CDEBUG(D_UPCALL, "upcall: (u,o,r) (%d, %d, %d) out at %p\n",
612                            out->unique, out->opcode, out->result, out);
613                     *size = req->rq_rep_size;
614                     EXIT;
615                     goto exit_req;
616             }
617             /* Interrupted before lento read it. */
618             if ( !(req->rq_flags & REQ_READ) && signal_pending(current)) {
619                     CDEBUG(D_UPCALL,
620                            "Interrupt before read: (op,un)=(%d,%d), flags %x\n",
621                            req->rq_opcode, req->rq_unique, req->rq_flags);
622                     /* perhaps the best way to convince the app to give up? */
623                     error = -EINTR;
624                     EXIT;
625                     goto exit_req;
626             }
627 
628             /* interrupted after Lento did its read, send signal */
629             if ( (req->rq_flags & REQ_READ) && signal_pending(current) ) {
630                     CDEBUG(D_UPCALL,"Interrupt after read: op = %d.%d, flags = %x\n",
631                            req->rq_opcode, req->rq_unique, req->rq_flags);
632 
633                     error = -EINTR;
634             } else {
635                   CERROR("Lento: Strange interruption - tell Peter.\n");
636                     error = -EINTR;
637             }
638         } else {        /* If lento died i.e. !UC_OPEN(channel) */
639                 CERROR("lento_upcall: Lento dead on (op,un) (%d.%d) flags %d\n",
640                        req->rq_opcode, req->rq_unique, req->rq_flags);
641                 error = -ENODEV;
642         }
643 
644 exit_req:
645         PRESTO_FREE(req, sizeof(struct upc_req));
646 exit_buf:
647         PRESTO_FREE(buffer,*size);
648         return error;
649 }
650