aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2009-09-29 09:48:56 -0400
committerAlex Elder <aelder@sgi.com>2009-12-11 16:11:19 -0500
commit848ce8f731aed0a2d4ab5884a4f6664af73d2dd0 (patch)
treecb8bdd8d2ce23f586e4bc0351dc934ae37a6db4e
parent22763c5cf3690a681551162c15d34d935308c8d7 (diff)
xfs: simplify inode teardown
Currently the reclaim code for the case where we don't reclaim the final reclaim is overly complicated. We know that the inode is clean but instead of just directly reclaiming the clean inode we go through the whole process of marking the inode reclaimable just to directly reclaim it from the calling context. Besides being overly complicated this introduces a race where iget could recycle an inode between marked reclaimable and actually being reclaimed leading to panics. This patch gets rid of the existing reclaim path, and replaces it with a simple call to xfs_ireclaim if the inode was clean. While we're at it we also use the slightly more lax xfs_inode_clean check we'd use later to determine if we need to flush the inode here. Finally get rid of xfs_reclaim function and place the remaining small bits of reclaim code directly into xfs_fs_destroy_inode. Signed-off-by: Christoph Hellwig <hch@lst.de> Reported-by: Patrick Schreurs <patrick@news-service.com> Reported-by: Tommy van Leeuwen <tommy@news-service.com> Tested-by: Patrick Schreurs <patrick@news-service.com> Reviewed-by: Alex Elder <aelder@sgi.com> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c34
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c15
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h1
-rw-r--r--fs/xfs/xfs_vnodeops.c40
-rw-r--r--fs/xfs/xfs_vnodeops.h1
5 files changed, 34 insertions, 57 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 18a4b8e11df2..a82a93db67c2 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -930,13 +930,39 @@ xfs_fs_alloc_inode(
930 */ 930 */
931STATIC void 931STATIC void
932xfs_fs_destroy_inode( 932xfs_fs_destroy_inode(
933 struct inode *inode) 933 struct inode *inode)
934{ 934{
935 xfs_inode_t *ip = XFS_I(inode); 935 struct xfs_inode *ip = XFS_I(inode);
936
937 xfs_itrace_entry(ip);
936 938
937 XFS_STATS_INC(vn_reclaim); 939 XFS_STATS_INC(vn_reclaim);
938 if (xfs_reclaim(ip)) 940
939 panic("%s: cannot reclaim 0x%p\n", __func__, inode); 941 /* bad inode, get out here ASAP */
942 if (is_bad_inode(inode))
943 goto out_reclaim;
944
945 xfs_ioend_wait(ip);
946
947 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
948
949 /*
950 * We should never get here with one of the reclaim flags already set.
951 */
952 ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
953 ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM));
954
955 /*
956 * If we have nothing to flush with this inode then complete the
957 * teardown now, otherwise delay the flush operation.
958 */
959 if (!xfs_inode_clean(ip)) {
960 xfs_inode_set_reclaim_tag(ip);
961 return;
962 }
963
964out_reclaim:
965 xfs_ireclaim(ip);
940} 966}
941 967
942/* 968/*
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 961df0a22c78..d895a3a960f5 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -663,10 +663,9 @@ xfs_syncd_stop(
663 kthread_stop(mp->m_sync_task); 663 kthread_stop(mp->m_sync_task);
664} 664}
665 665
666int 666STATIC int
667xfs_reclaim_inode( 667xfs_reclaim_inode(
668 xfs_inode_t *ip, 668 xfs_inode_t *ip,
669 int locked,
670 int sync_mode) 669 int sync_mode)
671{ 670{
672 xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); 671 xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino);
@@ -682,10 +681,6 @@ xfs_reclaim_inode(
682 !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { 681 !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
683 spin_unlock(&ip->i_flags_lock); 682 spin_unlock(&ip->i_flags_lock);
684 write_unlock(&pag->pag_ici_lock); 683 write_unlock(&pag->pag_ici_lock);
685 if (locked) {
686 xfs_ifunlock(ip);
687 xfs_iunlock(ip, XFS_ILOCK_EXCL);
688 }
689 return -EAGAIN; 684 return -EAGAIN;
690 } 685 }
691 __xfs_iflags_set(ip, XFS_IRECLAIM); 686 __xfs_iflags_set(ip, XFS_IRECLAIM);
@@ -704,10 +699,8 @@ xfs_reclaim_inode(
704 * We get the flush lock regardless, though, just to make sure 699 * We get the flush lock regardless, though, just to make sure
705 * we don't free it while it is being flushed. 700 * we don't free it while it is being flushed.
706 */ 701 */
707 if (!locked) { 702 xfs_ilock(ip, XFS_ILOCK_EXCL);
708 xfs_ilock(ip, XFS_ILOCK_EXCL); 703 xfs_iflock(ip);
709 xfs_iflock(ip);
710 }
711 704
712 /* 705 /*
713 * In the case of a forced shutdown we rely on xfs_iflush() to 706 * In the case of a forced shutdown we rely on xfs_iflush() to
@@ -778,7 +771,7 @@ xfs_reclaim_inode_now(
778 } 771 }
779 read_unlock(&pag->pag_ici_lock); 772 read_unlock(&pag->pag_ici_lock);
780 773
781 return xfs_reclaim_inode(ip, 0, flags); 774 return xfs_reclaim_inode(ip, flags);
782} 775}
783 776
784int 777int
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index 27920eb7a820..a500b4d91835 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -44,7 +44,6 @@ void xfs_quiesce_attr(struct xfs_mount *mp);
44 44
45void xfs_flush_inodes(struct xfs_inode *ip); 45void xfs_flush_inodes(struct xfs_inode *ip);
46 46
47int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
48int xfs_reclaim_inodes(struct xfs_mount *mp, int mode); 47int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
49 48
50void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); 49void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index b572f7e840e0..3fac146b3b7d 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -2456,46 +2456,6 @@ xfs_set_dmattrs(
2456 return error; 2456 return error;
2457} 2457}
2458 2458
2459int
2460xfs_reclaim(
2461 xfs_inode_t *ip)
2462{
2463
2464 xfs_itrace_entry(ip);
2465
2466 ASSERT(!VN_MAPPED(VFS_I(ip)));
2467
2468 /* bad inode, get out here ASAP */
2469 if (is_bad_inode(VFS_I(ip))) {
2470 xfs_ireclaim(ip);
2471 return 0;
2472 }
2473
2474 xfs_ioend_wait(ip);
2475
2476 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
2477
2478 /*
2479 * If we have nothing to flush with this inode then complete the
2480 * teardown now, otherwise break the link between the xfs inode and the
2481 * linux inode and clean up the xfs inode later. This avoids flushing
2482 * the inode to disk during the delete operation itself.
2483 *
2484 * When breaking the link, we need to set the XFS_IRECLAIMABLE flag
2485 * first to ensure that xfs_iunpin() will never see an xfs inode
2486 * that has a linux inode being reclaimed. Synchronisation is provided
2487 * by the i_flags_lock.
2488 */
2489 if (!ip->i_update_core && (ip->i_itemp == NULL)) {
2490 xfs_ilock(ip, XFS_ILOCK_EXCL);
2491 xfs_iflock(ip);
2492 xfs_iflags_set(ip, XFS_IRECLAIMABLE);
2493 return xfs_reclaim_inode(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC);
2494 }
2495 xfs_inode_set_reclaim_tag(ip);
2496 return 0;
2497}
2498
2499/* 2459/*
2500 * xfs_alloc_file_space() 2460 * xfs_alloc_file_space()
2501 * This routine allocates disk space for the given file. 2461 * This routine allocates disk space for the given file.
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index a9e102de71a1..167a467403a5 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -38,7 +38,6 @@ int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name,
38 const char *target_path, mode_t mode, struct xfs_inode **ipp, 38 const char *target_path, mode_t mode, struct xfs_inode **ipp,
39 cred_t *credp); 39 cred_t *credp);
40int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); 40int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
41int xfs_reclaim(struct xfs_inode *ip);
42int xfs_change_file_space(struct xfs_inode *ip, int cmd, 41int xfs_change_file_space(struct xfs_inode *ip, int cmd,
43 xfs_flock64_t *bf, xfs_off_t offset, int attr_flags); 42 xfs_flock64_t *bf, xfs_off_t offset, int attr_flags);
44int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name, 43int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,