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