aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-02-01 15:06:54 -0500
committerMark Fasheh <mfasheh@suse.com>2008-04-18 11:56:03 -0400
commit386a2ef8576e966076c293f6496b9e3d7e3d9035 (patch)
tree08b6cae47060497359a6ab78134a1bf8e38012cc /fs
parentfb86b1f07120b66769a39c445da5c4300069dd44 (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')
-rw-r--r--fs/ocfs2/ocfs2.h7
-rw-r--r--fs/ocfs2/ocfs2_fs.h31
-rw-r--r--fs/ocfs2/slot_map.c110
3 files changed, 133 insertions, 15 deletions
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 95f783dbe8b2..f78e9ed53249 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -374,6 +374,13 @@ static inline int ocfs2_mount_local(struct ocfs2_super *osb)
374 return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT); 374 return (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT);
375} 375}
376 376
377static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super *osb)
378{
379 return (osb->s_feature_incompat &
380 OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP);
381}
382
383
377#define OCFS2_IS_VALID_DINODE(ptr) \ 384#define OCFS2_IS_VALID_DINODE(ptr) \
378 (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE)) 385 (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
379 386
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 3299116b8021..c49502329ab0 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -88,7 +88,8 @@
88#define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB 88#define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB
89#define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \ 89#define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
90 | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \ 90 | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
91 | OCFS2_FEATURE_INCOMPAT_INLINE_DATA) 91 | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
92 | OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP)
92#define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 93#define OCFS2_FEATURE_RO_COMPAT_SUPP OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
93 94
94/* 95/*
@@ -125,6 +126,10 @@
125/* Support for data packed into inode blocks */ 126/* Support for data packed into inode blocks */
126#define OCFS2_FEATURE_INCOMPAT_INLINE_DATA 0x0040 127#define OCFS2_FEATURE_INCOMPAT_INLINE_DATA 0x0040
127 128
129/* Support for the extended slot map */
130#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP 0x100
131
132
128/* 133/*
129 * backup superblock flag is used to indicate that this volume 134 * backup superblock flag is used to indicate that this volume
130 * has backup superblocks. 135 * has backup superblocks.
@@ -476,7 +481,8 @@ struct ocfs2_extent_block
476 481
477/* 482/*
478 * On disk slot map for OCFS2. This defines the contents of the "slot_map" 483 * On disk slot map for OCFS2. This defines the contents of the "slot_map"
479 * system file. 484 * system file. A slot is valid if it contains a node number >= 0. The
485 * value -1 (0xFFFF) is OCFS2_INVALID_SLOT. This marks a slot empty.
480 */ 486 */
481struct ocfs2_slot_map { 487struct ocfs2_slot_map {
482/*00*/ __le16 sm_slots[0]; 488/*00*/ __le16 sm_slots[0];
@@ -486,6 +492,27 @@ struct ocfs2_slot_map {
486 */ 492 */
487}; 493};
488 494
495struct ocfs2_extended_slot {
496/*00*/ __u8 es_valid;
497 __u8 es_reserved1[3];
498 __le32 es_node_num;
499/*10*/
500};
501
502/*
503 * The extended slot map, used when OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP
504 * is set. It separates out the valid marker from the node number, and
505 * has room to grow. Unlike the old slot map, this format is defined by
506 * i_size.
507 */
508struct ocfs2_slot_map_extended {
509/*00*/ struct ocfs2_extended_slot se_slots[0];
510/*
511 * Actual size is i_size of the slot_map system file. It should
512 * match s_max_slots * sizeof(struct ocfs2_extended_slot)
513 */
514};
515
489/* 516/*
490 * On disk superblock for OCFS2 517 * On disk superblock for OCFS2
491 * Note that it is contained inside an ocfs2_dinode, so all offsets 518 * Note that it is contained inside an ocfs2_dinode, so all offsets
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
51struct ocfs2_slot_info { 51struct 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 */
84static 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 */
85static void ocfs2_update_slot_info(struct ocfs2_slot_info *si) 109static 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
124static 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
102int ocfs2_refresh_slot_info(struct ocfs2_super *osb) 136int 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. */
134static int ocfs2_update_disk_slots(struct ocfs2_super *osb, 168static 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
186static 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
204static 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
285static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, 357static 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
437void ocfs2_put_slot(struct ocfs2_super *osb) 520void 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;