Author: kib
Date: Tue Mar 19 15:01:50 2013
New Revision: 248519
URL: http://svnweb.freebsd.org/changeset/base/248519

Log:
  Support unmapped i/o for the md(4).
  
  The vnode-backed md(4) has to map the unmapped bio because VOP_READ()
  and VOP_WRITE() interfaces do not allow to pass unmapped requests to
  the filesystem. Vnode-backed md(4) uses pbufs instead of relying on
  the bio_transient_map, to avoid usual md deadlock.
  
  Sponsored by: The FreeBSD Foundation
  Tested by:    pho, scottl

Modified:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/cam_ccb.h
  head/sys/cam/scsi/scsi_all.c
  head/sys/cam/scsi/scsi_all.h
  head/sys/cam/scsi/scsi_cd.c
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c   Tue Mar 19 14:53:23 2013        (r248518)
+++ head/sys/cam/ata/ata_da.c   Tue Mar 19 15:01:50 2013        (r248519)
@@ -1167,6 +1167,8 @@ adaregister(struct cam_periph *periph, v
            ((softc->flags & ADA_FLAG_CAN_CFA) &&
            !(softc->flags & ADA_FLAG_CAN_48BIT)))
                softc->disk->d_flags |= DISKFLAG_CANDELETE;
+       if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
+               softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
        strlcpy(softc->disk->d_descr, cgd->ident_data.model,
            MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model)));
        strlcpy(softc->disk->d_ident, cgd->ident_data.serial,
@@ -1431,13 +1433,19 @@ adastart(struct cam_periph *periph, unio
                                return;
                        }
 #endif
+                       KASSERT((bp->bio_flags & BIO_UNMAPPED) == 0 ||
+                           round_page(bp->bio_bcount + bp->bio_ma_offset) /
+                           PAGE_SIZE == bp->bio_ma_n,
+                           ("Short bio %p", bp));
                        cam_fill_ataio(ataio,
                            ada_retry_count,
                            adadone,
-                           bp->bio_cmd == BIO_READ ?
-                               CAM_DIR_IN : CAM_DIR_OUT,
+                           (bp->bio_cmd == BIO_READ ? CAM_DIR_IN :
+                               CAM_DIR_OUT) | ((bp->bio_flags & BIO_UNMAPPED)
+                               != 0 ? CAM_DATA_BIO : 0),
                            tag_code,
-                           bp->bio_data,
+                           ((bp->bio_flags & BIO_UNMAPPED) != 0) ? (void *)bp :
+                               bp->bio_data,
                            bp->bio_bcount,
                            ada_default_timeout*1000);
 

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h      Tue Mar 19 14:53:23 2013        (r248518)
+++ head/sys/cam/cam_ccb.h      Tue Mar 19 15:01:50 2013        (r248519)
@@ -42,7 +42,6 @@
 #include <cam/scsi/scsi_all.h>
 #include <cam/ata/ata_all.h>
 
-
 /* General allocation length definitions for CCB structures */
 #define        IOCDBLEN        CAM_MAX_CDBLEN  /* Space for CDB bytes/pointer 
*/
 #define        VUHBALEN        14              /* Vendor Unique HBA length */
@@ -572,7 +571,8 @@ typedef enum {
        PIM_NOINITIATOR = 0x20, /* Initiator role not supported. */
        PIM_NOBUSRESET  = 0x10, /* User has disabled initial BUS RESET */
        PIM_NO_6_BYTE   = 0x08, /* Do not send 6-byte commands */
-       PIM_SEQSCAN     = 0x04  /* Do bus scans sequentially, not in parallel */
+       PIM_SEQSCAN     = 0x04, /* Do bus scans sequentially, not in parallel */
+       PIM_UNMAPPED    = 0x02,
 } pi_miscflag;
 
 /* Path Inquiry CCB */

Modified: head/sys/cam/scsi/scsi_all.c
==============================================================================
--- head/sys/cam/scsi/scsi_all.c        Tue Mar 19 14:53:23 2013        
(r248518)
+++ head/sys/cam/scsi/scsi_all.c        Tue Mar 19 15:01:50 2013        
(r248519)
@@ -5679,7 +5679,11 @@ scsi_read_write(struct ccb_scsiio *csio,
                u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
                u_int32_t timeout)
 {
+       int read;
        u_int8_t cdb_len;
+
+       read = (readop & SCSI_RW_DIRMASK) == SCSI_RW_READ;
+
        /*
         * Use the smallest possible command to perform the operation
         * as some legacy hardware does not support the 10 byte commands.
@@ -5696,7 +5700,7 @@ scsi_read_write(struct ccb_scsiio *csio,
                struct scsi_rw_6 *scsi_cmd;
 
                scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
-               scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
+               scsi_cmd->opcode = read ? READ_6 : WRITE_6;
                scsi_ulto3b(lba, scsi_cmd->addr);
                scsi_cmd->length = block_count & 0xff;
                scsi_cmd->control = 0;
@@ -5715,7 +5719,7 @@ scsi_read_write(struct ccb_scsiio *csio,
                struct scsi_rw_10 *scsi_cmd;
 
                scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
-               scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
+               scsi_cmd->opcode = read ? READ_10 : WRITE_10;
                scsi_cmd->byte2 = byte2;
                scsi_ulto4b(lba, scsi_cmd->addr);
                scsi_cmd->reserved = 0;
@@ -5738,7 +5742,7 @@ scsi_read_write(struct ccb_scsiio *csio,
                struct scsi_rw_12 *scsi_cmd;
 
                scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
-               scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
+               scsi_cmd->opcode = read ? READ_12 : WRITE_12;
                scsi_cmd->byte2 = byte2;
                scsi_ulto4b(lba, scsi_cmd->addr);
                scsi_cmd->reserved = 0;
@@ -5760,7 +5764,7 @@ scsi_read_write(struct ccb_scsiio *csio,
                struct scsi_rw_16 *scsi_cmd;
 
                scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes;
-               scsi_cmd->opcode = readop ? READ_16 : WRITE_16;
+               scsi_cmd->opcode = read ? READ_16 : WRITE_16;
                scsi_cmd->byte2 = byte2;
                scsi_u64to8b(lba, scsi_cmd->addr);
                scsi_cmd->reserved = 0;
@@ -5771,7 +5775,8 @@ scsi_read_write(struct ccb_scsiio *csio,
        cam_fill_csio(csio,
                      retries,
                      cbfcnp,
-                     /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
+                     (read ? CAM_DIR_IN : CAM_DIR_OUT) |
+                     ((readop & SCSI_RW_BIO) != 0 ? CAM_DATA_BIO : 0),
                      tag_action,
                      data_ptr,
                      dxfer_len,

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h        Tue Mar 19 14:53:23 2013        
(r248518)
+++ head/sys/cam/scsi/scsi_all.h        Tue Mar 19 15:01:50 2013        
(r248519)
@@ -2354,6 +2354,10 @@ void scsi_write_buffer(struct ccb_scsiio
                        uint8_t *data_ptr, uint32_t param_list_length,
                        uint8_t sense_len, uint32_t timeout);
 
+#define        SCSI_RW_READ    0x0001
+#define        SCSI_RW_WRITE   0x0002
+#define        SCSI_RW_DIRMASK 0x0003
+#define        SCSI_RW_BIO     0x1000
 void scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
                     void (*cbfcnp)(struct cam_periph *, union ccb *),
                     u_int8_t tag_action, int readop, u_int8_t byte2, 

Modified: head/sys/cam/scsi/scsi_cd.c
==============================================================================
--- head/sys/cam/scsi/scsi_cd.c Tue Mar 19 14:53:23 2013        (r248518)
+++ head/sys/cam/scsi/scsi_cd.c Tue Mar 19 15:01:50 2013        (r248519)
@@ -1575,7 +1575,8 @@ cdstart(struct cam_periph *periph, union
                                        /*retries*/ cd_retry_count,
                                        /* cbfcnp */ cddone,
                                        MSG_SIMPLE_Q_TAG,
-                                       /* read */bp->bio_cmd == BIO_READ,
+                                       /* read */bp->bio_cmd == BIO_READ ?
+                                       SCSI_RW_READ : SCSI_RW_WRITE,
                                        /* byte2 */ 0,
                                        /* minimum_cmd_size */ 10,
                                        /* lba */ bp->bio_offset /

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c Tue Mar 19 14:53:23 2013        (r248518)
+++ head/sys/cam/scsi/scsi_da.c Tue Mar 19 15:01:50 2013        (r248519)
@@ -1184,7 +1184,7 @@ dadump(void *arg, void *virtual, vm_offs
                                /*retries*/0,
                                dadone,
                                MSG_ORDERED_Q_TAG,
-                               /*read*/FALSE,
+                               /*read*/SCSI_RW_WRITE,
                                /*byte2*/0,
                                /*minimum_cmd_size*/ softc->minimum_cmd_size,
                                offset / secsize,
@@ -1757,6 +1757,8 @@ daregister(struct cam_periph *periph, vo
        softc->disk->d_flags = 0;
        if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
                softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
+       if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
+               softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
        cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
            sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
        strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
@@ -1985,14 +1987,18 @@ dastart(struct cam_periph *periph, union
                                        /*retries*/da_retry_count,
                                        /*cbfcnp*/dadone,
                                        /*tag_action*/tag_code,
-                                       /*read_op*/bp->bio_cmd
-                                               == BIO_READ,
+                                       /*read_op*/(bp->bio_cmd == BIO_READ ?
+                                       SCSI_RW_READ : SCSI_RW_WRITE) |
+                                       ((bp->bio_flags & BIO_UNMAPPED) != 0 ?
+                                       SCSI_RW_BIO : 0),
                                        /*byte2*/0,
                                        softc->minimum_cmd_size,
                                        /*lba*/bp->bio_pblkno,
                                        /*block_count*/bp->bio_bcount /
                                        softc->params.secsize,
-                                       /*data_ptr*/ bp->bio_data,
+                                       /*data_ptr*/ (bp->bio_flags &
+                                       BIO_UNMAPPED) != 0 ? (void *)bp :
+                                       bp->bio_data,
                                        /*dxfer_len*/ bp->bio_bcount,
                                        /*sense_len*/SSD_FULL_SIZE,
                                        da_default_timeout * 1000);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to