diff options
Diffstat (limited to 'fs/ocfs2/slot_map.c')
-rw-r--r-- | fs/ocfs2/slot_map.c | 454 |
1 files changed, 353 insertions, 101 deletions
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index 3a50ce555e64..bb5ff8939bf1 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c | |||
@@ -42,81 +42,244 @@ | |||
42 | 42 | ||
43 | #include "buffer_head_io.h" | 43 | #include "buffer_head_io.h" |
44 | 44 | ||
45 | static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, | 45 | |
46 | s16 global); | 46 | struct ocfs2_slot { |
47 | static void __ocfs2_fill_slot(struct ocfs2_slot_info *si, | 47 | int sl_valid; |
48 | s16 slot_num, | 48 | unsigned int sl_node_num; |
49 | s16 node_num); | 49 | }; |
50 | 50 | ||
51 | /* post the slot information on disk into our slot_info struct. */ | 51 | struct ocfs2_slot_info { |
52 | void ocfs2_update_slot_info(struct ocfs2_slot_info *si) | 52 | int si_extended; |
53 | int si_slots_per_block; | ||
54 | struct inode *si_inode; | ||
55 | unsigned int si_blocks; | ||
56 | struct buffer_head **si_bh; | ||
57 | unsigned int si_num_slots; | ||
58 | struct ocfs2_slot *si_slots; | ||
59 | }; | ||
60 | |||
61 | |||
62 | static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, | ||
63 | unsigned int node_num); | ||
64 | |||
65 | static void ocfs2_invalidate_slot(struct ocfs2_slot_info *si, | ||
66 | int slot_num) | ||
67 | { | ||
68 | BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); | ||
69 | si->si_slots[slot_num].sl_valid = 0; | ||
70 | } | ||
71 | |||
72 | static void ocfs2_set_slot(struct ocfs2_slot_info *si, | ||
73 | int slot_num, unsigned int node_num) | ||
74 | { | ||
75 | BUG_ON((slot_num < 0) || (slot_num >= si->si_num_slots)); | ||
76 | |||
77 | si->si_slots[slot_num].sl_valid = 1; | ||
78 | si->si_slots[slot_num].sl_node_num = node_num; | ||
79 | } | ||
80 | |||
81 | /* This version is for the extended slot map */ | ||
82 | static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si) | ||
83 | { | ||
84 | int b, i, slotno; | ||
85 | struct ocfs2_slot_map_extended *se; | ||
86 | |||
87 | slotno = 0; | ||
88 | for (b = 0; b < si->si_blocks; b++) { | ||
89 | se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; | ||
90 | for (i = 0; | ||
91 | (i < si->si_slots_per_block) && | ||
92 | (slotno < si->si_num_slots); | ||
93 | i++, slotno++) { | ||
94 | if (se->se_slots[i].es_valid) | ||
95 | ocfs2_set_slot(si, slotno, | ||
96 | le32_to_cpu(se->se_slots[i].es_node_num)); | ||
97 | else | ||
98 | ocfs2_invalidate_slot(si, slotno); | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Post the slot information on disk into our slot_info struct. | ||
105 | * Must be protected by osb_lock. | ||
106 | */ | ||
107 | static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si) | ||
53 | { | 108 | { |
54 | int i; | 109 | int i; |
55 | __le16 *disk_info; | 110 | struct ocfs2_slot_map *sm; |
56 | 111 | ||
57 | /* we don't read the slot block here as ocfs2_super_lock | 112 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; |
58 | * should've made sure we have the most recent copy. */ | ||
59 | spin_lock(&si->si_lock); | ||
60 | disk_info = (__le16 *) si->si_bh->b_data; | ||
61 | 113 | ||
62 | for (i = 0; i < si->si_size; i++) | 114 | for (i = 0; i < si->si_num_slots; i++) { |
63 | si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]); | 115 | if (le16_to_cpu(sm->sm_slots[i]) == (u16)OCFS2_INVALID_SLOT) |
116 | ocfs2_invalidate_slot(si, i); | ||
117 | else | ||
118 | ocfs2_set_slot(si, i, le16_to_cpu(sm->sm_slots[i])); | ||
119 | } | ||
120 | } | ||
64 | 121 | ||
65 | spin_unlock(&si->si_lock); | 122 | static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) |
123 | { | ||
124 | /* | ||
125 | * The slot data will have been refreshed when ocfs2_super_lock | ||
126 | * was taken. | ||
127 | */ | ||
128 | if (si->si_extended) | ||
129 | ocfs2_update_slot_info_extended(si); | ||
130 | else | ||
131 | ocfs2_update_slot_info_old(si); | ||
132 | } | ||
133 | |||
134 | int ocfs2_refresh_slot_info(struct ocfs2_super *osb) | ||
135 | { | ||
136 | int ret; | ||
137 | struct ocfs2_slot_info *si = osb->slot_info; | ||
138 | |||
139 | if (si == NULL) | ||
140 | return 0; | ||
141 | |||
142 | BUG_ON(si->si_blocks == 0); | ||
143 | BUG_ON(si->si_bh == NULL); | ||
144 | |||
145 | mlog(0, "Refreshing slot map, reading %u block(s)\n", | ||
146 | si->si_blocks); | ||
147 | |||
148 | /* | ||
149 | * We pass -1 as blocknr because we expect all of si->si_bh to | ||
150 | * be !NULL. Thus, ocfs2_read_blocks() will ignore blocknr. If | ||
151 | * this is not true, the read of -1 (UINT64_MAX) will fail. | ||
152 | */ | ||
153 | ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0, | ||
154 | si->si_inode); | ||
155 | if (ret == 0) { | ||
156 | spin_lock(&osb->osb_lock); | ||
157 | ocfs2_update_slot_info(si); | ||
158 | spin_unlock(&osb->osb_lock); | ||
159 | } | ||
160 | |||
161 | return ret; | ||
66 | } | 162 | } |
67 | 163 | ||
68 | /* post the our slot info stuff into it's destination bh and write it | 164 | /* post the our slot info stuff into it's destination bh and write it |
69 | * out. */ | 165 | * out. */ |
70 | int ocfs2_update_disk_slots(struct ocfs2_super *osb, | 166 | static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, |
71 | struct ocfs2_slot_info *si) | 167 | int slot_num, |
168 | struct buffer_head **bh) | ||
72 | { | 169 | { |
73 | int status, i; | 170 | int blkind = slot_num / si->si_slots_per_block; |
74 | __le16 *disk_info = (__le16 *) si->si_bh->b_data; | 171 | int slotno = slot_num % si->si_slots_per_block; |
172 | struct ocfs2_slot_map_extended *se; | ||
173 | |||
174 | BUG_ON(blkind >= si->si_blocks); | ||
175 | |||
176 | se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data; | ||
177 | se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; | ||
178 | if (si->si_slots[slot_num].sl_valid) | ||
179 | se->se_slots[slotno].es_node_num = | ||
180 | cpu_to_le32(si->si_slots[slot_num].sl_node_num); | ||
181 | *bh = si->si_bh[blkind]; | ||
182 | } | ||
75 | 183 | ||
76 | spin_lock(&si->si_lock); | 184 | static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, |
77 | for (i = 0; i < si->si_size; i++) | 185 | int slot_num, |
78 | disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]); | 186 | struct buffer_head **bh) |
79 | spin_unlock(&si->si_lock); | 187 | { |
188 | int i; | ||
189 | struct ocfs2_slot_map *sm; | ||
190 | |||
191 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; | ||
192 | for (i = 0; i < si->si_num_slots; i++) { | ||
193 | if (si->si_slots[i].sl_valid) | ||
194 | sm->sm_slots[i] = | ||
195 | cpu_to_le16(si->si_slots[i].sl_node_num); | ||
196 | else | ||
197 | sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); | ||
198 | } | ||
199 | *bh = si->si_bh[0]; | ||
200 | } | ||
201 | |||
202 | static int ocfs2_update_disk_slot(struct ocfs2_super *osb, | ||
203 | struct ocfs2_slot_info *si, | ||
204 | int slot_num) | ||
205 | { | ||
206 | int status; | ||
207 | struct buffer_head *bh; | ||
208 | |||
209 | spin_lock(&osb->osb_lock); | ||
210 | if (si->si_extended) | ||
211 | ocfs2_update_disk_slot_extended(si, slot_num, &bh); | ||
212 | else | ||
213 | ocfs2_update_disk_slot_old(si, slot_num, &bh); | ||
214 | spin_unlock(&osb->osb_lock); | ||
80 | 215 | ||
81 | status = ocfs2_write_block(osb, si->si_bh, si->si_inode); | 216 | status = ocfs2_write_block(osb, bh, si->si_inode); |
82 | if (status < 0) | 217 | if (status < 0) |
83 | mlog_errno(status); | 218 | mlog_errno(status); |
84 | 219 | ||
85 | return status; | 220 | return status; |
86 | } | 221 | } |
87 | 222 | ||
88 | /* try to find global node in the slot info. Returns | 223 | /* |
89 | * OCFS2_INVALID_SLOT if nothing is found. */ | 224 | * Calculate how many bytes are needed by the slot map. Returns |
90 | static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, | 225 | * an error if the slot map file is too small. |
91 | s16 global) | 226 | */ |
227 | static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb, | ||
228 | struct inode *inode, | ||
229 | unsigned long long *bytes) | ||
92 | { | 230 | { |
93 | int i; | 231 | unsigned long long bytes_needed; |
94 | s16 ret = OCFS2_INVALID_SLOT; | 232 | |
233 | if (ocfs2_uses_extended_slot_map(osb)) { | ||
234 | bytes_needed = osb->max_slots * | ||
235 | sizeof(struct ocfs2_extended_slot); | ||
236 | } else { | ||
237 | bytes_needed = osb->max_slots * sizeof(__le16); | ||
238 | } | ||
239 | if (bytes_needed > i_size_read(inode)) { | ||
240 | mlog(ML_ERROR, | ||
241 | "Slot map file is too small! (size %llu, needed %llu)\n", | ||
242 | i_size_read(inode), bytes_needed); | ||
243 | return -ENOSPC; | ||
244 | } | ||
245 | |||
246 | *bytes = bytes_needed; | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* try to find global node in the slot info. Returns -ENOENT | ||
251 | * if nothing is found. */ | ||
252 | static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, | ||
253 | unsigned int node_num) | ||
254 | { | ||
255 | int i, ret = -ENOENT; | ||
95 | 256 | ||
96 | for(i = 0; i < si->si_num_slots; i++) { | 257 | for(i = 0; i < si->si_num_slots; i++) { |
97 | if (global == si->si_global_node_nums[i]) { | 258 | if (si->si_slots[i].sl_valid && |
98 | ret = (s16) i; | 259 | (node_num == si->si_slots[i].sl_node_num)) { |
260 | ret = i; | ||
99 | break; | 261 | break; |
100 | } | 262 | } |
101 | } | 263 | } |
264 | |||
102 | return ret; | 265 | return ret; |
103 | } | 266 | } |
104 | 267 | ||
105 | static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, s16 preferred) | 268 | static int __ocfs2_find_empty_slot(struct ocfs2_slot_info *si, |
269 | int preferred) | ||
106 | { | 270 | { |
107 | int i; | 271 | int i, ret = -ENOSPC; |
108 | s16 ret = OCFS2_INVALID_SLOT; | ||
109 | 272 | ||
110 | if (preferred >= 0 && preferred < si->si_num_slots) { | 273 | if ((preferred >= 0) && (preferred < si->si_num_slots)) { |
111 | if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) { | 274 | if (!si->si_slots[preferred].sl_valid) { |
112 | ret = preferred; | 275 | ret = preferred; |
113 | goto out; | 276 | goto out; |
114 | } | 277 | } |
115 | } | 278 | } |
116 | 279 | ||
117 | for(i = 0; i < si->si_num_slots; i++) { | 280 | for(i = 0; i < si->si_num_slots; i++) { |
118 | if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) { | 281 | if (!si->si_slots[i].sl_valid) { |
119 | ret = (s16) i; | 282 | ret = i; |
120 | break; | 283 | break; |
121 | } | 284 | } |
122 | } | 285 | } |
@@ -124,58 +287,155 @@ out: | |||
124 | return ret; | 287 | return ret; |
125 | } | 288 | } |
126 | 289 | ||
127 | s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, | 290 | int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num) |
128 | s16 global) | ||
129 | { | 291 | { |
130 | s16 ret; | 292 | int slot; |
293 | struct ocfs2_slot_info *si = osb->slot_info; | ||
131 | 294 | ||
132 | spin_lock(&si->si_lock); | 295 | spin_lock(&osb->osb_lock); |
133 | ret = __ocfs2_node_num_to_slot(si, global); | 296 | slot = __ocfs2_node_num_to_slot(si, node_num); |
134 | spin_unlock(&si->si_lock); | 297 | spin_unlock(&osb->osb_lock); |
135 | return ret; | 298 | |
299 | return slot; | ||
300 | } | ||
301 | |||
302 | int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num, | ||
303 | unsigned int *node_num) | ||
304 | { | ||
305 | struct ocfs2_slot_info *si = osb->slot_info; | ||
306 | |||
307 | assert_spin_locked(&osb->osb_lock); | ||
308 | |||
309 | BUG_ON(slot_num < 0); | ||
310 | BUG_ON(slot_num > osb->max_slots); | ||
311 | |||
312 | if (!si->si_slots[slot_num].sl_valid) | ||
313 | return -ENOENT; | ||
314 | |||
315 | *node_num = si->si_slots[slot_num].sl_node_num; | ||
316 | return 0; | ||
136 | } | 317 | } |
137 | 318 | ||
138 | static void __ocfs2_fill_slot(struct ocfs2_slot_info *si, | 319 | static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si) |
139 | s16 slot_num, | ||
140 | s16 node_num) | ||
141 | { | 320 | { |
142 | BUG_ON(slot_num == OCFS2_INVALID_SLOT); | 321 | unsigned int i; |
143 | BUG_ON(slot_num >= si->si_num_slots); | 322 | |
144 | BUG_ON((node_num != O2NM_INVALID_NODE_NUM) && | 323 | if (si == NULL) |
145 | (node_num >= O2NM_MAX_NODES)); | 324 | return; |
325 | |||
326 | if (si->si_inode) | ||
327 | iput(si->si_inode); | ||
328 | if (si->si_bh) { | ||
329 | for (i = 0; i < si->si_blocks; i++) { | ||
330 | if (si->si_bh[i]) { | ||
331 | brelse(si->si_bh[i]); | ||
332 | si->si_bh[i] = NULL; | ||
333 | } | ||
334 | } | ||
335 | kfree(si->si_bh); | ||
336 | } | ||
146 | 337 | ||
147 | si->si_global_node_nums[slot_num] = node_num; | 338 | kfree(si); |
148 | } | 339 | } |
149 | 340 | ||
150 | void ocfs2_clear_slot(struct ocfs2_slot_info *si, | 341 | int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) |
151 | s16 slot_num) | ||
152 | { | 342 | { |
153 | spin_lock(&si->si_lock); | 343 | struct ocfs2_slot_info *si = osb->slot_info; |
154 | __ocfs2_fill_slot(si, slot_num, OCFS2_INVALID_SLOT); | 344 | |
155 | spin_unlock(&si->si_lock); | 345 | if (si == NULL) |
346 | return 0; | ||
347 | |||
348 | spin_lock(&osb->osb_lock); | ||
349 | ocfs2_invalidate_slot(si, slot_num); | ||
350 | spin_unlock(&osb->osb_lock); | ||
351 | |||
352 | return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num); | ||
156 | } | 353 | } |
157 | 354 | ||
158 | int ocfs2_init_slot_info(struct ocfs2_super *osb) | 355 | static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, |
356 | struct ocfs2_slot_info *si) | ||
159 | { | 357 | { |
160 | int status, i; | 358 | int status = 0; |
161 | u64 blkno; | 359 | u64 blkno; |
360 | unsigned long long blocks, bytes; | ||
361 | unsigned int i; | ||
362 | struct buffer_head *bh; | ||
363 | |||
364 | status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes); | ||
365 | if (status) | ||
366 | goto bail; | ||
367 | |||
368 | blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes); | ||
369 | BUG_ON(blocks > UINT_MAX); | ||
370 | si->si_blocks = blocks; | ||
371 | if (!si->si_blocks) | ||
372 | goto bail; | ||
373 | |||
374 | if (si->si_extended) | ||
375 | si->si_slots_per_block = | ||
376 | (osb->sb->s_blocksize / | ||
377 | sizeof(struct ocfs2_extended_slot)); | ||
378 | else | ||
379 | si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16); | ||
380 | |||
381 | /* The size checks above should ensure this */ | ||
382 | BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); | ||
383 | |||
384 | mlog(0, "Slot map needs %u buffers for %llu bytes\n", | ||
385 | si->si_blocks, bytes); | ||
386 | |||
387 | si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks, | ||
388 | GFP_KERNEL); | ||
389 | if (!si->si_bh) { | ||
390 | status = -ENOMEM; | ||
391 | mlog_errno(status); | ||
392 | goto bail; | ||
393 | } | ||
394 | |||
395 | for (i = 0; i < si->si_blocks; i++) { | ||
396 | status = ocfs2_extent_map_get_blocks(si->si_inode, i, | ||
397 | &blkno, NULL, NULL); | ||
398 | if (status < 0) { | ||
399 | mlog_errno(status); | ||
400 | goto bail; | ||
401 | } | ||
402 | |||
403 | mlog(0, "Reading slot map block %u at %llu\n", i, | ||
404 | (unsigned long long)blkno); | ||
405 | |||
406 | bh = NULL; /* Acquire a fresh bh */ | ||
407 | status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode); | ||
408 | if (status < 0) { | ||
409 | mlog_errno(status); | ||
410 | goto bail; | ||
411 | } | ||
412 | |||
413 | si->si_bh[i] = bh; | ||
414 | } | ||
415 | |||
416 | bail: | ||
417 | return status; | ||
418 | } | ||
419 | |||
420 | int ocfs2_init_slot_info(struct ocfs2_super *osb) | ||
421 | { | ||
422 | int status; | ||
162 | struct inode *inode = NULL; | 423 | struct inode *inode = NULL; |
163 | struct buffer_head *bh = NULL; | ||
164 | struct ocfs2_slot_info *si; | 424 | struct ocfs2_slot_info *si; |
165 | 425 | ||
166 | si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL); | 426 | si = kzalloc(sizeof(struct ocfs2_slot_info) + |
427 | (sizeof(struct ocfs2_slot) * osb->max_slots), | ||
428 | GFP_KERNEL); | ||
167 | if (!si) { | 429 | if (!si) { |
168 | status = -ENOMEM; | 430 | status = -ENOMEM; |
169 | mlog_errno(status); | 431 | mlog_errno(status); |
170 | goto bail; | 432 | goto bail; |
171 | } | 433 | } |
172 | 434 | ||
173 | spin_lock_init(&si->si_lock); | 435 | si->si_extended = ocfs2_uses_extended_slot_map(osb); |
174 | si->si_num_slots = osb->max_slots; | 436 | si->si_num_slots = osb->max_slots; |
175 | si->si_size = OCFS2_MAX_SLOTS; | 437 | si->si_slots = (struct ocfs2_slot *)((char *)si + |
176 | 438 | sizeof(struct ocfs2_slot_info)); | |
177 | for(i = 0; i < si->si_num_slots; i++) | ||
178 | si->si_global_node_nums[i] = OCFS2_INVALID_SLOT; | ||
179 | 439 | ||
180 | inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE, | 440 | inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE, |
181 | OCFS2_INVALID_SLOT); | 441 | OCFS2_INVALID_SLOT); |
@@ -185,61 +445,53 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb) | |||
185 | goto bail; | 445 | goto bail; |
186 | } | 446 | } |
187 | 447 | ||
188 | status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL); | 448 | si->si_inode = inode; |
189 | if (status < 0) { | 449 | status = ocfs2_map_slot_buffers(osb, si); |
190 | mlog_errno(status); | ||
191 | goto bail; | ||
192 | } | ||
193 | |||
194 | status = ocfs2_read_block(osb, blkno, &bh, 0, inode); | ||
195 | if (status < 0) { | 450 | if (status < 0) { |
196 | mlog_errno(status); | 451 | mlog_errno(status); |
197 | goto bail; | 452 | goto bail; |
198 | } | 453 | } |
199 | 454 | ||
200 | si->si_inode = inode; | 455 | osb->slot_info = (struct ocfs2_slot_info *)si; |
201 | si->si_bh = bh; | ||
202 | osb->slot_info = si; | ||
203 | bail: | 456 | bail: |
204 | if (status < 0 && si) | 457 | if (status < 0 && si) |
205 | ocfs2_free_slot_info(si); | 458 | __ocfs2_free_slot_info(si); |
206 | 459 | ||
207 | return status; | 460 | return status; |
208 | } | 461 | } |
209 | 462 | ||
210 | void ocfs2_free_slot_info(struct ocfs2_slot_info *si) | 463 | void ocfs2_free_slot_info(struct ocfs2_super *osb) |
211 | { | 464 | { |
212 | if (si->si_inode) | 465 | struct ocfs2_slot_info *si = osb->slot_info; |
213 | iput(si->si_inode); | 466 | |
214 | if (si->si_bh) | 467 | osb->slot_info = NULL; |
215 | brelse(si->si_bh); | 468 | __ocfs2_free_slot_info(si); |
216 | kfree(si); | ||
217 | } | 469 | } |
218 | 470 | ||
219 | int ocfs2_find_slot(struct ocfs2_super *osb) | 471 | int ocfs2_find_slot(struct ocfs2_super *osb) |
220 | { | 472 | { |
221 | int status; | 473 | int status; |
222 | s16 slot; | 474 | int slot; |
223 | struct ocfs2_slot_info *si; | 475 | struct ocfs2_slot_info *si; |
224 | 476 | ||
225 | mlog_entry_void(); | 477 | mlog_entry_void(); |
226 | 478 | ||
227 | si = osb->slot_info; | 479 | si = osb->slot_info; |
228 | 480 | ||
481 | spin_lock(&osb->osb_lock); | ||
229 | ocfs2_update_slot_info(si); | 482 | ocfs2_update_slot_info(si); |
230 | 483 | ||
231 | spin_lock(&si->si_lock); | ||
232 | /* search for ourselves first and take the slot if it already | 484 | /* search for ourselves first and take the slot if it already |
233 | * exists. Perhaps we need to mark this in a variable for our | 485 | * exists. Perhaps we need to mark this in a variable for our |
234 | * own journal recovery? Possibly not, though we certainly | 486 | * own journal recovery? Possibly not, though we certainly |
235 | * need to warn to the user */ | 487 | * need to warn to the user */ |
236 | slot = __ocfs2_node_num_to_slot(si, osb->node_num); | 488 | slot = __ocfs2_node_num_to_slot(si, osb->node_num); |
237 | if (slot == OCFS2_INVALID_SLOT) { | 489 | if (slot < 0) { |
238 | /* if no slot yet, then just take 1st available | 490 | /* if no slot yet, then just take 1st available |
239 | * one. */ | 491 | * one. */ |
240 | slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); | 492 | slot = __ocfs2_find_empty_slot(si, osb->preferred_slot); |
241 | if (slot == OCFS2_INVALID_SLOT) { | 493 | if (slot < 0) { |
242 | spin_unlock(&si->si_lock); | 494 | spin_unlock(&osb->osb_lock); |
243 | mlog(ML_ERROR, "no free slots available!\n"); | 495 | mlog(ML_ERROR, "no free slots available!\n"); |
244 | status = -EINVAL; | 496 | status = -EINVAL; |
245 | goto bail; | 497 | goto bail; |
@@ -248,13 +500,13 @@ int ocfs2_find_slot(struct ocfs2_super *osb) | |||
248 | mlog(ML_NOTICE, "slot %d is already allocated to this node!\n", | 500 | mlog(ML_NOTICE, "slot %d is already allocated to this node!\n", |
249 | slot); | 501 | slot); |
250 | 502 | ||
251 | __ocfs2_fill_slot(si, slot, osb->node_num); | 503 | ocfs2_set_slot(si, slot, osb->node_num); |
252 | osb->slot_num = slot; | 504 | osb->slot_num = slot; |
253 | spin_unlock(&si->si_lock); | 505 | spin_unlock(&osb->osb_lock); |
254 | 506 | ||
255 | mlog(0, "taking node slot %d\n", osb->slot_num); | 507 | mlog(0, "taking node slot %d\n", osb->slot_num); |
256 | 508 | ||
257 | status = ocfs2_update_disk_slots(osb, si); | 509 | status = ocfs2_update_disk_slot(osb, si, osb->slot_num); |
258 | if (status < 0) | 510 | if (status < 0) |
259 | mlog_errno(status); | 511 | mlog_errno(status); |
260 | 512 | ||
@@ -265,27 +517,27 @@ bail: | |||
265 | 517 | ||
266 | void ocfs2_put_slot(struct ocfs2_super *osb) | 518 | void ocfs2_put_slot(struct ocfs2_super *osb) |
267 | { | 519 | { |
268 | int status; | 520 | int status, slot_num; |
269 | struct ocfs2_slot_info *si = osb->slot_info; | 521 | struct ocfs2_slot_info *si = osb->slot_info; |
270 | 522 | ||
271 | if (!si) | 523 | if (!si) |
272 | return; | 524 | return; |
273 | 525 | ||
526 | spin_lock(&osb->osb_lock); | ||
274 | ocfs2_update_slot_info(si); | 527 | ocfs2_update_slot_info(si); |
275 | 528 | ||
276 | spin_lock(&si->si_lock); | 529 | slot_num = osb->slot_num; |
277 | __ocfs2_fill_slot(si, osb->slot_num, OCFS2_INVALID_SLOT); | 530 | ocfs2_invalidate_slot(si, osb->slot_num); |
278 | osb->slot_num = OCFS2_INVALID_SLOT; | 531 | osb->slot_num = OCFS2_INVALID_SLOT; |
279 | spin_unlock(&si->si_lock); | 532 | spin_unlock(&osb->osb_lock); |
280 | 533 | ||
281 | status = ocfs2_update_disk_slots(osb, si); | 534 | status = ocfs2_update_disk_slot(osb, si, slot_num); |
282 | if (status < 0) { | 535 | if (status < 0) { |
283 | mlog_errno(status); | 536 | mlog_errno(status); |
284 | goto bail; | 537 | goto bail; |
285 | } | 538 | } |
286 | 539 | ||
287 | bail: | 540 | bail: |
288 | osb->slot_info = NULL; | 541 | ocfs2_free_slot_info(osb); |
289 | ocfs2_free_slot_info(si); | ||
290 | } | 542 | } |
291 | 543 | ||