diff -Naur old/drivers/md/dm-statistic.c new/drivers/md/dm-statistic.c --- old/drivers/md/dm-statistic.c 1969-12-31 19:00:00.000000000 -0500 +++ new/drivers/md/dm-statistic.c 2013-04-29 02:02:22.219127000 -0400 @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2001-2003 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DM_MSG_PREFIX "statistic" + +#define STATISTIC_IOC_MAGIC 0xa1 +#define RESET_TIME _IO(STATISTIC_IOC_MAGIC, 0) +#define RESET_SPEED _IOW(STATISTIC_IOC_MAGIC, 1, unsigned long) +#define STATISTIC_IOC_MAXNR 2 + +static unsigned long write_per_sec = 1; /* One bio per second by default */ +module_param(write_per_sec, ulong, 0); + +/* + * statistic: maps a statistic range of a device. + */ +struct statistic_c { + struct dm_dev *dev; + sector_t start; +}; + +static struct mutex lock; + +static struct list_head head; +static struct list_head head_write; + +struct bio_data +{ + struct list_head list; + unsigned long bio_time; + struct bio bio_value; +}; + +unsigned long base_time; + +static void *statistic_seq_start(struct seq_file *s, loff_t *pos) +{ + mutex_lock(&lock); + return seq_list_start(&head, *pos); +} + +static void *statistic_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return seq_list_next(v, &head, pos); +} + +static void *statistic_seq_stop(struct seq_file *s, void *v) +{ + mutex_unlock(&lock); + return NULL; +} + +static int statistic_seq_show(struct seq_file *s, void *v) +{ + struct bio_data *data = list_entry(v, struct bio_data, list); + + seq_printf(s, "struct bio:\n"); + //seq_printf(s, "bi_cnt=%d\n", data->bio_value.bi_cnt); + seq_printf(s, "time: %lu\n", data->bio_time); + seq_printf(s, "Read or Write %lx\n", data->bio_value.bi_rw & 0x0001); + seq_printf(s, "\n"); + return 0; +} + +static struct seq_operations seq_ops = { + .start = statistic_seq_start, + .next = statistic_seq_next, + .stop = statistic_seq_stop, + .show = statistic_seq_show +}; + +static int statistic_open(struct inode *inode, struct file *file) +{ + return (seq_open(file, &seq_ops)); +} + +static struct file_operations seq_fops = { + .owner = THIS_MODULE, + .open = statistic_open, + .read = seq_read, + //.write = seq_write, + .llseek = seq_lseek, + .release = seq_release, +}; + +/* + * Construct a statistic mapping: + */ +static int statistic_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + struct statistic_c *lc; + unsigned long long tmp; + char dummy; + + if (argc != 2) { + ti->error = "Invalid argument count"; + return -EINVAL; + } + + lc = kmalloc(sizeof(*lc), GFP_KERNEL); + if (lc == NULL) { + ti->error = "dm-statistic: Cannot allocate statistic context"; + return -ENOMEM; + } + + if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) { + ti->error = "dm-statistic: Invalid device sector"; + goto bad; + } + lc->start = tmp; + + if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) { + ti->error = "dm-statistic: Device lookup failed"; + goto bad; + } + + ti->num_flush_requests = 1; + ti->num_discard_requests = 1; + ti->num_write_same_requests = 1; + ti->private = lc; + return 0; + + bad: + kfree(lc); + return -EINVAL; +} + +static void statistic_dtr(struct dm_target *ti) +{ + struct statistic_c *lc = (struct statistic_c *) ti->private; + + dm_put_device(ti, lc->dev); + kfree(lc); +} + +static sector_t statistic_map_sector(struct dm_target *ti, sector_t bi_sector) +{ + struct statistic_c *lc = ti->private; + + return lc->start + dm_target_offset(ti, bi_sector); +} + +static void add_bio(struct bio *bio) +{ + unsigned long current_time = jiffies - base_time; + struct bio_data *data; + + + mutex_lock(&lock); + data = (struct bio_data *)kmalloc(sizeof(*data), GFP_KERNEL); + if (data != NULL) + { + data->bio_time = current_time; + data->bio_value = *bio; + list_add(&data->list, &head); + if (data->bio_value.bi_rw & 0x0001) /* add the bio to the list if it is a write bio*/ + list_add(&data->list, &head_write); + } + mutex_unlock(&lock); +} + +static void bio_statistic(struct bio *bio) +{ + //int recent_bio; + struct bio_data *data; + if ((bio->bi_rw & 0x0001) && write_per_sec!=0) + { + if (!list_empty(&head_write)) + { + data = list_entry((&head_write)->next, struct bio_data, list); + if (jiffies-base_time-data->bio_timebio_time)); + } + } + + } + + add_bio(bio); + + //if (entry) + //entry->proc_fops = &seq_fops; + + printk(KERN_INFO "struct bio\n"); + printk(KERN_INFO "bi_flags=%lx\n", bio->bi_flags); + printk(KERN_INFO "bi_rw=%lx\n", bio->bi_rw); + //printk(KERN_INFO "bi_cnt=%d\n", bio->bi_cnt); + printk(KERN_INFO "\n"); +} + +static void clean_all(struct list_head *head) +{ + struct bio_data *data; + + while (!list_empty(head)) + { + data = list_entry(head->next, struct bio_data, list); + list_del(&data->list); + kfree(data); + } +} + +static void statistic_map_bio(struct dm_target *ti, struct bio *bio) +{ + struct statistic_c *lc = ti->private; + + bio_statistic(bio); + + //printk(KERN_INFO "In statistic_map_bio\nTestTestTest\n"); + + bio->bi_bdev = lc->dev->bdev; + if (bio_sectors(bio)) + bio->bi_sector = statistic_map_sector(ti, bio->bi_sector); +} + +static int statistic_map(struct dm_target *ti, struct bio *bio) +{ + statistic_map_bio(ti, bio); + + return DM_MAPIO_REMAPPED; +} + +static void statistic_status(struct dm_target *ti, status_type_t type, + unsigned status_flags, char *result, unsigned maxlen) +{ + struct statistic_c *lc = (struct statistic_c *) ti->private; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + snprintf(result, maxlen, "%s %llu", lc->dev->name, + (unsigned long long)lc->start); + break; + } +} + +static void statistic_reset_time(void) +{ + base_time = jiffies; + clean_all(&head); + clean_all(&head_write); +} +EXPORT_SYMBOL_GPL(statistic_reset_time); + +static void statistic_reset_speed(unsigned long arg) +{ + write_per_sec = arg; +} +EXPORT_SYMBOL_GPL(statistic_reset_speed); + +static int statistic_ioctl(struct dm_target *ti, unsigned int cmd, + unsigned long arg) +{ + struct statistic_c *lc = (struct statistic_c *) ti->private; + struct dm_dev *dev = lc->dev; + int r = 0; + + switch (cmd) + { + case RESET_TIME: statistic_reset_time(); break; + case RESET_SPEED: statistic_reset_speed(arg); break; + default: break; + } + + /* + * Only pass ioctls through if the device sizes match exactly. + */ + if (lc->start || + ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT) + r = scsi_verify_blk_ioctl(NULL, cmd); + + return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg); +} + +static int statistic_merge(struct dm_target *ti, struct bvec_merge_data *bvm, + struct bio_vec *biovec, int max_size) +{ + struct statistic_c *lc = ti->private; + struct request_queue *q = bdev_get_queue(lc->dev->bdev); + + if (!q->merge_bvec_fn) + return max_size; + + bvm->bi_bdev = lc->dev->bdev; + bvm->bi_sector = statistic_map_sector(ti, bvm->bi_sector); + + return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); +} + +static int statistic_iterate_devices(struct dm_target *ti, + iterate_devices_callout_fn fn, void *data) +{ + struct statistic_c *lc = ti->private; + + return fn(ti, lc->dev, lc->start, ti->len, data); +} + +static struct target_type statistic_target = { + .name = "statistic", + .version = {0, 1, 0}, + .module = THIS_MODULE, + .ctr = statistic_ctr, + .dtr = statistic_dtr, + .map = statistic_map, + .status = statistic_status, + .ioctl = statistic_ioctl, + .merge = statistic_merge, + .iterate_devices = statistic_iterate_devices, +}; + +int jiffies_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len; + if (off > 0) + { + *eof = 1; + return 0; + } + //len += sprintf(page, "%lu\n", base_time); + len = sprintf(page, "HZ=%d\nbase_time=%lu\ncurrent_jiffies=%lu\n",HZ, base_time, jiffies); + return len; +} + +static int proc_init(void) +{ + struct proc_dir_entry *entry, *jiffies_info; + + mutex_init(&lock); + INIT_LIST_HEAD(&head); + INIT_LIST_HEAD(&head_write); + + entry = create_proc_entry("statistic", S_IWUSR | S_IRUGO, NULL); + if (entry == NULL) + { + clean_all(&head); + return -ENOMEM; + } + base_time = jiffies; + entry->proc_fops = &seq_fops; + + jiffies_info = create_proc_entry("jiffies", S_IWUSR | S_IRUGO, NULL); + if (jiffies_info == NULL) + { + return -ENOMEM; + } + jiffies_info->read_proc = jiffies_read; + + + return 0; +} + +int __init dm_statistic_init(void) +{ + int r = dm_register_target(&statistic_target); + + if (r < 0) + DMERR("register failed %d", r); + + proc_init(); + + return r; +} + +static void proc_exit(void) +{ + remove_proc_entry("jiffies", NULL); + remove_proc_entry("statistic", NULL); + clean_all(&head); + clean_all(&head_write); +} + +void dm_statistic_exit(void) +{ + proc_exit(); + + dm_unregister_target(&statistic_target); +} diff -Naur old/drivers/md/Makefile new/drivers/md/Makefile --- old/drivers/md/Makefile 2013-04-12 12:52:28.000000000 -0400 +++ new/drivers/md/Makefile 2013-04-29 02:06:00.283123886 -0400 @@ -2,7 +2,7 @@ # Makefile for the kernel software RAID and LVM drivers. # -dm-mod-y += dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ +dm-mod-y += dm.o dm-table.o dm-target.o dm-linear.o dm-statistic.o dm-stripe.o \ dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o dm-multipath-y += dm-path-selector.o dm-mpath.o dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ diff -Naur old/drivers/md/Makefile~ new/drivers/md/Makefile~ --- old/drivers/md/Makefile~ 1969-12-31 19:00:00.000000000 -0500 +++ new/drivers/md/Makefile~ 2013-04-12 12:52:28.000000000 -0400 @@ -0,0 +1,50 @@ +# +# Makefile for the kernel software RAID and LVM drivers. +# + +dm-mod-y += dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ + dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o +dm-multipath-y += dm-path-selector.o dm-mpath.o +dm-snapshot-y += dm-snap.o dm-exception-store.o dm-snap-transient.o \ + dm-snap-persistent.o +dm-mirror-y += dm-raid1.o +dm-log-userspace-y \ + += dm-log-userspace-base.o dm-log-userspace-transfer.o +dm-thin-pool-y += dm-thin.o dm-thin-metadata.o +md-mod-y += md.o bitmap.o +raid456-y += raid5.o + +# Note: link order is important. All raid personalities +# and must come before md.o, as they each initialise +# themselves, and md.o may use the personalities when it +# auto-initialised. + +obj-$(CONFIG_MD_LINEAR) += linear.o +obj-$(CONFIG_MD_RAID0) += raid0.o +obj-$(CONFIG_MD_RAID1) += raid1.o +obj-$(CONFIG_MD_RAID10) += raid10.o +obj-$(CONFIG_MD_RAID456) += raid456.o +obj-$(CONFIG_MD_MULTIPATH) += multipath.o +obj-$(CONFIG_MD_FAULTY) += faulty.o +obj-$(CONFIG_BLK_DEV_MD) += md-mod.o +obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o +obj-$(CONFIG_DM_BUFIO) += dm-bufio.o +obj-$(CONFIG_DM_BIO_PRISON) += dm-bio-prison.o +obj-$(CONFIG_DM_CRYPT) += dm-crypt.o +obj-$(CONFIG_DM_DELAY) += dm-delay.o +obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o +obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o +obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o +obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o +obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o +obj-$(CONFIG_DM_PERSISTENT_DATA) += persistent-data/ +obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o +obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o +obj-$(CONFIG_DM_ZERO) += dm-zero.o +obj-$(CONFIG_DM_RAID) += dm-raid.o +obj-$(CONFIG_DM_THIN_PROVISIONING) += dm-thin-pool.o +obj-$(CONFIG_DM_VERITY) += dm-verity.o + +ifeq ($(CONFIG_DM_UEVENT),y) +dm-mod-objs += dm-uevent.o +endif