Changeset 250
- Timestamp:
- 10/03/13 23:46:37 (11 years ago)
- Location:
- ksyslog/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
ksyslog/trunk/ksyslog.c
r247 r250 12 12 #include <linux/namei.h> 13 13 #include <linux/proc_fs.h> 14 #include <linux/u64_stats_sync.h> 15 #include <linux/percpu.h> 14 16 #include <net/udp.h> 15 17 #include "compat.h" … … 27 29 static struct proc_dir_entry *ksyslog_procdir = NULL; 28 30 static struct proc_dir_entry *ksyslog_proc_queue = NULL; 29 static struct proc_dir_entry *ksyslog_proc_nr_queued = NULL; 30 static struct proc_dir_entry *ksyslog_proc_nr_written = NULL; 31 static struct proc_dir_entry *ksyslog_proc_nr_dropped = NULL; 31 static struct proc_dir_entry *ksyslog_proc_size = NULL; 32 static struct proc_dir_entry *ksyslog_proc_stats = NULL; 32 33 #endif 33 34 … … 35 36 static ushort ksyslog_port = 514; 36 37 static char *ksyslog_path = "/var/log/ksyslog.log"; 37 static ulong ksyslog_queue_ length= 4096;38 static ulong ksyslog_queue_size_max = 4096; 38 39 static ulong ksyslog_flush_interval = 45; /* milliseconds */ 39 40 … … 41 42 module_param(ksyslog_port, ushort, 0444); 42 43 module_param(ksyslog_path, charp, 0644); 43 module_param(ksyslog_queue_ length, ulong, 0644);44 module_param(ksyslog_queue_size_max, ulong, 0644); 44 45 module_param(ksyslog_flush_interval, ulong, 0644); 45 46 46 static void47 static int 47 48 ksyslog_queue_init(struct ksyslog_queue *queue) 48 49 { … … 50 51 INIT_LIST_HEAD(&queue->head); 51 52 spin_lock_init(&queue->lock); 52 atomic64_set(&queue->nr_queued, 0); 53 atomic64_set(&queue->nr_written, 0); 54 atomic64_set(&queue->nr_dropped, 0); 53 atomic64_set(&queue->size, 0); 54 queue->stats = alloc_percpu(struct ksyslog_stats); 55 if (unlikely(queue->stats == NULL)) 56 return -ENOMEM; 57 return 0; 58 } 59 60 static void 61 ksyslog_queue_uninit(struct ksyslog_queue *queue) 62 { 63 if (likely(queue->stats)) 64 free_percpu(queue->stats); 65 queue->stats = NULL; 55 66 } 56 67 … … 114 125 ksyslog_drop_warning(const struct ksyslog_entry *entry) 115 126 { 116 pr_warn(" dropped: %llu %s.%s %u.%u.%u.%u %.*s\n",127 pr_warn("ksyslog: dropped: %llu %s.%s %u.%u.%u.%u %.*s\n", 117 128 timeval_to_ns(&entry->tv) / 1000 / 1000 / 1000, 118 129 ksyslog_facility_str(entry->facility), … … 228 239 ksyslog_entry_add(struct ksyslog_queue *queue, struct ksyslog_entry *entry) 229 240 { 230 if (unlikely(atomic64_read(&queue-> nr_queued) >= ksyslog_queue_length))241 if (unlikely(atomic64_read(&queue->size) >= ksyslog_queue_size_max)) 231 242 return -ENOBUFS; 232 243 list_add_tail_rcu(&entry->list, &queue->head); 233 WARN_ON(atomic64_inc_return(&queue-> nr_queued) > ksyslog_queue_length);244 WARN_ON(atomic64_inc_return(&queue->size) > ksyslog_queue_size_max); 234 245 return 0; 235 246 } … … 238 249 ksyslog_entry_del(struct ksyslog_queue *queue, struct ksyslog_entry *entry, bool free) 239 250 { 240 WARN_ON(atomic64_dec_return(&queue-> nr_queued) < 0);251 WARN_ON(atomic64_dec_return(&queue->size) < 0); 241 252 list_del_rcu(&entry->list); 242 253 if (free) … … 261 272 ksyslog_entry_del(from, entry, false); 262 273 if (unlikely(ksyslog_entry_add(to, entry))) { 263 atomic64_inc(&from->nr_dropped);264 atomic64_inc(&to->nr_dropped);274 ksyslog_stats_add_drop(from, entry->length); 275 ksyslog_stats_add_drop(to, entry->length); 265 276 ksyslog_drop_warning(entry); 266 277 call_rcu(&entry->rcu, ksyslog_entry_free); … … 288 299 struct ksyslog_queue write_queue; 289 300 290 ksyslog_queue_init(&write_queue); 301 if (ksyslog_queue_init(&write_queue)) 302 goto out; 291 303 292 304 spin_lock_bh(&ksyslog_queue.lock); … … 294 306 spin_unlock_bh(&ksyslog_queue.lock); 295 307 296 if (atomic64_read(&write_queue. nr_queued) <= 0)308 if (atomic64_read(&write_queue.size) <= 0) 297 309 goto out; 298 310 … … 325 337 } 326 338 327 atomic64_inc(&ksyslog_queue.nr_written);339 ksyslog_stats_add_write(&ksyslog_queue, entry->length); 328 340 kfree(buf); 329 341 call_rcu(&entry->rcu, ksyslog_entry_free); … … 333 345 spin_lock_bh(&ksyslog_queue.lock); 334 346 if (unlikely(ksyslog_entry_add(&ksyslog_queue, entry))) { 335 atomic64_inc(&ksyslog_queue.nr_dropped);347 ksyslog_stats_add_drop(&ksyslog_queue, entry->length); 336 348 ksyslog_drop_warning(entry); 337 349 call_rcu(&entry->rcu, ksyslog_entry_free); … … 344 356 345 357 out: 358 ksyslog_queue_uninit(&write_queue); 346 359 ksyslog_work_register(ksyslog_flush_interval); 347 360 } … … 355 368 struct ksyslog_entry *entry; 356 369 357 if (unlikely(skb_linearize(skb))) 358 goto err; 370 if (unlikely(skb_linearize(skb))) { 371 ksyslog_stats_add_drop(&ksyslog_queue, skb->len); 372 goto out; 373 } 359 374 360 375 iph = ip_hdr(skb); 361 376 udph = udp_hdr(skb); 362 377 363 if (unlikely(!skb_pull(skb, sizeof(*udph)))) 364 goto err; 378 if (unlikely(!skb_pull(skb, sizeof(*udph)))) { 379 ksyslog_stats_add_drop(&ksyslog_queue, skb->len); 380 goto out; 381 } 365 382 366 383 entry = ksyslog_entry_create(skb, iph, udph); 367 if (unlikely(IS_ERR(entry))) 368 goto err; 384 if (unlikely(IS_ERR(entry))) { 385 if (PTR_ERR(entry) == -EINVAL) { 386 ksyslog_stats_add_discard(&ksyslog_queue, skb->len); 387 goto out; 388 } 389 390 ksyslog_stats_add_drop(&ksyslog_queue, skb->len); 391 goto out; 392 } 369 393 370 394 spin_lock_bh(&ksyslog_queue.lock); … … 373 397 374 398 if (unlikely(err)) { 399 ksyslog_stats_add_drop(&ksyslog_queue, entry->length); 375 400 ksyslog_drop_warning(entry); 376 401 ksyslog_entry_free(&entry->rcu); 377 goto err;402 goto out; 378 403 } 379 404 … … 381 406 consume_skb(skb); 382 407 return 0; 383 384 err:385 atomic64_inc(&ksyslog_queue.nr_dropped);386 goto out;387 408 } 388 409 … … 460 481 461 482 static int 462 ksyslog_ nr_queued_seq_show(struct seq_file *seq, void *v)463 { 464 seq_printf(seq, "%lu\n", atomic64_read(&ksyslog_queue. nr_queued));483 ksyslog_size_seq_show(struct seq_file *seq, void *v) 484 { 485 seq_printf(seq, "%lu\n", atomic64_read(&ksyslog_queue.size)); 465 486 return 0; 466 487 } 467 488 468 489 static int 469 ksyslog_nr_queued_seq_open(struct inode *inode, struct file *file) 470 { 471 return single_open(file, ksyslog_nr_queued_seq_show, PDE_DATA(inode)); 472 } 473 474 static int 475 ksyslog_nr_written_seq_show(struct seq_file *seq, void *v) 476 { 477 seq_printf(seq, "%lu\n", atomic64_read(&ksyslog_queue.nr_written)); 490 ksyslog_size_seq_open(struct inode *inode, struct file *file) 491 { 492 return single_open(file, ksyslog_size_seq_show, PDE_DATA(inode)); 493 } 494 495 static int 496 ksyslog_stats_seq_show(struct seq_file *seq, void *v) 497 { 498 int i; 499 struct ksyslog_stats stats; 500 501 memset(&stats, 0, sizeof(stats)); 502 503 for_each_possible_cpu(i) { 504 const struct ksyslog_stats *percpu_stats; 505 struct ksyslog_stats local_stats; 506 unsigned int start; 507 508 percpu_stats = per_cpu_ptr(ksyslog_queue.stats, i); 509 510 do { 511 start = u64_stats_fetch_begin_bh(&percpu_stats->sync); 512 local_stats = *percpu_stats; 513 } while (u64_stats_fetch_retry_bh(&percpu_stats->sync, start)); 514 515 stats.write_bytes += local_stats.write_bytes; 516 stats.write_packets += local_stats.write_packets; 517 stats.drop_bytes += local_stats.drop_bytes; 518 stats.drop_packets += local_stats.drop_packets; 519 stats.discard_bytes += local_stats.discard_bytes; 520 stats.discard_packets += local_stats.discard_packets; 521 } 522 523 seq_puts(seq, "{\n"); 524 seq_puts(seq, " \"write\": {\n"); 525 seq_printf(seq, " \"bytes\": \"%llu\",\n", stats.write_bytes); 526 seq_printf(seq, " \"packets\": \"%llu\"\n", stats.write_packets); 527 seq_puts(seq, " },\n"); 528 seq_puts(seq, " \"drop\": {\n"); 529 seq_printf(seq, " \"bytes\": \"%llu\",\n", stats.drop_bytes); 530 seq_printf(seq, " \"packets\": \"%llu\"\n", stats.drop_packets); 531 seq_puts(seq, " },\n"); 532 seq_puts(seq, " \"discard\": {\n"); 533 seq_printf(seq, " \"bytes\": \"%llu\",\n", stats.discard_bytes); 534 seq_printf(seq, " \"packets\": \"%llu\"\n", stats.discard_packets); 535 seq_puts(seq, " }\n"); 536 seq_puts(seq, "}\n"); 537 478 538 return 0; 479 539 } 480 540 481 541 static int 482 ksyslog_nr_written_seq_open(struct inode *inode, struct file *file) 483 { 484 return single_open(file, ksyslog_nr_written_seq_show, PDE_DATA(inode)); 485 } 486 487 static int 488 ksyslog_nr_dropped_seq_show(struct seq_file *seq, void *v) 489 { 490 seq_printf(seq, "%lu\n", atomic64_read(&ksyslog_queue.nr_dropped)); 491 return 0; 492 } 493 494 static int 495 ksyslog_nr_dropped_seq_open(struct inode *inode, struct file *file) 496 { 497 return single_open(file, ksyslog_nr_dropped_seq_show, PDE_DATA(inode)); 498 } 499 500 static struct file_operations ksyslog_nr_queued_fops = { 542 ksyslog_stats_seq_open(struct inode *inode, struct file *file) 543 { 544 return single_open(file, ksyslog_stats_seq_show, PDE_DATA(inode)); 545 } 546 547 static struct file_operations ksyslog_size_fops = { 501 548 .owner = THIS_MODULE, 502 .open = ksyslog_ nr_queued_seq_open,549 .open = ksyslog_size_seq_open, 503 550 .read = seq_read, 504 551 .llseek = seq_lseek, … … 506 553 }; 507 554 508 static struct file_operations ksyslog_ nr_written_fops = {555 static struct file_operations ksyslog_stats_fops = { 509 556 .owner = THIS_MODULE, 510 .open = ksyslog_ nr_written_seq_open,557 .open = ksyslog_stats_seq_open, 511 558 .read = seq_read, 512 559 .llseek = seq_lseek, … … 514 561 }; 515 562 516 static struct file_operations ksyslog_nr_dropped_fops = {517 .owner = THIS_MODULE,518 .open = ksyslog_nr_dropped_seq_open,519 .read = seq_read,520 .llseek = seq_lseek,521 .release = single_release,522 };523 524 563 static void 525 564 ksyslog_proc_destroy(void) … … 529 568 ksyslog_proc_queue = NULL; 530 569 531 if (ksyslog_proc_nr_queued) 532 remove_proc_entry("nr_queued", ksyslog_procdir); 533 ksyslog_proc_nr_queued = NULL; 534 535 if (ksyslog_proc_nr_written) 536 remove_proc_entry("nr_written", ksyslog_procdir); 537 ksyslog_proc_nr_written = NULL; 538 539 if (ksyslog_proc_nr_dropped) 540 remove_proc_entry("nr_dropped", ksyslog_procdir); 541 ksyslog_proc_nr_dropped = NULL; 570 if (ksyslog_proc_size) 571 remove_proc_entry("size", ksyslog_procdir); 572 ksyslog_proc_size = NULL; 573 574 if (ksyslog_proc_stats) 575 remove_proc_entry("stats", ksyslog_procdir); 576 ksyslog_proc_stats = NULL; 542 577 543 578 if (ksyslog_procdir) … … 551 586 ksyslog_procdir = proc_mkdir("ksyslog", NULL); 552 587 if (ksyslog_procdir == NULL) { 553 pr_err(" proc_mkdir failed\n");588 pr_err("ksyslog: proc_mkdir failed\n"); 554 589 goto err; 555 590 } … … 558 593 &ksyslog_queue_fops, &ksyslog_queue.head); 559 594 if (ksyslog_proc_queue == NULL) { 560 pr_err("proc_create(queue) failed\n"); 561 goto err; 562 } 563 564 ksyslog_proc_nr_queued = proc_create("nr_queued", S_IRUGO, ksyslog_procdir, 565 &ksyslog_nr_queued_fops); 566 if (ksyslog_proc_nr_queued == NULL) { 567 pr_err("proc_create(nr_queued) failed\n"); 568 goto err; 569 } 570 571 ksyslog_proc_nr_written = proc_create("nr_written", S_IRUGO, ksyslog_procdir, 572 &ksyslog_nr_written_fops); 573 if (ksyslog_proc_nr_written == NULL) { 574 pr_err("proc_create(nr_written) failed\n"); 575 goto err; 576 } 577 578 ksyslog_proc_nr_dropped = proc_create("nr_dropped", S_IRUGO, ksyslog_procdir, 579 &ksyslog_nr_dropped_fops); 580 if (ksyslog_proc_nr_dropped == NULL) { 581 pr_err("proc_create(nr_dropped) failed\n"); 595 pr_err("ksyslog: proc_create(queue) failed\n"); 596 goto err; 597 } 598 599 ksyslog_proc_size = proc_create("size", S_IRUGO, ksyslog_procdir, 600 &ksyslog_size_fops); 601 if (ksyslog_proc_size == NULL) { 602 pr_err("ksyslog: proc_create(size) failed\n"); 603 goto err; 604 } 605 606 ksyslog_proc_stats = proc_create("stats", S_IRUGO, ksyslog_procdir, 607 &ksyslog_stats_fops); 608 if (ksyslog_proc_stats == NULL) { 609 pr_err("ksyslog: proc_create(stats) failed\n"); 582 610 goto err; 583 611 } … … 610 638 ksyslog_entry_destroy(&ksyslog_queue); 611 639 rcu_barrier(); 640 641 ksyslog_queue_uninit(&ksyslog_queue); 612 642 } 613 643 … … 618 648 struct sockaddr_in sin; 619 649 620 ksyslog_queue_init(&ksyslog_queue); 650 err = ksyslog_queue_init(&ksyslog_queue); 651 if (err) 652 goto err; 621 653 622 654 #ifdef CONFIG_PROC_FS … … 628 660 ksyslog_wq = create_singlethread_workqueue("ksyslog"); 629 661 if (ksyslog_wq == NULL) { 630 pr_err(" create_workqueue failed\n");662 pr_err("ksyslog: create_workqueue failed\n"); 631 663 err = -ENOMEM; 632 664 goto err; … … 637 669 err = sock_create(AF_INET, SOCK_DGRAM, 0, &ksyslog_rcv_sk); 638 670 if (err) { 639 pr_err(" sock_create failed\n");671 pr_err("ksyslog: sock_create failed\n"); 640 672 goto err; 641 673 } … … 648 680 sizeof(struct sockaddr_in)); 649 681 if (err) { 650 pr_err("k ernel_bind failed\n");682 pr_err("ksyslog: kernel_bind failed\n"); 651 683 goto err; 652 684 } -
ksyslog/trunk/ksyslog.h
r249 r250 72 72 }; 73 73 74 struct ksyslog_stats { 75 u64 write_bytes; 76 u64 write_packets; 77 u64 drop_bytes; 78 u64 drop_packets; 79 u64 discard_bytes; 80 u64 discard_packets; 81 struct u64_stats_sync sync; 82 }; 83 74 84 struct ksyslog_queue { 75 85 struct list_head head; 76 86 spinlock_t lock; 77 atomic64_t nr_queued; 78 atomic64_t nr_written; 79 atomic64_t nr_dropped; 80 }; 87 atomic64_t size; 88 struct ksyslog_stats __percpu *stats; 89 }; 90 91 static inline void 92 ksyslog_stats_add_write(struct ksyslog_queue *queue, unsigned int len) 93 { 94 struct ksyslog_stats *stats; 95 96 stats = per_cpu_ptr(queue->stats, smp_processor_id()); 97 u64_stats_update_begin(&stats->sync); 98 stats->write_bytes += len; 99 stats->write_packets++; 100 u64_stats_update_end(&stats->sync); 101 } 102 103 static inline void 104 ksyslog_stats_add_drop(struct ksyslog_queue *queue, unsigned int len) 105 { 106 struct ksyslog_stats *stats; 107 108 stats = per_cpu_ptr(queue->stats, smp_processor_id()); 109 u64_stats_update_begin(&stats->sync); 110 stats->drop_bytes += len; 111 stats->drop_packets++; 112 u64_stats_update_end(&stats->sync); 113 } 114 115 static inline void 116 ksyslog_stats_add_discard(struct ksyslog_queue *queue, unsigned int len) 117 { 118 struct ksyslog_stats *stats; 119 120 stats = per_cpu_ptr(queue->stats, smp_processor_id()); 121 u64_stats_update_begin(&stats->sync); 122 stats->discard_bytes += len; 123 stats->discard_packets++; 124 u64_stats_update_end(&stats->sync); 125 } 81 126 82 127 static inline const char *
Note: See TracChangeset
for help on using the changeset viewer.