diff options
Diffstat (limited to 'fs/ocfs2/uptodate.c')
-rw-r--r-- | fs/ocfs2/uptodate.c | 265 |
1 files changed, 160 insertions, 105 deletions
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index 187b99ff0368..b6284f235d2f 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c | |||
@@ -75,15 +75,77 @@ struct ocfs2_meta_cache_item { | |||
75 | 75 | ||
76 | static struct kmem_cache *ocfs2_uptodate_cachep = NULL; | 76 | static struct kmem_cache *ocfs2_uptodate_cachep = NULL; |
77 | 77 | ||
78 | void ocfs2_metadata_cache_init(struct inode *inode) | 78 | u64 ocfs2_metadata_cache_owner(struct ocfs2_caching_info *ci) |
79 | { | 79 | { |
80 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 80 | BUG_ON(!ci || !ci->ci_ops); |
81 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
82 | 81 | ||
83 | oi->ip_flags |= OCFS2_INODE_CACHE_INLINE; | 82 | return ci->ci_ops->co_owner(ci); |
83 | } | ||
84 | |||
85 | struct super_block *ocfs2_metadata_cache_get_super(struct ocfs2_caching_info *ci) | ||
86 | { | ||
87 | BUG_ON(!ci || !ci->ci_ops); | ||
88 | |||
89 | return ci->ci_ops->co_get_super(ci); | ||
90 | } | ||
91 | |||
92 | static void ocfs2_metadata_cache_lock(struct ocfs2_caching_info *ci) | ||
93 | { | ||
94 | BUG_ON(!ci || !ci->ci_ops); | ||
95 | |||
96 | ci->ci_ops->co_cache_lock(ci); | ||
97 | } | ||
98 | |||
99 | static void ocfs2_metadata_cache_unlock(struct ocfs2_caching_info *ci) | ||
100 | { | ||
101 | BUG_ON(!ci || !ci->ci_ops); | ||
102 | |||
103 | ci->ci_ops->co_cache_unlock(ci); | ||
104 | } | ||
105 | |||
106 | void ocfs2_metadata_cache_io_lock(struct ocfs2_caching_info *ci) | ||
107 | { | ||
108 | BUG_ON(!ci || !ci->ci_ops); | ||
109 | |||
110 | ci->ci_ops->co_io_lock(ci); | ||
111 | } | ||
112 | |||
113 | void ocfs2_metadata_cache_io_unlock(struct ocfs2_caching_info *ci) | ||
114 | { | ||
115 | BUG_ON(!ci || !ci->ci_ops); | ||
116 | |||
117 | ci->ci_ops->co_io_unlock(ci); | ||
118 | } | ||
119 | |||
120 | |||
121 | static void ocfs2_metadata_cache_reset(struct ocfs2_caching_info *ci, | ||
122 | int clear) | ||
123 | { | ||
124 | ci->ci_flags |= OCFS2_CACHE_FL_INLINE; | ||
84 | ci->ci_num_cached = 0; | 125 | ci->ci_num_cached = 0; |
126 | |||
127 | if (clear) { | ||
128 | ci->ci_created_trans = 0; | ||
129 | ci->ci_last_trans = 0; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void ocfs2_metadata_cache_init(struct ocfs2_caching_info *ci, | ||
134 | const struct ocfs2_caching_operations *ops) | ||
135 | { | ||
136 | BUG_ON(!ops); | ||
137 | |||
138 | ci->ci_ops = ops; | ||
139 | ocfs2_metadata_cache_reset(ci, 1); | ||
85 | } | 140 | } |
86 | 141 | ||
142 | void ocfs2_metadata_cache_exit(struct ocfs2_caching_info *ci) | ||
143 | { | ||
144 | ocfs2_metadata_cache_purge(ci); | ||
145 | ocfs2_metadata_cache_reset(ci, 1); | ||
146 | } | ||
147 | |||
148 | |||
87 | /* No lock taken here as 'root' is not expected to be visible to other | 149 | /* No lock taken here as 'root' is not expected to be visible to other |
88 | * processes. */ | 150 | * processes. */ |
89 | static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) | 151 | static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) |
@@ -112,19 +174,20 @@ static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) | |||
112 | * This function is a few more lines longer than necessary due to some | 174 | * This function is a few more lines longer than necessary due to some |
113 | * accounting done here, but I think it's worth tracking down those | 175 | * accounting done here, but I think it's worth tracking down those |
114 | * bugs sooner -- Mark */ | 176 | * bugs sooner -- Mark */ |
115 | void ocfs2_metadata_cache_purge(struct inode *inode) | 177 | void ocfs2_metadata_cache_purge(struct ocfs2_caching_info *ci) |
116 | { | 178 | { |
117 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
118 | unsigned int tree, to_purge, purged; | 179 | unsigned int tree, to_purge, purged; |
119 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
120 | struct rb_root root = RB_ROOT; | 180 | struct rb_root root = RB_ROOT; |
121 | 181 | ||
122 | spin_lock(&oi->ip_lock); | 182 | BUG_ON(!ci || !ci->ci_ops); |
123 | tree = !(oi->ip_flags & OCFS2_INODE_CACHE_INLINE); | 183 | |
184 | ocfs2_metadata_cache_lock(ci); | ||
185 | tree = !(ci->ci_flags & OCFS2_CACHE_FL_INLINE); | ||
124 | to_purge = ci->ci_num_cached; | 186 | to_purge = ci->ci_num_cached; |
125 | 187 | ||
126 | mlog(0, "Purge %u %s items from Inode %llu\n", to_purge, | 188 | mlog(0, "Purge %u %s items from Owner %llu\n", to_purge, |
127 | tree ? "array" : "tree", (unsigned long long)oi->ip_blkno); | 189 | tree ? "array" : "tree", |
190 | (unsigned long long)ocfs2_metadata_cache_owner(ci)); | ||
128 | 191 | ||
129 | /* If we're a tree, save off the root so that we can safely | 192 | /* If we're a tree, save off the root so that we can safely |
130 | * initialize the cache. We do the work to free tree members | 193 | * initialize the cache. We do the work to free tree members |
@@ -132,16 +195,17 @@ void ocfs2_metadata_cache_purge(struct inode *inode) | |||
132 | if (tree) | 195 | if (tree) |
133 | root = ci->ci_cache.ci_tree; | 196 | root = ci->ci_cache.ci_tree; |
134 | 197 | ||
135 | ocfs2_metadata_cache_init(inode); | 198 | ocfs2_metadata_cache_reset(ci, 0); |
136 | spin_unlock(&oi->ip_lock); | 199 | ocfs2_metadata_cache_unlock(ci); |
137 | 200 | ||
138 | purged = ocfs2_purge_copied_metadata_tree(&root); | 201 | purged = ocfs2_purge_copied_metadata_tree(&root); |
139 | /* If possible, track the number wiped so that we can more | 202 | /* If possible, track the number wiped so that we can more |
140 | * easily detect counting errors. Unfortunately, this is only | 203 | * easily detect counting errors. Unfortunately, this is only |
141 | * meaningful for trees. */ | 204 | * meaningful for trees. */ |
142 | if (tree && purged != to_purge) | 205 | if (tree && purged != to_purge) |
143 | mlog(ML_ERROR, "Inode %llu, count = %u, purged = %u\n", | 206 | mlog(ML_ERROR, "Owner %llu, count = %u, purged = %u\n", |
144 | (unsigned long long)oi->ip_blkno, to_purge, purged); | 207 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
208 | to_purge, purged); | ||
145 | } | 209 | } |
146 | 210 | ||
147 | /* Returns the index in the cache array, -1 if not found. | 211 | /* Returns the index in the cache array, -1 if not found. |
@@ -182,27 +246,25 @@ ocfs2_search_cache_tree(struct ocfs2_caching_info *ci, | |||
182 | return NULL; | 246 | return NULL; |
183 | } | 247 | } |
184 | 248 | ||
185 | static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | 249 | static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, |
186 | struct buffer_head *bh) | 250 | struct buffer_head *bh) |
187 | { | 251 | { |
188 | int index = -1; | 252 | int index = -1; |
189 | struct ocfs2_meta_cache_item *item = NULL; | 253 | struct ocfs2_meta_cache_item *item = NULL; |
190 | 254 | ||
191 | spin_lock(&oi->ip_lock); | 255 | ocfs2_metadata_cache_lock(ci); |
192 | 256 | ||
193 | mlog(0, "Inode %llu, query block %llu (inline = %u)\n", | 257 | mlog(0, "Owner %llu, query block %llu (inline = %u)\n", |
194 | (unsigned long long)oi->ip_blkno, | 258 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
195 | (unsigned long long) bh->b_blocknr, | 259 | (unsigned long long) bh->b_blocknr, |
196 | !!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE)); | 260 | !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); |
197 | 261 | ||
198 | if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) | 262 | if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) |
199 | index = ocfs2_search_cache_array(&oi->ip_metadata_cache, | 263 | index = ocfs2_search_cache_array(ci, bh->b_blocknr); |
200 | bh->b_blocknr); | ||
201 | else | 264 | else |
202 | item = ocfs2_search_cache_tree(&oi->ip_metadata_cache, | 265 | item = ocfs2_search_cache_tree(ci, bh->b_blocknr); |
203 | bh->b_blocknr); | ||
204 | 266 | ||
205 | spin_unlock(&oi->ip_lock); | 267 | ocfs2_metadata_cache_unlock(ci); |
206 | 268 | ||
207 | mlog(0, "index = %d, item = %p\n", index, item); | 269 | mlog(0, "index = %d, item = %p\n", index, item); |
208 | 270 | ||
@@ -214,7 +276,7 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | |||
214 | * | 276 | * |
215 | * This can be called under lock_buffer() | 277 | * This can be called under lock_buffer() |
216 | */ | 278 | */ |
217 | int ocfs2_buffer_uptodate(struct inode *inode, | 279 | int ocfs2_buffer_uptodate(struct ocfs2_caching_info *ci, |
218 | struct buffer_head *bh) | 280 | struct buffer_head *bh) |
219 | { | 281 | { |
220 | /* Doesn't matter if the bh is in our cache or not -- if it's | 282 | /* Doesn't matter if the bh is in our cache or not -- if it's |
@@ -230,24 +292,24 @@ int ocfs2_buffer_uptodate(struct inode *inode, | |||
230 | 292 | ||
231 | /* Ok, locally the buffer is marked as up to date, now search | 293 | /* Ok, locally the buffer is marked as up to date, now search |
232 | * our cache to see if we can trust that. */ | 294 | * our cache to see if we can trust that. */ |
233 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); | 295 | return ocfs2_buffer_cached(ci, bh); |
234 | } | 296 | } |
235 | 297 | ||
236 | /* | 298 | /* |
237 | * Determine whether a buffer is currently out on a read-ahead request. | 299 | * Determine whether a buffer is currently out on a read-ahead request. |
238 | * ip_io_sem should be held to serialize submitters with the logic here. | 300 | * ci_io_sem should be held to serialize submitters with the logic here. |
239 | */ | 301 | */ |
240 | int ocfs2_buffer_read_ahead(struct inode *inode, | 302 | int ocfs2_buffer_read_ahead(struct ocfs2_caching_info *ci, |
241 | struct buffer_head *bh) | 303 | struct buffer_head *bh) |
242 | { | 304 | { |
243 | return buffer_locked(bh) && ocfs2_buffer_cached(OCFS2_I(inode), bh); | 305 | return buffer_locked(bh) && ocfs2_buffer_cached(ci, bh); |
244 | } | 306 | } |
245 | 307 | ||
246 | /* Requires ip_lock */ | 308 | /* Requires ip_lock */ |
247 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, | 309 | static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, |
248 | sector_t block) | 310 | sector_t block) |
249 | { | 311 | { |
250 | BUG_ON(ci->ci_num_cached >= OCFS2_INODE_MAX_CACHE_ARRAY); | 312 | BUG_ON(ci->ci_num_cached >= OCFS2_CACHE_INFO_MAX_ARRAY); |
251 | 313 | ||
252 | mlog(0, "block %llu takes position %u\n", (unsigned long long) block, | 314 | mlog(0, "block %llu takes position %u\n", (unsigned long long) block, |
253 | ci->ci_num_cached); | 315 | ci->ci_num_cached); |
@@ -292,66 +354,64 @@ static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci, | |||
292 | ci->ci_num_cached++; | 354 | ci->ci_num_cached++; |
293 | } | 355 | } |
294 | 356 | ||
295 | static inline int ocfs2_insert_can_use_array(struct ocfs2_inode_info *oi, | 357 | /* co_cache_lock() must be held */ |
296 | struct ocfs2_caching_info *ci) | 358 | static inline int ocfs2_insert_can_use_array(struct ocfs2_caching_info *ci) |
297 | { | 359 | { |
298 | assert_spin_locked(&oi->ip_lock); | 360 | return (ci->ci_flags & OCFS2_CACHE_FL_INLINE) && |
299 | 361 | (ci->ci_num_cached < OCFS2_CACHE_INFO_MAX_ARRAY); | |
300 | return (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) && | ||
301 | (ci->ci_num_cached < OCFS2_INODE_MAX_CACHE_ARRAY); | ||
302 | } | 362 | } |
303 | 363 | ||
304 | /* tree should be exactly OCFS2_INODE_MAX_CACHE_ARRAY wide. NULL the | 364 | /* tree should be exactly OCFS2_CACHE_INFO_MAX_ARRAY wide. NULL the |
305 | * pointers in tree after we use them - this allows caller to detect | 365 | * pointers in tree after we use them - this allows caller to detect |
306 | * when to free in case of error. */ | 366 | * when to free in case of error. |
307 | static void ocfs2_expand_cache(struct ocfs2_inode_info *oi, | 367 | * |
368 | * The co_cache_lock() must be held. */ | ||
369 | static void ocfs2_expand_cache(struct ocfs2_caching_info *ci, | ||
308 | struct ocfs2_meta_cache_item **tree) | 370 | struct ocfs2_meta_cache_item **tree) |
309 | { | 371 | { |
310 | int i; | 372 | int i; |
311 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
312 | 373 | ||
313 | mlog_bug_on_msg(ci->ci_num_cached != OCFS2_INODE_MAX_CACHE_ARRAY, | 374 | mlog_bug_on_msg(ci->ci_num_cached != OCFS2_CACHE_INFO_MAX_ARRAY, |
314 | "Inode %llu, num cached = %u, should be %u\n", | 375 | "Owner %llu, num cached = %u, should be %u\n", |
315 | (unsigned long long)oi->ip_blkno, ci->ci_num_cached, | 376 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
316 | OCFS2_INODE_MAX_CACHE_ARRAY); | 377 | ci->ci_num_cached, OCFS2_CACHE_INFO_MAX_ARRAY); |
317 | mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE), | 378 | mlog_bug_on_msg(!(ci->ci_flags & OCFS2_CACHE_FL_INLINE), |
318 | "Inode %llu not marked as inline anymore!\n", | 379 | "Owner %llu not marked as inline anymore!\n", |
319 | (unsigned long long)oi->ip_blkno); | 380 | (unsigned long long)ocfs2_metadata_cache_owner(ci)); |
320 | assert_spin_locked(&oi->ip_lock); | ||
321 | 381 | ||
322 | /* Be careful to initialize the tree members *first* because | 382 | /* Be careful to initialize the tree members *first* because |
323 | * once the ci_tree is used, the array is junk... */ | 383 | * once the ci_tree is used, the array is junk... */ |
324 | for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) | 384 | for (i = 0; i < OCFS2_CACHE_INFO_MAX_ARRAY; i++) |
325 | tree[i]->c_block = ci->ci_cache.ci_array[i]; | 385 | tree[i]->c_block = ci->ci_cache.ci_array[i]; |
326 | 386 | ||
327 | oi->ip_flags &= ~OCFS2_INODE_CACHE_INLINE; | 387 | ci->ci_flags &= ~OCFS2_CACHE_FL_INLINE; |
328 | ci->ci_cache.ci_tree = RB_ROOT; | 388 | ci->ci_cache.ci_tree = RB_ROOT; |
329 | /* this will be set again by __ocfs2_insert_cache_tree */ | 389 | /* this will be set again by __ocfs2_insert_cache_tree */ |
330 | ci->ci_num_cached = 0; | 390 | ci->ci_num_cached = 0; |
331 | 391 | ||
332 | for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) { | 392 | for (i = 0; i < OCFS2_CACHE_INFO_MAX_ARRAY; i++) { |
333 | __ocfs2_insert_cache_tree(ci, tree[i]); | 393 | __ocfs2_insert_cache_tree(ci, tree[i]); |
334 | tree[i] = NULL; | 394 | tree[i] = NULL; |
335 | } | 395 | } |
336 | 396 | ||
337 | mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n", | 397 | mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n", |
338 | (unsigned long long)oi->ip_blkno, oi->ip_flags, ci->ci_num_cached); | 398 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
399 | ci->ci_flags, ci->ci_num_cached); | ||
339 | } | 400 | } |
340 | 401 | ||
341 | /* Slow path function - memory allocation is necessary. See the | 402 | /* Slow path function - memory allocation is necessary. See the |
342 | * comment above ocfs2_set_buffer_uptodate for more information. */ | 403 | * comment above ocfs2_set_buffer_uptodate for more information. */ |
343 | static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | 404 | static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, |
344 | sector_t block, | 405 | sector_t block, |
345 | int expand_tree) | 406 | int expand_tree) |
346 | { | 407 | { |
347 | int i; | 408 | int i; |
348 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
349 | struct ocfs2_meta_cache_item *new = NULL; | 409 | struct ocfs2_meta_cache_item *new = NULL; |
350 | struct ocfs2_meta_cache_item *tree[OCFS2_INODE_MAX_CACHE_ARRAY] = | 410 | struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] = |
351 | { NULL, }; | 411 | { NULL, }; |
352 | 412 | ||
353 | mlog(0, "Inode %llu, block %llu, expand = %d\n", | 413 | mlog(0, "Owner %llu, block %llu, expand = %d\n", |
354 | (unsigned long long)oi->ip_blkno, | 414 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
355 | (unsigned long long)block, expand_tree); | 415 | (unsigned long long)block, expand_tree); |
356 | 416 | ||
357 | new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS); | 417 | new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS); |
@@ -364,7 +424,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | |||
364 | if (expand_tree) { | 424 | if (expand_tree) { |
365 | /* Do *not* allocate an array here - the removal code | 425 | /* Do *not* allocate an array here - the removal code |
366 | * has no way of tracking that. */ | 426 | * has no way of tracking that. */ |
367 | for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) { | 427 | for (i = 0; i < OCFS2_CACHE_INFO_MAX_ARRAY; i++) { |
368 | tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep, | 428 | tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep, |
369 | GFP_NOFS); | 429 | GFP_NOFS); |
370 | if (!tree[i]) { | 430 | if (!tree[i]) { |
@@ -376,21 +436,21 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | |||
376 | } | 436 | } |
377 | } | 437 | } |
378 | 438 | ||
379 | spin_lock(&oi->ip_lock); | 439 | ocfs2_metadata_cache_lock(ci); |
380 | if (ocfs2_insert_can_use_array(oi, ci)) { | 440 | if (ocfs2_insert_can_use_array(ci)) { |
381 | mlog(0, "Someone cleared the tree underneath us\n"); | 441 | mlog(0, "Someone cleared the tree underneath us\n"); |
382 | /* Ok, items were removed from the cache in between | 442 | /* Ok, items were removed from the cache in between |
383 | * locks. Detect this and revert back to the fast path */ | 443 | * locks. Detect this and revert back to the fast path */ |
384 | ocfs2_append_cache_array(ci, block); | 444 | ocfs2_append_cache_array(ci, block); |
385 | spin_unlock(&oi->ip_lock); | 445 | ocfs2_metadata_cache_unlock(ci); |
386 | goto out_free; | 446 | goto out_free; |
387 | } | 447 | } |
388 | 448 | ||
389 | if (expand_tree) | 449 | if (expand_tree) |
390 | ocfs2_expand_cache(oi, tree); | 450 | ocfs2_expand_cache(ci, tree); |
391 | 451 | ||
392 | __ocfs2_insert_cache_tree(ci, new); | 452 | __ocfs2_insert_cache_tree(ci, new); |
393 | spin_unlock(&oi->ip_lock); | 453 | ocfs2_metadata_cache_unlock(ci); |
394 | 454 | ||
395 | new = NULL; | 455 | new = NULL; |
396 | out_free: | 456 | out_free: |
@@ -400,14 +460,14 @@ out_free: | |||
400 | /* If these were used, then ocfs2_expand_cache re-set them to | 460 | /* If these were used, then ocfs2_expand_cache re-set them to |
401 | * NULL for us. */ | 461 | * NULL for us. */ |
402 | if (tree[0]) { | 462 | if (tree[0]) { |
403 | for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) | 463 | for (i = 0; i < OCFS2_CACHE_INFO_MAX_ARRAY; i++) |
404 | if (tree[i]) | 464 | if (tree[i]) |
405 | kmem_cache_free(ocfs2_uptodate_cachep, | 465 | kmem_cache_free(ocfs2_uptodate_cachep, |
406 | tree[i]); | 466 | tree[i]); |
407 | } | 467 | } |
408 | } | 468 | } |
409 | 469 | ||
410 | /* Item insertion is guarded by ip_io_mutex, so the insertion path takes | 470 | /* Item insertion is guarded by co_io_lock(), so the insertion path takes |
411 | * advantage of this by not rechecking for a duplicate insert during | 471 | * advantage of this by not rechecking for a duplicate insert during |
412 | * the slow case. Additionally, if the cache needs to be bumped up to | 472 | * the slow case. Additionally, if the cache needs to be bumped up to |
413 | * a tree, the code will not recheck after acquiring the lock -- | 473 | * a tree, the code will not recheck after acquiring the lock -- |
@@ -425,59 +485,55 @@ out_free: | |||
425 | * Readahead buffers can be passed in here before the I/O request is | 485 | * Readahead buffers can be passed in here before the I/O request is |
426 | * completed. | 486 | * completed. |
427 | */ | 487 | */ |
428 | void ocfs2_set_buffer_uptodate(struct inode *inode, | 488 | void ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, |
429 | struct buffer_head *bh) | 489 | struct buffer_head *bh) |
430 | { | 490 | { |
431 | int expand; | 491 | int expand; |
432 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
433 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
434 | 492 | ||
435 | /* The block may very well exist in our cache already, so avoid | 493 | /* The block may very well exist in our cache already, so avoid |
436 | * doing any more work in that case. */ | 494 | * doing any more work in that case. */ |
437 | if (ocfs2_buffer_cached(oi, bh)) | 495 | if (ocfs2_buffer_cached(ci, bh)) |
438 | return; | 496 | return; |
439 | 497 | ||
440 | mlog(0, "Inode %llu, inserting block %llu\n", | 498 | mlog(0, "Owner %llu, inserting block %llu\n", |
441 | (unsigned long long)oi->ip_blkno, | 499 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
442 | (unsigned long long)bh->b_blocknr); | 500 | (unsigned long long)bh->b_blocknr); |
443 | 501 | ||
444 | /* No need to recheck under spinlock - insertion is guarded by | 502 | /* No need to recheck under spinlock - insertion is guarded by |
445 | * ip_io_mutex */ | 503 | * co_io_lock() */ |
446 | spin_lock(&oi->ip_lock); | 504 | ocfs2_metadata_cache_lock(ci); |
447 | if (ocfs2_insert_can_use_array(oi, ci)) { | 505 | if (ocfs2_insert_can_use_array(ci)) { |
448 | /* Fast case - it's an array and there's a free | 506 | /* Fast case - it's an array and there's a free |
449 | * spot. */ | 507 | * spot. */ |
450 | ocfs2_append_cache_array(ci, bh->b_blocknr); | 508 | ocfs2_append_cache_array(ci, bh->b_blocknr); |
451 | spin_unlock(&oi->ip_lock); | 509 | ocfs2_metadata_cache_unlock(ci); |
452 | return; | 510 | return; |
453 | } | 511 | } |
454 | 512 | ||
455 | expand = 0; | 513 | expand = 0; |
456 | if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) { | 514 | if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) { |
457 | /* We need to bump things up to a tree. */ | 515 | /* We need to bump things up to a tree. */ |
458 | expand = 1; | 516 | expand = 1; |
459 | } | 517 | } |
460 | spin_unlock(&oi->ip_lock); | 518 | ocfs2_metadata_cache_unlock(ci); |
461 | 519 | ||
462 | __ocfs2_set_buffer_uptodate(oi, bh->b_blocknr, expand); | 520 | __ocfs2_set_buffer_uptodate(ci, bh->b_blocknr, expand); |
463 | } | 521 | } |
464 | 522 | ||
465 | /* Called against a newly allocated buffer. Most likely nobody should | 523 | /* Called against a newly allocated buffer. Most likely nobody should |
466 | * be able to read this sort of metadata while it's still being | 524 | * be able to read this sort of metadata while it's still being |
467 | * allocated, but this is careful to take ip_io_mutex anyway. */ | 525 | * allocated, but this is careful to take co_io_lock() anyway. */ |
468 | void ocfs2_set_new_buffer_uptodate(struct inode *inode, | 526 | void ocfs2_set_new_buffer_uptodate(struct ocfs2_caching_info *ci, |
469 | struct buffer_head *bh) | 527 | struct buffer_head *bh) |
470 | { | 528 | { |
471 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
472 | |||
473 | /* This should definitely *not* exist in our cache */ | 529 | /* This should definitely *not* exist in our cache */ |
474 | BUG_ON(ocfs2_buffer_cached(oi, bh)); | 530 | BUG_ON(ocfs2_buffer_cached(ci, bh)); |
475 | 531 | ||
476 | set_buffer_uptodate(bh); | 532 | set_buffer_uptodate(bh); |
477 | 533 | ||
478 | mutex_lock(&oi->ip_io_mutex); | 534 | ocfs2_metadata_cache_io_lock(ci); |
479 | ocfs2_set_buffer_uptodate(inode, bh); | 535 | ocfs2_set_buffer_uptodate(ci, bh); |
480 | mutex_unlock(&oi->ip_io_mutex); | 536 | ocfs2_metadata_cache_io_unlock(ci); |
481 | } | 537 | } |
482 | 538 | ||
483 | /* Requires ip_lock. */ | 539 | /* Requires ip_lock. */ |
@@ -487,7 +543,7 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci, | |||
487 | sector_t *array = ci->ci_cache.ci_array; | 543 | sector_t *array = ci->ci_cache.ci_array; |
488 | int bytes; | 544 | int bytes; |
489 | 545 | ||
490 | BUG_ON(index < 0 || index >= OCFS2_INODE_MAX_CACHE_ARRAY); | 546 | BUG_ON(index < 0 || index >= OCFS2_CACHE_INFO_MAX_ARRAY); |
491 | BUG_ON(index >= ci->ci_num_cached); | 547 | BUG_ON(index >= ci->ci_num_cached); |
492 | BUG_ON(!ci->ci_num_cached); | 548 | BUG_ON(!ci->ci_num_cached); |
493 | 549 | ||
@@ -515,21 +571,19 @@ static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci, | |||
515 | ci->ci_num_cached--; | 571 | ci->ci_num_cached--; |
516 | } | 572 | } |
517 | 573 | ||
518 | static void ocfs2_remove_block_from_cache(struct inode *inode, | 574 | static void ocfs2_remove_block_from_cache(struct ocfs2_caching_info *ci, |
519 | sector_t block) | 575 | sector_t block) |
520 | { | 576 | { |
521 | int index; | 577 | int index; |
522 | struct ocfs2_meta_cache_item *item = NULL; | 578 | struct ocfs2_meta_cache_item *item = NULL; |
523 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
524 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
525 | 579 | ||
526 | spin_lock(&oi->ip_lock); | 580 | ocfs2_metadata_cache_lock(ci); |
527 | mlog(0, "Inode %llu, remove %llu, items = %u, array = %u\n", | 581 | mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n", |
528 | (unsigned long long)oi->ip_blkno, | 582 | (unsigned long long)ocfs2_metadata_cache_owner(ci), |
529 | (unsigned long long) block, ci->ci_num_cached, | 583 | (unsigned long long) block, ci->ci_num_cached, |
530 | oi->ip_flags & OCFS2_INODE_CACHE_INLINE); | 584 | ci->ci_flags & OCFS2_CACHE_FL_INLINE); |
531 | 585 | ||
532 | if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) { | 586 | if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) { |
533 | index = ocfs2_search_cache_array(ci, block); | 587 | index = ocfs2_search_cache_array(ci, block); |
534 | if (index != -1) | 588 | if (index != -1) |
535 | ocfs2_remove_metadata_array(ci, index); | 589 | ocfs2_remove_metadata_array(ci, index); |
@@ -538,7 +592,7 @@ static void ocfs2_remove_block_from_cache(struct inode *inode, | |||
538 | if (item) | 592 | if (item) |
539 | ocfs2_remove_metadata_tree(ci, item); | 593 | ocfs2_remove_metadata_tree(ci, item); |
540 | } | 594 | } |
541 | spin_unlock(&oi->ip_lock); | 595 | ocfs2_metadata_cache_unlock(ci); |
542 | 596 | ||
543 | if (item) | 597 | if (item) |
544 | kmem_cache_free(ocfs2_uptodate_cachep, item); | 598 | kmem_cache_free(ocfs2_uptodate_cachep, item); |
@@ -549,23 +603,24 @@ static void ocfs2_remove_block_from_cache(struct inode *inode, | |||
549 | * bother reverting things to an inlined array in the case of a remove | 603 | * bother reverting things to an inlined array in the case of a remove |
550 | * which moves us back under the limit. | 604 | * which moves us back under the limit. |
551 | */ | 605 | */ |
552 | void ocfs2_remove_from_cache(struct inode *inode, | 606 | void ocfs2_remove_from_cache(struct ocfs2_caching_info *ci, |
553 | struct buffer_head *bh) | 607 | struct buffer_head *bh) |
554 | { | 608 | { |
555 | sector_t block = bh->b_blocknr; | 609 | sector_t block = bh->b_blocknr; |
556 | 610 | ||
557 | ocfs2_remove_block_from_cache(inode, block); | 611 | ocfs2_remove_block_from_cache(ci, block); |
558 | } | 612 | } |
559 | 613 | ||
560 | /* Called when we remove xattr clusters from an inode. */ | 614 | /* Called when we remove xattr clusters from an inode. */ |
561 | void ocfs2_remove_xattr_clusters_from_cache(struct inode *inode, | 615 | void ocfs2_remove_xattr_clusters_from_cache(struct ocfs2_caching_info *ci, |
562 | sector_t block, | 616 | sector_t block, |
563 | u32 c_len) | 617 | u32 c_len) |
564 | { | 618 | { |
565 | unsigned int i, b_len = ocfs2_clusters_to_blocks(inode->i_sb, 1) * c_len; | 619 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); |
620 | unsigned int i, b_len = ocfs2_clusters_to_blocks(sb, 1) * c_len; | ||
566 | 621 | ||
567 | for (i = 0; i < b_len; i++, block++) | 622 | for (i = 0; i < b_len; i++, block++) |
568 | ocfs2_remove_block_from_cache(inode, block); | 623 | ocfs2_remove_block_from_cache(ci, block); |
569 | } | 624 | } |
570 | 625 | ||
571 | int __init init_ocfs2_uptodate_cache(void) | 626 | int __init init_ocfs2_uptodate_cache(void) |
@@ -577,7 +632,7 @@ int __init init_ocfs2_uptodate_cache(void) | |||
577 | return -ENOMEM; | 632 | return -ENOMEM; |
578 | 633 | ||
579 | mlog(0, "%u inlined cache items per inode.\n", | 634 | mlog(0, "%u inlined cache items per inode.\n", |
580 | OCFS2_INODE_MAX_CACHE_ARRAY); | 635 | OCFS2_CACHE_INFO_MAX_ARRAY); |
581 | 636 | ||
582 | return 0; | 637 | return 0; |
583 | } | 638 | } |