📄 sd_iostats-2.6-rhel4.patch
字号:
Index: linux-2.6.9-5.0.3.EL/drivers/scsi/Kconfig
===================================================================
Index: linux+rhel4+chaos/drivers/scsi/Kconfig===================================================================--- linux+rhel4+chaos.orig/drivers/scsi/Kconfig+++ linux+rhel4+chaos/drivers/scsi/Kconfig@@ -61,6 +61,14 @@ config SCSI_DUMP help SCSI dump support +config SD_IOSTATS+ bool "Enable SCSI disk I/O stats"+ depends on BLK_DEV_SD+ default y+ ---help---+ This enables SCSI disk I/O stats collection. You must also enable+ /proc file system support if you want this feature.+ config CHR_DEV_ST tristate "SCSI tape support" depends on SCSIIndex: linux+rhel4+chaos/drivers/scsi/sd.c===================================================================--- linux+rhel4+chaos.orig/drivers/scsi/sd.c+++ linux+rhel4+chaos/drivers/scsi/sd.c@@ -63,6 +63,38 @@ #include "scsi_logging.h" +#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))+# include <linux/proc_fs.h>+# include <linux/seq_file.h>++typedef struct {+ unsigned long long iostat_size;+ unsigned long long iostat_count;+} iostat_counter_t;++#define IOSTAT_NCOUNTERS 16+typedef struct {+ iostat_counter_t iostat_read_histogram[IOSTAT_NCOUNTERS];+ iostat_counter_t iostat_write_histogram[IOSTAT_NCOUNTERS];+ struct timeval iostat_timeval;+} iostat_stats_t;++iostat_stats_t **sd_iostats;+spinlock_t sd_iostats_lock;+struct proc_dir_entry *sd_iostats_procdir;+char sd_iostats_procdir_name[] = "sd_iostats";++extern void sd_iostats_init(void);+extern void sd_iostats_init_disk(struct gendisk *);+extern void sd_iostats_fini(void);+extern void sd_iostats_bump(int disk, unsigned int nsect, int iswrite);+#else+static inline void sd_iostats_init(void) {}+static inline void sd_iostats_init_disk(struct gendisk *disk) {}+static inline void sd_iostats_fini(void) {}+static inline void sd_iostats_bump(int disk, unsigned int nsect, int iswrite) {}+#endif+ /* * More than enough for everybody ;) The huge number of majors * is a leftover from 16bit dev_t days, we don't really need that@@ -76,6 +108,7 @@ */ #define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) +#define SD_STATS 256 /* * Time out in seconds for disks and Magneto-opticals (which are slower). */@@ -278,6 +311,9 @@ static int sd_init_command(struct scsi_c SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n", disk->disk_name, (unsigned long long)block)); + sd_iostats_bump(scsi_disk(disk)->index, this_count,+ rq_data_dir(SCpnt->request) == WRITE);+ /* * If we have a 1K hardware sectorsize, prevent access to single * 512 byte sectors. In theory we could handle this - in fact@@ -474,6 +510,7 @@ static int sd_open(struct inode *inode, scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); } + sd_iostats_init_disk(disk); return 0; error_out:@@ -500,8 +537,20 @@ static int sd_release(struct inode *inod SCSI_LOG_HLQUEUE(3, printk("sd_release: disk=%s\n", disk->disk_name)); - if (!--sdkp->openers && sdev->removable) {- if (scsi_block_when_processing_errors(sdev))+ if (!--sdkp->openers) {+ /*+ * Remove sd_iostats information about this disk+ */+ if (sd_iostats_procdir != NULL) {+ remove_proc_entry(disk->disk_name, sd_iostats_procdir);+ }+ if (sd_iostats != NULL) {+ if (sd_iostats[sdkp->index] != NULL) {+ kfree (sd_iostats[sdkp->index]);+ sd_iostats[sdkp->index] = NULL;+ }+ }+ if (sdev->removable && scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } @@ -1575,6 +1624,342 @@ static void sd_shutdown(struct device *d sd_sync_cache(sdp); } +#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))+static int+sd_iostats_seq_show(struct seq_file *seq, void *v)+{+ struct timeval now;+ struct gendisk *disk;+ iostat_stats_t *stats;+ unsigned long long read_len;+ unsigned long long read_len_tot;+ unsigned long read_num;+ unsigned long read_num_tot;+ unsigned long long write_len;+ unsigned long long write_len_tot;+ unsigned long write_num;+ unsigned long write_num_tot;+ int i;+ int maxi;++ if (seq == NULL || seq->private == NULL) {+ printk(KERN_ERR "sd_iostats_seq_show: NULL disk\n");+ BUG();+ }++ disk = seq->private;++ if (scsi_disk(disk) == NULL || (disk->flags & GENHD_FL_UP) == 0) {+ seq_printf(seq, "sd_iostats_seq_show: Device %s "+ "does not exist\n", disk->disk_name);+ return 0;+ }++ if (sd_iostats == NULL) {+ printk(KERN_ERR "sd_iostats_seq_show: NULL stats array\n");+ BUG();+ }++ stats = sd_iostats[scsi_disk(disk)->index];+ if (stats == NULL) {+ seq_printf(seq, "sd_iostats_seq_show: sd_iostats "+ "entry %d does not exist\n",+ scsi_disk(disk)->index);+ return 0;+ }++ do_gettimeofday(&now);+ now.tv_sec -= stats->iostat_timeval.tv_sec;+ now.tv_usec -= stats->iostat_timeval.tv_usec;+ if (now.tv_usec < 0) {+ now.tv_usec += 1000000;+ now.tv_sec--;+ }++ /* this sampling races with updates */+ seq_printf(seq, "index: %lu snapshot_time: %lu.%06lu\n",+ scsi_disk(disk)->index, now.tv_sec, now.tv_usec);++ for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)+ if (stats->iostat_read_histogram[i].iostat_count != 0 ||+ stats->iostat_write_histogram[i].iostat_count != 0)+ break;+ maxi = i;++ seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", + "reads", "total", "writes", "total");++ read_len_tot = write_len_tot = 0;+ read_num_tot = write_num_tot = 0;+ for (i = 0; i <= maxi; i++) {+ read_len = stats->iostat_read_histogram[i].iostat_size;+ read_len_tot += read_len;+ read_num = stats->iostat_read_histogram[i].iostat_count;+ read_num_tot += read_num;++ write_len = stats->iostat_write_histogram[i].iostat_size;+ write_len_tot += write_len;+ write_num = stats->iostat_write_histogram[i].iostat_count;+ write_num_tot += write_num;++ seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", + 512<<i, read_num, read_len, write_num, write_len);+ }+ + seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n", "total",+ read_num_tot, read_len_tot, + write_num_tot, write_len_tot);+ return 0;+}++static void *+sd_iostats_seq_start(struct seq_file *p, loff_t *pos)+{+ return (*pos == 0) ? (void *)1 : NULL;+}++static void *+sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)+{+ ++*pos;+ return NULL;+}++static void+sd_iostats_seq_stop(struct seq_file *p, void *v)+{+}++static struct seq_operations sd_iostats_seqops = {+ .start = sd_iostats_seq_start,+ .stop = sd_iostats_seq_stop,+ .next = sd_iostats_seq_next,+ .show = sd_iostats_seq_show,+};++static int+sd_iostats_seq_open (struct inode *inode, struct file *file)+{+ int rc;++ rc = seq_open(file, &sd_iostats_seqops);+ if (rc != 0)+ return rc;++ ((struct seq_file *)file->private_data)->private = PDE(inode)->data;+ return 0;+}++static ssize_t+sd_iostats_seq_write(struct file *file, const char *buffer,+ size_t len, loff_t *off)+{+ struct seq_file *seq = file->private_data;+ struct gendisk *disk = seq->private;+ iostat_stats_t *stats = sd_iostats[scsi_disk(disk)->index];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -