2000-11-22 10:02:19

by Patrick vd Lageweg

[permalink] [raw]
Subject: [PATCH] atmrefcount

Hi Linus,

This patch contains the fix for the atmrefcount problem (noted as a
critical problem in Ted's todo list). It also has the makefile
modifications for the firestream driver in a separate email.


Patrick

diff -u -r linux-2.4.0-test11.clean/drivers/atm/Config.in linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/Config.in
--- linux-2.4.0-test11.clean/drivers/atm/Config.in Wed Jul 12 12:24:48 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/Config.in Wed Nov 22 08:59:12 2000
@@ -22,6 +22,7 @@
bool ' Enable 2W RX bursts (optional)' CONFIG_ATM_ENI_BURST_RX_2W
fi
fi
+ tristate 'Fujitsu FireStream (FS50/FS155) ' CONFIG_ATM_FIRESTREAM
tristate 'ZeitNet ZN1221/ZN1225' CONFIG_ATM_ZATM
if [ "$CONFIG_ATM_ZATM" != "n" ]; then
bool ' Enable extended debugging' CONFIG_ATM_ZATM_DEBUG
diff -u -r linux-2.4.0-test11.clean/drivers/atm/Makefile linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/Makefile
--- linux-2.4.0-test11.clean/drivers/atm/Makefile Sun Aug 6 20:23:40 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/Makefile Wed Nov 22 08:59:12 2000
@@ -19,6 +19,14 @@
endif
endif

+ifeq ($(CONFIG_ATM_FIRESTREAM),y)
+O_OBJS += firestream.o
+else
+ ifeq ($(CONFIG_ATM_FIRESTREAM),m)
+ M_OBJS += firestream.o
+ endif
+endif
+
ifeq ($(CONFIG_ATM_ZATM),y)
O_OBJS += zatm.o
OX_OBJS += uPD98402.o
diff -u -r linux-2.4.0-test11.clean/drivers/atm/ambassador.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/ambassador.c
--- linux-2.4.0-test11.clean/drivers/atm/ambassador.c Wed Jul 12 12:25:48 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/ambassador.c Wed Nov 22 08:59:12 2000
@@ -1251,15 +1251,10 @@
}
}

- // prevent module unload while sleeping (kmalloc/down)
- // doing this any earlier would complicate more error return paths
- MOD_INC_USE_COUNT;
-
// get space for our vcc stuff
vcc = kmalloc (sizeof(amb_vcc), GFP_KERNEL);
if (!vcc) {
PRINTK (KERN_ERR, "out of memory!");
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
atm_vcc->dev_data = (void *) vcc;
@@ -1425,7 +1420,6 @@
// say the VPI/VCI is free again
clear_bit(ATM_VF_ADDR,&atm_vcc->flags);

- MOD_DEC_USE_COUNT;
return;
}

@@ -1703,7 +1697,8 @@
close: amb_close,
send: amb_send,
sg_send: amb_sg_send,
- proc_read: amb_proc_read
+ proc_read: amb_proc_read,
+ owner: THIS_MODULE,
};

/********** housekeeping **********/
diff -u -r linux-2.4.0-test11.clean/drivers/atm/atmdev_init.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/atmdev_init.c
--- linux-2.4.0-test11.clean/drivers/atm/atmdev_init.c Fri Apr 14 18:37:10 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/atmdev_init.c Wed Nov 22 08:59:12 2000
@@ -54,7 +54,10 @@
devs += ia_detect();
#endif
#ifdef CONFIG_ATM_FORE200E
- devs += fore200e_detect();
+ devs += fore200e_detect();
+#endif
+#ifdef CONFIG_ATM_FIRESTREAM
+ devs += fs_detect();
#endif
return devs;
}
diff -u -r linux-2.4.0-test11.clean/drivers/atm/atmtcp.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/atmtcp.c
--- linux-2.4.0-test11.clean/drivers/atm/atmtcp.c Wed Jul 12 12:24:48 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/atmtcp.c Wed Nov 22 08:59:12 2000
@@ -109,7 +109,7 @@

static void atmtcp_v_dev_close(struct atm_dev *dev)
{
- MOD_DEC_USE_COUNT;
+ /* Nothing.... Isn't this simple :-) -- REW */
}


@@ -297,7 +297,8 @@
close: atmtcp_v_close,
ioctl: atmtcp_v_ioctl,
send: atmtcp_v_send,
- proc_read: atmtcp_v_proc
+ proc_read: atmtcp_v_proc,
+ owner: THIS_MODULE
};


@@ -330,18 +331,13 @@
struct atmtcp_dev_data *dev_data;
struct atm_dev *dev;

- MOD_INC_USE_COUNT;
-
dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL);
- if (!dev_data) {
- MOD_DEC_USE_COUNT;
+ if (!dev_data)
return -ENOMEM;
- }

dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,NULL);
if (!dev) {
kfree(dev_data);
- MOD_DEC_USE_COUNT;
return itf == -1 ? -ENOMEM : -EBUSY;
}
dev->ci_range.vpi_bits = MAX_VPI_BITS;
diff -u -r linux-2.4.0-test11.clean/drivers/atm/fore200e.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/fore200e.c
--- linux-2.4.0-test11.clean/drivers/atm/fore200e.c Wed Nov 1 13:57:15 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/fore200e.c Wed Nov 22 08:59:12 2000
@@ -1407,8 +1407,6 @@
struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
struct fore200e_vcc* fore200e_vcc;

- MOD_INC_USE_COUNT;
-
/* find a free VPI/VCI */
fore200e_walk_vccs(vcc, &vpi, &vci);

@@ -1416,10 +1414,8 @@
vcc->vci = vci;

/* ressource checking only? */
- if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) {
- MOD_DEC_USE_COUNT;
+ if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
return 0;
- }

set_bit(ATM_VF_ADDR, &vcc->flags);
vcc->itf = vcc->dev->number;
@@ -1437,7 +1433,6 @@
down(&fore200e->rate_sf);
if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
up(&fore200e->rate_sf);
- MOD_DEC_USE_COUNT;
return -EAGAIN;
}
/* reserving the pseudo-CBR bandwidth at this point grants us
@@ -1454,7 +1449,6 @@
down(&fore200e->rate_sf);
fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
up(&fore200e->rate_sf);
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}

@@ -1465,7 +1459,6 @@
down(&fore200e->rate_sf);
fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
up(&fore200e->rate_sf);
- MOD_DEC_USE_COUNT;
return -EBUSY;
}

@@ -1498,10 +1491,6 @@

fore200e_activate_vcin(fore200e, 0, vcc, 0);

-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
-
kfree(FORE200E_VCC(vcc));

if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
@@ -2599,8 +2588,6 @@

printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n");

- MOD_INC_USE_COUNT;
-
/* for each configured bus interface */
for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {

@@ -2626,9 +2613,6 @@
}
}

- if (link <= 0)
- MOD_DEC_USE_COUNT;
-
return link;
}

@@ -2943,21 +2927,15 @@

static const struct atmdev_ops fore200e_ops =
{
- NULL, /* fore200e_dev_close */
- fore200e_open,
- fore200e_close,
- fore200e_ioctl,
- fore200e_getsockopt,
- fore200e_setsockopt,
- fore200e_send,
- NULL, /* fore200e_sg_send, */
- NULL, /* fore200e_send_oam, */
- NULL, /* fore200e_phy_put, */
- NULL, /* fore200e_phy_get, */
- NULL, /* fore200e_feedback, */
- fore200e_change_qos,
- NULL, /* fore200e_free_rx_skb */
- fore200e_proc_read
+ open: fore200e_open,
+ close: fore200e_close,
+ ioctl: fore200e_ioctl,
+ getsockopt: fore200e_getsockopt,
+ setsockopt: fore200e_setsockopt,
+ send: fore200e_send,
+ change_qos: fore200e_change_qos,
+ proc_read: fore200e_proc_read,
+ owner: THIS_MODULE,
};


diff -u -r linux-2.4.0-test11.clean/drivers/atm/horizon.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/horizon.c
--- linux-2.4.0-test11.clean/drivers/atm/horizon.c Wed Jul 12 12:25:48 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/horizon.c Wed Nov 22 08:59:12 2000
@@ -2491,15 +2491,10 @@
return -EINVAL;
}

- // prevent module unload while sleeping (kmalloc)
- // doing this any earlier would complicate more error return paths
- MOD_INC_USE_COUNT;
-
// get space for our vcc stuff and copy parameters into it
vccp = kmalloc (sizeof(hrz_vcc), GFP_KERNEL);
if (!vccp) {
PRINTK (KERN_ERR, "out of memory!");
- MOD_DEC_USE_COUNT;
return -ENOMEM;
}
*vccp = vcc;
@@ -2531,7 +2526,6 @@
if (error) {
PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources");
kfree (vccp);
- MOD_DEC_USE_COUNT;
return error;
}

@@ -2550,7 +2544,6 @@
error = hrz_open_rx (dev, channel);
if (error) {
kfree (vccp);
- MOD_DEC_USE_COUNT;
return error;
}
// this link allows RX frames through
@@ -2620,7 +2613,6 @@
kfree (vcc);
// say the VPI/VCI is free again
clear_bit(ATM_VF_ADDR,&atm_vcc->flags);
- MOD_DEC_USE_COUNT;
}

#if 0
@@ -2751,7 +2743,8 @@
close: hrz_close,
send: hrz_send,
sg_send: hrz_sg_send,
- proc_read: hrz_proc_read
+ proc_read: hrz_proc_read,
+ owner: THIS_MODULE,
};

static int __init hrz_probe (void) {
diff -u -r linux-2.4.0-test11.clean/drivers/atm/iphase.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/iphase.c
--- linux-2.4.0-test11.clean/drivers/atm/iphase.c Mon Aug 7 07:20:09 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/iphase.c Wed Nov 22 08:59:12 2000
@@ -3143,7 +3143,8 @@
phy_put: ia_phy_put,
phy_get: ia_phy_get,
change_qos: ia_change_qos,
- proc_read: ia_proc_read
+ proc_read: ia_proc_read,
+ owner: THIS_MODULE,
};


@@ -3219,7 +3220,6 @@
printk(KERN_ERR DEV_LABEL ": no adapter found\n");
return -ENXIO;
}
- // MOD_INC_USE_COUNT;
ia_timer.expires = jiffies + 3*HZ;
add_timer(&ia_timer);

@@ -3235,7 +3235,6 @@
int i, j= 0;

IF_EVENT(printk(">ia cleanup_module\n");)
- // MOD_DEC_USE_COUNT;
if (MOD_IN_USE)
printk("ia: module in use\n");
del_timer(&ia_timer);
diff -u -r linux-2.4.0-test11.clean/drivers/atm/nicstar.c linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/nicstar.c
--- linux-2.4.0-test11.clean/drivers/atm/nicstar.c Wed Nov 1 13:57:15 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/atm/nicstar.c Wed Nov 22 08:59:12 2000
@@ -268,7 +268,8 @@
send: ns_send,
phy_put: ns_phy_put,
phy_get: ns_phy_get,
- proc_read: ns_proc_read
+ proc_read: ns_proc_read,
+ owner: THIS_MODULE,
};
static struct timer_list ns_timer;
static char *mac[NS_MAX_CARDS] = { NULL
@@ -1649,7 +1650,6 @@
}

set_bit(ATM_VF_READY,&vcc->flags);
- MOD_INC_USE_COUNT;
return 0;
}

@@ -1778,7 +1778,6 @@
vcc->dev_data = NULL;
clear_bit(ATM_VF_PARTIAL,&vcc->flags);
clear_bit(ATM_VF_ADDR,&vcc->flags);
- MOD_DEC_USE_COUNT;

#ifdef RX_DEBUG
{
diff -u -r linux-2.4.0-test11.clean/drivers/pci/pci.ids linux-2.4.0-test11.fs50+atmrefcount/drivers/pci/pci.ids
--- linux-2.4.0-test11.clean/drivers/pci/pci.ids Wed Nov 1 13:57:30 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/drivers/pci/pci.ids Wed Nov 22 08:59:13 2000
@@ -2438,7 +2438,9 @@
1221 82C092G
119c Information Technology Inst.
119d Bug, Inc. Sapporo Japan
-119e Fujitsu Microelectronics Ltd.
+119e Fujitsu Microelectronics Europe GMBH
+ 0001 FireStream 155
+ 0003 FireStream 50
119f Bull HN Information Systems
11a0 Convex Computer Corporation
11a1 Hamamatsu Photonics K.K.
diff -u -r linux-2.4.0-test11.clean/include/linux/atm_tcp.h linux-2.4.0-test11.fs50+atmrefcount/include/linux/atm_tcp.h
--- linux-2.4.0-test11.clean/include/linux/atm_tcp.h Fri Oct 27 14:00:45 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/include/linux/atm_tcp.h Wed Nov 22 09:16:47 2000
@@ -65,6 +65,7 @@
int (*attach)(struct atm_vcc *vcc,int itf);
int (*create_persistent)(int itf);
int (*remove_persistent)(int itf);
+ struct module *owner;
};

extern struct atm_tcp_ops atm_tcp_ops;
diff -u -r linux-2.4.0-test11.clean/include/linux/atmdev.h linux-2.4.0-test11.fs50+atmrefcount/include/linux/atmdev.h
--- linux-2.4.0-test11.clean/include/linux/atmdev.h Mon Nov 13 15:17:50 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/include/linux/atmdev.h Wed Nov 22 09:17:01 2000
@@ -375,6 +375,7 @@
void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb);
/* @@@ temporary hack */
int (*proc_read)(struct atm_dev *dev,loff_t *pos,char *page);
+ struct module *owner;
};


diff -u -r linux-2.4.0-test11.clean/include/linux/pci_ids.h linux-2.4.0-test11.fs50+atmrefcount/include/linux/pci_ids.h
--- linux-2.4.0-test11.clean/include/linux/pci_ids.h Wed Nov 1 13:57:45 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/include/linux/pci_ids.h Wed Nov 22 08:59:13 2000
@@ -871,6 +871,10 @@
#define PCI_VENDOR_ID_OMEGA 0x119b
#define PCI_DEVICE_ID_OMEGA_82C092G 0x1221

+#define PCI_VENDOR_ID_FUJITSU_ME 0x119e
+#define PCI_DEVICE_ID_FUJITSU_FS155 0x0001
+#define PCI_DEVICE_ID_FUJITSU_FS50 0x0003
+
#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9
#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334

diff -u -r linux-2.4.0-test11.clean/net/atm/addr.c linux-2.4.0-test11.fs50+atmrefcount/net/atm/addr.c
--- linux-2.4.0-test11.clean/net/atm/addr.c Wed Mar 22 08:38:26 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/net/atm/addr.c Wed Nov 22 08:59:13 2000
@@ -42,7 +42,7 @@
*/

static DECLARE_MUTEX(local_lock);
-
+extern spinlock_t atm_dev_lock;

static void notify_sigd(struct atm_dev *dev)
{
@@ -58,12 +58,14 @@
struct atm_dev_addr *this;

down(&local_lock);
+ spin_lock (&atm_dev_lock);
while (dev->local) {
this = dev->local;
dev->local = this->next;
kfree(this);
}
up(&local_lock);
+ spin_unlock (&atm_dev_lock);
notify_sigd(dev);
}

diff -u -r linux-2.4.0-test11.clean/net/atm/common.c linux-2.4.0-test11.fs50+atmrefcount/net/atm/common.c
--- linux-2.4.0-test11.clean/net/atm/common.c Wed Jul 12 12:26:08 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/net/atm/common.c Wed Nov 22 08:59:13 2000
@@ -72,6 +72,7 @@
#define DPRINTK(format,args...)
#endif

+spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;

static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
{
@@ -139,13 +140,19 @@
vcc->dev->ops->free_rx_skb(vcc,skb);
else kfree_skb(skb);
}
+ spin_lock (&atm_dev_lock);
+ fops_put (vcc->dev->ops);
if (atomic_read(&vcc->rx_inuse))
printk(KERN_WARNING "atm_release_vcc: strange ... "
"rx_inuse == %d after closing\n",
atomic_read(&vcc->rx_inuse));
bind_vcc(vcc,NULL);
- }
+ } else
+ spin_lock (&atm_dev_lock);
+
if (free_sk) free_atm_vcc_sk(sk);
+
+ spin_unlock (&atm_dev_lock);
}


@@ -238,9 +245,11 @@
vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
+ fops_get (dev->ops);
if (dev->ops->open) {
error = dev->ops->open(vcc,vpi,vci);
if (error) {
+ fops_put (dev->ops);
bind_vcc(vcc,NULL);
return error;
}
@@ -252,10 +261,18 @@
static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
{
struct atm_dev *dev;
+ int return_val;

+ spin_lock (&atm_dev_lock);
dev = atm_find_dev(itf);
- if (!dev) return -ENODEV;
- return atm_do_connect_dev(vcc,dev,vpi,vci);
+ if (!dev)
+ return_val = -ENODEV;
+ else
+ return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
+
+ spin_unlock (&atm_dev_lock);
+
+ return return_val;
}


@@ -285,8 +302,10 @@
else {
struct atm_dev *dev;

+ spin_lock (&atm_dev_lock);
for (dev = atm_devs; dev; dev = dev->next)
if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
+ spin_unlock (&atm_dev_lock);
if (!dev) return -ENODEV;
}
if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
@@ -523,57 +542,86 @@
struct atm_vcc *vcc;
int *tmp_buf;
void *buf;
- int error,len,size,number;
+ int error,len,size,number, ret_val;

+ ret_val = 0;
+ spin_lock (&atm_dev_lock);
vcc = ATM_SD(sock);
switch (cmd) {
case SIOCOUTQ:
if (sock->state != SS_CONNECTED ||
- !test_bit(ATM_VF_READY,&vcc->flags))
- return -EINVAL;
- return put_user(vcc->sk->sndbuf-
+ !test_bit(ATM_VF_READY,&vcc->flags)) {
+ ret_val = -EINVAL;
+ goto done;
+ }
+ ret_val = put_user(vcc->sk->sndbuf-
atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
(int *) arg) ? -EFAULT : 0;
+ goto done;
case SIOCINQ:
{
struct sk_buff *skb;

- if (sock->state != SS_CONNECTED)
- return -EINVAL;
+ if (sock->state != SS_CONNECTED) {
+ ret_val = -EINVAL;
+ goto done;
+ }
skb = skb_peek(&vcc->recvq);
- return put_user(skb ? skb->len : 0,(int *) arg)
+ ret_val = put_user(skb ? skb->len : 0,(int *) arg)
? -EFAULT : 0;
+ goto done;
}
case ATM_GETNAMES:
if (get_user(buf,
- &((struct atm_iobuf *) arg)->buffer))
- return -EFAULT;
+ &((struct atm_iobuf *) arg)->buffer)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
if (get_user(len,
- &((struct atm_iobuf *) arg)->length))
- return -EFAULT;
+ &((struct atm_iobuf *) arg)->length)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
size = 0;
for (dev = atm_devs; dev; dev = dev->next)
size += sizeof(int);
- if (size > len) return -E2BIG;
+ if (size > len) {
+ ret_val = -E2BIG;
+ goto done;
+ }
tmp_buf = kmalloc(size,GFP_KERNEL);
- if (!tmp_buf) return -ENOMEM;
+ if (!tmp_buf) {
+ ret_val = -ENOMEM;
+ goto done;
+ }
for (dev = atm_devs; dev; dev = dev->next)
*tmp_buf++ = dev->number;
- if (copy_to_user(buf,(char *) tmp_buf-size,size))
- return -EFAULT;
- return put_user(size,
+ if (copy_to_user(buf,(char *) tmp_buf-size,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ ret_val = put_user(size,
&((struct atm_iobuf *) arg)->length) ? -EFAULT : 0;
+ goto done;
case SIOCGSTAMP: /* borrowed from IP */
- if (!vcc->timestamp.tv_sec) return -ENOENT;
+ if (!vcc->timestamp.tv_sec) {
+ ret_val = -ENOENT;
+ goto done;
+ }
vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000;
vcc->timestamp.tv_usec %= 1000000;
- return copy_to_user((void *) arg,&vcc->timestamp,
+ ret_val = copy_to_user((void *) arg,&vcc->timestamp,
sizeof(struct timeval)) ? -EFAULT : 0;
+ goto done;
case ATM_SETSC:
printk(KERN_WARNING "ATM_SETSC is obsolete\n");
- return 0;
+ ret_val = 0;
+ goto done;
case ATMSIGD_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/*
* The user/kernel protocol for exchanging signalling
* info uses kernel pointers as opaque references,
@@ -581,175 +629,308 @@
* on the kernel... so we should make sure that we
* have the same privledges that /proc/kcore needs
*/
- if (!capable(CAP_SYS_RAWIO)) return -EPERM;
+ if (!capable(CAP_SYS_RAWIO)) {
+ ret_val = -EPERM;
+ goto done;
+ }
error = sigd_attach(vcc);
if (!error) sock->state = SS_CONNECTED;
- return error;
+ ret_val = error;
+ goto done;
#ifdef CONFIG_ATM_CLIP
case SIOCMKCLIP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_create(arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_create(arg);
+ goto done;
case ATMARPD_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
error = atm_init_atmarp(vcc);
if (!error) sock->state = SS_CONNECTED;
- return error;
+ ret_val = error;
+ goto done;
case ATMARP_MKIP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_mkip(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_mkip(vcc,arg);
+ goto done;
case ATMARP_SETENTRY:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_setentry(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_setentry(vcc,arg);
+ goto done;
case ATMARP_ENCAP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_encap(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_encap(vcc,arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
case ATMLEC_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
if (atm_lane_ops.lecd_attach == NULL)
atm_lane_init();
- if (atm_lane_ops.lecd_attach == NULL) /* try again */
- return -ENOSYS;
- error = atm_lane_ops.lecd_attach(vcc, (int)arg);
- if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ if (atm_lane_ops.lecd_attach == NULL) { /* try again */
+ ret_val = -ENOSYS;
+ goto done;
+ }
+ error = atm_lane_ops.lecd_attach(vcc, (int)arg);
+ if (error >= 0) sock->state = SS_CONNECTED;
+ ret_val = error;
+ goto done;
case ATMLEC_MCAST:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_lane_ops.mcast_attach(vcc, (int)arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
+ goto done;
case ATMLEC_DATA:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_lane_ops.vcc_attach(vcc, (void*)arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
case ATMMPC_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (atm_mpoa_ops.mpoad_attach == NULL)
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (atm_mpoa_ops.mpoad_attach == NULL)
atm_mpoa_init();
- if (atm_mpoa_ops.mpoad_attach == NULL) /* try again */
- return -ENOSYS;
- error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
- if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
+ ret_val = -ENOSYS;
+ goto done;
+ }
+ error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
+ if (error >= 0) sock->state = SS_CONNECTED;
+ ret_val = error;
+ goto done;
case ATMMPC_DATA:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_mpoa_ops.vcc_attach(vcc, arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
case SIOCSIFATMTCP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.attach) return -ENOPKG;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.attach) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ fops_get (&atm_tcp_ops);
error = atm_tcp_ops.attach(vcc,(int) arg);
if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ else fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
case ATMTCP_CREATE:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.create_persistent) return -ENOPKG;
- return atm_tcp_ops.create_persistent((int) arg);
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.create_persistent) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ error = atm_tcp_ops.create_persistent((int) arg);
+ if (error < 0) fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
case ATMTCP_REMOVE:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.remove_persistent) return -ENOPKG;
- return atm_tcp_ops.remove_persistent((int) arg);
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.remove_persistent) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ error = atm_tcp_ops.remove_persistent((int) arg);
+ fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
#endif
default:
break;
}
- if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) return -EFAULT;
- if (get_user(len,&((struct atmif_sioc *) arg)->length)) return -EFAULT;
- if (get_user(number,&((struct atmif_sioc *) arg)->number))
- return -EFAULT;
- if (!(dev = atm_find_dev(number))) return -ENODEV;
+ if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (get_user(len,&((struct atmif_sioc *) arg)->length)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (get_user(number,&((struct atmif_sioc *) arg)->number)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (!(dev = atm_find_dev(number))) {
+ ret_val = -ENODEV;
+ goto done;
+ }
+
size = 0;
switch (cmd) {
case ATM_GETTYPE:
size = strlen(dev->type)+1;
- if (copy_to_user(buf,dev->type,size)) return -EFAULT;
+ if (copy_to_user(buf,dev->type,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_GETESI:
size = ESI_LEN;
- if (copy_to_user(buf,dev->esi,size)) return -EFAULT;
+ if (copy_to_user(buf,dev->esi,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_SETESI:
{
int i;

for (i = 0; i < ESI_LEN; i++)
- if (dev->esi[i]) return -EEXIST;
+ if (dev->esi[i]) {
+ ret_val = -EEXIST;
+ goto done;
+ }
}
/* fall through */
case ATM_SETESIF:
{
unsigned char esi[ESI_LEN];

- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (copy_from_user(esi,buf,ESI_LEN))
- return -EFAULT;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (copy_from_user(esi,buf,ESI_LEN)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
memcpy(dev->esi,esi,ESI_LEN);
- return ESI_LEN;
+ ret_val = ESI_LEN;
+ goto done;
}
case ATM_GETSTATZ:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/* fall through */
case ATM_GETSTAT:
size = sizeof(struct atm_dev_stats);
error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ);
- if (error) return error;
+ if (error) {
+ ret_val = error;
+ goto done;
+ }
break;
case ATM_GETCIRANGE:
size = sizeof(struct atm_cirange);
- if (copy_to_user(buf,&dev->ci_range,size))
- return -EFAULT;
+ if (copy_to_user(buf,&dev->ci_range,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_GETLINKRATE:
size = sizeof(int);
- if (copy_to_user(buf,&dev->link_rate,size))
- return -EFAULT;
+ if (copy_to_user(buf,&dev->link_rate,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_RSTADDR:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
reset_addr(dev);
break;
case ATM_ADDADDR:
case ATM_DELADDR:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
{
struct sockaddr_atmsvc addr;

- if (copy_from_user(&addr,buf,sizeof(addr)))
- return -EFAULT;
+ if (copy_from_user(&addr,buf,sizeof(addr))) {
+ ret_val = -EFAULT;
+ goto done;
+ }
if (cmd == ATM_ADDADDR)
- return add_addr(dev,&addr);
- else return del_addr(dev,&addr);
+ ret_val = add_addr(dev,&addr);
+ else
+ ret_val = del_addr(dev,&addr);
+ goto done;
}
case ATM_GETADDR:
size = get_addr(dev,buf,len);
- if (size < 0) return size;
+ if (size < 0)
+ ret_val = size;
+ else
/* may return 0, but later on size == 0 means "don't
write the length" */
- return put_user(size,
- &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+ ret_val = put_user(size,
+ &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+ goto done;
case ATM_SETLOOP:
if (__ATM_LM_XTRMT((int) (long) buf) &&
__ATM_LM_XTLOC((int) (long) buf) >
- __ATM_LM_XTRMT((int) (long) buf))
- return -EINVAL;
+ __ATM_LM_XTRMT((int) (long) buf)) {
+ ret_val = -EINVAL;
+ goto done;
+ }
/* fall through */
case ATM_SETCIRANGE:
case SONET_GETSTATZ:
case SONET_SETDIAG:
case SONET_CLRDIAG:
case SONET_SETFRAMING:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/* fall through */
default:
- if (!dev->ops->ioctl) return -EINVAL;
+ if (!dev->ops->ioctl) {
+ ret_val = -EINVAL;
+ goto done;
+ }
size = dev->ops->ioctl(dev,cmd,buf);
- if (size < 0)
- return size == -ENOIOCTLCMD ? -EINVAL : size;
+ if (size < 0) {
+ ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);
+ goto done;
+ }
}
- if (!size) return 0;
- return put_user(size,&((struct atmif_sioc *) arg)->length) ?
- -EFAULT : 0;
+
+ if (size)
+ ret_val = put_user(size,&((struct atmif_sioc *) arg)->length) ?
+ -EFAULT : 0;
+
+ done:
+ spin_unlock (&atm_dev_lock);
+ return ret_val;
}


diff -u -r linux-2.4.0-test11.clean/net/atm/resources.c linux-2.4.0-test11.fs50+atmrefcount/net/atm/resources.c
--- linux-2.4.0-test11.clean/net/atm/resources.c Thu Oct 19 13:53:13 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/net/atm/resources.c Wed Nov 22 09:08:51 2000
@@ -25,6 +25,7 @@
struct atm_dev *atm_devs = NULL;
static struct atm_dev *last_dev = NULL;
struct atm_vcc *nodev_vccs = NULL;
+extern spinlock_t atm_dev_lock;

static spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;

@@ -38,7 +39,6 @@
memset(dev,0,sizeof(*dev));
dev->type = type;

- printk ("spin_lock alloc_atm_dev\n");
spin_lock (&atm_dev_lock);

dev->prev = last_dev;
@@ -52,7 +52,6 @@


last_dev = dev;
- printk ("spin_unlock alloc_atm_dev\n");
spin_unlock (&atm_dev_lock);

return dev;
@@ -61,11 +60,15 @@

static void free_atm_dev(struct atm_dev *dev)
{
+ spin_lock (&atm_dev_lock);
+
if (dev->prev) dev->prev->next = dev->next;
else atm_devs = dev->next;
if (dev->next) dev->next->prev = dev->prev;
else last_dev = dev->prev;
kfree(dev);
+
+ spin_unlock (&atm_dev_lock);
}


@@ -91,16 +94,13 @@
return NULL;
}
if (number != -1) {
- printk ("spin_lock alloc_atm_dev\n");
spin_lock (&atm_dev_lock);
if (atm_find_dev(number)) {
free_atm_dev(dev);
- printk ("spin_unlock alloc_atm_dev\n");
spin_unlock (&atm_dev_lock);
return NULL;
}
dev->number = number;
- printk ("spin_unlock alloc_atm_dev\n");
spin_unlock (&atm_dev_lock);
}
else {
@@ -119,10 +119,12 @@
if (atm_proc_dev_register(dev) < 0) {
printk(KERN_ERR "atm_dev_register: "
"atm_proc_dev_register failed for dev %s\n",type);
+ spin_unlock (&atm_dev_lock);
free_atm_dev(dev);
return NULL;
}
#endif
+ spin_unlock (&atm_dev_lock);
return dev;
}

diff -u -r linux-2.4.0-test11.clean/net/atm/signaling.c linux-2.4.0-test11.fs50+atmrefcount/net/atm/signaling.c
--- linux-2.4.0-test11.clean/net/atm/signaling.c Wed Aug 2 10:27:14 2000
+++ linux-2.4.0-test11.fs50+atmrefcount/net/atm/signaling.c Wed Nov 22 08:59:13 2000
@@ -33,6 +33,7 @@
struct atm_vcc *sigd = NULL;
static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep);

+extern spinlock_t atm_dev_lock;

static void sigd_put_skb(struct sk_buff *skb)
{
@@ -218,7 +219,10 @@
printk(KERN_ERR "sigd_close: closing with requests pending\n");
while ((skb = skb_dequeue(&vcc->recvq))) kfree_skb(skb);
purge_vccs(nodev_vccs);
+
+ spin_lock (&atm_dev_lock);
for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs);
+ spin_unlock (&atm_dev_lock);
}





2000-11-22 16:33:40

by Mitchell Blank Jr

[permalink] [raw]
Subject: Re: [PATCH] atmrefcount

Patrick van de Lageweg wrote:
> This patch contains the fix for the atmrefcount problem (noted as a
> critical problem in Ted's todo list). It also has the makefile
> modifications for the firestream driver in a separate email.

Could you please split the two patches so that they're actually independant
(i.e. put all the stuff for the new driver in its own patch). I'll
comment on that driver seperately.

-Mitch