aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/slot_map.c128
1 files changed, 108 insertions, 20 deletions
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
index 762360d95e93..5bddee110091 100644
--- a/fs/ocfs2/slot_map.c
+++ b/fs/ocfs2/slot_map.c
@@ -44,7 +44,8 @@
44 44
45struct ocfs2_slot_info { 45struct ocfs2_slot_info {
46 struct inode *si_inode; 46 struct inode *si_inode;
47 struct buffer_head *si_bh; 47 unsigned int si_blocks;
48 struct buffer_head **si_bh;
48 unsigned int si_num_slots; 49 unsigned int si_num_slots;
49 unsigned int si_size; 50 unsigned int si_size;
50 s16 si_global_node_nums[OCFS2_MAX_SLOTS]; 51 s16 si_global_node_nums[OCFS2_MAX_SLOTS];
@@ -68,7 +69,7 @@ static void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
68 69
69 /* we don't read the slot block here as ocfs2_super_lock 70 /* we don't read the slot block here as ocfs2_super_lock
70 * should've made sure we have the most recent copy. */ 71 * should've made sure we have the most recent copy. */
71 disk_info = (__le16 *) si->si_bh->b_data; 72 disk_info = (__le16 *) si->si_bh[0]->b_data;
72 73
73 for (i = 0; i < si->si_size; i++) 74 for (i = 0; i < si->si_size; i++)
74 si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]); 75 si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]);
@@ -78,13 +79,23 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb)
78{ 79{
79 int ret; 80 int ret;
80 struct ocfs2_slot_info *si = osb->slot_info; 81 struct ocfs2_slot_info *si = osb->slot_info;
81 struct buffer_head *bh;
82 82
83 if (si == NULL) 83 if (si == NULL)
84 return 0; 84 return 0;
85 85
86 bh = si->si_bh; 86 BUG_ON(si->si_blocks == 0);
87 ret = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0, si->si_inode); 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);
88 if (ret == 0) { 99 if (ret == 0) {
89 spin_lock(&osb->osb_lock); 100 spin_lock(&osb->osb_lock);
90 ocfs2_update_slot_info(si); 101 ocfs2_update_slot_info(si);
@@ -100,20 +111,42 @@ static int ocfs2_update_disk_slots(struct ocfs2_super *osb,
100 struct ocfs2_slot_info *si) 111 struct ocfs2_slot_info *si)
101{ 112{
102 int status, i; 113 int status, i;
103 __le16 *disk_info = (__le16 *) si->si_bh->b_data; 114 __le16 *disk_info = (__le16 *) si->si_bh[0]->b_data;
104 115
105 spin_lock(&osb->osb_lock); 116 spin_lock(&osb->osb_lock);
106 for (i = 0; i < si->si_size; i++) 117 for (i = 0; i < si->si_size; i++)
107 disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]); 118 disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
108 spin_unlock(&osb->osb_lock); 119 spin_unlock(&osb->osb_lock);
109 120
110 status = ocfs2_write_block(osb, si->si_bh, si->si_inode); 121 status = ocfs2_write_block(osb, si->si_bh[0], si->si_inode);
111 if (status < 0) 122 if (status < 0)
112 mlog_errno(status); 123 mlog_errno(status);
113 124
114 return status; 125 return status;
115} 126}
116 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 */
132static 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
117/* try to find global node in the slot info. Returns 150/* try to find global node in the slot info. Returns
118 * OCFS2_INVALID_SLOT if nothing is found. */ 151 * OCFS2_INVALID_SLOT if nothing is found. */
119static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, 152static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
@@ -188,13 +221,22 @@ int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num,
188 221
189static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si) 222static void __ocfs2_free_slot_info(struct ocfs2_slot_info *si)
190{ 223{
224 unsigned int i;
225
191 if (si == NULL) 226 if (si == NULL)
192 return; 227 return;
193 228
194 if (si->si_inode) 229 if (si->si_inode)
195 iput(si->si_inode); 230 iput(si->si_inode);
196 if (si->si_bh) 231 if (si->si_bh) {
197 brelse(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 }
198 240
199 kfree(si); 241 kfree(si);
200} 242}
@@ -225,12 +267,65 @@ int ocfs2_clear_slot(struct ocfs2_super *osb, s16 slot_num)
225 return ocfs2_update_disk_slots(osb, osb->slot_info); 267 return ocfs2_update_disk_slots(osb, osb->slot_info);
226} 268}
227 269
270static 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
321bail:
322 return status;
323}
324
228int ocfs2_init_slot_info(struct ocfs2_super *osb) 325int ocfs2_init_slot_info(struct ocfs2_super *osb)
229{ 326{
230 int status, i; 327 int status, i;
231 u64 blkno;
232 struct inode *inode = NULL; 328 struct inode *inode = NULL;
233 struct buffer_head *bh = NULL;
234 struct ocfs2_slot_info *si; 329 struct ocfs2_slot_info *si;
235 330
236 si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL); 331 si = kzalloc(sizeof(struct ocfs2_slot_info), GFP_KERNEL);
@@ -254,20 +349,13 @@ int ocfs2_init_slot_info(struct ocfs2_super *osb)
254 goto bail; 349 goto bail;
255 } 350 }
256 351
257 status = ocfs2_extent_map_get_blocks(inode, 0ULL, &blkno, NULL, NULL); 352 si->si_inode = inode;
258 if (status < 0) { 353 status = ocfs2_map_slot_buffers(osb, si);
259 mlog_errno(status);
260 goto bail;
261 }
262
263 status = ocfs2_read_block(osb, blkno, &bh, 0, inode);
264 if (status < 0) { 354 if (status < 0) {
265 mlog_errno(status); 355 mlog_errno(status);
266 goto bail; 356 goto bail;
267 } 357 }
268 358
269 si->si_inode = inode;
270 si->si_bh = bh;
271 osb->slot_info = (struct ocfs2_slot_info *)si; 359 osb->slot_info = (struct ocfs2_slot_info *)si;
272bail: 360bail:
273 if (status < 0 && si) 361 if (status < 0 && si)