]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Added locking to CAN core proc_fs output.
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Thu, 3 May 2007 10:26:19 +0000 (10:26 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Thu, 3 May 2007 10:26:19 +0000 (10:26 +0000)
git-svn-id: svn://svn.berlios.de//socketcan/trunk@271 030b6a49-0b11-0410-94ab-b0dab22257f2

kernel/2.6/net/can/af_can.c
kernel/2.6/net/can/af_can.h
kernel/2.6/net/can/proc.c

index 1387abaf06067c8c823350979dc44688560e2120..1192511aab8f6add2e177e3d8ef11071a0e6c54d 100644 (file)
@@ -116,6 +116,7 @@ static struct can_proto *proto_tab[CAN_NPROTO];
 struct timer_list stattimer; /* timer for statistics update */
 struct s_stats  stats;       /* packet statistics */
 struct s_pstats pstats;      /* receive list statistics */
+DEFINE_SPINLOCK(stats_lock);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
 static void *kzalloc(size_t size, unsigned int __nocast flags)
@@ -292,8 +293,10 @@ int can_send(struct sk_buff *skb, int loop)
                err = net_xmit_errno(err);
 
        /* update statistics */
+       spin_lock(&stats_lock);
        stats.tx_frames++;
        stats.tx_frames_delta++;
+       spin_unlock(&stats_lock);
 
        return err;
 }
@@ -657,8 +660,10 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
        }
 
        /* update statistics */
+       spin_lock(&stats_lock);
        stats.rx_frames++;
        stats.rx_frames_delta++;
+       spin_unlock(&stats_lock);
 
        rcu_read_lock();
 
@@ -677,8 +682,10 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
        kfree_skb(skb);
 
        if (matches > 0) {
+               spin_lock(&stats_lock);
                stats.matches++;
                stats.matches_delta++;
+               spin_unlock(&stats_lock);
        }
 
        return 0;
@@ -1060,7 +1067,8 @@ static __init int can_init(void)
                stattimer.expires = jiffies + HZ;
                /* start statistics timer */
                add_timer(&stattimer);
-       }
+       } else
+               stattimer.function = NULL;
 
        /* procfs init */
        can_init_proc();
index 874dd58a4af495342fe2ce4a99157ed95b64cc1f..dd1618feb96289abc66cb968cc86286d8e249191 100644 (file)
@@ -106,10 +106,13 @@ struct s_stats {
 
 struct s_pstats {
        unsigned long stats_reset;
+       unsigned long user_reset;
        unsigned long rcv_entries;
        unsigned long rcv_entries_max;
 }; /* persistent statistics */
 
+extern spinlock_t stats_lock;
+
 /* function prototypes for the CAN networklayer procfs (proc.c) */
 extern void can_init_proc(void);
 extern void can_remove_proc(void);
index 6c7b4d6c5f17a568de66eb76f0f661b2da786877..b1e3eb16156ae623915a8b06aaea58bf37bb7a3e 100644 (file)
@@ -78,15 +78,30 @@ static struct proc_dir_entry *pde_rcvlist_sff = NULL;
 static struct proc_dir_entry *pde_rcvlist_eff = NULL;
 static struct proc_dir_entry *pde_rcvlist_err = NULL;
 
+static int user_reset = 0;
+
 /* 
  * af_can statistics stuff
  */
 
 static void can_init_stats(void)
 {
+       /*
+        * This memset function is called from a timer context (when
+        * stattimer is active which is the default) OR in a process
+        * context (reading the proc_fs when stattimer is disabled).
+        */
+       spin_lock(&stats_lock);
        memset(&stats, 0, sizeof(stats));
-       stats.jiffies_init  = jiffies;
+       stats.jiffies_init = jiffies;
+       spin_unlock(&stats_lock);
+
        pstats.stats_reset++;
+
+       if (user_reset) {
+               user_reset = 0;
+               pstats.user_reset++;
+       }
 }
 
 static unsigned long calc_rate(unsigned long oldjif, unsigned long newjif,
@@ -113,6 +128,10 @@ void can_stat_update(unsigned long data)
 {
        unsigned long j = jiffies; /* snapshot */
 
+       /* restart counting in timer context on user request */
+       if (user_reset)
+               can_init_stats();
+
        /* restart counting on jiffies overflow */
        if (j < stats.jiffies_init)
                can_init_stats();
@@ -229,44 +248,46 @@ static int can_proc_read_stats(char *page, char **start, off_t off,
 
        len += snprintf(page + len, PAGE_SIZE - len, "\n");
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld %% total match ratio (RXMR)\n",
-                       stats.total_rx_match_ratio);
+       if (stattimer.function == can_stat_update) {
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld %% total match ratio (RXMR)\n",
+                               stats.total_rx_match_ratio);
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s total tx rate (TXR)\n",
-                       stats.total_tx_rate);
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s total rx rate (RXR)\n",
-                       stats.total_rx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s total tx rate (TXR)\n",
+                               stats.total_tx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s total rx rate (RXR)\n",
+                               stats.total_rx_rate);
 
-       len += snprintf(page + len, PAGE_SIZE - len, "\n");
+               len += snprintf(page + len, PAGE_SIZE - len, "\n");
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld %% current match ratio (CRXMR)\n",
-                       stats.current_rx_match_ratio);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld %% current match ratio (CRXMR)\n",
+                               stats.current_rx_match_ratio);
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s current tx rate (CTXR)\n",
-                       stats.current_tx_rate);
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s current rx rate (CRXR)\n",
-                       stats.current_rx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s current tx rate (CTXR)\n",
+                               stats.current_tx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s current rx rate (CRXR)\n",
+                               stats.current_rx_rate);
 
-       len += snprintf(page + len, PAGE_SIZE - len, "\n");
+               len += snprintf(page + len, PAGE_SIZE - len, "\n");
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld %% max match ratio (MRXMR)\n",
-                       stats.max_rx_match_ratio);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld %% max match ratio (MRXMR)\n",
+                               stats.max_rx_match_ratio);
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s max tx rate (MTXR)\n",
-                       stats.max_tx_rate);
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       " %8ld frames/s max rx rate (MRXR)\n",
-                       stats.max_rx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s max tx rate (MTXR)\n",
+                               stats.max_tx_rate);
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld frames/s max rx rate (MRXR)\n",
+                               stats.max_rx_rate);
 
-       len += snprintf(page + len, PAGE_SIZE - len, "\n");
+               len += snprintf(page + len, PAGE_SIZE - len, "\n");
+       }
 
        len += snprintf(page + len, PAGE_SIZE - len,
                        " %8ld current receive list entries (CRCV)\n",
@@ -280,6 +301,11 @@ static int can_proc_read_stats(char *page, char **start, off_t off,
                                "\n %8ld statistic resets (STR)\n",
                                pstats.stats_reset);
 
+       if (pstats.user_reset)
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               " %8ld user statistic resets (USTR)\n",
+                               pstats.user_reset);
+
        len += snprintf(page + len, PAGE_SIZE - len, "\n");
 
        *eof = 1;
@@ -291,11 +317,21 @@ static int can_proc_read_reset_stats(char *page, char **start, off_t off,
 {
        int len = 0;
 
-       can_init_stats();
+       user_reset = 1;
 
-       len += snprintf(page + len, PAGE_SIZE - len,
-                       "CAN statistic reset #%ld done.\n",
-                       pstats.stats_reset);
+       if (stattimer.function == can_stat_update) {
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               "Scheduled statistic reset #%ld.\n",
+                               pstats.stats_reset + 1);
+
+       } else {
+               if (stats.jiffies_init != jiffies)
+                       can_init_stats();
+
+               len += snprintf(page + len, PAGE_SIZE - len,
+                               "Performed statistic reset #%ld.\n",
+                               pstats.stats_reset);
+       }
 
        *eof = 1;
        return len;