diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-02-01 15:06:54 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-04-18 11:56:03 -0400 |
commit | 386a2ef8576e966076c293f6496b9e3d7e3d9035 (patch) | |
tree | 08b6cae47060497359a6ab78134a1bf8e38012cc /fs/ocfs2/slot_map.c | |
parent | fb86b1f07120b66769a39c445da5c4300069dd44 (diff) |
ocfs2: New slot map format
The old slot map had a few limitations:
- It was limited to one block, so the maximum slot count was 255.
- Each slot was signed 16bits, limiting node numbers to INT16_MAX.
- An empty slot was marked by the magic 0xFFFF (-1).
The new slot map format provides 32bit node numbers (UINT32_MAX), a
separate space to mark a slot in use, and extra room to grow. The slot
map is now bounded by i_size, not a block.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/slot_map.c')
-rw-r--r-- | fs/ocfs2/slot_map.c | 110 |
1 files changed, 97 insertions, 13 deletions
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index e7e7a74156b1..63fb1b26d964 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c | |||
@@ -49,6 +49,8 @@ struct ocfs2_slot { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct ocfs2_slot_info { | 51 | struct ocfs2_slot_info { |
52 | int si_extended; | ||
53 | int si_slots_per_block; | ||
52 | struct inode *si_inode; | 54 | struct inode *si_inode; |
53 | unsigned int si_blocks; | 55 | unsigned int si_blocks; |
54 | struct buffer_head **si_bh; | 56 | struct buffer_head **si_bh; |
@@ -78,17 +80,37 @@ static void ocfs2_set_slot(struct ocfs2_slot_info *si, | |||
78 | si->si_slots[slot_num].sl_node_num = node_num; | 80 | si->si_slots[slot_num].sl_node_num = node_num; |
79 | } | 81 | } |
80 | 82 | ||
83 | /* This version is for the extended slot map */ | ||
84 | static void ocfs2_update_slot_info_extended(struct ocfs2_slot_info *si) | ||
85 | { | ||
86 | int b, i, slotno; | ||
87 | struct ocfs2_slot_map_extended *se; | ||
88 | |||
89 | slotno = 0; | ||
90 | for (b = 0; b < si->si_blocks; b++) { | ||
91 | se = (struct ocfs2_slot_map_extended *)si->si_bh[b]->b_data; | ||
92 | for (i = 0; | ||
93 | (i < si->si_slots_per_block) && | ||
94 | (slotno < si->si_num_slots); | ||
95 | i++, slotno++) { | ||
96 | if (se->se_slots[i].es_valid) | ||
97 | ocfs2_set_slot(si, slotno, | ||
98 | le32_to_cpu(se->se_slots[i].es_node_num)); | ||
99 | else | ||
100 | ocfs2_invalidate_slot(si, slotno); | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
81 | /* | 105 | /* |
82 | * Post the slot information on disk into our slot_info struct. | 106 | * Post the slot information on disk into our slot_info struct. |
83 | * Must be protected by osb_lock. | 107 | * Must be protected by osb_lock. |
84 | */ | 108 | */ |
85 | static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) | 109 | static void ocfs2_update_slot_info_old(struct ocfs2_slot_info *si) |
86 | { | 110 | { |
87 | int i; | 111 | int i; |
88 | struct ocfs2_slot_map *sm; | 112 | struct ocfs2_slot_map *sm; |
89 | 113 | ||
90 | /* we don't read the slot block here as ocfs2_super_lock | ||
91 | * should've made sure we have the most recent copy. */ | ||
92 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; | 114 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; |
93 | 115 | ||
94 | for (i = 0; i < si->si_num_slots; i++) { | 116 | for (i = 0; i < si->si_num_slots; i++) { |
@@ -99,6 +121,18 @@ static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) | |||
99 | } | 121 | } |
100 | } | 122 | } |
101 | 123 | ||
124 | static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) | ||
125 | { | ||
126 | /* | ||
127 | * The slot data will have been refreshed when ocfs2_super_lock | ||
128 | * was taken. | ||
129 | */ | ||
130 | if (si->si_extended) | ||
131 | ocfs2_update_slot_info_extended(si); | ||
132 | else | ||
133 | ocfs2_update_slot_info_old(si); | ||
134 | } | ||
135 | |||
102 | int ocfs2_refresh_slot_info(struct ocfs2_super *osb) | 136 | int ocfs2_refresh_slot_info(struct ocfs2_super *osb) |
103 | { | 137 | { |
104 | int ret; | 138 | int ret; |
@@ -131,13 +165,31 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb) | |||
131 | 165 | ||
132 | /* post the our slot info stuff into it's destination bh and write it | 166 | /* post the our slot info stuff into it's destination bh and write it |
133 | * out. */ | 167 | * out. */ |
134 | static int ocfs2_update_disk_slots(struct ocfs2_super *osb, | 168 | static void ocfs2_update_disk_slot_extended(struct ocfs2_slot_info *si, |
135 | struct ocfs2_slot_info *si) | 169 | int slot_num, |
170 | struct buffer_head **bh) | ||
171 | { | ||
172 | int blkind = slot_num / si->si_slots_per_block; | ||
173 | int slotno = slot_num % si->si_slots_per_block; | ||
174 | struct ocfs2_slot_map_extended *se; | ||
175 | |||
176 | BUG_ON(blkind >= si->si_blocks); | ||
177 | |||
178 | se = (struct ocfs2_slot_map_extended *)si->si_bh[blkind]->b_data; | ||
179 | se->se_slots[slotno].es_valid = si->si_slots[slot_num].sl_valid; | ||
180 | if (si->si_slots[slot_num].sl_valid) | ||
181 | se->se_slots[slotno].es_node_num = | ||
182 | cpu_to_le32(si->si_slots[slot_num].sl_node_num); | ||
183 | *bh = si->si_bh[blkind]; | ||
184 | } | ||
185 | |||
186 | static void ocfs2_update_disk_slot_old(struct ocfs2_slot_info *si, | ||
187 | int slot_num, | ||
188 | struct buffer_head **bh) | ||
136 | { | 189 | { |
137 | int status, i; | 190 | int i; |
138 | struct ocfs2_slot_map *sm; | 191 | struct ocfs2_slot_map *sm; |
139 | 192 | ||
140 | spin_lock(&osb->osb_lock); | ||
141 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; | 193 | sm = (struct ocfs2_slot_map *)si->si_bh[0]->b_data; |
142 | for (i = 0; i < si->si_num_slots; i++) { | 194 | for (i = 0; i < si->si_num_slots; i++) { |
143 | if (si->si_slots[i].sl_valid) | 195 | if (si->si_slots[i].sl_valid) |
@@ -146,9 +198,24 @@ static int ocfs2_update_disk_slots(struct ocfs2_super *osb, | |||
146 | else | 198 | else |
147 | sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); | 199 | sm->sm_slots[i] = cpu_to_le16(OCFS2_INVALID_SLOT); |
148 | } | 200 | } |
201 | *bh = si->si_bh[0]; | ||
202 | } | ||
203 | |||
204 | static int ocfs2_update_disk_slot(struct ocfs2_super *osb, | ||
205 | struct ocfs2_slot_info *si, | ||
206 | int slot_num) | ||
207 | { | ||
208 | int status; | ||
209 | struct buffer_head *bh; | ||
210 | |||
211 | spin_lock(&osb->osb_lock); | ||
212 | if (si->si_extended) | ||
213 | ocfs2_update_disk_slot_extended(si, slot_num, &bh); | ||
214 | else | ||
215 | ocfs2_update_disk_slot_old(si, slot_num, &bh); | ||
149 | spin_unlock(&osb->osb_lock); | 216 | spin_unlock(&osb->osb_lock); |
150 | 217 | ||
151 | status = ocfs2_write_block(osb, si->si_bh[0], si->si_inode); | 218 | status = ocfs2_write_block(osb, bh, si->si_inode); |
152 | if (status < 0) | 219 | if (status < 0) |
153 | mlog_errno(status); | 220 | mlog_errno(status); |
154 | 221 | ||
@@ -165,7 +232,12 @@ static int ocfs2_slot_map_physical_size(struct ocfs2_super *osb, | |||
165 | { | 232 | { |
166 | unsigned long long bytes_needed; | 233 | unsigned long long bytes_needed; |
167 | 234 | ||
168 | bytes_needed = osb->max_slots * sizeof(__le16); | 235 | if (ocfs2_uses_extended_slot_map(osb)) { |
236 | bytes_needed = osb->max_slots * | ||
237 | sizeof(struct ocfs2_extended_slot); | ||
238 | } else { | ||
239 | bytes_needed = osb->max_slots * sizeof(__le16); | ||
240 | } | ||
169 | if (bytes_needed > i_size_read(inode)) { | 241 | if (bytes_needed > i_size_read(inode)) { |
170 | mlog(ML_ERROR, | 242 | mlog(ML_ERROR, |
171 | "Slot map file is too small! (size %llu, needed %llu)\n", | 243 | "Slot map file is too small! (size %llu, needed %llu)\n", |
@@ -279,7 +351,7 @@ int ocfs2_clear_slot(struct ocfs2_super *osb, int slot_num) | |||
279 | ocfs2_invalidate_slot(si, slot_num); | 351 | ocfs2_invalidate_slot(si, slot_num); |
280 | spin_unlock(&osb->osb_lock); | 352 | spin_unlock(&osb->osb_lock); |
281 | 353 | ||
282 | return ocfs2_update_disk_slots(osb, osb->slot_info); | 354 | return ocfs2_update_disk_slot(osb, osb->slot_info, slot_num); |
283 | } | 355 | } |
284 | 356 | ||
285 | static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, | 357 | static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, |
@@ -301,6 +373,16 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, | |||
301 | if (!si->si_blocks) | 373 | if (!si->si_blocks) |
302 | goto bail; | 374 | goto bail; |
303 | 375 | ||
376 | if (si->si_extended) | ||
377 | si->si_slots_per_block = | ||
378 | (osb->sb->s_blocksize / | ||
379 | sizeof(struct ocfs2_extended_slot)); | ||
380 | else | ||
381 | si->si_slots_per_block = osb->sb->s_blocksize / sizeof(__le16); | ||
382 | |||
383 | /* The size checks above should ensure this */ | ||
384 | BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); | ||
385 | |||
304 | mlog(0, "Slot map needs %u buffers for %llu bytes\n", | 386 | mlog(0, "Slot map needs %u buffers for %llu bytes\n", |
305 | si->si_blocks, bytes); | 387 | si->si_blocks, bytes); |
306 | 388 | ||
@@ -352,6 +434,7 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb) | |||
352 | goto bail; | 434 | goto bail; |
353 | } | 435 | } |
354 | 436 | ||
437 | si->si_extended = ocfs2_uses_extended_slot_map(osb); | ||
355 | si->si_num_slots = osb->max_slots; | 438 | si->si_num_slots = osb->max_slots; |
356 | si->si_slots = (struct ocfs2_slot *)((char *)si + | 439 | si->si_slots = (struct ocfs2_slot *)((char *)si + |
357 | sizeof(struct ocfs2_slot_info)); | 440 | sizeof(struct ocfs2_slot_info)); |
@@ -425,7 +508,7 @@ int ocfs2_find_slot(struct ocfs2_super *osb) | |||
425 | 508 | ||
426 | mlog(0, "taking node slot %d\n", osb->slot_num); | 509 | mlog(0, "taking node slot %d\n", osb->slot_num); |
427 | 510 | ||
428 | status = ocfs2_update_disk_slots(osb, si); | 511 | status = ocfs2_update_disk_slot(osb, si, osb->slot_num); |
429 | if (status < 0) | 512 | if (status < 0) |
430 | mlog_errno(status); | 513 | mlog_errno(status); |
431 | 514 | ||
@@ -436,7 +519,7 @@ bail: | |||
436 | 519 | ||
437 | void ocfs2_put_slot(struct ocfs2_super *osb) | 520 | void ocfs2_put_slot(struct ocfs2_super *osb) |
438 | { | 521 | { |
439 | int status; | 522 | int status, slot_num; |
440 | struct ocfs2_slot_info *si = osb->slot_info; | 523 | struct ocfs2_slot_info *si = osb->slot_info; |
441 | 524 | ||
442 | if (!si) | 525 | if (!si) |
@@ -445,11 +528,12 @@ void ocfs2_put_slot(struct ocfs2_super *osb) | |||
445 | spin_lock(&osb->osb_lock); | 528 | spin_lock(&osb->osb_lock); |
446 | ocfs2_update_slot_info(si); | 529 | ocfs2_update_slot_info(si); |
447 | 530 | ||
531 | slot_num = osb->slot_num; | ||
448 | ocfs2_invalidate_slot(si, osb->slot_num); | 532 | ocfs2_invalidate_slot(si, osb->slot_num); |
449 | osb->slot_num = OCFS2_INVALID_SLOT; | 533 | osb->slot_num = OCFS2_INVALID_SLOT; |
450 | spin_unlock(&osb->osb_lock); | 534 | spin_unlock(&osb->osb_lock); |
451 | 535 | ||
452 | status = ocfs2_update_disk_slots(osb, si); | 536 | status = ocfs2_update_disk_slot(osb, si, slot_num); |
453 | if (status < 0) { | 537 | if (status < 0) { |
454 | mlog_errno(status); | 538 | mlog_errno(status); |
455 | goto bail; | 539 | goto bail; |