ocfs2: slot_map I/O based on max_slots.
[safe/jmp/linux-2.6] / fs / ocfs2 / slot_map.c
1 /* -*- mode: c; c-basic-offset: 8; -*-
2  * vim: noexpandtab sw=8 ts=8 sts=0:
3  *
4  * slot_map.c
5  *
6  *
7  *
8  * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this program; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 021110-1307, USA.
24  */
25
26 #include <linux/types.h>
27 #include <linux/slab.h>
28 #include <linux/highmem.h>
29
30 #define MLOG_MASK_PREFIX ML_SUPER
31 #include <cluster/masklog.h>
32
33 #include "ocfs2.h"
34
35 #include "dlmglue.h"
36 #include "extent_map.h"
37 #include "heartbeat.h"
38 #include "inode.h"
39 #include "slot_map.h"
40 #include "super.h"
41 #include "sysfile.h"
42
43 #include "buffer_head_io.h"
44
45 struct ocfs2_slot_info {
46         struct inode *si_inode;
47         unsigned int si_blocks;
48         struct buffer_head **si_bh;
49         unsigned int si_num_slots;
50         unsigned int si_size;
51         s16 si_global_node_nums[OCFS2_MAX_SLOTS];
52 };
53
54
55 static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
56                                     s16 global);
57 static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
58                               s16 slot_num,
59                               s16 node_num);
60
61 /*
62  * Post the slot information on disk into our slot_info struct.
63  * Must be protected by osb_lock.
64  */
65 static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
66 {
67         int i;
68         __le16 *disk_info;
69
70         /* we don't read the slot block here as ocfs2_super_lock
71          * should've made sure we have the most recent copy. */
72         disk_info = (__le16 *) si->si_bh[0]->b_data;
73
74         for (i = 0; i < si->si_size; i++)
75                 si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]);
76 }
77
78 int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
79 {
80         int ret;
81         struct ocfs2_slot_info *si = osb->slot_info;
82
83         if (si == NULL)
84                 return 0;
85
86         BUG_ON(si->si_blocks == 0);
87         BUG_ON(si->si_bh == NULL);
88
89         mlog(0, "Refreshing slot map, reading %u block(s)\n",
90              si->si_blocks);
91
92         /*
93          * We pass -1 as blocknr because we expect all of si->si_bh to
94          * be !NULL.  Thus, ocfs2_read_blocks() will ignore blocknr.  If
95          * this is not true, the read of -1 (UINT64_MAX) will fail.
96          */
97         ret = ocfs2_read_blocks(osb, -1, si->si_blocks, si->si_bh, 0,
98                                 si->si_inode);
99         if (ret == 0) {
100                 spin_lock(&osb->osb_lock);
101                 ocfs2_update_slot_info(si);
102                 spin_unlock(&osb->osb_lock);
103         }
104
105         return ret;
106 }
107
108 /* post the our slot info stuff into it's destination bh and write it
109  * out. */
110 static int ocfs2_update_disk_slots(struct ocfs2_super *osb,
111                                    struct ocfs2_slot_info *si)
112 {
113         int status, i;
114         __le16 *disk_info = (__le16 *) si->si_bh[0]->b_data;
115
116         spin_lock(&osb->osb_lock);
117         for (i = 0; i < si->si_size; i++)
118                 disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
119         spin_unlock(&osb->osb_lock);
120
121         status = ocfs2_write_block(osb, si->si_bh[0], si->si_inode);
122         if (status < 0)
123                 mlog_errno(status);
124
125         return status;
126 }
127
128 /*
129  * Calculate how many bytes are needed by the slot map.  Returns
130  * an error if the slot map file is too small.
131  */
132 static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb,
133                                         struct inode *inode,
134                                         unsigned long long *bytes)
135 {
136         unsigned long long bytes_needed;
137
138         bytes_needed = osb->max_slots * sizeof(__le16);
139         if (bytes_needed > i_size_read(inode)) {
140                 mlog(ML_ERROR,
141                      "Slot map file is too small!  (size %llu, needed %llu)\n",
142                      i_size_read(inode), bytes_needed);
143                 return -ENOSPC;
144         }
145
146         *bytes = bytes_needed;
147         return 0;
148 }
149
150 /* try to find global node in the slot info. Returns
151  * OCFS2_INVALID_SLOT if nothing is found. */
152 static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
153                                     s16 global)
154 {
155         int i;
156         s16 ret = OCFS2_INVALID_SLOT;
157
158         for(i = 0; i < si->si_num_slots; i++) {
159                 if (global == si->si_global_node_nums[i]) {
160                         ret = (s16) i;
161                         break;
162                 }
163         }
164         return ret;
165 }
166
167 static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si,
168                                    s16 preferred)
169 {
170         int i;
171         s16 ret = OCFS2_INVALID_SLOT;
172
173         if (preferred >= 0 && preferred < si->si_num_slots) {
174                 if (OCFS2_INVALID_SLOT == si->si_global_node_nums[preferred]) {
175                         ret = preferred;
176                         goto out;
177                 }
178         }
179
180         for(i = 0; i < si->si_num_slots; i++) {
181                 if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
182                         ret = (s16) i;
183                         break;
184                 }
185         }
186 out:
187         return ret;
188 }
189
190 int ocfs2_node_num_to_slot(struct ocfs2_super *osb, unsigned int node_num)
191 {
192         s16 slot;
193         struct ocfs2_slot_info *si = osb->slot_info;
194
195         spin_lock(&osb->osb_lock);
196         slot = __ocfs2_node_num_to_slot(si, node_num);
197         spin_unlock(&osb->osb_lock);
198
199         if (slot == OCFS2_INVALID_SLOT)
200                 return -ENOENT;
201
202         return slot;
203 }
204
205 int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
206                                   unsigned int *node_num)
207 {
208         struct ocfs2_slot_info *si = osb->slot_info;
209
210         assert_spin_locked(&osb->osb_lock);
211
212         BUG_ON(slot_num < 0);
213         BUG_ON(slot_num > osb->max_slots);
214
215         if (si->si_global_node_nums[slot_num] == OCFS2_INVALID_SLOT)
216                 return -ENOENT;
217
218         *node_num = si->si_global_node_nums[slot_num];
219         return 0;
220 }
221
222 static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
223 {
224         unsigned int i;
225
226         if (si == NULL)
227                 return;
228
229         if (si->si_inode)
230                 iput(si->si_inode);
231         if (si->si_bh) {
232                 for (i = 0; i < si->si_blocks; i++) {
233                         if (si->si_bh[i]) {
234                                 brelse(si->si_bh[i]);
235                                 si->si_bh[i] = NULL;
236                         }
237                 }
238                 kfree(si->si_bh);
239         }
240
241         kfree(si);
242 }
243
244 static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
245                               s16 slot_num,
246                               s16 node_num)
247 {
248         BUG_ON(slot_num == OCFS2_INVALID_SLOT);
249         BUG_ON(slot_num >= si->si_num_slots);
250         BUG_ON((node_num != O2NM_INVALID_NODE_NUM) &&
251                (node_num >= O2NM_MAX_NODES));
252
253         si->si_global_node_nums[slot_num] = node_num;
254 }
255
256 int ocfs2_clear_slot(struct ocfs2_super *osb, s16 slot_num)
257 {
258         struct ocfs2_slot_info *si = osb->slot_info;
259
260         if (si == NULL)
261                 return 0;
262
263         spin_lock(&osb->osb_lock);
264         __ocfs2_fill_slot(si, slot_num, OCFS2_INVALID_SLOT);
265         spin_unlock(&osb->osb_lock);
266
267         return ocfs2_update_disk_slots(osb, osb->slot_info);
268 }
269
270 static int ocfs2_map_slot_buffers(struct ocfs2_super *osb,
271                                   struct ocfs2_slot_info *si)
272 {
273         int status = 0;
274         u64 blkno;
275         unsigned long long blocks, bytes;
276         unsigned int i;
277         struct buffer_head *bh;
278
279         status = ocfs2_slot_map_physical_size(osb, si->si_inode, &bytes);
280         if (status)
281                 goto bail;
282
283         blocks = ocfs2_blocks_for_bytes(si->si_inode->i_sb, bytes);
284         BUG_ON(blocks > UINT_MAX);
285         si->si_blocks = blocks;
286         if (!si->si_blocks)
287                 goto bail;
288
289         mlog(0, "Slot map needs %u buffers for %llu bytes\n",
290              si->si_blocks, bytes);
291
292         si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks,
293                             GFP_KERNEL);
294         if (!si->si_bh) {
295                 status = -ENOMEM;
296                 mlog_errno(status);
297                 goto bail;
298         }
299
300         for (i = 0; i < si->si_blocks; i++) {
301                 status = ocfs2_extent_map_get_blocks(si->si_inode, i,
302                                                      &blkno, NULL, NULL);
303                 if (status < 0) {
304                         mlog_errno(status);
305                         goto bail;
306                 }
307
308                 mlog(0, "Reading slot map block %u at %llu\n", i,
309                      (unsigned long long)blkno);
310
311                 bh = NULL;  /* Acquire a fresh bh */
312                 status = ocfs2_read_block(osb, blkno, &bh, 0, si->si_inode);
313                 if (status < 0) {
314                         mlog_errno(status);
315                         goto bail;
316                 }
317
318                 si->si_bh[i] = bh;
319         }
320
321 bail:
322         return status;
323 }
324
325 int ocfs2_init_slot_info(struct ocfs2_super *osb)
326 {
327         int status, i;
328         struct inode *inode = NULL;
329         struct ocfs2_slot_info *si;
330
331         si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
332         if (!si) {
333                 status = -ENOMEM;
334                 mlog_errno(status);
335                 goto bail;
336         }
337
338         si->si_num_slots = osb->max_slots;
339         si->si_size = OCFS2_MAX_SLOTS;
340
341         for(i = 0; i < si->si_num_slots; i++)
342                 si->si_global_node_nums[i] = OCFS2_INVALID_SLOT;
343
344         inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
345                                             OCFS2_INVALID_SLOT);
346         if (!inode) {
347                 status = -EINVAL;
348                 mlog_errno(status);
349                 goto bail;
350         }
351
352         si->si_inode = inode;
353         status = ocfs2_map_slot_buffers(osb, si);
354         if (status < 0) {
355                 mlog_errno(status);
356                 goto bail;
357         }
358
359         osb->slot_info = (struct ocfs2_slot_info *)si;
360 bail:
361         if (status < 0 && si)
362                 __ocfs2_free_slot_info(si);
363
364         return status;
365 }
366
367 void ocfs2_free_slot_info(struct ocfs2_super *osb)
368 {
369         struct ocfs2_slot_info *si = osb->slot_info;
370
371         osb->slot_info = NULL;
372         __ocfs2_free_slot_info(si);
373 }
374
375 int ocfs2_find_slot(struct ocfs2_super *osb)
376 {
377         int status;
378         s16 slot;
379         struct ocfs2_slot_info *si;
380
381         mlog_entry_void();
382
383         si = osb->slot_info;
384
385         spin_lock(&osb->osb_lock);
386         ocfs2_update_slot_info(si);
387
388         /* search for ourselves first and take the slot if it already
389          * exists. Perhaps we need to mark this in a variable for our
390          * own journal recovery? Possibly not, though we certainly
391          * need to warn to the user */
392         slot = __ocfs2_node_num_to_slot(si, osb->node_num);
393         if (slot == OCFS2_INVALID_SLOT) {
394                 /* if no slot yet, then just take 1st available
395                  * one. */
396                 slot = __ocfs2_find_empty_slot(si, osb->preferred_slot);
397                 if (slot == OCFS2_INVALID_SLOT) {
398                         spin_unlock(&osb->osb_lock);
399                         mlog(ML_ERROR, "no free slots available!\n");
400                         status = -EINVAL;
401                         goto bail;
402                 }
403         } else
404                 mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
405                      slot);
406
407         __ocfs2_fill_slot(si, slot, osb->node_num);
408         osb->slot_num = slot;
409         spin_unlock(&osb->osb_lock);
410
411         mlog(0, "taking node slot %d\n", osb->slot_num);
412
413         status = ocfs2_update_disk_slots(osb, si);
414         if (status < 0)
415                 mlog_errno(status);
416
417 bail:
418         mlog_exit(status);
419         return status;
420 }
421
422 void ocfs2_put_slot(struct ocfs2_super *osb)
423 {
424         int status;
425         struct ocfs2_slot_info *si = osb->slot_info;
426
427         if (!si)
428                 return;
429
430         spin_lock(&osb->osb_lock);
431         ocfs2_update_slot_info(si);
432
433         __ocfs2_fill_slot(si, osb->slot_num, OCFS2_INVALID_SLOT);
434         osb->slot_num = OCFS2_INVALID_SLOT;
435         spin_unlock(&osb->osb_lock);
436
437         status = ocfs2_update_disk_slots(osb, si);
438         if (status < 0) {
439                 mlog_errno(status);
440                 goto bail;
441         }
442
443 bail:
444         ocfs2_free_slot_info(osb);
445 }
446