Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.12-rc2 214 lines 4.6 kB view raw
1/* 2 * Copyright (C) 2003 Sistina Software. 3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. 4 * 5 * Module Author: Heinz Mauelshagen 6 * 7 * This file is released under the GPL. 8 * 9 * Round-robin path selector. 10 */ 11 12#include "dm.h" 13#include "dm-path-selector.h" 14 15#include <linux/slab.h> 16 17/*----------------------------------------------------------------- 18 * Path-handling code, paths are held in lists 19 *---------------------------------------------------------------*/ 20struct path_info { 21 struct list_head list; 22 struct path *path; 23 unsigned repeat_count; 24}; 25 26static void free_paths(struct list_head *paths) 27{ 28 struct path_info *pi, *next; 29 30 list_for_each_entry_safe(pi, next, paths, list) { 31 list_del(&pi->list); 32 kfree(pi); 33 } 34} 35 36/*----------------------------------------------------------------- 37 * Round-robin selector 38 *---------------------------------------------------------------*/ 39 40#define RR_MIN_IO 1000 41 42struct selector { 43 struct list_head valid_paths; 44 struct list_head invalid_paths; 45}; 46 47static struct selector *alloc_selector(void) 48{ 49 struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL); 50 51 if (s) { 52 INIT_LIST_HEAD(&s->valid_paths); 53 INIT_LIST_HEAD(&s->invalid_paths); 54 } 55 56 return s; 57} 58 59static int rr_create(struct path_selector *ps, unsigned argc, char **argv) 60{ 61 struct selector *s; 62 63 s = alloc_selector(); 64 if (!s) 65 return -ENOMEM; 66 67 ps->context = s; 68 return 0; 69} 70 71static void rr_destroy(struct path_selector *ps) 72{ 73 struct selector *s = (struct selector *) ps->context; 74 75 free_paths(&s->valid_paths); 76 free_paths(&s->invalid_paths); 77 kfree(s); 78 ps->context = NULL; 79} 80 81static int rr_status(struct path_selector *ps, struct path *path, 82 status_type_t type, char *result, unsigned int maxlen) 83{ 84 struct path_info *pi; 85 int sz = 0; 86 87 if (!path) 88 DMEMIT("0 "); 89 else { 90 switch(type) { 91 case STATUSTYPE_INFO: 92 break; 93 case STATUSTYPE_TABLE: 94 pi = path->pscontext; 95 DMEMIT("%u ", pi->repeat_count); 96 break; 97 } 98 } 99 100 return sz; 101} 102 103/* 104 * Called during initialisation to register each path with an 105 * optional repeat_count. 106 */ 107static int rr_add_path(struct path_selector *ps, struct path *path, 108 int argc, char **argv, char **error) 109{ 110 struct selector *s = (struct selector *) ps->context; 111 struct path_info *pi; 112 unsigned repeat_count = RR_MIN_IO; 113 114 if (argc > 1) { 115 *error = "round-robin ps: incorrect number of arguments"; 116 return -EINVAL; 117 } 118 119 /* First path argument is number of I/Os before switching path */ 120 if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) { 121 *error = "round-robin ps: invalid repeat count"; 122 return -EINVAL; 123 } 124 125 /* allocate the path */ 126 pi = kmalloc(sizeof(*pi), GFP_KERNEL); 127 if (!pi) { 128 *error = "round-robin ps: Error allocating path context"; 129 return -ENOMEM; 130 } 131 132 pi->path = path; 133 pi->repeat_count = repeat_count; 134 135 path->pscontext = pi; 136 137 list_add(&pi->list, &s->valid_paths); 138 139 return 0; 140} 141 142static void rr_fail_path(struct path_selector *ps, struct path *p) 143{ 144 struct selector *s = (struct selector *) ps->context; 145 struct path_info *pi = p->pscontext; 146 147 list_move(&pi->list, &s->invalid_paths); 148} 149 150static int rr_reinstate_path(struct path_selector *ps, struct path *p) 151{ 152 struct selector *s = (struct selector *) ps->context; 153 struct path_info *pi = p->pscontext; 154 155 list_move(&pi->list, &s->valid_paths); 156 157 return 0; 158} 159 160static struct path *rr_select_path(struct path_selector *ps, 161 unsigned *repeat_count) 162{ 163 struct selector *s = (struct selector *) ps->context; 164 struct path_info *pi = NULL; 165 166 if (!list_empty(&s->valid_paths)) { 167 pi = list_entry(s->valid_paths.next, struct path_info, list); 168 list_move_tail(&pi->list, &s->valid_paths); 169 *repeat_count = pi->repeat_count; 170 } 171 172 return pi ? pi->path : NULL; 173} 174 175static struct path_selector_type rr_ps = { 176 .name = "round-robin", 177 .module = THIS_MODULE, 178 .table_args = 1, 179 .info_args = 0, 180 .create = rr_create, 181 .destroy = rr_destroy, 182 .status = rr_status, 183 .add_path = rr_add_path, 184 .fail_path = rr_fail_path, 185 .reinstate_path = rr_reinstate_path, 186 .select_path = rr_select_path, 187}; 188 189static int __init dm_rr_init(void) 190{ 191 int r = dm_register_path_selector(&rr_ps); 192 193 if (r < 0) 194 DMERR("round-robin: register failed %d", r); 195 196 DMINFO("dm-round-robin version 1.0.0 loaded"); 197 198 return r; 199} 200 201static void __exit dm_rr_exit(void) 202{ 203 int r = dm_unregister_path_selector(&rr_ps); 204 205 if (r < 0) 206 DMERR("round-robin: unregister failed %d", r); 207} 208 209module_init(dm_rr_init); 210module_exit(dm_rr_exit); 211 212MODULE_DESCRIPTION(DM_NAME " round-robin multipath path selector"); 213MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>"); 214MODULE_LICENSE("GPL");