diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-02-10 23:00:41 -0500 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-04 19:07:48 -0400 |
commit | 8cb471e8f82506937fe5e2e9fb0bf90f6b1f1170 (patch) | |
tree | e275a8f5db101a9990ba44931cfd116123112b11 /fs/ocfs2/uptodate.c | |
parent | 6e5a3d7538ad4e46a976862f593faf65750e37cc (diff) |
ocfs2: Take the inode out of the metadata read/write paths.
We are really passing the inode into the ocfs2_read/write_blocks()
functions to get at the metadata cache. This commit passes the cache
directly into the metadata block functions, divorcing them from the
inode.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/uptodate.c')
-rw-r--r-- | fs/ocfs2/uptodate.c | 83 |
1 files changed, 38 insertions, 45 deletions
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index 226d0429fd7f..1c829e451019 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c | |||
@@ -75,13 +75,20 @@ 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 | static u64 ocfs2_metadata_cache_owner(struct ocfs2_caching_info *ci) | 78 | u64 ocfs2_metadata_cache_owner(struct ocfs2_caching_info *ci) |
79 | { | 79 | { |
80 | BUG_ON(!ci || !ci->ci_ops); | 80 | BUG_ON(!ci || !ci->ci_ops); |
81 | 81 | ||
82 | return ci->ci_ops->co_owner(ci); | 82 | return ci->ci_ops->co_owner(ci); |
83 | } | 83 | } |
84 | 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 | |||
85 | static void ocfs2_metadata_cache_lock(struct ocfs2_caching_info *ci) | 92 | static void ocfs2_metadata_cache_lock(struct ocfs2_caching_info *ci) |
86 | { | 93 | { |
87 | BUG_ON(!ci || !ci->ci_ops); | 94 | BUG_ON(!ci || !ci->ci_ops); |
@@ -96,14 +103,14 @@ static void ocfs2_metadata_cache_unlock(struct ocfs2_caching_info *ci) | |||
96 | ci->ci_ops->co_cache_unlock(ci); | 103 | ci->ci_ops->co_cache_unlock(ci); |
97 | } | 104 | } |
98 | 105 | ||
99 | static void ocfs2_metadata_cache_io_lock(struct ocfs2_caching_info *ci) | 106 | void ocfs2_metadata_cache_io_lock(struct ocfs2_caching_info *ci) |
100 | { | 107 | { |
101 | BUG_ON(!ci || !ci->ci_ops); | 108 | BUG_ON(!ci || !ci->ci_ops); |
102 | 109 | ||
103 | ci->ci_ops->co_io_lock(ci); | 110 | ci->ci_ops->co_io_lock(ci); |
104 | } | 111 | } |
105 | 112 | ||
106 | static void ocfs2_metadata_cache_io_unlock(struct ocfs2_caching_info *ci) | 113 | void ocfs2_metadata_cache_io_unlock(struct ocfs2_caching_info *ci) |
107 | { | 114 | { |
108 | BUG_ON(!ci || !ci->ci_ops); | 115 | BUG_ON(!ci || !ci->ci_ops); |
109 | 116 | ||
@@ -149,11 +156,9 @@ static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) | |||
149 | * This function is a few more lines longer than necessary due to some | 156 | * This function is a few more lines longer than necessary due to some |
150 | * accounting done here, but I think it's worth tracking down those | 157 | * accounting done here, but I think it's worth tracking down those |
151 | * bugs sooner -- Mark */ | 158 | * bugs sooner -- Mark */ |
152 | void ocfs2_metadata_cache_purge(struct inode *inode) | 159 | void ocfs2_metadata_cache_purge(struct ocfs2_caching_info *ci) |
153 | { | 160 | { |
154 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
155 | unsigned int tree, to_purge, purged; | 161 | unsigned int tree, to_purge, purged; |
156 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
157 | struct rb_root root = RB_ROOT; | 162 | struct rb_root root = RB_ROOT; |
158 | 163 | ||
159 | BUG_ON(!ci || !ci->ci_ops); | 164 | BUG_ON(!ci || !ci->ci_ops); |
@@ -223,12 +228,11 @@ ocfs2_search_cache_tree(struct ocfs2_caching_info *ci, | |||
223 | return NULL; | 228 | return NULL; |
224 | } | 229 | } |
225 | 230 | ||
226 | static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | 231 | static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, |
227 | struct buffer_head *bh) | 232 | struct buffer_head *bh) |
228 | { | 233 | { |
229 | int index = -1; | 234 | int index = -1; |
230 | struct ocfs2_meta_cache_item *item = NULL; | 235 | struct ocfs2_meta_cache_item *item = NULL; |
231 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
232 | 236 | ||
233 | ocfs2_metadata_cache_lock(ci); | 237 | ocfs2_metadata_cache_lock(ci); |
234 | 238 | ||
@@ -238,11 +242,9 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | |||
238 | !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); | 242 | !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); |
239 | 243 | ||
240 | if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) | 244 | if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) |
241 | index = ocfs2_search_cache_array(&oi->ip_metadata_cache, | 245 | index = ocfs2_search_cache_array(ci, bh->b_blocknr); |
242 | bh->b_blocknr); | ||
243 | else | 246 | else |
244 | item = ocfs2_search_cache_tree(&oi->ip_metadata_cache, | 247 | item = ocfs2_search_cache_tree(ci, bh->b_blocknr); |
245 | bh->b_blocknr); | ||
246 | 248 | ||
247 | ocfs2_metadata_cache_unlock(ci); | 249 | ocfs2_metadata_cache_unlock(ci); |
248 | 250 | ||
@@ -256,7 +258,7 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, | |||
256 | * | 258 | * |
257 | * This can be called under lock_buffer() | 259 | * This can be called under lock_buffer() |
258 | */ | 260 | */ |
259 | int ocfs2_buffer_uptodate(struct inode *inode, | 261 | int ocfs2_buffer_uptodate(struct ocfs2_caching_info *ci, |
260 | struct buffer_head *bh) | 262 | struct buffer_head *bh) |
261 | { | 263 | { |
262 | /* Doesn't matter if the bh is in our cache or not -- if it's | 264 | /* Doesn't matter if the bh is in our cache or not -- if it's |
@@ -272,17 +274,17 @@ int ocfs2_buffer_uptodate(struct inode *inode, | |||
272 | 274 | ||
273 | /* Ok, locally the buffer is marked as up to date, now search | 275 | /* Ok, locally the buffer is marked as up to date, now search |
274 | * our cache to see if we can trust that. */ | 276 | * our cache to see if we can trust that. */ |
275 | return ocfs2_buffer_cached(OCFS2_I(inode), bh); | 277 | return ocfs2_buffer_cached(ci, bh); |
276 | } | 278 | } |
277 | 279 | ||
278 | /* | 280 | /* |
279 | * Determine whether a buffer is currently out on a read-ahead request. | 281 | * Determine whether a buffer is currently out on a read-ahead request. |
280 | * ci_io_sem should be held to serialize submitters with the logic here. | 282 | * ci_io_sem should be held to serialize submitters with the logic here. |
281 | */ | 283 | */ |
282 | int ocfs2_buffer_read_ahead(struct inode *inode, | 284 | int ocfs2_buffer_read_ahead(struct ocfs2_caching_info *ci, |
283 | struct buffer_head *bh) | 285 | struct buffer_head *bh) |
284 | { | 286 | { |
285 | return buffer_locked(bh) && ocfs2_buffer_cached(OCFS2_I(inode), bh); | 287 | return buffer_locked(bh) && ocfs2_buffer_cached(ci, bh); |
286 | } | 288 | } |
287 | 289 | ||
288 | /* Requires ip_lock */ | 290 | /* Requires ip_lock */ |
@@ -335,8 +337,7 @@ static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci, | |||
335 | } | 337 | } |
336 | 338 | ||
337 | /* co_cache_lock() must be held */ | 339 | /* co_cache_lock() must be held */ |
338 | static inline int ocfs2_insert_can_use_array(struct ocfs2_inode_info *oi, | 340 | static inline int ocfs2_insert_can_use_array(struct ocfs2_caching_info *ci) |
339 | struct ocfs2_caching_info *ci) | ||
340 | { | 341 | { |
341 | return (ci->ci_flags & OCFS2_CACHE_FL_INLINE) && | 342 | return (ci->ci_flags & OCFS2_CACHE_FL_INLINE) && |
342 | (ci->ci_num_cached < OCFS2_CACHE_INFO_MAX_ARRAY); | 343 | (ci->ci_num_cached < OCFS2_CACHE_INFO_MAX_ARRAY); |
@@ -347,11 +348,10 @@ static inline int ocfs2_insert_can_use_array(struct ocfs2_inode_info *oi, | |||
347 | * when to free in case of error. | 348 | * when to free in case of error. |
348 | * | 349 | * |
349 | * The co_cache_lock() must be held. */ | 350 | * The co_cache_lock() must be held. */ |
350 | static void ocfs2_expand_cache(struct ocfs2_inode_info *oi, | 351 | static void ocfs2_expand_cache(struct ocfs2_caching_info *ci, |
351 | struct ocfs2_meta_cache_item **tree) | 352 | struct ocfs2_meta_cache_item **tree) |
352 | { | 353 | { |
353 | int i; | 354 | int i; |
354 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
355 | 355 | ||
356 | mlog_bug_on_msg(ci->ci_num_cached != OCFS2_CACHE_INFO_MAX_ARRAY, | 356 | mlog_bug_on_msg(ci->ci_num_cached != OCFS2_CACHE_INFO_MAX_ARRAY, |
357 | "Owner %llu, num cached = %u, should be %u\n", | 357 | "Owner %llu, num cached = %u, should be %u\n", |
@@ -383,12 +383,11 @@ static void ocfs2_expand_cache(struct ocfs2_inode_info *oi, | |||
383 | 383 | ||
384 | /* Slow path function - memory allocation is necessary. See the | 384 | /* Slow path function - memory allocation is necessary. See the |
385 | * comment above ocfs2_set_buffer_uptodate for more information. */ | 385 | * comment above ocfs2_set_buffer_uptodate for more information. */ |
386 | static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | 386 | static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, |
387 | sector_t block, | 387 | sector_t block, |
388 | int expand_tree) | 388 | int expand_tree) |
389 | { | 389 | { |
390 | int i; | 390 | int i; |
391 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
392 | struct ocfs2_meta_cache_item *new = NULL; | 391 | struct ocfs2_meta_cache_item *new = NULL; |
393 | struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] = | 392 | struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] = |
394 | { NULL, }; | 393 | { NULL, }; |
@@ -420,7 +419,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | |||
420 | } | 419 | } |
421 | 420 | ||
422 | ocfs2_metadata_cache_lock(ci); | 421 | ocfs2_metadata_cache_lock(ci); |
423 | if (ocfs2_insert_can_use_array(oi, ci)) { | 422 | if (ocfs2_insert_can_use_array(ci)) { |
424 | mlog(0, "Someone cleared the tree underneath us\n"); | 423 | mlog(0, "Someone cleared the tree underneath us\n"); |
425 | /* Ok, items were removed from the cache in between | 424 | /* Ok, items were removed from the cache in between |
426 | * locks. Detect this and revert back to the fast path */ | 425 | * locks. Detect this and revert back to the fast path */ |
@@ -430,7 +429,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, | |||
430 | } | 429 | } |
431 | 430 | ||
432 | if (expand_tree) | 431 | if (expand_tree) |
433 | ocfs2_expand_cache(oi, tree); | 432 | ocfs2_expand_cache(ci, tree); |
434 | 433 | ||
435 | __ocfs2_insert_cache_tree(ci, new); | 434 | __ocfs2_insert_cache_tree(ci, new); |
436 | ocfs2_metadata_cache_unlock(ci); | 435 | ocfs2_metadata_cache_unlock(ci); |
@@ -468,16 +467,14 @@ out_free: | |||
468 | * Readahead buffers can be passed in here before the I/O request is | 467 | * Readahead buffers can be passed in here before the I/O request is |
469 | * completed. | 468 | * completed. |
470 | */ | 469 | */ |
471 | void ocfs2_set_buffer_uptodate(struct inode *inode, | 470 | void ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, |
472 | struct buffer_head *bh) | 471 | struct buffer_head *bh) |
473 | { | 472 | { |
474 | int expand; | 473 | int expand; |
475 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
476 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
477 | 474 | ||
478 | /* The block may very well exist in our cache already, so avoid | 475 | /* The block may very well exist in our cache already, so avoid |
479 | * doing any more work in that case. */ | 476 | * doing any more work in that case. */ |
480 | if (ocfs2_buffer_cached(oi, bh)) | 477 | if (ocfs2_buffer_cached(ci, bh)) |
481 | return; | 478 | return; |
482 | 479 | ||
483 | mlog(0, "Owner %llu, inserting block %llu\n", | 480 | mlog(0, "Owner %llu, inserting block %llu\n", |
@@ -487,7 +484,7 @@ void ocfs2_set_buffer_uptodate(struct inode *inode, | |||
487 | /* No need to recheck under spinlock - insertion is guarded by | 484 | /* No need to recheck under spinlock - insertion is guarded by |
488 | * co_io_lock() */ | 485 | * co_io_lock() */ |
489 | ocfs2_metadata_cache_lock(ci); | 486 | ocfs2_metadata_cache_lock(ci); |
490 | if (ocfs2_insert_can_use_array(oi, ci)) { | 487 | if (ocfs2_insert_can_use_array(ci)) { |
491 | /* Fast case - it's an array and there's a free | 488 | /* Fast case - it's an array and there's a free |
492 | * spot. */ | 489 | * spot. */ |
493 | ocfs2_append_cache_array(ci, bh->b_blocknr); | 490 | ocfs2_append_cache_array(ci, bh->b_blocknr); |
@@ -502,25 +499,22 @@ void ocfs2_set_buffer_uptodate(struct inode *inode, | |||
502 | } | 499 | } |
503 | ocfs2_metadata_cache_unlock(ci); | 500 | ocfs2_metadata_cache_unlock(ci); |
504 | 501 | ||
505 | __ocfs2_set_buffer_uptodate(oi, bh->b_blocknr, expand); | 502 | __ocfs2_set_buffer_uptodate(ci, bh->b_blocknr, expand); |
506 | } | 503 | } |
507 | 504 | ||
508 | /* Called against a newly allocated buffer. Most likely nobody should | 505 | /* Called against a newly allocated buffer. Most likely nobody should |
509 | * be able to read this sort of metadata while it's still being | 506 | * be able to read this sort of metadata while it's still being |
510 | * allocated, but this is careful to take co_io_lock() anyway. */ | 507 | * allocated, but this is careful to take co_io_lock() anyway. */ |
511 | void ocfs2_set_new_buffer_uptodate(struct inode *inode, | 508 | void ocfs2_set_new_buffer_uptodate(struct ocfs2_caching_info *ci, |
512 | struct buffer_head *bh) | 509 | struct buffer_head *bh) |
513 | { | 510 | { |
514 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
515 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
516 | |||
517 | /* This should definitely *not* exist in our cache */ | 511 | /* This should definitely *not* exist in our cache */ |
518 | BUG_ON(ocfs2_buffer_cached(oi, bh)); | 512 | BUG_ON(ocfs2_buffer_cached(ci, bh)); |
519 | 513 | ||
520 | set_buffer_uptodate(bh); | 514 | set_buffer_uptodate(bh); |
521 | 515 | ||
522 | ocfs2_metadata_cache_io_lock(ci); | 516 | ocfs2_metadata_cache_io_lock(ci); |
523 | ocfs2_set_buffer_uptodate(inode, bh); | 517 | ocfs2_set_buffer_uptodate(ci, bh); |
524 | ocfs2_metadata_cache_io_unlock(ci); | 518 | ocfs2_metadata_cache_io_unlock(ci); |
525 | } | 519 | } |
526 | 520 | ||
@@ -559,13 +553,11 @@ static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci, | |||
559 | ci->ci_num_cached--; | 553 | ci->ci_num_cached--; |
560 | } | 554 | } |
561 | 555 | ||
562 | static void ocfs2_remove_block_from_cache(struct inode *inode, | 556 | static void ocfs2_remove_block_from_cache(struct ocfs2_caching_info *ci, |
563 | sector_t block) | 557 | sector_t block) |
564 | { | 558 | { |
565 | int index; | 559 | int index; |
566 | struct ocfs2_meta_cache_item *item = NULL; | 560 | struct ocfs2_meta_cache_item *item = NULL; |
567 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
568 | struct ocfs2_caching_info *ci = &oi->ip_metadata_cache; | ||
569 | 561 | ||
570 | ocfs2_metadata_cache_lock(ci); | 562 | ocfs2_metadata_cache_lock(ci); |
571 | mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n", | 563 | mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n", |
@@ -593,23 +585,24 @@ static void ocfs2_remove_block_from_cache(struct inode *inode, | |||
593 | * bother reverting things to an inlined array in the case of a remove | 585 | * bother reverting things to an inlined array in the case of a remove |
594 | * which moves us back under the limit. | 586 | * which moves us back under the limit. |
595 | */ | 587 | */ |
596 | void ocfs2_remove_from_cache(struct inode *inode, | 588 | void ocfs2_remove_from_cache(struct ocfs2_caching_info *ci, |
597 | struct buffer_head *bh) | 589 | struct buffer_head *bh) |
598 | { | 590 | { |
599 | sector_t block = bh->b_blocknr; | 591 | sector_t block = bh->b_blocknr; |
600 | 592 | ||
601 | ocfs2_remove_block_from_cache(inode, block); | 593 | ocfs2_remove_block_from_cache(ci, block); |
602 | } | 594 | } |
603 | 595 | ||
604 | /* Called when we remove xattr clusters from an inode. */ | 596 | /* Called when we remove xattr clusters from an inode. */ |
605 | void ocfs2_remove_xattr_clusters_from_cache(struct inode *inode, | 597 | void ocfs2_remove_xattr_clusters_from_cache(struct ocfs2_caching_info *ci, |
606 | sector_t block, | 598 | sector_t block, |
607 | u32 c_len) | 599 | u32 c_len) |
608 | { | 600 | { |
609 | unsigned int i, b_len = ocfs2_clusters_to_blocks(inode->i_sb, 1) * c_len; | 601 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); |
602 | unsigned int i, b_len = ocfs2_clusters_to_blocks(sb, 1) * c_len; | ||
610 | 603 | ||
611 | for (i = 0; i < b_len; i++, block++) | 604 | for (i = 0; i < b_len; i++, block++) |
612 | ocfs2_remove_block_from_cache(inode, block); | 605 | ocfs2_remove_block_from_cache(ci, block); |
613 | } | 606 | } |
614 | 607 | ||
615 | int __init init_ocfs2_uptodate_cache(void) | 608 | int __init init_ocfs2_uptodate_cache(void) |