# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet v2.6.0-test10 -> 1.1489 # drivers/scsi/libata-core.c 1.6 -> 1.7 # drivers/scsi/scsi_error.c 1.65 -> 1.66 # include/linux/libata.h 1.3 -> 1.4 # include/scsi/scsi_device.h 1.10 -> 1.11 # kernel/fork.c 1.145 -> 1.146 # drivers/scsi/scsi_sysfs.c 1.36 -> 1.38 # drivers/scsi/libata.h 1.2 -> 1.3 # net/econet/af_econet.c 1.27 -> 1.28 # drivers/scsi/scsi_lib.c 1.114 -> 1.115 # drivers/scsi/scsi.c 1.130 -> 1.131 # fs/jfs/jfs_logmgr.c 1.50 -> 1.51 # drivers/scsi/sata_svw.c 1.2 -> 1.4 # drivers/net/pppoe.c 1.35 -> 1.36 # drivers/scsi/scsi_priv.h 1.28 -> 1.29 # drivers/scsi/sata_promise.c 1.12 -> 1.13 # include/net/sock.h 1.46 -> 1.47 # drivers/scsi/scsi_scan.c 1.112 -> 1.114 # net/ipv6/mcast.c 1.46 -> 1.47 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/11/23 torvalds@home.osdl.org 1.1481.2.2 # Linux 2.6.0-test10 # -------------------------------------------- # 03/11/23 dlstevens@us.ibm.com 1.1481.2.3 # [IPV6]: Multicast output bypasses netfilter hooks, fix. # # Noted by Harald Welte (laforge@netfilter.org) # -------------------------------------------- # 03/11/24 jgarzik@redhat.com 1.1481.1.3 # Merge redhat.com:/spare/repo/linux-2.5 # into redhat.com:/spare/repo/libata-2.5 # -------------------------------------------- # 03/11/24 jejb@raven.il.steeleye.com 1.1484 # Fix locking problems in scsi_report_bus_reset() causing aic7xxx to hang # # All the users of this function in the SCSI tree call it with the host # lock held. With the new list traversal code, it was trying to take # the lock again to traverse the list. # # Fix it to use the unlocked version of list traversal and modify the # header comments to make it clear that the lock is expected to be held # on calling it. # -------------------------------------------- # 03/11/24 benh@kernel.crashing.org 1.1481.1.4 # [libata] Fix flush of Device Control register to device # # Also add some ServerWorks-specific tweaks. # -------------------------------------------- # 03/11/24 jgarzik@redhat.com 1.1481.1.5 # [libata] bump versions for core and serverworks driver # -------------------------------------------- # 03/11/24 torvalds@home.osdl.org 1.1485 # Merge bk://linux-scsi.bkbits.net/scsi-bugfixes-2.6 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/11/24 davem@nuts.ninka.net 1.1481.2.4 # [NET]: In sock_queue_rcv_skb(), do not deref skb->len after it is queued to the socket. # # In implementations that use no socket locking, such as RAW sockets, # once we queue the SKB to the socket another cpu can remove the SKB # from the socket queue and free up the SKB making the skb->len access # touch freed memory. # # Based upon a report from Burton Windle, kernel bugzilla #937 # -------------------------------------------- # 03/11/24 davem@nuts.ninka.net 1.1481.2.5 # [PPPOE]: Do not leak SKB if sock_queue_rcv_skb() fails. # -------------------------------------------- # 03/11/24 davem@nuts.ninka.net 1.1481.2.6 # [ECONET]: Do not leak SKBs if ec_queue_packet() fails. # # Also, make sure NET_RX_DROP is returned if we did not accept the # packet. # -------------------------------------------- # 03/11/24 torvalds@home.osdl.org 1.1486 # Merge master.kernel.org:/home/davem/BK/net-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/11/25 torvalds@home.osdl.org 1.1487 # Fix error return on concurrent fork() with threaded exit() # -------------------------------------------- # 03/11/25 shaggy@austin.ibm.com 1.1488 # [PATCH] JFS: Avoid segfault when dirty inodes are written on readonly mount # # This fixes an oops that can occur if JFS is used as the root filesystem. # # Writes to a device node may cause a ->write_inode to be called during a # read-only mount. JFS needs to check for NULL log in jfs_flush_journal. # -------------------------------------------- # 03/11/25 torvalds@home.osdl.org 1.1489 # Merge bk://gkernel.bkbits.net/libata-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Tue Nov 25 19:25:22 2003 +++ b/drivers/net/pppoe.c Tue Nov 25 19:25:22 2003 @@ -352,7 +352,8 @@ if (!__pppoe_xmit( relay_po->sk, skb)) goto abort_put; } else { - sock_queue_rcv_skb(sk, skb); + if (sock_queue_rcv_skb(sk, skb)) + goto abort_kfree; } return NET_RX_SUCCESS; diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c --- a/drivers/scsi/libata-core.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/libata-core.c Tue Nov 25 19:25:22 2003 @@ -133,7 +133,11 @@ struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - outb(tf->ctl, ioaddr->ctl_addr); + if (tf->ctl != ap->last_ctl) { + outb(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { outb(tf->hob_feature, ioaddr->error_addr); @@ -187,7 +191,11 @@ struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - writeb(tf->ctl, ap->ioaddr.ctl_addr); + if (tf->ctl != ap->last_ctl) { + writeb(tf->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { writeb(tf->hob_feature, (void *) ioaddr->error_addr); @@ -1281,9 +1289,9 @@ /* software reset. causes dev0 to be selected */ if (ap->flags & ATA_FLAG_MMIO) { writeb(ap->ctl, ioaddr->ctl_addr); - udelay(10); /* FIXME: flush */ + udelay(20); /* FIXME: flush */ writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr); - udelay(10); /* FIXME: flush */ + udelay(20); /* FIXME: flush */ writeb(ap->ctl, ioaddr->ctl_addr); } else { outb(ap->ctl, ioaddr->ctl_addr); @@ -2755,6 +2763,7 @@ ap->cbl = ATA_CBL_NONE; ap->device[0].flags = ATA_DFLAG_MASTER; ap->active_tag = ATA_TAG_POISON; + ap->last_ctl = 0xFF; /* ata_engine init */ ap->eng.flags = 0; diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h --- a/drivers/scsi/libata.h Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/libata.h Tue Nov 25 19:25:22 2003 @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "0.80" /* must be exactly four chars */ +#define DRV_VERSION "0.81" /* must be exactly four chars */ struct ata_scsi_args { struct ata_port *ap; diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c --- a/drivers/scsi/sata_promise.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/sata_promise.c Tue Nov 25 19:25:22 2003 @@ -213,6 +213,8 @@ board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c --- a/drivers/scsi/sata_svw.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/sata_svw.c Tue Nov 25 19:25:22 2003 @@ -44,7 +44,7 @@ #endif /* CONFIG_ALL_PPC */ #define DRV_NAME "ata_k2" -#define DRV_VERSION "1.02" +#define DRV_VERSION "1.03" static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) @@ -69,8 +69,11 @@ struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - writeb(tf->ctl, ioaddr->ctl_addr); - + if (tf->ctl != ap->last_ctl) { + writeb(tf->ctl, ioaddr->ctl_addr); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr); writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr); @@ -311,13 +314,24 @@ rc = -ENODEV; goto err_out_unmap; } + + /* Clear a magic bit in SCR1 according to Darwin, those help + * some funky seagate drives (though so far, those were already + * set by the firmware on the machines I had access to + */ + writel(readl(mmio_base + 0x80) & ~0x00040000, mmio_base + 0x80); + + /* Clear SATA error & interrupts we don't use */ + writel(0xffffffff, mmio_base + 0x44); + writel(0x0, mmio_base + 0x88); + probe_ent->sht = &k2_sata_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | + ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; probe_ent->port_ops = &k2_sata_ops; - probe_ent->n_ports = 2; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = SA_SHIRQ; + probe_ent->n_ports = 2; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; probe_ent->mmio_base = mmio_base; /* diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi.c Tue Nov 25 19:25:22 2003 @@ -367,6 +367,16 @@ unsigned long timeout; int rtn = 0; + /* check if the device is still usable */ + if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { + /* in SDEV_DEL we error all commands. DID_NO_CONNECT + * returns an immediate error upwards, and signals + * that the device is no longer present */ + cmd->result = DID_NO_CONNECT << 16; + scsi_done(cmd); + /* return 0 (because the command has been processed) */ + goto out; + } /* Assign a unique nonzero serial_number. */ /* XXX(hch): this is racy */ if (++serial_number == 0) @@ -893,7 +903,7 @@ */ int scsi_device_get(struct scsi_device *sdev) { - if (test_bit(SDEV_DEL, &sdev->sdev_state)) + if (sdev->sdev_state == SDEV_DEL) return -ENXIO; if (!get_device(&sdev->sdev_gendev)) return -ENXIO; @@ -1015,7 +1025,7 @@ struct list_head *lh, *lh_sf; unsigned long flags; - set_bit(SDEV_CANCEL, &sdev->sdev_state); + sdev->sdev_state = SDEV_CANCEL; spin_lock_irqsave(&sdev->list_lock, flags); list_for_each_entry(scmd, &sdev->cmd_list, list) { diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi_error.c Tue Nov 25 19:25:22 2003 @@ -911,7 +911,9 @@ if (rtn == SUCCESS) { scsi_sleep(BUS_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); } return rtn; @@ -940,7 +942,9 @@ if (rtn == SUCCESS) { scsi_sleep(HOST_RESET_SETTLE_TIME); + spin_lock_irqsave(scmd->device->host->host_lock, flags); scsi_report_bus_reset(scmd->device->host, scmd->device->channel); + spin_unlock_irqrestore(scmd->device->host->host_lock, flags); } return rtn; @@ -1608,7 +1612,7 @@ * * Returns: Nothing * - * Lock status: No locks are assumed held. + * Lock status: Host lock must be held. * * Notes: This only needs to be called if the reset is one which * originates from an unknown location. Resets originated @@ -1622,7 +1626,7 @@ { struct scsi_device *sdev; - shost_for_each_device(sdev, shost) { + __shost_for_each_device(sdev, shost) { if (channel == sdev->channel) { sdev->was_reset = 1; sdev->expecting_cc_ua = 1; @@ -1642,7 +1646,7 @@ * * Returns: Nothing * - * Lock status: No locks are assumed held. + * Lock status: Host lock must be held * * Notes: This only needs to be called if the reset is one which * originates from an unknown location. Resets originated @@ -1656,7 +1660,7 @@ { struct scsi_device *sdev; - shost_for_each_device(sdev, shost) { + __shost_for_each_device(sdev, shost) { if (channel == sdev->channel && target == sdev->id) { sdev->was_reset = 1; diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi_lib.c Tue Nov 25 19:25:22 2003 @@ -923,6 +923,22 @@ { struct scsi_device *sdev = q->queuedata; struct scsi_cmnd *cmd; + int specials_only = 0; + + if(unlikely(sdev->sdev_state != SDEV_RUNNING)) { + /* OK, we're not in a running state don't prep + * user commands */ + if(sdev->sdev_state == SDEV_DEL) { + /* Device is fully deleted, no commands + * at all allowed down */ + printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n", + sdev->host->host_no, sdev->id, sdev->lun); + return BLKPREP_KILL; + } + /* OK, we only allow special commands (i.e. not + * user initiated ones */ + specials_only = 1; + } /* * Find the actual device driver associated with this command. @@ -945,6 +961,14 @@ } else cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { + + if(unlikely(specials_only)) { + printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", + sdev->host->host_no, sdev->id, sdev->lun); + return BLKPREP_KILL; + } + + /* * Just check to see if the device is online. If * it isn't, we refuse to process ordinary commands @@ -1127,6 +1151,10 @@ struct scsi_cmnd *cmd; struct request *req; + if(!get_device(&sdev->sdev_gendev)) + /* We must be tearing the block queue down already */ + return; + /* * To start with, we keep looping until the queue is empty, or until * the host is no longer able to accept any more requests. @@ -1199,7 +1227,7 @@ } } - return; + goto out; not_ready: spin_unlock_irq(shost->host_lock); @@ -1217,6 +1245,12 @@ sdev->device_busy--; if(sdev->device_busy == 0) blk_plug_device(q); + out: + /* must be careful here...if we trigger the ->remove() function + * we cannot be holding the q lock */ + spin_unlock_irq(q->queue_lock); + put_device(&sdev->sdev_gendev); + spin_lock_irq(q->queue_lock); } u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- a/drivers/scsi/scsi_priv.h Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi_priv.h Tue Nov 25 19:25:22 2003 @@ -130,7 +130,6 @@ extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, int); extern void scsi_forget_host(struct Scsi_Host *); -extern void scsi_free_sdev(struct scsi_device *); extern void scsi_rescan_device(struct device *); /* scsi_sysctl.c */ @@ -143,7 +142,8 @@ #endif /* CONFIG_SYSCTL */ /* scsi_sysfs.c */ -extern int scsi_device_register(struct scsi_device *); +extern void scsi_device_dev_release(struct device *); +extern int scsi_sysfs_add_sdev(struct scsi_device *); extern int scsi_sysfs_add_host(struct Scsi_Host *); extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi_scan.c Tue Nov 25 19:25:22 2003 @@ -205,6 +205,7 @@ sdev->lun = lun; sdev->channel = channel; sdev->online = TRUE; + sdev->sdev_state = SDEV_CREATED; INIT_LIST_HEAD(&sdev->siblings); INIT_LIST_HEAD(&sdev->same_target_siblings); INIT_LIST_HEAD(&sdev->cmd_list); @@ -236,6 +237,25 @@ goto out_free_queue; } + if (get_device(&sdev->host->shost_gendev)) { + + device_initialize(&sdev->sdev_gendev); + sdev->sdev_gendev.parent = &sdev->host->shost_gendev; + sdev->sdev_gendev.bus = &scsi_bus_type; + sdev->sdev_gendev.release = scsi_device_dev_release; + sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", + sdev->host->host_no, sdev->channel, sdev->id, + sdev->lun); + + class_device_initialize(&sdev->sdev_classdev); + sdev->sdev_classdev.dev = &sdev->sdev_gendev; + sdev->sdev_classdev.class = &sdev_class; + snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, + "%d:%d:%d:%d", sdev->host->host_no, + sdev->channel, sdev->id, sdev->lun); + } else + goto out_free_queue; + /* * If there are any same target siblings, add this to the * sibling list @@ -273,36 +293,6 @@ } /** - * scsi_free_sdev - cleanup and free a scsi_device - * @sdev: cleanup and free this scsi_device - * - * Description: - * Undo the actions in scsi_alloc_sdev, including removing @sdev from - * the list, and freeing @sdev. - **/ -void scsi_free_sdev(struct scsi_device *sdev) -{ - unsigned long flags; - - spin_lock_irqsave(sdev->host->host_lock, flags); - list_del(&sdev->siblings); - list_del(&sdev->same_target_siblings); - spin_unlock_irqrestore(sdev->host->host_lock, flags); - - if (sdev->request_queue) - scsi_free_queue(sdev->request_queue); - - spin_lock_irqsave(sdev->host->host_lock, flags); - list_del(&sdev->starved_entry); - if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0) - kfree(sdev->sdev_target); - spin_unlock_irqrestore(sdev->host->host_lock, flags); - - kfree(sdev->inquiry); - kfree(sdev); -} - -/** * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY * @sreq: used to send the INQUIRY * @inq_result: area to store the INQUIRY result @@ -642,7 +632,7 @@ * register it and tell the rest of the kernel * about it. */ - scsi_device_register(sdev); + scsi_sysfs_add_sdev(sdev); return SCSI_SCAN_LUN_PRESENT; } @@ -748,8 +738,11 @@ if (res == SCSI_SCAN_LUN_PRESENT) { if (sdevp) *sdevp = sdev; - } else - scsi_free_sdev(sdev); + } else { + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + put_device(&sdev->sdev_gendev); + } out: return res; } @@ -1301,5 +1294,8 @@ void scsi_free_host_dev(struct scsi_device *sdev) { BUG_ON(sdev->id != sdev->host->this_id); - scsi_free_sdev(sdev); + + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + put_device(&sdev->sdev_gendev); } diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Tue Nov 25 19:25:22 2003 +++ b/drivers/scsi/scsi_sysfs.c Tue Nov 25 19:25:22 2003 @@ -115,14 +115,29 @@ put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release(struct device *dev) +void scsi_device_dev_release(struct device *dev) { struct scsi_device *sdev; struct device *parent; + unsigned long flags; parent = dev->parent; sdev = to_scsi_device(dev); - scsi_free_sdev(sdev); + + spin_lock_irqsave(sdev->host->host_lock, flags); + list_del(&sdev->siblings); + list_del(&sdev->same_target_siblings); + list_del(&sdev->starved_entry); + if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0) + kfree(sdev->sdev_target); + spin_unlock_irqrestore(sdev->host->host_lock, flags); + + if (sdev->request_queue) + scsi_free_queue(sdev->request_queue); + + kfree(sdev->inquiry); + kfree(sdev); + put_device(parent); } @@ -321,29 +336,20 @@ } /** - * scsi_device_register - register a scsi device with the scsi bus - * @sdev: scsi_device to register + * scsi_sysfs_add_sdev - add scsi device to sysfs + * @sdev: scsi_device to add * * Return value: * 0 on Success / non-zero on Failure **/ -int scsi_device_register(struct scsi_device *sdev) +int scsi_sysfs_add_sdev(struct scsi_device *sdev) { - int error = 0, i; + int error = -EINVAL, i; + + if (sdev->sdev_state != SDEV_CREATED) + return error; - set_bit(SDEV_ADD, &sdev->sdev_state); - device_initialize(&sdev->sdev_gendev); - sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", - sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); - sdev->sdev_gendev.parent = &sdev->host->shost_gendev; - sdev->sdev_gendev.bus = &scsi_bus_type; - sdev->sdev_gendev.release = scsi_device_dev_release; - - class_device_initialize(&sdev->sdev_classdev); - sdev->sdev_classdev.dev = &sdev->sdev_gendev; - sdev->sdev_classdev.class = &sdev_class; - snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d", - sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); + sdev->sdev_state = SDEV_RUNNING; error = device_add(&sdev->sdev_gendev); if (error) { @@ -351,8 +357,6 @@ return error; } - get_device(sdev->sdev_gendev.parent); - error = class_device_add(&sdev->sdev_classdev); if (error) { printk(KERN_INFO "error 2\n"); @@ -384,8 +388,11 @@ return error; clean_device: + sdev->sdev_state = SDEV_CANCEL; + device_del(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev); + return error; } @@ -396,12 +403,14 @@ **/ void scsi_remove_device(struct scsi_device *sdev) { - class_device_unregister(&sdev->sdev_classdev); - set_bit(SDEV_DEL, &sdev->sdev_state); - if (sdev->host->hostt->slave_destroy) - sdev->host->hostt->slave_destroy(sdev); - device_del(&sdev->sdev_gendev); - put_device(&sdev->sdev_gendev); + if (sdev->sdev_state == SDEV_RUNNING || sdev->sdev_state == SDEV_CANCEL) { + sdev->sdev_state = SDEV_DEL; + class_device_unregister(&sdev->sdev_classdev); + device_del(&sdev->sdev_gendev); + if (sdev->host->hostt->slave_destroy) + sdev->host->hostt->slave_destroy(sdev); + put_device(&sdev->sdev_gendev); + } } int scsi_register_driver(struct device_driver *drv) diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c --- a/fs/jfs/jfs_logmgr.c Tue Nov 25 19:25:22 2003 +++ b/fs/jfs/jfs_logmgr.c Tue Nov 25 19:25:22 2003 @@ -1415,6 +1415,10 @@ int i; struct tblock *target; + /* jfs_write_inode may call us during read-only mount */ + if (!log) + return; + jfs_info("jfs_flush_journal: log:0x%p wait=%d", log, wait); LOGGC_LOCK(log); diff -Nru a/include/linux/libata.h b/include/linux/libata.h --- a/include/linux/libata.h Tue Nov 25 19:25:22 2003 +++ b/include/linux/libata.h Tue Nov 25 19:25:22 2003 @@ -310,6 +310,7 @@ struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ u8 ctl; /* cache of ATA control register */ + u8 last_ctl; /* Cache last written value */ unsigned int bus_state; unsigned int port_state; unsigned int pio_mask; @@ -522,12 +523,12 @@ struct ata_ioports *ioaddr = &ap->ioaddr; ap->ctl &= ~ATA_NIEN; + ap->last_ctl = ap->ctl; if (ap->flags & ATA_FLAG_MMIO) writeb(ap->ctl, ioaddr->ctl_addr); else outb(ap->ctl, ioaddr->ctl_addr); - return ata_wait_idle(ap); } diff -Nru a/include/net/sock.h b/include/net/sock.h --- a/include/net/sock.h Tue Nov 25 19:25:22 2003 +++ b/include/net/sock.h Tue Nov 25 19:25:22 2003 @@ -917,6 +917,7 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { int err = 0; + int skb_len; /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces number of warnings when compiling with -W --ANK @@ -937,9 +938,18 @@ skb->dev = NULL; skb_set_owner_r(skb, sk); + + /* Cache the SKB length before we tack it onto the receive + * queue. Once it is added it no longer belongs to us and + * may be freed by other threads of control pulling packets + * from the queue. + */ + skb_len = skb->len; + skb_queue_tail(&sk->sk_receive_queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk, skb->len); + sk->sk_data_ready(sk, skb_len); out: return err; } diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h --- a/include/scsi/scsi_device.h Tue Nov 25 19:25:22 2003 +++ b/include/scsi/scsi_device.h Tue Nov 25 19:25:22 2003 @@ -14,11 +14,15 @@ /* * sdev state */ -enum { - SDEV_ADD, - SDEV_DEL, - SDEV_CANCEL, - SDEV_RECOVERY, +enum scsi_device_state { + SDEV_CREATED, /* device created but not added to sysfs + * Only internal commands allowed (for inq) */ + SDEV_RUNNING, /* device properly configured + * All commands allowed */ + SDEV_CANCEL, /* beginning to delete device + * Only error handler commands allowed */ + SDEV_DEL, /* device deleted + * no commands allowed */ }; struct scsi_device { @@ -99,7 +103,7 @@ struct device sdev_gendev; struct class_device sdev_classdev; - unsigned long sdev_state; + enum scsi_device_state sdev_state; }; #define to_scsi_device(d) \ container_of(d, struct scsi_device, sdev_gendev) diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Tue Nov 25 19:25:22 2003 +++ b/kernel/fork.c Tue Nov 25 19:25:22 2003 @@ -1014,6 +1014,7 @@ if (current->signal->group_exit) { spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); + retval = -EAGAIN; goto bad_fork_cleanup_namespace; } p->tgid = current->tgid; diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c --- a/net/econet/af_econet.c Tue Nov 25 19:25:22 2003 +++ b/net/econet/af_econet.c Tue Nov 25 19:25:22 2003 @@ -1041,12 +1041,15 @@ if (!sk) goto drop; - return ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, - hdr->port); + if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, + hdr->port)) + goto drop; + + return 0; drop: kfree_skb(skb); - return 0; + return NET_RX_DROP; } static struct packet_type econet_packet_type = { diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c --- a/net/ipv6/mcast.c Tue Nov 25 19:25:22 2003 +++ b/net/ipv6/mcast.c Tue Nov 25 19:25:22 2003 @@ -47,6 +47,9 @@ #include #include +#include +#include + #include #include @@ -1270,6 +1273,7 @@ struct mld2_report *pmr = (struct mld2_report *)skb->h.raw; int payload_len, mldlen; struct inet6_dev *idev = in6_dev_get(skb->dev); + int err; payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - sizeof(struct ipv6hdr); @@ -1278,8 +1282,10 @@ pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0)); - dev_queue_xmit(skb); - ICMP6_INC_STATS(idev,Icmp6OutMsgs); + err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, + dev_queue_xmit); + if (!err) + ICMP6_INC_STATS(idev,Icmp6OutMsgs); if (likely(idev != NULL)) in6_dev_put(idev); } @@ -1608,12 +1614,15 @@ idev = in6_dev_get(skb->dev); - dev_queue_xmit(skb); - if (type == ICMPV6_MGM_REDUCTION) - ICMP6_INC_STATS(idev, Icmp6OutGroupMembReductions); - else - ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses); - ICMP6_INC_STATS(idev, Icmp6OutMsgs); + err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, + dev_queue_xmit); + if (!err) { + if (type == ICMPV6_MGM_REDUCTION) + ICMP6_INC_STATS(idev, Icmp6OutGroupMembReductions); + else + ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses); + ICMP6_INC_STATS(idev, Icmp6OutMsgs); + } if (likely(idev != NULL)) in6_dev_put(idev);