00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <linux/kernel.h>
00037 #include <linux/module.h>
00038 #include <linux/ioctl.h>
00039 #include <linux/proc_fs.h>
00040 #include <linux/fs.h>
00041
00042 #include "oq_kmod.h"
00043 #include "avl.h"
00044 #include <sim_if.h>
00045
00046
00048
00049
00050 struct oq_req_resp_list *req_resp_lists;
00051 EXPORT_SYMBOL(req_resp_lists);
00052
00053
00054 extern char oq_simulation_daemon[PATH_MAX];
00055 extern struct proc_dir_entry *oq_dir;
00056 extern struct oq_dev *oq_device;
00057
00058
00059 struct proc_dir_entry *oq_hosts;
00060 struct proc_dir_entry *oq_sensors;
00061
00062 struct knode {
00063 unsigned int id;
00064 };
00065
00066 struct ksensor {
00067 unsigned int node_id;
00068 unsigned int sensor_number;
00069 struct proc_dir_entry *proc_entry;
00070 struct sensor_stats sensor;
00071 };
00072
00073 struct avltree ksensors;
00074 struct avltree knodes;
00075
00076
00077 unsigned int simulation_on;
00078 unsigned long ksim_id;
00079 unsigned long ktime_dilation_ratio;
00080
00081 struct khost {
00082 struct list_head list;
00083 char name[MAX_NAME];
00084 } khosts;
00085
00086
00087
00088 static int sim_test;
00089 static struct oq_req_resp_list rr_lists;
00090
00091
00092
00093
00094
00095
00096
00097 #define META_NUM_TYPES 4
00098
00099 enum file_t {
00100 SIM_ID = 0, TIME = 1, ADD_HOST = 2, RM_HOST = 3,
00101 };
00102
00103 struct data_t {
00104 enum file_t file;
00105 } metadata[META_NUM_TYPES];
00106
00107
00108
00109
00110 static int read_base(char *page, char **start, off_t off,
00111 int count, int *eof, void *data)
00112 {
00113 int result = 0;
00114 enum file_t type = *((enum file_t *) data);
00115
00116 if (off > 0) {
00117 *eof = 1;
00118 return 0;
00119 }
00120
00121 switch (type) {
00122 case SIM_ID:
00123 result = sprintf(page, "%ld\n", ksim_id);
00124 break;
00125
00126 case TIME:
00127 result = sprintf(page, "%ld\n", ktime_dilation_ratio);
00128 break;
00129
00130 default:
00131 break;
00132 }
00133 return result;
00134 }
00135
00136
00137 static ssize_t write_base(struct file *filp, const char __user *buf,
00138 unsigned long len, void *data)
00139 {
00140 struct khost *tmp;
00141 struct list_head *pos, *q;
00142 char user_str[len + 1];
00143 enum file_t type = *((enum file_t *) data);
00144
00145 memset(user_str, '\0', len + 1);
00146
00147 if (copy_from_user(&user_str, buf, len))
00148 return -EFAULT;
00149
00150 switch (type) {
00151 case SIM_ID:
00152 ksim_id = simple_strtoul(user_str, NULL, 10);
00153 break;
00154
00155 case TIME:
00156 ktime_dilation_ratio =
00157 simple_strtoul(user_str, NULL, 10);
00158 break;
00159
00160 case ADD_HOST:
00161 tmp = (struct khost *)
00162 kmalloc(sizeof(struct khost), GFP_KERNEL);
00163 strncpy(tmp->name, user_str, len);
00164 list_add(&(tmp->list), &(khosts.list));
00165 create_proc_entry(tmp->name, 0666, oq_hosts);
00166 break;
00167
00168 case RM_HOST:
00169 list_for_each_safe(pos, q, &khosts.list) {
00170 tmp = list_entry(pos, struct khost, list);
00171 if (strncmp(tmp->name, user_str, len) == 0) {
00172 remove_proc_entry(tmp->name, oq_hosts);
00173 list_del(pos);
00174 kfree(tmp);
00175 }
00176 }
00177 break;
00178
00179 default:
00180 break;
00181 }
00182 return len;
00183 }
00184
00185
00186
00187
00188 static void initialize(struct ksensor *ksensor, unsigned int node_id,
00189 unsigned int sensor_num, unsigned int id)
00190 {
00191 if (ksensor == NULL)
00192 return;
00193
00194 ksensor->node_id = node_id;
00195 ksensor->sensor_number = sensor_num;
00196 ksensor->proc_entry = NULL;
00197 ksensor->sensor.id = id;
00198 ksensor->sensor.rx_bytes = ksensor->sensor.rx_errors = 0;
00199 ksensor->sensor.rx_dropped = ksensor->sensor.rx_overruns = 0;
00200 ksensor->sensor.tx_bytes = ksensor->sensor.tx_errors = 0;
00201 ksensor->sensor.tx_dropped = ksensor->sensor.tx_overruns = 0;
00202 }
00203
00204
00205
00206 static int read_nodes(char *page, char **start, off_t off,
00207 int count, int *eof, void *data)
00208 {
00209 struct avlnode *item;
00210 unsigned int len = MAX_NODES * (INTEGER_STRING + 2);
00211 char nodes[len];
00212
00213 if (off > 0) {
00214 *eof = 1;
00215 return 0;
00216 }
00217
00218
00219 while ((item = avl_find_min(&knodes)) != NULL) {
00220 char name[INTEGER_STRING];
00221 snprintf(name, INTEGER_STRING, "%d, ",
00222 ((struct knode *)item->element)->id);
00223 strncat(nodes, name, len - (strlen(nodes) + strlen(name)));
00224 }
00225 nodes[strlen(nodes)-2] = '\0';
00226
00227 return sprintf(page, "%s\n", nodes);
00228 }
00229
00230
00231
00232 static int read_sensor(char *page, char **start, off_t off,
00233 int count, int *eof, void *data)
00234 {
00235 unsigned int number = *(unsigned int *) data;
00236 struct ksensor *ksensor =
00237 (struct ksensor *) avl_retrieve(number, &ksensors);
00238 struct sensor_stats *sensor;
00239
00240 if (ksensor == NULL)
00241 return 0;
00242
00243 if (off > 0) {
00244 *eof = 1;
00245 return 0;
00246 }
00247
00248 sensor = &(ksensor->sensor);
00249 return sprintf(page,
00250 "RX bytes:%ld errors:%ld dropped:%ld overruns:%ld\n"
00251 "TX bytes:%ld errors:%ld dropped:%ld overruns:%ld\n",
00252 sensor->rx_bytes, sensor->rx_errors,
00253 sensor->rx_dropped, sensor->rx_overruns,
00254 sensor->tx_bytes, sensor->tx_errors,
00255 sensor->tx_dropped, sensor->tx_overruns);
00256 }
00257
00258
00259 int add_node(unsigned int id)
00260 {
00261 struct knode *knode;
00262 if ((knode = OQ_ALLOCATE(sizeof(struct knode))) == NULL) {
00263 printk(KERN_WARNING
00264 "orbisquartus: knode id %d failed\n", id);
00265 return -ENOMEM;
00266 }
00267
00268 knode->id = id;
00269
00270 if (avl_insert(knode, id, &knodes) != 0) {
00271 printk(KERN_WARNING
00272 "orbisquartus: knode id %d insertion failed\n", id);
00273 OQ_FREE(knode);
00274 return -EFAULT;
00275 }
00276
00277 return 0;
00278 }
00279
00280
00281 void remove_node(unsigned int number)
00282 {
00283 void *knode = NULL;
00284
00285 avl_delete(knode, number, &knodes);
00286 OQ_FREE(knode);
00287 }
00288
00289
00290 int add_sensor_entry(unsigned int node, unsigned int number, unsigned int id)
00291 {
00292 int len = 0;
00293 char entry_name[MAX_NAME];
00294 struct ksensor *ksensor =
00295 (struct ksensor *) avl_retrieve(id, &ksensors);
00296
00297 if (ksensor != NULL) {
00298 printk(KERN_WARNING
00299 "orbisquartus: sensor id %d is in use\n", id);
00300 return -EFAULT;
00301 }
00302 if ((ksensor = OQ_ALLOCATE(sizeof(struct ksensor))) == NULL) {
00303 printk(KERN_WARNING
00304 "orbisquartus: ksensor id %d failed\n", id);
00305 return -ENOMEM;
00306 }
00307
00308 if (avl_insert(ksensor, id, &ksensors) != 0) {
00309 printk(KERN_WARNING
00310 "orbisquartus: ksensor id %d insertion failed\n", id);
00311 len = -EFAULT;
00312 goto cleanup_avl_entry;
00313 }
00314
00315 initialize(ksensor, node, number, id);
00316 snprintf(entry_name, MAX_NAME, "%d::%d", node, number);
00317
00318 if ((ksensor->proc_entry =
00319 proc_mkdir(entry_name, oq_sensors)) == NULL) {
00320 printk(KERN_WARNING
00321 "orbisquartus: Couldn't create sensor proc entry\n");
00322 len = -ENOMEM;
00323 goto cleanup_proc_entry;
00324 }
00325 ksensor->proc_entry->read_proc = read_sensor;
00326 ksensor->proc_entry->owner = THIS_MODULE;
00327 ksensor->proc_entry->data = &(ksensor->sensor.id);
00328
00329 goto end;
00330
00331
00332 cleanup_proc_entry:
00333 remove_proc_entry(entry_name, oq_sensors);
00334 ksensor->proc_entry = NULL;
00335 cleanup_avl_entry:
00336 avl_delete(NULL, id, &ksensors);
00337 OQ_FREE(ksensor);
00338 end:
00339 return len;
00340 }
00341
00342
00343 void remove_sensor_entry(unsigned int number)
00344 {
00345 char entry_name[MAX_NAME];
00346 struct ksensor *ksensor =
00347 (struct ksensor *) avl_retrieve(number, &ksensors);
00348
00349 if (ksensor == NULL)
00350 return;
00351
00352 snprintf(entry_name, MAX_NAME, "%d::%d",
00353 ksensor->node_id, ksensor->sensor_number);
00354 remove_proc_entry(entry_name, oq_sensors);
00355 ksensor->proc_entry = NULL;
00356 avl_delete(NULL, ksensor->sensor.id, &ksensors);
00357 OQ_FREE(ksensor);
00358 }
00359
00360
00361 int post_sensor_stats(struct sensor_stats stats)
00362 {
00363 struct ksensor *ksensor =
00364 (struct ksensor *) avl_retrieve(stats.id, &ksensors);
00365 if (ksensor == NULL)
00366 return 0;
00367
00368 ksensor->sensor.rx_bytes = stats.rx_bytes;
00369 ksensor->sensor.rx_errors = stats.rx_errors;
00370 ksensor->sensor.rx_dropped = stats.rx_dropped;
00371 ksensor->sensor.rx_overruns = stats.rx_overruns;
00372 ksensor->sensor.tx_bytes = stats.tx_bytes;
00373 ksensor->sensor.tx_errors = stats.tx_errors;
00374 ksensor->sensor.tx_dropped = stats.tx_dropped;
00375 ksensor->sensor.tx_overruns = stats.tx_overruns;
00376 return 1;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 static int oq_clear_log(struct oq_dev *dev)
00389 {
00390 struct oq_log_item *next, *dptr;
00391 int i, qset = OQ_LOG_SIZE;
00392
00393 for (dptr = dev->data; dptr; dptr = next) {
00394 if (dptr->data) {
00395 for (i = 0; i < qset; i++)
00396 kfree(dptr->data[i]);
00397 kfree(dptr->data);
00398 dptr->data = NULL;
00399 }
00400 next = dptr->next;
00401 kfree(dptr);
00402 }
00403 dev->size = 0;
00404 dev->data = NULL;
00405 return 0;
00406 }
00407
00408
00409 static struct oq_log_item *oq_traverse_log(struct oq_dev *dev, int where)
00410 {
00411 struct oq_log_item *items = dev->data;
00412
00413 if (!items) {
00414 dev->data = kmalloc(sizeof(struct oq_log_item), GFP_KERNEL);
00415 if ((items = dev->data) == NULL)
00416 return NULL;
00417 memset(items, 0, sizeof(struct oq_log_item));
00418 }
00419 while (where--) {
00420 if (!items->next) {
00421 if ((items->next = kmalloc(sizeof(struct oq_log_item),
00422 GFP_KERNEL)) == NULL)
00423 return NULL;
00424 memset(items->next, 0, sizeof(struct oq_log_item));
00425 }
00426 items = items->next;
00427 }
00428 return items;
00429 }
00430
00431
00432
00433 loff_t oq_llseek(struct file *filp, loff_t pos, int where)
00434 {
00435 struct oq_dev *dev = filp->private_data;
00436 loff_t new_pos;
00437
00438 switch(where) {
00439 case 0:
00440 new_pos = pos;
00441 break;
00442
00443 case 1:
00444 new_pos = filp->f_pos + pos;
00445 break;
00446
00447 case 2:
00448 new_pos = dev->size + pos;
00449 break;
00450
00451 default:
00452 return -EINVAL;
00453 }
00454
00455 if (new_pos < 0)
00456 return -EINVAL;
00457
00458 filp->f_pos = new_pos;
00459 return new_pos;
00460 }
00461
00462
00463 ssize_t oq_read(struct file *filp, char __user *buf, size_t count,
00464 loff_t *f_pos)
00465 {
00466 struct oq_dev *dev = filp->private_data;
00467 struct oq_log_item *dptr;
00468 int quantum = OQ_LOG_ITEM_SIZE;
00469 int qset = OQ_LOG_SIZE;
00470 int itemsize = quantum * qset;
00471 int item, s_pos, q_pos, rest;
00472 ssize_t retval = 0;
00473
00474 if (down_interruptible(&dev->sem))
00475 return -ERESTARTSYS;
00476 if (*f_pos >= dev->size)
00477 goto end;
00478 if (*f_pos + count > dev->size)
00479 count = dev->size - *f_pos;
00480
00481 item = (long)*f_pos / itemsize;
00482 rest = (long)*f_pos % itemsize;
00483 s_pos = rest / quantum; q_pos = rest % quantum;
00484
00485 dptr = oq_traverse_log(dev, item);
00486
00487 if (dptr == NULL || !dptr->data || ! dptr->data[s_pos])
00488 goto end;
00489
00490 if (count > quantum - q_pos)
00491 count = quantum - q_pos;
00492
00493 if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count)) {
00494 retval = -EFAULT;
00495 goto end;
00496 }
00497 *f_pos += count;
00498 retval = count;
00499
00500 end:
00501 up(&dev->sem);
00502 return retval;
00503 }
00504
00505
00506 static ssize_t __oq_wrt(struct oq_dev *dev, const char __user *buf,
00507 size_t count, loff_t *f_pos)
00508 {
00509 struct oq_log_item *dptr;
00510 int quantum = OQ_LOG_ITEM_SIZE;
00511 int qset = OQ_LOG_SIZE;
00512 int itemsize = quantum * qset;
00513 int item, s_pos, q_pos, rest;
00514 ssize_t retval = -ENOMEM;
00515
00516 if (down_interruptible(&dev->sem))
00517 return -ERESTARTSYS;
00518
00519 item = (long)*f_pos / itemsize;
00520 rest = (long)*f_pos % itemsize;
00521 s_pos = rest / quantum;
00522 q_pos = rest % quantum;
00523
00524 dptr = oq_traverse_log(dev, item);
00525 if (dptr == NULL)
00526 goto end;
00527 if (!dptr->data) {
00528 dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);
00529 if (!dptr->data)
00530 goto end;
00531 memset(dptr->data, 0, qset * sizeof(char *));
00532 }
00533 if (!dptr->data[s_pos]) {
00534 dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
00535 if (!dptr->data[s_pos])
00536 goto end;
00537 }
00538
00539 if (count > quantum - q_pos)
00540 count = quantum - q_pos;
00541
00542 if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) {
00543 retval = -EFAULT;
00544 goto end;
00545 }
00546 *f_pos += count;
00547 retval = count;
00548
00549 if (dev->size < *f_pos)
00550 dev->size = *f_pos;
00551
00552 end:
00553 up(&dev->sem);
00554 return retval;
00555 }
00556
00557
00558 ssize_t oq_write(struct file *filp, const char __user *buf, size_t count,
00559 loff_t *f_pos)
00560 {
00561 struct oq_dev *dev = filp->private_data;
00562 return __oq_wrt(dev, buf, count, f_pos);
00563 }
00564
00565
00566
00567 int oq_ioctl(struct inode *inode, struct file *filp,
00568 unsigned int cmd, unsigned long arg)
00569 {
00570 DECLARE_WAITQUEUE(waitqueue, current);
00571 struct oq_req_resp *req;
00572 struct oq_req_resp *resp;
00573 int result = 0;
00574
00575
00577 switch (cmd) {
00578 case OQ_RESP_INIT:
00579 simulation_on++;
00580 if (down_interruptible(&req_resp_lists->simd_sem))
00581 return -ERESTARTSYS;
00582 goto await_result;
00583 break;
00584
00585 case OQ_RESP_REINIT:
00586 if (down_interruptible(&req_resp_lists->simd_sem))
00587 return -ERESTARTSYS;
00588 goto await_result;
00589 break;
00590
00591 case OQ_RESP_RESULT:
00592 if (down_interruptible(&req_resp_lists->simd_sem))
00593 return -ERESTARTSYS;
00594
00595 if ((resp = new_response(arg)) == NULL)
00596 return OQ_REQ_REPEAT;
00597 list_add_tail(&resp->list, &req_resp_lists->response_list);
00598 wake_up_interruptible(&req_resp_lists->response_wait);
00599
00600 await_result:
00601 add_wait_queue(&req_resp_lists->request_wait, &waitqueue);
00602 set_current_state(TASK_INTERRUPTIBLE);
00603 while (list_empty(&req_resp_lists->request_list)) {
00604 up(&req_resp_lists->simd_sem);
00605
00606 schedule();
00607
00608 if (signal_pending(current))
00609 return OQ_REQ_REPEAT;
00610 if (down_interruptible(&req_resp_lists->simd_sem))
00611 return OQ_REQ_REPEAT;
00612 }
00613 __set_current_state(TASK_RUNNING);
00614 remove_wait_queue(&req_resp_lists->request_wait, &waitqueue);
00615
00616 req = list_entry(&req_resp_lists->request_list,
00617 struct oq_req_resp, list);
00618 list_del(&req->list);
00619 result = copy_to_user((struct oq_req_resp __user *)arg, req,
00620 sizeof(struct oq_req_resp));
00621 kfree(req);
00622 up(&req_resp_lists->simd_sem);
00623 break;
00624
00625 default:
00626 return -ENOIOCTLCMD;
00627 }
00628
00629 return result;
00630 }
00631
00632
00633 int oq_open(struct inode *inode, struct file *filp)
00634 {
00635 struct oq_dev *dev;
00636 dev = container_of(inode->i_cdev, struct oq_dev, cdev);
00637 filp->private_data = dev;
00638
00639 if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
00640 if (down_interruptible(&dev->sem))
00641 return -ERESTARTSYS;
00642 oq_clear_log(dev);
00643 up(&dev->sem);
00644 }
00645 return 0;
00646 }
00647
00648
00649 int oq_release(struct inode *inode, struct file *filp)
00650 {
00651 return 0;
00652 }
00653
00654
00655
00656 int OQLOG(const char *fmt, ...)
00657 {
00658 va_list ap;
00659 char buf[OQ_LOG_ITEM_SIZE];
00660 int len;
00661
00662 va_start(ap, fmt);
00663 if ((len = vsnprintf(buf, OQ_LOG_ITEM_SIZE, fmt, ap)) < 0)
00664 return len;
00665 if (oq_device == NULL)
00666 return -ENODEV;
00667 len = __oq_wrt(oq_device, buf, strlen(buf) + 1,
00668 (loff_t *) &oq_device->size);
00669 va_end(ap);
00670 return len;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 int init_simulator_iface(int test)
00682 {
00683 int result = -1;
00684 struct proc_dir_entry *id_entry, *dilation_entry,
00685 *add_entry, *rm_entry, *nodes_entry;
00686
00687 req_resp_lists = &rr_lists;
00688 simulation_on = 0;
00689 sim_test = test;
00690
00691 init_waitqueue_head(&req_resp_lists->request_wait);
00692 init_waitqueue_head(&req_resp_lists->response_wait);
00693 init_MUTEX_LOCKED(&req_resp_lists->simd_sem);
00694 INIT_LIST_HEAD(&req_resp_lists->request_list);
00695 INIT_LIST_HEAD(&req_resp_lists->response_list);
00696
00697 INIT_LIST_HEAD(&khosts.list);
00698
00699 if ((id_entry =
00700 create_proc_entry("simulation_id", 0666, oq_dir)) == NULL) {
00701 printk(KERN_WARNING
00702 "orbisquartus: Couldn't create sim id entry\n");
00703 result = -ENOMEM;
00704 goto cleanup_id;
00705 }
00706 id_entry->read_proc = read_base;
00707 id_entry->write_proc = write_base;
00708 id_entry->owner = THIS_MODULE;
00709 id_entry->data = &metadata[SIM_ID];
00710
00711
00712 if ((dilation_entry =
00713 create_proc_entry("time_dilation", 0666, oq_dir)) == NULL) {
00714 printk(KERN_WARNING
00715 "orbisquartus: Couldn't enable time dilation entry\n");
00716 result = -ENOMEM;
00717 goto cleanup_time;
00718 }
00719 dilation_entry->read_proc = read_base;
00720 dilation_entry->write_proc = write_base;
00721 dilation_entry->owner = THIS_MODULE;
00722 dilation_entry->data = &metadata[TIME];
00723
00724
00725 if ((oq_hosts = proc_mkdir("hosts", oq_dir)) == NULL) {
00726 printk(KERN_ERR
00727 "orbisquartus: Couldn't create hosts proc entry\n");
00728 result = -ENOMEM;
00729 goto cleanup_hosts;
00730 }
00731 oq_hosts->owner = THIS_MODULE;
00732
00733
00734 if ((add_entry =
00735 create_proc_entry("add", 0666, oq_hosts)) == NULL) {
00736 printk(KERN_WARNING
00737 "orbisquartus: Couldn't enable hosts entry\n");
00738 result = -ENOMEM;
00739 goto cleanup_add;
00740 }
00741 add_entry->read_proc = read_base;
00742 add_entry->write_proc = write_base;
00743 add_entry->owner = THIS_MODULE;
00744 add_entry->data = &metadata[ADD_HOST];
00745
00746
00747 if ((rm_entry =
00748 create_proc_entry("remove", 0666, oq_hosts)) == NULL) {
00749 printk(KERN_WARNING
00750 "orbisquartus: Couldn't enable hosts entry\n");
00751 result = -ENOMEM;
00752 goto cleanup_rm;
00753 }
00754 rm_entry->read_proc = read_base;
00755 rm_entry->write_proc = write_base;
00756 rm_entry->owner = THIS_MODULE;
00757 rm_entry->data = &metadata[RM_HOST];
00758
00759
00760 if ((oq_sensors = proc_mkdir("sensors", oq_dir)) == NULL) {
00761 printk(KERN_WARNING
00762 "orbisquartus: Couldn't create sensors proc entry\n");
00763 result = -ENOMEM;
00764 goto cleanup_sensors;
00765 }
00766 oq_sensors->owner = THIS_MODULE;
00767
00768 if ((nodes_entry =
00769 create_proc_entry("nodes", 0666, oq_dir)) == NULL) {
00770 printk(KERN_WARNING
00771 "orbisquartus: Couldn't create nodes entry\n");
00772 result = -ENOMEM;
00773 goto cleanup_nodes;
00774 }
00775 nodes_entry->read_proc = read_nodes;
00776 nodes_entry->owner = THIS_MODULE;
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 goto end;
00789
00790
00791 cleanup_nodes:
00792 remove_proc_entry("nodes", oq_dir);
00793 cleanup_sensors:
00794 remove_proc_entry("sensors", oq_dir);
00795 cleanup_time:
00796 remove_proc_entry("time_dilation", oq_dir);
00797 cleanup_rm:
00798 remove_proc_entry("remove", oq_hosts);
00799 cleanup_add:
00800 remove_proc_entry("add", oq_hosts);
00801 cleanup_hosts:
00802 remove_proc_entry("hosts", oq_dir);
00803 cleanup_id:
00804 remove_proc_entry("simulation_id", oq_dir);
00805 end:
00806 return result;
00807 }
00808
00809
00810
00811 void shutdown_simulator_iface(void)
00812 {
00813 struct khost *tmp;
00814 struct list_head *pos, *q;
00815 struct avlnode *item;
00816
00817 simulation_on = 0;
00818
00819
00820 while ((item = avl_find_min(&ksensors)) != NULL) {
00821 unsigned int num = ((struct knode *)item->element)->id;
00822 remove_node(num);
00823 }
00824 remove_proc_entry("nodes", oq_dir);
00825 while ((item = avl_find_min(&ksensors)) != NULL) {
00826 unsigned int num =
00827 ((struct ksensor *)item->element)->sensor.id;
00828 remove_sensor_entry(num);
00829 }
00830 remove_proc_entry("sensors", oq_dir);
00831 remove_proc_entry("time_dilation", oq_dir);
00832
00833 list_for_each_safe(pos, q, &khosts.list) {
00834 tmp = list_entry(pos, struct khost, list);
00835 remove_proc_entry(tmp->name, oq_hosts);
00836 list_del(pos);
00837 kfree(tmp);
00838 }
00839
00840 remove_proc_entry("remove", oq_hosts);
00841 remove_proc_entry("add", oq_hosts);
00842 remove_proc_entry("hosts", oq_dir);
00843 remove_proc_entry("simulation_id", oq_dir);
00844 }