Commit ea5c48ab authored by Jerome Marchand's avatar Jerome Marchand Committed by Jens Axboe

Enhanced partition statistics: core statistics

This patch contain the core infrastructure of enhanced partition
statistics. It adds to struct hd_struct the same stats data as struct
gendisk and define basics function to manipulate them.
Signed-off-by: default avatarJerome Marchand <jmarchan@redhat.com>
Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 63a71386
...@@ -91,6 +91,15 @@ struct partition { ...@@ -91,6 +91,15 @@ struct partition {
__le32 nr_sects; /* nr of sectors in partition */ __le32 nr_sects; /* nr of sectors in partition */
} __attribute__((packed)); } __attribute__((packed));
struct disk_stats {
unsigned long sectors[2]; /* READs and WRITEs */
unsigned long ios[2];
unsigned long merges[2];
unsigned long ticks[2];
unsigned long io_ticks;
unsigned long time_in_queue;
};
struct hd_struct { struct hd_struct {
sector_t start_sect; sector_t start_sect;
sector_t nr_sects; sector_t nr_sects;
...@@ -100,6 +109,13 @@ struct hd_struct { ...@@ -100,6 +109,13 @@ struct hd_struct {
int policy, partno; int policy, partno;
#ifdef CONFIG_FAIL_MAKE_REQUEST #ifdef CONFIG_FAIL_MAKE_REQUEST
int make_it_fail; int make_it_fail;
#endif
unsigned long stamp;
int in_flight;
#ifdef CONFIG_SMP
struct disk_stats *dkstats;
#else
struct disk_stats dkstats;
#endif #endif
}; };
...@@ -111,14 +127,6 @@ struct hd_struct { ...@@ -111,14 +127,6 @@ struct hd_struct {
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32
#define GENHD_FL_FAIL 64 #define GENHD_FL_FAIL 64
struct disk_stats {
unsigned long sectors[2]; /* READs and WRITEs */
unsigned long ios[2];
unsigned long merges[2];
unsigned long ticks[2];
unsigned long io_ticks;
unsigned long time_in_queue;
};
struct gendisk { struct gendisk {
int major; /* major number of driver */ int major; /* major number of driver */
...@@ -158,6 +166,20 @@ struct gendisk { ...@@ -158,6 +166,20 @@ struct gendisk {
* The __ variants should only be called in critical sections. The full * The __ variants should only be called in critical sections. The full
* variants disable/enable preemption. * variants disable/enable preemption.
*/ */
static inline struct hd_struct *get_part(struct gendisk *gendiskp,
sector_t sector)
{
struct hd_struct *part;
int i;
for (i = 0; i < gendiskp->minors - 1; i++) {
part = gendiskp->part[i];
if (part && part->start_sect <= sector
&& sector < part->start_sect + part->nr_sects)
return part;
}
return NULL;
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define __disk_stat_add(gendiskp, field, addnd) \ #define __disk_stat_add(gendiskp, field, addnd) \
(per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd) (per_cpu_ptr(gendiskp->dkstats, smp_processor_id())->field += addnd)
...@@ -178,14 +200,61 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { ...@@ -178,14 +200,61 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
sizeof (struct disk_stats)); sizeof (struct disk_stats));
} }
#define __part_stat_add(part, field, addnd) \
(per_cpu_ptr(part->dkstats, smp_processor_id())->field += addnd)
#define __all_stat_add(gendiskp, field, addnd, sector) \
({ \
struct hd_struct *part = get_part(gendiskp, sector); \
if (part) \
__part_stat_add(part, field, addnd); \
__disk_stat_add(gendiskp, field, addnd); \
})
#define part_stat_read(part, field) \
({ \
typeof(part->dkstats->field) res = 0; \
int i; \
for_each_possible_cpu(i) \
res += per_cpu_ptr(part->dkstats, i)->field; \
res; \
})
static inline void part_stat_set_all(struct hd_struct *part, int value) {
int i;
for_each_possible_cpu(i)
memset(per_cpu_ptr(part->dkstats, i), value,
sizeof(struct disk_stats));
}
#else #else
#define __disk_stat_add(gendiskp, field, addnd) \ #define __disk_stat_add(gendiskp, field, addnd) \
(gendiskp->dkstats.field += addnd) (gendiskp->dkstats.field += addnd)
#define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field) #define disk_stat_read(gendiskp, field) (gendiskp->dkstats.field)
static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { static inline void disk_stat_set_all(struct gendisk *gendiskp, int value)
{
memset(&gendiskp->dkstats, value, sizeof (struct disk_stats)); memset(&gendiskp->dkstats, value, sizeof (struct disk_stats));
} }
#define __part_stat_add(part, field, addnd) \
(part->dkstats.field += addnd)
#define __all_stat_add(gendiskp, field, addnd, sector) \
({ \
struct hd_struct *part = get_part(gendiskp, sector); \
if (part) \
part->dkstats.field += addnd; \
__disk_stat_add(gendiskp, field, addnd); \
})
#define part_stat_read(part, field) (part->dkstats.field)
static inline void part_stat_set_all(struct hd_struct *part, int value)
{
memset(&part->dkstats, value, sizeof(struct disk_stats));
}
#endif #endif
#define disk_stat_add(gendiskp, field, addnd) \ #define disk_stat_add(gendiskp, field, addnd) \
...@@ -206,6 +275,45 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { ...@@ -206,6 +275,45 @@ static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) {
#define disk_stat_sub(gendiskp, field, subnd) \ #define disk_stat_sub(gendiskp, field, subnd) \
disk_stat_add(gendiskp, field, -subnd) disk_stat_add(gendiskp, field, -subnd)
#define part_stat_add(gendiskp, field, addnd) \
do { \
preempt_disable(); \
__part_stat_add(gendiskp, field, addnd);\
preempt_enable(); \
} while (0)
#define __part_stat_dec(gendiskp, field) __part_stat_add(gendiskp, field, -1)
#define part_stat_dec(gendiskp, field) part_stat_add(gendiskp, field, -1)
#define __part_stat_inc(gendiskp, field) __part_stat_add(gendiskp, field, 1)
#define part_stat_inc(gendiskp, field) part_stat_add(gendiskp, field, 1)
#define __part_stat_sub(gendiskp, field, subnd) \
__part_stat_add(gendiskp, field, -subnd)
#define part_stat_sub(gendiskp, field, subnd) \
part_stat_add(gendiskp, field, -subnd)
#define all_stat_add(gendiskp, field, addnd, sector) \
do { \
preempt_disable(); \
__all_stat_add(gendiskp, field, addnd, sector); \
preempt_enable(); \
} while (0)
#define __all_stat_dec(gendiskp, field, sector) \
__all_stat_add(gendiskp, field, -1, sector)
#define all_stat_dec(gendiskp, field, sector) \
all_stat_add(gendiskp, field, -1, sector)
#define __all_stat_inc(gendiskp, field, sector) \
__all_stat_add(gendiskp, field, 1, sector)
#define all_stat_inc(gendiskp, field, sector) \
all_stat_add(gendiskp, field, 1, sector)
#define __all_stat_sub(gendiskp, field, subnd, sector) \
__all_stat_add(gendiskp, field, -subnd, sector)
#define all_stat_sub(gendiskp, field, subnd, sector) \
all_stat_add(gendiskp, field, -subnd, sector)
/* Inlines to alloc and free disk stats in struct gendisk */ /* Inlines to alloc and free disk stats in struct gendisk */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -221,6 +329,20 @@ static inline void free_disk_stats(struct gendisk *disk) ...@@ -221,6 +329,20 @@ static inline void free_disk_stats(struct gendisk *disk)
{ {
free_percpu(disk->dkstats); free_percpu(disk->dkstats);
} }
static inline int init_part_stats(struct hd_struct *part)
{
part->dkstats = alloc_percpu(struct disk_stats);
if (!part->dkstats)
return 0;
return 1;
}
static inline void free_part_stats(struct hd_struct *part)
{
free_percpu(part->dkstats);
}
#else /* CONFIG_SMP */ #else /* CONFIG_SMP */
static inline int init_disk_stats(struct gendisk *disk) static inline int init_disk_stats(struct gendisk *disk)
{ {
...@@ -230,6 +352,15 @@ static inline int init_disk_stats(struct gendisk *disk) ...@@ -230,6 +352,15 @@ static inline int init_disk_stats(struct gendisk *disk)
static inline void free_disk_stats(struct gendisk *disk) static inline void free_disk_stats(struct gendisk *disk)
{ {
} }
static inline int init_part_stats(struct hd_struct *part)
{
return 1;
}
static inline void free_part_stats(struct hd_struct *part)
{
}
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
/* drivers/block/ll_rw_blk.c */ /* drivers/block/ll_rw_blk.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment