]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
7b718769 NS |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | |
1da177e4 | 4 | * |
7b718769 NS |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License as | |
1da177e4 LT |
7 | * published by the Free Software Foundation. |
8 | * | |
7b718769 NS |
9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
1da177e4 | 13 | * |
7b718769 NS |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
1da177e4 LT |
17 | */ |
18 | #include "xfs.h" | |
19 | ||
20 | /* | |
21 | * Source file used to associate/disassociate behaviors with virtualized | |
22 | * objects. See xfs_behavior.h for more information about behaviors, etc. | |
23 | * | |
24 | * The implementation is split between functions in this file and macros | |
25 | * in xfs_behavior.h. | |
26 | */ | |
27 | ||
28 | /* | |
29 | * Insert a new behavior descriptor into a behavior chain. | |
30 | * | |
31 | * The behavior chain is ordered based on the 'position' number which | |
32 | * lives in the first field of the ops vector (higher numbers first). | |
33 | * | |
34 | * Attemps to insert duplicate ops result in an EINVAL return code. | |
35 | * Otherwise, return 0 to indicate success. | |
36 | */ | |
37 | int | |
38 | bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp) | |
39 | { | |
40 | bhv_desc_t *curdesc, *prev; | |
41 | int position; | |
42 | ||
43 | /* | |
44 | * Validate the position value of the new behavior. | |
45 | */ | |
46 | position = BHV_POSITION(bdp); | |
47 | ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP); | |
48 | ||
49 | /* | |
50 | * Find location to insert behavior. Check for duplicates. | |
51 | */ | |
52 | prev = NULL; | |
53 | for (curdesc = bhp->bh_first; | |
54 | curdesc != NULL; | |
55 | curdesc = curdesc->bd_next) { | |
56 | ||
57 | /* Check for duplication. */ | |
58 | if (curdesc->bd_ops == bdp->bd_ops) { | |
59 | ASSERT(0); | |
60 | return EINVAL; | |
61 | } | |
62 | ||
63 | /* Find correct position */ | |
64 | if (position >= BHV_POSITION(curdesc)) { | |
65 | ASSERT(position != BHV_POSITION(curdesc)); | |
66 | break; /* found it */ | |
67 | } | |
68 | ||
69 | prev = curdesc; | |
70 | } | |
71 | ||
72 | if (prev == NULL) { | |
73 | /* insert at front of chain */ | |
74 | bdp->bd_next = bhp->bh_first; | |
75 | bhp->bh_first = bdp; | |
76 | } else { | |
77 | /* insert after prev */ | |
78 | bdp->bd_next = prev->bd_next; | |
79 | prev->bd_next = bdp; | |
80 | } | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
85 | /* | |
86 | * Remove a behavior descriptor from a position in a behavior chain; | |
87 | * the postition is guaranteed not to be the first position. | |
88 | * Should only be called by the bhv_remove() macro. | |
89 | */ | |
90 | void | |
91 | bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp) | |
92 | { | |
93 | bhv_desc_t *curdesc, *prev; | |
94 | ||
95 | ASSERT(bhp->bh_first != NULL); | |
96 | ASSERT(bhp->bh_first->bd_next != NULL); | |
97 | ||
98 | prev = bhp->bh_first; | |
99 | for (curdesc = bhp->bh_first->bd_next; | |
100 | curdesc != NULL; | |
101 | curdesc = curdesc->bd_next) { | |
102 | ||
103 | if (curdesc == bdp) | |
104 | break; /* found it */ | |
105 | prev = curdesc; | |
106 | } | |
107 | ||
108 | ASSERT(curdesc == bdp); | |
109 | prev->bd_next = bdp->bd_next; /* remove from after prev */ | |
110 | } | |
111 | ||
112 | /* | |
113 | * Look for a specific ops vector on the specified behavior chain. | |
114 | * Return the associated behavior descriptor. Or NULL, if not found. | |
115 | */ | |
116 | bhv_desc_t * | |
117 | bhv_lookup(bhv_head_t *bhp, void *ops) | |
118 | { | |
119 | bhv_desc_t *curdesc; | |
120 | ||
121 | for (curdesc = bhp->bh_first; | |
122 | curdesc != NULL; | |
123 | curdesc = curdesc->bd_next) { | |
124 | ||
125 | if (curdesc->bd_ops == ops) | |
126 | return curdesc; | |
127 | } | |
128 | ||
129 | return NULL; | |
130 | } | |
131 | ||
132 | /* | |
133 | * Looks for the first behavior within a specified range of positions. | |
134 | * Return the associated behavior descriptor. Or NULL, if none found. | |
135 | */ | |
136 | bhv_desc_t * | |
137 | bhv_lookup_range(bhv_head_t *bhp, int low, int high) | |
138 | { | |
139 | bhv_desc_t *curdesc; | |
140 | ||
141 | for (curdesc = bhp->bh_first; | |
142 | curdesc != NULL; | |
143 | curdesc = curdesc->bd_next) { | |
144 | ||
145 | int position = BHV_POSITION(curdesc); | |
146 | ||
147 | if (position <= high) { | |
148 | if (position >= low) | |
149 | return curdesc; | |
150 | return NULL; | |
151 | } | |
152 | } | |
153 | ||
154 | return NULL; | |
155 | } | |
156 | ||
157 | /* | |
158 | * Return the base behavior in the chain, or NULL if the chain | |
159 | * is empty. | |
160 | * | |
161 | * The caller has not read locked the behavior chain, so acquire the | |
162 | * lock before traversing the chain. | |
163 | */ | |
164 | bhv_desc_t * | |
165 | bhv_base(bhv_head_t *bhp) | |
166 | { | |
167 | bhv_desc_t *curdesc; | |
168 | ||
169 | for (curdesc = bhp->bh_first; | |
170 | curdesc != NULL; | |
171 | curdesc = curdesc->bd_next) { | |
172 | ||
173 | if (curdesc->bd_next == NULL) { | |
174 | return curdesc; | |
175 | } | |
176 | } | |
177 | ||
178 | return NULL; | |
179 | } | |
180 | ||
181 | void | |
182 | bhv_head_init( | |
183 | bhv_head_t *bhp, | |
184 | char *name) | |
185 | { | |
186 | bhp->bh_first = NULL; | |
187 | } | |
188 | ||
189 | void | |
190 | bhv_insert_initial( | |
191 | bhv_head_t *bhp, | |
192 | bhv_desc_t *bdp) | |
193 | { | |
194 | ASSERT(bhp->bh_first == NULL); | |
195 | (bhp)->bh_first = bdp; | |
196 | } | |
197 | ||
198 | void | |
199 | bhv_head_destroy( | |
200 | bhv_head_t *bhp) | |
201 | { | |
202 | ASSERT(bhp->bh_first == NULL); | |
203 | } |