OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [md/] [dm-round-robin.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.