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>
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
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;
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
00209 return -ERESTARTSYS;
00210 }
00211
00212 if (signal_pending(current)) {
00213
00214 return -ERESTARTSYS;
00215 }
00216
00217 if (down_interruptible(&fsc_sem)) {
00218
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
00247 return -ERESTARTSYS;
00248 }
00249
00250 if (signal_pending(current)) {
00251
00252 return -ERESTARTSYS;
00253 }
00254
00255 if (down_interruptible(&fsc_sem)) {
00256
00257 return -ERESTARTSYS;
00258 }
00259
00260 }
00261 return 0;
00262 }
00263
00264
00265
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)) {
00304 PDEBUG("fsc_query returning error on semaphore: -ERESTARTSYS\n");
00305 return -ERESTARTSYS;
00306 }
00307
00308 result = fsc_waitforempty_output();
00309
00310
00311 if (result) {
00312 PDEBUG("fsc_query returning error from waitforempty_output - ERESTARTSYS: %d\n", result);
00313
00314 return result;
00315 }
00316
00317 if (out_count >= MAX_BUFFER_LENGTH) {
00318 up(&fsc_sem);
00319 return -EINVAL;
00320 }
00321
00322
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
00333 wake_up_interruptible(&fsc_output_buffer.deamon_queue);
00334
00335
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
00345 return result;
00346 }
00347
00348
00349 for (i = 0; i<fsc_input_buffer.length && i<in_count; i++) {
00350
00351 in_buf[i] = fsc_input_buffer.data[i];
00352 }
00353
00354
00355 response_len = fsc_input_buffer.length;
00356 in_buf[response_len] = '\0';
00357
00358 fsc_input_buffer.length = 0;
00359 up(&fsc_sem);
00360 PDEBUG("input buffer read, waking up sleeping deamon writer\n");
00361
00362
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
00392 if (down_interruptible(&fsc_sem)) {
00393 return -ERESTARTSYS;
00394 }
00395
00396
00397 while (fsc_input_buffer.length != 0) {
00398 up(&fsc_sem);
00399 PDEBUG("attemt for writing, buffer full, going to sleep\n");
00400
00401
00402 if (wait_event_interruptible(fsc_input_buffer.deamon_queue, fsc_input_buffer.length == 0)) {
00403
00404 return -ERESTARTSYS;
00405 }
00406
00407 if (down_interruptible(&fsc_sem)) {
00408
00409 return -ERESTARTSYS;
00410 }
00411
00412 }
00413
00414
00415
00416
00417 if (copy_from_user(fsc_input_buffer.data, buf, count + 1)) {
00418 up(&fsc_sem);
00419
00420 return -EFAULT;
00421 }
00422
00423
00424 fsc_input_buffer.length = count;
00425 up(&fsc_sem);
00426 PDEBUG("buffer full, waking up sleeping kernel reader\n");
00427
00428
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
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
00469 while (fsc_output_buffer.length == 0) {
00470 up(&fsc_sem);
00471 PDEBUG("attemt for reading, buffer empty, going to sleep\n");
00472
00473
00474 if (wait_event_interruptible(fsc_output_buffer.deamon_queue, fsc_output_buffer.length != 0)) {
00475
00476 return -ERESTARTSYS;
00477 }
00478
00479 if (down_interruptible(&fsc_sem)) {
00480
00481 return -ERESTARTSYS;
00482 }
00483
00484 }
00485
00486
00487
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
00497 if (copy_to_user(buf, fsc_output_buffer.data, fsc_output_buffer.length + 1)) {
00498 up(&fsc_sem);
00499
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
00509 PDEBUG("db request fetched from fsc_output_buffer: %s\n", fsc_output_buffer.data);
00510 return tmp_count;
00511 }
00512
00513