diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-05-10 08:00:57 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-05-10 08:00:57 -0700 |
| commit | bb1fe39aab462862f90c4c6904ebdeea481360ef (patch) | |
| tree | b215023cddd2eeaa491e1bac231fc9d34c9ea04e | |
| parent | 278b7cdbd0c4102831c3ba1b4c0cc11a48618eb9 (diff) | |
| parent | 855677ee07ee9f6361dea0de94ccd7404f4e0230 (diff) | |
Merge bk://kernel.bkbits.net/davem/net-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
45 files changed, 306 insertions, 141 deletions
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index cc50547af68a..e89d801d1507 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -362,43 +362,56 @@ he_find_vcc(struct he_dev *he_dev, unsigned cid) static int __devinit he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) { - struct atm_dev *atm_dev; - struct he_dev *he_dev; + struct atm_dev *atm_dev = NULL; + struct he_dev *he_dev = NULL; + int err = 0; printk(KERN_INFO "he: %s\n", version); if (pci_enable_device(pci_dev)) return -EIO; - if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) - { + if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) { printk(KERN_WARNING "he: no suitable dma available\n"); - return -EIO; + err = -EIO; + goto init_one_failure; } atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0); - if (!atm_dev) return -ENODEV; + if (!atm_dev) { + err = -ENODEV; + goto init_one_failure; + } pci_set_drvdata(pci_dev, atm_dev); he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev), GFP_KERNEL); - if (!he_dev) return -ENOMEM; + if (!he_dev) { + err = -ENOMEM; + goto init_one_failure; + } memset(he_dev, 0, sizeof(struct he_dev)); he_dev->pci_dev = pci_dev; he_dev->atm_dev = atm_dev; he_dev->atm_dev->dev_data = he_dev; HE_DEV(atm_dev) = he_dev; - he_dev->number = atm_dev->number; /* was devs */ + he_dev->number = atm_dev->number; if (he_start(atm_dev)) { - atm_dev_deregister(atm_dev); he_stop(he_dev); - kfree(he_dev); - return -ENODEV; + err = -ENODEV; + goto init_one_failure; } he_dev->next = NULL; if (he_devs) he_dev->next = he_devs; he_devs = he_dev; - return 0; + +init_one_failure: + if (atm_dev) + atm_dev_deregister(atm_dev); + if (he_dev) + kfree(he_dev); + pci_disable_device(pci_dev); + return err; } static void __devexit @@ -417,6 +430,7 @@ he_remove_one (struct pci_dev *pci_dev) kfree(he_dev); pci_set_drvdata(pci_dev, NULL); + pci_disable_device(pci_dev); } diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index c2e784c51d0d..680ccf7f4a53 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -2777,7 +2777,7 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) if (!capable(CAP_NET_ADMIN)) return -EPERM; tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - if(put_user(*(u16*)(iadev->seg_reg+i), tmps)) return -EFAULT; + if(put_user((u16)(readl(iadev->seg_reg+i) & 0xffff), tmps)) return -EFAULT; ia_cmds.status = 0; ia_cmds.len = 0x80; break; @@ -2785,7 +2785,7 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) if (!capable(CAP_NET_ADMIN)) return -EPERM; tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - if(put_user(*(u16*)(iadev->reass_reg+i), tmps)) return -EFAULT; + if(put_user((u16)(readl(iadev->reass_reg+i) & 0xffff), tmps)) return -EFAULT; ia_cmds.status = 0; ia_cmds.len = 0x80; break; @@ -2802,10 +2802,10 @@ static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) rfL = ®s_local->rfredn; /* Copy real rfred registers into the local copy */ for (i=0; i<(sizeof (rfredn_t))/4; i++) - ((u_int *)rfL)[i] = ((u_int *)iadev->reass_reg)[i] & 0xffff; + ((u_int *)rfL)[i] = readl(iadev->reass_reg + i) & 0xffff; /* Copy real ffred registers into the local copy */ for (i=0; i<(sizeof (ffredn_t))/4; i++) - ((u_int *)ffL)[i] = ((u_int *)iadev->seg_reg)[i] & 0xffff; + ((u_int *)ffL)[i] = readl(iadev->seg_reg + i) & 0xffff; if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) { kfree(regs_local); diff --git a/include/net/protocol.h b/include/net/protocol.h index 6f0e4234a442..f67327486a9c 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -80,11 +80,9 @@ struct inet_protosw { extern struct inet_protocol *inet_protocol_base; extern struct inet_protocol *inet_protos[MAX_INET_PROTOS]; -extern struct list_head inetsw[SOCK_MAX]; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; -extern struct list_head inetsw6[SOCK_MAX]; #endif extern int inet_add_protocol(struct inet_protocol *prot, unsigned char num); diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index be15a34cfbdb..b8e70418ce5f 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -18,6 +18,7 @@ *****************************************************************************/ #include <linux/config.h> +#include <linux/module.h> #include <linux/stddef.h> /* offsetof(), etc. */ #include <linux/errno.h> /* return codes */ #include <linux/kernel.h> @@ -75,6 +76,7 @@ static char term_msg[] = "***KERNEL: Out of buffer space!***\n"; */ static struct file_operations vlan_fops = { + .owner = THIS_MODULE, .read = vlan_proc_read, .ioctl = NULL, /* vlan_proc_ioctl */ }; @@ -84,6 +86,7 @@ static struct file_operations vlan_fops = { */ static struct file_operations vlandev_fops = { + .owner = THIS_MODULE, .read = vlan_proc_read, .ioctl =NULL, /* vlan_proc_ioctl */ }; diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index 2e667f43f0e5..a21585280eba 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c @@ -241,6 +241,7 @@ static int atalk_seq_socket_open(struct inode *inode, struct file *file) } static struct file_operations atalk_seq_interface_fops = { + .owner = THIS_MODULE, .open = atalk_seq_interface_open, .read = seq_read, .llseek = seq_lseek, @@ -248,6 +249,7 @@ static struct file_operations atalk_seq_interface_fops = { }; static struct file_operations atalk_seq_route_fops = { + .owner = THIS_MODULE, .open = atalk_seq_route_open, .read = seq_read, .llseek = seq_lseek, @@ -255,6 +257,7 @@ static struct file_operations atalk_seq_route_fops = { }; static struct file_operations atalk_seq_socket_fops = { + .owner = THIS_MODULE, .open = atalk_seq_socket_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 5483b125ba13..40600fc86a7c 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -42,6 +42,7 @@ static int parse_qos(const char *buff, int len); * Define allowed FILE OPERATIONS */ static struct file_operations mpc_file_operations = { + .owner = THIS_MODULE, .read = proc_mpc_read, .write = proc_mpc_write, }; diff --git a/net/atm/proc.c b/net/atm/proc.c index f2d1b18d52f9..8aec2ef13809 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -57,10 +57,12 @@ static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count, loff_t *pos); static struct file_operations proc_dev_atm_operations = { + .owner = THIS_MODULE, .read = proc_dev_atm_read, }; static struct file_operations proc_spec_atm_operations = { + .owner = THIS_MODULE, .read = proc_spec_atm_read, }; diff --git a/net/bluetooth/hci_proc.c b/net/bluetooth/hci_proc.c index 132e44ec6245..494436344b1c 100644 --- a/net/bluetooth/hci_proc.c +++ b/net/bluetooth/hci_proc.c @@ -115,6 +115,7 @@ static int inq_seq_open(struct inode *inode, struct file *file) } static struct file_operations inq_seq_fops = { + .owner = THIS_MODULE, .open = inq_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index fe811355a735..e9c1cee3ae56 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -2048,6 +2048,7 @@ static int l2cap_seq_open(struct inode *inode, struct file *file) } static struct file_operations l2cap_seq_fops = { + .owner = THIS_MODULE, .open = l2cap_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c193d77b6e57..68a447eced0d 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1824,6 +1824,7 @@ static int rfcomm_seq_open(struct inode *inode, struct file *file) } static struct file_operations rfcomm_seq_fops = { + .owner = THIS_MODULE, .open = rfcomm_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 81bdda3ce9bd..5a8c62dd5377 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -821,6 +821,7 @@ static int rfcomm_seq_open(struct inode *inode, struct file *file) } static struct file_operations rfcomm_seq_fops = { + .owner = THIS_MODULE, .open = rfcomm_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 02ac269362f1..ee8a4383211e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -933,6 +933,7 @@ static int sco_seq_open(struct inode *inode, struct file *file) } static struct file_operations sco_seq_fops = { + .owner = THIS_MODULE, .open = sco_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/core/dev.c b/net/core/dev.c index 31d1f97c5cd4..6f9ce1949224 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1912,6 +1912,7 @@ static int dev_seq_open(struct inode *inode, struct file *file) } static struct file_operations dev_seq_fops = { + .owner = THIS_MODULE, .open = dev_seq_open, .read = seq_read, .llseek = seq_lseek, @@ -1931,6 +1932,7 @@ static int softnet_seq_open(struct inode *inode, struct file *file) } static struct file_operations softnet_seq_fops = { + .owner = THIS_MODULE, .open = softnet_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/core/wireless.c b/net/core/wireless.c index 806708eebd34..46753d6658c4 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -465,6 +465,7 @@ static int wireless_seq_open(struct inode *inode, struct file *file) } static struct file_operations wireless_seq_fops = { + .owner = THIS_MODULE, .open = wireless_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 7bac06e55316..b54763934640 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -693,6 +693,7 @@ out_kfree: } static struct file_operations dn_neigh_seq_fops = { + .owner = THIS_MODULE, .open = dn_neigh_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 69cfc1691f4a..2ccf51403636 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -94,7 +94,6 @@ #include <linux/inet.h> #include <linux/igmp.h> #include <linux/netdevice.h> -#include <linux/brlock.h> #include <net/ip.h> #include <net/protocol.h> #include <net/arp.h> @@ -129,7 +128,8 @@ static kmem_cache_t *raw4_sk_cachep; /* The inetsw table contains everything that inet_create needs to * build a new socket. */ -struct list_head inetsw[SOCK_MAX]; +static struct list_head inetsw[SOCK_MAX]; +static spinlock_t inetsw_lock = SPIN_LOCK_UNLOCKED; /* New destruction routine */ @@ -337,8 +337,8 @@ static int inet_create(struct socket *sock, int protocol) /* Look for the requested type/protocol pair. */ answer = NULL; - br_read_lock_bh(BR_NETPROTO_LOCK); - list_for_each(p, &inetsw[sock->type]) { + rcu_read_lock(); + list_for_each_rcu(p, &inetsw[sock->type]) { answer = list_entry(p, struct inet_protosw, list); /* Check the non-wild match. */ @@ -356,7 +356,6 @@ static int inet_create(struct socket *sock, int protocol) } answer = NULL; } - br_read_unlock_bh(BR_NETPROTO_LOCK); err = -ESOCKTNOSUPPORT; if (!answer) @@ -373,6 +372,7 @@ static int inet_create(struct socket *sock, int protocol) sk->no_check = answer->no_check; if (INET_PROTOSW_REUSE & answer->flags) sk->reuse = 1; + rcu_read_unlock(); inet = inet_sk(sk); @@ -427,6 +427,7 @@ static int inet_create(struct socket *sock, int protocol) out: return err; out_sk_free: + rcu_read_unlock(); sk_free(sk); goto out; } @@ -979,7 +980,7 @@ void inet_register_protosw(struct inet_protosw *p) int protocol = p->protocol; struct list_head *last_perm; - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inetsw_lock); if (p->type > SOCK_MAX) goto out_illegal; @@ -1008,9 +1009,12 @@ void inet_register_protosw(struct inet_protosw *p) * non-permanent entry. This means that when we remove this entry, the * system automatically returns to the old behavior. */ - list_add(&p->list, last_perm); + list_add_rcu(&p->list, last_perm); out: - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inetsw_lock); + + synchronize_kernel(); + return; out_permanent: @@ -1032,9 +1036,11 @@ void inet_unregister_protosw(struct inet_protosw *p) "Attempt to unregister permanent protocol %d.\n", p->protocol); } else { - br_write_lock_bh(BR_NETPROTO_LOCK); - list_del(&p->list); - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inetsw_lock); + list_del_rcu(&p->list); + spin_unlock_bh(&inetsw_lock); + + synchronize_kernel(); } } diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index f4d4a3d88306..feda223a2d88 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1384,6 +1384,7 @@ out_kfree: } static struct file_operations arp_seq_fops = { + .owner = THIS_MODULE, .open = arp_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index 257b6adc18b8..5002cd1fb9da 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -1065,6 +1065,7 @@ out_kfree: } static struct file_operations fib_seq_fops = { + .owner = THIS_MODULE, .open = fib_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 04e3361034d4..4589ca2d16b0 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -695,15 +695,12 @@ static void icmp_unreach(struct sk_buff *skb) } read_unlock(&raw_v4_lock); - /* - * This can't change while we are doing it. - * Callers have obtained BR_NETPROTO_LOCK so - * we are OK. - */ - + rcu_read_lock(); ipprot = inet_protos[hash]; + smp_read_barrier_depends(); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, info); + rcu_read_unlock(); out: return; diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 6131e3babfca..fe561aa4a767 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -215,6 +215,7 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) /* Point into the IP datagram, just past the header. */ skb->h.raw = skb->data; + rcu_read_lock(); { /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */ int protocol = skb->nh.iph->protocol; @@ -235,10 +236,11 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) if ((ipprot = inet_protos[hash]) != NULL) { int ret; + smp_read_barrier_depends(); if (!ipprot->no_policy && !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { kfree_skb(skb); - return 0; + goto out; } ret = ipprot->handler(skb); if (ret < 0) { @@ -258,6 +260,8 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) kfree_skb(skb); } } + out: + rcu_read_unlock(); return 0; } diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index d07556385a0b..b4ea53493320 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -80,6 +80,7 @@ static int sockstat_seq_open(struct inode *inode, struct file *file) } static struct file_operations sockstat_seq_fops = { + .owner = THIS_MODULE, .open = sockstat_seq_open, .read = seq_read, .llseek = seq_lseek, @@ -171,6 +172,7 @@ static int snmp_seq_open(struct inode *inode, struct file *file) } static struct file_operations snmp_seq_fops = { + .owner = THIS_MODULE, .open = snmp_seq_open, .read = seq_read, .llseek = seq_lseek, @@ -227,6 +229,7 @@ static int netstat_seq_open(struct inode *inode, struct file *file) } static struct file_operations netstat_seq_fops = { + .owner = THIS_MODULE, .open = netstat_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c index 302e10a3ccfb..9735e45d5b86 100644 --- a/net/ipv4/protocol.c +++ b/net/ipv4/protocol.c @@ -37,7 +37,6 @@ #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/timer.h> -#include <linux/brlock.h> #include <net/ip.h> #include <net/protocol.h> #include <net/tcp.h> @@ -49,6 +48,7 @@ #include <linux/igmp.h> struct inet_protocol *inet_protos[MAX_INET_PROTOS]; +static spinlock_t inet_proto_lock = SPIN_LOCK_UNLOCKED; /* * Add a protocol handler to the hash tables @@ -60,16 +60,14 @@ int inet_add_protocol(struct inet_protocol *prot, unsigned char protocol) hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); - + spin_lock_bh(&inet_proto_lock); if (inet_protos[hash]) { ret = -1; } else { inet_protos[hash] = prot; ret = 0; } - - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet_proto_lock); return ret; } @@ -84,16 +82,15 @@ int inet_del_protocol(struct inet_protocol *prot, unsigned char protocol) hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); - + spin_lock_bh(&inet_proto_lock); if (inet_protos[hash] == prot) { inet_protos[hash] = NULL; ret = 0; } else { ret = -1; } + spin_unlock_bh(&inet_proto_lock); - br_write_unlock_bh(BR_NETPROTO_LOCK); return ret; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 1afbef9cd6a7..6a76726b9919 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -807,6 +807,7 @@ static int raw_seq_open(struct inode *inode, struct file *file) } static struct file_operations raw_seq_fops = { + .owner = THIS_MODULE, .open = raw_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3ffb5c702905..768de343822b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -382,6 +382,7 @@ out_kfree: } static struct file_operations rt_cache_seq_fops = { + .owner = THIS_MODULE, .open = rt_cache_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 65b4b06b8de0..c794eb7140ef 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2569,6 +2569,7 @@ out_kfree: } static struct file_operations tcp_seq_fops = { + .owner = THIS_MODULE, .open = tcp_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 547dfa233a0f..1aca38acb984 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -760,6 +760,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, tcp_reset_keepalive_timer(newsk, keepalive_time_when(newtp)); newsk->socket = NULL; newsk->sleep = NULL; + newsk->owner = NULL; newtp->tstamp_ok = req->tstamp_ok; if((newtp->sack_ok = req->sack_ok) != 0) { diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 71f5a0df5296..6f8f76e0ddf8 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1483,6 +1483,7 @@ out_kfree: } static struct file_operations udp_seq_fops = { + .owner = THIS_MODULE, .open = udp_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 8ae2dfaba7a5..ec1a43b38b4f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -45,7 +45,6 @@ #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/icmpv6.h> -#include <linux/brlock.h> #include <linux/smp_lock.h> #include <net/ip.h> @@ -75,8 +74,10 @@ MODULE_LICENSE("GPL"); /* IPv6 procfs goodies... */ #ifdef CONFIG_PROC_FS +extern int raw6_proc_init(void); +extern int raw6_proc_exit(void); + extern int anycast6_get_info(char *, char **, off_t, int); -extern int raw6_get_info(char *, char **, off_t, int); extern int tcp6_get_info(char *, char **, off_t, int); extern int udp6_get_info(char *, char **, off_t, int); extern int afinet6_get_info(char *, char **, off_t, int); @@ -102,7 +103,8 @@ kmem_cache_t *raw6_sk_cachep; /* The inetsw table contains everything that inet_create needs to * build a new socket. */ -struct list_head inetsw6[SOCK_MAX]; +static struct list_head inetsw6[SOCK_MAX]; +static spinlock_t inetsw6_lock = SPIN_LOCK_UNLOCKED; static void inet6_sock_destruct(struct sock *sk) { @@ -162,8 +164,8 @@ static int inet6_create(struct socket *sock, int protocol) /* Look for the requested type/protocol pair. */ answer = NULL; - br_read_lock_bh(BR_NETPROTO_LOCK); - list_for_each(p, &inetsw6[sock->type]) { + rcu_read_lock(); + list_for_each_rcu(p, &inetsw6[sock->type]) { answer = list_entry(p, struct inet_protosw, list); /* Check the non-wild match. */ @@ -181,7 +183,6 @@ static int inet6_create(struct socket *sock, int protocol) } answer = NULL; } - br_read_unlock_bh(BR_NETPROTO_LOCK); if (!answer) goto free_and_badtype; @@ -198,6 +199,7 @@ static int inet6_create(struct socket *sock, int protocol) sk->no_check = answer->no_check; if (INET_PROTOSW_REUSE & answer->flags) sk->reuse = 1; + rcu_read_unlock(); inet = inet_sk(sk); @@ -260,12 +262,15 @@ static int inet6_create(struct socket *sock, int protocol) return 0; free_and_badtype: + rcu_read_unlock(); sk_free(sk); return -ESOCKTNOSUPPORT; free_and_badperm: + rcu_read_unlock(); sk_free(sk); return -EPERM; free_and_noproto: + rcu_read_unlock(); sk_free(sk); return -EPROTONOSUPPORT; do_oom: @@ -574,7 +579,7 @@ inet6_register_protosw(struct inet_protosw *p) int protocol = p->protocol; struct list_head *last_perm; - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inetsw6_lock); if (p->type > SOCK_MAX) goto out_illegal; @@ -603,9 +608,9 @@ inet6_register_protosw(struct inet_protosw *p) * non-permanent entry. This means that when we remove this entry, the * system automatically returns to the old behavior. */ - list_add(&p->list, last_perm); + list_add_rcu(&p->list, last_perm); out: - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inetsw6_lock); return; out_permanent: @@ -623,7 +628,17 @@ out_illegal: void inet6_unregister_protosw(struct inet_protosw *p) { - inet_unregister_protosw(p); + if (INET_PROTOSW_PERMANENT & p->flags) { + printk(KERN_ERR + "Attempt to unregister permanent protocol %d.\n", + p->protocol); + } else { + spin_lock_bh(&inetsw6_lock); + list_del_rcu(&p->list); + spin_unlock_bh(&inetsw6_lock); + + synchronize_kernel(); + } } int @@ -773,7 +788,7 @@ static int __init inet6_init(void) /* Create /proc/foo6 entries. */ #ifdef CONFIG_PROC_FS err = -ENOMEM; - if (!proc_net_create("raw6", 0, raw6_get_info)) + if (raw6_proc_init()) goto proc_raw6_fail; if (!proc_net_create("tcp6", 0, tcp6_get_info)) goto proc_tcp6_fail; @@ -814,7 +829,7 @@ proc_misc6_fail: proc_udp6_fail: proc_net_remove("tcp6"); proc_tcp6_fail: - proc_net_remove("raw6"); + raw6_proc_exit(); proc_raw6_fail: igmp6_cleanup(); #endif @@ -839,7 +854,7 @@ static void inet6_exit(void) /* First of all disallow new sockets creation. */ sock_unregister(PF_INET6); #ifdef CONFIG_PROC_FS - proc_net_remove("raw6"); + raw6_proc_exit(); proc_net_remove("tcp6"); proc_net_remove("udp6"); proc_net_remove("sockstat6"); diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 9f420ea0f94f..8a415c312de0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -456,9 +456,12 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) hash = nexthdr & (MAX_INET_PROTOS - 1); + rcu_read_lock(); ipprot = inet6_protos[hash]; + smp_read_barrier_depends(); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, NULL, type, code, inner_offset, info); + rcu_read_unlock(); read_lock(&raw_v6_lock); if ((sk = raw_v6_htable[hash]) != NULL) { diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c737d2f3d486..16feb45246a9 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -152,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) skb->h.raw += (skb->h.raw[1]+1)<<3; } + rcu_read_lock(); resubmit: if (!pskb_pull(skb, skb->h.raw - skb->data)) goto discard; @@ -165,6 +166,7 @@ resubmit: if ((ipprot = inet6_protos[hash]) != NULL) { int ret; + smp_read_barrier_depends(); if (ipprot->flags & INET6_PROTO_FINAL) { if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) { skb->csum = csum_sub(skb->csum, @@ -173,10 +175,8 @@ resubmit: } } if (!(ipprot->flags & INET6_PROTO_NOPOLICY) && - !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { - kfree_skb(skb); - return 0; - } + !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto discard; ret = ipprot->handler(&skb, &nhoff); if (ret > 0) @@ -194,10 +194,11 @@ resubmit: kfree_skb(skb); } } - + rcu_read_unlock(); return 0; discard: + rcu_read_unlock(); kfree_skb(skb); return 0; } diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 403b6853c2e7..edcf68ed04dd 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -198,6 +198,7 @@ static int sockstat6_seq_open(struct inode *inode, struct file *file) } static struct file_operations sockstat6_seq_fops = { + .owner = THIS_MODULE, .open = sockstat6_seq_open, .read = seq_read, .llseek = seq_lseek, @@ -210,6 +211,7 @@ static int snmp6_seq_open(struct inode *inode, struct file *file) } static struct file_operations snmp6_seq_fops = { + .owner = THIS_MODULE, .open = snmp6_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index d070acfd8e1b..d1dc7ac40ae2 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -32,7 +32,6 @@ #include <linux/in6.h> #include <linux/netdevice.h> #include <linux/if_arp.h> -#include <linux/brlock.h> #include <net/sock.h> #include <net/snmp.h> @@ -41,12 +40,14 @@ #include <net/protocol.h> struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; +static spinlock_t inet6_proto_lock = SPIN_LOCK_UNLOCKED; + int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol) { int ret, hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inet6_proto_lock); if (inet6_protos[hash]) { ret = -1; @@ -55,7 +56,7 @@ int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol) ret = 0; } - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet6_proto_lock); return ret; } @@ -68,7 +69,7 @@ int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol) { int ret, hash = protocol & (MAX_INET_PROTOS - 1); - br_write_lock_bh(BR_NETPROTO_LOCK); + spin_lock_bh(&inet6_proto_lock); if (inet6_protos[hash] != prot) { ret = -1; @@ -77,7 +78,7 @@ int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol) ret = 0; } - br_write_unlock_bh(BR_NETPROTO_LOCK); + spin_unlock_bh(&inet6_proto_lock); return ret; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 70953d767456..dbec69833323 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -47,6 +47,9 @@ #include <net/rawv6.h> #include <net/xfrm.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> + struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE]; rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED; @@ -831,80 +834,6 @@ static int rawv6_init_sk(struct sock *sk) return(0); } -#define LINE_LEN 190 -#define LINE_FMT "%-190s\n" - -static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i) -{ - struct ipv6_pinfo *np = inet6_sk(sp); - struct in6_addr *dest, *src; - __u16 destp, srcp; - - dest = &np->daddr; - src = &np->rcv_saddr; - destp = 0; - srcp = inet_sk(sp)->num; - sprintf(tmpbuf, - "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p", - i, - src->s6_addr32[0], src->s6_addr32[1], - src->s6_addr32[2], src->s6_addr32[3], srcp, - dest->s6_addr32[0], dest->s6_addr32[1], - dest->s6_addr32[2], dest->s6_addr32[3], destp, - sp->state, - atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc), - 0, 0L, 0, - sock_i_uid(sp), 0, - sock_i_ino(sp), - atomic_read(&sp->refcnt), sp); -} - -int raw6_get_info(char *buffer, char **start, off_t offset, int length) -{ - int len = 0, num = 0, i; - off_t pos = 0; - off_t begin; - char tmpbuf[LINE_LEN+2]; - - if (offset < LINE_LEN+1) - len += sprintf(buffer, LINE_FMT, - " sl " /* 6 */ - "local_address " /* 38 */ - "remote_address " /* 38 */ - "st tx_queue rx_queue tr tm->when retrnsmt" /* 41 */ - " uid timeout inode"); /* 21 */ - /*----*/ - /*144 */ - pos = LINE_LEN+1; - read_lock(&raw_v6_lock); - for (i = 0; i < RAWV6_HTABLE_SIZE; i++) { - struct sock *sk; - - for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) { - if (sk->family != PF_INET6) - continue; - pos += LINE_LEN+1; - if (pos <= offset) - continue; - get_raw6_sock(sk, tmpbuf, i); - len += sprintf(buffer+len, LINE_FMT, tmpbuf); - if(len >= length) - goto out; - } - } -out: - read_unlock(&raw_v6_lock); - begin = len - (pos - offset); - *start = buffer + begin; - len -= begin; - if(len > length) - len = length; - if (len < 0) - len = 0; - return len; -} - struct proto rawv6_prot = { .name = "RAW", .close = rawv6_close, @@ -922,3 +851,151 @@ struct proto rawv6_prot = { .hash = raw_v6_hash, .unhash = raw_v6_unhash, }; + +#ifdef CONFIG_PROC_FS +struct raw6_iter_state { + int bucket; +}; + +#define raw6_seq_private(seq) ((struct raw6_iter_state *)&seq->private) + +static struct sock *raw6_get_first(struct seq_file *seq) +{ + struct sock *sk = NULL; + struct raw6_iter_state* state = raw6_seq_private(seq); + + for (state->bucket = 0; state->bucket < RAWV6_HTABLE_SIZE; ++state->bucket) { + sk = raw_v6_htable[state->bucket]; + while (sk && sk->family != PF_INET6) + sk = sk->next; + if (sk) + break; + } + return sk; +} + +static struct sock *raw6_get_next(struct seq_file *seq, struct sock *sk) +{ + struct raw6_iter_state* state = raw6_seq_private(seq); + + do { + sk = sk->next; +try_again: + ; + } while (sk && sk->family != PF_INET6); + + if (!sk && ++state->bucket < RAWV6_HTABLE_SIZE) { + sk = raw_v6_htable[state->bucket]; + goto try_again; + } + return sk; +} + +static struct sock *raw6_get_idx(struct seq_file *seq, loff_t pos) +{ + struct sock *sk = raw6_get_first(seq); + if (sk) + while (pos && (sk = raw6_get_next(seq, sk)) != NULL) + --pos; + return pos ? NULL : sk; +} + +static void *raw6_seq_start(struct seq_file *seq, loff_t *pos) +{ + read_lock(&raw_v6_lock); + return *pos ? raw6_get_idx(seq, *pos) : (void *)1; +} + +static void *raw6_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct sock *sk; + + if (v == (void *)1) + sk = raw6_get_first(seq); + else + sk = raw6_get_next(seq, v); + ++*pos; + return sk; +} + +static void raw6_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&raw_v6_lock); +} + +static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) +{ + struct ipv6_pinfo *np = inet6_sk(sp); + struct in6_addr *dest, *src; + __u16 destp, srcp; + + dest = &np->daddr; + src = &np->rcv_saddr; + destp = 0; + srcp = inet_sk(sp)->num; + seq_printf(seq, + "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n", + i, + src->s6_addr32[0], src->s6_addr32[1], + src->s6_addr32[2], src->s6_addr32[3], srcp, + dest->s6_addr32[0], dest->s6_addr32[1], + dest->s6_addr32[2], dest->s6_addr32[3], destp, + sp->state, + atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc), + 0, 0L, 0, + sock_i_uid(sp), 0, + sock_i_ino(sp), + atomic_read(&sp->refcnt), sp); +} + +static int raw6_seq_show(struct seq_file *seq, void *v) +{ + if (v == (void *)1) + seq_printf(seq, + " sl " + "local_address " + "remote_address " + "st tx_queue rx_queue tr tm->when retrnsmt" + " uid timeout inode\n"); + else + raw6_sock_seq_show(seq, v, raw6_seq_private(seq)->bucket); + return 0; +} + +static struct seq_operations raw6_seq_ops = { + .start = raw6_seq_start, + .next = raw6_seq_next, + .stop = raw6_seq_stop, + .show = raw6_seq_show, +}; + +static int raw6_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &raw6_seq_ops); +} + +static struct file_operations raw6_seq_fops = { + .owner = THIS_MODULE, + .open = raw6_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +int __init raw6_proc_init(void) +{ + struct proc_dir_entry *p = create_proc_entry("raw6", S_IRUGO, proc_net); + + if (!p) + return -ENOMEM; + p->proc_fops = &raw6_seq_fops; + + return 0; +} + +void raw6_proc_exit(void) +{ + remove_proc_entry("raw6", proc_net); +} +#endif /* CONFIG_PROC_FS */ diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b19d726562a0..1b8d62e30dc5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1797,6 +1797,7 @@ static int rt6_stats_seq_open(struct inode *inode, struct file *file) } static struct file_operations rt6_stats_seq_fops = { + .owner = THIS_MODULE, .open = rt6_stats_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index 8b854d146701..922a83845c10 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c @@ -319,6 +319,7 @@ static int ipx_seq_socket_open(struct inode *inode, struct file *file) } static struct file_operations ipx_seq_interface_fops = { + .owner = THIS_MODULE, .open = ipx_seq_interface_open, .read = seq_read, .llseek = seq_lseek, @@ -326,6 +327,7 @@ static struct file_operations ipx_seq_interface_fops = { }; static struct file_operations ipx_seq_route_fops = { + .owner = THIS_MODULE, .open = ipx_seq_route_open, .read = seq_read, .llseek = seq_lseek, @@ -333,6 +335,7 @@ static struct file_operations ipx_seq_route_fops = { }; static struct file_operations ipx_seq_socket_fops = { + .owner = THIS_MODULE, .open = ipx_seq_socket_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 50aaf724bde9..c27759125555 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -211,6 +211,7 @@ static int llc_seq_core_open(struct inode *inode, struct file *file) } static struct file_operations llc_seq_socket_fops = { + .owner = THIS_MODULE, .open = llc_seq_socket_open, .read = seq_read, .llseek = seq_lseek, @@ -218,6 +219,7 @@ static struct file_operations llc_seq_socket_fops = { }; static struct file_operations llc_seq_core_fops = { + .owner = THIS_MODULE, .open = llc_seq_core_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/nonet.c b/net/nonet.c index ffaf8363f74f..997b0e138485 100644 --- a/net/nonet.c +++ b/net/nonet.c @@ -24,5 +24,6 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) } struct file_operations bad_sock_fops = { + .owner = THIS_MODULE, .open = sock_no_open, }; diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c index 03e5442d81cb..81ca4224c9fc 100644 --- a/net/rxrpc/proc.c +++ b/net/rxrpc/proc.c @@ -38,6 +38,7 @@ static struct seq_operations rxrpc_proc_transports_ops = { }; static struct file_operations rxrpc_proc_transports_fops = { + .owner = THIS_MODULE, .open = rxrpc_proc_transports_open, .read = seq_read, .llseek = seq_lseek, @@ -51,6 +52,7 @@ static void rxrpc_proc_peers_stop(struct seq_file *p, void *v); static int rxrpc_proc_peers_show(struct seq_file *m, void *v); static struct seq_operations rxrpc_proc_peers_ops = { + .owner = THIS_MODULE, .start = rxrpc_proc_peers_start, .next = rxrpc_proc_peers_next, .stop = rxrpc_proc_peers_stop, @@ -58,6 +60,7 @@ static struct seq_operations rxrpc_proc_peers_ops = { }; static struct file_operations rxrpc_proc_peers_fops = { + .owner = THIS_MODULE, .open = rxrpc_proc_peers_open, .read = seq_read, .llseek = seq_lseek, @@ -78,6 +81,7 @@ static struct seq_operations rxrpc_proc_conns_ops = { }; static struct file_operations rxrpc_proc_conns_fops = { + .owner = THIS_MODULE, .open = rxrpc_proc_conns_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 4df681dde7e5..bce6f15fb892 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -75,6 +75,7 @@ config SCTP_DBG_OBJCNT choice prompt "SCTP: Cookie HMAC Algorithm" + depends on IP_SCTP help HMAC algorithm to be used during association initialization. It is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 7c34f8303b48..fef9b27a98a5 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -102,6 +102,7 @@ static int sctp_snmp_seq_open(struct inode *inode, struct file *file) } static struct file_operations sctp_snmp_seq_fops = { + .owner = THIS_MODULE, .open = sctp_snmp_seq_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/socket.c b/net/socket.c index 3f07e4a507c0..3fa4dc24576f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -121,6 +121,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page, */ static struct file_operations socket_file_ops = { + .owner = THIS_MODULE, .llseek = no_llseek, .aio_read = sock_aio_read, .aio_write = sock_aio_write, @@ -490,6 +491,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) } struct file_operations bad_sock_fops = { + .owner = THIS_MODULE, .open = sock_no_open, }; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index d8f6e0a7f2cc..9a8c6b39f18c 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -733,6 +733,7 @@ cache_release(struct inode *inode, struct file *filp) static struct file_operations cache_file_operations = { + .owner = THIS_MODULE, .llseek = no_llseek, .read = cache_read, .write = cache_write, diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 879fbc8cdf73..281a336f3224 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -310,6 +310,7 @@ rpc_info_release(struct inode *inode, struct file *file) } static struct file_operations rpc_info_operations = { + .owner = THIS_MODULE, .open = rpc_info_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index aae0e01ad266..1500be8de8e1 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -202,6 +202,7 @@ static int status_open(struct inode *inode, struct file *file) static struct file_operations config_fops = { + .owner = THIS_MODULE, .open = config_open, .read = seq_read, .llseek = seq_lseek, @@ -210,6 +211,7 @@ static struct file_operations config_fops = static struct file_operations status_fops = { + .owner = THIS_MODULE, .open = status_open, .read = seq_read, .llseek = seq_lseek, @@ -285,6 +287,7 @@ static int wandev_open(struct inode *inode, struct file *file) static struct file_operations wandev_fops = { + .owner = THIS_MODULE, .open = wandev_open, .read = seq_read, .llseek = seq_lseek, diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index a8961fa0a341..686506f39e7f 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c @@ -189,6 +189,7 @@ static int x25_seq_route_open(struct inode *inode, struct file *file) } static struct file_operations x25_seq_socket_fops = { + .owner = THIS_MODULE, .open = x25_seq_socket_open, .read = seq_read, .llseek = seq_lseek, @@ -196,6 +197,7 @@ static struct file_operations x25_seq_socket_fops = { }; static struct file_operations x25_seq_route_fops = { + .owner = THIS_MODULE, .open = x25_seq_route_open, .read = seq_read, .llseek = seq_lseek, |
