// Block I/O tapset
// Copyright (C) 2006 Intel Corp.
+// Copyright (C) 2006 IBM Corp.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
// later version.
%{
-#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/genhd.h>
%}
-/* probe ioblock.submit
+/* get i-node number of mapped file */
+function __bio_ino:long(bio:long)
+%{
+ struct bio *bio = (struct bio *)(long)THIS->bio;
+ if ((bio->bi_io_vec[0].bv_page == NULL) ||
+ (bio->bi_io_vec[0].bv_page->mapping == NULL))
+ THIS->__retvalue = -1;
+ else
+ THIS->__retvalue = bio->bi_io_vec[0].bv_page->mapping->host->i_ino;
+ if (0) {
+deref_fault:
+ CONTEXT->last_error = "pointer dereference fault";
+ }
+%}
+
+/* returns 0 for read, 1 for write */
+function __bio_direction:long(rw:long)
+%{
+ long rw = (long)THIS->rw;
+ THIS->__retvalue = (rw & (1 << BIO_RW));
+%}
+
+/* returns R for read, W for write */
+function bio_rw_str(rw)
+{
+ return __bio_direction(rw) == BIO_READ ? "R" : "W"
+}
+
+/* returns start sector */
+function __bio_start_sect:long(bio:long)
+%{
+ struct bio *bio = (struct bio *)(long)THIS->bio;
+ if ((bio == NULL) || (bio->bi_bdev == NULL) ||
+ (bio->bi_bdev->bd_part == NULL))
+ THIS->__retvalue = -1;
+ else
+ THIS->__retvalue = bio->bi_bdev->bd_part->start_sect;
+ if (0) {
+deref_fault:
+ CONTEXT->last_error = "pointer dereference fault";
+ }
+%}
+
+/* returns the block device name */
+function __bio_devname:string(bio:long)
+%{
+ char b[BDEVNAME_SIZE];
+ struct bio *bio = (struct bio *)(long)THIS->bio;
+ if (bio == NULL || bio->bi_bdev == NULL) {
+ strlcpy(THIS->__retvalue, "N/A", MAXSTRINGLEN);
+ return;
+ }
+ deref_string(THIS->__retvalue, bdevname(bio->bi_bdev,b), MAXSTRINGLEN);
+ if (0) {
+deref_fault:
+ CONTEXT->last_error = "pointer dereference fault";
+ }
+%}
+
+global BIO_READ, BIO_WRITE
+probe begin
+{
+ BIO_READ = 0
+ BIO_WRITE = 1
+}
+
+/* probe ioblock.request
*
- * Fires whenever a block I/O is submitted.
+ * Fires whenever making a generic block I/O request.
*
* Context:
- * The process which submits block I/O
+ * The process makes block I/O request
*
- * Arguments:
- * rw_string - string (READ/WRITE).
- * rw - binary trace for read/write
- * sector - beginning sector for the entire bio
- * bio_devname - block device name
+ * Variables:
+ * devname - block device name
+ * ino - i-node number of the mapped file
+ * sector - beginning sector for the entire bio
+ * flags - see below
+ * BIO_UPTODATE 0 ok after I/O completion
+ * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block
+ * BIO_EOF 2 out-out-bounds error
+ * BIO_SEG_VALID 3 nr_hw_seg valid
+ * BIO_CLONED 4 doesn't own data
+ * BIO_BOUNCED 5 bio is a bounce bio
+ * BIO_USER_MAPPED 6 contains user pages
+ * BIO_EOPNOTSUPP 7 not supported
+ *
+ * rw_str - read/write request
+ * rw - binary trace for read/write request
+ * vcnt - bio vector count which represents number of array element (page,
+ * offset, length) which make up this I/O request
+ * idx - offset into the bio vector array
+ * phys_segments - number of segments in this bio after physical address
+ * coalescing is performed.
+ * hw_segments - number of segments after physical and DMA remapping
+ * hardware coalescing is performed
+ * size - total size in bytes
+ * bdev - target block device
+ * bdev_contains - points to the device object which contains the
+ * partition (when bio structure represents a partition)
+ * p_start_sect - points to the start sector of the partition
+ * structure of the device
*/
-probe ioblock.submit
- = kernel.function("submit_bio")
+probe ioblock.request = kernel.function ("generic_make_request")
{
- rw_string = bio_read_write($rw);
- rw = $rw
- sector = $bio->bi_sector
- bio_devname = bio_devname($bio)
+ devname = __bio_devname($bio)
+ ino = __bio_ino($bio)
+
+ sector = $bio->bi_sector
+ flags = $bio->bi_flags
+ rw = $bio->bi_rw
+ vcnt = $bio->bi_vcnt
+ idx = $bio->bi_idx
+ phys_segments = $bio->bi_phys_segments
+ hw_segments = $bio->bi_hw_segments
+ size = $bio->bi_size
+
+ bdev = $bio->bi_bdev
+ bdev_contains = $bio->bi_bdev->bd_contains
+ p_start_sect = __bio_start_sect($bio)
}
/* probe ioblock.end
* Fires whenever a block I/O transfer is complete.
*
* Context:
- * The process which signals the transfer is done.
+ * The process signals the transfer is done.
*
- * Arguments:
- * rw_string - string (READ/WRITE).
- * rw - binary trace for read/write
- * sector - beginning sector for the entire bio
- * bytes_done - number of bytes done
- * error - success: 0
- * bio_devname - block device name
+ * Variables:
+ * devname - block device name
+ * ino - i-node number of the mapped file
+ * byte_done - number of bytes transferred
+ * sector - beginning sector for the entire bio
+ * flags - see below
+ * BIO_UPTODATE 0 ok after I/O completion
+ * BIO_RW_BLOCK 1 RW_AHEAD set, and read/write would block
+ * BIO_EOF 2 out-out-bounds error
+ * BIO_SEG_VALID 3 nr_hw_seg valid
+ * BIO_CLONED 4 doesn't own data
+ * BIO_BOUNCED 5 bio is a bounce bio
+ * BIO_USER_MAPPED 6 contains user pages
+ * BIO_EOPNOTSUPP 7 not supported
+ * error - 0 on success
+ * rw_str - read/write request
+ * rw - binary trace for read/write request
+ * vcnt - bio vector count which represents number of array element (page,
+ * offset, length) which makes up this I/O request
+ * idx - offset into the bio vector array
+ * phys_segments - number of segments in this bio after physical address
+ * coalescing is performed.
+ * hw_segments - number of segments after physical and DMA remapping
+ * hardware coalescing is performed
+ * size - total size in bytes
*/
-probe ioblock.end
- = kernel.function("bio_endio")
+probe ioblock.end = kernel.function("bio_endio")
{
- rw_string = bio_read_write($bio->bi_rw)
- rw = $bio->bi_rw
- sector = $bio->bi_sector
- bytes_done = $bytes_done;
- error = $error;
- bio_devname = bio_devname($bio)
-}
+ devname = __bio_devname($bio)
+ ino = __bio_ino($bio)
+ bytes_done = $bytes_done
+ error = $error
-/* Return the block device name */
-function bio_devname:string(bio:long)
-%{
- char b[BDEVNAME_SIZE] = "";
- struct bio *bp;
-
- bp = (struct bio *) ((unsigned long) THIS->bio);
- if (bp->bi_bdev)
- bdevname(bp->bi_bdev,b);
- sprintf(THIS->__retvalue,"%s",b);
-%}
-
-/* Return a READ/WRITE status string */
-function bio_read_write:string(var_rw:long)
-%{
- sprintf(THIS->__retvalue,"%s", (THIS->var_rw & WRITE) ? "WRITE" : "READ");
-%}
+ sector = $bio->bi_sector
+ flags = $bio->bi_flags
+ rw = $bio->bi_rw
+ vcnt = $bio->bi_vcnt
+ idx = $bio->bi_idx
+ phys_segments = $bio->bi_phys_segments
+ hw_segments = $bio->bi_hw_segments
+ size = $bio->bi_size
+}