Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Jan 2008 22:30:10 +0000 (09:30 +1100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Jan 2008 22:30:10 +0000 (09:30 +1100)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm: (249 commits)
  KVM: Move apic timer migration away from critical section
  KVM: Put kvm_para.h include outside __KERNEL__
  KVM: Fix unbounded preemption latency
  KVM: Initialize the mmu caches only after verifying cpu support
  KVM: MMU: Fix dirty page setting for pages removed from rmap
  KVM: Portability: Move kvm_fpu to asm-x86/kvm.h
  KVM: x86 emulator: Only allow VMCALL/VMMCALL trapped by #UD
  KVM: MMU: Merge shadow level check in FNAME(fetch)
  KVM: MMU: Move kvm_free_some_pages() into critical section
  KVM: MMU: Switch to mmu spinlock
  KVM: MMU: Avoid calling gfn_to_page() in mmu_set_spte()
  KVM: Add kvm_read_guest_atomic()
  KVM: MMU: Concurrent guest walkers
  KVM: Disable vapic support on Intel machines with FlexPriority
  KVM: Accelerated apic support
  KVM: local APIC TPR access reporting facility
  KVM: Print data for unimplemented wrmsr
  KVM: MMU: Add cache miss statistic
  KVM: MMU: Coalesce remote tlb flushes
  KVM: Expose ioapic to ia64 save/restore APIs
  ...

86 files changed:
Documentation/DocBook/kernel-api.tmpl
arch/ia64/hp/sim/simscsi.c
block/bsg.c
drivers/base/class.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-xxxx.c
drivers/scsi/BusLogic.c
drivers/scsi/Kconfig
drivers/scsi/NCR53c406a.c
drivers/scsi/a100u2w.c
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aha1740.c
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic7xxx.h
drivers/scsi/aic7xxx/aic7xxx_core.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx_old.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/dc395x.c
drivers/scsi/dpt_i2o.c
drivers/scsi/eata.c
drivers/scsi/hosts.c
drivers/scsi/hptiop.c
drivers/scsi/ibmmca.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/initio.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/libsrp.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/mac53c94.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/mesh.c
drivers/scsi/ncr53c8xx.c
drivers/scsi/nsp32.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qlogicfas.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/sd.c
drivers/scsi/sgiwd93.c
drivers/scsi/sr.c
drivers/scsi/stex.c
drivers/scsi/sym53c416.c
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/scsi/u14-34f.c
drivers/scsi/ultrastor.c
drivers/scsi/wd7000.c
drivers/usb/storage/isd200.c
fs/dlm/dir.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lock.h
fs/dlm/lockspace.c
fs/dlm/lowcomms.c
fs/dlm/main.c
fs/dlm/member.c
fs/dlm/member.h
fs/dlm/memory.c
fs/dlm/memory.h
fs/dlm/midcomms.c
fs/dlm/rcom.c
fs/dlm/recover.c
fs/dlm/recoverd.c
fs/dlm/user.c
fs/dlm/util.c
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h

index aa38cc5692a005fe4a48f59bdabff3689865c6db..77436d735013f37195750aec890f7db57a1b130d 100644 (file)
@@ -419,7 +419,13 @@ X!Edrivers/pnp/system.c
 
   <chapter id="blkdev">
      <title>Block Devices</title>
-!Eblock/ll_rw_blk.c
+!Eblock/blk-core.c
+!Eblock/blk-map.c
+!Iblock/blk-sysfs.c
+!Eblock/blk-settings.c
+!Eblock/blk-exec.c
+!Eblock/blk-barrier.c
+!Eblock/blk-tag.c
   </chapter>
 
   <chapter id="chrdev">
index 6ef9b52199304af2f472f92becd0216cbbe2e492..7661bb065fa570a4a61036acf551d5feacda94ef 100644 (file)
@@ -360,7 +360,6 @@ static struct scsi_host_template driver_template = {
        .max_sectors            = 1024,
        .cmd_per_lun            = SIMSCSI_REQ_QUEUE_LEN,
        .use_clustering         = DISABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 static int __init
index 69b0a9d333064c782676a4f84fd79e4006c2c879..8917c5174dc2646c5ad8d4d67eb67529a98783f5 100644 (file)
@@ -279,6 +279,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
                        goto out;
                }
                rq->next_rq = next_rq;
+               next_rq->cmd_type = rq->cmd_type;
 
                dxferp = (void*)(unsigned long)hdr->din_xferp;
                ret =  blk_rq_map_user(q, next_rq, dxferp, hdr->din_xfer_len);
index 59cf35894cfce832c814128baa495a2e35f4971b..412fd9a05573e742117fced63ed4210512fbe79d 100644 (file)
@@ -863,7 +863,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device);
  * The callback should return 0 if the device doesn't match and non-zero
  * if it does.  If the callback returns non-zero, this function will
  * return to the caller and not iterate over any more devices.
-
+ *
  * Note, you will need to drop the reference with put_device() after use.
  *
  * We hold class->sem in this function, so it can not be
index f2d2c7e2c76b9cd1b778da992a481b65e575bf7a..195ce7c123191896aa2946b0dc2499f13d23cbfb 100644 (file)
@@ -1571,7 +1571,6 @@ static struct scsi_host_template srp_template = {
        .this_id                        = -1,
        .cmd_per_lun                    = SRP_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
        .shost_attrs                    = srp_host_attrs
 };
 
index e45f85f7c7ed815d1c4017baf16465762200235b..0dff05840ee2e1ffcdb222cdb3805c01054fbd65 100644 (file)
@@ -4224,10 +4224,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 
                ZFCP_LOG_TRACE("%i bytes sense data provided by FCP\n",
                               fcp_rsp_iu->fcp_sns_len);
-               memcpy(&scpnt->sense_buffer,
+               memcpy(scpnt->sense_buffer,
                       zfcp_get_fcp_sns_info_ptr(fcp_rsp_iu), sns_len);
                ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE,
-                             (void *) &scpnt->sense_buffer, sns_len);
+                             (void *)scpnt->sense_buffer, sns_len);
        }
 
        /* check for overrun */
index 1c244832c6c8aa0049d560883c3b959845050b83..b4912d1cee2aa164e81a82ffaefd9e01d991b2b0 100644 (file)
@@ -1990,7 +1990,6 @@ static struct scsi_host_template driver_template = {
        .max_sectors            = TW_MAX_SECTORS,
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .shost_attrs            = twa_host_attrs,
        .emulated               = 1
 };
index 59716ebeb10c1a5c100d42d5941f18e2ba1769ff..d09532162217b5f04376845546bbced6ada5b05a 100644 (file)
@@ -2261,7 +2261,6 @@ static struct scsi_host_template driver_template = {
        .max_sectors            = TW_MAX_SECTORS,
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,  
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .shost_attrs            = tw_host_attrs,
        .emulated               = 1
 };
index ead47c143ce04fd9792da0d30c9a7b31f7d0db03..4d3ebb1af49022e9777a6472f368d96e1a6dec45 100644 (file)
@@ -3575,7 +3575,6 @@ static struct scsi_host_template Bus_Logic_template = {
        .unchecked_isa_dma = 1,
        .max_sectors = 128,
        .use_clustering = ENABLE_CLUSTERING,
-       .use_sg_chaining = ENABLE_SG_CHAINING,
 };
 
 /*
index 3e161cd664637292927686aaf954e23dfc3b1a02..14fc7f39e83e0be1ad26267daad4853544775223 100644 (file)
@@ -345,7 +345,7 @@ config ISCSI_TCP
 
 config SGIWD93_SCSI
        tristate "SGI WD93C93 SCSI Driver"
-       depends on SGI_IP22 && SCSI
+       depends on SGI_HAS_WD93 && SCSI
        help
          If you have a Western Digital WD93 SCSI controller on
          an SGI MIPS system, say Y.  Otherwise, say N.
index 137d065db3da037f350a53c0afb1afa4ad8a187b..6961f78742aedbc86de34d810891737eeece4ec9 100644 (file)
@@ -1065,7 +1065,6 @@ static struct scsi_host_template driver_template =
      .cmd_per_lun              = 1                     /* commands per lun */, 
      .unchecked_isa_dma        = 1                     /* unchecked_isa_dma */,
      .use_clustering           = ENABLE_CLUSTERING,
-     .use_sg_chaining           = ENABLE_SG_CHAINING,
 };
 
 #include "scsi_module.c"
index d3a6d15fb77af90ead7ee78bfd1deed94e5bef8f..f608d4a1d6daeaa8b44ca46d25cb3fe2b3cc2276 100644 (file)
@@ -1071,7 +1071,6 @@ static struct scsi_host_template inia100_template = {
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 static int __devinit inia100_probe_one(struct pci_dev *pdev,
index 851a7e599c500bc5f4e24b2a3aba4a23a4e153f9..f8afa358b6b67fba3ba9aa36293ecfdbfd9be01d 100644 (file)
@@ -243,7 +243,6 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
         *      Search the list of AdapterFibContext addresses on the adapter
         *      to be sure this is a valid address
         */
-       spin_lock_irqsave(&dev->fib_lock, flags);
        entry = dev->fib_list.next;
        fibctx = NULL;
 
@@ -252,25 +251,24 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
                /*
                 *      Extract the AdapterFibContext from the Input parameters.
                 */
-               if (fibctx->unique == f.fibctx) { /* We found a winner */
+               if (fibctx->unique == f.fibctx) {   /* We found a winner */
                        break;
                }
                entry = entry->next;
                fibctx = NULL;
        }
        if (!fibctx) {
-               spin_unlock_irqrestore(&dev->fib_lock, flags);
                dprintk ((KERN_INFO "Fib Context not found\n"));
                return -EINVAL;
        }
 
        if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
                 (fibctx->size != sizeof(struct aac_fib_context))) {
-               spin_unlock_irqrestore(&dev->fib_lock, flags);
                dprintk ((KERN_INFO "Fib Context corrupt?\n"));
                return -EINVAL;
        }
        status = 0;
+       spin_lock_irqsave(&dev->fib_lock, flags);
        /*
         *      If there are no fibs to send back, then either wait or return
         *      -EAGAIN
@@ -328,9 +326,7 @@ return_fib:
 int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
 {
        struct fib *fib;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dev->fib_lock, flags);
        /*
         *      First free any FIBs that have not been consumed.
         */
@@ -353,7 +349,6 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
         *      Remove the Context from the AdapterFibContext List
         */
        list_del(&fibctx->next);
-       spin_unlock_irqrestore(&dev->fib_lock, flags);
        /*
         *      Invalidate context
         */
@@ -419,8 +414,8 @@ static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)
  *     @arg: ioctl arguments
  *
  *     This routine returns the driver version.
- *     Under Linux, there have been no version incompatibilities, so this is
- *     simple!
+ *      Under Linux, there have been no version incompatibilities, so this is
+ *      simple!
  */
 
 static int check_revision(struct aac_dev *dev, void __user *arg)
@@ -468,7 +463,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
        u32 data_dir;
        void __user *sg_user[32];
        void *sg_list[32];
-       u32 sg_indx = 0;
+       u32   sg_indx = 0;
        u32 byte_count = 0;
        u32 actual_fibsize64, actual_fibsize = 0;
        int i;
@@ -522,11 +517,11 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
        // Fix up srb for endian and force some values
 
        srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);       // Force this
-       srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
+       srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
        srbcmd->id       = cpu_to_le32(user_srbcmd->id);
-       srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
-       srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
-       srbcmd->flags    = cpu_to_le32(flags);
+       srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
+       srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
+       srbcmd->flags    = cpu_to_le32(flags);
        srbcmd->retry_limit = 0; // Obsolete parameter
        srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
        memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
@@ -791,9 +786,9 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
        pci_info.bus = dev->pdev->bus->number;
        pci_info.slot = PCI_SLOT(dev->pdev->devfn);
 
-       if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
-               dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
-               return -EFAULT;
+       if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
+              dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
+              return -EFAULT;
        }
        return 0;
 }
index 61be22774e99786390ca0702cb932b3aa1812799..0e8267c1e9155a29df404823454a47268442a667 100644 (file)
@@ -1032,7 +1032,6 @@ static struct scsi_host_template aac_driver_template = {
        .cmd_per_lun                    = AAC_NUM_IO_FIB,
 #endif
        .use_clustering                 = ENABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
        .emulated                       = 1,
 };
 
index be58a0b097c76752d0827ee097c4c198db09fe17..7c45d88a205bfd2a9fd2d916f228f796d42f2cd5 100644 (file)
@@ -563,7 +563,6 @@ static struct scsi_host_template aha1740_template = {
        .sg_tablesize     = AHA1740_SCATTER,
        .cmd_per_lun      = AHA1740_CMDLUN,
        .use_clustering   = ENABLE_CLUSTERING,
-       .use_sg_chaining  = ENABLE_SG_CHAINING,
        .eh_abort_handler = aha1740_eh_abort_handler,
 };
 
index ce638aa6005ad93537cf4b86b15c6cc453b31f09..2f00467b6b8c8bd12418614d186e475f2fd24590 100644 (file)
@@ -1340,8 +1340,10 @@ struct   ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
 int                      ahd_pci_config(struct ahd_softc *,
                                         struct ahd_pci_identity *);
 int    ahd_pci_test_register_access(struct ahd_softc *);
+#ifdef CONFIG_PM
 void   ahd_pci_suspend(struct ahd_softc *);
 void   ahd_pci_resume(struct ahd_softc *);
+#endif
 
 /************************** SCB and SCB queue management **********************/
 void           ahd_qinfifo_requeue_tail(struct ahd_softc *ahd,
@@ -1352,8 +1354,10 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name);
 int                     ahd_softc_init(struct ahd_softc *);
 void                    ahd_controller_info(struct ahd_softc *ahd, char *buf);
 int                     ahd_init(struct ahd_softc *ahd);
+#ifdef CONFIG_PM
 int                     ahd_suspend(struct ahd_softc *ahd);
 void                    ahd_resume(struct ahd_softc *ahd);
+#endif
 int                     ahd_default_config(struct ahd_softc *ahd);
 int                     ahd_parse_vpddata(struct ahd_softc *ahd,
                                           struct vpd_config *vpd);
@@ -1361,7 +1365,6 @@ int                        ahd_parse_cfgdata(struct ahd_softc *ahd,
                                           struct seeprom_config *sc);
 void                    ahd_intr_enable(struct ahd_softc *ahd, int enable);
 void                    ahd_pause_and_flushwork(struct ahd_softc *ahd);
-int                     ahd_suspend(struct ahd_softc *ahd); 
 void                    ahd_set_unit(struct ahd_softc *, int);
 void                    ahd_set_name(struct ahd_softc *, char *);
 struct scb             *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
index a7dd8cdda472d6f31ac5ea57dbd7688da4a94c8e..ade0fb8fbdb23fa9264174e9b6b2c08a972e42f2 100644 (file)
@@ -7175,6 +7175,7 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
        ahd->flags &= ~AHD_ALL_INTERRUPTS;
 }
 
+#ifdef CONFIG_PM
 int
 ahd_suspend(struct ahd_softc *ahd)
 {
@@ -7197,6 +7198,7 @@ ahd_resume(struct ahd_softc *ahd)
        ahd_intr_enable(ahd, TRUE); 
        ahd_restart(ahd);
 }
+#endif
 
 /************************** Busy Target Table *********************************/
 /*
index 0e4708fd43c8e00d861b80392c976683d43145fa..01465479290135bcd4d03719880bc360fc28947e 100644 (file)
@@ -766,7 +766,6 @@ struct scsi_host_template aic79xx_driver_template = {
        .max_sectors            = 8192,
        .cmd_per_lun            = 2,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .slave_alloc            = ahd_linux_slave_alloc,
        .slave_configure        = ahd_linux_slave_configure,
        .target_alloc           = ahd_linux_target_alloc,
@@ -1922,7 +1921,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
                                struct scsi_sense_data *sense;
                                
                                sense = (struct scsi_sense_data *)
-                                       &cmd->sense_buffer;
+                                       cmd->sense_buffer;
                                if (sense->extra_len >= 5 &&
                                    (sense->add_sense_code == 0x47
                                     || sense->add_sense_code == 0x48))
index 66f0259edb697c34f25ea3e410a963ce2b814e70..4150c8a8fdc2546cdd21224dd0f1dea987ee2416 100644 (file)
 #include "aic79xx_inline.h"
 #include "aic79xx_pci.h"
 
-static int     ahd_linux_pci_dev_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent);
-static int     ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd,
-                                                u_long *base, u_long *base2);
-static int     ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
-                                                u_long *bus_addr,
-                                                uint8_t __iomem **maddr);
-static int     ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
-static int     ahd_linux_pci_dev_resume(struct pci_dev *pdev);
-static void    ahd_linux_pci_dev_remove(struct pci_dev *pdev);
-
 /* Define the macro locally since it's different for different class of chips.
  */
 #define ID(x)            \
@@ -85,17 +74,7 @@ static struct pci_device_id ahd_linux_pci_id_table[] = {
 
 MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
 
-static struct pci_driver aic79xx_pci_driver = {
-       .name           = "aic79xx",
-       .probe          = ahd_linux_pci_dev_probe,
 #ifdef CONFIG_PM
-       .suspend        = ahd_linux_pci_dev_suspend,
-       .resume         = ahd_linux_pci_dev_resume,
-#endif
-       .remove         = ahd_linux_pci_dev_remove,
-       .id_table       = ahd_linux_pci_id_table
-};
-
 static int
 ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
@@ -139,6 +118,7 @@ ahd_linux_pci_dev_resume(struct pci_dev *pdev)
 
        return rc;
 }
+#endif
 
 static void
 ahd_linux_pci_dev_remove(struct pci_dev *pdev)
@@ -245,6 +225,17 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return (0);
 }
 
+static struct pci_driver aic79xx_pci_driver = {
+       .name           = "aic79xx",
+       .probe          = ahd_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+       .suspend        = ahd_linux_pci_dev_suspend,
+       .resume         = ahd_linux_pci_dev_resume,
+#endif
+       .remove         = ahd_linux_pci_dev_remove,
+       .id_table       = ahd_linux_pci_id_table
+};
+
 int
 ahd_linux_pci_init(void)
 {
index 7a203a90601ae06c4e434f36b3f719e5a3eea204..df853676e66a8d7174c81862e65559c99fd45121 100644 (file)
@@ -389,6 +389,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
        return error;
 }
 
+#ifdef CONFIG_PM
 void
 ahd_pci_suspend(struct ahd_softc *ahd)
 {
@@ -415,6 +416,7 @@ ahd_pci_resume(struct ahd_softc *ahd)
        ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
                             ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
 }
+#endif
 
 /*
  * Perform some simple tests that should catch situations where
index 3d4e42d904521c2f01768506aee696ed799174f6..c0344e61765112195bb711ad25137e34da58fc61 100644 (file)
@@ -1143,7 +1143,9 @@ struct ahc_pci_identity   *ahc_find_pci_device(ahc_dev_softc_t);
 int                     ahc_pci_config(struct ahc_softc *,
                                        struct ahc_pci_identity *);
 int                     ahc_pci_test_register_access(struct ahc_softc *);
+#ifdef CONFIG_PM
 void                    ahc_pci_resume(struct ahc_softc *ahc);
+#endif
 
 /*************************** EISA/VL Front End ********************************/
 struct aic7770_identity *aic7770_find_device(uint32_t);
@@ -1170,8 +1172,10 @@ int                       ahc_chip_init(struct ahc_softc *ahc);
 int                     ahc_init(struct ahc_softc *ahc);
 void                    ahc_intr_enable(struct ahc_softc *ahc, int enable);
 void                    ahc_pause_and_flushwork(struct ahc_softc *ahc);
+#ifdef CONFIG_PM
 int                     ahc_suspend(struct ahc_softc *ahc); 
 int                     ahc_resume(struct ahc_softc *ahc);
+#endif
 void                    ahc_set_unit(struct ahc_softc *, int);
 void                    ahc_set_name(struct ahc_softc *, char *);
 void                    ahc_alloc_scbs(struct ahc_softc *ahc);
index f350b5e89e76d01485cb9fb22cb16c8a8d2c967c..6d2ae641273c9fe56826043fb623761fe1063bb9 100644 (file)
@@ -5078,6 +5078,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
        ahc->flags &= ~AHC_ALL_INTERRUPTS;
 }
 
+#ifdef CONFIG_PM
 int
 ahc_suspend(struct ahc_softc *ahc)
 {
@@ -5113,7 +5114,7 @@ ahc_resume(struct ahc_softc *ahc)
        ahc_restart(ahc);
        return (0);
 }
-
+#endif
 /************************** Busy Target Table *********************************/
 /*
  * Return the untagged transaction id for a given target/channel lun.
index e310e414067fc767ef0e8ede1a6864d90650ca6a..99a3b33a3233591834e670c95b8152af9df3d12d 100644 (file)
@@ -747,7 +747,6 @@ struct scsi_host_template aic7xxx_driver_template = {
        .max_sectors            = 8192,
        .cmd_per_lun            = 2,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .slave_alloc            = ahc_linux_slave_alloc,
        .slave_configure        = ahc_linux_slave_configure,
        .target_alloc           = ahc_linux_target_alloc,
@@ -1658,9 +1657,12 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
                untagged_q = &(ahc->untagged_queues[target_offset]);
                TAILQ_REMOVE(untagged_q, scb, links.tqe);
                BUG_ON(!TAILQ_EMPTY(untagged_q));
-       }
-
-       if ((scb->flags & SCB_ACTIVE) == 0) {
+       } else if ((scb->flags & SCB_ACTIVE) == 0) {
+               /*
+                * Transactions aborted from the untagged queue may
+                * not have been dispatched to the controller, so
+                * only check the SCB_ACTIVE flag for tagged transactions.
+                */
                printf("SCB %d done'd twice\n", scb->hscb->tag);
                ahc_dump_card_state(ahc);
                panic("Stopping for safety");
index 4488946cff2e518e501686852090b02f44fc6b62..dd6e21d6f1dd36ae12ec4b18eebb1e7e53c6ce9b 100644 (file)
 #include "aic7xxx_osm.h"
 #include "aic7xxx_pci.h"
 
-static int     ahc_linux_pci_dev_probe(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent);
-static int     ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
-                                               u_long *base);
-static int     ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
-                                                u_long *bus_addr,
-                                                uint8_t __iomem **maddr);
-static int     ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg);
-static int     ahc_linux_pci_dev_resume(struct pci_dev *pdev);
-static void    ahc_linux_pci_dev_remove(struct pci_dev *pdev);
-
 /* Define the macro locally since it's different for different class of chips.
 */
 #define ID(x)  ID_C(x, PCI_CLASS_STORAGE_SCSI)
@@ -132,17 +121,7 @@ static struct pci_device_id ahc_linux_pci_id_table[] = {
 
 MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table);
 
-static struct pci_driver aic7xxx_pci_driver = {
-       .name           = "aic7xxx",
-       .probe          = ahc_linux_pci_dev_probe,
 #ifdef CONFIG_PM
-       .suspend        = ahc_linux_pci_dev_suspend,
-       .resume         = ahc_linux_pci_dev_resume,
-#endif
-       .remove         = ahc_linux_pci_dev_remove,
-       .id_table       = ahc_linux_pci_id_table
-};
-
 static int
 ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
@@ -182,6 +161,7 @@ ahc_linux_pci_dev_resume(struct pci_dev *pdev)
 
        return (ahc_resume(ahc));
 }
+#endif
 
 static void
 ahc_linux_pci_dev_remove(struct pci_dev *pdev)
@@ -289,6 +269,17 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return (0);
 }
 
+static struct pci_driver aic7xxx_pci_driver = {
+       .name           = "aic7xxx",
+       .probe          = ahc_linux_pci_dev_probe,
+#ifdef CONFIG_PM
+       .suspend        = ahc_linux_pci_dev_suspend,
+       .resume         = ahc_linux_pci_dev_resume,
+#endif
+       .remove         = ahc_linux_pci_dev_remove,
+       .id_table       = ahc_linux_pci_id_table
+};
+
 int
 ahc_linux_pci_init(void)
 {
index ae35937b8055b346f394dcb994006f8465c2abcf..56848f41e4f961f7a70d66964a8d770671ff0663 100644 (file)
@@ -2020,6 +2020,7 @@ ahc_pci_chip_init(struct ahc_softc *ahc)
        return (ahc_chip_init(ahc));
 }
 
+#ifdef CONFIG_PM
 void
 ahc_pci_resume(struct ahc_softc *ahc)
 {
@@ -2051,6 +2052,7 @@ ahc_pci_resume(struct ahc_softc *ahc)
                ahc_release_seeprom(&sd);
        }
 }
+#endif
 
 static int
 ahc_aic785X_setup(struct ahc_softc *ahc)
index bcb0b870320c166b56f2c08c6ee07113d6fa915d..3bfd9296bbfaaa75dc314d9be939c05eb2688b82 100644 (file)
@@ -11141,7 +11141,6 @@ static struct scsi_host_template driver_template = {
        .max_sectors            = 2048,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 #include "scsi_module.c"
index d80dba913a750c8e051b16ec28215348cb55ef41..f4a202e8df267329e44b15cbe48ad546911de118 100644 (file)
@@ -122,7 +122,6 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .max_sectors            = ARCMSR_MAX_XFER_SECTORS,
        .cmd_per_lun            = ARCMSR_MAX_CMD_PERLUN,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .shost_attrs            = arcmsr_host_attrs,
 };
 #ifdef CONFIG_SCSI_ARCMSR_AER
index f93c73c0ba53d7081a187f17e5c17bf7224da77d..22ef3716e7864168977b4e7967358bf0b6496b1a 100644 (file)
@@ -4763,7 +4763,6 @@ static struct scsi_host_template dc395x_driver_template = {
        .eh_bus_reset_handler   = dc395x_eh_bus_reset,
        .unchecked_isa_dma      = 0,
        .use_clustering         = DISABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 
index 19cce125124c8d423fc9cd500175f2b70bd9e7ce..c9dd8392aab20f138916d6b46150aba96b336483 100644 (file)
@@ -3340,7 +3340,6 @@ static struct scsi_host_template driver_template = {
        .this_id                = 7,
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 #include "scsi_module.c"
 MODULE_LICENSE("GPL");
index 05163cefec12f7f2f806009de76da5d77767a0ed..8be3d76656faab6fdbfa92548febc77bb4db03e5 100644 (file)
@@ -524,7 +524,6 @@ static struct scsi_host_template driver_template = {
        .this_id = 7,
        .unchecked_isa_dma = 1,
        .use_clustering = ENABLE_CLUSTERING,
-       .use_sg_chaining = ENABLE_SG_CHAINING,
 };
 
 #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
index 5ea1f986220cf052e2786d6f91a5d7e86aebcf39..880c78bff0e14a35e2ac6d6677b213946eca7ee8 100644 (file)
@@ -342,7 +342,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
        shost->active_mode = sht->supported_mode;
-       shost->use_sg_chaining = sht->use_sg_chaining;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index e7b2f3575ce99466c1ddf50991744205b4d0c0fa..ff149ad6bc4ed103e44f7497b174391a94ede468 100644 (file)
@@ -573,7 +573,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
                scsi_set_resid(scp,
                        scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
                scp->result = SAM_STAT_CHECK_CONDITION;
-               memcpy(&scp->sense_buffer, &req->sg_list,
+               memcpy(scp->sense_buffer, &req->sg_list,
                                min_t(size_t, SCSI_SENSE_BUFFERSIZE,
                                        le32_to_cpu(req->dataxfer_length)));
                break;
@@ -906,7 +906,6 @@ static struct scsi_host_template driver_template = {
        .unchecked_isa_dma          = 0,
        .emulated                   = 0,
        .use_clustering             = ENABLE_CLUSTERING,
-       .use_sg_chaining            = ENABLE_SG_CHAINING,
        .proc_name                  = driver_name,
        .shost_attrs                = hptiop_attrs,
        .this_id                    = -1,
index db004a45073277edbd946cff38e941893de01a95..4d15a62914e92f9ea322557be2a798c90b154706 100644 (file)
@@ -1501,7 +1501,6 @@ static struct scsi_host_template ibmmca_driver_template = {
           .sg_tablesize   = 16,
           .cmd_per_lun    = 1,
           .use_clustering = ENABLE_CLUSTERING,
-          .use_sg_chaining = ENABLE_SG_CHAINING,
 };
 
 static int ibmmca_probe(struct device *dev)
index 30819012898fca80eb828e81ed2a3aa2c3d308cd..78d46a900bb51a5e43d8877bb0882f983e6ae13f 100644 (file)
@@ -1600,7 +1600,6 @@ static struct scsi_host_template driver_template = {
        .this_id = -1,
        .sg_tablesize = SG_ALL,
        .use_clustering = ENABLE_CLUSTERING,
-       .use_sg_chaining = ENABLE_SG_CHAINING,
        .shost_attrs = ibmvscsi_attrs,
 };
 
index a10a5c74b48db6d2150905b252f52fbc3b0d3362..0cc8868ea35d03de01ebfbf25df8ab25f634f5b8 100644 (file)
@@ -2833,7 +2833,6 @@ static struct scsi_host_template initio_template = {
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 static int initio_probe_one(struct pci_dev *pdev,
index e5be5fd4ef583f10ba907721da19249999d609bb..b6f99dfbb038b91d02ef59d473a1052d4ab7b82b 100644 (file)
@@ -1933,7 +1933,6 @@ static struct scsi_host_template iscsi_sht = {
        .eh_device_reset_handler= iscsi_eh_device_reset,
        .eh_host_reset_handler  = iscsi_eh_host_reset,
        .use_clustering         = DISABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .slave_configure        = iscsi_tcp_slave_configure,
        .proc_name              = "iscsi_tcp",
        .this_id                = -1,
index 5cff0204227dc8267ff6443cefa76eb248360f16..6d6a76e65a6c3fc9e391c17b2fe34cf61176f718 100644 (file)
@@ -426,8 +426,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
 
        sc->SCp.ptr = info;
        memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
-       sc->request_bufflen = len;
-       sc->request_buffer = (void *) (unsigned long) addr;
+       sc->sdb.length = len;
+       sc->sdb.table.sgl = (void *) (unsigned long) addr;
        sc->tag = tag;
        err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
                                     cmd->tag);
index 6483c62730b3b8b71c55b10389c881ce2c222d23..fc5c3a42b05a67c0b9b37f8ae03a68521529f2e1 100644 (file)
@@ -1459,7 +1459,6 @@ struct scsi_host_template lpfc_template = {
        .scan_finished          = lpfc_scan_finished,
        .this_id                = -1,
        .sg_tablesize           = LPFC_DEFAULT_SG_SEG_CNT,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = lpfc_hba_attrs,
@@ -1482,7 +1481,6 @@ struct scsi_host_template lpfc_vport_template = {
        .sg_tablesize           = LPFC_DEFAULT_SG_SEG_CNT,
        .cmd_per_lun            = LPFC_CMD_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .shost_attrs            = lpfc_vport_attrs,
        .max_sectors            = 0xFFFF,
 };
index a035001f44386a36e49abcd3d292fb31239cf85e..b12ad7c7c6736908419987896a2402898ba2620e 100644 (file)
@@ -402,7 +402,6 @@ static struct scsi_host_template mac53c94_template = {
        .sg_tablesize   = SG_ALL,
        .cmd_per_lun    = 1,
        .use_clustering = DISABLE_CLUSTERING,
-       .use_sg_chaining = ENABLE_SG_CHAINING,
 };
 
 static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *match)
index 765c24d2bc3842d54da9ffcc214cff782d46eaaa..4d59ae8491a4edac9f6fae0138202e639ee82b93 100644 (file)
@@ -4490,7 +4490,6 @@ static struct scsi_host_template megaraid_template = {
        .sg_tablesize                   = MAX_SGLIST,
        .cmd_per_lun                    = DEF_CMD_PER_LUN,
        .use_clustering                 = ENABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
        .eh_abort_handler               = megaraid_abort,
        .eh_device_reset_handler        = megaraid_reset,
        .eh_bus_reset_handler           = megaraid_reset,
index 24e32e446e76048ed461c105539e730a9376ad98..6db77c00e3eed4b802eeab7b9ec662194522d526 100644 (file)
@@ -361,7 +361,6 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_host_reset_handler          = megaraid_reset_handler,
        .change_queue_depth             = megaraid_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
        .sdev_attrs                     = megaraid_sdev_attrs,
        .shost_attrs                    = megaraid_shost_attrs,
 };
index d7ec921865c4fdf4a911fd6c46f97e6b12ff9cd5..672c759ac24d7719c3371c191d572e25bd8c4d4f 100644 (file)
@@ -1192,7 +1192,6 @@ static struct scsi_host_template megasas_template = {
        .eh_timed_out = megasas_reset_timer,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
-       .use_sg_chaining = ENABLE_SG_CHAINING,
 };
 
 /**
index 7470ff39ab22f59bd09e8140ba42811730b50230..651d09b08f2a22eb6283da21830736271d1d4cd8 100644 (file)
@@ -1843,7 +1843,6 @@ static struct scsi_host_template mesh_template = {
        .sg_tablesize                   = SG_ALL,
        .cmd_per_lun                    = 2,
        .use_clustering                 = DISABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
 };
 
 static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
index c02771aa6c9b4d76d6abc52c509ec9c0327b83f3..c5ebf018b378fc3d026b3bb02eda29f8731be27a 100644 (file)
@@ -4967,7 +4967,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
                             sizeof(cp->sense_buf)));
 
                if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
-                       u_char * p = (u_char*) & cmd->sense_buffer;
+                       u_char *p = cmd->sense_buffer;
                        int i;
                        PRINT_ADDR(cmd, "sense data:");
                        for (i=0; i<14; i++) printk (" %x", *p++);
index 28161dc95e0d7107613933da5186e50f265a0ded..7fed35372150afe68d619d61d4faa4a2a4588437 100644 (file)
@@ -281,7 +281,6 @@ static struct scsi_host_template nsp32_template = {
        .cmd_per_lun                    = 1,
        .this_id                        = NSP32_HOST_SCSIID,
        .use_clustering                 = DISABLE_CLUSTERING,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
        .eh_abort_handler               = nsp32_eh_abort,
        .eh_bus_reset_handler           = nsp32_eh_bus_reset,
        .eh_host_reset_handler          = nsp32_eh_host_reset,
index 969b9387a0c370c8990ff2608d1238441df5fa94..3454a57147496cddc1d012699fbd8334b8e8e2e8 100644 (file)
@@ -692,7 +692,6 @@ static struct scsi_host_template sym53c500_driver_template = {
      .sg_tablesize             = 32,
      .cmd_per_lun              = 1,
      .use_clustering           = ENABLE_CLUSTERING,
-     .use_sg_chaining          = ENABLE_SG_CHAINING,
      .shost_attrs              = SYM53C500_shost_attrs
 };
 
index c94906abfee353137b4483dbcfcc2346cc4aeab9..68c0d09ffe786fe6416f69e948fd0a82e85d5e28 100644 (file)
@@ -4204,7 +4204,6 @@ static struct scsi_host_template qla1280_driver_template = {
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 
index aba1e6d480669ff6e9f932e55e6364f397d050df..3954ed2d7b517acbd183f30049625bf43a3750b2 100644 (file)
@@ -131,7 +131,6 @@ static struct scsi_host_template qla2x00_driver_template = {
        .this_id                = -1,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .sg_tablesize           = SG_ALL,
 
        /*
@@ -163,7 +162,6 @@ struct scsi_host_template qla24xx_driver_template = {
        .this_id                = -1,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .sg_tablesize           = SG_ALL,
 
        .max_sectors            = 0xFFFF,
index d3f86646cb088b0fecbbd9edcd0b26c8b51bebd1..2e2b9fedffcc7c763b1f1d8f70df0faa38e27f61 100644 (file)
@@ -94,7 +94,6 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .this_id                = -1,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .sg_tablesize           = SG_ALL,
 
        .max_sectors            = 0xFFFF,
index 1769f965eedf496e9e0602365220641c5caa2fd1..1e874f1fb5c64a403fd6e7da8365edce51b929df 100644 (file)
@@ -197,7 +197,6 @@ static struct scsi_host_template qlogicfas_driver_template = {
        .sg_tablesize           = SG_ALL,
        .cmd_per_lun            = 1,
        .use_clustering         = DISABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 static __init int qlogicfas_init(void)
index 1a9fba6a9f92ac7ad60d05f1923f8fb45ccca574..b35d19472caa080a7a8614a8e211216b001e8f62 100644 (file)
@@ -757,7 +757,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
                                "Notifying upper driver of completion "
                                "(result %x)\n", cmd->result));
 
-       good_bytes = cmd->request_bufflen;
+       good_bytes = scsi_bufflen(cmd);
         if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
                drv = scsi_cmd_to_driver(cmd);
                if (drv->done)
index 82c06f0a9d0201ae42deb14bec2f2f0f4a239fa9..1541c174937ac81017502253116baeda7350f7c5 100644 (file)
@@ -280,6 +280,8 @@ static int resp_write(struct scsi_cmnd * SCpnt, unsigned long long lba,
                      unsigned int num, struct sdebug_dev_info * devip);
 static int resp_report_luns(struct scsi_cmnd * SCpnt,
                            struct sdebug_dev_info * devip);
+static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+                           unsigned int num, struct sdebug_dev_info *devip);
 static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
                                 int arr_len);
 static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
@@ -311,12 +313,48 @@ static void sdebug_max_tgts_luns(void);
 static struct device pseudo_primary;
 static struct bus_type pseudo_lld_bus;
 
+static void get_data_transfer_info(unsigned char *cmd,
+                                  unsigned long long *lba, unsigned int *num)
+{
+       int i;
+
+       switch (*cmd) {
+       case WRITE_16:
+       case READ_16:
+               for (*lba = 0, i = 0; i < 8; ++i) {
+                       if (i > 0)
+                               *lba <<= 8;
+                       *lba += cmd[2 + i];
+               }
+               *num = cmd[13] + (cmd[12] << 8) +
+                       (cmd[11] << 16) + (cmd[10] << 24);
+               break;
+       case WRITE_12:
+       case READ_12:
+               *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+               *num = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
+               break;
+       case WRITE_10:
+       case READ_10:
+       case XDWRITEREAD_10:
+               *lba = cmd[5] + (cmd[4] << 8) + (cmd[3] << 16) + (cmd[2] << 24);
+               *num = cmd[8] + (cmd[7] << 8);
+               break;
+       case WRITE_6:
+       case READ_6:
+               *lba = cmd[3] + (cmd[2] << 8) + ((cmd[1] & 0x1f) << 16);
+               *num = (0 == cmd[4]) ? 256 : cmd[4];
+               break;
+       default:
+               break;
+       }
+}
 
 static
 int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 {
        unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
-       int len, k, j;
+       int len, k;
        unsigned int num;
        unsigned long long lba;
        int errsts = 0;
@@ -452,28 +490,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
                        break;
                if (scsi_debug_fake_rw)
                        break;
-               if ((*cmd) == READ_16) {
-                       for (lba = 0, j = 0; j < 8; ++j) {
-                               if (j > 0)
-                                       lba <<= 8;
-                               lba += cmd[2 + j];
-                       }
-                       num = cmd[13] + (cmd[12] << 8) +
-                               (cmd[11] << 16) + (cmd[10] << 24);
-               } else if ((*cmd) == READ_12) {
-                       lba = cmd[5] + (cmd[4] << 8) +
-                               (cmd[3] << 16) + (cmd[2] << 24);
-                       num = cmd[9] + (cmd[8] << 8) +
-                               (cmd[7] << 16) + (cmd[6] << 24);
-               } else if ((*cmd) == READ_10) {
-                       lba = cmd[5] + (cmd[4] << 8) +
-                               (cmd[3] << 16) + (cmd[2] << 24);
-                       num = cmd[8] + (cmd[7] << 8);
-               } else {        /* READ (6) */
-                       lba = cmd[3] + (cmd[2] << 8) +
-                               ((cmd[1] & 0x1f) << 16);
-                       num = (0 == cmd[4]) ? 256 : cmd[4];
-               }
+               get_data_transfer_info(cmd, &lba, &num);
                errsts = resp_read(SCpnt, lba, num, devip);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
@@ -500,28 +517,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
                        break;
                if (scsi_debug_fake_rw)
                        break;
-               if ((*cmd) == WRITE_16) {
-                       for (lba = 0, j = 0; j < 8; ++j) {
-                               if (j > 0)
-                                       lba <<= 8;
-                               lba += cmd[2 + j];
-                       }
-                       num = cmd[13] + (cmd[12] << 8) +
-                               (cmd[11] << 16) + (cmd[10] << 24);
-               } else if ((*cmd) == WRITE_12) {
-                       lba = cmd[5] + (cmd[4] << 8) +
-                               (cmd[3] << 16) + (cmd[2] << 24);
-                       num = cmd[9] + (cmd[8] << 8) +
-                               (cmd[7] << 16) + (cmd[6] << 24);
-               } else if ((*cmd) == WRITE_10) {
-                       lba = cmd[5] + (cmd[4] << 8) +
-                               (cmd[3] << 16) + (cmd[2] << 24);
-                       num = cmd[8] + (cmd[7] << 8);
-               } else {        /* WRITE (6) */
-                       lba = cmd[3] + (cmd[2] << 8) +
-                               ((cmd[1] & 0x1f) << 16);
-                       num = (0 == cmd[4]) ? 256 : cmd[4];
-               }
+               get_data_transfer_info(cmd, &lba, &num);
                errsts = resp_write(SCpnt, lba, num, devip);
                if (inj_recovered && (0 == errsts)) {
                        mk_sense_buffer(devip, RECOVERED_ERROR,
@@ -549,6 +545,28 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
        case WRITE_BUFFER:
                errsts = check_readiness(SCpnt, 1, devip);
                break;
+       case XDWRITEREAD_10:
+               if (!scsi_bidi_cmnd(SCpnt)) {
+                       mk_sense_buffer(devip, ILLEGAL_REQUEST,
+                                       INVALID_FIELD_IN_CDB, 0);
+                       errsts = check_condition_result;
+                       break;
+               }
+
+               errsts = check_readiness(SCpnt, 0, devip);
+               if (errsts)
+                       break;
+               if (scsi_debug_fake_rw)
+                       break;
+               get_data_transfer_info(cmd, &lba, &num);
+               errsts = resp_read(SCpnt, lba, num, devip);
+               if (errsts)
+                       break;
+               errsts = resp_write(SCpnt, lba, num, devip);
+               if (errsts)
+                       break;
+               errsts = resp_xdwriteread(SCpnt, lba, num, devip);
+               break;
        default:
                if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                        printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
@@ -601,18 +619,18 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
        int k, req_len, act_len, len, active;
        void * kaddr;
        void * kaddr_off;
-       struct scatterlist * sg;
+       struct scatterlist *sg;
+       struct scsi_data_buffer *sdb = scsi_in(scp);
 
-       if (0 == scsi_bufflen(scp))
+       if (!sdb->length)
                return 0;
-       if (NULL == scsi_sglist(scp))
+       if (!sdb->table.sgl)
                return (DID_ERROR << 16);
-       if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||
-             (scp->sc_data_direction == DMA_FROM_DEVICE)))
+       if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
                return (DID_ERROR << 16);
        active = 1;
        req_len = act_len = 0;
-       scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) {
+       for_each_sg(sdb->table.sgl, sg, sdb->table.nents, k) {
                if (active) {
                        kaddr = (unsigned char *)
                                kmap_atomic(sg_page(sg), KM_USER0);
@@ -630,10 +648,10 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
                }
                req_len += sg->length;
        }
-       if (scsi_get_resid(scp))
-               scsi_set_resid(scp, scsi_get_resid(scp) - act_len);
+       if (sdb->resid)
+               sdb->resid -= act_len;
        else
-               scsi_set_resid(scp, req_len - act_len);
+               sdb->resid = req_len - act_len;
        return 0;
 }
 
@@ -650,8 +668,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
                return 0;
        if (NULL == scsi_sglist(scp))
                return -1;
-       if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||
-             (scp->sc_data_direction == DMA_TO_DEVICE)))
+       if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_TO_DEVICE))
                return -1;
        req_len = fin = 0;
        scsi_for_each_sg(scp, sg, scsi_sg_count(scp), k) {
@@ -1956,6 +1973,50 @@ static int resp_report_luns(struct scsi_cmnd * scp,
                                    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
 }
 
+static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
+                           unsigned int num, struct sdebug_dev_info *devip)
+{
+       int i, j, ret = -1;
+       unsigned char *kaddr, *buf;
+       unsigned int offset;
+       struct scatterlist *sg;
+       struct scsi_data_buffer *sdb = scsi_in(scp);
+
+       /* better not to use temporary buffer. */
+       buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
+       if (!buf)
+               return ret;
+
+       offset = 0;
+       scsi_for_each_sg(scp, sg, scsi_sg_count(scp), i) {
+               kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+               if (!kaddr)
+                       goto out;
+
+               memcpy(buf + offset, kaddr + sg->offset, sg->length);
+               offset += sg->length;
+               kunmap_atomic(kaddr, KM_USER0);
+       }
+
+       offset = 0;
+       for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
+               kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+               if (!kaddr)
+                       goto out;
+
+               for (j = 0; j < sg->length; j++)
+                       *(kaddr + sg->offset + j) ^= *(buf + offset + j);
+
+               offset += sg->length;
+               kunmap_atomic(kaddr, KM_USER0);
+       }
+       ret = 0;
+out:
+       kfree(buf);
+
+       return ret;
+}
+
 /* When timer goes off this function is called. */
 static void timer_intr_handler(unsigned long indx)
 {
@@ -1989,6 +2050,7 @@ static int scsi_debug_slave_alloc(struct scsi_device * sdp)
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
                       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
+       set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
        return 0;
 }
 
index 547e85aa414f2b06a27a5b298e917c456e472f60..045a0868fc7b4540ac53676206ab1f5136355f13 100644 (file)
@@ -617,29 +617,27 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
        ses->cmd_len = scmd->cmd_len;
        memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
        ses->data_direction = scmd->sc_data_direction;
-       ses->bufflen = scmd->request_bufflen;
-       ses->buffer = scmd->request_buffer;
-       ses->use_sg = scmd->use_sg;
-       ses->resid = scmd->resid;
+       ses->sdb = scmd->sdb;
+       ses->next_rq = scmd->request->next_rq;
        ses->result = scmd->result;
 
+       memset(&scmd->sdb, 0, sizeof(scmd->sdb));
+       scmd->request->next_rq = NULL;
+
        if (sense_bytes) {
-               scmd->request_bufflen = min_t(unsigned,
-                                      SCSI_SENSE_BUFFERSIZE, sense_bytes);
+               scmd->sdb.length = min_t(unsigned, SCSI_SENSE_BUFFERSIZE,
+                                        sense_bytes);
                sg_init_one(&ses->sense_sgl, scmd->sense_buffer,
-                                                      scmd->request_bufflen);
-               scmd->request_buffer = &ses->sense_sgl;
+                           scmd->sdb.length);
+               scmd->sdb.table.sgl = &ses->sense_sgl;
                scmd->sc_data_direction = DMA_FROM_DEVICE;
-               scmd->use_sg = 1;
+               scmd->sdb.table.nents = 1;
                memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
                scmd->cmnd[0] = REQUEST_SENSE;
-               scmd->cmnd[4] = scmd->request_bufflen;
+               scmd->cmnd[4] = scmd->sdb.length;
                scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
        } else {
-               scmd->request_buffer = NULL;
-               scmd->request_bufflen = 0;
                scmd->sc_data_direction = DMA_NONE;
-               scmd->use_sg = 0;
                if (cmnd) {
                        memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
                        memcpy(scmd->cmnd, cmnd, cmnd_size);
@@ -676,10 +674,8 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
        scmd->cmd_len = ses->cmd_len;
        memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
        scmd->sc_data_direction = ses->data_direction;
-       scmd->request_bufflen = ses->bufflen;
-       scmd->request_buffer = ses->buffer;
-       scmd->use_sg = ses->use_sg;
-       scmd->resid = ses->resid;
+       scmd->sdb = ses->sdb;
+       scmd->request->next_rq = ses->next_rq;
        scmd->result = ses->result;
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
@@ -1700,8 +1696,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
     
        scmd->scsi_done         = scsi_reset_provider_done_command;
-       scmd->request_buffer            = NULL;
-       scmd->request_bufflen           = 0;
+       memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 
        scmd->cmd_len                   = 0;
 
index 7c4c889c5221e09ed9cb00380c5c3053256c8545..b12fb310e3999af497c21778b62f40c46892e8fd 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/bio.h>
+#include <linux/bitops.h>
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/kernel.h>
 #define SG_MEMPOOL_NR          ARRAY_SIZE(scsi_sg_pools)
 #define SG_MEMPOOL_SIZE                2
 
-/*
- * The maximum number of SG segments that we will put inside a scatterlist
- * (unless chaining is used). Should ideally fit inside a single page, to
- * avoid a higher order allocation.
- */
-#define SCSI_MAX_SG_SEGMENTS   128
-
 struct scsi_host_sg_pool {
        size_t          size;
        char            *name;
@@ -48,22 +42,31 @@ struct scsi_host_sg_pool {
        mempool_t       *pool;
 };
 
-#define SP(x) { x, "sgpool-" #x }
+#define SP(x) { x, "sgpool-" __stringify(x) }
+#if (SCSI_MAX_SG_SEGMENTS < 32)
+#error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater)
+#endif
 static struct scsi_host_sg_pool scsi_sg_pools[] = {
        SP(8),
        SP(16),
-#if (SCSI_MAX_SG_SEGMENTS > 16)
-       SP(32),
 #if (SCSI_MAX_SG_SEGMENTS > 32)
-       SP(64),
+       SP(32),
 #if (SCSI_MAX_SG_SEGMENTS > 64)
+       SP(64),
+#if (SCSI_MAX_SG_SEGMENTS > 128)
        SP(128),
+#if (SCSI_MAX_SG_SEGMENTS > 256)
+#error SCSI_MAX_SG_SEGMENTS is too large (256 MAX)
+#endif
 #endif
 #endif
 #endif
+       SP(SCSI_MAX_SG_SEGMENTS)
 };
 #undef SP
 
+static struct kmem_cache *scsi_bidi_sdb_cache;
+
 static void scsi_run_queue(struct request_queue *q);
 
 /*
@@ -440,7 +443,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async);
 static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
 {
        cmd->serial_number = 0;
-       cmd->resid = 0;
+       scsi_set_resid(cmd, 0);
        memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
        if (cmd->cmd_len == 0)
                cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
@@ -690,42 +693,16 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
        return NULL;
 }
 
-/*
- * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit
- * is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
- */
-#define SCSI_MAX_SG_CHAIN_SEGMENTS     2048
-
 static inline unsigned int scsi_sgtable_index(unsigned short nents)
 {
        unsigned int index;
 
-       switch (nents) {
-       case 1 ... 8:
+       BUG_ON(nents > SCSI_MAX_SG_SEGMENTS);
+
+       if (nents <= 8)
                index = 0;
-               break;
-       case 9 ... 16:
-               index = 1;
-               break;
-#if (SCSI_MAX_SG_SEGMENTS > 16)
-       case 17 ... 32:
-               index = 2;
-               break;
-#if (SCSI_MAX_SG_SEGMENTS > 32)
-       case 33 ... 64:
-               index = 3;
-               break;
-#if (SCSI_MAX_SG_SEGMENTS > 64)
-       case 65 ... 128:
-               index = 4;
-               break;
-#endif
-#endif
-#endif
-       default:
-               printk(KERN_ERR "scsi: bad segment count=%d\n", nents);
-               BUG();
-       }
+       else
+               index = get_count_order(nents) - 3;
 
        return index;
 }
@@ -746,31 +723,27 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
        return mempool_alloc(sgp->pool, gfp_mask);
 }
 
-int scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
+                             gfp_t gfp_mask)
 {
        int ret;
 
-       BUG_ON(!cmd->use_sg);
+       BUG_ON(!nents);
 
-       ret = __sg_alloc_table(&cmd->sg_table, cmd->use_sg,
-                              SCSI_MAX_SG_SEGMENTS, gfp_mask, scsi_sg_alloc);
+       ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS,
+                              gfp_mask, scsi_sg_alloc);
        if (unlikely(ret))
-               __sg_free_table(&cmd->sg_table, SCSI_MAX_SG_SEGMENTS,
+               __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS,
                                scsi_sg_free);
 
-       cmd->request_buffer = cmd->sg_table.sgl;
        return ret;
 }
 
-EXPORT_SYMBOL(scsi_alloc_sgtable);
-
-void scsi_free_sgtable(struct scsi_cmnd *cmd)
+static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
 {
-       __sg_free_table(&cmd->sg_table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
+       __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
 }
 
-EXPORT_SYMBOL(scsi_free_sgtable);
-
 /*
  * Function:    scsi_release_buffers()
  *
@@ -788,17 +761,49 @@ EXPORT_SYMBOL(scsi_free_sgtable);
  *             the scatter-gather table, and potentially any bounce
  *             buffers.
  */
-static void scsi_release_buffers(struct scsi_cmnd *cmd)
+void scsi_release_buffers(struct scsi_cmnd *cmd)
+{
+       if (cmd->sdb.table.nents)
+               scsi_free_sgtable(&cmd->sdb);
+
+       memset(&cmd->sdb, 0, sizeof(cmd->sdb));
+
+       if (scsi_bidi_cmnd(cmd)) {
+               struct scsi_data_buffer *bidi_sdb =
+                       cmd->request->next_rq->special;
+               scsi_free_sgtable(bidi_sdb);
+               kmem_cache_free(scsi_bidi_sdb_cache, bidi_sdb);
+               cmd->request->next_rq->special = NULL;
+       }
+}
+EXPORT_SYMBOL(scsi_release_buffers);
+
+/*
+ * Bidi commands Must be complete as a whole, both sides at once.
+ * If part of the bytes were written and lld returned
+ * scsi_in()->resid and/or scsi_out()->resid this information will be left
+ * in req->data_len and req->next_rq->data_len. The upper-layer driver can
+ * decide what to do with this information.
+ */
+void scsi_end_bidi_request(struct scsi_cmnd *cmd)
 {
-       if (cmd->use_sg)
-               scsi_free_sgtable(cmd);
+       struct request *req = cmd->request;
+       unsigned int dlen = req->data_len;
+       unsigned int next_dlen = req->next_rq->data_len;
+
+       req->data_len = scsi_out(cmd)->resid;
+       req->next_rq->data_len = scsi_in(cmd)->resid;
+
+       /* The req and req->next_rq have not been completed */
+       BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen));
+
+       scsi_release_buffers(cmd);
 
        /*
-        * Zero these out.  They now point to freed memory, and it is
-        * dangerous to hang onto the pointers.
+        * This will goose the queue request function at the end, so we don't
+        * need to worry about launching another command.
         */
-       cmd->request_buffer = NULL;
-       cmd->request_bufflen = 0;
+       scsi_next_command(cmd);
 }
 
 /*
@@ -832,7 +837,7 @@ static void scsi_release_buffers(struct scsi_cmnd *cmd)
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
-       int this_count = cmd->request_bufflen;
+       int this_count = scsi_bufflen(cmd);
        struct request_queue *q = cmd->device->request_queue;
        struct request *req = cmd->request;
        int clear_errors = 1;
@@ -840,8 +845,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        int sense_valid = 0;
        int sense_deferred = 0;
 
-       scsi_release_buffers(cmd);
-
        if (result) {
                sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
                if (sense_valid)
@@ -864,9 +867,17 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                req->sense_len = len;
                        }
                }
-               req->data_len = cmd->resid;
+               if (scsi_bidi_cmnd(cmd)) {
+                       /* will also release_buffers */
+                       scsi_end_bidi_request(cmd);
+                       return;
+               }
+               req->data_len = scsi_get_resid(cmd);
        }
 
+       BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */
+       scsi_release_buffers(cmd);
+
        /*
         * Next deal with any sectors which we were able to correctly
         * handle.
@@ -874,7 +885,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, "
                                      "%d bytes done.\n",
                                      req->nr_sectors, good_bytes));
-       SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg));
 
        if (clear_errors)
                req->errors = 0;
@@ -991,52 +1001,80 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        scsi_end_request(cmd, -EIO, this_count, !result);
 }
 
-/*
- * Function:    scsi_init_io()
- *
- * Purpose:     SCSI I/O initialize function.
- *
- * Arguments:   cmd   - Command descriptor we wish to initialize
- *
- * Returns:     0 on success
- *             BLKPREP_DEFER if the failure is retryable
- */
-static int scsi_init_io(struct scsi_cmnd *cmd)
+static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
+                            gfp_t gfp_mask)
 {
-       struct request     *req = cmd->request;
-       int                count;
-
-       /*
-        * We used to not use scatter-gather for single segment request,
-        * but now we do (it makes highmem I/O easier to support without
-        * kmapping pages)
-        */
-       cmd->use_sg = req->nr_phys_segments;
+       int count;
 
        /*
         * If sg table allocation fails, requeue request later.
         */
-       if (unlikely(scsi_alloc_sgtable(cmd, GFP_ATOMIC))) {
-               scsi_unprep_request(req);
+       if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments,
+                                       gfp_mask))) {
                return BLKPREP_DEFER;
        }
 
        req->buffer = NULL;
        if (blk_pc_request(req))
-               cmd->request_bufflen = req->data_len;
+               sdb->length = req->data_len;
        else
-               cmd->request_bufflen = req->nr_sectors << 9;
+               sdb->length = req->nr_sectors << 9;
 
        /* 
         * Next, walk the list, and fill in the addresses and sizes of
         * each segment.
         */
-       count = blk_rq_map_sg(req->q, req, cmd->request_buffer);
-       BUG_ON(count > cmd->use_sg);
-       cmd->use_sg = count;
+       count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
+       BUG_ON(count > sdb->table.nents);
+       sdb->table.nents = count;
        return BLKPREP_OK;
 }
 
+/*
+ * Function:    scsi_init_io()
+ *
+ * Purpose:     SCSI I/O initialize function.
+ *
+ * Arguments:   cmd   - Command descriptor we wish to initialize
+ *
+ * Returns:     0 on success
+ *             BLKPREP_DEFER if the failure is retryable
+ *             BLKPREP_KILL if the failure is fatal
+ */
+int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+{
+       int error = scsi_init_sgtable(cmd->request, &cmd->sdb, gfp_mask);
+       if (error)
+               goto err_exit;
+
+       if (blk_bidi_rq(cmd->request)) {
+               struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc(
+                       scsi_bidi_sdb_cache, GFP_ATOMIC);
+               if (!bidi_sdb) {
+                       error = BLKPREP_DEFER;
+                       goto err_exit;
+               }
+
+               cmd->request->next_rq->special = bidi_sdb;
+               error = scsi_init_sgtable(cmd->request->next_rq, bidi_sdb,
+                                                                   GFP_ATOMIC);
+               if (error)
+                       goto err_exit;
+       }
+
+       return BLKPREP_OK ;
+
+err_exit:
+       scsi_release_buffers(cmd);
+       if (error == BLKPREP_KILL)
+               scsi_put_command(cmd);
+       else /* BLKPREP_DEFER */
+               scsi_unprep_request(cmd->request);
+
+       return error;
+}
+EXPORT_SYMBOL(scsi_init_io);
+
 static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
                struct request *req)
 {
@@ -1081,16 +1119,14 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 
                BUG_ON(!req->nr_phys_segments);
 
-               ret = scsi_init_io(cmd);
+               ret = scsi_init_io(cmd, GFP_ATOMIC);
                if (unlikely(ret))
                        return ret;
        } else {
                BUG_ON(req->data_len);
                BUG_ON(req->data);
 
-               cmd->request_bufflen = 0;
-               cmd->request_buffer = NULL;
-               cmd->use_sg = 0;
+               memset(&cmd->sdb, 0, sizeof(cmd->sdb));
                req->buffer = NULL;
        }
 
@@ -1132,7 +1168,7 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
        if (unlikely(!cmd))
                return BLKPREP_DEFER;
 
-       return scsi_init_io(cmd);
+       return scsi_init_io(cmd, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(scsi_setup_fs_cmnd);
 
@@ -1542,20 +1578,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
         * this limit is imposed by hardware restrictions
         */
        blk_queue_max_hw_segments(q, shost->sg_tablesize);
-
-       /*
-        * In the future, sg chaining support will be mandatory and this
-        * ifdef can then go away. Right now we don't have all archs
-        * converted, so better keep it safe.
-        */
-#ifdef ARCH_HAS_SG_CHAIN
-       if (shost->use_sg_chaining)
-               blk_queue_max_phys_segments(q, SCSI_MAX_SG_CHAIN_SEGMENTS);
-       else
-               blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS);
-#else
-       blk_queue_max_phys_segments(q, SCSI_MAX_SG_SEGMENTS);
-#endif
+       blk_queue_max_phys_segments(q, SCSI_MAX_SG_CHAIN_SEGMENTS);
 
        blk_queue_max_sectors(q, shost->max_sectors);
        blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
@@ -1654,6 +1677,14 @@ int __init scsi_init_queue(void)
                return -ENOMEM;
        }
 
+       scsi_bidi_sdb_cache = kmem_cache_create("scsi_bidi_sdb",
+                                       sizeof(struct scsi_data_buffer),
+                                       0, 0, NULL);
+       if (!scsi_bidi_sdb_cache) {
+               printk(KERN_ERR "SCSI: can't init scsi bidi sdb cache\n");
+               goto cleanup_io_context;
+       }
+
        for (i = 0; i < SG_MEMPOOL_NR; i++) {
                struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
                int size = sgp->size * sizeof(struct scatterlist);
@@ -1663,6 +1694,7 @@ int __init scsi_init_queue(void)
                if (!sgp->slab) {
                        printk(KERN_ERR "SCSI: can't init sg slab %s\n",
                                        sgp->name);
+                       goto cleanup_bidi_sdb;
                }
 
                sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
@@ -1670,10 +1702,25 @@ int __init scsi_init_queue(void)
                if (!sgp->pool) {
                        printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
                                        sgp->name);
+                       goto cleanup_bidi_sdb;
                }
        }
 
        return 0;
+
+cleanup_bidi_sdb:
+       for (i = 0; i < SG_MEMPOOL_NR; i++) {
+               struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
+               if (sgp->pool)
+                       mempool_destroy(sgp->pool);
+               if (sgp->slab)
+                       kmem_cache_destroy(sgp->slab);
+       }
+       kmem_cache_destroy(scsi_bidi_sdb_cache);
+cleanup_io_context:
+       kmem_cache_destroy(scsi_io_context_cache);
+
+       return -ENOMEM;
 }
 
 void scsi_exit_queue(void)
@@ -1681,6 +1728,7 @@ void scsi_exit_queue(void)
        int i;
 
        kmem_cache_destroy(scsi_io_context_cache);
+       kmem_cache_destroy(scsi_bidi_sdb_cache);
 
        for (i = 0; i < SG_MEMPOOL_NR; i++) {
                struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
index 01e03f3f6ffa39ea7240dfe355ddd7edf5a5981c..91630baea532e0656883ee2c427b21467a9bf629 100644 (file)
@@ -331,8 +331,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
 
        scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag);
 
-       if (scsi_sglist(cmd))
-               scsi_free_sgtable(cmd);
+       scsi_release_buffers(cmd);
 
        queue_work(scsi_tgtd, &tcmd->work);
 }
@@ -353,25 +352,6 @@ static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd)
        return 0;
 }
 
-static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask)
-{
-       struct request *rq = cmd->request;
-       int count;
-
-       cmd->use_sg = rq->nr_phys_segments;
-       if (scsi_alloc_sgtable(cmd, gfp_mask))
-               return -ENOMEM;
-
-       cmd->request_bufflen = rq->data_len;
-
-       dprintk("cmd %p cnt %d %lu\n", cmd, scsi_sg_count(cmd),
-               rq_data_dir(rq));
-       count = blk_rq_map_sg(rq->q, rq, scsi_sglist(cmd));
-       BUG_ON(count > cmd->use_sg);
-       cmd->use_sg = count;
-       return 0;
-}
-
 /* TODO: test this crap and replace bio_map_user with new interface maybe */
 static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
                               unsigned long uaddr, unsigned int len, int rw)
@@ -397,9 +377,11 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd,
        }
 
        tcmd->bio = rq->bio;
-       err = scsi_tgt_init_cmd(cmd, GFP_KERNEL);
-       if (err)
+       err = scsi_init_io(cmd, GFP_KERNEL);
+       if (err) {
+               scsi_release_buffers(cmd);
                goto unmap_rq;
+       }
 
        return 0;
 
index 24eba3118b5a415e9b76c0d5a668a72fab58d303..51a5557f42dda472fd67bb0b7352ddb7ff1d3c7a 100644 (file)
@@ -519,7 +519,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                SCpnt->cmnd[4] = (unsigned char) this_count;
                SCpnt->cmnd[5] = 0;
        }
-       SCpnt->request_bufflen = this_count * sdp->sector_size;
+       SCpnt->sdb.length = this_count * sdp->sector_size;
 
        /*
         * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -926,7 +926,7 @@ static struct block_device_operations sd_fops = {
 static int sd_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
-       unsigned int xfer_size = SCpnt->request_bufflen;
+       unsigned int xfer_size = scsi_bufflen(SCpnt);
        unsigned int good_bytes = result ? 0 : xfer_size;
        u64 start_lba = SCpnt->request->sector;
        u64 bad_lba;
index d4ebe8c67ba92b901298f5d4dda08c4bd69507b0..26cfc56c7091e6d5cf388eba98c456cc1a6ab8c8 100644 (file)
 
 struct ip22_hostdata {
        struct WD33C93_hostdata wh;
-       struct hpc_data {
-               dma_addr_t      dma;
-               void            *cpu;
-       } hd;
+       dma_addr_t dma;
+       void *cpu;
+       struct device *dev;
 };
 
 #define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata))
@@ -46,6 +45,11 @@ struct hpc_chunk {
        u32 _padding;   /* align to quadword boundary */
 };
 
+/* space for hpc dma descriptors */
+#define HPC_DMA_SIZE   PAGE_SIZE
+
+#define DMA_DIR(d)   ((d == DATA_OUT_DIR) ? DMA_TO_DEVICE : DMA_FROM_DEVICE)
+
 static irqreturn_t sgiwd93_intr(int irq, void *dev_id)
 {
        struct Scsi_Host * host = dev_id;
@@ -59,15 +63,17 @@ static irqreturn_t sgiwd93_intr(int irq, void *dev_id)
 }
 
 static inline
-void fill_hpc_entries(struct hpc_chunk *hcp, struct scsi_cmnd *cmd, int datainp)
+void fill_hpc_entries(struct ip22_hostdata *hd, struct scsi_cmnd *cmd, int din)
 {
        unsigned long len = cmd->SCp.this_residual;
        void *addr = cmd->SCp.ptr;
        dma_addr_t physaddr;
        unsigned long count;
+       struct hpc_chunk *hcp;
 
-       physaddr = dma_map_single(NULL, addr, len, cmd->sc_data_direction);
+       physaddr = dma_map_single(hd->dev, addr, len, DMA_DIR(din));
        cmd->SCp.dma_handle = physaddr;
+       hcp = hd->cpu;
 
        while (len) {
                /*
@@ -89,6 +95,9 @@ void fill_hpc_entries(struct hpc_chunk *hcp, struct scsi_cmnd *cmd, int datainp)
         */
        hcp->desc.pbuf = 0;
        hcp->desc.cntinfo = HPCDMA_EOX;
+       dma_cache_sync(hd->dev, hd->cpu,
+                      (unsigned long)(hcp + 1) - (unsigned long)hd->cpu,
+                      DMA_TO_DEVICE);
 }
 
 static int dma_setup(struct scsi_cmnd *cmd, int datainp)
@@ -96,9 +105,8 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp)
        struct ip22_hostdata *hdata = host_to_hostdata(cmd->device->host);
        struct hpc3_scsiregs *hregs =
                (struct hpc3_scsiregs *) cmd->device->host->base;
-       struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu;
 
-       pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
+       pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hdata->cpu);
 
        hdata->wh.dma_dir = datainp;
 
@@ -111,12 +119,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int datainp)
        if (cmd->SCp.ptr == NULL || cmd->SCp.this_residual == 0)
                return 1;
 
-       fill_hpc_entries(hcp, cmd, datainp);
+       fill_hpc_entries(hdata, cmd, datainp);
 
        pr_debug(" HPCGO\n");
 
        /* Start up the HPC. */
-       hregs->ndptr = hdata->hd.dma;
+       hregs->ndptr = hdata->dma;
        if (datainp)
                hregs->ctrl = HPC3_SCTRL_ACTIVE;
        else
@@ -134,6 +142,9 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
        if (!SCpnt)
                return;
 
+       if (SCpnt->SCp.ptr == NULL || SCpnt->SCp.this_residual == 0)
+               return;
+
        hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base;
 
        pr_debug("dma_stop: status<%d> ", status);
@@ -145,8 +156,9 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
                        barrier();
        }
        hregs->ctrl = 0;
-       dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual,
-                        SCpnt->sc_data_direction);
+       dma_unmap_single(hdata->dev, SCpnt->SCp.dma_handle,
+                        SCpnt->SCp.this_residual,
+                        DMA_DIR(hdata->wh.dma_dir));
 
        pr_debug("\n");
 }
@@ -161,22 +173,23 @@ void sgiwd93_reset(unsigned long base)
 }
 EXPORT_SYMBOL_GPL(sgiwd93_reset);
 
-static inline void init_hpc_chain(struct hpc_data *hd)
+static inline void init_hpc_chain(struct ip22_hostdata *hdata)
 {
-       struct hpc_chunk *hcp = (struct hpc_chunk *) hd->cpu;
-       struct hpc_chunk *dma = (struct hpc_chunk *) hd->dma;
+       struct hpc_chunk *hcp = (struct hpc_chunk *)hdata->cpu;
+       dma_addr_t dma = hdata->dma;
        unsigned long start, end;
 
        start = (unsigned long) hcp;
-       end = start + PAGE_SIZE;
+       end = start + HPC_DMA_SIZE;
        while (start < end) {
-               hcp->desc.pnext = (u32) (dma + 1);
+               hcp->desc.pnext = (u32) (dma + sizeof(struct hpc_chunk));
                hcp->desc.cntinfo = HPCDMA_EOX;
-               hcp++; dma++;
+               hcp++;
+               dma += sizeof(struct hpc_chunk);
                start += sizeof(struct hpc_chunk);
        };
        hcp--;
-       hcp->desc.pnext = hd->dma;
+       hcp->desc.pnext = hdata->dma;
 }
 
 static int sgiwd93_bus_reset(struct scsi_cmnd *cmd)
@@ -235,16 +248,17 @@ static int __init sgiwd93_probe(struct platform_device *pdev)
        host->irq = irq;
 
        hdata = host_to_hostdata(host);
-       hdata->hd.cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
-                                          &hdata->hd.dma, GFP_KERNEL);
-       if (!hdata->hd.cpu) {
+       hdata->dev = &pdev->dev;
+       hdata->cpu = dma_alloc_noncoherent(&pdev->dev, HPC_DMA_SIZE,
+                                          &hdata->dma, GFP_KERNEL);
+       if (!hdata->cpu) {
                printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
                       "host %d buffer.\n", unit);
                err = -ENOMEM;
                goto out_put;
        }
 
-       init_hpc_chain(&hdata->hd);
+       init_hpc_chain(hdata);
 
        regs.SASR = wdregs + 3;
        regs.SCMD = wdregs + 7;
@@ -274,7 +288,7 @@ static int __init sgiwd93_probe(struct platform_device *pdev)
 out_irq:
        free_irq(irq, host);
 out_free:
-       dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+       dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma);
 out_put:
        scsi_host_put(host);
 out:
@@ -290,7 +304,7 @@ static void __exit sgiwd93_remove(struct platform_device *pdev)
 
        scsi_remove_host(host);
        free_irq(pd->irq, host);
-       dma_free_coherent(&pdev->dev, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+       dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma);
        scsi_host_put(host);
 }
 
index 1fcee16fa36dbd47246b659a2c2dfb1d23daecb9..50ba492502035afe85d0bd62899b02c132022c63 100644 (file)
@@ -231,7 +231,7 @@ out:
 static int sr_done(struct scsi_cmnd *SCpnt)
 {
        int result = SCpnt->result;
-       int this_count = SCpnt->request_bufflen;
+       int this_count = scsi_bufflen(SCpnt);
        int good_bytes = (result == 0 ? this_count : 0);
        int block_sectors = 0;
        long error_sector;
@@ -379,17 +379,18 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
        }
 
        {
-               struct scatterlist *sg = SCpnt->request_buffer;
-               int i, size = 0;
-               for (i = 0; i < SCpnt->use_sg; i++)
-                       size += sg[i].length;
+               struct scatterlist *sg;
+               int i, size = 0, sg_count = scsi_sg_count(SCpnt);
 
-               if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
+               scsi_for_each_sg(SCpnt, sg, sg_count, i)
+                       size += sg->length;
+
+               if (size != scsi_bufflen(SCpnt)) {
                        scmd_printk(KERN_ERR, SCpnt,
                                "mismatch count %d, bytes %d\n",
-                               size, SCpnt->request_bufflen);
-                       if (SCpnt->request_bufflen > size)
-                               SCpnt->request_bufflen = size;
+                               size, scsi_bufflen(SCpnt));
+                       if (scsi_bufflen(SCpnt) > size)
+                               SCpnt->sdb.length = size;
                }
        }
 
@@ -397,12 +398,12 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
         * request doesn't start on hw block boundary, add scatter pads
         */
        if (((unsigned int)rq->sector % (s_size >> 9)) ||
-           (SCpnt->request_bufflen % s_size)) {
+           (scsi_bufflen(SCpnt) % s_size)) {
                scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n");
                goto out;
        }
 
-       this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
+       this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9);
 
 
        SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
@@ -416,7 +417,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq)
 
        if (this_count > 0xffff) {
                this_count = 0xffff;
-               SCpnt->request_bufflen = this_count * s_size;
+               SCpnt->sdb.length = this_count * s_size;
        }
 
        SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
index e3fab3a6aed79f843e44de0720ff3dea485b18b2..72f6d8015358d6f52c967f51876d53cac2597c29 100644 (file)
@@ -1123,7 +1123,6 @@ static struct scsi_host_template driver_template = {
        .this_id                        = -1,
        .sg_tablesize                   = ST_MAX_SG,
        .cmd_per_lun                    = ST_CMD_PER_LUN,
-       .use_sg_chaining                = ENABLE_SG_CHAINING,
 };
 
 static int stex_set_dma_mask(struct pci_dev * pdev)
index 1f6fd16803351f7d67940d864cfdca2148eec3c7..6325901e509342c8e95aae2ce81f35c8bdd11900 100644 (file)
@@ -840,6 +840,5 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun =          1,
        .unchecked_isa_dma =    1,
        .use_clustering =       ENABLE_CLUSTERING,
-       .use_sg_chaining =      ENABLE_SG_CHAINING,
 };
 #include "scsi_module.c"
index 21e926dcdab0bfc73d6bc89d85f7c4d177d5c0ea..d39107b7669bfb22e3fa1e278166dd2c2766616f 100644 (file)
@@ -207,7 +207,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
                        /*
                         *  Bounce back the sense data to user.
                         */
-                       memset(&cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+                       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                        memcpy(cmd->sense_buffer, cp->sns_bbuf,
                               min(SCSI_SENSE_BUFFERSIZE, SYM_SNS_BBUF_LEN));
 #if 0
@@ -1681,7 +1681,6 @@ static struct scsi_host_template sym2_template = {
        .eh_host_reset_handler  = sym53c8xx_eh_host_reset_handler,
        .this_id                = 7,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .max_sectors            = 0xFFFF,
 #ifdef SYM_LINUX_PROC_INFO_SUPPORT
        .proc_info              = sym53c8xx_proc_info,
index 4bc5407f96958598f3a44ca56c8d387a6a86100e..662c00451be443556e32f1bbd930a4c6dcd811bc 100644 (file)
@@ -451,7 +451,6 @@ static struct scsi_host_template driver_template = {
                 .this_id                 = 7,
                 .unchecked_isa_dma       = 1,
                 .use_clustering          = ENABLE_CLUSTERING,
-                .use_sg_chaining         = ENABLE_SG_CHAINING,
                 };
 
 #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)
index 75eca6b22db561e7508d52dd2cb1be70cafdb98f..f385dce8dfbeb16d809a04eaf149edfb25c9cbf6 100644 (file)
@@ -1204,6 +1204,5 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun       = ULTRASTOR_MAX_CMDS_PER_LUN,
        .unchecked_isa_dma = 1,
        .use_clustering    = ENABLE_CLUSTERING,
-       .use_sg_chaining   = ENABLE_SG_CHAINING,
 };
 #include "scsi_module.c"
index b4304ae78527e409bae6ad6334ec68b7199e22b1..c975c01b3a02431000f071116f3b40caffd4f3f8 100644 (file)
@@ -1671,7 +1671,6 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = 1,
        .unchecked_isa_dma      = 1,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
 };
 
 #include "scsi_module.c"
index 178e8c2a8a2feb41f03fd7d16117347647f6247b..0db488624ab1c4983cf481ec637e29a9650bc586 100644 (file)
@@ -415,14 +415,14 @@ static void isd200_set_srb(struct isd200_info *info,
                sg_init_one(&info->sg, buff, bufflen);
 
        srb->sc_data_direction = dir;
-       srb->request_buffer = buff ? &info->sg : NULL;
-       srb->request_bufflen = bufflen;
-       srb->use_sg = buff ? 1 : 0;
+       srb->sdb.table.sgl = buff ? &info->sg : NULL;
+       srb->sdb.length = bufflen;
+       srb->sdb.table.nents = buff ? 1 : 0;
 }
 
 static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen)
 {
-       srb->request_bufflen = bufflen;
+       srb->sdb.length = bufflen;
 }
 
 
index 46754553fdcc4ae06799d7f0a1c9a102c4a6900f..ff97ba924333fccfc7cbb9699753f194d47eda7b 100644 (file)
@@ -49,7 +49,7 @@ static struct dlm_direntry *get_free_de(struct dlm_ls *ls, int len)
        spin_unlock(&ls->ls_recover_list_lock);
 
        if (!found)
-               de = allocate_direntry(ls, len);
+               de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_KERNEL);
        return de;
 }
 
@@ -62,7 +62,7 @@ void dlm_clear_free_entries(struct dlm_ls *ls)
                de = list_entry(ls->ls_recover_list.next, struct dlm_direntry,
                                list);
                list_del(&de->list);
-               free_direntry(de);
+               kfree(de);
        }
        spin_unlock(&ls->ls_recover_list_lock);
 }
@@ -171,7 +171,7 @@ void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen
        }
 
        list_del(&de->list);
-       free_direntry(de);
+       kfree(de);
  out:
        write_unlock(&ls->ls_dirtbl[bucket].lock);
 }
@@ -302,7 +302,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
 
        write_unlock(&ls->ls_dirtbl[bucket].lock);
 
-       de = allocate_direntry(ls, namelen);
+       de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL);
        if (!de)
                return -ENOMEM;
 
@@ -313,7 +313,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name,
        write_lock(&ls->ls_dirtbl[bucket].lock);
        tmp = search_bucket(ls, name, namelen, bucket);
        if (tmp) {
-               free_direntry(de);
+               kfree(de);
                de = tmp;
        } else {
                list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list);
@@ -329,49 +329,47 @@ int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen,
        return get_entry(ls, nodeid, name, namelen, r_nodeid);
 }
 
-/* Copy the names of master rsb's into the buffer provided.
-   Only select names whose dir node is the given nodeid. */
+static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len)
+{
+       struct dlm_rsb *r;
+
+       down_read(&ls->ls_root_sem);
+       list_for_each_entry(r, &ls->ls_root_list, res_root_list) {
+               if (len == r->res_length && !memcmp(name, r->res_name, len)) {
+                       up_read(&ls->ls_root_sem);
+                       return r;
+               }
+       }
+       up_read(&ls->ls_root_sem);
+       return NULL;
+}
+
+/* Find the rsb where we left off (or start again), then send rsb names
+   for rsb's we're master of and whose directory node matches the requesting
+   node.  inbuf is the rsb name last sent, inlen is the name's length */
 
 void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen,
                           char *outbuf, int outlen, int nodeid)
 {
        struct list_head *list;
-       struct dlm_rsb *start_r = NULL, *r = NULL;
-       int offset = 0, start_namelen, error, dir_nodeid;
-       char *start_name;
+       struct dlm_rsb *r;
+       int offset = 0, dir_nodeid;
        uint16_t be_namelen;
 
-       /*
-        * Find the rsb where we left off (or start again)
-        */
-
-       start_namelen = inlen;
-       start_name = inbuf;
-
-       if (start_namelen > 1) {
-               /*
-                * We could also use a find_rsb_root() function here that
-                * searched the ls_root_list.
-                */
-               error = dlm_find_rsb(ls, start_name, start_namelen, R_MASTER,
-                                    &start_r);
-               DLM_ASSERT(!error && start_r,
-                          printk("error %d\n", error););
-               DLM_ASSERT(!list_empty(&start_r->res_root_list),
-                          dlm_print_rsb(start_r););
-               dlm_put_rsb(start_r);
-       }
-
-       /*
-        * Send rsb names for rsb's we're master of and whose directory node
-        * matches the requesting node.
-        */
-
        down_read(&ls->ls_root_sem);
-       if (start_r)
-               list = start_r->res_root_list.next;
-       else
+
+       if (inlen > 1) {
+               r = find_rsb_root(ls, inbuf, inlen);
+               if (!r) {
+                       inbuf[inlen - 1] = '\0';
+                       log_error(ls, "copy_master_names from %d start %d %s",
+                                 nodeid, inlen, inbuf);
+                       goto out;
+               }
+               list = r->res_root_list.next;
+       } else {
                list = ls->ls_root_list.next;
+       }
 
        for (offset = 0; list != &ls->ls_root_list; list = list->next) {
                r = list_entry(list, struct dlm_rsb, res_root_list);
index d2fc2384c3bed34e32b83ed98804d01961eb7d5a..ec61bbaf25dfdae4cc6d56ec7acff1b50e71c4ff 100644 (file)
@@ -570,5 +570,21 @@ static inline int dlm_no_directory(struct dlm_ls *ls)
        return (ls->ls_exflags & DLM_LSFL_NODIR) ? 1 : 0;
 }
 
+int dlm_netlink_init(void);
+void dlm_netlink_exit(void);
+void dlm_timeout_warn(struct dlm_lkb *lkb);
+
+#ifdef CONFIG_DLM_DEBUG
+int dlm_register_debugfs(void);
+void dlm_unregister_debugfs(void);
+int dlm_create_debug_file(struct dlm_ls *ls);
+void dlm_delete_debug_file(struct dlm_ls *ls);
+#else
+static inline int dlm_register_debugfs(void) { return 0; }
+static inline void dlm_unregister_debugfs(void) { }
+static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; }
+static inline void dlm_delete_debug_file(struct dlm_ls *ls) { }
+#endif
+
 #endif                         /* __DLM_INTERNAL_DOT_H__ */
 
index 3915b8e1414623db82bce20d0d4b4c41fc6b9fa3..ff4a198fa6776a325d730748bd3d8b5782cd189a 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -88,7 +88,6 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
 static int receive_extralen(struct dlm_message *ms);
 static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
 static void del_timeout(struct dlm_lkb *lkb);
-void dlm_timeout_warn(struct dlm_lkb *lkb);
 
 /*
  * Lock compatibilty matrix - thanks Steve
@@ -335,7 +334,7 @@ static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len)
 {
        struct dlm_rsb *r;
 
-       r = allocate_rsb(ls, len);
+       r = dlm_allocate_rsb(ls, len);
        if (!r)
                return NULL;
 
@@ -478,7 +477,7 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
        error = _search_rsb(ls, name, namelen, bucket, 0, &tmp);
        if (!error) {
                write_unlock(&ls->ls_rsbtbl[bucket].lock);
-               free_rsb(r);
+               dlm_free_rsb(r);
                r = tmp;
                goto out;
        }
@@ -490,12 +489,6 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
        return error;
 }
 
-int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen,
-                unsigned int flags, struct dlm_rsb **r_ret)
-{
-       return find_rsb(ls, name, namelen, flags, r_ret);
-}
-
 /* This is only called to add a reference when the code already holds
    a valid reference to the rsb, so there's no need for locking. */
 
@@ -519,7 +512,7 @@ static void toss_rsb(struct kref *kref)
        list_move(&r->res_hashchain, &ls->ls_rsbtbl[r->res_bucket].toss);
        r->res_toss_time = jiffies;
        if (r->res_lvbptr) {
-               free_lvb(r->res_lvbptr);
+               dlm_free_lvb(r->res_lvbptr);
                r->res_lvbptr = NULL;
        }
 }
@@ -589,7 +582,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
        uint32_t lkid = 0;
        uint16_t bucket;
 
-       lkb = allocate_lkb(ls);
+       lkb = dlm_allocate_lkb(ls);
        if (!lkb)
                return -ENOMEM;
 
@@ -683,8 +676,8 @@ static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb)
 
                /* for local/process lkbs, lvbptr points to caller's lksb */
                if (lkb->lkb_lvbptr && is_master_copy(lkb))
-                       free_lvb(lkb->lkb_lvbptr);
-               free_lkb(lkb);
+                       dlm_free_lvb(lkb->lkb_lvbptr);
+               dlm_free_lkb(lkb);
                return 1;
        } else {
                write_unlock(&ls->ls_lkbtbl[bucket].lock);
@@ -988,7 +981,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b)
 
                        if (is_master(r))
                                dir_remove(r);
-                       free_rsb(r);
+                       dlm_free_rsb(r);
                        count++;
                } else {
                        write_unlock(&ls->ls_rsbtbl[b].lock);
@@ -1171,7 +1164,7 @@ static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
                        return;
 
                if (!r->res_lvbptr)
-                       r->res_lvbptr = allocate_lvb(r->res_ls);
+                       r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
 
                if (!r->res_lvbptr)
                        return;
@@ -1203,7 +1196,7 @@ static void set_lvb_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb)
                return;
 
        if (!r->res_lvbptr)
-               r->res_lvbptr = allocate_lvb(r->res_ls);
+               r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
 
        if (!r->res_lvbptr)
                return;
@@ -1852,7 +1845,7 @@ static void send_blocking_asts_all(struct dlm_rsb *r, struct dlm_lkb *lkb)
 static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb)
 {
        struct dlm_ls *ls = r->res_ls;
-       int error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid();
+       int i, error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid();
 
        if (rsb_flag(r, RSB_MASTER_UNCERTAIN)) {
                rsb_clear_flag(r, RSB_MASTER_UNCERTAIN);
@@ -1886,7 +1879,7 @@ static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb)
                return 1;
        }
 
-       for (;;) {
+       for (i = 0; i < 2; i++) {
                /* It's possible for dlm_scand to remove an old rsb for
                   this same resource from the toss list, us to create
                   a new one, look up the master locally, and find it
@@ -1900,6 +1893,8 @@ static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb)
                log_debug(ls, "dir_lookup error %d %s", error, r->res_name);
                schedule();
        }
+       if (error && error != -EEXIST)
+               return error;
 
        if (ret_nodeid == our_nodeid) {
                r->res_first_lkid = 0;
@@ -1941,8 +1936,11 @@ static void confirm_master(struct dlm_rsb *r, int error)
                break;
 
        case -EAGAIN:
-               /* the remote master didn't queue our NOQUEUE request;
-                  make a waiting lkb the first_lkid */
+       case -EBADR:
+       case -ENOTBLK:
+               /* the remote request failed and won't be retried (it was
+                  a NOQUEUE, or has been canceled/unlocked); make a waiting
+                  lkb the first_lkid */
 
                r->res_first_lkid = 0;
 
@@ -2108,17 +2106,18 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
        /* an lkb may be waiting for an rsb lookup to complete where the
           lookup was initiated by another lock */
 
-       if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) {
-               if (!list_empty(&lkb->lkb_rsb_lookup)) {
+       if (!list_empty(&lkb->lkb_rsb_lookup)) {
+               if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) {
                        log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id);
                        list_del_init(&lkb->lkb_rsb_lookup);
                        queue_cast(lkb->lkb_resource, lkb,
                                   args->flags & DLM_LKF_CANCEL ?
                                   -DLM_ECANCEL : -DLM_EUNLOCK);
                        unhold_lkb(lkb); /* undoes create_lkb() */
-                       rv = -EBUSY;
-                       goto out;
                }
+               /* caller changes -EBUSY to 0 for CANCEL and FORCEUNLOCK */
+               rv = -EBUSY;
+               goto out;
        }
 
        /* cancel not allowed with another cancel/unlock in progress */
@@ -2986,7 +2985,7 @@ static int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb,
 
        if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
                if (!lkb->lkb_lvbptr)
-                       lkb->lkb_lvbptr = allocate_lvb(ls);
+                       lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
                if (!lkb->lkb_lvbptr)
                        return -ENOMEM;
                len = receive_extralen(ms);
@@ -3006,11 +3005,9 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
        lkb->lkb_bastaddr = (void *) (long) (ms->m_asts & AST_BAST);
        lkb->lkb_astaddr = (void *) (long) (ms->m_asts & AST_COMP);
 
-       DLM_ASSERT(is_master_copy(lkb), dlm_print_lkb(lkb););
-
        if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
                /* lkb was just created so there won't be an lvb yet */
-               lkb->lkb_lvbptr = allocate_lvb(ls);
+               lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
                if (!lkb->lkb_lvbptr)
                        return -ENOMEM;
        }
@@ -3021,16 +3018,6 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
                                struct dlm_message *ms)
 {
-       if (lkb->lkb_nodeid != ms->m_header.h_nodeid) {
-               log_error(ls, "convert_args nodeid %d %d lkid %x %x",
-                         lkb->lkb_nodeid, ms->m_header.h_nodeid,
-                         lkb->lkb_id, lkb->lkb_remid);
-               return -EINVAL;
-       }
-
-       if (!is_master_copy(lkb))
-               return -EINVAL;
-
        if (lkb->lkb_status != DLM_LKSTS_GRANTED)
                return -EBUSY;
 
@@ -3046,8 +3033,6 @@ static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 static int receive_unlock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
                               struct dlm_message *ms)
 {
-       if (!is_master_copy(lkb))
-               return -EINVAL;
        if (receive_lvb(ls, lkb, ms))
                return -ENOMEM;
        return 0;
@@ -3063,6 +3048,50 @@ static void setup_stub_lkb(struct dlm_ls *ls, struct dlm_message *ms)
        lkb->lkb_remid = ms->m_lkid;
 }
 
+/* This is called after the rsb is locked so that we can safely inspect
+   fields in the lkb. */
+
+static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms)
+{
+       int from = ms->m_header.h_nodeid;
+       int error = 0;
+
+       switch (ms->m_type) {
+       case DLM_MSG_CONVERT:
+       case DLM_MSG_UNLOCK:
+       case DLM_MSG_CANCEL:
+               if (!is_master_copy(lkb) || lkb->lkb_nodeid != from)
+                       error = -EINVAL;
+               break;
+
+       case DLM_MSG_CONVERT_REPLY:
+       case DLM_MSG_UNLOCK_REPLY:
+       case DLM_MSG_CANCEL_REPLY:
+       case DLM_MSG_GRANT:
+       case DLM_MSG_BAST:
+               if (!is_process_copy(lkb) || lkb->lkb_nodeid != from)
+                       error = -EINVAL;
+               break;
+
+       case DLM_MSG_REQUEST_REPLY:
+               if (!is_process_copy(lkb))
+                       error = -EINVAL;
+               else if (lkb->lkb_nodeid != -1 && lkb->lkb_nodeid != from)
+                       error = -EINVAL;
+               break;
+
+       default:
+               error = -EINVAL;
+       }
+
+       if (error)
+               log_error(lkb->lkb_resource->res_ls,
+                         "ignore invalid message %d from %d %x %x %x %d",
+                         ms->m_type, from, lkb->lkb_id, lkb->lkb_remid,
+                         lkb->lkb_flags, lkb->lkb_nodeid);
+       return error;
+}
+
 static void receive_request(struct dlm_ls *ls, struct dlm_message *ms)
 {
        struct dlm_lkb *lkb;
@@ -3124,17 +3153,21 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        receive_flags(lkb, ms);
        error = receive_convert_args(ls, lkb, ms);
        if (error)
-               goto out;
+               goto out_reply;
        reply = !down_conversion(lkb);
 
        error = do_convert(r, lkb);
- out:
+ out_reply:
        if (reply)
                send_convert_reply(r, lkb, error);
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
        dlm_put_lkb(lkb);
@@ -3160,15 +3193,19 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        receive_flags(lkb, ms);
        error = receive_unlock_args(ls, lkb, ms);
        if (error)
-               goto out;
+               goto out_reply;
 
        error = do_unlock(r, lkb);
- out:
+ out_reply:
        send_unlock_reply(r, lkb, error);
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
        dlm_put_lkb(lkb);
@@ -3196,9 +3233,13 @@ static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        error = do_cancel(r, lkb);
        send_cancel_reply(r, lkb, error);
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
        dlm_put_lkb(lkb);
@@ -3217,22 +3258,26 @@ static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_grant no lkb");
+               log_debug(ls, "receive_grant from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        r = lkb->lkb_resource;
 
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        receive_flags_reply(lkb, ms);
        if (is_altmode(lkb))
                munge_altmode(lkb, ms);
        grant_lock_pc(r, lkb, ms);
        queue_cast(r, lkb, 0);
-
+ out:
        unlock_rsb(r);
        put_rsb(r);
        dlm_put_lkb(lkb);
@@ -3246,18 +3291,22 @@ static void receive_bast(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_bast no lkb");
+               log_debug(ls, "receive_bast from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        r = lkb->lkb_resource;
 
        hold_rsb(r);
        lock_rsb(r);
 
-       queue_bast(r, lkb, ms->m_bastmode);
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
 
+       queue_bast(r, lkb, ms->m_bastmode);
+ out:
        unlock_rsb(r);
        put_rsb(r);
        dlm_put_lkb(lkb);
@@ -3323,15 +3372,19 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_request_reply no lkb");
+               log_debug(ls, "receive_request_reply from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        r = lkb->lkb_resource;
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        mstype = lkb->lkb_wait_type;
        error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY);
        if (error)
@@ -3383,6 +3436,7 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
                if (is_overlap(lkb)) {
                        /* we'll ignore error in cancel/unlock reply */
                        queue_cast_overlap(r, lkb);
+                       confirm_master(r, result);
                        unhold_lkb(lkb); /* undoes create_lkb() */
                } else
                        _request_lock(r, lkb);
@@ -3463,6 +3517,10 @@ static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        /* stub reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms);
        if (error)
@@ -3481,10 +3539,10 @@ static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_convert_reply no lkb");
+               log_debug(ls, "receive_convert_reply from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        _receive_convert_reply(lkb, ms);
        dlm_put_lkb(lkb);
@@ -3498,6 +3556,10 @@ static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        /* stub reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms);
        if (error)
@@ -3529,10 +3591,10 @@ static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_unlock_reply no lkb");
+               log_debug(ls, "receive_unlock_reply from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        _receive_unlock_reply(lkb, ms);
        dlm_put_lkb(lkb);
@@ -3546,6 +3608,10 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
        hold_rsb(r);
        lock_rsb(r);
 
+       error = validate_message(lkb, ms);
+       if (error)
+               goto out;
+
        /* stub reply can happen with waiters_mutex held */
        error = remove_from_waiters_ms(lkb, ms);
        if (error)
@@ -3577,10 +3643,10 @@ static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms)
 
        error = find_lkb(ls, ms->m_remid, &lkb);
        if (error) {
-               log_error(ls, "receive_cancel_reply no lkb");
+               log_debug(ls, "receive_cancel_reply from %d no lkb %x",
+                         ms->m_header.h_nodeid, ms->m_remid);
                return;
        }
-       DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb););
 
        _receive_cancel_reply(lkb, ms);
        dlm_put_lkb(lkb);
@@ -3640,6 +3706,13 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms)
 
 static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms)
 {
+       if (!dlm_is_member(ls, ms->m_header.h_nodeid)) {
+               log_debug(ls, "ignore non-member message %d from %d %x %x %d",
+                         ms->m_type, ms->m_header.h_nodeid, ms->m_lkid,
+                         ms->m_remid, ms->m_result);
+               return;
+       }
+
        switch (ms->m_type) {
 
        /* messages sent to a master node */
@@ -3778,8 +3851,9 @@ void dlm_receive_buffer(struct dlm_header *hd, int nodeid)
 
        ls = dlm_find_lockspace_global(hd->h_lockspace);
        if (!ls) {
-               log_print("invalid h_lockspace %x from %d cmd %d type %d",
-                         hd->h_lockspace, nodeid, hd->h_cmd, type);
+               if (dlm_config.ci_log_debug)
+                       log_print("invalid lockspace %x from %d cmd %d type %d",
+                                 hd->h_lockspace, nodeid, hd->h_cmd, type);
 
                if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS)
                        dlm_send_ls_not_ready(nodeid, rc);
@@ -3806,6 +3880,7 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb)
                ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY;
                ls->ls_stub_ms.m_result = -EINPROGRESS;
                ls->ls_stub_ms.m_flags = lkb->lkb_flags;
+               ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid;
                _receive_convert_reply(lkb, &ls->ls_stub_ms);
 
                /* Same special case as in receive_rcom_lock_args() */
@@ -3847,6 +3922,7 @@ static int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb)
 void dlm_recover_waiters_pre(struct dlm_ls *ls)
 {
        struct dlm_lkb *lkb, *safe;
+       int wait_type, stub_unlock_result, stub_cancel_result;
 
        mutex_lock(&ls->ls_waiters_mutex);
 
@@ -3865,7 +3941,33 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
                if (!waiter_needs_recovery(ls, lkb))
                        continue;
 
-               switch (lkb->lkb_wait_type) {
+               wait_type = lkb->lkb_wait_type;
+               stub_unlock_result = -DLM_EUNLOCK;
+               stub_cancel_result = -DLM_ECANCEL;
+
+               /* Main reply may have been received leaving a zero wait_type,
+                  but a reply for the overlapping op may not have been
+                  received.  In that case we need to fake the appropriate
+                  reply for the overlap op. */
+
+               if (!wait_type) {
+                       if (is_overlap_cancel(lkb)) {
+                               wait_type = DLM_MSG_CANCEL;
+                               if (lkb->lkb_grmode == DLM_LOCK_IV)
+                                       stub_cancel_result = 0;
+                       }
+                       if (is_overlap_unlock(lkb)) {
+                               wait_type = DLM_MSG_UNLOCK;
+                               if (lkb->lkb_grmode == DLM_LOCK_IV)
+                                       stub_unlock_result = -ENOENT;
+                       }
+
+                       log_debug(ls, "rwpre overlap %x %x %d %d %d",
+                                 lkb->lkb_id, lkb->lkb_flags, wait_type,
+                                 stub_cancel_result, stub_unlock_result);
+               }
+
+               switch (wait_type) {
 
                case DLM_MSG_REQUEST:
                        lkb->lkb_flags |= DLM_IFL_RESEND;
@@ -3878,8 +3980,9 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
                case DLM_MSG_UNLOCK:
                        hold_lkb(lkb);
                        ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY;
-                       ls->ls_stub_ms.m_result = -DLM_EUNLOCK;
+                       ls->ls_stub_ms.m_result = stub_unlock_result;
                        ls->ls_stub_ms.m_flags = lkb->lkb_flags;
+                       ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid;
                        _receive_unlock_reply(lkb, &ls->ls_stub_ms);
                        dlm_put_lkb(lkb);
                        break;
@@ -3887,15 +3990,16 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
                case DLM_MSG_CANCEL:
                        hold_lkb(lkb);
                        ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY;
-                       ls->ls_stub_ms.m_result = -DLM_ECANCEL;
+                       ls->ls_stub_ms.m_result = stub_cancel_result;
                        ls->ls_stub_ms.m_flags = lkb->lkb_flags;
+                       ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid;
                        _receive_cancel_reply(lkb, &ls->ls_stub_ms);
                        dlm_put_lkb(lkb);
                        break;
 
                default:
-                       log_error(ls, "invalid lkb wait_type %d",
-                                 lkb->lkb_wait_type);
+                       log_error(ls, "invalid lkb wait_type %d %d",
+                                 lkb->lkb_wait_type, wait_type);
                }
                schedule();
        }
@@ -4184,7 +4288,7 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
        lkb->lkb_astaddr = (void *) (long) (rl->rl_asts & AST_COMP);
 
        if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
-               lkb->lkb_lvbptr = allocate_lvb(ls);
+               lkb->lkb_lvbptr = dlm_allocate_lvb(ls);
                if (!lkb->lkb_lvbptr)
                        return -ENOMEM;
                lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) -
@@ -4259,7 +4363,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
        put_rsb(r);
  out:
        if (error)
-               log_print("recover_master_copy %d %x", error, rl->rl_lkid);
+               log_debug(ls, "recover_master_copy %d %x", error, rl->rl_lkid);
        rl->rl_result = error;
        return error;
 }
@@ -4342,7 +4446,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
                }
        }
 
-       /* After ua is attached to lkb it will be freed by free_lkb().
+       /* After ua is attached to lkb it will be freed by dlm_free_lkb().
           When DLM_IFL_USER is set, the dlm knows that this is a userspace
           lock and that lkb_astparam is the dlm_user_args structure. */
 
@@ -4679,6 +4783,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
        }
 
        list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
+               lkb->lkb_ast_type = 0;
                list_del(&lkb->lkb_astqueue);
                dlm_put_lkb(lkb);
        }
index ada04680a1e5d9ff994aa82a35c899b6a975692b..27b6ed3029115d194a809373b739f841162dea92 100644 (file)
@@ -19,8 +19,6 @@ void dlm_print_lkb(struct dlm_lkb *lkb);
 void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms);
 void dlm_receive_buffer(struct dlm_header *hd, int nodeid);
 int dlm_modes_compat(int mode1, int mode2);
-int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen,
-       unsigned int flags, struct dlm_rsb **r_ret);
 void dlm_put_rsb(struct dlm_rsb *r);
 void dlm_hold_rsb(struct dlm_rsb *r);
 int dlm_put_lkb(struct dlm_lkb *lkb);
index 5c108c49cb8cd30128d533630cdd3ac72810839d..b180fdc51085adba0be6ace10703efdfab5507b9 100644 (file)
 #include "recover.h"
 #include "requestqueue.h"
 
-#ifdef CONFIG_DLM_DEBUG
-int dlm_create_debug_file(struct dlm_ls *ls);
-void dlm_delete_debug_file(struct dlm_ls *ls);
-#else
-static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; }
-static inline void dlm_delete_debug_file(struct dlm_ls *ls) { }
-#endif
-
 static int                     ls_count;
 static struct mutex            ls_lock;
 static struct list_head                lslist;
@@ -684,9 +676,9 @@ static int release_lockspace(struct dlm_ls *ls, int force)
                        dlm_del_ast(lkb);
 
                        if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY)
-                               free_lvb(lkb->lkb_lvbptr);
+                               dlm_free_lvb(lkb->lkb_lvbptr);
 
-                       free_lkb(lkb);
+                       dlm_free_lkb(lkb);
                }
        }
        dlm_astd_resume();
@@ -704,7 +696,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
                                         res_hashchain);
 
                        list_del(&rsb->res_hashchain);
-                       free_rsb(rsb);
+                       dlm_free_rsb(rsb);
                }
 
                head = &ls->ls_rsbtbl[i].toss;
@@ -712,7 +704,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
                        rsb = list_entry(head->next, struct dlm_rsb,
                                         res_hashchain);
                        list_del(&rsb->res_hashchain);
-                       free_rsb(rsb);
+                       dlm_free_rsb(rsb);
                }
        }
 
index e9923ca9c2d9ee4c700eb6f18ea1bfb150fee52f..7c1e5e5cccd8ae97a87a618ad9818d5b35721553 100644 (file)
@@ -864,7 +864,7 @@ static void sctp_init_assoc(struct connection *con)
 static void tcp_connect_to_sock(struct connection *con)
 {
        int result = -EHOSTUNREACH;
-       struct sockaddr_storage saddr;
+       struct sockaddr_storage saddr, src_addr;
        int addr_len;
        struct socket *sock;
 
@@ -898,6 +898,17 @@ static void tcp_connect_to_sock(struct connection *con)
        con->connect_action = tcp_connect_to_sock;
        add_sock(sock, con);
 
+       /* Bind to our cluster-known address connecting to avoid
+          routing problems */
+       memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr));
+       make_sockaddr(&src_addr, 0, &addr_len);
+       result = sock->ops->bind(sock, (struct sockaddr *) &src_addr,
+                                addr_len);
+       if (result < 0) {
+               log_print("could not bind for connect: %d", result);
+               /* This *may* not indicate a critical error */
+       }
+
        make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len);
 
        log_print("connecting to %d", con->nodeid);
@@ -1426,6 +1437,8 @@ void dlm_lowcomms_stop(void)
                con = __nodeid2con(i, 0);
                if (con) {
                        close_connection(con, true);
+                       if (con->othercon)
+                               kmem_cache_free(con_cache, con->othercon);
                        kmem_cache_free(con_cache, con);
                }
        }
index eca2907f2386da93396d19d5195bd59101614b54..58487fb95a4c258b6e33f38a167460cadfa171be 100644 (file)
 #include "memory.h"
 #include "config.h"
 
-#ifdef CONFIG_DLM_DEBUG
-int dlm_register_debugfs(void);
-void dlm_unregister_debugfs(void);
-#else
-static inline int dlm_register_debugfs(void) { return 0; }
-static inline void dlm_unregister_debugfs(void) { }
-#endif
-int dlm_netlink_init(void);
-void dlm_netlink_exit(void);
-
 static int __init init_dlm(void)
 {
        int error;
index e9cdcab306e2a06037c4e0c32ac1c0e7be3097dc..fa17f5a278831fa3acf3977930fae7fcc63af2df 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -70,7 +70,7 @@ static void dlm_remove_member(struct dlm_ls *ls, struct dlm_member *memb)
        ls->ls_num_nodes--;
 }
 
-static int dlm_is_member(struct dlm_ls *ls, int nodeid)
+int dlm_is_member(struct dlm_ls *ls, int nodeid)
 {
        struct dlm_member *memb;
 
index 927c08c192148ef07c165b29d1715a4ed35c2fa9..7a26fca1e0b5386e6b5906655b57f6fd80e1fe3c 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -19,6 +19,7 @@ void dlm_clear_members(struct dlm_ls *ls);
 void dlm_clear_members_gone(struct dlm_ls *ls);
 int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out);
 int dlm_is_removed(struct dlm_ls *ls, int nodeid);
+int dlm_is_member(struct dlm_ls *ls, int nodeid);
 
 #endif                          /* __MEMBER_DOT_H__ */
 
index ecf0e5cb2035e885e90bf8acbc992c3c9b0c397d..f7783867491aedf9678f6c506d49bf636ddb68e0 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -35,7 +35,7 @@ void dlm_memory_exit(void)
                kmem_cache_destroy(lkb_cache);
 }
 
-char *allocate_lvb(struct dlm_ls *ls)
+char *dlm_allocate_lvb(struct dlm_ls *ls)
 {
        char *p;
 
@@ -43,7 +43,7 @@ char *allocate_lvb(struct dlm_ls *ls)
        return p;
 }
 
-void free_lvb(char *p)
+void dlm_free_lvb(char *p)
 {
        kfree(p);
 }
@@ -51,7 +51,7 @@ void free_lvb(char *p)
 /* FIXME: have some minimal space built-in to rsb for the name and
    kmalloc a separate name if needed, like dentries are done */
 
-struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen)
+struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen)
 {
        struct dlm_rsb *r;
 
@@ -61,14 +61,14 @@ struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen)
        return r;
 }
 
-void free_rsb(struct dlm_rsb *r)
+void dlm_free_rsb(struct dlm_rsb *r)
 {
        if (r->res_lvbptr)
-               free_lvb(r->res_lvbptr);
+               dlm_free_lvb(r->res_lvbptr);
        kfree(r);
 }
 
-struct dlm_lkb *allocate_lkb(struct dlm_ls *ls)
+struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls)
 {
        struct dlm_lkb *lkb;
 
@@ -76,7 +76,7 @@ struct dlm_lkb *allocate_lkb(struct dlm_ls *ls)
        return lkb;
 }
 
-void free_lkb(struct dlm_lkb *lkb)
+void dlm_free_lkb(struct dlm_lkb *lkb)
 {
        if (lkb->lkb_flags & DLM_IFL_USER) {
                struct dlm_user_args *ua;
@@ -90,19 +90,3 @@ void free_lkb(struct dlm_lkb *lkb)
        kmem_cache_free(lkb_cache, lkb);
 }
 
-struct dlm_direntry *allocate_direntry(struct dlm_ls *ls, int namelen)
-{
-       struct dlm_direntry *de;
-
-       DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,
-                  printk("namelen = %d\n", namelen););
-
-       de = kzalloc(sizeof(*de) + namelen, GFP_KERNEL);
-       return de;
-}
-
-void free_direntry(struct dlm_direntry *de)
-{
-       kfree(de);
-}
-
index 6ead158ccc5c661cb4138bfd756bb05d69382989..485fb29143bdd0d86af973523ea8ab4a584780ab 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
 
 int dlm_memory_init(void);
 void dlm_memory_exit(void);
-struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen);
-void free_rsb(struct dlm_rsb *r);
-struct dlm_lkb *allocate_lkb(struct dlm_ls *ls);
-void free_lkb(struct dlm_lkb *l);
-struct dlm_direntry *allocate_direntry(struct dlm_ls *ls, int namelen);
-void free_direntry(struct dlm_direntry *de);
-char *allocate_lvb(struct dlm_ls *ls);
-void free_lvb(char *l);
+struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen);
+void dlm_free_rsb(struct dlm_rsb *r);
+struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls);
+void dlm_free_lkb(struct dlm_lkb *l);
+char *dlm_allocate_lvb(struct dlm_ls *ls);
+void dlm_free_lvb(char *l);
 
 #endif         /* __MEMORY_DOT_H__ */
 
index f8c69dda16a080af8e960f2111772bed46d2c8c2..e69926e984db3f07565aa052335e49151bd489d5 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2004-2007 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -58,8 +58,12 @@ static void copy_from_cb(void *dst, const void *base, unsigned offset,
 int dlm_process_incoming_buffer(int nodeid, const void *base,
                                unsigned offset, unsigned len, unsigned limit)
 {
-       unsigned char __tmp[DLM_INBUF_LEN];
-       struct dlm_header *msg = (struct dlm_header *) __tmp;
+       union {
+               unsigned char __buf[DLM_INBUF_LEN];
+               /* this is to force proper alignment on some arches */
+               struct dlm_header dlm;
+       } __tmp;
+       struct dlm_header *msg = &__tmp.dlm;
        int ret = 0;
        int err = 0;
        uint16_t msglen;
@@ -100,8 +104,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
                   in the buffer on the stack (which should work for most
                   ordinary messages). */
 
-               if (msglen > sizeof(__tmp) &&
-                   msg == (struct dlm_header *) __tmp) {
+               if (msglen > DLM_INBUF_LEN && msg == &__tmp.dlm) {
                        msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL);
                        if (msg == NULL)
                                return ret;
@@ -119,7 +122,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base,
                dlm_receive_buffer(msg, nodeid);
        }
 
-       if (msg != (struct dlm_header *) __tmp)
+       if (msg != &__tmp.dlm)
                kfree(msg);
 
        return err ? err : ret;
index ae2fd97fa4adc8392b720f1e455e4a53968c8d0c..026824cd3acbdd5198d9a4a299b4b6babaf7b02c 100644 (file)
@@ -2,7 +2,7 @@
 *******************************************************************************
 **
 **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
-**  Copyright (C) 2005-2007 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
@@ -197,11 +197,6 @@ static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
        spin_unlock(&ls->ls_rcom_spin);
 }
 
-static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
-       receive_sync_reply(ls, rc_in);
-}
-
 int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
 {
        struct dlm_rcom *rc;
@@ -254,11 +249,6 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
        send_rcom(ls, mh, rc);
 }
 
-static void receive_rcom_names_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
-       receive_sync_reply(ls, rc_in);
-}
-
 int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid)
 {
        struct dlm_rcom *rc;
@@ -381,11 +371,6 @@ static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in)
        send_rcom(ls, mh, rc);
 }
 
-static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
-{
-       dlm_recover_process_copy(ls, rc_in);
-}
-
 /* If the lockspace doesn't exist then still send a status message
    back; it's possible that it just doesn't have its global_id yet. */
 
@@ -481,11 +466,11 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
                break;
 
        case DLM_RCOM_STATUS_REPLY:
-               receive_rcom_status_reply(ls, rc);
+               receive_sync_reply(ls, rc);
                break;
 
        case DLM_RCOM_NAMES_REPLY:
-               receive_rcom_names_reply(ls, rc);
+               receive_sync_reply(ls, rc);
                break;
 
        case DLM_RCOM_LOOKUP_REPLY:
@@ -493,11 +478,11 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
                break;
 
        case DLM_RCOM_LOCK_REPLY:
-               receive_rcom_lock_reply(ls, rc);
+               dlm_recover_process_copy(ls, rc);
                break;
 
        default:
-               DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type););
+               log_error(ls, "receive_rcom bad type %d", rc->rc_type);
        }
  out:
        return;
index c2cc7694cd164b6847f35c12257b6a783bf82525..df075dc300fa4ad7bbe8364478b297795d562a61 100644 (file)
@@ -629,7 +629,7 @@ static void recover_lvb(struct dlm_rsb *r)
                goto out;
 
        if (!r->res_lvbptr) {
-               r->res_lvbptr = allocate_lvb(r->res_ls);
+               r->res_lvbptr = dlm_allocate_lvb(r->res_ls);
                if (!r->res_lvbptr)
                        goto out;
        }
@@ -731,6 +731,20 @@ int dlm_create_root_list(struct dlm_ls *ls)
                        list_add(&r->res_root_list, &ls->ls_root_list);
                        dlm_hold_rsb(r);
                }
+
+               /* If we're using a directory, add tossed rsbs to the root
+                  list; they'll have entries created in the new directory,
+                  but no other recovery steps should do anything with them. */
+
+               if (dlm_no_directory(ls)) {
+                       read_unlock(&ls->ls_rsbtbl[i].lock);
+                       continue;
+               }
+
+               list_for_each_entry(r, &ls->ls_rsbtbl[i].toss, res_hashchain) {
+                       list_add(&r->res_root_list, &ls->ls_root_list);
+                       dlm_hold_rsb(r);
+               }
                read_unlock(&ls->ls_rsbtbl[i].lock);
        }
  out:
@@ -750,6 +764,11 @@ void dlm_release_root_list(struct dlm_ls *ls)
        up_write(&ls->ls_root_sem);
 }
 
+/* If not using a directory, clear the entire toss list, there's no benefit to
+   caching the master value since it's fixed.  If we are using a dir, keep the
+   rsb's we're the master of.  Recovery will add them to the root list and from
+   there they'll be entered in the rebuilt directory. */
+
 void dlm_clear_toss_list(struct dlm_ls *ls)
 {
        struct dlm_rsb *r, *safe;
@@ -759,8 +778,10 @@ void dlm_clear_toss_list(struct dlm_ls *ls)
                write_lock(&ls->ls_rsbtbl[i].lock);
                list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss,
                                         res_hashchain) {
-                       list_del(&r->res_hashchain);
-                       free_rsb(r);
+                       if (dlm_no_directory(ls) || !is_master(r)) {
+                               list_del(&r->res_hashchain);
+                               dlm_free_rsb(r);
+                       }
                }
                write_unlock(&ls->ls_rsbtbl[i].lock);
        }
index 4b89e20eebe702f32a9214d2f377e1efc2768001..997f9531d59482ed1d3fecee535d8aada119b302 100644 (file)
@@ -67,17 +67,18 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
        dlm_astd_resume();
 
        /*
-        * This list of root rsb's will be the basis of most of the recovery
-        * routines.
+        * Free non-master tossed rsb's.  Master rsb's are kept on toss
+        * list and put on root list to be included in resdir recovery.
         */
 
-       dlm_create_root_list(ls);
+       dlm_clear_toss_list(ls);
 
        /*
-        * Free all the tossed rsb's so we don't have to recover them.
+        * This list of root rsb's will be the basis of most of the recovery
+        * routines.
         */
 
-       dlm_clear_toss_list(ls);
+       dlm_create_root_list(ls);
 
        /*
         * Add or remove nodes from the lockspace's ls_nodes list.
index 4f741546f4bbce873079bee9060eac437934d8b6..7cbc6826239b10b5b17b70c0d4f737f7e77152fa 100644 (file)
@@ -24,8 +24,7 @@
 #include "lvb_table.h"
 #include "user.h"
 
-static const char *name_prefix="dlm";
-static struct miscdevice ctl_device;
+static const char name_prefix[] = "dlm";
 static const struct file_operations device_fops;
 
 #ifdef CONFIG_COMPAT
@@ -82,7 +81,8 @@ struct dlm_lock_result32 {
 };
 
 static void compat_input(struct dlm_write_request *kb,
-                        struct dlm_write_request32 *kb32)
+                        struct dlm_write_request32 *kb32,
+                        int max_namelen)
 {
        kb->version[0] = kb32->version[0];
        kb->version[1] = kb32->version[1];
@@ -112,7 +112,11 @@ static void compat_input(struct dlm_write_request *kb,
                kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr;
                kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb;
                memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN);
-               memcpy(kb->i.lock.name, kb32->i.lock.name, kb->i.lock.namelen);
+               if (kb->i.lock.namelen <= max_namelen)
+                       memcpy(kb->i.lock.name, kb32->i.lock.name,
+                              kb->i.lock.namelen);
+               else
+                       kb->i.lock.namelen = max_namelen;
        }
 }
 
@@ -236,12 +240,12 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
        spin_unlock(&proc->asts_spin);
 
        if (eol) {
-               spin_lock(&ua->proc->locks_spin);
+               spin_lock(&proc->locks_spin);
                if (!list_empty(&lkb->lkb_ownqueue)) {
                        list_del_init(&lkb->lkb_ownqueue);
                        dlm_put_lkb(lkb);
                }
-               spin_unlock(&ua->proc->locks_spin);
+               spin_unlock(&proc->locks_spin);
        }
  out:
        mutex_unlock(&ls->ls_clear_proc_locks);
@@ -529,7 +533,8 @@ static ssize_t device_write(struct file *file, const char __user *buf,
 
                if (proc)
                        set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags);
-               compat_input(kbuf, k32buf);
+               compat_input(kbuf, k32buf,
+                            count - sizeof(struct dlm_write_request32));
                kfree(k32buf);
        }
 #endif
@@ -896,14 +901,16 @@ static const struct file_operations ctl_device_fops = {
        .owner   = THIS_MODULE,
 };
 
+static struct miscdevice ctl_device = {
+       .name  = "dlm-control",
+       .fops  = &ctl_device_fops,
+       .minor = MISC_DYNAMIC_MINOR,
+};
+
 int dlm_user_init(void)
 {
        int error;
 
-       ctl_device.name = "dlm-control";
-       ctl_device.fops = &ctl_device_fops;
-       ctl_device.minor = MISC_DYNAMIC_MINOR;
-
        error = misc_register(&ctl_device);
        if (error)
                log_print("misc_register failed for control device");
index 963889cf674063fb5591cc0ab7b933afb06b24b5..4d9c1f4e1bd10af144a0ae813badaf528c042532 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 *******************************************************************************
 **
-**  Copyright (C) 2005 Red Hat, Inc.  All rights reserved.
+**  Copyright (C) 2005-2008 Red Hat, Inc.  All rights reserved.
 **
 **  This copyrighted material is made available to anyone wishing to use,
 **  modify, copy, or redistribute it subject to the terms and conditions
 #include "rcom.h"
 #include "util.h"
 
+#define DLM_ERRNO_EDEADLK              35
+#define DLM_ERRNO_EBADR                        53
+#define DLM_ERRNO_EBADSLT              57
+#define DLM_ERRNO_EPROTO               71
+#define DLM_ERRNO_EOPNOTSUPP           95
+#define DLM_ERRNO_ETIMEDOUT           110
+#define DLM_ERRNO_EINPROGRESS         115
+
 static void header_out(struct dlm_header *hd)
 {
        hd->h_version           = cpu_to_le32(hd->h_version);
@@ -30,11 +38,54 @@ static void header_in(struct dlm_header *hd)
        hd->h_length            = le16_to_cpu(hd->h_length);
 }
 
-void dlm_message_out(struct dlm_message *ms)
+/* higher errno values are inconsistent across architectures, so select
+   one set of values for on the wire */
+
+static int to_dlm_errno(int err)
+{
+       switch (err) {
+       case -EDEADLK:
+               return -DLM_ERRNO_EDEADLK;
+       case -EBADR:
+               return -DLM_ERRNO_EBADR;
+       case -EBADSLT:
+               return -DLM_ERRNO_EBADSLT;
+       case -EPROTO:
+               return -DLM_ERRNO_EPROTO;
+       case -EOPNOTSUPP:
+               return -DLM_ERRNO_EOPNOTSUPP;
+       case -ETIMEDOUT:
+               return -DLM_ERRNO_ETIMEDOUT;
+       case -EINPROGRESS:
+               return -DLM_ERRNO_EINPROGRESS;
+       }
+       return err;
+}
+
+static int from_dlm_errno(int err)
 {
-       struct dlm_header *hd = (struct dlm_header *) ms;
+       switch (err) {
+       case -DLM_ERRNO_EDEADLK:
+               return -EDEADLK;
+       case -DLM_ERRNO_EBADR:
+               return -EBADR;
+       case -DLM_ERRNO_EBADSLT:
+               return -EBADSLT;
+       case -DLM_ERRNO_EPROTO:
+               return -EPROTO;
+       case -DLM_ERRNO_EOPNOTSUPP:
+               return -EOPNOTSUPP;
+       case -DLM_ERRNO_ETIMEDOUT:
+               return -ETIMEDOUT;
+       case -DLM_ERRNO_EINPROGRESS:
+               return -EINPROGRESS;
+       }
+       return err;
+}
 
-       header_out(hd);
+void dlm_message_out(struct dlm_message *ms)
+{
+       header_out(&ms->m_header);
 
        ms->m_type              = cpu_to_le32(ms->m_type);
        ms->m_nodeid            = cpu_to_le32(ms->m_nodeid);
@@ -53,14 +104,12 @@ void dlm_message_out(struct dlm_message *ms)
        ms->m_rqmode            = cpu_to_le32(ms->m_rqmode);
        ms->m_bastmode          = cpu_to_le32(ms->m_bastmode);
        ms->m_asts              = cpu_to_le32(ms->m_asts);
-       ms->m_result            = cpu_to_le32(ms->m_result);
+       ms->m_result            = cpu_to_le32(to_dlm_errno(ms->m_result));
 }
 
 void dlm_message_in(struct dlm_message *ms)
 {
-       struct dlm_header *hd = (struct dlm_header *) ms;
-
-       header_in(hd);
+       header_in(&ms->m_header);
 
        ms->m_type              = le32_to_cpu(ms->m_type);
        ms->m_nodeid            = le32_to_cpu(ms->m_nodeid);
@@ -79,7 +128,7 @@ void dlm_message_in(struct dlm_message *ms)
        ms->m_rqmode            = le32_to_cpu(ms->m_rqmode);
        ms->m_bastmode          = le32_to_cpu(ms->m_bastmode);
        ms->m_asts              = le32_to_cpu(ms->m_asts);
-       ms->m_result            = le32_to_cpu(ms->m_result);
+       ms->m_result            = from_dlm_errno(le32_to_cpu(ms->m_result));
 }
 
 static void rcom_lock_out(struct rcom_lock *rl)
@@ -126,10 +175,9 @@ static void rcom_config_in(struct rcom_config *rf)
 
 void dlm_rcom_out(struct dlm_rcom *rc)
 {
-       struct dlm_header *hd = (struct dlm_header *) rc;
        int type = rc->rc_type;
 
-       header_out(hd);
+       header_out(&rc->rc_header);
 
        rc->rc_type             = cpu_to_le32(rc->rc_type);
        rc->rc_result           = cpu_to_le32(rc->rc_result);
@@ -137,7 +185,7 @@ void dlm_rcom_out(struct dlm_rcom *rc)
        rc->rc_seq              = cpu_to_le64(rc->rc_seq);
        rc->rc_seq_reply        = cpu_to_le64(rc->rc_seq_reply);
 
-       if (type == DLM_RCOM_LOCK)
+       if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY))
                rcom_lock_out((struct rcom_lock *) rc->rc_buf);
 
        else if (type == DLM_RCOM_STATUS_REPLY)
@@ -146,9 +194,9 @@ void dlm_rcom_out(struct dlm_rcom *rc)
 
 void dlm_rcom_in(struct dlm_rcom *rc)
 {
-       struct dlm_header *hd = (struct dlm_header *) rc;
+       int type;
 
-       header_in(hd);
+       header_in(&rc->rc_header);
 
        rc->rc_type             = le32_to_cpu(rc->rc_type);
        rc->rc_result           = le32_to_cpu(rc->rc_result);
@@ -156,10 +204,12 @@ void dlm_rcom_in(struct dlm_rcom *rc)
        rc->rc_seq              = le64_to_cpu(rc->rc_seq);
        rc->rc_seq_reply        = le64_to_cpu(rc->rc_seq_reply);
 
-       if (rc->rc_type == DLM_RCOM_LOCK)
+       type = rc->rc_type;
+
+       if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY))
                rcom_lock_in((struct rcom_lock *) rc->rc_buf);
 
-       else if (rc->rc_type == DLM_RCOM_STATUS_REPLY)
+       else if (type == DLM_RCOM_STATUS_REPLY)
                rcom_config_in((struct rcom_config *) rc->rc_buf);
 }
 
index 702fcfeb37f19c1d4ef5f7c03692d4e900b574cd..82251575a9b45e1a4e24475dc71503deef0223a8 100644 (file)
 
 #include <linux/types.h>
 
+/*
+ * The maximum number of SG segments that we will put inside a
+ * scatterlist (unless chaining is used). Should ideally fit inside a
+ * single page, to avoid a higher order allocation.  We could define this
+ * to SG_MAX_SINGLE_ALLOC to pack correctly at the highest order.  The
+ * minimum value is 32
+ */
+#define SCSI_MAX_SG_SEGMENTS   128
+
+/*
+ * Like SCSI_MAX_SG_SEGMENTS, but for archs that have sg chaining. This limit
+ * is totally arbitrary, a setting of 2048 will get you at least 8mb ios.
+ */
+#ifdef ARCH_HAS_SG_CHAIN
+#define SCSI_MAX_SG_CHAIN_SEGMENTS     2048
+#else
+#define SCSI_MAX_SG_CHAIN_SEGMENTS     SCSI_MAX_SG_SEGMENTS
+#endif
+
 /*
  *     SCSI command lengths
  */
@@ -83,6 +102,7 @@ extern const unsigned char scsi_command_size[8];
 #define READ_TOC              0x43
 #define LOG_SELECT            0x4c
 #define LOG_SENSE             0x4d
+#define XDWRITEREAD_10        0x53
 #define MODE_SELECT_10        0x55
 #define RESERVE_10            0x56
 #define RELEASE_10            0x57
index a457fca66f6156c4b3629c06d10a71e4c453c5ee..de28aab820b0cca9cdd7261c4000ee965f821e1d 100644 (file)
@@ -2,15 +2,20 @@
 #define _SCSI_SCSI_CMND_H
 
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/timer.h>
 #include <linux/scatterlist.h>
 
-struct request;
 struct Scsi_Host;
 struct scsi_device;
 
+struct scsi_data_buffer {
+       struct sg_table table;
+       unsigned length;
+       int resid;
+};
 
 /* embedded in scsi_cmnd */
 struct scsi_pointer {
@@ -61,15 +66,11 @@ struct scsi_cmnd {
        /* These elements define the operation we are about to perform */
 #define MAX_COMMAND_SIZE       16
        unsigned char cmnd[MAX_COMMAND_SIZE];
-       unsigned request_bufflen;       /* Actual request size */
 
        struct timer_list eh_timeout;   /* Used to time out the command. */
-       void *request_buffer;           /* Actual requested buffer */
 
        /* These elements define the operation we ultimately want to perform */
-       struct sg_table sg_table;
-       unsigned short use_sg;  /* Number of pieces of scatter-gather */
-
+       struct scsi_data_buffer sdb;
        unsigned underflow;     /* Return error if less than
                                   this amount is transferred */
 
@@ -79,10 +80,6 @@ struct scsi_cmnd {
                                   reconnects.   Probably == sector
                                   size */
 
-       int resid;              /* Number of bytes requested to be
-                                  transferred less actual number
-                                  transferred (0 if not supported) */
-
        struct request *request;        /* The command we are
                                           working on */
 
@@ -127,27 +124,55 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
                                 size_t *offset, size_t *len);
 extern void scsi_kunmap_atomic_sg(void *virt);
 
-extern int scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t);
-extern void scsi_free_sgtable(struct scsi_cmnd *);
+extern int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask);
+extern void scsi_release_buffers(struct scsi_cmnd *cmd);
 
 extern int scsi_dma_map(struct scsi_cmnd *cmd);
 extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
 
-#define scsi_sg_count(cmd) ((cmd)->use_sg)
-#define scsi_sglist(cmd) ((cmd)->sg_table.sgl)
-#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
+{
+       return cmd->sdb.table.nents;
+}
+
+static inline struct scatterlist *scsi_sglist(struct scsi_cmnd *cmd)
+{
+       return cmd->sdb.table.sgl;
+}
+
+static inline unsigned scsi_bufflen(struct scsi_cmnd *cmd)
+{
+       return cmd->sdb.length;
+}
 
 static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
 {
-       cmd->resid = resid;
+       cmd->sdb.resid = resid;
 }
 
 static inline int scsi_get_resid(struct scsi_cmnd *cmd)
 {
-       return cmd->resid;
+       return cmd->sdb.resid;
 }
 
 #define scsi_for_each_sg(cmd, sg, nseg, __i)                   \
        for_each_sg(scsi_sglist(cmd), sg, nseg, __i)
 
+static inline int scsi_bidi_cmnd(struct scsi_cmnd *cmd)
+{
+       return blk_bidi_rq(cmd->request) &&
+               (cmd->request->next_rq->special != NULL);
+}
+
+static inline struct scsi_data_buffer *scsi_in(struct scsi_cmnd *cmd)
+{
+       return scsi_bidi_cmnd(cmd) ?
+               cmd->request->next_rq->special : &cmd->sdb;
+}
+
+static inline struct scsi_data_buffer *scsi_out(struct scsi_cmnd *cmd)
+{
+       return &cmd->sdb;
+}
+
 #endif /* _SCSI_SCSI_CMND_H */
index d21b8913ceb3d709f5c711d3b9380f930cc874b9..25071d5d9bf813e95b49efa567fbed23c16f2236 100644 (file)
@@ -68,16 +68,15 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
 extern int scsi_reset_provider(struct scsi_device *, int);
 
 struct scsi_eh_save {
+       /* saved state */
        int result;
        enum dma_data_direction data_direction;
        unsigned char cmd_len;
        unsigned char cmnd[MAX_COMMAND_SIZE];
+       struct scsi_data_buffer sdb;
+       struct request *next_rq;
 
-       void *buffer;
-       unsigned bufflen;
-       unsigned short use_sg;
-       int resid;
-
+       /* new command support */
        struct scatterlist sense_sgl;
 };
 
index 0fd4746ee39d4437e788c37b9a7f59d9b65dc11a..5c58d594126a93bcb697e4c61b9a61c31aaa30b3 100644 (file)
@@ -39,9 +39,6 @@ struct blk_queue_tags;
 #define DISABLE_CLUSTERING 0
 #define ENABLE_CLUSTERING 1
 
-#define DISABLE_SG_CHAINING 0
-#define ENABLE_SG_CHAINING 1
-
 enum scsi_eh_timer_return {
        EH_NOT_HANDLED,
        EH_HANDLED,
@@ -136,9 +133,9 @@ struct scsi_host_template {
         * the done callback is invoked.
         *
         * This is called to inform the LLD to transfer
-        * cmd->request_bufflen bytes. The cmd->use_sg speciefies the
+        * scsi_bufflen(cmd) bytes. scsi_sg_count(cmd) speciefies the
         * number of scatterlist entried in the command and
-        * cmd->request_buffer contains the scatterlist.
+        * scsi_sglist(cmd) returns the scatterlist.
         *
         * return values: see queuecommand
         *
@@ -445,15 +442,6 @@ struct scsi_host_template {
         */
        unsigned ordered_tag:1;
 
-       /*
-        * true if the low-level driver can support sg chaining. this
-        * will be removed eventually when all the drivers are
-        * converted to support sg chaining.
-        *
-        * Status: OBSOLETE
-        */
-       unsigned use_sg_chaining:1;
-
        /*
         * Countdown for host blocking with no commands outstanding
         */
@@ -598,7 +586,6 @@ struct Scsi_Host {
        unsigned unchecked_isa_dma:1;
        unsigned use_clustering:1;
        unsigned use_blk_tcq:1;
-       unsigned use_sg_chaining:1;
 
        /*
         * Host has requested that no further requests come through for the