aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_iget.c128
-rw-r--r--fs/xfs/xfs_inode.c72
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_mount.h1
4 files changed, 86 insertions, 117 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 27ec2417b852..f58e5e000fce 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -450,65 +450,109 @@ xfs_iput_new(
450 IRELE(ip); 450 IRELE(ip);
451} 451}
452 452
453
454/* 453/*
455 * This routine embodies the part of the reclaim code that pulls 454 * This is called free all the memory associated with an inode.
456 * the inode from the inode hash table and the mount structure's 455 * It must free the inode itself and any buffers allocated for
457 * inode list. 456 * if_extents/if_data and if_broot. It must also free the lock
458 * This should only be called from xfs_reclaim(). 457 * associated with the inode.
458 *
459 * Note: because we don't initialise everything on reallocation out
460 * of the zone, we must ensure we nullify everything correctly before
461 * freeing the structure.
459 */ 462 */
460void 463void
461xfs_ireclaim(xfs_inode_t *ip) 464xfs_ireclaim(
465 struct xfs_inode *ip)
462{ 466{
463 /* 467 struct xfs_mount *mp = ip->i_mount;
464 * Remove from old hash list and mount list. 468 struct xfs_perag *pag;
465 */
466 XFS_STATS_INC(xs_ig_reclaims);
467 469
468 xfs_iextract(ip); 470 XFS_STATS_INC(xs_ig_reclaims);
469 471
470 /* 472 /*
471 * Here we do a spurious inode lock in order to coordinate with inode 473 * Remove the inode from the per-AG radix tree. It doesn't matter
472 * cache radix tree lookups. This is because the lookup can reference 474 * if it was never added to it because radix_tree_delete can deal
473 * the inodes in the cache without taking references. We make that OK 475 * with that case just fine.
474 * here by ensuring that we wait until the inode is unlocked after the
475 * lookup before we go ahead and free it. We get both the ilock and
476 * the iolock because the code may need to drop the ilock one but will
477 * still hold the iolock.
478 */ 476 */
479 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 477 pag = xfs_get_perag(mp, ip->i_ino);
478 write_lock(&pag->pag_ici_lock);
479 radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino));
480 write_unlock(&pag->pag_ici_lock);
481 xfs_put_perag(mp, pag);
480 482
481 /* 483 /*
482 * Release dquots (and their references) if any. An inode may escape 484 * Here we do an (almost) spurious inode lock in order to coordinate
483 * xfs_inactive and get here via vn_alloc->vn_reclaim path. 485 * with inode cache radix tree lookups. This is because the lookup
486 * can reference the inodes in the cache without taking references.
487 *
488 * We make that OK here by ensuring that we wait until the inode is
489 * unlocked after the lookup before we go ahead and free it. We get
490 * both the ilock and the iolock because the code may need to drop the
491 * ilock one but will still hold the iolock.
484 */ 492 */
485 XFS_QM_DQDETACH(ip->i_mount, ip); 493 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
486
487 /* 494 /*
488 * Free all memory associated with the inode. 495 * Release dquots (and their references) if any.
489 */ 496 */
497 XFS_QM_DQDETACH(ip->i_mount, ip);
490 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 498 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
491 xfs_idestroy(ip);
492}
493 499
494/* 500 switch (ip->i_d.di_mode & S_IFMT) {
495 * This routine removes an about-to-be-destroyed inode from 501 case S_IFREG:
496 * all of the lists in which it is located with the exception 502 case S_IFDIR:
497 * of the behavior chain. 503 case S_IFLNK:
498 */ 504 xfs_idestroy_fork(ip, XFS_DATA_FORK);
499void 505 break;
500xfs_iextract( 506 }
501 xfs_inode_t *ip)
502{
503 xfs_mount_t *mp = ip->i_mount;
504 xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
505 507
506 write_lock(&pag->pag_ici_lock); 508 if (ip->i_afp)
507 radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino)); 509 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
508 write_unlock(&pag->pag_ici_lock);
509 xfs_put_perag(mp, pag);
510 510
511 mp->m_ireclaims++; 511#ifdef XFS_INODE_TRACE
512 ktrace_free(ip->i_trace);
513#endif
514#ifdef XFS_BMAP_TRACE
515 ktrace_free(ip->i_xtrace);
516#endif
517#ifdef XFS_BTREE_TRACE
518 ktrace_free(ip->i_btrace);
519#endif
520#ifdef XFS_RW_TRACE
521 ktrace_free(ip->i_rwtrace);
522#endif
523#ifdef XFS_ILOCK_TRACE
524 ktrace_free(ip->i_lock_trace);
525#endif
526#ifdef XFS_DIR2_TRACE
527 ktrace_free(ip->i_dir_trace);
528#endif
529 if (ip->i_itemp) {
530 /*
531 * Only if we are shutting down the fs will we see an
532 * inode still in the AIL. If it is there, we should remove
533 * it to prevent a use-after-free from occurring.
534 */
535 xfs_log_item_t *lip = &ip->i_itemp->ili_item;
536 struct xfs_ail *ailp = lip->li_ailp;
537
538 ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
539 XFS_FORCED_SHUTDOWN(ip->i_mount));
540 if (lip->li_flags & XFS_LI_IN_AIL) {
541 spin_lock(&ailp->xa_lock);
542 if (lip->li_flags & XFS_LI_IN_AIL)
543 xfs_trans_ail_delete(ailp, lip);
544 else
545 spin_unlock(&ailp->xa_lock);
546 }
547 xfs_inode_item_destroy(ip);
548 ip->i_itemp = NULL;
549 }
550 /* asserts to verify all state is correct here */
551 ASSERT(atomic_read(&ip->i_iocount) == 0);
552 ASSERT(atomic_read(&ip->i_pincount) == 0);
553 ASSERT(!spin_is_locked(&ip->i_flags_lock));
554 ASSERT(completion_done(&ip->i_flush));
555 kmem_zone_free(xfs_inode_zone, ip);
512} 556}
513 557
514/* 558/*
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 872191b46784..4e664f57860b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2450,78 +2450,6 @@ xfs_idestroy_fork(
2450} 2450}
2451 2451
2452/* 2452/*
2453 * This is called free all the memory associated with an inode.
2454 * It must free the inode itself and any buffers allocated for
2455 * if_extents/if_data and if_broot. It must also free the lock
2456 * associated with the inode.
2457 *
2458 * Note: because we don't initialise everything on reallocation out
2459 * of the zone, we must ensure we nullify everything correctly before
2460 * freeing the structure.
2461 */
2462void
2463xfs_idestroy(
2464 xfs_inode_t *ip)
2465{
2466 switch (ip->i_d.di_mode & S_IFMT) {
2467 case S_IFREG:
2468 case S_IFDIR:
2469 case S_IFLNK:
2470 xfs_idestroy_fork(ip, XFS_DATA_FORK);
2471 break;
2472 }
2473 if (ip->i_afp)
2474 xfs_idestroy_fork(ip, XFS_ATTR_FORK);
2475
2476#ifdef XFS_INODE_TRACE
2477 ktrace_free(ip->i_trace);
2478#endif
2479#ifdef XFS_BMAP_TRACE
2480 ktrace_free(ip->i_xtrace);
2481#endif
2482#ifdef XFS_BTREE_TRACE
2483 ktrace_free(ip->i_btrace);
2484#endif
2485#ifdef XFS_RW_TRACE
2486 ktrace_free(ip->i_rwtrace);
2487#endif
2488#ifdef XFS_ILOCK_TRACE
2489 ktrace_free(ip->i_lock_trace);
2490#endif
2491#ifdef XFS_DIR2_TRACE
2492 ktrace_free(ip->i_dir_trace);
2493#endif
2494 if (ip->i_itemp) {
2495 /*
2496 * Only if we are shutting down the fs will we see an
2497 * inode still in the AIL. If it is there, we should remove
2498 * it to prevent a use-after-free from occurring.
2499 */
2500 xfs_log_item_t *lip = &ip->i_itemp->ili_item;
2501 struct xfs_ail *ailp = lip->li_ailp;
2502
2503 ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
2504 XFS_FORCED_SHUTDOWN(ip->i_mount));
2505 if (lip->li_flags & XFS_LI_IN_AIL) {
2506 spin_lock(&ailp->xa_lock);
2507 if (lip->li_flags & XFS_LI_IN_AIL)
2508 xfs_trans_ail_delete(ailp, lip);
2509 else
2510 spin_unlock(&ailp->xa_lock);
2511 }
2512 xfs_inode_item_destroy(ip);
2513 ip->i_itemp = NULL;
2514 }
2515 /* asserts to verify all state is correct here */
2516 ASSERT(atomic_read(&ip->i_iocount) == 0);
2517 ASSERT(atomic_read(&ip->i_pincount) == 0);
2518 ASSERT(!spin_is_locked(&ip->i_flags_lock));
2519 ASSERT(completion_done(&ip->i_flush));
2520 kmem_zone_free(xfs_inode_zone, ip);
2521}
2522
2523
2524/*
2525 * Increment the pin count of the given buffer. 2453 * Increment the pin count of the given buffer.
2526 * This value is protected by ipinlock spinlock in the mount structure. 2454 * This value is protected by ipinlock spinlock in the mount structure.
2527 */ 2455 */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index c38d4509c66d..03ae96bdae7e 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -529,8 +529,6 @@ int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
529 xfs_fsize_t, int, int); 529 xfs_fsize_t, int, int);
530int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); 530int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
531 531
532void xfs_idestroy(xfs_inode_t *);
533void xfs_iextract(xfs_inode_t *);
534void xfs_iext_realloc(xfs_inode_t *, int, int); 532void xfs_iext_realloc(xfs_inode_t *, int, int);
535void xfs_ipin(xfs_inode_t *); 533void xfs_ipin(xfs_inode_t *);
536void xfs_iunpin(xfs_inode_t *); 534void xfs_iunpin(xfs_inode_t *);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 4fce22a8c355..38252554b1cc 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -241,7 +241,6 @@ typedef struct xfs_mount {
241 xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */ 241 xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */
242 spinlock_t m_agirotor_lock;/* .. and lock protecting it */ 242 spinlock_t m_agirotor_lock;/* .. and lock protecting it */
243 xfs_agnumber_t m_maxagi; /* highest inode alloc group */ 243 xfs_agnumber_t m_maxagi; /* highest inode alloc group */
244 uint m_ireclaims; /* count of calls to reclaim*/
245 uint m_readio_log; /* min read size log bytes */ 244 uint m_readio_log; /* min read size log bytes */
246 uint m_readio_blocks; /* min read size blocks */ 245 uint m_readio_blocks; /* min read size blocks */
247 uint m_writeio_log; /* min write size log bytes */ 246 uint m_writeio_log; /* min write size log bytes */