diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/xfs/xfs_iget.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r-- | fs/xfs/xfs_iget.c | 160 |
1 files changed, 45 insertions, 115 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 80e526489be5..6845db90818f 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include "xfs_inode_item.h" | 43 | #include "xfs_inode_item.h" |
44 | #include "xfs_bmap.h" | 44 | #include "xfs_bmap.h" |
45 | #include "xfs_btree_trace.h" | 45 | #include "xfs_btree_trace.h" |
46 | #include "xfs_dir2_trace.h" | 46 | #include "xfs_trace.h" |
47 | 47 | ||
48 | 48 | ||
49 | /* | 49 | /* |
@@ -74,6 +74,8 @@ xfs_inode_alloc( | |||
74 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 74 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
75 | ASSERT(completion_done(&ip->i_flush)); | 75 | ASSERT(completion_done(&ip->i_flush)); |
76 | 76 | ||
77 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | ||
78 | |||
77 | /* initialise the xfs inode */ | 79 | /* initialise the xfs inode */ |
78 | ip->i_ino = ino; | 80 | ip->i_ino = ino; |
79 | ip->i_mount = mp; | 81 | ip->i_mount = mp; |
@@ -87,30 +89,8 @@ xfs_inode_alloc( | |||
87 | ip->i_size = 0; | 89 | ip->i_size = 0; |
88 | ip->i_new_size = 0; | 90 | ip->i_new_size = 0; |
89 | 91 | ||
90 | /* | ||
91 | * Initialize inode's trace buffers. | ||
92 | */ | ||
93 | #ifdef XFS_INODE_TRACE | ||
94 | ip->i_trace = ktrace_alloc(INODE_TRACE_SIZE, KM_NOFS); | ||
95 | #endif | ||
96 | #ifdef XFS_BMAP_TRACE | ||
97 | ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_NOFS); | ||
98 | #endif | ||
99 | #ifdef XFS_BTREE_TRACE | ||
100 | ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_NOFS); | ||
101 | #endif | ||
102 | #ifdef XFS_RW_TRACE | ||
103 | ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_NOFS); | ||
104 | #endif | ||
105 | #ifdef XFS_ILOCK_TRACE | ||
106 | ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_NOFS); | ||
107 | #endif | ||
108 | #ifdef XFS_DIR2_TRACE | ||
109 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); | ||
110 | #endif | ||
111 | |||
112 | /* prevent anyone from using this yet */ | 92 | /* prevent anyone from using this yet */ |
113 | VFS_I(ip)->i_state = I_NEW|I_LOCK; | 93 | VFS_I(ip)->i_state = I_NEW; |
114 | 94 | ||
115 | return ip; | 95 | return ip; |
116 | } | 96 | } |
@@ -130,25 +110,6 @@ xfs_inode_free( | |||
130 | if (ip->i_afp) | 110 | if (ip->i_afp) |
131 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | 111 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); |
132 | 112 | ||
133 | #ifdef XFS_INODE_TRACE | ||
134 | ktrace_free(ip->i_trace); | ||
135 | #endif | ||
136 | #ifdef XFS_BMAP_TRACE | ||
137 | ktrace_free(ip->i_xtrace); | ||
138 | #endif | ||
139 | #ifdef XFS_BTREE_TRACE | ||
140 | ktrace_free(ip->i_btrace); | ||
141 | #endif | ||
142 | #ifdef XFS_RW_TRACE | ||
143 | ktrace_free(ip->i_rwtrace); | ||
144 | #endif | ||
145 | #ifdef XFS_ILOCK_TRACE | ||
146 | ktrace_free(ip->i_lock_trace); | ||
147 | #endif | ||
148 | #ifdef XFS_DIR2_TRACE | ||
149 | ktrace_free(ip->i_dir_trace); | ||
150 | #endif | ||
151 | |||
152 | if (ip->i_itemp) { | 113 | if (ip->i_itemp) { |
153 | /* | 114 | /* |
154 | * Only if we are shutting down the fs will we see an | 115 | * Only if we are shutting down the fs will we see an |
@@ -207,6 +168,7 @@ xfs_iget_cache_hit( | |||
207 | * instead of polling for it. | 168 | * instead of polling for it. |
208 | */ | 169 | */ |
209 | if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) { | 170 | if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) { |
171 | trace_xfs_iget_skip(ip); | ||
210 | XFS_STATS_INC(xs_ig_frecycle); | 172 | XFS_STATS_INC(xs_ig_frecycle); |
211 | error = EAGAIN; | 173 | error = EAGAIN; |
212 | goto out_error; | 174 | goto out_error; |
@@ -225,16 +187,15 @@ xfs_iget_cache_hit( | |||
225 | * Need to carefully get it back into useable state. | 187 | * Need to carefully get it back into useable state. |
226 | */ | 188 | */ |
227 | if (ip->i_flags & XFS_IRECLAIMABLE) { | 189 | if (ip->i_flags & XFS_IRECLAIMABLE) { |
228 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | 190 | trace_xfs_iget_reclaim(ip); |
229 | 191 | ||
230 | /* | 192 | /* |
231 | * We need to set XFS_INEW atomically with clearing the | 193 | * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode |
232 | * reclaimable tag so that we do have an indicator of the | 194 | * from stomping over us while we recycle the inode. We can't |
233 | * inode still being initialized. | 195 | * clear the radix tree reclaimable tag yet as it requires |
196 | * pag_ici_lock to be held exclusive. | ||
234 | */ | 197 | */ |
235 | ip->i_flags |= XFS_INEW; | 198 | ip->i_flags |= XFS_IRECLAIM; |
236 | ip->i_flags &= ~XFS_IRECLAIMABLE; | ||
237 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | ||
238 | 199 | ||
239 | spin_unlock(&ip->i_flags_lock); | 200 | spin_unlock(&ip->i_flags_lock); |
240 | read_unlock(&pag->pag_ici_lock); | 201 | read_unlock(&pag->pag_ici_lock); |
@@ -251,9 +212,18 @@ xfs_iget_cache_hit( | |||
251 | ip->i_flags &= ~XFS_INEW; | 212 | ip->i_flags &= ~XFS_INEW; |
252 | ip->i_flags |= XFS_IRECLAIMABLE; | 213 | ip->i_flags |= XFS_IRECLAIMABLE; |
253 | __xfs_inode_set_reclaim_tag(pag, ip); | 214 | __xfs_inode_set_reclaim_tag(pag, ip); |
215 | trace_xfs_iget_reclaim(ip); | ||
254 | goto out_error; | 216 | goto out_error; |
255 | } | 217 | } |
256 | inode->i_state = I_LOCK|I_NEW; | 218 | |
219 | write_lock(&pag->pag_ici_lock); | ||
220 | spin_lock(&ip->i_flags_lock); | ||
221 | ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM); | ||
222 | ip->i_flags |= XFS_INEW; | ||
223 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | ||
224 | inode->i_state = I_NEW; | ||
225 | spin_unlock(&ip->i_flags_lock); | ||
226 | write_unlock(&pag->pag_ici_lock); | ||
257 | } else { | 227 | } else { |
258 | /* If the VFS inode is being torn down, pause and try again. */ | 228 | /* If the VFS inode is being torn down, pause and try again. */ |
259 | if (!igrab(inode)) { | 229 | if (!igrab(inode)) { |
@@ -270,8 +240,9 @@ xfs_iget_cache_hit( | |||
270 | xfs_ilock(ip, lock_flags); | 240 | xfs_ilock(ip, lock_flags); |
271 | 241 | ||
272 | xfs_iflags_clear(ip, XFS_ISTALE); | 242 | xfs_iflags_clear(ip, XFS_ISTALE); |
273 | xfs_itrace_exit_tag(ip, "xfs_iget.found"); | ||
274 | XFS_STATS_INC(xs_ig_found); | 243 | XFS_STATS_INC(xs_ig_found); |
244 | |||
245 | trace_xfs_iget_found(ip); | ||
275 | return 0; | 246 | return 0; |
276 | 247 | ||
277 | out_error: | 248 | out_error: |
@@ -290,7 +261,7 @@ xfs_iget_cache_miss( | |||
290 | struct xfs_inode **ipp, | 261 | struct xfs_inode **ipp, |
291 | xfs_daddr_t bno, | 262 | xfs_daddr_t bno, |
292 | int flags, | 263 | int flags, |
293 | int lock_flags) __releases(pag->pag_ici_lock) | 264 | int lock_flags) |
294 | { | 265 | { |
295 | struct xfs_inode *ip; | 266 | struct xfs_inode *ip; |
296 | int error; | 267 | int error; |
@@ -305,7 +276,7 @@ xfs_iget_cache_miss( | |||
305 | if (error) | 276 | if (error) |
306 | goto out_destroy; | 277 | goto out_destroy; |
307 | 278 | ||
308 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | 279 | xfs_itrace_entry(ip); |
309 | 280 | ||
310 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { | 281 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { |
311 | error = ENOENT; | 282 | error = ENOENT; |
@@ -350,6 +321,8 @@ xfs_iget_cache_miss( | |||
350 | 321 | ||
351 | write_unlock(&pag->pag_ici_lock); | 322 | write_unlock(&pag->pag_ici_lock); |
352 | radix_tree_preload_end(); | 323 | radix_tree_preload_end(); |
324 | |||
325 | trace_xfs_iget_alloc(ip); | ||
353 | *ipp = ip; | 326 | *ipp = ip; |
354 | return 0; | 327 | return 0; |
355 | 328 | ||
@@ -408,7 +381,7 @@ xfs_iget( | |||
408 | return EINVAL; | 381 | return EINVAL; |
409 | 382 | ||
410 | /* get the perag structure and ensure that it's inode capable */ | 383 | /* get the perag structure and ensure that it's inode capable */ |
411 | pag = xfs_get_perag(mp, ino); | 384 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino)); |
412 | if (!pag->pagi_inodeok) | 385 | if (!pag->pagi_inodeok) |
413 | return EINVAL; | 386 | return EINVAL; |
414 | ASSERT(pag->pag_ici_init); | 387 | ASSERT(pag->pag_ici_init); |
@@ -432,7 +405,7 @@ again: | |||
432 | if (error) | 405 | if (error) |
433 | goto out_error_or_again; | 406 | goto out_error_or_again; |
434 | } | 407 | } |
435 | xfs_put_perag(mp, pag); | 408 | xfs_perag_put(pag); |
436 | 409 | ||
437 | *ipp = ip; | 410 | *ipp = ip; |
438 | 411 | ||
@@ -451,7 +424,7 @@ out_error_or_again: | |||
451 | delay(1); | 424 | delay(1); |
452 | goto again; | 425 | goto again; |
453 | } | 426 | } |
454 | xfs_put_perag(mp, pag); | 427 | xfs_perag_put(pag); |
455 | return error; | 428 | return error; |
456 | } | 429 | } |
457 | 430 | ||
@@ -511,19 +484,23 @@ xfs_ireclaim( | |||
511 | { | 484 | { |
512 | struct xfs_mount *mp = ip->i_mount; | 485 | struct xfs_mount *mp = ip->i_mount; |
513 | struct xfs_perag *pag; | 486 | struct xfs_perag *pag; |
487 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); | ||
514 | 488 | ||
515 | XFS_STATS_INC(xs_ig_reclaims); | 489 | XFS_STATS_INC(xs_ig_reclaims); |
516 | 490 | ||
517 | /* | 491 | /* |
518 | * Remove the inode from the per-AG radix tree. It doesn't matter | 492 | * Remove the inode from the per-AG radix tree. |
519 | * if it was never added to it because radix_tree_delete can deal | 493 | * |
520 | * with that case just fine. | 494 | * Because radix_tree_delete won't complain even if the item was never |
495 | * added to the tree assert that it's been there before to catch | ||
496 | * problems with the inode life time early on. | ||
521 | */ | 497 | */ |
522 | pag = xfs_get_perag(mp, ip->i_ino); | 498 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); |
523 | write_lock(&pag->pag_ici_lock); | 499 | write_lock(&pag->pag_ici_lock); |
524 | radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino)); | 500 | if (!radix_tree_delete(&pag->pag_ici_root, agino)) |
501 | ASSERT(0); | ||
525 | write_unlock(&pag->pag_ici_lock); | 502 | write_unlock(&pag->pag_ici_lock); |
526 | xfs_put_perag(mp, pag); | 503 | xfs_perag_put(pag); |
527 | 504 | ||
528 | /* | 505 | /* |
529 | * Here we do an (almost) spurious inode lock in order to coordinate | 506 | * Here we do an (almost) spurious inode lock in order to coordinate |
@@ -636,7 +613,7 @@ xfs_ilock( | |||
636 | else if (lock_flags & XFS_ILOCK_SHARED) | 613 | else if (lock_flags & XFS_ILOCK_SHARED) |
637 | mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags)); | 614 | mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags)); |
638 | 615 | ||
639 | xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address); | 616 | trace_xfs_ilock(ip, lock_flags, _RET_IP_); |
640 | } | 617 | } |
641 | 618 | ||
642 | /* | 619 | /* |
@@ -681,7 +658,7 @@ xfs_ilock_nowait( | |||
681 | if (!mrtryaccess(&ip->i_lock)) | 658 | if (!mrtryaccess(&ip->i_lock)) |
682 | goto out_undo_iolock; | 659 | goto out_undo_iolock; |
683 | } | 660 | } |
684 | xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address); | 661 | trace_xfs_ilock_nowait(ip, lock_flags, _RET_IP_); |
685 | return 1; | 662 | return 1; |
686 | 663 | ||
687 | out_undo_iolock: | 664 | out_undo_iolock: |
@@ -743,7 +720,7 @@ xfs_iunlock( | |||
743 | xfs_trans_unlocked_item(ip->i_itemp->ili_item.li_ailp, | 720 | xfs_trans_unlocked_item(ip->i_itemp->ili_item.li_ailp, |
744 | (xfs_log_item_t*)(ip->i_itemp)); | 721 | (xfs_log_item_t*)(ip->i_itemp)); |
745 | } | 722 | } |
746 | xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address); | 723 | trace_xfs_iunlock(ip, lock_flags, _RET_IP_); |
747 | } | 724 | } |
748 | 725 | ||
749 | /* | 726 | /* |
@@ -762,6 +739,8 @@ xfs_ilock_demote( | |||
762 | mrdemote(&ip->i_lock); | 739 | mrdemote(&ip->i_lock); |
763 | if (lock_flags & XFS_IOLOCK_EXCL) | 740 | if (lock_flags & XFS_IOLOCK_EXCL) |
764 | mrdemote(&ip->i_iolock); | 741 | mrdemote(&ip->i_iolock); |
742 | |||
743 | trace_xfs_ilock_demote(ip, lock_flags, _RET_IP_); | ||
765 | } | 744 | } |
766 | 745 | ||
767 | #ifdef DEBUG | 746 | #ifdef DEBUG |
@@ -792,52 +771,3 @@ xfs_isilocked( | |||
792 | return 1; | 771 | return 1; |
793 | } | 772 | } |
794 | #endif | 773 | #endif |
795 | |||
796 | #ifdef XFS_INODE_TRACE | ||
797 | |||
798 | #define KTRACE_ENTER(ip, vk, s, line, ra) \ | ||
799 | ktrace_enter((ip)->i_trace, \ | ||
800 | /* 0 */ (void *)(__psint_t)(vk), \ | ||
801 | /* 1 */ (void *)(s), \ | ||
802 | /* 2 */ (void *)(__psint_t) line, \ | ||
803 | /* 3 */ (void *)(__psint_t)atomic_read(&VFS_I(ip)->i_count), \ | ||
804 | /* 4 */ (void *)(ra), \ | ||
805 | /* 5 */ NULL, \ | ||
806 | /* 6 */ (void *)(__psint_t)current_cpu(), \ | ||
807 | /* 7 */ (void *)(__psint_t)current_pid(), \ | ||
808 | /* 8 */ (void *)__return_address, \ | ||
809 | /* 9 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL) | ||
810 | |||
811 | /* | ||
812 | * Vnode tracing code. | ||
813 | */ | ||
814 | void | ||
815 | _xfs_itrace_entry(xfs_inode_t *ip, const char *func, inst_t *ra) | ||
816 | { | ||
817 | KTRACE_ENTER(ip, INODE_KTRACE_ENTRY, func, 0, ra); | ||
818 | } | ||
819 | |||
820 | void | ||
821 | _xfs_itrace_exit(xfs_inode_t *ip, const char *func, inst_t *ra) | ||
822 | { | ||
823 | KTRACE_ENTER(ip, INODE_KTRACE_EXIT, func, 0, ra); | ||
824 | } | ||
825 | |||
826 | void | ||
827 | xfs_itrace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
828 | { | ||
829 | KTRACE_ENTER(ip, INODE_KTRACE_HOLD, file, line, ra); | ||
830 | } | ||
831 | |||
832 | void | ||
833 | _xfs_itrace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
834 | { | ||
835 | KTRACE_ENTER(ip, INODE_KTRACE_REF, file, line, ra); | ||
836 | } | ||
837 | |||
838 | void | ||
839 | xfs_itrace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra) | ||
840 | { | ||
841 | KTRACE_ENTER(ip, INODE_KTRACE_RELE, file, line, ra); | ||
842 | } | ||
843 | #endif /* XFS_INODE_TRACE */ | ||