Changeset 250


Ignore:
Timestamp:
10/03/13 23:46:37 (11 years ago)
Author:
atzm
Message:

optimize stats

Location:
ksyslog/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • ksyslog/trunk/ksyslog.c

    r247 r250  
    1212#include <linux/namei.h> 
    1313#include <linux/proc_fs.h> 
     14#include <linux/u64_stats_sync.h> 
     15#include <linux/percpu.h> 
    1416#include <net/udp.h> 
    1517#include "compat.h" 
     
    2729static struct proc_dir_entry *ksyslog_procdir = NULL; 
    2830static 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; 
     31static struct proc_dir_entry *ksyslog_proc_size = NULL; 
     32static struct proc_dir_entry *ksyslog_proc_stats = NULL; 
    3233#endif 
    3334 
     
    3536static ushort ksyslog_port = 514; 
    3637static char *ksyslog_path = "/var/log/ksyslog.log"; 
    37 static ulong ksyslog_queue_length = 4096; 
     38static ulong ksyslog_queue_size_max = 4096; 
    3839static ulong ksyslog_flush_interval = 45;  /* milliseconds */ 
    3940 
     
    4142module_param(ksyslog_port, ushort, 0444); 
    4243module_param(ksyslog_path, charp, 0644); 
    43 module_param(ksyslog_queue_length, ulong, 0644); 
     44module_param(ksyslog_queue_size_max, ulong, 0644); 
    4445module_param(ksyslog_flush_interval, ulong, 0644); 
    4546 
    46 static void 
     47static int 
    4748ksyslog_queue_init(struct ksyslog_queue *queue) 
    4849{ 
     
    5051        INIT_LIST_HEAD(&queue->head); 
    5152        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 
     60static void 
     61ksyslog_queue_uninit(struct ksyslog_queue *queue) 
     62{ 
     63        if (likely(queue->stats)) 
     64                free_percpu(queue->stats); 
     65        queue->stats = NULL; 
    5566} 
    5667 
     
    114125ksyslog_drop_warning(const struct ksyslog_entry *entry) 
    115126{ 
    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", 
    117128                timeval_to_ns(&entry->tv) / 1000 / 1000 / 1000, 
    118129                ksyslog_facility_str(entry->facility), 
     
    228239ksyslog_entry_add(struct ksyslog_queue *queue, struct ksyslog_entry *entry) 
    229240{ 
    230         if (unlikely(atomic64_read(&queue->nr_queued) >= ksyslog_queue_length)) 
     241        if (unlikely(atomic64_read(&queue->size) >= ksyslog_queue_size_max)) 
    231242                return -ENOBUFS; 
    232243        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); 
    234245        return 0; 
    235246} 
     
    238249ksyslog_entry_del(struct ksyslog_queue *queue, struct ksyslog_entry *entry, bool free) 
    239250{ 
    240         WARN_ON(atomic64_dec_return(&queue->nr_queued) < 0); 
     251        WARN_ON(atomic64_dec_return(&queue->size) < 0); 
    241252        list_del_rcu(&entry->list); 
    242253        if (free) 
     
    261272                ksyslog_entry_del(from, entry, false); 
    262273                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); 
    265276                        ksyslog_drop_warning(entry); 
    266277                        call_rcu(&entry->rcu, ksyslog_entry_free); 
     
    288299        struct ksyslog_queue write_queue; 
    289300 
    290         ksyslog_queue_init(&write_queue); 
     301        if (ksyslog_queue_init(&write_queue)) 
     302                goto out; 
    291303 
    292304        spin_lock_bh(&ksyslog_queue.lock); 
     
    294306        spin_unlock_bh(&ksyslog_queue.lock); 
    295307 
    296         if (atomic64_read(&write_queue.nr_queued) <= 0) 
     308        if (atomic64_read(&write_queue.size) <= 0) 
    297309                goto out; 
    298310 
     
    325337                } 
    326338 
    327                 atomic64_inc(&ksyslog_queue.nr_written); 
     339                ksyslog_stats_add_write(&ksyslog_queue, entry->length); 
    328340                kfree(buf); 
    329341                call_rcu(&entry->rcu, ksyslog_entry_free); 
     
    333345                spin_lock_bh(&ksyslog_queue.lock); 
    334346                if (unlikely(ksyslog_entry_add(&ksyslog_queue, entry))) { 
    335                         atomic64_inc(&ksyslog_queue.nr_dropped); 
     347                        ksyslog_stats_add_drop(&ksyslog_queue, entry->length); 
    336348                        ksyslog_drop_warning(entry); 
    337349                        call_rcu(&entry->rcu, ksyslog_entry_free); 
     
    344356 
    345357out: 
     358        ksyslog_queue_uninit(&write_queue); 
    346359        ksyslog_work_register(ksyslog_flush_interval); 
    347360} 
     
    355368        struct ksyslog_entry *entry; 
    356369 
    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        } 
    359374 
    360375        iph = ip_hdr(skb); 
    361376        udph = udp_hdr(skb); 
    362377 
    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        } 
    365382 
    366383        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        } 
    369393 
    370394        spin_lock_bh(&ksyslog_queue.lock); 
     
    373397 
    374398        if (unlikely(err)) { 
     399                ksyslog_stats_add_drop(&ksyslog_queue, entry->length); 
    375400                ksyslog_drop_warning(entry); 
    376401                ksyslog_entry_free(&entry->rcu); 
    377                 goto err; 
     402                goto out; 
    378403        } 
    379404 
     
    381406        consume_skb(skb); 
    382407        return 0; 
    383  
    384 err: 
    385         atomic64_inc(&ksyslog_queue.nr_dropped); 
    386         goto out; 
    387408} 
    388409 
     
    460481 
    461482static 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)); 
     483ksyslog_size_seq_show(struct seq_file *seq, void *v) 
     484{ 
     485        seq_printf(seq, "%lu\n", atomic64_read(&ksyslog_queue.size)); 
    465486        return 0; 
    466487} 
    467488 
    468489static 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)); 
     490ksyslog_size_seq_open(struct inode *inode, struct file *file) 
     491{ 
     492        return single_open(file, ksyslog_size_seq_show, PDE_DATA(inode)); 
     493} 
     494 
     495static int 
     496ksyslog_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 
    478538        return 0; 
    479539} 
    480540 
    481541static 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 = { 
     542ksyslog_stats_seq_open(struct inode *inode, struct file *file) 
     543{ 
     544        return single_open(file, ksyslog_stats_seq_show, PDE_DATA(inode)); 
     545} 
     546 
     547static struct file_operations ksyslog_size_fops = { 
    501548        .owner   = THIS_MODULE, 
    502         .open    = ksyslog_nr_queued_seq_open, 
     549        .open    = ksyslog_size_seq_open, 
    503550        .read    = seq_read, 
    504551        .llseek  = seq_lseek, 
     
    506553}; 
    507554 
    508 static struct file_operations ksyslog_nr_written_fops = { 
     555static struct file_operations ksyslog_stats_fops = { 
    509556        .owner   = THIS_MODULE, 
    510         .open    = ksyslog_nr_written_seq_open, 
     557        .open    = ksyslog_stats_seq_open, 
    511558        .read    = seq_read, 
    512559        .llseek  = seq_lseek, 
     
    514561}; 
    515562 
    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  
    524563static void 
    525564ksyslog_proc_destroy(void) 
     
    529568        ksyslog_proc_queue = NULL; 
    530569 
    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; 
    542577 
    543578        if (ksyslog_procdir) 
     
    551586        ksyslog_procdir = proc_mkdir("ksyslog", NULL); 
    552587        if (ksyslog_procdir == NULL) { 
    553                 pr_err("proc_mkdir failed\n"); 
     588                pr_err("ksyslog: proc_mkdir failed\n"); 
    554589                goto err; 
    555590        } 
     
    558593                                              &ksyslog_queue_fops, &ksyslog_queue.head); 
    559594        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"); 
    582610                goto err; 
    583611        } 
     
    610638        ksyslog_entry_destroy(&ksyslog_queue); 
    611639        rcu_barrier(); 
     640 
     641        ksyslog_queue_uninit(&ksyslog_queue); 
    612642} 
    613643 
     
    618648        struct sockaddr_in sin; 
    619649 
    620         ksyslog_queue_init(&ksyslog_queue); 
     650        err = ksyslog_queue_init(&ksyslog_queue); 
     651        if (err) 
     652                goto err; 
    621653 
    622654#ifdef CONFIG_PROC_FS 
     
    628660        ksyslog_wq = create_singlethread_workqueue("ksyslog"); 
    629661        if (ksyslog_wq == NULL) { 
    630                 pr_err("create_workqueue failed\n"); 
     662                pr_err("ksyslog: create_workqueue failed\n"); 
    631663                err = -ENOMEM; 
    632664                goto err; 
     
    637669        err = sock_create(AF_INET, SOCK_DGRAM, 0, &ksyslog_rcv_sk); 
    638670        if (err) { 
    639                 pr_err("sock_create failed\n"); 
     671                pr_err("ksyslog: sock_create failed\n"); 
    640672                goto err; 
    641673        } 
     
    648680                          sizeof(struct sockaddr_in)); 
    649681        if (err) { 
    650                 pr_err("kernel_bind failed\n"); 
     682                pr_err("ksyslog: kernel_bind failed\n"); 
    651683                goto err; 
    652684        } 
  • ksyslog/trunk/ksyslog.h

    r249 r250  
    7272}; 
    7373 
     74struct 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 
    7484struct ksyslog_queue { 
    7585        struct list_head head; 
    7686        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 
     91static inline void 
     92ksyslog_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 
     103static inline void 
     104ksyslog_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 
     115static inline void 
     116ksyslog_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} 
    81126 
    82127static inline const char * 
Note: See TracChangeset for help on using the changeset viewer.