bioclone(9F)




NAME

     bioclone - clone another buffer


SYNOPSIS

     #include <sys/ddi.h> #include <sys/sunddi.h>

     struct buf *bioclone(struct buf *bp, off_t off, size_t  len,
     dev_t  dev,  daddr_t  blkno,  int  (*iodone) (struct buf *),
     struct buf *bp_mem, int sleepflag);


INTERFACE LEVEL

     Solaris DDI specific (Solaris DDI).


PARAMETERS

      bp   Pointer to the buf(9S) structure describing the origi-
           nal I/O request.

     off   Offset within  original  I/O  request  where  new  I/O
           request should start.

     len   Length of the I/O request.

     dev   Device number.

     blkno Block number on device.

     iodone
           Specific biodone(9F) routine.

     bp_mem
           Pointer to a buffer structure to be filled in or NULL.

     sleepflag
           Determines whether caller can sleep for memory. Possi-
           ble  flags are KM_SLEEP to allow sleeping until memory
           is available, or KM_NOSLEEP to return NULL immediately
           if memory is not available.


DESCRIPTION

     bioclone() returns an initialized buffer to perform I/O to a
     portion  of another buffer. The new buffer will be set up to
     perform I/O to the range within  the  original  I/O  request
     specified by the parameters off and len.  An offset 0 starts
     the new I/O request at the  same  address  as  the  original
     request.  off  + len must not exceed b_bcount, the length of
     the original request. The device number  dev  specifies  the
     device  to  which the buffer is to perform I/O. blkno is the
     block number on device.  It will be assigned to the  b_blkno
     field of the cloned buffer structure. iodone lets the driver
     identify a specific biodone(9F) routine to be called by  the
     driver  when  the  I/O  is  complete. bp_mem determines from
     where the space for  the  buffer  should  be  allocated.  If
     bp_mem  is NULL, bioclone() will allocate a new buffer using
     getrbuf(9F).  If sleepflag is set to  KM_SLEEP,  the  driver
     may  sleep  until  space is freed up. If sleepflag is set to
     KM_NOSLEEP, the driver will not sleep.  In  either  case,  a
     pointer  to the allocated space is returned or NULL to indi-
     cate that no space was available. After the transfer is com-
     pleted,  the  buffer has to be freed using freerbuf(9F).  If
     bp_mem is not NULL, it will be used as  the  space  for  the
     buffer  structure.  The  driver has to ensure that bp_mem is
     initialized   properly   either   using    getrbuf(9F)    or
     bioinit(9F).

     If the original buffer is mapped  into  the  kernel  virtual
     address  space using bp_mapin(9F) before calling bioclone(),
     a clone buffer will share the kernel mapping of the original
     buffer. An additional bp_mapin() to get a kernel mapping for
     the clone buffer is not necessary.

     The driver has to ensure that the  original  buffer  is  not
     freed  while  any  of  the clone buffers is still performing
     I/O. The biodone() function has to be called  on  all  clone
     buffers before it is called on the original buffer.


RETURN VALUES

     The bioclone() function returns a pointer to the initialized
     buffer header, or NULL if no space is available.


CONTEXT

     bioclone() can be called from  user  or  interrupt  context.
     Drivers must not allow bioclone() to sleep if called from an
     interrupt routine.


EXAMPLES

     Example 1: Using bioclone() for Disk Striping

     A device driver can use bioclone() for disk  striping.   For
     each  disk  in  the  stripe, a clone buffer is created which
     performs I/O to a portion of the original buffer.

     static int
     stripe_strategy(struct buf *bp)
     {
            ...
            bp_orig = bp;
            bp_1 = bioclone(bp_orig, 0, size_1, dev_1, blkno_1,
                            stripe_done, NULL, KM_SLEEP);
            fragment++;
            ...
            bp_n = bioclone(bp_orig, offset_n, size_n, dev_n,
                          blkno_n, stripe_done, NULL, KM_SLEEP);
            fragment++;
            /* submit bp_1 ... bp_n to device */
            xxstrategy(bp_x);
            return (0);
     }

     static uint_t
     xxintr(caddr_t arg)
     {
            ...
            /*
            * get bp of completed subrequest. biodone(9F) will
            * call stripe_done()
            */
            biodone(bp);
            return (0);
     }

     static int
     stripe_done(struct buf *bp)
     {
            ...
            freerbuf(bp);
            fragment--;
            if (fragment == 0) {
                    /* get bp_orig */
                    biodone(bp_orig);
            }
            return (0);
     }


SEE ALSO

     biodone(9F),   bp_mapin(9F),   freerbuf(9F),    getrbuf(9F),
     buf(9S)

     Writing Device Drivers


Man(1) output converted with man2html