fsc_device.c

Go to the documentation of this file.
00001 
00024 #include <linux/init.h>
00025 #include <linux/kernel.h>
00026 #include <linux/module.h>
00027 #include <linux/version.h>
00028 #include <linux/fs.h>
00029 #include <linux/sched.h>
00030 #include <linux/statfs.h>
00031 #include <linux/mm.h>
00032 #include <asm/uaccess.h>
00033 #include <asm/errno.h>
00034 #include <linux/buffer_head.h>
00035 #include <linux/pagemap.h>      /* unlock_page */
00036 #include <linux/proc_fs.h>
00037 #include <asm/atomic.h>
00038 
00039 
00040 #include "fsc_debug.h"
00041 #include "fsc_device.h"
00042 
00043 
00045 struct buffer fsc_output_buffer;
00046 
00047 
00049 struct buffer fsc_input_buffer; 
00050 
00051 
00053 atomic_t fsc_available = ATOMIC_INIT(1);
00054 
00055 
00057 struct semaphore fsc_sem; 
00058 
00059 
00061 struct mutex query_mutex;
00062 
00063 
00065 int fsc_major = 0;
00066 
00067 
00069 module_param(fsc_major, int, S_IRUSR);
00070 
00071 
00072 /* char device functions declarations */
00073 ssize_t fsc_read(struct file *, char *, size_t, loff_t *);
00074 ssize_t fsc_write(struct file *, const char *, size_t, loff_t *);
00075 int fsc_release(struct inode *, struct file *);
00076 int fsc_open(struct inode *, struct file *);
00077 
00078 
00082 struct file_operations fsc_fops = {
00083   .read = fsc_read,        
00084   .write = fsc_write,      
00085   .open = fsc_open,        
00086   .release = fsc_release   
00087 };
00088 
00089 
00098 void fsc_init(void) {
00099     fsc_output_buffer.length = 0;
00100     fsc_input_buffer.length = 0;
00101     init_MUTEX(&fsc_sem);
00102     mutex_init(&query_mutex);
00103     init_waitqueue_head(&fsc_output_buffer.deamon_queue);
00104     init_waitqueue_head(&fsc_output_buffer.kernel_queue);
00105     init_waitqueue_head(&fsc_input_buffer.deamon_queue);
00106     init_waitqueue_head(&fsc_input_buffer.kernel_queue);
00107 }
00108 
00109 
00116 void fsc_fini(void) {
00117     mutex_destroy(&query_mutex);
00118 }
00119 
00120 
00137 int fsc_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data) {
00138                 
00139   *eof=1; /* No further reading after this info print */        
00140   return sprintf(buf, "FSC input buffer: %s\n"
00141                      "FSC input buffer length declared: %d\n"
00142                      "FSC output buffer: %s\n"
00143                      "FSC output buffer length declared: %d\n",
00144                       fsc_input_buffer.data, fsc_input_buffer.length, 
00145                       fsc_output_buffer.data, fsc_output_buffer.length);
00146 }
00147 
00148  
00159 int fsc_open(struct inode *inode, struct file *filp) {
00160         PDEBUG("fsc_open(%p, %p), major=%d minor=%d\n", inode, filp, 
00161                         MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
00162         if (! atomic_dec_and_test (&fsc_available)) {
00163                 atomic_inc(&fsc_available);
00164                 return -EBUSY;
00165         }
00166         
00167         try_module_get(THIS_MODULE);
00168         return 0;
00169 }
00170 
00171 
00180 int fsc_release(struct inode *inode, struct file *filp) {
00181         atomic_inc(&fsc_available);
00182         PDEBUG("fsc_release(%p, %p), major=%d minor=%d\n", inode, filp, 
00183                         MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
00184         module_put(THIS_MODULE);
00185         return 0;
00186 }
00187 
00188 
00203 int fsc_waitforempty_output(void) {
00204         while (fsc_output_buffer.length != 0) {
00205                 up(&fsc_sem);
00206                 PDEBUG("fsc_waitforempty_output (len=%d) - going to sleep\n", fsc_output_buffer.length);
00207                 if (wait_event_interruptible(fsc_output_buffer.kernel_queue, fsc_output_buffer.length == 0)) {
00208                         /* signal: tell the fs layer to handle it */
00209                         return -ERESTARTSYS; 
00210                 }
00211                 
00212                 if (signal_pending(current)) {
00213                         /* signal: tell the fs layer to handle it */
00214                         return -ERESTARTSYS; 
00215                 }
00216                 
00217                 if (down_interruptible(&fsc_sem)) {
00218                         /* semaphore: char device in use */
00219                         return -ERESTARTSYS; 
00220                 }
00221                 
00222         }
00223         return 0;
00224 }
00225 
00226 
00241 int fsc_waitforfull_input(void) {
00242         while (fsc_input_buffer.length == 0) {
00243                 up(&fsc_sem);
00244                 PDEBUG("fsc_waitforfull_input (len=%d) - going to sleep\n", fsc_input_buffer.length);
00245                 if (wait_event_interruptible(fsc_input_buffer.kernel_queue, fsc_input_buffer.length != 0)) {
00246                         /* signal: tell the fs layer to handle it */
00247                         return -ERESTARTSYS; 
00248                 }
00249                 
00250                 if (signal_pending(current)) {
00251                         /* signal: tell the fs layer to handle it */
00252                         return -ERESTARTSYS; 
00253                 }
00254                 
00255                 if (down_interruptible(&fsc_sem)) {
00256                         /* semaphore: char device in use */
00257                         return -ERESTARTSYS; 
00258                 }
00259                 
00260         }
00261         return 0;
00262 }
00263 
00264 
00265 /* forward declaration */
00266 int __fsc_query__(const char*, const int, char*, int);
00267 
00268 
00270 int fsc_query(const char * out_buf, const int out_count, char* in_buf, int in_count) {
00271   static int result;
00272   mutex_lock(&query_mutex);
00273   result = __fsc_query__(out_buf, out_count, in_buf, in_count);
00274   mutex_unlock(&query_mutex);
00275   return result;
00276 }
00277 
00298 int __fsc_query__(const char * out_buf, const int out_count, char* in_buf, int in_count) {
00299         int i;
00300         int result;
00301         int response_len;
00302         PDEBUG("fsc_query(%s, %d, %s, %d)\n", out_buf, out_count, in_buf, in_count);
00303         if (down_interruptible(&fsc_sem)) { /* lock the char device internals */
00304                 PDEBUG("fsc_query returning error on semaphore: -ERESTARTSYS\n");
00305                 return -ERESTARTSYS;
00306         }
00307         
00308         result = fsc_waitforempty_output();
00309         
00310         /* if error occurs, return it */
00311         if (result) {
00312                 PDEBUG("fsc_query returning error from waitforempty_output - ERESTARTSYS: %d\n", result);
00313                 /* up called by waitforempty_output() */
00314                 return result; 
00315         }
00316         
00317         if (out_count >= MAX_BUFFER_LENGTH) {   /* just for case */
00318                 up(&fsc_sem);
00319                 return -EINVAL;
00320         }
00321         
00322         /* copy the out_buffer to output_buffer */
00323         for (i=0; i<out_count; i++) {  
00324                 fsc_output_buffer.data[i] = out_buf[i];
00325         }
00326         
00327         fsc_output_buffer.data[out_count] = '\0';
00328         fsc_output_buffer.length = out_count; 
00329         up(&fsc_sem);
00330         PDEBUG("output buffer filled, waking up sleeping deamon reader\n");
00331         
00332         /* the buffer is full, wake up sleaping reader - FS Deamon */
00333         wake_up_interruptible(&fsc_output_buffer.deamon_queue); 
00334 
00335         /* hold the semaphore lock */
00336         if (down_interruptible(&fsc_sem)) { 
00337                 PDEBUG("fsc_query returning error on semaphore: -ERESTARTSYS\n");
00338                 return -ERESTARTSYS;
00339         }
00340         
00341         result = fsc_waitforfull_input();
00342         if (result) {
00343                 PDEBUG("fsc_query returning error from waitforempty_output - ERESTARTSYS: %d\n", result);
00344                 /* up called by waitforempty_output() */
00345                 return result; 
00346         }
00347         
00348         /* copy the input buffer to in_buf */
00349         for (i = 0; i<fsc_input_buffer.length && i<in_count; i++) {
00350                 /* the leading zero isn't copied, for writing to log add it later */ 
00351                 in_buf[i] = fsc_input_buffer.data[i];   
00352         }
00353         
00354         /* storing number of recieved chars in the response */
00355         response_len = fsc_input_buffer.length; 
00356         in_buf[response_len] = '\0';
00357         /* declare input buffer as empty, for the deamon can fill it again */
00358         fsc_input_buffer.length = 0; 
00359         up(&fsc_sem); 
00360         PDEBUG("input buffer read, waking up sleeping deamon writer\n");
00361         
00362         /* the buffer is empty, the FS Deamon writer can be woken up again. */
00363         wake_up_interruptible(&fsc_input_buffer.deamon_queue); 
00364         return response_len;
00365 }
00366 
00367 
00385 ssize_t fsc_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) {
00386   PDEBUG("fsc_write(%p, %p,  %d, %lld)\n", filp, buf, (int) count, *f_pos);
00387   if (count > MAX_BUFFER_LENGTH) {
00388         return -EINVAL;
00389   }
00390   
00391   /* lock the char device internals */
00392   if (down_interruptible(&fsc_sem)) { 
00393     return -ERESTARTSYS;
00394   }
00395   
00396   /* wait for empty input buffer */
00397   while (fsc_input_buffer.length != 0) { 
00398     up(&fsc_sem); 
00399     PDEBUG("attemt for writing, buffer full, going to sleep\n");
00400     
00401     /* the user space deamon waits allways in deamon_queue, kernel has got it's own */
00402     if (wait_event_interruptible(fsc_input_buffer.deamon_queue, fsc_input_buffer.length == 0)) {
00403       /* signal: tell the fs layer to handle it */      
00404       return -ERESTARTSYS; 
00405     }
00406     
00407     if (down_interruptible(&fsc_sem)) {
00408       /* semaphore: char device internals in use */
00409       return -ERESTARTSYS; 
00410     }
00411     
00412   }
00413   
00414   /* buffer is clear, let's write something
00415    * copy +1 byte for trailing zero - added for debugging printouts 
00416    */
00417   if (copy_from_user(fsc_input_buffer.data, buf, count + 1)) {  
00418         up(&fsc_sem); 
00419         /* on error release the lock first */
00420         return -EFAULT;
00421   }
00422   
00423   /* save number of written characters */
00424   fsc_input_buffer.length = count; 
00425   up(&fsc_sem);
00426   PDEBUG("buffer full, waking up sleeping kernel reader\n");
00427   
00428   /* the kernel can now read the content of input_buffer */
00429   wake_up_interruptible(&fsc_input_buffer.kernel_queue); 
00430   fsc_input_buffer.data[fsc_input_buffer.length] = '\0';
00431   PDEBUG("db response stored in fsc_input_buffer: '%s'\n", fsc_input_buffer.data);
00432   
00433   /* allways all chars written */ 
00434   return count; 
00435 }
00436 
00437 
00460 ssize_t fsc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) {
00461   int tmp_count;
00462 
00463   PDEBUG("fsc_read(%p, %p, %d, %lld)\n", filp, buf, (int) count, *f_pos);
00464   if (down_interruptible(&fsc_sem)) {
00465           return -ERESTARTSYS;
00466   }
00467   
00468   /* wait for non-emtpy output buffer */
00469   while (fsc_output_buffer.length == 0) { 
00470     up(&fsc_sem);
00471     PDEBUG("attemt for reading, buffer empty, going to sleep\n");
00472     
00473     /* the user space deamon waits allways in deamon_queue, kernel has got it's own */
00474     if (wait_event_interruptible(fsc_output_buffer.deamon_queue, fsc_output_buffer.length != 0)) {
00475       /* signal: tell the fs layer to handle it */
00476       return -ERESTARTSYS; 
00477     }
00478     
00479     if (down_interruptible(&fsc_sem)) {
00480       /* otherewise loop, but first reacquire the lock */
00481       return -ERESTARTSYS;
00482     }
00483     
00484   }
00485   
00486   /* User wants less data then present. It generates error, 
00487    * becouse fsc dont support countinuous reads 
00488    */
00489   if (count < fsc_output_buffer.length) {       
00490         return -EINVAL;
00491   }
00492   
00493   tmp_count = fsc_output_buffer.length;
00494   fsc_output_buffer.data[fsc_output_buffer.length]='\0';
00495   
00496   /* copy +1 byte for trailing zero - added for debugging printouts */
00497   if (copy_to_user(buf, fsc_output_buffer.data, fsc_output_buffer.length + 1)) { 
00498         up(&fsc_sem); 
00499         /* on error release the lock first */
00500         return -EFAULT;
00501   }
00502   
00503   fsc_output_buffer.length = 0; 
00504   up(&fsc_sem);
00505   PDEBUG("buffer empty, waking up sleeping writers\n");
00506   wake_up_interruptible(&fsc_output_buffer.kernel_queue); 
00507   
00508   /* the kernel can now fill the output buffer with commands and data again */
00509   PDEBUG("db request fetched from fsc_output_buffer: %s\n", fsc_output_buffer.data); 
00510   return tmp_count;
00511 } 
00512 
00513 

Generated on Mon May 28 13:33:08 2007 for MYSQLFS by  doxygen 1.5.0