Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64bf69dd authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by David S. Miller
Browse files

[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: default avatarStanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: default avatarChas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aaaaaadb
Loading
Loading
Loading
Loading
+2 −18
Original line number Diff line number Diff line
@@ -246,10 +246,6 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
{
	struct atm_dev *atmtcp_dev;
	struct atmtcp_dev_data *dev_data;
	struct sock *s;
	struct hlist_node *node;
	struct atm_vcc *walk;
	int i;

	atmtcp_dev = (struct atm_dev *) vcc->dev_data;
	dev_data = PRIV(atmtcp_dev);
@@ -257,20 +253,8 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
	if (dev_data->persist) return;
	atmtcp_dev->dev_data = NULL;
	kfree(dev_data);
	shutdown_atm_dev(atmtcp_dev);
	atm_dev_deregister(atmtcp_dev);
	vcc->dev_data = NULL;
	read_lock(&vcc_sklist_lock);
	for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
		struct hlist_head *head = &vcc_hash[i];

		sk_for_each(s, node, head) {
			walk = atm_sk(s);
			if (walk->dev != atmtcp_dev)
				continue;
			wake_up(s->sk_sleep);
		}
	}
	read_unlock(&vcc_sklist_lock);
	module_put(THIS_MODULE);
}

@@ -450,7 +434,7 @@ static int atmtcp_remove_persistent(int itf)
	if (PRIV(dev)->vcc) return 0;
	kfree(dev_data);
	atm_dev_put(dev);
	shutdown_atm_dev(dev);
	atm_dev_deregister(dev);
	return 0;
}

+2 −2
Original line number Diff line number Diff line
@@ -879,7 +879,7 @@ static int usbatm_atm_init(struct usbatm_data *instance)

 fail:
	instance->atm_dev = NULL;
	shutdown_atm_dev(atm_dev); /* usbatm_atm_dev_close will eventually be called */
	atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */
	return ret;
}

@@ -1164,7 +1164,7 @@ void usbatm_usb_disconnect(struct usb_interface *intf)

	/* ATM finalize */
	if (instance->atm_dev)
		shutdown_atm_dev(instance->atm_dev);
		atm_dev_deregister(instance->atm_dev);

	usbatm_put_instance(instance);	/* taken in usbatm_usb_probe */
}
+7 −7
Original line number Diff line number Diff line
@@ -274,7 +274,7 @@ enum {


enum {
	ATM_DF_CLOSE,		/* close device when last VCC is closed */
	ATM_DF_REMOVED,		/* device was removed from atm_devs list */
};


@@ -415,7 +415,6 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
    int number,unsigned long *flags); /* number == -1: pick first available */
struct atm_dev *atm_dev_lookup(int number);
void atm_dev_deregister(struct atm_dev *dev);
void shutdown_atm_dev(struct atm_dev *dev);
void vcc_insert_socket(struct sock *sk);


@@ -457,11 +456,12 @@ static inline void atm_dev_hold(struct atm_dev *dev)

static inline void atm_dev_put(struct atm_dev *dev)
{
	atomic_dec(&dev->refcnt);

	if ((atomic_read(&dev->refcnt) == 1) &&
	    test_bit(ATM_DF_CLOSE,&dev->flags))
		shutdown_atm_dev(dev);
	if (atomic_dec_and_test(&dev->refcnt)) {
		BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
		if (dev->ops->dev_close)
			dev->ops->dev_close(dev);
		kfree(dev);
	}
}


+27 −3
Original line number Diff line number Diff line
@@ -221,6 +221,29 @@ void vcc_release_async(struct atm_vcc *vcc, int reply)
EXPORT_SYMBOL(vcc_release_async);


void atm_dev_release_vccs(struct atm_dev *dev)
{
	int i;

	write_lock_irq(&vcc_sklist_lock);
	for (i = 0; i < VCC_HTABLE_SIZE; i++) {
		struct hlist_head *head = &vcc_hash[i];
		struct hlist_node *node, *tmp;
		struct sock *s;
		struct atm_vcc *vcc;

		sk_for_each_safe(s, node, tmp, head) {
			vcc = atm_sk(s);
			if (vcc->dev == dev) {
				vcc_release_async(vcc, -EPIPE);
				sk_del_node_init(s);
			}
		}
	}
	write_unlock_irq(&vcc_sklist_lock);
}


static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
{
	int max_sdu;
@@ -332,12 +355,13 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
		return -EINVAL;
	if (vci > 0 && vci < ATM_NOT_RSV_VCI && !capable(CAP_NET_BIND_SERVICE))
		return -EPERM;
	error = 0;
	error = -ENODEV;
	if (!try_module_get(dev->ops->owner))
		return -ENODEV;
		return error;
	vcc->dev = dev;
	write_lock_irq(&vcc_sklist_lock);
	if ((error = find_ci(vcc, &vpi, &vci))) {
	if (test_bit(ATM_DF_REMOVED, &dev->flags) || 
	    (error = find_ci(vcc, &vpi, &vci))) {
		write_unlock_irq(&vcc_sklist_lock);
		goto fail_module_put;
	}
+2 −0
Original line number Diff line number Diff line
@@ -47,4 +47,6 @@ static inline void atm_proc_exit(void)
/* SVC */
int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);

void atm_dev_release_vccs(struct atm_dev *dev);

#endif
Loading