[NET]: Fix locking in shaper driver.

o use a semaphore instead of an opencoded and racy lock
o move locking out of shaper_kick and into the callers - most just
released the lock before calling shaper_kick
o remove in_interrupt() tests. from ->close we can always block, from
->hard_start_xmit and timer context never

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Christoph Hellwig and committed by
David S. Miller
b597ef47 4fef0304

+20 -69
+19 -67
drivers/net/shaper.c
··· 100 101 #define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n" 102 103 - /* 104 - * Locking 105 - */ 106 - 107 - static int shaper_lock(struct shaper *sh) 108 - { 109 - /* 110 - * Lock in an interrupt must fail 111 - */ 112 - while (test_and_set_bit(0, &sh->locked)) 113 - { 114 - if (!in_interrupt()) 115 - sleep_on(&sh->wait_queue); 116 - else 117 - return 0; 118 - 119 - } 120 - return 1; 121 - } 122 - 123 static void shaper_kick(struct shaper *sh); 124 - 125 - static void shaper_unlock(struct shaper *sh) 126 - { 127 - clear_bit(0, &sh->locked); 128 - wake_up(&sh->wait_queue); 129 - shaper_kick(sh); 130 - } 131 132 /* 133 * Compute clocks on a buffer ··· 130 * Throw a frame at a shaper. 131 */ 132 133 - static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb) 134 { 135 struct sk_buff *ptr; 136 137 - /* 138 - * Get ready to work on this shaper. Lock may fail if its 139 - * an interrupt and locked. 140 - */ 141 - 142 - if(!shaper_lock(shaper)) 143 - return -1; 144 ptr=shaper->sendq.prev; 145 146 /* ··· 231 dev_kfree_skb(ptr); 232 shaper->stats.collisions++; 233 } 234 - shaper_unlock(shaper); 235 return 0; 236 } 237 ··· 269 270 static void shaper_timer(unsigned long data) 271 { 272 - struct shaper *sh=(struct shaper *)data; 273 - shaper_kick(sh); 274 } 275 276 /* ··· 287 { 288 struct sk_buff *skb; 289 290 - /* 291 - * Shaper unlock will kick 292 - */ 293 - 294 - if (test_and_set_bit(0, &shaper->locked)) 295 - { 296 - if(sh_debug) 297 - printk("Shaper locked.\n"); 298 - mod_timer(&shaper->timer, jiffies); 299 - return; 300 - } 301 - 302 - 303 /* 304 * Walk the list (may be empty) 305 */ ··· 328 329 if(skb!=NULL) 330 mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock); 331 - 332 - clear_bit(0, &shaper->locked); 333 } 334 335 ··· 338 static void shaper_flush(struct shaper *shaper) 339 { 340 struct sk_buff *skb; 341 - if(!shaper_lock(shaper)) 342 - { 343 - printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n"); 344 - return; 345 - } 346 while((skb=skb_dequeue(&shaper->sendq))!=NULL) 347 dev_kfree_skb(skb); 348 - shaper_unlock(shaper); 349 } 350 351 /* ··· 385 * for our attached device. This enables us to bandwidth allocate after 386 * ARP and other resolutions and not before. 387 */ 388 - 389 - 390 - static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) 391 - { 392 - struct shaper *sh=dev->priv; 393 - return shaper_qframe(sh, skb); 394 - } 395 396 static struct net_device_stats *shaper_get_stats(struct net_device *dev) 397 { ··· 576 init_timer(&sh->timer); 577 sh->timer.function=shaper_timer; 578 sh->timer.data=(unsigned long)sh; 579 - init_waitqueue_head(&sh->wait_queue); 580 } 581 582 /*
··· 100 101 #define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n" 102 103 static void shaper_kick(struct shaper *sh); 104 105 /* 106 * Compute clocks on a buffer ··· 157 * Throw a frame at a shaper. 158 */ 159 160 + 161 + static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev) 162 { 163 + struct shaper *shaper = dev->priv; 164 struct sk_buff *ptr; 165 166 + if (down_trylock(&shaper->sem)) 167 + return -1; 168 + 169 ptr=shaper->sendq.prev; 170 171 /* ··· 260 dev_kfree_skb(ptr); 261 shaper->stats.collisions++; 262 } 263 + shaper_kick(shaper); 264 + up(&shaper->sem); 265 return 0; 266 } 267 ··· 297 298 static void shaper_timer(unsigned long data) 299 { 300 + struct shaper *shaper = (struct shaper *)data; 301 + 302 + if (!down_trylock(&shaper->sem)) { 303 + shaper_kick(shaper); 304 + up(&shaper->sem); 305 + } else 306 + mod_timer(&shaper->timer, jiffies); 307 } 308 309 /* ··· 310 { 311 struct sk_buff *skb; 312 313 /* 314 * Walk the list (may be empty) 315 */ ··· 364 365 if(skb!=NULL) 366 mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock); 367 } 368 369 ··· 376 static void shaper_flush(struct shaper *shaper) 377 { 378 struct sk_buff *skb; 379 + 380 + down(&shaper->sem); 381 while((skb=skb_dequeue(&shaper->sendq))!=NULL) 382 dev_kfree_skb(skb); 383 + shaper_kick(shaper); 384 + up(&shaper->sem); 385 } 386 387 /* ··· 425 * for our attached device. This enables us to bandwidth allocate after 426 * ARP and other resolutions and not before. 427 */ 428 429 static struct net_device_stats *shaper_get_stats(struct net_device *dev) 430 { ··· 623 init_timer(&sh->timer); 624 sh->timer.function=shaper_timer; 625 sh->timer.data=(unsigned long)sh; 626 } 627 628 /*
+1 -2
include/linux/if_shaper.h
··· 23 __u32 shapeclock; 24 unsigned long recovery; /* Time we can next clock a packet out on 25 an empty queue */ 26 - unsigned long locked; 27 struct net_device_stats stats; 28 struct net_device *dev; 29 int (*hard_start_xmit) (struct sk_buff *skb, ··· 38 int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh); 39 void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); 40 struct net_device_stats* (*get_stats)(struct net_device *dev); 41 - wait_queue_head_t wait_queue; 42 struct timer_list timer; 43 }; 44
··· 23 __u32 shapeclock; 24 unsigned long recovery; /* Time we can next clock a packet out on 25 an empty queue */ 26 + struct semaphore sem; 27 struct net_device_stats stats; 28 struct net_device *dev; 29 int (*hard_start_xmit) (struct sk_buff *skb, ··· 38 int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh); 39 void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr); 40 struct net_device_stats* (*get_stats)(struct net_device *dev); 41 struct timer_list timer; 42 }; 43