]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-sd_iostats-2.6.22.patch
- updated to 2.6.29.2 (builds and works --without apparmor --without grsecurity)
[packages/kernel.git] / kernel-sd_iostats-2.6.22.patch
1 Index: linux-2.6.22-rc4/drivers/scsi/Kconfig
2 ===================================================================
3 --- linux-2.6.22-rc4.orig/drivers/scsi/Kconfig  2007-06-11 20:23:32.000000000 +0200
4 +++ linux-2.6.22-rc4/drivers/scsi/Kconfig       2007-06-11 20:24:20.000000000 +0200
5 @@ -75,6 +75,14 @@
6           In this case, do not compile the driver for your SCSI host adapter
7           (below) as a module either.
8  
9 +config SD_IOSTATS
10 +   bool "Enable SCSI disk I/O stats"
11 +   depends on BLK_DEV_SD
12 +   default y
13 +   ---help---
14 +     This enables SCSI disk I/O stats collection.  You must also enable
15 +     /proc file system support if you want this feature.
16 +
17  config CHR_DEV_ST
18         tristate "SCSI tape support"
19         depends on SCSI
20 Index: linux-2.6.22-rc4/drivers/scsi/sd.c
21 ===================================================================
22 --- linux-2.6.22-rc4.orig/drivers/scsi/sd.c     2007-06-11 20:23:32.000000000 +0200
23 +++ linux-2.6.22-rc4/drivers/scsi/sd.c  2007-06-11 20:33:35.000000000 +0200
24 @@ -244,6 +244,38 @@
25         .issue_flush            = sd_issue_flush,
26  };
27  
28 +#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
29 +# include <linux/proc_fs.h>
30 +# include <linux/seq_file.h>
31 +
32 +typedef struct {
33 +        unsigned long long iostat_size;
34 +        unsigned long long iostat_count;
35 +} iostat_counter_t;
36 +
37 +#define IOSTAT_NCOUNTERS 16
38 +typedef struct {
39 +        iostat_counter_t        iostat_read_histogram[IOSTAT_NCOUNTERS];
40 +        iostat_counter_t        iostat_write_histogram[IOSTAT_NCOUNTERS];
41 +        struct timeval          iostat_timeval;
42 +} iostat_stats_t;
43 +
44 +iostat_stats_t       **sd_iostats;
45 +spinlock_t             sd_iostats_lock;
46 +struct proc_dir_entry *sd_iostats_procdir;
47 +char                   sd_iostats_procdir_name[] = "sd_iostats";
48 +
49 +extern void sd_iostats_init(void);
50 +extern void sd_iostats_init_disk(struct gendisk *);
51 +extern void sd_iostats_fini(void);
52 +extern void sd_iostats_bump(int disk, unsigned int nsect, int iswrite);
53 +#else
54 +static inline void sd_iostats_init(void) {}
55 +static inline void sd_iostats_init_disk(struct gendisk *disk) {}
56 +static inline void sd_iostats_fini(void) {}
57 +static inline void sd_iostats_bump(int disk, unsigned int nsect, int iswrite) {}
58 +#endif
59 +
60  /*
61   * Device no to disk mapping:
62   * 
63 @@ -347,6 +379,9 @@
64                                         (unsigned long long)block,
65                                         this_count));
66  
67 +       sd_iostats_bump(scsi_disk(disk)->index, this_count,
68 +                      rq_data_dir(SCpnt->request) == WRITE);
69 +
70         if (!sdp || !scsi_device_online(sdp) ||
71             block + rq->nr_sectors > get_capacity(disk)) {
72                 SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt,
73 @@ -575,6 +610,8 @@
74                         scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT);
75         }
76  
77 +       sd_iostats_init_disk(disk);
78 +
79         return 0;
80  
81  error_out:
82 @@ -1002,6 +1039,7 @@
83         return 1;
84  }
85  
86 +#define SD_STATS 256
87  /*
88   * spinup disk - called only in sd_revalidate_disk()
89   */
90 @@ -1684,6 +1722,327 @@
91         return error;
92  }
93  
94 +#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
95 +static int
96 +sd_iostats_seq_show(struct seq_file *seq, void *v)
97 +{
98 +        struct timeval     now;
99 +        struct gendisk *disk = seq->private;
100 +        iostat_stats_t    *stats;
101 +        unsigned long long read_len;
102 +        unsigned long long read_len_tot;
103 +        unsigned long      read_num;
104 +        unsigned long      read_num_tot;
105 +        unsigned long long write_len;
106 +        unsigned long long write_len_tot;
107 +        unsigned long      write_num;
108 +        unsigned long      write_num_tot;
109 +        int                i;
110 +        int                maxi;
111 +
112 +        if (sd_iostats == NULL) {
113 +                printk(KERN_ERR "sd_iostats_seq_show: NULL stats array\n");
114 +                BUG();
115 +        }
116 +
117 +        stats = sd_iostats[scsi_disk(disk)->index];
118 +        if (stats == NULL) {
119 +                printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
120 +                BUG();
121 +        }
122 +
123 +        do_gettimeofday(&now);
124 +        now.tv_sec -= stats->iostat_timeval.tv_sec;
125 +        now.tv_usec -= stats->iostat_timeval.tv_usec;
126 +        if (now.tv_usec < 0) {
127 +                now.tv_usec += 1000000;
128 +                now.tv_sec--;
129 +        }
130 +
131 +        /* this sampling races with updates */
132 +        seq_printf(seq, "index:        %u   snapshot_time:         %lu.%06lu\n",
133 +                   scsi_disk(disk)->index, now.tv_sec, now.tv_usec);
134 +
135 +        for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
136 +                if (stats->iostat_read_histogram[i].iostat_count != 0 ||
137 +                    stats->iostat_write_histogram[i].iostat_count != 0)
138 +                        break;
139 +        maxi = i;
140 +
141 +        seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size",
142 +                   "reads", "total", "writes", "total");
143 +
144 +        read_len_tot = write_len_tot = 0;
145 +        read_num_tot = write_num_tot = 0;
146 +        for (i = 0; i <= maxi; i++) {
147 +                read_len = stats->iostat_read_histogram[i].iostat_size;
148 +                read_len_tot += read_len;
149 +                read_num = stats->iostat_read_histogram[i].iostat_count;
150 +                read_num_tot += read_num;
151 +
152 +                write_len = stats->iostat_write_histogram[i].iostat_size;
153 +                write_len_tot += write_len;
154 +                write_num = stats->iostat_write_histogram[i].iostat_count;
155 +                write_num_tot += write_num;
156 +
157 +                seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n",
158 +                            512<<i, read_num, read_len, write_num, write_len);
159 +        }
160 +
161 +        seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n", "total",
162 +                   read_num_tot, read_len_tot,
163 +                   write_num_tot, write_len_tot);
164 +        return 0;
165 +}
166 +
167 +static void *
168 +sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
169 +{
170 +        return (*pos == 0) ? (void *)1 : NULL;
171 +}
172 +
173 +static void *
174 +sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
175 +{
176 +        ++*pos;
177 +        return NULL;
178 +}
179 +
180 +static void
181 +sd_iostats_seq_stop(struct seq_file *p, void *v)
182 +{
183 +}
184 +
185 +static struct seq_operations sd_iostats_seqops = {
186 +        .start = sd_iostats_seq_start,
187 +        .stop  = sd_iostats_seq_stop,
188 +        .next  = sd_iostats_seq_next,
189 +        .show  = sd_iostats_seq_show,
190 +};
191 +
192 +static int
193 +sd_iostats_seq_open (struct inode *inode, struct file *file)
194 +{
195 +        int                    rc;
196 +
197 +        rc = seq_open(file, &sd_iostats_seqops);
198 +        if (rc != 0)
199 +                return rc;
200 +
201 +        ((struct seq_file *)file->private_data)->private = PDE(inode)->data;
202 +        return 0;
203 +}
204 +
205 +static ssize_t
206 +sd_iostats_seq_write(struct file *file, const char *buffer,
207 +                     size_t len, loff_t *off)
208 +{
209 +        struct seq_file   *seq = file->private_data;
210 +        struct gendisk *disk = seq->private;
211 +        iostat_stats_t    *stats = sd_iostats[scsi_disk(disk)->index];
212 +        unsigned long      flags;
213 +
214 +
215 +        spin_lock_irqsave (&sd_iostats_lock, flags);
216 +        memset (stats, 0, sizeof(*stats));
217 +        do_gettimeofday(&stats->iostat_timeval);
218 +        spin_unlock_irqrestore (&sd_iostats_lock, flags);
219 +
220 +        return len;
221 +}
222 +
223 +static struct file_operations sd_iostats_proc_fops = {
224 +        .owner   = THIS_MODULE,
225 +        .open    = sd_iostats_seq_open,
226 +        .read    = seq_read,
227 +        .write   = sd_iostats_seq_write,
228 +        .llseek  = seq_lseek,
229 +        .release = seq_release,
230 +};
231 +
232 +extern struct proc_dir_entry *proc_scsi;
233 +
234 +void
235 +sd_iostats_init(void)
236 +{
237 +        int    i;
238 +
239 +        spin_lock_init(&sd_iostats_lock);
240 +
241 +        sd_iostats = kmalloc(SD_STATS * sizeof(iostat_stats_t *), GFP_KERNEL);
242 +        if (sd_iostats == NULL) {
243 +                printk(KERN_WARNING "Can't keep sd iostats: "
244 +                       "ENOMEM allocating stats array size %ld\n",
245 +                       SD_STATS * sizeof(iostat_stats_t *));
246 +                return;
247 +        }
248 +
249 +        for (i = 0; i < SD_STATS; i++)
250 +                sd_iostats[i] = NULL;
251 +
252 +        if (proc_scsi == NULL) {
253 +                printk(KERN_WARNING "No access to sd iostats: "
254 +                       "proc_scsi is NULL\n");
255 +                return;
256 +        }
257 +
258 +        sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
259 +                                               S_IFDIR | S_IRUGO | S_IXUGO,
260 +                                               proc_scsi);
261 +        if (sd_iostats_procdir == NULL) {
262 +                printk(KERN_WARNING "No access to sd iostats: "
263 +                       "can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
264 +                return;
265 +        }
266 +}
267 +
268 +void
269 +sd_iostats_init_disk(struct gendisk *disk)
270 +{
271 +        struct proc_dir_entry *pde;
272 +        unsigned long          flags;
273 +        iostat_stats_t        *stats;
274 +
275 +        if (sd_iostats == NULL ||
276 +            sd_iostats_procdir == NULL)
277 +                return;
278 +
279 +        if (scsi_disk(disk)->index > SD_STATS) {
280 +                printk(KERN_ERR "sd_iostats_init_disk: "
281 +                       "unexpected disk index %d(%d)\n",
282 +                       scsi_disk(disk)->index, SD_STATS);
283 +                                   return;
284 +        }
285 +
286 +        if (sd_iostats[scsi_disk(disk)->index] != NULL)
287 +                return;
288 +
289 +        stats = kmalloc(sizeof(*stats), GFP_KERNEL);
290 +        if (stats == NULL) {
291 +                printk(KERN_WARNING "Can't keep %s iostats: "
292 +                       "ENOMEM allocating stats size %ld\n",
293 +                       disk->disk_name, sizeof(*stats));
294 +                return;
295 +        }
296 +
297 +        memset (stats, 0, sizeof(*stats));
298 +        do_gettimeofday(&stats->iostat_timeval);
299 +
300 +        spin_lock_irqsave(&sd_iostats_lock, flags);
301 +
302 +        if (sd_iostats[scsi_disk(disk)->index] != NULL) {
303 +                spin_unlock_irqrestore(&sd_iostats_lock, flags);
304 +                kfree (stats);
305 +                return;
306 +        }
307 +
308 +        sd_iostats[scsi_disk(disk)->index] = stats;
309 +
310 +        spin_unlock_irqrestore(&sd_iostats_lock, flags);
311 +
312 +        pde = create_proc_entry(disk->disk_name, S_IRUGO | S_IWUSR,
313 +                                sd_iostats_procdir);
314 +        if (pde == NULL) {
315 +                printk(KERN_WARNING "Can't create /proc/scsi/%s/%s\n",
316 +                       sd_iostats_procdir_name, disk->disk_name);
317 +        } else {
318 +                pde->proc_fops = &sd_iostats_proc_fops;
319 +                pde->data = disk;
320 +        }
321 +}
322 +
323 +static void sd_devname(unsigned int disknum, char *buffer)
324 +{
325 +        if (disknum < 26)
326 +                sprintf(buffer, "sd%c", 'a' + disknum);
327 +        else {
328 +                unsigned int min1;
329 +                unsigned int min2;
330 +                /*
331 +                 * For larger numbers of disks, we need to go to a new
332 +                 * naming scheme.
333 +                 */
334 +                min1 = disknum / 26;
335 +                min2 = disknum % 26;
336 +                sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
337 +        }
338 +}
339 +
340 +void
341 +sd_iostats_fini(void)
342 +{
343 +        char name[6];
344 +        int  i;
345 +
346 +        if (sd_iostats_procdir != NULL) {
347 +                for (i = 0; i < SD_STATS; i++) {
348 +                        sd_devname(i, name);
349 +                        remove_proc_entry(name, sd_iostats_procdir);
350 +                }
351 +
352 +                if (proc_scsi == NULL) {
353 +                        printk(KERN_ERR "sd_iostats_fini: proc_scsi NULL\n");
354 +                        BUG();
355 +                }
356 +                remove_proc_entry(sd_iostats_procdir_name,
357 +                                  proc_scsi);
358 +
359 +                sd_iostats_procdir = NULL;
360 +        }
361 +
362 +        if (sd_iostats != NULL) {
363 +                for (i = 0; i < SD_STATS; i++) {
364 +                        if (sd_iostats[i] != NULL)
365 +                                kfree (sd_iostats[i]);
366 +                }
367 +
368 +                kfree(sd_iostats);
369 +                sd_iostats = NULL;
370 +        }
371 +}
372 +
373 +void
374 +sd_iostats_bump(int disk, unsigned int nsect, int iswrite)
375 +{
376 +        iostat_stats_t    *stats;
377 +        iostat_counter_t  *counter;
378 +        int                bucket;
379 +        int                tmp;
380 +        unsigned long      irqflags;
381 +
382 +        if (sd_iostats == NULL)
383 +                return;
384 +
385 +        if (disk < 0 || disk >= SD_STATS) {
386 +                printk(KERN_ERR "sd_iostats_bump: unexpected disk index %d([0-%d])\n",
387 +                       disk, SD_STATS);
388 +                BUG();
389 +        }
390 +
391 +        for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
392 +                tmp /= 2;
393 +
394 +        if (bucket >= IOSTAT_NCOUNTERS) {
395 +                printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
396 +                BUG();
397 +        }
398 +
399 +        spin_lock_irqsave(&sd_iostats_lock, irqflags);
400 +
401 +        stats = sd_iostats[disk];
402 +        if (stats != NULL) {
403 +                counter = iswrite ?
404 +                          &stats->iostat_write_histogram[bucket] :
405 +                          &stats->iostat_read_histogram[bucket];
406 +
407 +                counter->iostat_size += nsect;
408 +                counter->iostat_count++;
409 +        }
410 +
411 +        spin_unlock_irqrestore(&sd_iostats_lock, irqflags);
412 +}
413 +#endif
414 +
415  /**
416   *     sd_remove - called whenever a scsi disk (previously recognized by
417   *     sd_probe) is detached from the system. It is called (potentially
418 @@ -1855,6 +2214,7 @@
419         if (err)
420                 goto err_out_class;
421  
422 +       sd_iostats_init();
423         return 0;
424  
425  err_out_class:
426 @@ -1876,6 +2236,7 @@
427  
428         SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
429  
430 +   sd_iostats_fini();
431         scsi_unregister_driver(&sd_template.gendrv);
432         class_unregister(&sd_disk_class);
433  
434 Index: linux-2.6.22-rc4/drivers/scsi/scsi_proc.c
435 ===================================================================
436 --- linux-2.6.22-rc4.orig/drivers/scsi/scsi_proc.c      2007-06-11 20:23:32.000000000 +0200
437 +++ linux-2.6.22-rc4/drivers/scsi/scsi_proc.c   2007-06-11 20:24:20.000000000 +0200
438 @@ -40,7 +40,8 @@
439  /* 4K page size, but our output routines, use some slack for overruns */
440  #define PROC_BLOCK_SIZE (3*1024)
441  
442 -static struct proc_dir_entry *proc_scsi;
443 +struct proc_dir_entry *proc_scsi;
444 +EXPORT_SYMBOL(proc_scsi);
445  
446  /* Protect sht->present and sht->proc_dir */
447  static DEFINE_MUTEX(global_host_template_mutex);
This page took 0.1626 seconds and 3 git commands to generate.