7a8 > #include 12a14,18 > #include > #include > #include > #include > #include 15c21,29 < #define DM_MSG_PREFIX "linear" --- > #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); 18c32 < * Linear: maps a linear range of a device. --- > * statistic: maps a statistic range of a device. 20c34 < struct linear_c { --- > struct statistic_c { 24a39,102 > 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, > }; > 26c104 < * Construct a linear mapping: --- > * Construct a statistic mapping: 28c106 < static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) --- > static int statistic_ctr(struct dm_target *ti, unsigned int argc, char **argv) 30c108 < struct linear_c *lc; --- > struct statistic_c *lc; 41c119 < ti->error = "dm-linear: Cannot allocate linear context"; --- > ti->error = "dm-statistic: Cannot allocate statistic context"; 46c124 < ti->error = "dm-linear: Invalid device sector"; --- > ti->error = "dm-statistic: Invalid device sector"; 52c130 < ti->error = "dm-linear: Device lookup failed"; --- > ti->error = "dm-statistic: Device lookup failed"; 67c145 < static void linear_dtr(struct dm_target *ti) --- > static void statistic_dtr(struct dm_target *ti) 69c147 < struct linear_c *lc = (struct linear_c *) ti->private; --- > struct statistic_c *lc = (struct statistic_c *) ti->private; 75c153 < static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector) --- > static sector_t statistic_map_sector(struct dm_target *ti, sector_t bi_sector) 77c155 < struct linear_c *lc = ti->private; --- > struct statistic_c *lc = ti->private; 82c160,179 < static void linear_map_bio(struct dm_target *ti, struct bio *bio) --- > 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) 84c181,226 < struct linear_c *lc = ti->private; --- > //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_time { > msleep(HZ-(jiffies-base_time-data->bio_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"); 88c230 < bio->bi_sector = linear_map_sector(ti, bio->bi_sector); --- > bio->bi_sector = statistic_map_sector(ti, bio->bi_sector); 91c233 < static int linear_map(struct dm_target *ti, struct bio *bio) --- > static int statistic_map(struct dm_target *ti, struct bio *bio) 93c235 < linear_map_bio(ti, bio); --- > statistic_map_bio(ti, bio); 98c240 < static void linear_status(struct dm_target *ti, status_type_t type, --- > static void statistic_status(struct dm_target *ti, status_type_t type, 101c243 < struct linear_c *lc = (struct linear_c *) ti->private; --- > struct statistic_c *lc = (struct statistic_c *) ti->private; 115c257,271 < static int linear_ioctl(struct dm_target *ti, unsigned int cmd, --- > 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, 118c274 < struct linear_c *lc = (struct linear_c *) ti->private; --- > struct statistic_c *lc = (struct statistic_c *) ti->private; 120a277,283 > > switch (cmd) > { > case RESET_TIME: statistic_reset_time(); break; > case RESET_SPEED: statistic_reset_speed(arg); break; > default: break; > } 132c295 < static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm, --- > static int statistic_merge(struct dm_target *ti, struct bvec_merge_data *bvm, 135c298 < struct linear_c *lc = ti->private; --- > struct statistic_c *lc = ti->private; 142c305 < bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector); --- > bvm->bi_sector = statistic_map_sector(ti, bvm->bi_sector); 147c310 < static int linear_iterate_devices(struct dm_target *ti, --- > static int statistic_iterate_devices(struct dm_target *ti, 150c313 < struct linear_c *lc = ti->private; --- > struct statistic_c *lc = ti->private; 155,157c318,320 < static struct target_type linear_target = { < .name = "linear", < .version = {1, 2, 1}, --- > static struct target_type statistic_target = { > .name = "statistic", > .version = {0, 1, 0}, 159,165c322,328 < .ctr = linear_ctr, < .dtr = linear_dtr, < .map = linear_map, < .status = linear_status, < .ioctl = linear_ioctl, < .merge = linear_merge, < .iterate_devices = linear_iterate_devices, --- > .ctr = statistic_ctr, > .dtr = statistic_dtr, > .map = statistic_map, > .status = statistic_status, > .ioctl = statistic_ioctl, > .merge = statistic_merge, > .iterate_devices = statistic_iterate_devices, 168c331 < int __init dm_linear_init(void) --- > int jiffies_read(char *page, char **start, off_t off, int count, int *eof, void *data) 170c333,374 < int r = dm_register_target(&linear_target); --- > 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); 174a379,380 > proc_init(); > 178c384,392 < void dm_linear_exit(void) --- > 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) 180c394,396 < dm_unregister_target(&linear_target); --- > proc_exit(); > > dm_unregister_target(&statistic_target);