[ATM]: deregistration removes device from atm_devs list immediately

atm_dev_deregister() removes device from atm_dev list immediately to
prevent operations on a phantom device. Decision to free device based
only on ->refcnt now. Remove shutdown_atm_dev() use atm_dev_deregister()
instead. atm_dev_deregister() also asynchronously releases all vccs
related to device.

Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Stanislaw Gruszka and committed by David S. Miller 64bf69dd aaaaaadb

+51 -56
+2 -18
drivers/atm/atmtcp.c
··· 246 246 { 247 247 struct atm_dev *atmtcp_dev; 248 248 struct atmtcp_dev_data *dev_data; 249 - struct sock *s; 250 - struct hlist_node *node; 251 - struct atm_vcc *walk; 252 - int i; 253 249 254 250 atmtcp_dev = (struct atm_dev *) vcc->dev_data; 255 251 dev_data = PRIV(atmtcp_dev); ··· 253 257 if (dev_data->persist) return; 254 258 atmtcp_dev->dev_data = NULL; 255 259 kfree(dev_data); 256 - shutdown_atm_dev(atmtcp_dev); 260 + atm_dev_deregister(atmtcp_dev); 257 261 vcc->dev_data = NULL; 258 - read_lock(&vcc_sklist_lock); 259 - for(i = 0; i < VCC_HTABLE_SIZE; ++i) { 260 - struct hlist_head *head = &vcc_hash[i]; 261 - 262 - sk_for_each(s, node, head) { 263 - walk = atm_sk(s); 264 - if (walk->dev != atmtcp_dev) 265 - continue; 266 - wake_up(s->sk_sleep); 267 - } 268 - } 269 - read_unlock(&vcc_sklist_lock); 270 262 module_put(THIS_MODULE); 271 263 } 272 264 ··· 434 450 if (PRIV(dev)->vcc) return 0; 435 451 kfree(dev_data); 436 452 atm_dev_put(dev); 437 - shutdown_atm_dev(dev); 453 + atm_dev_deregister(dev); 438 454 return 0; 439 455 } 440 456
+2 -2
drivers/usb/atm/usbatm.c
··· 879 879 880 880 fail: 881 881 instance->atm_dev = NULL; 882 - shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */ 882 + atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */ 883 883 return ret; 884 884 } 885 885 ··· 1164 1164 1165 1165 /* ATM finalize */ 1166 1166 if (instance->atm_dev) 1167 - shutdown_atm_dev(instance->atm_dev); 1167 + atm_dev_deregister(instance->atm_dev); 1168 1168 1169 1169 usbatm_put_instance(instance); /* taken in usbatm_usb_probe */ 1170 1170 }
+7 -7
include/linux/atmdev.h
··· 274 274 275 275 276 276 enum { 277 - ATM_DF_CLOSE, /* close device when last VCC is closed */ 277 + ATM_DF_REMOVED, /* device was removed from atm_devs list */ 278 278 }; 279 279 280 280 ··· 415 415 int number,unsigned long *flags); /* number == -1: pick first available */ 416 416 struct atm_dev *atm_dev_lookup(int number); 417 417 void atm_dev_deregister(struct atm_dev *dev); 418 - void shutdown_atm_dev(struct atm_dev *dev); 419 418 void vcc_insert_socket(struct sock *sk); 420 419 421 420 ··· 456 457 457 458 static inline void atm_dev_put(struct atm_dev *dev) 458 459 { 459 - atomic_dec(&dev->refcnt); 460 - 461 - if ((atomic_read(&dev->refcnt) == 1) && 462 - test_bit(ATM_DF_CLOSE,&dev->flags)) 463 - shutdown_atm_dev(dev); 460 + if (atomic_dec_and_test(&dev->refcnt)) { 461 + BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags)); 462 + if (dev->ops->dev_close) 463 + dev->ops->dev_close(dev); 464 + kfree(dev); 465 + } 464 466 } 465 467 466 468
+27 -3
net/atm/common.c
··· 221 221 EXPORT_SYMBOL(vcc_release_async); 222 222 223 223 224 + void atm_dev_release_vccs(struct atm_dev *dev) 225 + { 226 + int i; 227 + 228 + write_lock_irq(&vcc_sklist_lock); 229 + for (i = 0; i < VCC_HTABLE_SIZE; i++) { 230 + struct hlist_head *head = &vcc_hash[i]; 231 + struct hlist_node *node, *tmp; 232 + struct sock *s; 233 + struct atm_vcc *vcc; 234 + 235 + sk_for_each_safe(s, node, tmp, head) { 236 + vcc = atm_sk(s); 237 + if (vcc->dev == dev) { 238 + vcc_release_async(vcc, -EPIPE); 239 + sk_del_node_init(s); 240 + } 241 + } 242 + } 243 + write_unlock_irq(&vcc_sklist_lock); 244 + } 245 + 246 + 224 247 static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) 225 248 { 226 249 int max_sdu; ··· 355 332 return -EINVAL; 356 333 if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE)) 357 334 return -EPERM; 358 - error = 0; 335 + error = -ENODEV; 359 336 if (!try_module_get(dev->ops->owner)) 360 - return -ENODEV; 337 + return error; 361 338 vcc->dev = dev; 362 339 write_lock_irq(&vcc_sklist_lock); 363 - if ((error = find_ci(vcc, &vpi, &vci))) { 340 + if (test_bit(ATM_DF_REMOVED, &dev->flags) || 341 + (error = find_ci(vcc, &vpi, &vci))) { 364 342 write_unlock_irq(&vcc_sklist_lock); 365 343 goto fail_module_put; 366 344 }
+2
net/atm/common.h
··· 47 47 /* SVC */ 48 48 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); 49 49 50 + void atm_dev_release_vccs(struct atm_dev *dev); 51 + 50 52 #endif
+11 -26
net/atm/resources.c
··· 70 70 return dev; 71 71 } 72 72 73 + 73 74 struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, 74 75 int number, unsigned long *flags) 75 76 { ··· 124 123 125 124 void atm_dev_deregister(struct atm_dev *dev) 126 125 { 127 - unsigned long warning_time; 126 + BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags)); 127 + set_bit(ATM_DF_REMOVED, &dev->flags); 128 128 129 - atm_proc_dev_deregister(dev); 130 - 129 + /* 130 + * if we remove current device from atm_devs list, new device 131 + * with same number can appear, such we need deregister proc, 132 + * release async all vccs and remove them from vccs list too 133 + */ 131 134 down(&atm_dev_mutex); 132 135 list_del(&dev->dev_list); 133 136 up(&atm_dev_mutex); 134 137 135 - warning_time = jiffies; 136 - while (atomic_read(&dev->refcnt) != 1) { 137 - msleep(250); 138 - if ((jiffies - warning_time) > 10 * HZ) { 139 - printk(KERN_EMERG "atm_dev_deregister: waiting for " 140 - "dev %d to become free. Usage count = %d\n", 141 - dev->number, atomic_read(&dev->refcnt)); 142 - warning_time = jiffies; 143 - } 144 - } 138 + atm_dev_release_vccs(dev); 139 + atm_proc_dev_deregister(dev); 145 140 146 - kfree(dev); 147 - } 148 - 149 - void shutdown_atm_dev(struct atm_dev *dev) 150 - { 151 - if (atomic_read(&dev->refcnt) > 1) { 152 - set_bit(ATM_DF_CLOSE, &dev->flags); 153 - return; 154 - } 155 - if (dev->ops->dev_close) 156 - dev->ops->dev_close(dev); 157 - atm_dev_deregister(dev); 141 + atm_dev_put(dev); 158 142 } 159 143 160 144 ··· 419 433 EXPORT_SYMBOL(atm_dev_register); 420 434 EXPORT_SYMBOL(atm_dev_deregister); 421 435 EXPORT_SYMBOL(atm_dev_lookup); 422 - EXPORT_SYMBOL(shutdown_atm_dev);