00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <linux/slab.h>
00015 #include <linux/mm.h>
00016 #include <linux/sched.h>
00017 #include <linux/errno.h>
00018 #include <linux/module.h>
00019
00020 #include <linux/bank.h>
00021
00022 #include <asm/bug.h>
00023
00024
00025
00026
00027
00028 #ifdef CONFIG_BANK_DEBUG
00029 #define dprintk(format...) printk(format)
00030 #else
00031 #define dprintk(format)
00032 #endif
00033
00034 #define ELSACCT_MIN_PID 1024
00035
00036
00037 static int elsa_process_present(struct task_struct *p, struct elsa_bank *b);
00038
00039
00040
00041
00042
00048 struct elsa_bank *elsa_bank_alloc(void)
00049 {
00050 struct elsa_bank *b;
00051
00052
00053 b = (struct elsa_bank *)kmalloc(sizeof(struct elsa_bank), GFP_KERNEL);
00054 if (!b) {
00055 printk("elsa_bank_alloc: cannot allocate space\n");
00056 return NULL;
00057 }
00058
00059
00060 b->info = NULL;
00061 b->callback = NULL;
00062 INIT_LIST_HEAD(&(b->data_head));
00063
00064 return b;
00065 }
00066
00073 void elsa_bank_free(struct elsa_bank *b)
00074 {
00075
00076
00077
00078
00079
00080
00081
00082 if (b->callback) {
00083 (b->callback) (ELSA_BANK_CALLBACK, b, NULL);
00084 }
00085
00086 dprintk("elsa_bank_free: bank released\n");
00087 kfree(b);
00088 }
00089
00102 int elsa_bank_add(struct bank_root *br,
00103 struct elsa_bank *b,
00104 int (*fn) (int, struct elsa_bank *, struct elsa_data *),
00105 void *info)
00106 {
00107
00108
00109
00110
00111
00112
00113
00114
00115 b->bid = br->next_bid++;
00116
00117 if (b->bid <= 0) {
00118 printk("elsa_bank_alloc: can not find bank identifier\n");
00119 return 0;
00120 }
00121
00122
00123 b->info = info;
00124 b->callback = fn;
00125
00126
00127
00128
00129 list_add(&(b->bank_list), &(br->bank_head));
00130
00131 dprintk("elsa_bank_alloc: bank #%d created\n", b->bid);
00132
00133 return b->bid;
00134 }
00135
00147 int elsa_bank_remove(struct elsa_bank *b)
00148 {
00149 BUG_ON(b == NULL);
00150 BUG_ON(!list_empty(&b->data_head));
00151
00152
00153
00154
00155 list_del(&(b->bank_list));
00156
00157 dprintk("elsa_bank_remove: bank #%d removed\n", b->bid);
00158
00159 return b->bid;
00160 }
00161
00171 struct elsa_data *elsa_data_alloc(void)
00172 {
00173 static struct elsa_data *d;
00174
00175
00176 d = (struct elsa_data *)kmalloc(sizeof(struct elsa_data), GFP_KERNEL);
00177 if (!d) {
00178 printk("elsa_data_alloc: cannot allocate space\n");
00179 return NULL;
00180 }
00181
00182
00183 d->bid = 0;
00184 d->process = NULL;
00185 INIT_LIST_HEAD(&(d->data_list));
00186 INIT_LIST_HEAD(&(d->bank_list));
00187
00188 return d;
00189 }
00190
00197 void elsa_data_free(struct elsa_data *d)
00198 {
00199 dprintk("elsa_data_free: data released\n");
00200 kfree(d);
00201 }
00202
00216 int elsa_data_add(struct elsa_bank *b, struct elsa_data *d)
00217 {
00218 static int present;
00219
00220 if (!b || !d || !(d->process)) {
00221 dprintk("elsa_data_add: Wrong parameters\n");
00222 return -EINVAL;
00223 }
00224
00225
00226 BUG_ON(b->bid == 0);
00227
00228 if (d->process->pid < ELSACCT_MIN_PID) {
00229 dprintk("elsa_data_add: PID < %d\n", ELSACCT_MIN_PID);
00230 return -EINVAL;
00231 }
00232
00233
00234 present = elsa_process_present(d->process, b);
00235 if (present) {
00236
00237 return -EPERM;
00238 }
00239
00240
00241 d->bid = b->bid;
00242
00243
00244 list_add(&(d->data_list), &(b->data_head));
00245
00246
00247
00248
00249
00250 write_lock_irq(&tasklist_lock);
00251 list_add(&(d->bank_list), &(d->process->bank_head));
00252 write_unlock_irq(&tasklist_lock);
00253
00254 dprintk("elsa_data_add: Add process #%d to bank #%d\n", d->process->pid,
00255 b->bid);
00256
00257 return b->bid;
00258 }
00259
00269 int elsa_data_remove(struct elsa_bank *b, struct elsa_data *d)
00270 {
00271
00272 if (!d)
00273 return -EINVAL;
00274
00275 BUG_ON(d->process->pid < ELSACCT_MIN_PID);
00276
00277
00278 if (b && b->callback) {
00279 (b->callback) (ELSA_DATA_CALLBACK, b, d);
00280 }
00281
00282
00283 list_del(&d->data_list);
00284
00285
00286
00287 write_lock_irq(&tasklist_lock);
00288 list_del(&d->bank_list);
00289 write_unlock_irq(&tasklist_lock);
00290
00291 if (list_empty(&(b->data_head)))
00292
00293 return b->bid;
00294
00295 return 0;
00296 }
00297
00305 struct elsa_bank *elsa_get_bank(struct bank_root *br, __u32 bid)
00306 {
00307 static struct list_head *entry;
00308 static struct elsa_bank *b;
00309
00310 if (bid == 0)
00311 return NULL;
00312
00313
00314
00315
00316
00317 list_for_each(entry, &(br->bank_head)) {
00318 b = list_entry(entry, struct elsa_bank, bank_list);
00319 if (b->bid == bid) {
00320 return b;
00321 }
00322 }
00323
00324
00325 return NULL;
00326 }
00327
00336 struct elsa_data *elsa_get_data(pid_t pid, __u32 bid)
00337 {
00338 static struct list_head *entry;
00339 static struct task_struct *p;
00340 static struct elsa_data *d;
00341
00342 read_lock(&tasklist_lock);
00343 p = find_task_by_pid(pid);
00344 read_unlock(&tasklist_lock);
00345
00346 if ((p == NULL) || (bid == 0))
00347 return NULL;
00348
00349 list_for_each(entry, &(p->bank_head)) {
00350 d = list_entry(entry, struct elsa_data, bank_list);
00351
00352 BUG_ON(d == NULL);
00353 if (d->bid == bid) {
00354
00355 return d;
00356 }
00357 }
00358
00359 return NULL;
00360 }
00361
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 EXPORT_SYMBOL(elsa_bank_alloc);
00384 EXPORT_SYMBOL(elsa_bank_free);
00385 EXPORT_SYMBOL(elsa_data_alloc);
00386 EXPORT_SYMBOL(elsa_data_free);
00387
00388
00389 EXPORT_SYMBOL(elsa_bank_add);
00390 EXPORT_SYMBOL(elsa_bank_remove);
00391 EXPORT_SYMBOL(elsa_data_add);
00392 EXPORT_SYMBOL(elsa_data_remove);
00393
00394
00395 EXPORT_SYMBOL(elsa_get_bank);
00396 EXPORT_SYMBOL(elsa_get_data);
00397
00398
00399
00400
00401
00409 static int elsa_process_present(struct task_struct *p, struct elsa_bank *b)
00410 {
00411 static struct list_head *entry;
00412 static struct elsa_data *d;
00413
00414 read_lock(&tasklist_lock);
00415 list_for_each(entry, &(b->data_head)) {
00416 d = list_entry(entry, struct elsa_data, data_list);
00417 if (d->process == p) {
00418
00419 read_unlock(&tasklist_lock);
00420 return 1;
00421 }
00422 }
00423 read_unlock(&tasklist_lock);
00424
00425
00426 return 0;
00427 }