Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 6 Mar 2008 16:14:00 +0000 (08:14 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 6 Mar 2008 16:14:00 +0000 (08:14 -0800)
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6:
  [XFS] fix inode leak in xfs_iget_core()
  [XFS] 977545 977545 977545 977545 977545 977545 xfsaild causing too many

65 files changed:
Documentation/scsi/ChangeLog.arcmsr
arch/s390/Kconfig
arch/s390/defconfig
arch/s390/kernel/Makefile
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/process.c
arch/s390/kernel/smp.c
arch/s390/kernel/time.c
arch/x86/kernel/cpu/cpufreq/e_powersaver.c
drivers/ata/ahci.c
drivers/ata/pata_hpt366.c
drivers/ata/pata_hpt37x.c
drivers/ata/pata_serverworks.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_stats.c
drivers/message/fusion/mptsas.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/sclp_vt220.c
drivers/s390/crypto/ap_bus.c
drivers/scsi/aic94xx/aic94xx.h
drivers/scsi/aic94xx/aic94xx_hwi.h
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/aic94xx/aic94xx_tmf.c
drivers/scsi/arcmsr/arcmsr.h
drivers/scsi/gdth.c
drivers/scsi/gdth.h
drivers/scsi/ibmvscsi/ibmvstgt.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/mvsas.c
drivers/scsi/ps3rom.c
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/scsi_transport_iscsi.c
fs/nfs/internal.h
fs/nfs/super.c
fs/super.c
include/asm-mn10300/Kbuild
include/asm-x86/Kbuild
include/linux/security.h
include/scsi/libsas.h
include/scsi/scsi_transport_iscsi.h
kernel/cpuset.c
security/dummy.c
security/security.c
security/selinux/hooks.c
security/selinux/include/security.h
security/smack/smack_lsm.c

index de2bcacfa870a6f1e3bc94369fda343db1e8b4a7..038a3e6ecaa43d5c064061734ea7e893675893e9 100644 (file)
 **                                             8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer()
 **                                             9. fix the release of dma memory for type B in arcmsr_free_ccb_pool()
 **                                             10.fix the arcmsr_polling_hbb_ccbdone()
+** 1.20.00.15  02/27/2008      Erich Chen & Nick Cheng
+**                                             1.arcmsr_iop_message_xfer() is called from atomic context under the
+**                                             queuecommand scsi_host_template handler. James Bottomley pointed out
+**                                             that the current GFP_KERNEL|GFP_DMA flags are wrong: firstly we are in
+**                                             atomic context, secondly this memory is not used for DMA.
+**                                             Also removed some unneeded casts. Thanks to Daniel Drake <dsd@gentoo.org>
 **************************************************************************
index 9892827b6176ca5f75f250807ef5e88903f7d1a7..1831833c430edc8d17015c739e9262b46bc88e77 100644 (file)
@@ -351,6 +351,10 @@ endchoice
 
 source "fs/Kconfig.binfmt"
 
+config FORCE_MAX_ZONEORDER
+       int
+       default "9"
+
 config PROCESS_DEBUG
        bool "Show crashed user process info"
        help
index 39921f3a9685a74247c9c2b8fbee8ad48bf1142c..62f6b5a606ddf3a8afbd63983822c0f14e45d483 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24
-# Sat Feb  9 12:13:01 2008
+# Linux kernel version: 2.6.25-rc4
+# Wed Mar  5 11:22:59 2008
 #
 CONFIG_MMU=y
 CONFIG_ZONE_DMA=y
@@ -43,12 +43,15 @@ CONFIG_CGROUPS=y
 # CONFIG_CGROUP_DEBUG is not set
 CONFIG_CGROUP_NS=y
 # CONFIG_CPUSETS is not set
+CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUP_CPUACCT is not set
 # CONFIG_RESOURCE_COUNTERS is not set
 CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
@@ -85,7 +88,9 @@ CONFIG_SLAB=y
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
 CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -185,6 +190,7 @@ CONFIG_IPL=y
 CONFIG_IPL_VM=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
+CONFIG_FORCE_MAX_ZONEORDER=9
 # CONFIG_PROCESS_DEBUG is not set
 CONFIG_PFAULT=y
 # CONFIG_SHARED_KERNEL is not set
@@ -435,6 +441,7 @@ CONFIG_DASD_EER=y
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HAVE_IDE is not set
 
 #
 # SCSI device support
@@ -593,6 +600,7 @@ CONFIG_S390_VMUR=m
 #
 # Sonics Silicon Backplane
 #
+# CONFIG_MEMSTICK is not set
 
 #
 # File systems
@@ -750,7 +758,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_FRAME_POINTER is not set
-CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_KPROBES_SANITY_TEST is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -759,6 +766,7 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_LATENCYTOP is not set
 CONFIG_SAMPLES=y
 # CONFIG_SAMPLE_KOBJECT is not set
+# CONFIG_SAMPLE_KPROBES is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
 
 #
index b3b650a93c7c752f6d95c5b789beef5cfbd99589..4d3e38392cb1486dd11db7868098ec30c22808b4 100644 (file)
@@ -4,6 +4,11 @@
 
 EXTRA_AFLAGS   := -traditional
 
+#
+# Passing null pointers is ok for smp code, since we access the lowcore here.
+#
+CFLAGS_smp.o   := -Wno-nonnull
+
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
            semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o
index 9f7b73b180f00a064ce36457b9ba88e0ecb38c79..01832c44063629ebf66afc77bb01fc2d838197bc 100644 (file)
@@ -88,13 +88,17 @@ static noinline __init void create_kernel_nss(void)
 
        __cpcmd(defsys_cmd, NULL, 0, &response);
 
-       if (response != 0)
+       if (response != 0) {
+               kernel_nss_name[0] = '\0';
                return;
+       }
 
        __cpcmd(savesys_cmd, NULL, 0, &response);
 
-       if (response != strlen(savesys_cmd))
+       if (response != strlen(savesys_cmd)) {
+               kernel_nss_name[0] = '\0';
                return;
+       }
 
        ipl_flags = IPL_NSS_VALID;
 }
index 60acdc266db177fab528d5cedea72829a1cbe939..375232c46c7a51178f1e51c7a83043026c8c68d1 100644 (file)
@@ -704,6 +704,7 @@ void reipl_run(struct shutdown_trigger *trigger)
        default:
                break;
        }
+       disabled_wait((unsigned long) __builtin_return_address(0));
 }
 
 static void __init reipl_probe(void)
index 1c59ec161cf8772e5ac260aa0cce812c4db84ba8..ce203154d8ce3a6c8f9bf4a07cd7ad072e3b3ec8 100644 (file)
@@ -152,6 +152,10 @@ static void default_idle(void)
        local_mcck_disable();
        if (test_thread_flag(TIF_MCCK_PENDING)) {
                local_mcck_enable();
+               /* disable monitor call class 0 */
+               __ctl_clear_bit(8, 15);
+               atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+                                          hcpu);
                local_irq_enable();
                s390_handle_mcck();
                return;
index 818bd09c0260e05fb3a58eb2764f88e8f055a585..8f894d380a626316c68aeb073043f027abdcfee6 100644 (file)
@@ -629,14 +629,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
        panic_stack = __get_free_page(GFP_KERNEL);
        if (!panic_stack || !async_stack)
                goto out;
-       /*
-        * Only need to copy the first 512 bytes from address 0. But since
-        * the compiler emits a warning if src == NULL for memcpy use copy_page
-        * instead. Copies more than needed but this code is not performance
-        * critical.
-        */
-       copy_page(lowcore, &S390_lowcore);
-       memset((void *)lowcore + 512, 0, sizeof(*lowcore) - 512);
+       memcpy(lowcore, &S390_lowcore, 512);
+       memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
        lowcore->async_stack = async_stack + ASYNC_SIZE;
        lowcore->panic_stack = panic_stack + PAGE_SIZE;
 
index 76a5dd1b4ce9a1376f85c7d1e8711aa423a6f85a..cb232c155360627866c4e9f7decda622f4048b50 100644 (file)
@@ -209,8 +209,6 @@ static void stop_hz_timer(void)
  */
 static void start_hz_timer(void)
 {
-       BUG_ON(!in_interrupt());
-
        if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
                return;
        account_ticks(get_clock());
index 39f8cb18296c68fc74fa999a195f0d1fa20a9787..c2f930d8664091932c1a7b614d860f8f365b7f10 100644 (file)
@@ -55,7 +55,6 @@ static int eps_set_state(struct eps_cpu_data *centaur,
 {
        struct cpufreq_freqs freqs;
        u32 lo, hi;
-       u8 current_multiplier, current_voltage;
        int err = 0;
        int i;
 
@@ -95,6 +94,10 @@ postchange:
        rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
        freqs.new = centaur->fsb * ((lo >> 8) & 0xff);
 
+#ifdef DEBUG
+       {
+       u8 current_multiplier, current_voltage;
+
        /* Print voltage and multiplier */
        rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
        current_voltage = lo & 0xff;
@@ -103,7 +106,8 @@ postchange:
        current_multiplier = (lo >> 8) & 0xff;
        printk(KERN_INFO "eps: Current multiplier = %d\n",
                current_multiplier);
-
+       }
+#endif
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
        return err;
 }
index 1db93b6190744015e251c5d428b58a762cf3c39a..8a49835bd0f85b141b53507e73b78cab945ef6ff 100644 (file)
@@ -186,6 +186,7 @@ enum {
        AHCI_HFLAG_NO_MSI               = (1 << 5), /* no PCI MSI */
        AHCI_HFLAG_NO_PMP               = (1 << 6), /* no PMP */
        AHCI_HFLAG_NO_HOTPLUG           = (1 << 7), /* ignore PxSERR.DIAG.N */
+       AHCI_HFLAG_SECT255              = (1 << 8), /* max 255 sectors */
 
        /* ap->flags bits */
 
@@ -255,6 +256,7 @@ static void ahci_vt8251_error_handler(struct ata_port *ap);
 static void ahci_p5wdh_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static int ahci_port_resume(struct ata_port *ap);
+static void ahci_dev_config(struct ata_device *dev);
 static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
 static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
                               u32 opts);
@@ -294,6 +296,8 @@ static const struct ata_port_operations ahci_ops = {
        .check_altstatus        = ahci_check_status,
        .dev_select             = ata_noop_dev_select,
 
+       .dev_config             = ahci_dev_config,
+
        .tf_read                = ahci_tf_read,
 
        .qc_defer               = sata_pmp_qc_defer_cmd_switch,
@@ -425,7 +429,7 @@ static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci_sb600 */
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_SERR_INTERNAL |
-                                AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_PMP),
+                                AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
                .flags          = AHCI_FLAG_COMMON,
                .link_flags     = AHCI_LFLAG_COMMON,
                .pio_mask       = 0x1f, /* pio0-4 */
@@ -1176,6 +1180,14 @@ static void ahci_init_controller(struct ata_host *host)
        VPRINTK("HOST_CTL 0x%x\n", tmp);
 }
 
+static void ahci_dev_config(struct ata_device *dev)
+{
+       struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
+
+       if (hpriv->flags & AHCI_HFLAG_SECT255)
+               dev->max_sectors = 255;
+}
+
 static unsigned int ahci_dev_classify(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
index 0713872cf65c64c936c14a15aacda6c7f851f640..a742efa0da2b53cbde8409e87a6a57c01b503c76 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt366"
-#define DRV_VERSION    "0.6.1"
+#define DRV_VERSION    "0.6.2"
 
 struct hpt_clock {
        u8      xfer_speed;
@@ -180,9 +180,9 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
                if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
                        mask &= ~ATA_MASK_UDMA;
                if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
-                       mask &= ~(0x07 << ATA_SHIFT_UDMA);
+                       mask &= ~(0xF8 << ATA_SHIFT_UDMA);
                if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
-                       mask &= ~(0x0F << ATA_SHIFT_UDMA);
+                       mask &= ~(0xF0 << ATA_SHIFT_UDMA);
        }
        return ata_pci_default_filter(adev, mask);
 }
index 68eb34929cecde9c7ed149f3fa5e1dc15c65fd3a..9a10878b2ad870049cbd0341dee7b30adacbf44c 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt37x"
-#define DRV_VERSION    "0.6.9"
+#define DRV_VERSION    "0.6.11"
 
 struct hpt_clock {
        u8      xfer_speed;
@@ -281,7 +281,7 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask)
                if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
                        mask &= ~ATA_MASK_UDMA;
                if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
-                       mask &= ~(0x1F << ATA_SHIFT_UDMA);
+                       mask &= ~(0xE0 << ATA_SHIFT_UDMA);
        }
        return ata_pci_default_filter(adev, mask);
 }
@@ -297,7 +297,7 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
 {
        if (adev->class == ATA_DEV_ATA) {
                if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
-                       mask &= ~ (0x1F << ATA_SHIFT_UDMA);
+                       mask &= ~(0xE0 << ATA_SHIFT_UDMA);
        }
        return ata_pci_default_filter(adev, mask);
 }
index 9c523fbf529ead0d92fe8c8d60356be5f0c5cbbd..a589c0fa0dbb699d3e1108f59b577cc645f4bfad 100644 (file)
@@ -226,7 +226,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
 
        for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) {
                if (!strcmp(p, model_num))
-                       mask &= ~(0x1F << ATA_SHIFT_UDMA);
+                       mask &= ~(0xE0 << ATA_SHIFT_UDMA);
        }
        return ata_pci_default_filter(adev, mask);
 }
index 89a29cd9378379a00f80e6899eadbac949f03fde..35a26a3e5f6804d977563ddd5ef03db8e8ea5f5c 100644 (file)
@@ -671,13 +671,13 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
 {
        struct cpufreq_policy * policy = to_policy(kobj);
        struct freq_attr * fattr = to_attr(attr);
-       ssize_t ret;
+       ssize_t ret = -EINVAL;
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
-               return -EINVAL;
+               goto no_policy;
 
        if (lock_policy_rwsem_read(policy->cpu) < 0)
-               return -EINVAL;
+               goto fail;
 
        if (fattr->show)
                ret = fattr->show(policy, buf);
@@ -685,8 +685,9 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
                ret = -EIO;
 
        unlock_policy_rwsem_read(policy->cpu);
-
+fail:
        cpufreq_cpu_put(policy);
+no_policy:
        return ret;
 }
 
@@ -695,13 +696,13 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
 {
        struct cpufreq_policy * policy = to_policy(kobj);
        struct freq_attr * fattr = to_attr(attr);
-       ssize_t ret;
+       ssize_t ret = -EINVAL;
        policy = cpufreq_cpu_get(policy->cpu);
        if (!policy)
-               return -EINVAL;
+               goto no_policy;
 
        if (lock_policy_rwsem_write(policy->cpu) < 0)
-               return -EINVAL;
+               goto fail;
 
        if (fattr->store)
                ret = fattr->store(policy, buf, count);
@@ -709,8 +710,9 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
                ret = -EIO;
 
        unlock_policy_rwsem_write(policy->cpu);
-
+fail:
        cpufreq_cpu_put(policy);
+no_policy:
        return ret;
 }
 
@@ -1775,7 +1777,7 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata cpufreq_cpu_notifier =
+static struct notifier_block __refdata cpufreq_cpu_notifier =
 {
     .notifier_call = cpufreq_cpu_callback,
 };
index 1b8312b0200675e81722def6d6b51134594e1250..070421a5480e731116ed58845e5ac424cfaf0aba 100644 (file)
@@ -323,7 +323,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block cpufreq_stat_cpu_notifier __cpuinitdata =
+static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
 {
        .notifier_call = cpufreq_stat_cpu_callback,
 };
index f77b329f6923baab6e4b23742981b97b58393046..78734e25edd515bcc863fbcae3216c6447e045eb 100644 (file)
@@ -1701,6 +1701,11 @@ mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
        if (error)
                goto out_free_consistent;
 
+       if (!buffer->NumPhys) {
+               error = -ENODEV;
+               goto out_free_consistent;
+       }
+
        /* save config data */
        port_info->num_phys = buffer->NumPhys;
        port_info->phy_info = kcalloc(port_info->num_phys,
index 6ac81e35355cd39fc8232698b790de75f077e59b..2759604629703e6ea9d9c2e6735478a9cd5a9e1c 100644 (file)
@@ -1000,8 +1000,8 @@ static int __init ubi_init(void)
                mutex_unlock(&ubi_devices_mutex);
                if (err < 0) {
                        put_mtd_device(mtd);
-                       printk(KERN_ERR "UBI error: cannot attach %s\n",
-                              p->name);
+                       printk(KERN_ERR "UBI error: cannot attach mtd%d\n",
+                              mtd->index);
                        goto out_detach;
                }
        }
index 457710615261126e2fef2d2ad6463c991d83a895..a548c1d28fa818a5485aa5524a2527eff269edf0 100644 (file)
@@ -217,11 +217,11 @@ struct ubi_volume {
        void *upd_buf;
 
        int *eba_tbl;
-       int checked:1;
-       int corrupted:1;
-       int upd_marker:1;
-       int updating:1;
-       int changing_leb:1;
+       unsigned int checked:1;
+       unsigned int corrupted:1;
+       unsigned int upd_marker:1;
+       unsigned int updating:1;
+       unsigned int changing_leb:1;
 
 #ifdef CONFIG_MTD_UBI_GLUEBI
        /*
index a3ca2257e6015e586ddcbfa513acb760b01afb08..5be58d85c6393c53c2be0f4693ff8a9bd13e40b3 100644 (file)
@@ -376,7 +376,9 @@ out_sysfs:
        get_device(&vol->dev);
        volume_sysfs_close(vol);
 out_gluebi:
-       ubi_destroy_gluebi(vol);
+       if (ubi_destroy_gluebi(vol))
+               dbg_err("cannot destroy gluebi for volume %d:%d",
+                       ubi->ubi_num, vol_id);
 out_cdev:
        cdev_del(&vol->cdev);
 out_mapping:
index 56fc3fbce838179b7d34276ccbb51e1ee2ff2018..af36b12be27871ddefd1c34a0d17f95483042343 100644 (file)
@@ -519,6 +519,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
                        if (ubi->autoresize_vol_id != -1) {
                                ubi_err("more then one auto-resize volume (%d "
                                        "and %d)", ubi->autoresize_vol_id, i);
+                               kfree(vol);
                                return -EINVAL;
                        }
 
index 60d338cd80090ff02dd20cc9e1fec5b684e8f588..62db3c3fe4dcbd35dcd6181c4061954e4b0b0d87 100644 (file)
@@ -366,8 +366,8 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
        ** ggg sacrifices another 710 to the computer gods.
        */
 
-       boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, 1 << IOVP_SHIFT);
-       boundary_size >>= IOVP_SHIFT;
+       boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
+                             1ULL << IOVP_SHIFT) >> IOVP_SHIFT;
 
        if (pages_needed <= 8) {
                /*
index e834127a8505350554806369e3d31e9cba129440..bdbe780e21c51e36de99d359c4304bfac2cc2054 100644 (file)
@@ -341,8 +341,8 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev,
        unsigned long shift;
        int ret;
 
-       boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, 1 << IOVP_SHIFT);
-       boundary_size >>= IOVP_SHIFT;
+       boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
+                             1ULL << IOVP_SHIFT) >> IOVP_SHIFT;
 
 #if defined(ZX1_SUPPORT)
        BUG_ON(ioc->ibase & ~IOVP_MASK);
index f69714a0e9e7bf3ed750e3b497ce429d2f459ffb..b19db20a0befdc1c31ea98bdf691daaec6807f6f 100644 (file)
@@ -2310,10 +2310,8 @@ static int
 dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
 {
 
-       /* check failed CCW */
-       if (cqr1->irb.scsw.cpa != cqr2->irb.scsw.cpa) {
-               //      return 0;       /* CCW doesn't match */
-       }
+       if (cqr1->startdev != cqr2->startdev)
+               return 0;
 
        if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons)
                return 0;
index 28a86f070048b4a3a25719fb100546df9cd8ebd8..556063e8f7a91d1163450cc63d1cd9128e6a77b4 100644 (file)
@@ -62,8 +62,10 @@ dasd_devices_show(struct seq_file *m, void *v)
                return 0;
        if (device->block)
                block = device->block;
-       else
+       else {
+               dasd_put_device(device);
                return 0;
+       }
        /* Print device number. */
        seq_printf(m, "%s", device->cdev->dev.bus_id);
        /* Print discipline string. */
index 92f527201792971095eea15a1503c0938d1eaeb0..f7b258dfd52cf5a40c14470654a240c0f29b0a93 100644 (file)
@@ -367,7 +367,7 @@ sclp_vt220_timeout(unsigned long data)
        sclp_vt220_emit_current();
 }
 
-#define BUFFER_MAX_DELAY       HZ/2
+#define BUFFER_MAX_DELAY       HZ/20
 
 /* 
  * Internal implementation of the write function. Write COUNT bytes of data
index d0c6fd3b1c19a02af51665e657fc102829d4d488..7b0b81901297e9b0d28d967dee4694fb2cd9fadc 100644 (file)
@@ -490,10 +490,12 @@ static int ap_device_probe(struct device *dev)
        int rc;
 
        ap_dev->drv = ap_drv;
-       spin_lock_bh(&ap_device_lock);
-       list_add(&ap_dev->list, &ap_device_list);
-       spin_unlock_bh(&ap_device_lock);
        rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
+       if (!rc) {
+               spin_lock_bh(&ap_device_lock);
+               list_add(&ap_dev->list, &ap_device_list);
+               spin_unlock_bh(&ap_device_lock);
+       }
        return rc;
 }
 
@@ -532,11 +534,11 @@ static int ap_device_remove(struct device *dev)
 
        ap_flush_queue(ap_dev);
        del_timer_sync(&ap_dev->timeout);
-       if (ap_drv->remove)
-               ap_drv->remove(ap_dev);
        spin_lock_bh(&ap_device_lock);
        list_del_init(&ap_dev->list);
        spin_unlock_bh(&ap_device_lock);
+       if (ap_drv->remove)
+               ap_drv->remove(ap_dev);
        spin_lock_bh(&ap_dev->lock);
        atomic_sub(ap_dev->queue_count, &ap_poll_requests);
        spin_unlock_bh(&ap_dev->lock);
index 32f513b1b78ab314253e7ddceb4117aa5e40fcad..eb8efdcefe482e0bf8997b566a72db30d76027ba 100644 (file)
@@ -102,6 +102,7 @@ int  asd_abort_task_set(struct domain_device *, u8 *lun);
 int  asd_clear_aca(struct domain_device *, u8 *lun);
 int  asd_clear_task_set(struct domain_device *, u8 *lun);
 int  asd_lu_reset(struct domain_device *, u8 *lun);
+int  asd_I_T_nexus_reset(struct domain_device *dev);
 int  asd_query_task(struct sas_task *);
 
 /* ---------- Adapter and Port management ---------- */
index 150f6706d23f8d95a024fbd5836da76bcd8ac91c..abc757559c1af2911584f3e14be97c69159d923c 100644 (file)
@@ -140,7 +140,7 @@ struct asd_ascb {
 
        /* internally generated command */
        struct timer_list timer;
-       struct completion completion;
+       struct completion *completion;
        u8        tag_valid:1;
        __be16    tag;            /* error recovery only */
 
@@ -294,7 +294,6 @@ static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
        ascb->timer.function = NULL;
        init_timer(&ascb->timer);
        ascb->tc_index = -1;
-       init_completion(&ascb->completion);
 }
 
 /* Must be called with the tc_index_lock held!
index 5d761eb67442356fa50e360e4cde33af360c8612..88d1e731b65e15b04e5e1a71f281ba1d2035a8d7 100644 (file)
@@ -1003,7 +1003,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
        .lldd_abort_task_set    = asd_abort_task_set,
        .lldd_clear_aca         = asd_clear_aca,
        .lldd_clear_task_set    = asd_clear_task_set,
-       .lldd_I_T_nexus_reset   = NULL,
+       .lldd_I_T_nexus_reset   = asd_I_T_nexus_reset,
        .lldd_lu_reset          = asd_lu_reset,
        .lldd_query_task        = asd_query_task,
 
index 965d4bb999d919f314ec83e810c8ad85b0f17075..008df9ab92a5f89b57c8f8cf36fa8ede7abc36d8 100644 (file)
@@ -343,11 +343,13 @@ Again:
        task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
        task->task_state_flags |= SAS_TASK_STATE_DONE;
        if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
+               struct completion *completion = ascb->completion;
                spin_unlock_irqrestore(&task->task_state_lock, flags);
                ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x "
                            "stat 0x%x but aborted by upper layer!\n",
                            task, opcode, ts->resp, ts->stat);
-               complete(&ascb->completion);
+               if (completion)
+                       complete(completion);
        } else {
                spin_unlock_irqrestore(&task->task_state_lock, flags);
                task->lldd_task = NULL;
index 144f5ad20453bbc56ec010d8e870c881c0ef0fd2..b9ac8f703a1d7914d3f269a4e6bddee9a90cda4c 100644 (file)
@@ -53,50 +53,64 @@ static int asd_enqueue_internal(struct asd_ascb *ascb,
        return res;
 }
 
-static inline void asd_timedout_common(unsigned long data)
-{
-       struct asd_ascb *ascb = (void *) data;
-       struct asd_seq_data *seq = &ascb->ha->seq;
-        unsigned long flags;
+/* ---------- CLEAR NEXUS ---------- */
 
-       spin_lock_irqsave(&seq->pend_q_lock, flags);
-        seq->pending--;
-        list_del_init(&ascb->list);
-        spin_unlock_irqrestore(&seq->pend_q_lock, flags);
-}
+struct tasklet_completion_status {
+       int     dl_opcode;
+       int     tmf_state;
+       u8      tag_valid:1;
+       __be16  tag;
+};
+
+#define DECLARE_TCS(tcs) \
+       struct tasklet_completion_status tcs = { \
+               .dl_opcode = 0, \
+               .tmf_state = 0, \
+               .tag_valid = 0, \
+               .tag = 0, \
+       }
 
-/* ---------- CLEAR NEXUS ---------- */
 
 static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,
                                             struct done_list_struct *dl)
 {
+       struct tasklet_completion_status *tcs = ascb->uldd_task;
        ASD_DPRINTK("%s: here\n", __FUNCTION__);
        if (!del_timer(&ascb->timer)) {
                ASD_DPRINTK("%s: couldn't delete timer\n", __FUNCTION__);
                return;
        }
        ASD_DPRINTK("%s: opcode: 0x%x\n", __FUNCTION__, dl->opcode);
-       ascb->uldd_task = (void *) (unsigned long) dl->opcode;
-       complete(&ascb->completion);
+       tcs->dl_opcode = dl->opcode;
+       complete(ascb->completion);
+       asd_ascb_free(ascb);
 }
 
 static void asd_clear_nexus_timedout(unsigned long data)
 {
-       struct asd_ascb *ascb = (void *) data;
+       struct asd_ascb *ascb = (void *)data;
+       struct tasklet_completion_status *tcs = ascb->uldd_task;
 
        ASD_DPRINTK("%s: here\n", __FUNCTION__);
-       asd_timedout_common(data);
-       ascb->uldd_task = (void *) TMF_RESP_FUNC_FAILED;
-       complete(&ascb->completion);
+       tcs->dl_opcode = TMF_RESP_FUNC_FAILED;
+       complete(ascb->completion);
 }
 
 #define CLEAR_NEXUS_PRE         \
+       struct asd_ascb *ascb; \
+       struct scb *scb; \
+       int res; \
+       DECLARE_COMPLETION_ONSTACK(completion); \
+       DECLARE_TCS(tcs); \
+               \
        ASD_DPRINTK("%s: PRE\n", __FUNCTION__); \
         res = 1;                \
        ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \
        if (!ascb)              \
                return -ENOMEM; \
                                 \
+       ascb->completion = &completion; \
+       ascb->uldd_task = &tcs; \
        scb = ascb->scb;        \
        scb->header.opcode = CLEAR_NEXUS
 
@@ -107,10 +121,11 @@ static void asd_clear_nexus_timedout(unsigned long data)
        if (res)                \
                goto out_err;   \
        ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __FUNCTION__); \
-       wait_for_completion(&ascb->completion); \
-       res = (int) (unsigned long) ascb->uldd_task; \
+       wait_for_completion(&completion); \
+       res = tcs.dl_opcode; \
        if (res == TC_NO_ERROR) \
                res = TMF_RESP_FUNC_COMPLETE;   \
+       return res; \
 out_err:                        \
        asd_ascb_free(ascb);    \
        return res
@@ -118,9 +133,6 @@ out_err:                        \
 int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)
 {
        struct asd_ha_struct *asd_ha = sas_ha->lldd_ha;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_ADAPTER;
@@ -130,9 +142,6 @@ int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)
 int asd_clear_nexus_port(struct asd_sas_port *port)
 {
        struct asd_ha_struct *asd_ha = port->ha->lldd_ha;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_PORT;
@@ -140,29 +149,73 @@ int asd_clear_nexus_port(struct asd_sas_port *port)
        CLEAR_NEXUS_POST;
 }
 
-#if 0
-static int asd_clear_nexus_I_T(struct domain_device *dev)
+enum clear_nexus_phase {
+       NEXUS_PHASE_PRE,
+       NEXUS_PHASE_POST,
+       NEXUS_PHASE_RESUME,
+};
+
+static int asd_clear_nexus_I_T(struct domain_device *dev,
+                              enum clear_nexus_phase phase)
 {
        struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_I_T;
-       scb->clear_nexus.flags = SEND_Q | EXEC_Q | NOTINQ;
+       switch (phase) {
+       case NEXUS_PHASE_PRE:
+               scb->clear_nexus.flags = EXEC_Q | SUSPEND_TX;
+               break;
+       case NEXUS_PHASE_POST:
+               scb->clear_nexus.flags = SEND_Q | NOTINQ;
+               break;
+       case NEXUS_PHASE_RESUME:
+               scb->clear_nexus.flags = RESUME_TX;
+       }
        scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)
                                                   dev->lldd_dev);
        CLEAR_NEXUS_POST;
 }
-#endif
+
+int asd_I_T_nexus_reset(struct domain_device *dev)
+{
+       int res, tmp_res, i;
+       struct sas_phy *phy = sas_find_local_phy(dev);
+       /* Standard mandates link reset for ATA  (type 0) and
+        * hard reset for SSP (type 1) */
+       int reset_type = (dev->dev_type == SATA_DEV ||
+                         (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
+
+       asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);
+       /* send a hard reset */
+       ASD_DPRINTK("sending %s reset to %s\n",
+                   reset_type ? "hard" : "soft", phy->dev.bus_id);
+       res = sas_phy_reset(phy, reset_type);
+       if (res == TMF_RESP_FUNC_COMPLETE) {
+               /* wait for the maximum settle time */
+               msleep(500);
+               /* clear all outstanding commands (keep nexus suspended) */
+               asd_clear_nexus_I_T(dev, NEXUS_PHASE_POST);
+       }
+       for (i = 0 ; i < 3; i++) {
+               tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);
+               if (tmp_res == TC_RESUME)
+                       return res;
+               msleep(500);
+       }
+
+       /* This is a bit of a problem:  the sequencer is still suspended
+        * and is refusing to resume.  Hope it will resume on a bigger hammer
+        * or the disk is lost */
+       dev_printk(KERN_ERR, &phy->dev,
+                  "Failed to resume nexus after reset 0x%x\n", tmp_res);
+
+       return TMF_RESP_FUNC_FAILED;
+}
 
 static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)
 {
        struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_I_T_L;
@@ -177,9 +230,6 @@ static int asd_clear_nexus_tag(struct sas_task *task)
 {
        struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
        struct asd_ascb *tascb = task->lldd_task;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_TAG;
@@ -195,9 +245,6 @@ static int asd_clear_nexus_index(struct sas_task *task)
 {
        struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
        struct asd_ascb *tascb = task->lldd_task;
-       struct asd_ascb *ascb;
-       struct scb *scb;
-       int res;
 
        CLEAR_NEXUS_PRE;
        scb->clear_nexus.nexus = NEXUS_TRANS_CX;
@@ -213,11 +260,11 @@ static int asd_clear_nexus_index(struct sas_task *task)
 static void asd_tmf_timedout(unsigned long data)
 {
        struct asd_ascb *ascb = (void *) data;
+       struct tasklet_completion_status *tcs = ascb->uldd_task;
 
        ASD_DPRINTK("tmf timed out\n");
-       asd_timedout_common(data);
-       ascb->uldd_task = (void *) TMF_RESP_FUNC_FAILED;
-       complete(&ascb->completion);
+       tcs->tmf_state = TMF_RESP_FUNC_FAILED;
+       complete(ascb->completion);
 }
 
 static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb,
@@ -269,18 +316,24 @@ static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb,
 static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
                                     struct done_list_struct *dl)
 {
+       struct tasklet_completion_status *tcs;
+
        if (!del_timer(&ascb->timer))
                return;
 
+       tcs = ascb->uldd_task;
        ASD_DPRINTK("tmf tasklet complete\n");
 
-       if (dl->opcode == TC_SSP_RESP)
-               ascb->uldd_task = (void *) (unsigned long)
-                       asd_get_tmf_resp_tasklet(ascb, dl);
-       else
-               ascb->uldd_task = (void *) 0xFF00 + (unsigned long) dl->opcode;
+       tcs->dl_opcode = dl->opcode;
+
+       if (dl->opcode == TC_SSP_RESP) {
+               tcs->tmf_state = asd_get_tmf_resp_tasklet(ascb, dl);
+               tcs->tag_valid = ascb->tag_valid;
+               tcs->tag = ascb->tag;
+       }
 
-       complete(&ascb->completion);
+       complete(ascb->completion);
+       asd_ascb_free(ascb);
 }
 
 static inline int asd_clear_nexus(struct sas_task *task)
@@ -288,15 +341,19 @@ static inline int asd_clear_nexus(struct sas_task *task)
        int res = TMF_RESP_FUNC_FAILED;
        int leftover;
        struct asd_ascb *tascb = task->lldd_task;
+       DECLARE_COMPLETION_ONSTACK(completion);
        unsigned long flags;
 
+       tascb->completion = &completion;
+
        ASD_DPRINTK("task not done, clearing nexus\n");
        if (tascb->tag_valid)
                res = asd_clear_nexus_tag(task);
        else
                res = asd_clear_nexus_index(task);
-       leftover = wait_for_completion_timeout(&tascb->completion,
+       leftover = wait_for_completion_timeout(&completion,
                                               AIC94XX_SCB_TIMEOUT);
+       tascb->completion = NULL;
        ASD_DPRINTK("came back from clear nexus\n");
        spin_lock_irqsave(&task->task_state_lock, flags);
        if (leftover < 1)
@@ -350,6 +407,11 @@ int asd_abort_task(struct sas_task *task)
        struct asd_ascb *ascb = NULL;
        struct scb *scb;
        int leftover;
+       DECLARE_TCS(tcs);
+       DECLARE_COMPLETION_ONSTACK(completion);
+       DECLARE_COMPLETION_ONSTACK(tascb_completion);
+
+       tascb->completion = &tascb_completion;
 
        spin_lock_irqsave(&task->task_state_lock, flags);
        if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -363,8 +425,10 @@ int asd_abort_task(struct sas_task *task)
        ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
        if (!ascb)
                return -ENOMEM;
-       scb = ascb->scb;
 
+       ascb->uldd_task = &tcs;
+       ascb->completion = &completion;
+       scb = ascb->scb;
        scb->header.opcode = SCB_ABORT_TASK;
 
        switch (task->task_proto) {
@@ -406,13 +470,12 @@ int asd_abort_task(struct sas_task *task)
        res = asd_enqueue_internal(ascb, asd_tmf_tasklet_complete,
                                   asd_tmf_timedout);
        if (res)
-               goto out;
-       wait_for_completion(&ascb->completion);
+               goto out_free;
+       wait_for_completion(&completion);
        ASD_DPRINTK("tmf came back\n");
 
-       res = (int) (unsigned long) ascb->uldd_task;
-       tascb->tag = ascb->tag;
-       tascb->tag_valid = ascb->tag_valid;
+       tascb->tag = tcs.tag;
+       tascb->tag_valid = tcs.tag_valid;
 
        spin_lock_irqsave(&task->task_state_lock, flags);
        if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -423,63 +486,68 @@ int asd_abort_task(struct sas_task *task)
        }
        spin_unlock_irqrestore(&task->task_state_lock, flags);
 
-       switch (res) {
-       /* The task to be aborted has been sent to the device.
-        * We got a Response IU for the ABORT TASK TMF. */
-       case TC_NO_ERROR + 0xFF00:
-       case TMF_RESP_FUNC_COMPLETE:
-       case TMF_RESP_FUNC_FAILED:
-               res = asd_clear_nexus(task);
-               break;
-       case TMF_RESP_INVALID_FRAME:
-       case TMF_RESP_OVERLAPPED_TAG:
-       case TMF_RESP_FUNC_ESUPP:
-       case TMF_RESP_NO_LUN:
-               goto out_done; break;
-       }
-       /* In the following we assume that the managing layer
-        * will _never_ make a mistake, when issuing ABORT TASK.
-        */
-       switch (res) {
-       default:
-               res = asd_clear_nexus(task);
-               /* fallthrough */
-       case TC_NO_ERROR + 0xFF00:
-       case TMF_RESP_FUNC_COMPLETE:
-               break;
-       /* The task hasn't been sent to the device xor we never got
-        * a (sane) Response IU for the ABORT TASK TMF.
-        */
-       case TF_NAK_RECV + 0xFF00:
-               res = TMF_RESP_INVALID_FRAME;
-               break;
-       case TF_TMF_TASK_DONE + 0xFF00: /* done but not reported yet */
+       if (tcs.dl_opcode == TC_SSP_RESP) {
+               /* The task to be aborted has been sent to the device.
+                * We got a Response IU for the ABORT TASK TMF. */
+               if (tcs.tmf_state == TMF_RESP_FUNC_COMPLETE)
+                       res = asd_clear_nexus(task);
+               else
+                       res = tcs.tmf_state;
+       } else if (tcs.dl_opcode == TC_NO_ERROR &&
+                  tcs.tmf_state == TMF_RESP_FUNC_FAILED) {
+               /* timeout */
                res = TMF_RESP_FUNC_FAILED;
-               leftover = wait_for_completion_timeout(&tascb->completion,
-                                                      AIC94XX_SCB_TIMEOUT);
-               spin_lock_irqsave(&task->task_state_lock, flags);
-               if (leftover < 1)
+       } else {
+               /* In the following we assume that the managing layer
+                * will _never_ make a mistake, when issuing ABORT
+                * TASK.
+                */
+               switch (tcs.dl_opcode) {
+               default:
+                       res = asd_clear_nexus(task);
+                       /* fallthrough */
+               case TC_NO_ERROR:
+                       break;
+                       /* The task hasn't been sent to the device xor
+                        * we never got a (sane) Response IU for the
+                        * ABORT TASK TMF.
+                        */
+               case TF_NAK_RECV:
+                       res = TMF_RESP_INVALID_FRAME;
+                       break;
+               case TF_TMF_TASK_DONE:  /* done but not reported yet */
                        res = TMF_RESP_FUNC_FAILED;
-               if (task->task_state_flags & SAS_TASK_STATE_DONE)
+                       leftover =
+                               wait_for_completion_timeout(&tascb_completion,
+                                                         AIC94XX_SCB_TIMEOUT);
+                       spin_lock_irqsave(&task->task_state_lock, flags);
+                       if (leftover < 1)
+                               res = TMF_RESP_FUNC_FAILED;
+                       if (task->task_state_flags & SAS_TASK_STATE_DONE)
+                               res = TMF_RESP_FUNC_COMPLETE;
+                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+                       break;
+               case TF_TMF_NO_TAG:
+               case TF_TMF_TAG_FREE: /* the tag is in the free list */
+               case TF_TMF_NO_CONN_HANDLE: /* no such device */
                        res = TMF_RESP_FUNC_COMPLETE;
-               spin_unlock_irqrestore(&task->task_state_lock, flags);
-               goto out_done;
-       case TF_TMF_NO_TAG + 0xFF00:
-       case TF_TMF_TAG_FREE + 0xFF00: /* the tag is in the free list */
-       case TF_TMF_NO_CONN_HANDLE + 0xFF00: /* no such device */
-               res = TMF_RESP_FUNC_COMPLETE;
-               goto out_done;
-       case TF_TMF_NO_CTX + 0xFF00: /* not in seq, or proto != SSP */
-               res = TMF_RESP_FUNC_ESUPP;
-               goto out;
+                       break;
+               case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */
+                       res = TMF_RESP_FUNC_ESUPP;
+                       break;
+               }
        }
-out_done:
+ out_done:
+       tascb->completion = NULL;
        if (res == TMF_RESP_FUNC_COMPLETE) {
                task->lldd_task = NULL;
                mb();
                asd_ascb_free(tascb);
        }
-out:
+       ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);
+       return res;
+
+ out_free:
        asd_ascb_free(ascb);
        ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);
        return res;
@@ -507,6 +575,8 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
        struct asd_ascb *ascb;
        int res = 1;
        struct scb *scb;
+       DECLARE_COMPLETION_ONSTACK(completion);
+       DECLARE_TCS(tcs);
 
        if (!(dev->tproto & SAS_PROTOCOL_SSP))
                return TMF_RESP_FUNC_ESUPP;
@@ -514,6 +584,9 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
        ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
        if (!ascb)
                return -ENOMEM;
+
+       ascb->completion = &completion;
+       ascb->uldd_task = &tcs;
        scb = ascb->scb;
 
        if (tmf == TMF_QUERY_TASK)
@@ -546,31 +619,32 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
                                   asd_tmf_timedout);
        if (res)
                goto out_err;
-       wait_for_completion(&ascb->completion);
-       res = (int) (unsigned long) ascb->uldd_task;
+       wait_for_completion(&completion);
 
-       switch (res) {
-       case TC_NO_ERROR + 0xFF00:
+       switch (tcs.dl_opcode) {
+       case TC_NO_ERROR:
                res = TMF_RESP_FUNC_COMPLETE;
                break;
-       case TF_NAK_RECV + 0xFF00:
+       case TF_NAK_RECV:
                res = TMF_RESP_INVALID_FRAME;
                break;
-       case TF_TMF_TASK_DONE + 0xFF00:
+       case TF_TMF_TASK_DONE:
                res = TMF_RESP_FUNC_FAILED;
                break;
-       case TF_TMF_NO_TAG + 0xFF00:
-       case TF_TMF_TAG_FREE + 0xFF00: /* the tag is in the free list */
-       case TF_TMF_NO_CONN_HANDLE + 0xFF00: /* no such device */
+       case TF_TMF_NO_TAG:
+       case TF_TMF_TAG_FREE: /* the tag is in the free list */
+       case TF_TMF_NO_CONN_HANDLE: /* no such device */
                res = TMF_RESP_FUNC_COMPLETE;
                break;
-       case TF_TMF_NO_CTX + 0xFF00: /* not in seq, or proto != SSP */
+       case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */
                res = TMF_RESP_FUNC_ESUPP;
                break;
        default:
                /* Allow TMF response codes to propagate upwards */
+               res = tcs.dl_opcode;
                break;
        }
+       return res;
 out_err:
        asd_ascb_free(ascb);
        return res;
index 57786502e3ec18df7f47815b549a2e0152791110..0393707bdfce2a56ade99f0e5e2938a15ae84d78 100644 (file)
@@ -48,7 +48,7 @@ struct class_device_attribute;
 /*The limit of outstanding scsi command that firmware can handle*/
 #define ARCMSR_MAX_OUTSTANDING_CMD                                             256
 #define ARCMSR_MAX_FREECCB_NUM                                                 320
-#define ARCMSR_DRIVER_VERSION               "Driver Version 1.20.00.15 2007/12/24"
+#define ARCMSR_DRIVER_VERSION               "Driver Version 1.20.00.15 2008/02/27"
 #define ARCMSR_SCSI_INITIATOR_ID                                               255
 #define ARCMSR_MAX_XFER_SECTORS                                                        512
 #define ARCMSR_MAX_XFER_SECTORS_B                                              4096
index 6d67f5c0eb8e4133621898d7f5f07f18920592a5..27ebd336409b6fbd922c17360438a7c0ec79babe 100644 (file)
@@ -160,7 +160,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
 static void gdth_clear_events(void);
 
 static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
-                                    char *buffer, ushort count, int to_buffer);
+                                    char *buffer, ushort count);
 static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
 static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive);
 
@@ -182,7 +182,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
                       unsigned int cmd, unsigned long arg);
 
 static void gdth_flush(gdth_ha_str *ha);
-static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
 static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
 static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
                                struct gdth_cmndinfo *cmndinfo);
@@ -417,12 +416,6 @@ static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
 #include "gdth_proc.h"
 #include "gdth_proc.c"
 
-/* notifier block to get a notify on system shutdown/halt/reboot */
-static struct notifier_block gdth_notifier = {
-    gdth_halt, NULL, 0
-};
-static int notifier_disabled = 0;
-
 static gdth_ha_str *gdth_find_ha(int hanum)
 {
        gdth_ha_str *ha;
@@ -445,8 +438,8 @@ static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha)
        for (i=0; i<GDTH_MAXCMDS; ++i) {
                if (ha->cmndinfo[i].index == 0) {
                        priv = &ha->cmndinfo[i];
-                       priv->index = i+1;
                        memset(priv, 0, sizeof(*priv));
+                       priv->index = i+1;
                        break;
                }
        }
@@ -493,7 +486,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     gdth_ha_str *ha = shost_priv(sdev->host);
     Scsi_Cmnd *scp;
     struct gdth_cmndinfo cmndinfo;
-    struct scatterlist one_sg;
     DECLARE_COMPLETION_ONSTACK(wait);
     int rval;
 
@@ -507,13 +499,10 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     /* use request field to save the ptr. to completion struct. */
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
-    sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd));
-    gdth_set_sglist(scp, &one_sg);
-    gdth_set_sg_count(scp, 1);
-    gdth_set_bufflen(scp, sizeof(*gdtcmd));
     scp->cmd_len = 12;
     memcpy(scp->cmnd, cmnd, 12);
     cmndinfo.priority = IOCTL_PRI;
+    cmndinfo.internal_cmd_str = gdtcmd;
     cmndinfo.internal_command = 1;
 
     TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
@@ -2355,7 +2344,7 @@ static void gdth_next(gdth_ha_str *ha)
  * buffers, kmap_atomic() as needed.
  */
 static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
-                                    char *buffer, ushort count, int to_buffer)
+                                    char *buffer, ushort count)
 {
     ushort cpcount,i, max_sg = gdth_sg_count(scp);
     ushort cpsum,cpnow;
@@ -2381,10 +2370,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
             }
             local_irq_save(flags);
             address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset;
-            if (to_buffer)
-                memcpy(buffer, address, cpnow);
-            else
-                memcpy(address, buffer, cpnow);
+            memcpy(address, buffer, cpnow);
             flush_dcache_page(sg_page(sl));
             kunmap_atomic(address, KM_BIO_SRC_IRQ);
             local_irq_restore(flags);
@@ -2438,7 +2424,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
         strcpy(inq.vendor,ha->oem_name);
         sprintf(inq.product,"Host Drive  #%02d",t);
         strcpy(inq.revision,"   ");
-        gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0);
+        gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data));
         break;
 
       case REQUEST_SENSE:
@@ -2448,7 +2434,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
         sd.key       = NO_SENSE;
         sd.info      = 0;
         sd.add_length= 0;
-        gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0);
+        gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data));
         break;
 
       case MODE_SENSE:
@@ -2460,7 +2446,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
         mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
-        gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0);
+        gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data));
         break;
 
       case READ_CAPACITY:
@@ -2470,7 +2456,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
         else
             rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
         rdc.block_length  = cpu_to_be32(SECTOR_SIZE);
-        gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0);
+        gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data));
         break;
 
       case SERVICE_ACTION_IN:
@@ -2482,7 +2468,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
             rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
             rdc16.block_length  = cpu_to_be32(SECTOR_SIZE);
             gdth_copy_internal_data(ha, scp, (char*)&rdc16,
-                                                 sizeof(gdth_rdcap16_data), 0);
+                                                 sizeof(gdth_rdcap16_data));
         } else { 
             scp->result = DID_ABORT << 16;
         }
@@ -2852,6 +2838,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
 static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
 {
     register gdth_cmd_str *cmdp;
+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
     int cmd_index;
 
     cmdp= ha->pccb;
@@ -2860,7 +2847,7 @@ static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 0;
 
-    gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1);
+    *cmdp = *cmndinfo->internal_cmd_str;
     cmdp->RequestBuffer = scp;
 
     /* search free command index */
@@ -3794,6 +3781,8 @@ static void gdth_timeout(ulong data)
     gdth_ha_str *ha;
     ulong flags;
 
+    BUG_ON(list_empty(&gdth_instances));
+
     ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
@@ -4669,45 +4658,6 @@ static void gdth_flush(gdth_ha_str *ha)
     }
 }
 
-/* shutdown routine */
-static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
-{
-    gdth_ha_str *ha;
-#ifndef __alpha__
-    gdth_cmd_str    gdtcmd;
-    char            cmnd[MAX_COMMAND_SIZE];   
-#endif
-
-    if (notifier_disabled)
-        return NOTIFY_OK;
-
-    TRACE2(("gdth_halt() event %d\n",(int)event));
-    if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
-        return NOTIFY_DONE;
-
-    notifier_disabled = 1;
-    printk("GDT-HA: Flushing all host drives .. ");
-    list_for_each_entry(ha, &gdth_instances, list) {
-        gdth_flush(ha);
-
-#ifndef __alpha__
-        /* controller reset */
-        memset(cmnd, 0xff, MAX_COMMAND_SIZE);
-        gdtcmd.BoardNode = LOCALBOARD;
-        gdtcmd.Service = CACHESERVICE;
-        gdtcmd.OpCode = GDT_RESET;
-        TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum));
-        gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL);
-#endif
-    }
-    printk("Done.\n");
-
-#ifdef GDTH_STATISTICS
-    del_timer(&gdth_timer);
-#endif
-    return NOTIFY_OK;
-}
-
 /* configure lun */
 static int gdth_slave_configure(struct scsi_device *sdev)
 {
@@ -5142,13 +5092,13 @@ static void gdth_remove_one(gdth_ha_str *ha)
 
        scsi_remove_host(shp);
 
+       gdth_flush(ha);
+
        if (ha->sdev) {
                scsi_free_host_dev(ha->sdev);
                ha->sdev = NULL;
        }
 
-       gdth_flush(ha);
-
        if (shp->irq)
                free_irq(shp->irq,ha);
 
@@ -5174,6 +5124,24 @@ static void gdth_remove_one(gdth_ha_str *ha)
        scsi_host_put(shp);
 }
 
+static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
+{
+       gdth_ha_str *ha;
+
+       TRACE2(("gdth_halt() event %d\n", (int)event));
+       if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
+               return NOTIFY_DONE;
+
+       list_for_each_entry(ha, &gdth_instances, list)
+               gdth_flush(ha);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block gdth_notifier = {
+    gdth_halt, NULL, 0
+};
+
 static int __init gdth_init(void)
 {
        if (disable) {
@@ -5236,7 +5204,6 @@ static int __init gdth_init(void)
        add_timer(&gdth_timer);
 #endif
        major = register_chrdev(0,"gdth", &gdth_fops);
-       notifier_disabled = 0;
        register_reboot_notifier(&gdth_notifier);
        gdth_polling = FALSE;
        return 0;
@@ -5246,14 +5213,15 @@ static void __exit gdth_exit(void)
 {
        gdth_ha_str *ha;
 
-       list_for_each_entry(ha, &gdth_instances, list)
-               gdth_remove_one(ha);
+       unregister_chrdev(major, "gdth");
+       unregister_reboot_notifier(&gdth_notifier);
 
 #ifdef GDTH_STATISTICS
-       del_timer(&gdth_timer);
+       del_timer_sync(&gdth_timer);
 #endif
-       unregister_chrdev(major,"gdth");
-       unregister_reboot_notifier(&gdth_notifier);
+
+       list_for_each_entry(ha, &gdth_instances, list)
+               gdth_remove_one(ha);
 }
 
 module_init(gdth_init);
index 1434c6b0297c6977f17c73166ddcd6b9c48bb7ed..26e4e92515e0cfcc0793f9b01b15e1e669acbfe2 100644 (file)
@@ -915,6 +915,7 @@ typedef struct {
     struct gdth_cmndinfo {                      /* per-command private info */
         int index;
         int internal_command;                   /* don't call scsi_done */
+        gdth_cmd_str *internal_cmd_str;         /* crier for internal messages*/
         dma_addr_t sense_paddr;                 /* sense dma-addr */
         unchar priority;
         int timeout;
index bd62131b97a1d431eef230ab0efd9ed487a7234f..e5881e92d0fb29f730d93f79b8c554e629a72dfa 100644 (file)
@@ -290,7 +290,7 @@ static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
        int err = 0;
 
        dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0],
-               cmd->usg_sg);
+               scsi_sg_count(sc));
 
        if (scsi_sg_count(sc))
                err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
@@ -838,9 +838,6 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        if (!shost)
                goto free_vport;
        shost->transportt = ibmvstgt_transport_template;
-       err = scsi_tgt_alloc_queue(shost);
-       if (err)
-               goto put_host;
 
        target = host_to_srp_target(shost);
        target->shost = shost;
@@ -872,6 +869,10 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
        if (err)
                goto destroy_queue;
 
+       err = scsi_tgt_alloc_queue(shost);
+       if (err)
+               goto destroy_queue;
+
        return 0;
 destroy_queue:
        crq_queue_destroy(target);
index 59f8445eab0daa7a5b138c278897da53aa4ca351..bdd7de7da39a5819cea137dcb5b083f6f69a8d3c 100644 (file)
@@ -1708,8 +1708,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
                qdepth = ISCSI_DEF_CMD_PER_LUN;
        }
 
-       if (!is_power_of_2(cmds_max) ||
-           cmds_max >= ISCSI_MGMT_ITT_OFFSET) {
+       if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET ||
+           cmds_max < 2) {
                if (cmds_max != 0)
                        printk(KERN_ERR "iscsi: invalid can_queue of %d. "
                               "can_queue must be a power of 2 and between "
index 7cd05b599a12ca68348ccd721963e4afb7becede..b0e5ac372a3223453b3e4fbfecc737d21fad2977 100644 (file)
@@ -236,12 +236,12 @@ static void sas_ata_phy_reset(struct ata_port *ap)
        struct domain_device *dev = ap->private_data;
        struct sas_internal *i =
                to_sas_internal(dev->port->ha->core.shost->transportt);
-       int res = 0;
+       int res = TMF_RESP_FUNC_FAILED;
 
        if (i->dft->lldd_I_T_nexus_reset)
                res = i->dft->lldd_I_T_nexus_reset(dev);
 
-       if (res)
+       if (res != TMF_RESP_FUNC_COMPLETE)
                SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__);
 
        switch (dev->sata_dev.command_set) {
@@ -656,21 +656,6 @@ out:
        return res;
 }
 
-static void sas_sata_propagate_sas_addr(struct domain_device *dev)
-{
-       unsigned long flags;
-       struct asd_sas_port *port = dev->port;
-       struct asd_sas_phy  *phy;
-
-       BUG_ON(dev->parent);
-
-       memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE);
-       spin_lock_irqsave(&port->phy_list_lock, flags);
-       list_for_each_entry(phy, &port->phy_list, port_phy_el)
-               memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE);
-       spin_unlock_irqrestore(&port->phy_list_lock, flags);
-}
-
 #define ATA_IDENTIFY_DEV         0xEC
 #define ATA_IDENTIFY_PACKET_DEV  0xA1
 #define ATA_SET_FEATURES         0xEF
@@ -728,26 +713,6 @@ static int sas_discover_sata_dev(struct domain_device *dev)
                        goto out_err;
        }
 cont1:
-       /* Get WWN */
-       if (dev->port->oob_mode != SATA_OOB_MODE) {
-               memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr,
-                      SAS_ADDR_SIZE);
-       } else if (dev->sata_dev.command_set == ATA_COMMAND_SET &&
-                  (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000)
-                  == 0x5000) {
-               int i;
-
-               for (i = 0; i < 4; i++) {
-                       dev->sas_addr[2*i] =
-            (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8;
-                       dev->sas_addr[2*i+1] =
-             le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF;
-               }
-       }
-       sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
-       if (!dev->parent)
-               sas_sata_propagate_sas_addr(dev);
-
        /* XXX Hint: register this SATA device with SATL.
           When this returns, dev->sata_dev->lu is alive and
           present.
index e1e2d085c920918dc508d4ec8d67dfad98095450..39ae68a3b0ef57a14eefcff9112e9668deb6fe1f 100644 (file)
@@ -92,9 +92,6 @@ static void sas_form_port(struct asd_sas_phy *phy)
        if (!port->phy)
                port->phy = phy->phy;
 
-       SAS_DPRINTK("phy%d added to port%d, phy_mask:0x%x\n", phy->id,
-                   port->id, port->phy_mask);
-
        if (*(u64 *)port->attached_sas_addr == 0) {
                port->class = phy->class;
                memcpy(port->attached_sas_addr, phy->attached_sas_addr,
@@ -115,6 +112,11 @@ static void sas_form_port(struct asd_sas_phy *phy)
        }
        sas_port_add_phy(port->port, phy->phy);
 
+       SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n",
+                   phy->phy->dev.bus_id,port->port->dev.bus_id,
+                   port->phy_mask,
+                   SAS_ADDR(port->attached_sas_addr));
+
        if (port->port_dev)
                port->port_dev->pathways = port->num_phys;
 
@@ -255,12 +257,11 @@ void sas_porte_hard_reset(struct work_struct *work)
 static void sas_init_port(struct asd_sas_port *port,
                          struct sas_ha_struct *sas_ha, int i)
 {
+       memset(port, 0, sizeof(*port));
        port->id = i;
        INIT_LIST_HEAD(&port->dev_list);
        spin_lock_init(&port->phy_list_lock);
        INIT_LIST_HEAD(&port->phy_list);
-       port->num_phys = 0;
-       port->phy_mask = 0;
        port->ha = sas_ha;
 
        spin_lock_init(&port->dev_list_lock);
index 704ea06a6e500a8d3bfd25179dc9efa73791c655..1f8241563c6ccea625640eb69c22554d931f3d87 100644 (file)
@@ -434,7 +434,7 @@ static int sas_recover_I_T(struct domain_device *dev)
 }
 
 /* Find the sas_phy that's attached to this device */
-static struct sas_phy *find_local_sas_phy(struct domain_device *dev)
+struct sas_phy *sas_find_local_phy(struct domain_device *dev)
 {
        struct domain_device *pdev = dev->parent;
        struct ex_phy *exphy = NULL;
@@ -456,6 +456,7 @@ static struct sas_phy *find_local_sas_phy(struct domain_device *dev)
        BUG_ON(!exphy);
        return exphy->phy;
 }
+EXPORT_SYMBOL_GPL(sas_find_local_phy);
 
 /* Attempt to send a LUN reset message to a device */
 int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
@@ -482,7 +483,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd)
 int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
 {
        struct domain_device *dev = cmd_to_domain_dev(cmd);
-       struct sas_phy *phy = find_local_sas_phy(dev);
+       struct sas_phy *phy = sas_find_local_phy(dev);
        int res;
 
        res = sas_phy_reset(phy, 1);
@@ -497,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd)
 }
 
 /* Try to reset a device */
-static int try_to_reset_cmd_device(struct Scsi_Host *shost,
-                                  struct scsi_cmnd *cmd)
+static int try_to_reset_cmd_device(struct scsi_cmnd *cmd)
 {
        int res;
+       struct Scsi_Host *shost = cmd->device->host;
 
        if (!shost->hostt->eh_device_reset_handler)
                goto try_bus_reset;
@@ -540,6 +541,12 @@ Again:
                need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET;
                spin_unlock_irqrestore(&task->task_state_lock, flags);
 
+               if (need_reset) {
+                       SAS_DPRINTK("%s: task 0x%p requests reset\n",
+                                   __FUNCTION__, task);
+                       goto reset;
+               }
+
                SAS_DPRINTK("trying to find task 0x%p\n", task);
                res = sas_scsi_find_task(task);
 
@@ -550,18 +557,15 @@ Again:
                        SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__,
                                    task);
                        sas_eh_finish_cmd(cmd);
-                       if (need_reset)
-                               try_to_reset_cmd_device(shost, cmd);
                        continue;
                case TASK_IS_ABORTED:
                        SAS_DPRINTK("%s: task 0x%p is aborted\n",
                                    __FUNCTION__, task);
                        sas_eh_finish_cmd(cmd);
-                       if (need_reset)
-                               try_to_reset_cmd_device(shost, cmd);
                        continue;
                case TASK_IS_AT_LU:
                        SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
+ reset:
                        tmf_resp = sas_recover_lu(task->dev, cmd);
                        if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
                                SAS_DPRINTK("dev %016llx LU %x is "
@@ -569,8 +573,6 @@ Again:
                                            SAS_ADDR(task->dev),
                                            cmd->device->lun);
                                sas_eh_finish_cmd(cmd);
-                               if (need_reset)
-                                       try_to_reset_cmd_device(shost, cmd);
                                sas_scsi_clear_queue_lu(work_q, cmd);
                                goto Again;
                        }
@@ -581,15 +583,15 @@ Again:
                                    task);
                        tmf_resp = sas_recover_I_T(task->dev);
                        if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
+                               struct domain_device *dev = task->dev;
                                SAS_DPRINTK("I_T %016llx recovered\n",
                                            SAS_ADDR(task->dev->sas_addr));
                                sas_eh_finish_cmd(cmd);
-                               if (need_reset)
-                                       try_to_reset_cmd_device(shost, cmd);
-                               sas_scsi_clear_queue_I_T(work_q, task->dev);
+                               sas_scsi_clear_queue_I_T(work_q, dev);
                                goto Again;
                        }
                        /* Hammer time :-) */
+                       try_to_reset_cmd_device(cmd);
                        if (i->dft->lldd_clear_nexus_port) {
                                struct asd_sas_port *port = task->dev->port;
                                SAS_DPRINTK("clearing nexus for port:%d\n",
@@ -599,8 +601,6 @@ Again:
                                        SAS_DPRINTK("clear nexus port:%d "
                                                    "succeeded\n", port->id);
                                        sas_eh_finish_cmd(cmd);
-                                       if (need_reset)
-                                               try_to_reset_cmd_device(shost, cmd);
                                        sas_scsi_clear_queue_port(work_q,
                                                                  port);
                                        goto Again;
@@ -613,8 +613,6 @@ Again:
                                        SAS_DPRINTK("clear nexus ha "
                                                    "succeeded\n");
                                        sas_eh_finish_cmd(cmd);
-                                       if (need_reset)
-                                               try_to_reset_cmd_device(shost, cmd);
                                        goto clear_q;
                                }
                        }
@@ -628,8 +626,6 @@ Again:
                                    cmd->device->lun);
 
                        sas_eh_finish_cmd(cmd);
-                       if (need_reset)
-                               try_to_reset_cmd_device(shost, cmd);
                        goto clear_q;
                }
        }
index d4a6ac3c9c4746155eca706225995344ff265e52..5ec0665b3a3dd875e9e555def0bd4d2977f4a782 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "mvsas"
-#define DRV_VERSION    "0.5"
+#define DRV_VERSION    "0.5.1"
 #define _MV_DUMP 0
 #define MVS_DISABLE_NVRAM
 #define MVS_DISABLE_MSI
@@ -1005,7 +1005,7 @@ err_out:
        return rc;
 #else
        /* FIXME , For SAS target mode */
-       memcpy(buf, "\x00\x00\xab\x11\x30\x04\x05\x50", 8);
+       memcpy(buf, "\x50\x05\x04\x30\x11\xab\x00\x00", 8);
        return 0;
 #endif
 }
@@ -1330,7 +1330,7 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
 
                mvs_hba_cq_dump(mvi);
 
-               if (unlikely(rx_desc & RXQ_DONE))
+               if (likely(rx_desc & RXQ_DONE))
                        mvs_slot_complete(mvi, rx_desc);
                if (rx_desc & RXQ_ATTN) {
                        attn = true;
@@ -2720,9 +2720,8 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi)
        msleep(100);
        /* init and reset phys */
        for (i = 0; i < mvi->chip->n_phy; i++) {
-               /* FIXME: is this the correct dword order? */
-               u32 lo = *((u32 *)&mvi->sas_addr[0]);
-               u32 hi = *((u32 *)&mvi->sas_addr[4]);
+               u32 lo = be32_to_cpu(*(u32 *)&mvi->sas_addr[4]);
+               u32 hi = be32_to_cpu(*(u32 *)&mvi->sas_addr[0]);
 
                mvs_detect_porttype(mvi, i);
 
index 0cd614a0fa73d98eb354aee000c1c4f1909de050..fad6cb5cba283acc8410e9d8bed1e996062d03b8 100644 (file)
@@ -124,7 +124,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
                }
                req_len += sgpnt->length;
        }
-       scsi_set_resid(cmd, req_len - act_len);
+       scsi_set_resid(cmd, buflen - act_len);
        return 0;
 }
 
@@ -427,7 +427,7 @@ static struct scsi_host_template ps3rom_host_template = {
        .cmd_per_lun =          1,
        .emulated =             1,              /* only sg driver uses this */
        .max_sectors =          PS3ROM_MAX_SECTORS,
-       .use_clustering =       ENABLE_CLUSTERING,
+       .use_clustering =       DISABLE_CLUSTERING,
        .module =               THIS_MODULE,
 };
 
index 6226d88479f59fa2a1ded8423180281a98393ab0..c1808763d40ef21608e6dab7fab271712098f975 100644 (file)
@@ -39,7 +39,7 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
        ms_pkt->entry_count = 1;
        SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER);
        ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
-       ms_pkt->timeout = __constant_cpu_to_le16(25);
+       ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
        ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
        ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
@@ -75,7 +75,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size)
        ct_pkt->entry_type = CT_IOCB_TYPE;
        ct_pkt->entry_count = 1;
        ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS);
-       ct_pkt->timeout = __constant_cpu_to_le16(25);
+       ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
@@ -1144,7 +1144,7 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
        ms_pkt->entry_count = 1;
        SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id);
        ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG);
-       ms_pkt->timeout = __constant_cpu_to_le16(59);
+       ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
        ms_pkt->total_dsd_count = __constant_cpu_to_le16(2);
        ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
@@ -1181,7 +1181,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size,
        ct_pkt->entry_type = CT_IOCB_TYPE;
        ct_pkt->entry_count = 1;
        ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
-       ct_pkt->timeout = __constant_cpu_to_le16(59);
+       ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
@@ -1761,7 +1761,7 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size,
        ct_pkt->entry_type = CT_IOCB_TYPE;
        ct_pkt->entry_count = 1;
        ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id);
-       ct_pkt->timeout = __constant_cpu_to_le16(59);
+       ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1);
        ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
index d5c7853e7ebab34e0b621d98dbb6f36de823ca06..364be7d068759c4972cc7fd414cc26c63c396323 100644 (file)
@@ -1733,8 +1733,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
        ha->login_timeout = nv->login_timeout;
        icb->login_timeout = nv->login_timeout;
 
-       /* Set minimum RATOV to 200 tenths of a second. */
-       ha->r_a_tov = 200;
+       /* Set minimum RATOV to 100 tenths of a second. */
+       ha->r_a_tov = 100;
 
        ha->loop_reset_delay = nv->reset_delay;
 
@@ -3645,8 +3645,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
        ha->login_timeout = le16_to_cpu(nv->login_timeout);
        icb->login_timeout = cpu_to_le16(nv->login_timeout);
 
-       /* Set minimum RATOV to 200 tenths of a second. */
-       ha->r_a_tov = 200;
+       /* Set minimum RATOV to 100 tenths of a second. */
+       ha->r_a_tov = 100;
 
        ha->loop_reset_delay = nv->reset_delay;
 
@@ -4022,7 +4022,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
                return;
 
        ret = qla2x00_stop_firmware(ha);
-       for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) {
+       for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
+           retries ; retries--) {
                qla2x00_reset_chip(ha);
                if (qla2x00_chip_diag(ha) != QLA_SUCCESS)
                        continue;
index 14e6f22944b71886be2ba17094a406e2f49b2f7c..f0337036c7bb144242567963591c368999deecbd 100644 (file)
@@ -958,6 +958,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
                }
        }
 
+       /* Check for overrun. */
+       if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE &&
+           scsi_status & SS_RESIDUAL_OVER)
+               comp_status = CS_DATA_OVERRUN;
+
        /*
         * Based on Host and scsi status generate status code for Linux
         */
index 99d29fff836d631bc37686b6c45bee7972dcb4e4..bb103580e1ba8b874e59bb8987c2b5addad940cb 100644 (file)
@@ -2206,7 +2206,7 @@ qla24xx_abort_target(fc_port_t *fcport)
        tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
        tsk->p.tsk.entry_count = 1;
        tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
-       tsk->p.tsk.timeout = __constant_cpu_to_le16(25);
+       tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
        tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET);
        tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
        tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
index c5742cc15abbbc56b1134619d09714e400d1a33d..ea08a129fee91827b4c3b285f78c8ae171782cdf 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.02.00-k8"
+#define QLA2XXX_VERSION      "8.02.00-k9"
 
 #define QLA_DRIVER_MAJOR_VER   8
 #define QLA_DRIVER_MINOR_VER   2
index 10b3b9a620f357f0bcf91a39546a9b594451f149..109c5f5985ecfb1772956296a27ea219ee7a01ff 100644 (file)
@@ -1299,9 +1299,9 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
        ddb_entry->fw_ddb_device_state = state;
        /* Device is back online. */
        if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+               atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
                atomic_set(&ddb_entry->port_down_timer,
                           ha->port_down_retry_count);
-               atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
                atomic_set(&ddb_entry->relogin_retry_count, 0);
                atomic_set(&ddb_entry->relogin_timer, 0);
                clear_bit(DF_RELOGIN, &ddb_entry->flags);
index c3c59d7630371781b25a7bf46fed47d02f37edb6..8b92f348f02c73ad8e139be5ede91843d31afc47 100644 (file)
@@ -75,6 +75,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_slave_alloc(struct scsi_device *device);
 static int qla4xxx_slave_configure(struct scsi_device *device);
 static void qla4xxx_slave_destroy(struct scsi_device *sdev);
+static void qla4xxx_scan_start(struct Scsi_Host *shost);
 
 static struct scsi_host_template qla4xxx_driver_template = {
        .module                 = THIS_MODULE,
@@ -90,6 +91,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .slave_destroy          = qla4xxx_slave_destroy,
 
        .scan_finished          = iscsi_scan_finished,
+       .scan_start             = qla4xxx_scan_start,
 
        .this_id                = -1,
        .cmd_per_lun            = 3,
@@ -299,6 +301,18 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha)
        return ddb_entry;
 }
 
+static void qla4xxx_scan_start(struct Scsi_Host *shost)
+{
+       struct scsi_qla_host *ha = shost_priv(shost);
+       struct ddb_entry *ddb_entry, *ddbtemp;
+
+       /* finish setup of sessions that were already setup in firmware */
+       list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
+               if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
+                       qla4xxx_add_sess(ddb_entry);
+       }
+}
+
 /*
  * Timer routines
  */
@@ -864,8 +878,9 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha)
  * qla4xxx_recover_adapter - recovers adapter after a fatal error
  * @ha: Pointer to host adapter structure.
  * @renew_ddb_list: Indicates what to do with the adapter's ddb list
- *     after adapter recovery has completed.
- *     0=preserve ddb list, 1=destroy and rebuild ddb list
+ *
+ * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild
+ * ddb list.
  **/
 static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
                                uint8_t renew_ddb_list)
@@ -874,6 +889,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
 
        /* Stall incoming I/O until we are done */
        clear_bit(AF_ONLINE, &ha->flags);
+
        DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no,
                      __func__));
 
@@ -1176,7 +1192,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
        int ret = -ENODEV, status;
        struct Scsi_Host *host;
        struct scsi_qla_host *ha;
-       struct ddb_entry *ddb_entry, *ddbtemp;
        uint8_t init_retry_count = 0;
        char buf[34];
 
@@ -1295,13 +1310,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
        if (ret)
                goto probe_failed;
 
-       /* Update transport device information for all devices. */
-       list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) {
-               if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE)
-                       if (qla4xxx_add_sess(ddb_entry))
-                               goto remove_host;
-       }
-
        printk(KERN_INFO
               " QLogic iSCSI HBA Driver version: %s\n"
               "  QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",
@@ -1311,10 +1319,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
        scsi_scan_host(host);
        return 0;
 
-remove_host:
-       qla4xxx_free_ddb_list(ha);
-       scsi_remove_host(host);
-
 probe_failed:
        qla4xxx_free_adapter(ha);
        scsi_host_put(ha->host);
@@ -1600,9 +1604,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
                return FAILED;
        }
 
-       if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) {
+       /* make sure the dpc thread is stopped while we reset the hba */
+       clear_bit(AF_ONLINE, &ha->flags);
+       flush_workqueue(ha->dpc_thread);
+
+       if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS)
                return_status = SUCCESS;
-       }
 
        dev_info(&ha->pdev->dev, "HOST RESET %s.\n",
                   return_status == FAILED ? "FAILED" : "SUCCEDED");
index 3677fbb30b720d50b6777a395125ba03ae1c492b..a0f308bd145b062e2403af9b57a2c32d92108ca0 100644 (file)
@@ -103,7 +103,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost,
        if (!cmd)
                goto release_rq;
 
-       memset(cmd, 0, sizeof(*cmd));
        cmd->sc_data_direction = data_dir;
        cmd->jiffies_at_alloc = jiffies;
        cmd->request = rq;
@@ -382,6 +381,11 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
                scsi_release_buffers(cmd);
                goto unmap_rq;
        }
+       /*
+        * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the
+        * length for us.
+        */
+       cmd->sdb.length = rq->data_len;
 
        return 0;
 
index 9981682d5302d5ea0bbbea58f181fb75458345f2..ca7bb6f63bdeb6bcee801e8588b5d339c47a6f57 100644 (file)
@@ -33,7 +33,7 @@
 #define ISCSI_SESSION_ATTRS 19
 #define ISCSI_CONN_ATTRS 13
 #define ISCSI_HOST_ATTRS 4
-#define ISCSI_TRANSPORT_VERSION "2.0-868"
+#define ISCSI_TRANSPORT_VERSION "2.0-869"
 
 struct iscsi_internal {
        int daemon_pid;
@@ -373,24 +373,25 @@ static void session_recovery_timedout(struct work_struct *work)
        scsi_target_unblock(&session->dev);
 }
 
-static void __iscsi_unblock_session(struct iscsi_cls_session *session)
-{
-       if (!cancel_delayed_work(&session->recovery_work))
-               flush_workqueue(iscsi_eh_timer_workq);
-       scsi_target_unblock(&session->dev);
-}
-
-void iscsi_unblock_session(struct iscsi_cls_session *session)
+static void __iscsi_unblock_session(struct work_struct *work)
 {
+       struct iscsi_cls_session *session =
+                       container_of(work, struct iscsi_cls_session,
+                                    unblock_work);
        struct Scsi_Host *shost = iscsi_session_to_shost(session);
        struct iscsi_host *ihost = shost->shost_data;
        unsigned long flags;
 
+       /*
+        * The recovery and unblock work get run from the same workqueue,
+        * so try to cancel it if it was going to run after this unblock.
+        */
+       cancel_delayed_work(&session->recovery_work);
        spin_lock_irqsave(&session->lock, flags);
        session->state = ISCSI_SESSION_LOGGED_IN;
        spin_unlock_irqrestore(&session->lock, flags);
-
-       __iscsi_unblock_session(session);
+       /* start IO */
+       scsi_target_unblock(&session->dev);
        /*
         * Only do kernel scanning if the driver is properly hooked into
         * the async scanning code (drivers like iscsi_tcp do login and
@@ -401,20 +402,43 @@ void iscsi_unblock_session(struct iscsi_cls_session *session)
                        atomic_inc(&ihost->nr_scans);
        }
 }
+
+/**
+ * iscsi_unblock_session - set a session as logged in and start IO.
+ * @session: iscsi session
+ *
+ * Mark a session as ready to accept IO.
+ */
+void iscsi_unblock_session(struct iscsi_cls_session *session)
+{
+       queue_work(iscsi_eh_timer_workq, &session->unblock_work);
+       /*
+        * make sure all the events have completed before tell the driver
+        * it is safe
+        */
+       flush_workqueue(iscsi_eh_timer_workq);
+}
 EXPORT_SYMBOL_GPL(iscsi_unblock_session);
 
-void iscsi_block_session(struct iscsi_cls_session *session)
+static void __iscsi_block_session(struct work_struct *work)
 {
+       struct iscsi_cls_session *session =
+                       container_of(work, struct iscsi_cls_session,
+                                    block_work);
        unsigned long flags;
 
        spin_lock_irqsave(&session->lock, flags);
        session->state = ISCSI_SESSION_FAILED;
        spin_unlock_irqrestore(&session->lock, flags);
-
        scsi_target_block(&session->dev);
        queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work,
                           session->recovery_tmo * HZ);
 }
+
+void iscsi_block_session(struct iscsi_cls_session *session)
+{
+       queue_work(iscsi_eh_timer_workq, &session->block_work);
+}
 EXPORT_SYMBOL_GPL(iscsi_block_session);
 
 static void __iscsi_unbind_session(struct work_struct *work)
@@ -463,6 +487,8 @@ iscsi_alloc_session(struct Scsi_Host *shost,
        INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
        INIT_LIST_HEAD(&session->host_list);
        INIT_LIST_HEAD(&session->sess_list);
+       INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
+       INIT_WORK(&session->block_work, __iscsi_block_session);
        INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
        INIT_WORK(&session->scan_work, iscsi_scan_session);
        spin_lock_init(&session->lock);
@@ -575,24 +601,25 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
        list_del(&session->sess_list);
        spin_unlock_irqrestore(&sesslock, flags);
 
+       /* make sure there are no blocks/unblocks queued */
+       flush_workqueue(iscsi_eh_timer_workq);
+       /* make sure the timedout callout is not running */
+       if (!cancel_delayed_work(&session->recovery_work))
+               flush_workqueue(iscsi_eh_timer_workq);
        /*
         * If we are blocked let commands flow again. The lld or iscsi
         * layer should set up the queuecommand to fail commands.
+        * We assume that LLD will not be calling block/unblock while
+        * removing the session.
         */
        spin_lock_irqsave(&session->lock, flags);
        session->state = ISCSI_SESSION_FREE;
        spin_unlock_irqrestore(&session->lock, flags);
-       __iscsi_unblock_session(session);
-       __iscsi_unbind_session(&session->unbind_work);
 
-       /* flush running scans */
+       scsi_target_unblock(&session->dev);
+       /* flush running scans then delete devices */
        flush_workqueue(ihost->scan_workq);
-       /*
-        * If the session dropped while removing devices then we need to make
-        * sure it is not blocked
-        */
-       if (!cancel_delayed_work(&session->recovery_work))
-               flush_workqueue(iscsi_eh_timer_workq);
+       __iscsi_unbind_session(&session->unbind_work);
 
        /* hw iscsi may not have removed all connections from session */
        err = device_for_each_child(&session->dev, NULL,
@@ -802,23 +829,16 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
 
 void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error)
 {
-       struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
        struct nlmsghdr *nlh;
        struct sk_buff  *skb;
        struct iscsi_uevent *ev;
        struct iscsi_internal *priv;
        int len = NLMSG_SPACE(sizeof(*ev));
-       unsigned long flags;
 
        priv = iscsi_if_transport_lookup(conn->transport);
        if (!priv)
                return;
 
-       spin_lock_irqsave(&session->lock, flags);
-       if (session->state == ISCSI_SESSION_LOGGED_IN)
-               session->state = ISCSI_SESSION_FAILED;
-       spin_unlock_irqrestore(&session->lock, flags);
-
        skb = alloc_skb(len, GFP_ATOMIC);
        if (!skb) {
                iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
index 0f5619611b8dc5d313accd81658fd6dd32e6a647..931992763e68c2e68f7e1f3501de25a8340dc50b 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include <linux/mount.h>
+#include <linux/security.h>
 
 struct nfs_string;
 
@@ -57,6 +58,8 @@ struct nfs_parsed_mount_data {
                char                    *export_path;
                int                     protocol;
        } nfs_server;
+
+       struct security_mnt_opts lsm_opts;
 };
 
 /* client.c */
index 1fb3818436501bc7bfd7637d7744576fe09e6041..fcf4b982c88580bca2d841d13c8e00e75f281627 100644 (file)
@@ -684,8 +684,9 @@ static void nfs_parse_server_address(char *value,
 static int nfs_parse_mount_options(char *raw,
                                   struct nfs_parsed_mount_data *mnt)
 {
-       char *p, *string;
+       char *p, *string, *secdata;
        unsigned short port = 0;
+       int rc;
 
        if (!raw) {
                dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -693,6 +694,20 @@ static int nfs_parse_mount_options(char *raw,
        }
        dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
 
+       secdata = alloc_secdata();
+       if (!secdata)
+               goto out_nomem;
+
+       rc = security_sb_copy_data(raw, secdata);
+       if (rc)
+               goto out_security_failure;
+
+       rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts);
+       if (rc)
+               goto out_security_failure;
+
+       free_secdata(secdata);
+
        while ((p = strsep(&raw, ",")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
                int option, token;
@@ -1042,7 +1057,10 @@ static int nfs_parse_mount_options(char *raw,
 out_nomem:
        printk(KERN_INFO "NFS: not enough memory to parse option\n");
        return 0;
-
+out_security_failure:
+       free_secdata(secdata);
+       printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
+       return 0;
 out_unrec_vers:
        printk(KERN_INFO "NFS: unrecognized NFS version number\n");
        return 0;
@@ -1214,6 +1232,33 @@ static int nfs_validate_mount_data(void *options,
                args->namlen            = data->namlen;
                args->bsize             = data->bsize;
                args->auth_flavors[0]   = data->pseudoflavor;
+
+               /*
+                * The legacy version 6 binary mount data from userspace has a
+                * field used only to transport selinux information into the
+                * the kernel.  To continue to support that functionality we
+                * have a touch of selinux knowledge here in the NFS code. The
+                * userspace code converted context=blah to just blah so we are
+                * converting back to the full string selinux understands.
+                */
+               if (data->context[0]){
+#ifdef CONFIG_SECURITY_SELINUX
+                       int rc;
+                       char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL);
+                       if (!opts_str)
+                               return -ENOMEM;
+                       strcpy(opts_str, "context=");
+                       data->context[NFS_MAX_CONTEXT_LEN] = '\0';
+                       strcat(opts_str, &data->context[0]);
+                       rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts);
+                       kfree(opts_str);
+                       if (rc)
+                               return rc;
+#else
+                       return -EINVAL;
+#endif
+               }
+
                break;
        default: {
                unsigned int len;
@@ -1476,6 +1521,8 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        };
        int error;
 
+       security_init_mnt_opts(&data.lsm_opts);
+
        /* Validate the mount data */
        error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name);
        if (error < 0)
@@ -1515,6 +1562,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                goto error_splat_super;
        }
 
+       error = security_sb_set_mnt_opts(s, &data.lsm_opts);
+       if (error)
+               goto error_splat_root;
+
        s->s_flags |= MS_ACTIVE;
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
@@ -1523,12 +1574,15 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 out:
        kfree(data.nfs_server.hostname);
        kfree(data.mount_server.hostname);
+       security_free_mnt_opts(&data.lsm_opts);
        return error;
 
 out_err_nosb:
        nfs_free_server(server);
        goto out;
 
+error_splat_root:
+       dput(mntroot);
 error_splat_super:
        up_write(&s->s_umount);
        deactivate_super(s);
@@ -1608,6 +1662,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
 
+       /* clone any lsm security options from the parent to the new sb */
+       security_sb_clone_mnt_opts(data->sb, s);
+
        dprintk("<-- nfs_xdev_get_sb() = 0\n");
        return 0;
 
@@ -1850,6 +1907,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        };
        int error;
 
+       security_init_mnt_opts(&data.lsm_opts);
+
        /* Validate the mount data */
        error = nfs4_validate_mount_data(raw_data, &data, dev_name);
        if (error < 0)
@@ -1898,6 +1957,7 @@ out:
        kfree(data.client_address);
        kfree(data.nfs_server.export_path);
        kfree(data.nfs_server.hostname);
+       security_free_mnt_opts(&data.lsm_opts);
        return error;
 
 out_free:
index 88811f60c8de517829ce7828c1971bfb4f90d8a1..010446d8c40a03512e4c1a8dc689581a67c5bbf3 100644 (file)
@@ -870,12 +870,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        if (!mnt)
                goto out;
 
-       if (data) {
+       if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
                secdata = alloc_secdata();
                if (!secdata)
                        goto out_mnt;
 
-               error = security_sb_copy_data(type, data, secdata);
+               error = security_sb_copy_data(data, secdata);
                if (error)
                        goto out_free_secdata;
        }
index 79384c537dc6299c9d352ed1cbcea52b03704542..c68e1680da0173d5754d1a1df4944120a5239e58 100644 (file)
@@ -1,5 +1 @@
 include include/asm-generic/Kbuild.asm
-
-unifdef-y += termios.h
-unifdef-y += ptrace.h
-unifdef-y += page.h
index b04a7ff46df17c2261476741b6e704c8d65ccd52..3b8160a2b47e0eaa145610a3b092b40769a9cd92 100644 (file)
@@ -16,7 +16,6 @@ unifdef-y += ist.h
 unifdef-y += mce.h
 unifdef-y += msr.h
 unifdef-y += mtrr.h
-unifdef-y += page.h
 unifdef-y += posix_types_32.h
 unifdef-y += posix_types_64.h
 unifdef-y += ptrace.h
index fe52cdeab0a67ba5cd1220383b9bd0872efd78e1..b07357ca2137c6b6b5c3bb031336e84941f6c1a8 100644 (file)
 #include <linux/xfrm.h>
 #include <net/flow.h>
 
-/* only a char in selinux superblock security struct flags */
-#define FSCONTEXT_MNT          0x01
-#define CONTEXT_MNT            0x02
-#define ROOTCONTEXT_MNT                0x04
-#define DEFCONTEXT_MNT         0x08
-
 extern unsigned securebits;
 
 struct ctl_table;
@@ -114,6 +108,32 @@ struct request_sock;
 
 #ifdef CONFIG_SECURITY
 
+struct security_mnt_opts {
+       char **mnt_opts;
+       int *mnt_opts_flags;
+       int num_mnt_opts;
+};
+
+static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
+{
+       opts->mnt_opts = NULL;
+       opts->mnt_opts_flags = NULL;
+       opts->num_mnt_opts = 0;
+}
+
+static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+{
+       int i;
+       if (opts->mnt_opts)
+               for(i = 0; i < opts->num_mnt_opts; i++)
+                       kfree(opts->mnt_opts[i]);
+       kfree(opts->mnt_opts);
+       opts->mnt_opts = NULL;
+       kfree(opts->mnt_opts_flags);
+       opts->mnt_opts_flags = NULL;
+       opts->num_mnt_opts = 0;
+}
+
 /**
  * struct security_operations - main security structure
  *
@@ -262,19 +282,19 @@ struct request_sock;
  * @sb_get_mnt_opts:
  *     Get the security relevant mount options used for a superblock
  *     @sb the superblock to get security mount options from
- *     @mount_options array for pointers to mount options
- *     @mount_flags array of ints specifying what each mount options is
- *     @num_opts number of options in the arrays
+ *     @opts binary data structure containing all lsm mount data
  * @sb_set_mnt_opts:
  *     Set the security relevant mount options used for a superblock
  *     @sb the superblock to set security mount options for
- *     @mount_options array for pointers to mount options
- *     @mount_flags array of ints specifying what each mount options is
- *     @num_opts number of options in the arrays
+ *     @opts binary data structure containing all lsm mount data
  * @sb_clone_mnt_opts:
  *     Copy all security options from a given superblock to another
  *     @oldsb old superblock which contain information to clone
  *     @newsb new superblock which needs filled in
+ * @sb_parse_opts_str:
+ *     Parse a string of security data filling in the opts structure
+ *     @options string containing all mount options known by the LSM
+ *     @opts binary data structure usable by the LSM
  *
  * Security hooks for inode operations.
  *
@@ -1238,8 +1258,7 @@ struct security_operations {
 
        int (*sb_alloc_security) (struct super_block * sb);
        void (*sb_free_security) (struct super_block * sb);
-       int (*sb_copy_data)(struct file_system_type *type,
-                           void *orig, void *copy);
+       int (*sb_copy_data)(char *orig, char *copy);
        int (*sb_kern_mount) (struct super_block *sb, void *data);
        int (*sb_statfs) (struct dentry *dentry);
        int (*sb_mount) (char *dev_name, struct nameidata * nd,
@@ -1257,12 +1276,12 @@ struct security_operations {
        void (*sb_post_pivotroot) (struct nameidata * old_nd,
                                   struct nameidata * new_nd);
        int (*sb_get_mnt_opts) (const struct super_block *sb,
-                               char ***mount_options, int **flags,
-                               int *num_opts);
-       int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options,
-                               int *flags, int num_opts);
+                               struct security_mnt_opts *opts);
+       int (*sb_set_mnt_opts) (struct super_block *sb,
+                               struct security_mnt_opts *opts);
        void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
                                   struct super_block *newsb);
+       int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
 
        int (*inode_alloc_security) (struct inode *inode);      
        void (*inode_free_security) (struct inode *inode);
@@ -1507,7 +1526,7 @@ int security_bprm_check(struct linux_binprm *bprm);
 int security_bprm_secureexec(struct linux_binprm *bprm);
 int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
-int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy);
+int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct nameidata *nd,
@@ -1520,12 +1539,12 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
 void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
 int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
 void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
-int security_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options,
-                            int **flags, int *num_opts);
-int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options,
-                            int *flags, int num_opts);
+int security_sb_get_mnt_opts(const struct super_block *sb,
+                               struct security_mnt_opts *opts);
+int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb);
+int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
@@ -1635,6 +1654,16 @@ int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
 
 #else /* CONFIG_SECURITY */
+struct security_mnt_opts {
+};
+
+static inline void security_init_mnt_opts(struct security_mnt_opts *opts)
+{
+}
+
+static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
+{
+}
 
 /*
  * This is the default capabilities functionality.  Most of these functions
@@ -1762,8 +1791,7 @@ static inline int security_sb_alloc (struct super_block *sb)
 static inline void security_sb_free (struct super_block *sb)
 { }
 
-static inline int security_sb_copy_data (struct file_system_type *type,
-                                        void *orig, void *copy)
+static inline int security_sb_copy_data (char *orig, char *copy)
 {
        return 0;
 }
@@ -1819,6 +1847,27 @@ static inline int security_sb_pivotroot (struct nameidata *old_nd,
 static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
                                               struct nameidata *new_nd)
 { }
+static inline int security_sb_get_mnt_opts(const struct super_block *sb,
+                                          struct security_mnt_opts *opts)
+{
+       security_init_mnt_opts(opts);
+       return 0;
+}
+
+static inline int security_sb_set_mnt_opts(struct super_block *sb,
+                                          struct security_mnt_opts *opts)
+{
+       return 0;
+}
+
+static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb,
+                                             struct super_block *newsb)
+{ }
+
+static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
+{
+       return 0;
+}
 
 static inline int security_inode_alloc (struct inode *inode)
 {
index 3ffd6b582a97144cb37009ef6ef47d1ff4cd8feb..39e1cac24bb751503fdef353a764292326b32037 100644 (file)
@@ -675,5 +675,6 @@ extern int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
 extern void sas_ssp_task_response(struct device *dev, struct sas_task *task,
                                  struct ssp_response_iu *iu);
+struct sas_phy *sas_find_local_phy(struct domain_device *dev);
 
 #endif /* _SASLIB_H_ */
index dbc96ef4cc72020b827e6e04e4dfe0d125091e38..aab1eae2ec4c4a6d310ab79cc214d6e627ec79ea 100644 (file)
@@ -177,6 +177,8 @@ struct iscsi_cls_session {
        struct list_head host_list;
        struct iscsi_transport *transport;
        spinlock_t lock;
+       struct work_struct block_work;
+       struct work_struct unblock_work;
        struct work_struct scan_work;
        struct work_struct unbind_work;
 
index 3e296ed81d4da76aefa913e7deed8f76f2032087..a1b61f414228ea031cc40ea9ea17ab95e264ceaf 100644 (file)
@@ -322,8 +322,8 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
  * Call without callback_mutex or task_lock() held.  May be
  * called with or without cgroup_mutex held.  Thanks in part to
  * 'the_top_cpuset_hack', the task's cpuset pointer will never
- * be NULL.  This routine also might acquire callback_mutex and
- * current->mm->mmap_sem during call.
+ * be NULL.  This routine also might acquire callback_mutex during
+ * call.
  *
  * Reading current->cpuset->mems_generation doesn't need task_lock
  * to guard the current->cpuset derefence, because it is guarded
index 649326bf64ea37e82afe63901560f96c687a468b..78d8f92310a4651e5069c3ea32c3cbbd09f77dc9 100644 (file)
@@ -181,8 +181,7 @@ static void dummy_sb_free_security (struct super_block *sb)
        return;
 }
 
-static int dummy_sb_copy_data (struct file_system_type *type,
-                              void *orig, void *copy)
+static int dummy_sb_copy_data (char *orig, char *copy)
 {
        return 0;
 }
@@ -245,19 +244,17 @@ static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata
        return;
 }
 
-static int dummy_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options,
-                                int **flags, int *num_opts)
+static int dummy_sb_get_mnt_opts(const struct super_block *sb,
+                                struct security_mnt_opts *opts)
 {
-       *mount_options = NULL;
-       *flags = NULL;
-       *num_opts = 0;
+       security_init_mnt_opts(opts);
        return 0;
 }
 
-static int dummy_sb_set_mnt_opts(struct super_block *sb, char **mount_options,
-                                int *flags, int num_opts)
+static int dummy_sb_set_mnt_opts(struct super_block *sb,
+                                struct security_mnt_opts *opts)
 {
-       if (unlikely(num_opts))
+       if (unlikely(opts->num_mnt_opts))
                return -EOPNOTSUPP;
        return 0;
 }
@@ -268,6 +265,11 @@ static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb,
        return;
 }
 
+static int dummy_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
+{
+       return 0;
+}
+
 static int dummy_inode_alloc_security (struct inode *inode)
 {
        return 0;
@@ -1028,6 +1030,7 @@ void security_fixup_ops (struct security_operations *ops)
        set_to_dummy_if_null(ops, sb_get_mnt_opts);
        set_to_dummy_if_null(ops, sb_set_mnt_opts);
        set_to_dummy_if_null(ops, sb_clone_mnt_opts);
+       set_to_dummy_if_null(ops, sb_parse_opts_str);
        set_to_dummy_if_null(ops, inode_alloc_security);
        set_to_dummy_if_null(ops, inode_free_security);
        set_to_dummy_if_null(ops, inode_init_security);
index d15e56cbaadeea25c550cfc985de2dbbfbf410fa..b1387a6b416da9f85a8a8fa3114d386abc1d8757 100644 (file)
@@ -244,10 +244,11 @@ void security_sb_free(struct super_block *sb)
        security_ops->sb_free_security(sb);
 }
 
-int security_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
+int security_sb_copy_data(char *orig, char *copy)
 {
-       return security_ops->sb_copy_data(type, orig, copy);
+       return security_ops->sb_copy_data(orig, copy);
 }
+EXPORT_SYMBOL(security_sb_copy_data);
 
 int security_sb_kern_mount(struct super_block *sb, void *data)
 {
@@ -306,24 +307,30 @@ void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_
 }
 
 int security_sb_get_mnt_opts(const struct super_block *sb,
-                             char ***mount_options,
-                             int **flags, int *num_opts)
+                               struct security_mnt_opts *opts)
 {
-       return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts);
+       return security_ops->sb_get_mnt_opts(sb, opts);
 }
 
 int security_sb_set_mnt_opts(struct super_block *sb,
-                             char **mount_options,
-                             int *flags, int num_opts)
+                               struct security_mnt_opts *opts)
 {
-       return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts);
+       return security_ops->sb_set_mnt_opts(sb, opts);
 }
+EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb)
 {
        security_ops->sb_clone_mnt_opts(oldsb, newsb);
 }
+EXPORT_SYMBOL(security_sb_clone_mnt_opts);
+
+int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
+{
+       return security_ops->sb_parse_opts_str(options, opts);
+}
+EXPORT_SYMBOL(security_sb_parse_opts_str);
 
 int security_inode_alloc(struct inode *inode)
 {
index 75c2e99bfb813a0653350bf18572d1359878dde5..4bf4807f2d44351f9a46084a21e26567e8602448 100644 (file)
@@ -443,8 +443,7 @@ out:
  * mount options, or whatever.
  */
 static int selinux_get_mnt_opts(const struct super_block *sb,
-                               char ***mount_options, int **mnt_opts_flags,
-                               int *num_opts)
+                               struct security_mnt_opts *opts)
 {
        int rc = 0, i;
        struct superblock_security_struct *sbsec = sb->s_security;
@@ -452,9 +451,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
        u32 len;
        char tmp;
 
-       *num_opts = 0;
-       *mount_options = NULL;
-       *mnt_opts_flags = NULL;
+       security_init_mnt_opts(opts);
 
        if (!sbsec->initialized)
                return -EINVAL;
@@ -470,18 +467,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
        /* count the number of mount options for this sb */
        for (i = 0; i < 8; i++) {
                if (tmp & 0x01)
-                       (*num_opts)++;
+                       opts->num_mnt_opts++;
                tmp >>= 1;
        }
 
-       *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC);
-       if (!*mount_options) {
+       opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
+       if (!opts->mnt_opts) {
                rc = -ENOMEM;
                goto out_free;
        }
 
-       *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC);
-       if (!*mnt_opts_flags) {
+       opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
+       if (!opts->mnt_opts_flags) {
                rc = -ENOMEM;
                goto out_free;
        }
@@ -491,22 +488,22 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
                rc = security_sid_to_context(sbsec->sid, &context, &len);
                if (rc)
                        goto out_free;
-               (*mount_options)[i] = context;
-               (*mnt_opts_flags)[i++] = FSCONTEXT_MNT;
+               opts->mnt_opts[i] = context;
+               opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
        }
        if (sbsec->flags & CONTEXT_MNT) {
                rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
                if (rc)
                        goto out_free;
-               (*mount_options)[i] = context;
-               (*mnt_opts_flags)[i++] = CONTEXT_MNT;
+               opts->mnt_opts[i] = context;
+               opts->mnt_opts_flags[i++] = CONTEXT_MNT;
        }
        if (sbsec->flags & DEFCONTEXT_MNT) {
                rc = security_sid_to_context(sbsec->def_sid, &context, &len);
                if (rc)
                        goto out_free;
-               (*mount_options)[i] = context;
-               (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT;
+               opts->mnt_opts[i] = context;
+               opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
        }
        if (sbsec->flags & ROOTCONTEXT_MNT) {
                struct inode *root = sbsec->sb->s_root->d_inode;
@@ -515,24 +512,16 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
                rc = security_sid_to_context(isec->sid, &context, &len);
                if (rc)
                        goto out_free;
-               (*mount_options)[i] = context;
-               (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT;
+               opts->mnt_opts[i] = context;
+               opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
        }
 
-       BUG_ON(i != *num_opts);
+       BUG_ON(i != opts->num_mnt_opts);
 
        return 0;
 
 out_free:
-       /* don't leak context string if security_sid_to_context had an error */
-       if (*mount_options && i)
-               for (; i > 0; i--)
-                       kfree((*mount_options)[i-1]);
-       kfree(*mount_options);
-       *mount_options = NULL;
-       kfree(*mnt_opts_flags);
-       *mnt_opts_flags = NULL;
-       *num_opts = 0;
+       security_free_mnt_opts(opts);
        return rc;
 }
 
@@ -553,12 +542,13 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
                        return 1;
        return 0;
 }
+
 /*
  * Allow filesystems with binary mount data to explicitly set mount point
  * labeling information.
  */
-static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
-                               int *flags, int num_opts)
+static int selinux_set_mnt_opts(struct super_block *sb,
+                               struct security_mnt_opts *opts)
 {
        int rc = 0, i;
        struct task_security_struct *tsec = current->security;
@@ -568,6 +558,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
        struct inode_security_struct *root_isec = inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
        u32 defcontext_sid = 0;
+       char **mount_options = opts->mnt_opts;
+       int *flags = opts->mnt_opts_flags;
+       int num_opts = opts->num_mnt_opts;
 
        mutex_lock(&sbsec->lock);
 
@@ -588,6 +581,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
                goto out;
        }
 
+       /*
+        * Binary mount data FS will come through this function twice.  Once
+        * from an explicit call and once from the generic calls from the vfs.
+        * Since the generic VFS calls will not contain any security mount data
+        * we need to skip the double mount verification.
+        *
+        * This does open a hole in which we will not notice if the first
+        * mount using this sb set explict options and a second mount using
+        * this sb does not set any security options.  (The first options
+        * will be used for both mounts)
+        */
+       if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
+           && (num_opts == 0))
+               goto out;
+
        /*
         * parse the mount options, check if they are valid sids.
         * also check if someone is trying to mount the same sb more
@@ -792,43 +800,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
        mutex_unlock(&newsbsec->lock);
 }
 
-/*
- * string mount options parsing and call set the sbsec
- */
-static int superblock_doinit(struct super_block *sb, void *data)
+int selinux_parse_opts_str(char *options, struct security_mnt_opts *opts)
 {
+       char *p;
        char *context = NULL, *defcontext = NULL;
        char *fscontext = NULL, *rootcontext = NULL;
-       int rc = 0;
-       char *p, *options = data;
-       /* selinux only know about a fixed number of mount options */
-       char *mnt_opts[NUM_SEL_MNT_OPTS];
-       int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
-
-       if (!data)
-               goto out;
+       int rc, num_mnt_opts = 0;
 
-       /* with the nfs patch this will become a goto out; */
-       if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
-               const char *name = sb->s_type->name;
-               /* NFS we understand. */
-               if (!strcmp(name, "nfs")) {
-                       struct nfs_mount_data *d = data;
-
-                       if (d->version !=  NFS_MOUNT_VERSION)
-                               goto out;
-
-                       if (d->context[0]) {
-                               context = kstrdup(d->context, GFP_KERNEL);
-                               if (!context) {
-                                       rc = -ENOMEM;
-                                       goto out;
-                               }
-                       }
-                       goto build_flags;
-               } else
-                       goto out;
-       }
+       opts->num_mnt_opts = 0;
 
        /* Standard string-based options. */
        while ((p = strsep(&options, "|")) != NULL) {
@@ -901,26 +880,37 @@ static int superblock_doinit(struct super_block *sb, void *data)
                }
        }
 
-build_flags:
+       rc = -ENOMEM;
+       opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
+       if (!opts->mnt_opts)
+               goto out_err;
+
+       opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
+       if (!opts->mnt_opts_flags) {
+               kfree(opts->mnt_opts);
+               goto out_err;
+       }
+
        if (fscontext) {
-               mnt_opts[num_mnt_opts] = fscontext;
-               mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
+               opts->mnt_opts[num_mnt_opts] = fscontext;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
        }
        if (context) {
-               mnt_opts[num_mnt_opts] = context;
-               mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
+               opts->mnt_opts[num_mnt_opts] = context;
+               opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
        }
        if (rootcontext) {
-               mnt_opts[num_mnt_opts] = rootcontext;
-               mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
+               opts->mnt_opts[num_mnt_opts] = rootcontext;
+               opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
        }
        if (defcontext) {
-               mnt_opts[num_mnt_opts] = defcontext;
-               mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
+               opts->mnt_opts[num_mnt_opts] = defcontext;
+               opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
        }
 
-out:
-       rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
+       opts->num_mnt_opts = num_mnt_opts;
+       return 0;
+
 out_err:
        kfree(context);
        kfree(defcontext);
@@ -928,6 +918,33 @@ out_err:
        kfree(rootcontext);
        return rc;
 }
+/*
+ * string mount options parsing and call set the sbsec
+ */
+static int superblock_doinit(struct super_block *sb, void *data)
+{
+       int rc = 0;
+       char *options = data;
+       struct security_mnt_opts opts;
+
+       security_init_mnt_opts(&opts);
+
+       if (!data)
+               goto out;
+
+       BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
+
+       rc = selinux_parse_opts_str(options, &opts);
+       if (rc)
+               goto out_err;
+
+out:
+       rc = selinux_set_mnt_opts(sb, &opts);
+
+out_err:
+       security_free_mnt_opts(&opts);
+       return rc;
+}
 
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
@@ -2253,7 +2270,7 @@ static inline void take_selinux_option(char **to, char *from, int *first,
        }
 }
 
-static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
+static int selinux_sb_copy_data(char *orig, char *copy)
 {
        int fnosec, fsec, rc = 0;
        char *in_save, *in_curr, *in_end;
@@ -2263,12 +2280,6 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
        in_curr = orig;
        sec_curr = copy;
 
-       /* Binary mount data: just copy */
-       if (type->fs_flags & FS_BINARY_MOUNTDATA) {
-               copy_page(sec_curr, in_curr);
-               goto out;
-       }
-
        nosec = (char *)get_zeroed_page(GFP_KERNEL);
        if (!nosec) {
                rc = -ENOMEM;
@@ -5251,6 +5262,8 @@ static struct security_operations selinux_ops = {
        .sb_get_mnt_opts =              selinux_get_mnt_opts,
        .sb_set_mnt_opts =              selinux_set_mnt_opts,
        .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
+       .sb_parse_opts_str =            selinux_parse_opts_str,
+
 
        .inode_alloc_security =         selinux_inode_alloc_security,
        .inode_free_security =          selinux_inode_free_security,
index 837ce420d2f64ff810c4e96b7b7ce9a1ca695328..f7d2f03781f29b650d7e9bfa82822bb680b2a82d 100644 (file)
 #define POLICYDB_VERSION_MAX   POLICYDB_VERSION_POLCAP
 #endif
 
+#define CONTEXT_MNT    0x01
+#define FSCONTEXT_MNT  0x02
+#define ROOTCONTEXT_MNT        0x04
+#define DEFCONTEXT_MNT 0x08
+
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;
index 770eb067e165f493b1e153cac3cfcec6d66953f7..0241fd359675a947def24347cbc22dd559fe314e 100644 (file)
@@ -189,17 +189,10 @@ static void smack_sb_free_security(struct super_block *sb)
  * Copy the Smack specific mount options out of the mount
  * options list.
  */
-static int smack_sb_copy_data(struct file_system_type *type, void *orig,
-                             void *smackopts)
+static int smack_sb_copy_data(char *orig, char *smackopts)
 {
        char *cp, *commap, *otheropts, *dp;
 
-       /* Binary mount data: just copy */
-       if (type->fs_flags & FS_BINARY_MOUNTDATA) {
-               copy_page(smackopts, orig);
-               return 0;
-       }
-
        otheropts = (char *)get_zeroed_page(GFP_KERNEL);
        if (otheropts == NULL)
                return -ENOMEM;