1 #ifndef _BLK_CGROUP_H 2 #define _BLK_CGROUP_H 3 /* 4 * Common Block IO controller cgroup interface 5 * 6 * Based on ideas and code from CFQ, CFS and BFQ: 7 * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk> 8 * 9 * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it> 10 * Paolo Valente <paolo.valente@unimore.it> 11 * 12 * Copyright (C) 2009 Vivek Goyal <vgoyal@redhat.com> 13 * Nauman Rafique <nauman@google.com> 14 */ 15 16 #include <linux/cgroup.h> 17 18 enum blkio_policy_id { 19 BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */ 20 BLKIO_POLICY_THROTL, /* Throttling */ 21 }; 22 23 /* Max limits for throttle policy */ 24 #define THROTL_IOPS_MAX UINT_MAX 25 26 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) 27 28 #ifndef CONFIG_BLK_CGROUP 29 /* When blk-cgroup is a module, its subsys_id isn't a compile-time constant */ 30 extern struct cgroup_subsys blkio_subsys; 31 #define blkio_subsys_id blkio_subsys.subsys_id 32 #endif 33 34 enum stat_type { 35 /* Total time spent (in ns) between request dispatch to the driver and 36 * request completion for IOs doen by this cgroup. This may not be 37 * accurate when NCQ is turned on. */ 38 BLKIO_STAT_SERVICE_TIME = 0, 39 /* Total bytes transferred */ 40 BLKIO_STAT_SERVICE_BYTES, 41 /* Total IOs serviced, post merge */ 42 BLKIO_STAT_SERVICED, 43 /* Total time spent waiting in scheduler queue in ns */ 44 BLKIO_STAT_WAIT_TIME, 45 /* Number of IOs merged */ 46 BLKIO_STAT_MERGED, 47 /* Number of IOs queued up */ 48 BLKIO_STAT_QUEUED, 49 /* All the single valued stats go below this */ 50 BLKIO_STAT_TIME, 51 BLKIO_STAT_SECTORS, 52 #ifdef CONFIG_DEBUG_BLK_CGROUP 53 BLKIO_STAT_AVG_QUEUE_SIZE, 54 BLKIO_STAT_IDLE_TIME, 55 BLKIO_STAT_EMPTY_TIME, 56 BLKIO_STAT_GROUP_WAIT_TIME, 57 BLKIO_STAT_DEQUEUE 58 #endif 59 }; 60 61 enum stat_sub_type { 62 BLKIO_STAT_READ = 0, 63 BLKIO_STAT_WRITE, 64 BLKIO_STAT_SYNC, 65 BLKIO_STAT_ASYNC, 66 BLKIO_STAT_TOTAL 67 }; 68 69 /* blkg state flags */ 70 enum blkg_state_flags { 71 BLKG_waiting = 0, 72 BLKG_idling, 73 BLKG_empty, 74 }; 75 76 /* cgroup files owned by proportional weight policy */ 77 enum blkcg_file_name_prop { 78 BLKIO_PROP_weight = 1, 79 BLKIO_PROP_weight_device, 80 BLKIO_PROP_io_service_bytes, 81 BLKIO_PROP_io_serviced, 82 BLKIO_PROP_time, 83 BLKIO_PROP_sectors, 84 BLKIO_PROP_io_service_time, 85 BLKIO_PROP_io_wait_time, 86 BLKIO_PROP_io_merged, 87 BLKIO_PROP_io_queued, 88 BLKIO_PROP_avg_queue_size, 89 BLKIO_PROP_group_wait_time, 90 BLKIO_PROP_idle_time, 91 BLKIO_PROP_empty_time, 92 BLKIO_PROP_dequeue, 93 }; 94 95 /* cgroup files owned by throttle policy */ 96 enum blkcg_file_name_throtl { 97 BLKIO_THROTL_read_bps_device, 98 BLKIO_THROTL_write_bps_device, 99 BLKIO_THROTL_read_iops_device, 100 BLKIO_THROTL_write_iops_device, 101 BLKIO_THROTL_io_service_bytes, 102 BLKIO_THROTL_io_serviced, 103 }; 104 105 struct blkio_cgroup { 106 struct cgroup_subsys_state css; 107 unsigned int weight; 108 spinlock_t lock; 109 struct hlist_head blkg_list; 110 struct list_head policy_list; /* list of blkio_policy_node */ 111 }; 112 113 struct blkio_group_stats { 114 /* total disk time and nr sectors dispatched by this group */ 115 uint64_t time; 116 uint64_t sectors; 117 uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL]; 118 #ifdef CONFIG_DEBUG_BLK_CGROUP 119 /* Sum of number of IOs queued across all samples */ 120 uint64_t avg_queue_size_sum; 121 /* Count of samples taken for average */ 122 uint64_t avg_queue_size_samples; 123 /* How many times this group has been removed from service tree */ 124 unsigned long dequeue; 125 126 /* Total time spent waiting for it to be assigned a timeslice. */ 127 uint64_t group_wait_time; 128 uint64_t start_group_wait_time; 129 130 /* Time spent idling for this blkio_group */ 131 uint64_t idle_time; 132 uint64_t start_idle_time; 133 /* 134 * Total time when we have requests queued and do not contain the 135 * current active queue. 136 */ 137 uint64_t empty_time; 138 uint64_t start_empty_time; 139 uint16_t flags; 140 #endif 141 }; 142 143 struct blkio_group { 144 /* An rcu protected unique identifier for the group */ 145 void *key; 146 struct hlist_node blkcg_node; 147 unsigned short blkcg_id; 148 /* Store cgroup path */ 149 char path[128]; 150 /* The device MKDEV(major, minor), this group has been created for */ 151 dev_t dev; 152 /* policy which owns this blk group */ 153 enum blkio_policy_id plid; 154 155 /* Need to serialize the stats in the case of reset/update */ 156 spinlock_t stats_lock; 157 struct blkio_group_stats stats; 158 }; 159 160 struct blkio_policy_node { 161 struct list_head node; 162 dev_t dev; 163 /* This node belongs to max bw policy or porportional weight policy */ 164 enum blkio_policy_id plid; 165 /* cgroup file to which this rule belongs to */ 166 int fileid; 167 168 union { 169 unsigned int weight; 170 /* 171 * Rate read/write in terms of byptes per second 172 * Whether this rate represents read or write is determined 173 * by file type "fileid". 174 */ 175 u64 bps; 176 unsigned int iops; 177 } val; 178 }; 179 180 extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, 181 dev_t dev); 182 extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, 183 dev_t dev); 184 extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, 185 dev_t dev); 186 extern unsigned int blkcg_get_read_iops(struct blkio_cgroup *blkcg, 187 dev_t dev); 188 extern unsigned int blkcg_get_write_iops(struct blkio_cgroup *blkcg, 189 dev_t dev); 190 191 typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg); 192 193 typedef void (blkio_update_group_weight_fn) (void *key, 194 struct blkio_group *blkg, unsigned int weight); 195 typedef void (blkio_update_group_read_bps_fn) (void * key, 196 struct blkio_group *blkg, u64 read_bps); 197 typedef void (blkio_update_group_write_bps_fn) (void *key, 198 struct blkio_group *blkg, u64 write_bps); 199 typedef void (blkio_update_group_read_iops_fn) (void *key, 200 struct blkio_group *blkg, unsigned int read_iops); 201 typedef void (blkio_update_group_write_iops_fn) (void *key, 202 struct blkio_group *blkg, unsigned int write_iops); 203 204 struct blkio_policy_ops { 205 blkio_unlink_group_fn *blkio_unlink_group_fn; 206 blkio_update_group_weight_fn *blkio_update_group_weight_fn; 207 blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn; 208 blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn; 209 blkio_update_group_read_iops_fn *blkio_update_group_read_iops_fn; 210 blkio_update_group_write_iops_fn *blkio_update_group_write_iops_fn; 211 }; 212 213 struct blkio_policy_type { 214 struct list_head list; 215 struct blkio_policy_ops ops; 216 enum blkio_policy_id plid; 217 }; 218 219 /* Blkio controller policy registration */ 220 extern void blkio_policy_register(struct blkio_policy_type *); 221 extern void blkio_policy_unregister(struct blkio_policy_type *); 222 223 static inline char *blkg_path(struct blkio_group *blkg) 224 { 225 return blkg->path; 226 } 227 228 #else 229 230 struct blkio_group { 231 }; 232 233 struct blkio_policy_type { 234 }; 235 236 static inline void blkio_policy_register(struct blkio_policy_type *blkiop) { } 237 static inline void blkio_policy_unregister(struct blkio_policy_type *blkiop) { } 238 239 static inline char *blkg_path(struct blkio_group *blkg) { return NULL; } 240 241 #endif 242 243 #define BLKIO_WEIGHT_MIN 100 244 #define BLKIO_WEIGHT_MAX 1000 245 #define BLKIO_WEIGHT_DEFAULT 500 246 247 #ifdef CONFIG_DEBUG_BLK_CGROUP 248 void blkiocg_update_avg_queue_size_stats(struct blkio_group *blkg); 249 void blkiocg_update_dequeue_stats(struct blkio_group *blkg, 250 unsigned long dequeue); 251 void blkiocg_update_set_idle_time_stats(struct blkio_group *blkg); 252 void blkiocg_update_idle_time_stats(struct blkio_group *blkg); 253 void blkiocg_set_start_empty_time(struct blkio_group *blkg); 254 255 #define BLKG_FLAG_FNS(name) \ 256 static inline void blkio_mark_blkg_##name( \ 257 struct blkio_group_stats *stats) \ 258 { \ 259 stats->flags |= (1 << BLKG_##name); \ 260 } \ 261 static inline void blkio_clear_blkg_##name( \ 262 struct blkio_group_stats *stats) \ 263 { \ 264 stats->flags &= ~(1 << BLKG_##name); \ 265 } \ 266 static inline int blkio_blkg_##name(struct blkio_group_stats *stats) \ 267 { \ 268 return (stats->flags & (1 << BLKG_##name)) != 0; \ 269 } \ 270 271 BLKG_FLAG_FNS(waiting) 272 BLKG_FLAG_FNS(idling) 273 BLKG_FLAG_FNS(empty) 274 #undef BLKG_FLAG_FNS 275 #else 276 static inline void blkiocg_update_avg_queue_size_stats( 277 struct blkio_group *blkg) {} 278 static inline void blkiocg_update_dequeue_stats(struct blkio_group *blkg, 279 unsigned long dequeue) {} 280 static inline void blkiocg_update_set_idle_time_stats(struct blkio_group *blkg) 281 {} 282 static inline void blkiocg_update_idle_time_stats(struct blkio_group *blkg) {} 283 static inline void blkiocg_set_start_empty_time(struct blkio_group *blkg) {} 284 #endif 285 286 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) 287 extern struct blkio_cgroup blkio_root_cgroup; 288 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); 289 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, 290 struct blkio_group *blkg, void *key, dev_t dev, 291 enum blkio_policy_id plid); 292 extern int blkiocg_del_blkio_group(struct blkio_group *blkg); 293 extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, 294 void *key); 295 void blkiocg_update_timeslice_used(struct blkio_group *blkg, 296 unsigned long time); 297 void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, 298 bool direction, bool sync); 299 void blkiocg_update_completion_stats(struct blkio_group *blkg, 300 uint64_t start_time, uint64_t io_start_time, bool direction, bool sync); 301 void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction, 302 bool sync); 303 void blkiocg_update_io_add_stats(struct blkio_group *blkg, 304 struct blkio_group *curr_blkg, bool direction, bool sync); 305 void blkiocg_update_io_remove_stats(struct blkio_group *blkg, 306 bool direction, bool sync); 307 #else 308 struct cgroup; 309 static inline struct blkio_cgroup * 310 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } 311 312 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, 313 struct blkio_group *blkg, void *key, dev_t dev, 314 enum blkio_policy_id plid) {} 315 316 static inline int 317 blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; } 318 319 static inline struct blkio_group * 320 blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; } 321 static inline void blkiocg_update_timeslice_used(struct blkio_group *blkg, 322 unsigned long time) {} 323 static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg, 324 uint64_t bytes, bool direction, bool sync) {} 325 static inline void blkiocg_update_completion_stats(struct blkio_group *blkg, 326 uint64_t start_time, uint64_t io_start_time, bool direction, 327 bool sync) {} 328 static inline void blkiocg_update_io_merged_stats(struct blkio_group *blkg, 329 bool direction, bool sync) {} 330 static inline void blkiocg_update_io_add_stats(struct blkio_group *blkg, 331 struct blkio_group *curr_blkg, bool direction, bool sync) {} 332 static inline void blkiocg_update_io_remove_stats(struct blkio_group *blkg, 333 bool direction, bool sync) {} 334 #endif 335 #endif /* _BLK_CGROUP_H */ 336