aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/Makefile5
-rw-r--r--drivers/acpi/processor_idle.c20
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c3
-rw-r--r--drivers/scsi/scsi_scan.c48
-rw-r--r--drivers/scsi/scsi_transport_fc.c59
-rw-r--r--drivers/usb/core/usb.c9
-rw-r--r--drivers/usb/storage/scsiglue.c4
-rw-r--r--fs/relayfs/relay.c8
-rw-r--r--include/linux/irq.h2
-rw-r--r--include/linux/relayfs_fs.h5
-rw-r--r--include/scsi/scsi_transport_fc.h11
-rw-r--r--init/Kconfig1
-rw-r--r--net/8021q/vlan.c6
-rw-r--r--net/dccp/ipv4.c2
-rw-r--r--net/ipv6/addrconf.c5
-rw-r--r--net/netrom/nr_in.c6
-rw-r--r--net/xfrm/xfrm_policy.c30
18 files changed, 182 insertions, 45 deletions
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index 43fe382da07..cad10c5b83d 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -17,7 +17,6 @@ CC := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then
NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow)
NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
-INLINE_LIMIT := $(call cc-option-yn, -m64 -finline-limit=100000)
export NEW_GCC
@@ -49,10 +48,6 @@ else
AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL)
endif
-ifeq ($(INLINE_LIMIT),y)
- CFLAGS := $(CFLAGS) -finline-limit=100000
-endif
-
ifeq ($(CONFIG_MCOUNT),y)
CFLAGS := $(CFLAGS) -pg
endif
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5f51057518b..807b0df308f 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -274,8 +274,6 @@ static void acpi_processor_idle(void)
}
}
- cx->usage++;
-
#ifdef CONFIG_HOTPLUG_CPU
/*
* Check for P_LVL2_UP flag before entering C2 and above on
@@ -283,9 +281,12 @@ static void acpi_processor_idle(void)
* detection phase, to work cleanly with logical CPU hotplug.
*/
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
- !pr->flags.has_cst && acpi_fadt.plvl2_up)
- cx->type = ACPI_STATE_C1;
+ !pr->flags.has_cst && !acpi_fadt.plvl2_up)
+ cx = &pr->power.states[ACPI_STATE_C1];
#endif
+
+ cx->usage++;
+
/*
* Sleep:
* ------
@@ -386,6 +387,15 @@ static void acpi_processor_idle(void)
next_state = pr->power.state;
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Don't do promotion/demotion */
+ if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) &&
+ !pr->flags.has_cst && !acpi_fadt.plvl2_up) {
+ next_state = cx;
+ goto end;
+ }
+#endif
+
/*
* Promotion?
* ----------
@@ -557,7 +567,7 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
* Check for P_LVL2_UP flag before entering C2 and above on
* an SMP system.
*/
- if ((num_online_cpus() > 1) && acpi_fadt.plvl2_up)
+ if ((num_online_cpus() > 1) && !acpi_fadt.plvl2_up)
return_VALUE(-ENODEV);
#endif
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 953d5fec82d..6752dd1c1e8 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -1028,7 +1028,8 @@ static void saa7134_alsa_exit(void)
return;
}
-module_init(saa7134_alsa_init);
+/* We initialize this late, to make sure the sound system is up and running */
+late_initcall(saa7134_alsa_init);
module_exit(saa7134_alsa_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ricardo Cerqueira");
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 513a699a6df..c450d57b294 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1002,7 +1002,8 @@ static void saa7134_oss_exit(void)
return;
}
-module_init(saa7134_oss_init);
+/* We initialize this late, to make sure the sound system is up and running */
+late_initcall(saa7134_oss_init);
module_exit(saa7134_oss_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 94e5167f260..e36c21e06d3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -400,6 +400,35 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
return found_target;
}
+struct work_queue_wrapper {
+ struct work_struct work;
+ struct scsi_target *starget;
+};
+
+static void scsi_target_reap_work(void *data) {
+ struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data;
+ struct scsi_target *starget = wqw->starget;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+
+ kfree(wqw);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+ list_del_init(&starget->siblings);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ device_del(&starget->dev);
+ transport_unregister_device(&starget->dev);
+ put_device(&starget->dev);
+ return;
+
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ return;
+}
+
/**
* scsi_target_reap - check to see if target is in use and destroy if not
*
@@ -411,19 +440,18 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
*/
void scsi_target_reap(struct scsi_target *starget)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- unsigned long flags;
- spin_lock_irqsave(shost->host_lock, flags);
+ struct work_queue_wrapper *wqw =
+ kzalloc(sizeof(struct work_queue_wrapper), GFP_ATOMIC);
- if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
- list_del_init(&starget->siblings);
- spin_unlock_irqrestore(shost->host_lock, flags);
- device_del(&starget->dev);
- transport_unregister_device(&starget->dev);
- put_device(&starget->dev);
+ if (!wqw) {
+ starget_printk(KERN_ERR, starget,
+ "Failed to allocate memory in scsi_reap_target()\n");
return;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
+
+ INIT_WORK(&wqw->work, scsi_target_reap_work, wqw);
+ wqw->starget = starget;
+ schedule_work(&wqw->work);
}
/**
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6cd5931d9a5..2a1a99a2ef5 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -105,6 +105,7 @@ static struct {
{ FC_PORTSTATE_LINKDOWN, "Linkdown" },
{ FC_PORTSTATE_ERROR, "Error" },
{ FC_PORTSTATE_LOOPBACK, "Loopback" },
+ { FC_PORTSTATE_DELETED, "Deleted" },
};
fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
#define FC_PORTSTATE_MAX_NAMELEN 20
@@ -211,6 +212,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
#define FC_MGMTSRVR_PORTID 0x00000a
+static void fc_shost_remove_rports(void *data);
static void fc_timeout_deleted_rport(void *data);
static void fc_scsi_scan_rport(void *data);
static void fc_rport_terminate(struct fc_rport *rport);
@@ -318,6 +320,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host_next_rport_number(shost) = 0;
fc_host_next_target_id(shost) = 0;
+ fc_host_flags(shost) = 0;
+ INIT_WORK(&fc_host_rport_del_work(shost), fc_shost_remove_rports, shost);
return 0;
}
@@ -387,6 +391,7 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \
struct fc_internal *i = to_fc_internal(shost->transportt); \
if ((i->f->get_rport_##field) && \
!((rport->port_state == FC_PORTSTATE_BLOCKED) || \
+ (rport->port_state == FC_PORTSTATE_DELETED) || \
(rport->port_state == FC_PORTSTATE_NOTPRESENT))) \
i->f->get_rport_##field(rport); \
return snprintf(buf, sz, format_string, cast rport->field); \
@@ -402,6 +407,7 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
struct Scsi_Host *shost = rport_to_shost(rport); \
struct fc_internal *i = to_fc_internal(shost->transportt); \
if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
+ (rport->port_state == FC_PORTSTATE_DELETED) || \
(rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
return -EBUSY; \
val = simple_strtoul(buf, NULL, 0); \
@@ -519,6 +525,7 @@ store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
struct Scsi_Host *shost = rport_to_shost(rport);
struct fc_internal *i = to_fc_internal(shost->transportt);
if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
+ (rport->port_state == FC_PORTSTATE_DELETED) ||
(rport->port_state == FC_PORTSTATE_NOTPRESENT))
return -EBUSY;
val = simple_strtoul(buf, NULL, 0);
@@ -1769,7 +1776,7 @@ fc_timeout_deleted_rport(void *data)
rport->maxframe_size = -1;
rport->supported_classes = FC_COS_UNSPECIFIED;
rport->roles = FC_RPORT_ROLE_UNKNOWN;
- rport->port_state = FC_PORTSTATE_NOTPRESENT;
+ rport->port_state = FC_PORTSTATE_DELETED;
/* remove the identifiers that aren't used in the consisting binding */
switch (fc_host_tgtid_bind_type(shost)) {
@@ -1789,14 +1796,23 @@ fc_timeout_deleted_rport(void *data)
break;
}
- spin_unlock_irqrestore(shost->host_lock, flags);
-
/*
* As this only occurs if the remote port (scsi target)
* went away and didn't come back - we'll remove
* all attached scsi devices.
+ *
+ * We'll schedule the shost work item to perform the actual removal
+ * to avoid recursion in the different flush calls if we perform
+ * the removal in each target - and there are lots of targets
+ * whose timeouts fire at the same time.
*/
- fc_rport_tgt_remove(rport);
+
+ if ( !(fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED)) {
+ fc_host_flags(shost) |= FC_SHOST_RPORT_DEL_SCHEDULED;
+ scsi_queue_work(shost, &fc_host_rport_del_work(shost));
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
/**
@@ -1818,6 +1834,41 @@ fc_scsi_scan_rport(void *data)
}
+/**
+ * fc_shost_remove_rports - called to remove all rports that are marked
+ * as in a deleted (not connected) state.
+ *
+ * @data: shost whose rports are to be looked at
+ **/
+static void
+fc_shost_remove_rports(void *data)
+{
+ struct Scsi_Host *shost = (struct Scsi_Host *)data;
+ struct fc_rport *rport, *next_rport;
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ while (fc_host_flags(shost) & FC_SHOST_RPORT_DEL_SCHEDULED) {
+
+ fc_host_flags(shost) &= ~FC_SHOST_RPORT_DEL_SCHEDULED;
+
+restart_search:
+ list_for_each_entry_safe(rport, next_rport,
+ &fc_host_rport_bindings(shost), peers) {
+ if (rport->port_state == FC_PORTSTATE_DELETED) {
+ rport->port_state = FC_PORTSTATE_NOTPRESENT;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ fc_rport_tgt_remove(rport);
+ spin_lock_irqsave(shost->host_lock, flags);
+ goto restart_search;
+ }
+ }
+
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+
MODULE_AUTHOR("Martin Hicks");
MODULE_DESCRIPTION("FC Transport Attributes");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e197ce9353d..e80ef946782 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1432,7 +1432,8 @@ static int usb_generic_suspend(struct device *dev, pm_message_t message)
mark_quiesced(intf);
} else {
// FIXME else if there's no suspend method, disconnect...
- dev_warn(dev, "no %s?\n", "suspend");
+ dev_warn(dev, "no suspend for driver %s?\n", driver->name);
+ mark_quiesced(intf);
status = 0;
}
return status;
@@ -1460,8 +1461,10 @@ static int usb_generic_resume(struct device *dev)
}
if ((dev->driver == NULL) ||
- (dev->driver_data == &usb_generic_driver_data))
+ (dev->driver_data == &usb_generic_driver_data)) {
+ dev->power.power_state.event = PM_EVENT_FREEZE;
return 0;
+ }
intf = to_usb_interface(dev);
driver = to_usb_driver(dev->driver);
@@ -1481,7 +1484,7 @@ static int usb_generic_resume(struct device *dev)
mark_quiesced(intf);
}
} else
- dev_warn(dev, "no %s?\n", "resume");
+ dev_warn(dev, "no resume for driver %s?\n", driver->name);
return 0;
}
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 4837524eada..4ef5527028c 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -109,7 +109,7 @@ static int slave_configure(struct scsi_device *sdev)
* data comes from.
*/
if (sdev->scsi_level < SCSI_2)
- sdev->scsi_level = SCSI_2;
+ sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
/* According to the technical support people at Genesys Logic,
* devices using their chips have problems transferring more than
@@ -162,7 +162,7 @@ static int slave_configure(struct scsi_device *sdev)
* a Get-Max-LUN request, we won't lose much by setting the
* revision level down to 2. The only devices that would be
* affected are those with sparse LUNs. */
- sdev->scsi_level = SCSI_2;
+ sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
* Hardware Error) when any low-level error occurs,
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index 16446a15c96..2a6f7f12b7f 100644
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -333,8 +333,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
return length;
toobig:
- printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length);
- WARN_ON(1);
+ buf->chan->last_toobig = length;
return 0;
}
@@ -399,6 +398,11 @@ void relay_close(struct rchan *chan)
relay_close_buf(chan->buf[i]);
}
+ if (chan->last_toobig)
+ printk(KERN_WARNING "relayfs: one or more items not logged "
+ "[item size (%Zd) > sub-buffer size (%Zd)]\n",
+ chan->last_toobig, chan->subbuf_size);
+
kref_put(&chan->kref, relay_destroy_channel);
}
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c516382fbec..f04ba20712a 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -10,7 +10,7 @@
*/
#include <linux/config.h>
-#include <asm/smp.h> /* cpu_online_map */
+#include <linux/smp.h>
#if !defined(CONFIG_ARCH_S390)
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
index cfafc3e76bc..fb7e8073732 100644
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -20,9 +20,9 @@
#include <linux/kref.h>
/*
- * Tracks changes to rchan_buf struct
+ * Tracks changes to rchan/rchan_buf structs
*/
-#define RELAYFS_CHANNEL_VERSION 5
+#define RELAYFS_CHANNEL_VERSION 6
/*
* Per-cpu relay channel buffer
@@ -60,6 +60,7 @@ struct rchan
struct rchan_callbacks *cb; /* client callbacks */
struct kref kref; /* channel refcount */
void *private_data; /* for user-defined data */
+ size_t last_toobig; /* tried to log event > subbuf size */
struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
};
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index fac547d32a9..394f14a5b7c 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -79,6 +79,7 @@ enum fc_port_state {
FC_PORTSTATE_LINKDOWN,
FC_PORTSTATE_ERROR,
FC_PORTSTATE_LOOPBACK,
+ FC_PORTSTATE_DELETED,
};
@@ -325,8 +326,14 @@ struct fc_host_attrs {
struct list_head rport_bindings;
u32 next_rport_number;
u32 next_target_id;
+ u8 flags;
+ struct work_struct rport_del_work;
};
+/* values for struct fc_host_attrs "flags" field: */
+#define FC_SHOST_RPORT_DEL_SCHEDULED 0x01
+
+
#define fc_host_node_name(x) \
(((struct fc_host_attrs *)(x)->shost_data)->node_name)
#define fc_host_port_name(x) \
@@ -365,6 +372,10 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
#define fc_host_next_target_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
+#define fc_host_flags(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->flags)
+#define fc_host_rport_del_work(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->rport_del_work)
/* The functions by which the transport class and the driver communicate */
diff --git a/init/Kconfig b/init/Kconfig
index 6c5dbedc6e9..9fc0759fa94 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -260,7 +260,6 @@ config CC_OPTIMIZE_FOR_SIZE
bool "Optimize for size (Look out for broken compilers!)"
default y
depends on ARM || H8300 || EXPERIMENTAL
- depends on !SPARC64
help
Enabling this option will pass "-Os" instead of "-O2" to gcc
resulting in a smaller kernel.
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 91e412b0ab0..67465b65abe 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -753,6 +753,8 @@ static int vlan_ioctl_handler(void __user *arg)
break;
case GET_VLAN_REALDEV_NAME_CMD:
err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
+ if (err)
+ goto out;
if (copy_to_user(arg, &args,
sizeof(struct vlan_ioctl_args))) {
err = -EFAULT;
@@ -761,6 +763,8 @@ static int vlan_ioctl_handler(void __user *arg)
case GET_VLAN_VID_CMD:
err = vlan_dev_get_vid(args.device1, &vid);
+ if (err)
+ goto out;
args.u.VID = vid;
if (copy_to_user(arg, &args,
sizeof(struct vlan_ioctl_args))) {
@@ -774,7 +778,7 @@ static int vlan_ioctl_handler(void __user *arg)
__FUNCTION__, args.cmd);
return -EINVAL;
};
-
+out:
return err;
}
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index ca03521112c..656e13e38cf 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -1251,7 +1251,7 @@ static int dccp_v4_destroy_sock(struct sock *sk)
struct dccp_sock *dp = dccp_sk(sk);
/*
- * DCCP doesn't use sk_qrite_queue, just sk_send_head
+ * DCCP doesn't use sk_write_queue, just sk_send_head
* for retransmissions
*/
if (sk->sk_send_head != NULL) {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index fd03c394436..510220f2ae8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -639,8 +639,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
}
#endif
- for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;
- ifap = &ifa->if_next) {
+ for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) {
if (ifa == ifp) {
*ifap = ifa->if_next;
__in6_ifa_put(ifp);
@@ -648,6 +647,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
break;
deleted = 1;
+ continue;
} else if (ifp->flags & IFA_F_PERMANENT) {
if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
ifp->prefix_len)) {
@@ -671,6 +671,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
}
}
}
+ ifap = &ifa->if_next;
}
write_unlock_bh(&idev->lock);
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index 004e8599b8f..a7d88b5ad75 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -99,7 +99,7 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
break;
case NR_RESET:
- if (sysctl_netrom_reset_circuit);
+ if (sysctl_netrom_reset_circuit)
nr_disconnect(sk, ECONNRESET);
break;
@@ -130,7 +130,7 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
break;
case NR_RESET:
- if (sysctl_netrom_reset_circuit);
+ if (sysctl_netrom_reset_circuit)
nr_disconnect(sk, ECONNRESET);
break;
@@ -265,7 +265,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
break;
case NR_RESET:
- if (sysctl_netrom_reset_circuit);
+ if (sysctl_netrom_reset_circuit)
nr_disconnect(sk, ECONNRESET);
break;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 54a4be6a7d2..d19e274b9c4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -346,6 +346,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
struct xfrm_policy *pol, **p;
struct xfrm_policy *delpol = NULL;
struct xfrm_policy **newpos = NULL;
+ struct dst_entry *gc_list;
write_lock_bh(&xfrm_policy_lock);
for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
@@ -381,9 +382,36 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
xfrm_pol_hold(policy);
write_unlock_bh(&xfrm_policy_lock);
- if (delpol) {
+ if (delpol)
xfrm_policy_kill(delpol);
+
+ read_lock_bh(&xfrm_policy_lock);
+ gc_list = NULL;
+ for (policy = policy->next; policy; policy = policy->next) {
+ struct dst_entry *dst;
+
+ write_lock(&policy->lock);
+ dst = policy->bundles;
+ if (dst) {
+ struct dst_entry *tail = dst;
+ while (tail->next)
+ tail = tail->next;
+ tail->next = gc_list;
+ gc_list = dst;
+
+ policy->bundles = NULL;
+ }
+ write_unlock(&policy->lock);
}
+ read_unlock_bh(&xfrm_policy_lock);
+
+ while (gc_list) {
+ struct dst_entry *dst = gc_list;
+
+ gc_list = dst->next;
+ dst_free(dst);
+ }
+
return 0;
}
EXPORT_SYMBOL(xfrm_policy_insert);