diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
| -rw-r--r-- | fs/xfs/xfs_inode.c | 144 |
1 files changed, 62 insertions, 82 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 8cd6e8d8fe9c..d53c39de7d05 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -1940,10 +1940,10 @@ xfs_ifree_cluster( | |||
| 1940 | int blks_per_cluster; | 1940 | int blks_per_cluster; |
| 1941 | int nbufs; | 1941 | int nbufs; |
| 1942 | int ninodes; | 1942 | int ninodes; |
| 1943 | int i, j, found, pre_flushed; | 1943 | int i, j; |
| 1944 | xfs_daddr_t blkno; | 1944 | xfs_daddr_t blkno; |
| 1945 | xfs_buf_t *bp; | 1945 | xfs_buf_t *bp; |
| 1946 | xfs_inode_t *ip, **ip_found; | 1946 | xfs_inode_t *ip; |
| 1947 | xfs_inode_log_item_t *iip; | 1947 | xfs_inode_log_item_t *iip; |
| 1948 | xfs_log_item_t *lip; | 1948 | xfs_log_item_t *lip; |
| 1949 | struct xfs_perag *pag; | 1949 | struct xfs_perag *pag; |
| @@ -1960,114 +1960,97 @@ xfs_ifree_cluster( | |||
| 1960 | nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster; | 1960 | nbufs = XFS_IALLOC_BLOCKS(mp) / blks_per_cluster; |
| 1961 | } | 1961 | } |
| 1962 | 1962 | ||
| 1963 | ip_found = kmem_alloc(ninodes * sizeof(xfs_inode_t *), KM_NOFS); | ||
| 1964 | |||
| 1965 | for (j = 0; j < nbufs; j++, inum += ninodes) { | 1963 | for (j = 0; j < nbufs; j++, inum += ninodes) { |
| 1964 | int found = 0; | ||
| 1965 | |||
| 1966 | blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum), | 1966 | blkno = XFS_AGB_TO_DADDR(mp, XFS_INO_TO_AGNO(mp, inum), |
| 1967 | XFS_INO_TO_AGBNO(mp, inum)); | 1967 | XFS_INO_TO_AGBNO(mp, inum)); |
| 1968 | 1968 | ||
| 1969 | /* | ||
| 1970 | * We obtain and lock the backing buffer first in the process | ||
| 1971 | * here, as we have to ensure that any dirty inode that we | ||
| 1972 | * can't get the flush lock on is attached to the buffer. | ||
| 1973 | * If we scan the in-memory inodes first, then buffer IO can | ||
| 1974 | * complete before we get a lock on it, and hence we may fail | ||
| 1975 | * to mark all the active inodes on the buffer stale. | ||
| 1976 | */ | ||
| 1977 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, | ||
| 1978 | mp->m_bsize * blks_per_cluster, | ||
| 1979 | XBF_LOCK); | ||
| 1980 | |||
| 1981 | /* | ||
| 1982 | * Walk the inodes already attached to the buffer and mark them | ||
| 1983 | * stale. These will all have the flush locks held, so an | ||
| 1984 | * in-memory inode walk can't lock them. | ||
| 1985 | */ | ||
| 1986 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); | ||
| 1987 | while (lip) { | ||
| 1988 | if (lip->li_type == XFS_LI_INODE) { | ||
| 1989 | iip = (xfs_inode_log_item_t *)lip; | ||
| 1990 | ASSERT(iip->ili_logged == 1); | ||
| 1991 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; | ||
| 1992 | xfs_trans_ail_copy_lsn(mp->m_ail, | ||
| 1993 | &iip->ili_flush_lsn, | ||
| 1994 | &iip->ili_item.li_lsn); | ||
| 1995 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); | ||
| 1996 | found++; | ||
| 1997 | } | ||
| 1998 | lip = lip->li_bio_list; | ||
| 1999 | } | ||
| 1969 | 2000 | ||
| 1970 | /* | 2001 | /* |
| 1971 | * Look for each inode in memory and attempt to lock it, | 2002 | * For each inode in memory attempt to add it to the inode |
| 1972 | * we can be racing with flush and tail pushing here. | 2003 | * buffer and set it up for being staled on buffer IO |
| 1973 | * any inode we get the locks on, add to an array of | 2004 | * completion. This is safe as we've locked out tail pushing |
| 1974 | * inode items to process later. | 2005 | * and flushing by locking the buffer. |
| 1975 | * | 2006 | * |
| 1976 | * The get the buffer lock, we could beat a flush | 2007 | * We have already marked every inode that was part of a |
| 1977 | * or tail pushing thread to the lock here, in which | 2008 | * transaction stale above, which means there is no point in |
| 1978 | * case they will go looking for the inode buffer | 2009 | * even trying to lock them. |
| 1979 | * and fail, we need some other form of interlock | ||
| 1980 | * here. | ||
| 1981 | */ | 2010 | */ |
| 1982 | found = 0; | ||
| 1983 | for (i = 0; i < ninodes; i++) { | 2011 | for (i = 0; i < ninodes; i++) { |
| 1984 | read_lock(&pag->pag_ici_lock); | 2012 | read_lock(&pag->pag_ici_lock); |
| 1985 | ip = radix_tree_lookup(&pag->pag_ici_root, | 2013 | ip = radix_tree_lookup(&pag->pag_ici_root, |
| 1986 | XFS_INO_TO_AGINO(mp, (inum + i))); | 2014 | XFS_INO_TO_AGINO(mp, (inum + i))); |
| 1987 | 2015 | ||
| 1988 | /* Inode not in memory or we found it already, | 2016 | /* Inode not in memory or stale, nothing to do */ |
| 1989 | * nothing to do | ||
| 1990 | */ | ||
| 1991 | if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { | 2017 | if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { |
| 1992 | read_unlock(&pag->pag_ici_lock); | 2018 | read_unlock(&pag->pag_ici_lock); |
| 1993 | continue; | 2019 | continue; |
| 1994 | } | 2020 | } |
| 1995 | 2021 | ||
| 1996 | if (xfs_inode_clean(ip)) { | 2022 | /* don't try to lock/unlock the current inode */ |
| 1997 | read_unlock(&pag->pag_ici_lock); | 2023 | if (ip != free_ip && |
| 1998 | continue; | 2024 | !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { |
| 1999 | } | ||
| 2000 | |||
| 2001 | /* If we can get the locks then add it to the | ||
| 2002 | * list, otherwise by the time we get the bp lock | ||
| 2003 | * below it will already be attached to the | ||
| 2004 | * inode buffer. | ||
| 2005 | */ | ||
| 2006 | |||
| 2007 | /* This inode will already be locked - by us, lets | ||
| 2008 | * keep it that way. | ||
| 2009 | */ | ||
| 2010 | |||
| 2011 | if (ip == free_ip) { | ||
| 2012 | if (xfs_iflock_nowait(ip)) { | ||
| 2013 | xfs_iflags_set(ip, XFS_ISTALE); | ||
| 2014 | if (xfs_inode_clean(ip)) { | ||
| 2015 | xfs_ifunlock(ip); | ||
| 2016 | } else { | ||
| 2017 | ip_found[found++] = ip; | ||
| 2018 | } | ||
| 2019 | } | ||
| 2020 | read_unlock(&pag->pag_ici_lock); | 2025 | read_unlock(&pag->pag_ici_lock); |
| 2021 | continue; | 2026 | continue; |
| 2022 | } | 2027 | } |
| 2028 | read_unlock(&pag->pag_ici_lock); | ||
| 2023 | 2029 | ||
| 2024 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { | 2030 | if (!xfs_iflock_nowait(ip)) { |
| 2025 | if (xfs_iflock_nowait(ip)) { | 2031 | if (ip != free_ip) |
| 2026 | xfs_iflags_set(ip, XFS_ISTALE); | ||
| 2027 | |||
| 2028 | if (xfs_inode_clean(ip)) { | ||
| 2029 | xfs_ifunlock(ip); | ||
| 2030 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 2031 | } else { | ||
| 2032 | ip_found[found++] = ip; | ||
| 2033 | } | ||
| 2034 | } else { | ||
| 2035 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2032 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 2036 | } | 2033 | continue; |
| 2037 | } | 2034 | } |
| 2038 | read_unlock(&pag->pag_ici_lock); | ||
| 2039 | } | ||
| 2040 | 2035 | ||
| 2041 | bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, | 2036 | xfs_iflags_set(ip, XFS_ISTALE); |
| 2042 | mp->m_bsize * blks_per_cluster, | 2037 | if (xfs_inode_clean(ip)) { |
| 2043 | XBF_LOCK); | 2038 | ASSERT(ip != free_ip); |
| 2044 | 2039 | xfs_ifunlock(ip); | |
| 2045 | pre_flushed = 0; | 2040 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 2046 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); | 2041 | continue; |
| 2047 | while (lip) { | ||
| 2048 | if (lip->li_type == XFS_LI_INODE) { | ||
| 2049 | iip = (xfs_inode_log_item_t *)lip; | ||
| 2050 | ASSERT(iip->ili_logged == 1); | ||
| 2051 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; | ||
| 2052 | xfs_trans_ail_copy_lsn(mp->m_ail, | ||
| 2053 | &iip->ili_flush_lsn, | ||
| 2054 | &iip->ili_item.li_lsn); | ||
| 2055 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); | ||
| 2056 | pre_flushed++; | ||
| 2057 | } | 2042 | } |
| 2058 | lip = lip->li_bio_list; | ||
| 2059 | } | ||
| 2060 | 2043 | ||
| 2061 | for (i = 0; i < found; i++) { | ||
| 2062 | ip = ip_found[i]; | ||
| 2063 | iip = ip->i_itemp; | 2044 | iip = ip->i_itemp; |
| 2064 | |||
| 2065 | if (!iip) { | 2045 | if (!iip) { |
| 2046 | /* inode with unlogged changes only */ | ||
| 2047 | ASSERT(ip != free_ip); | ||
| 2066 | ip->i_update_core = 0; | 2048 | ip->i_update_core = 0; |
| 2067 | xfs_ifunlock(ip); | 2049 | xfs_ifunlock(ip); |
| 2068 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2050 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 2069 | continue; | 2051 | continue; |
| 2070 | } | 2052 | } |
| 2053 | found++; | ||
| 2071 | 2054 | ||
| 2072 | iip->ili_last_fields = iip->ili_format.ilf_fields; | 2055 | iip->ili_last_fields = iip->ili_format.ilf_fields; |
| 2073 | iip->ili_format.ilf_fields = 0; | 2056 | iip->ili_format.ilf_fields = 0; |
| @@ -2078,17 +2061,16 @@ xfs_ifree_cluster( | |||
| 2078 | xfs_buf_attach_iodone(bp, | 2061 | xfs_buf_attach_iodone(bp, |
| 2079 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 2062 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) |
| 2080 | xfs_istale_done, (xfs_log_item_t *)iip); | 2063 | xfs_istale_done, (xfs_log_item_t *)iip); |
| 2081 | if (ip != free_ip) { | 2064 | |
| 2065 | if (ip != free_ip) | ||
| 2082 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2066 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 2083 | } | ||
| 2084 | } | 2067 | } |
| 2085 | 2068 | ||
| 2086 | if (found || pre_flushed) | 2069 | if (found) |
| 2087 | xfs_trans_stale_inode_buf(tp, bp); | 2070 | xfs_trans_stale_inode_buf(tp, bp); |
| 2088 | xfs_trans_binval(tp, bp); | 2071 | xfs_trans_binval(tp, bp); |
| 2089 | } | 2072 | } |
| 2090 | 2073 | ||
| 2091 | kmem_free(ip_found); | ||
| 2092 | xfs_perag_put(pag); | 2074 | xfs_perag_put(pag); |
| 2093 | } | 2075 | } |
| 2094 | 2076 | ||
| @@ -2649,8 +2631,6 @@ xfs_iflush_cluster( | |||
| 2649 | int i; | 2631 | int i; |
| 2650 | 2632 | ||
| 2651 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); | 2633 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); |
| 2652 | ASSERT(pag->pagi_inodeok); | ||
| 2653 | ASSERT(pag->pag_ici_init); | ||
| 2654 | 2634 | ||
| 2655 | inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog; | 2635 | inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog; |
| 2656 | ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *); | 2636 | ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *); |
