diff options
| author | Ingo Molnar <mingo@elte.hu> | 2011-02-02 01:10:03 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2011-02-02 01:10:06 -0500 |
| commit | 8104a4775ad8a7863af0b898224b15aa708582db (patch) | |
| tree | 71380e4db36e9d91e521d0a98be74981e32a6700 /fs/xfs | |
| parent | f6bbc1daac964da551130dbf01809d3fbd178b2d (diff) | |
| parent | ebf53826e105f488f4f628703a108e98940d1dc5 (diff) | |
Merge commit 'v2.6.38-rc3' into perf/core
Merge reason: Pick up latest fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 20 | ||||
| -rw-r--r-- | fs/xfs/quota/xfs_qm.c | 46 | ||||
| -rw-r--r-- | fs/xfs/xfs_alloc.h | 16 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 61 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf_item.c | 12 | ||||
| -rw-r--r-- | fs/xfs/xfs_extfree_item.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_log_cil.c | 15 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans.c | 41 |
10 files changed, 152 insertions, 71 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index b06ede1d0bed..f5e2a19e0f8e 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
| @@ -985,10 +985,22 @@ xfs_ioctl_setattr( | |||
| 985 | 985 | ||
| 986 | /* | 986 | /* |
| 987 | * Extent size must be a multiple of the appropriate block | 987 | * Extent size must be a multiple of the appropriate block |
| 988 | * size, if set at all. | 988 | * size, if set at all. It must also be smaller than the |
| 989 | * maximum extent size supported by the filesystem. | ||
| 990 | * | ||
| 991 | * Also, for non-realtime files, limit the extent size hint to | ||
| 992 | * half the size of the AGs in the filesystem so alignment | ||
| 993 | * doesn't result in extents larger than an AG. | ||
| 989 | */ | 994 | */ |
| 990 | if (fa->fsx_extsize != 0) { | 995 | if (fa->fsx_extsize != 0) { |
| 991 | xfs_extlen_t size; | 996 | xfs_extlen_t size; |
| 997 | xfs_fsblock_t extsize_fsb; | ||
| 998 | |||
| 999 | extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize); | ||
| 1000 | if (extsize_fsb > MAXEXTLEN) { | ||
| 1001 | code = XFS_ERROR(EINVAL); | ||
| 1002 | goto error_return; | ||
| 1003 | } | ||
| 992 | 1004 | ||
| 993 | if (XFS_IS_REALTIME_INODE(ip) || | 1005 | if (XFS_IS_REALTIME_INODE(ip) || |
| 994 | ((mask & FSX_XFLAGS) && | 1006 | ((mask & FSX_XFLAGS) && |
| @@ -997,6 +1009,10 @@ xfs_ioctl_setattr( | |||
| 997 | mp->m_sb.sb_blocklog; | 1009 | mp->m_sb.sb_blocklog; |
| 998 | } else { | 1010 | } else { |
| 999 | size = mp->m_sb.sb_blocksize; | 1011 | size = mp->m_sb.sb_blocksize; |
| 1012 | if (extsize_fsb > mp->m_sb.sb_agblocks / 2) { | ||
| 1013 | code = XFS_ERROR(EINVAL); | ||
| 1014 | goto error_return; | ||
| 1015 | } | ||
| 1000 | } | 1016 | } |
| 1001 | 1017 | ||
| 1002 | if (fa->fsx_extsize % size) { | 1018 | if (fa->fsx_extsize % size) { |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index f8e854b4fde8..206a2815ced6 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
| @@ -1863,12 +1863,14 @@ xfs_qm_dqreclaim_one(void) | |||
| 1863 | xfs_dquot_t *dqpout; | 1863 | xfs_dquot_t *dqpout; |
| 1864 | xfs_dquot_t *dqp; | 1864 | xfs_dquot_t *dqp; |
| 1865 | int restarts; | 1865 | int restarts; |
| 1866 | int startagain; | ||
| 1866 | 1867 | ||
| 1867 | restarts = 0; | 1868 | restarts = 0; |
| 1868 | dqpout = NULL; | 1869 | dqpout = NULL; |
| 1869 | 1870 | ||
| 1870 | /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ | 1871 | /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ |
| 1871 | startagain: | 1872 | again: |
| 1873 | startagain = 0; | ||
| 1872 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | 1874 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); |
| 1873 | 1875 | ||
| 1874 | list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { | 1876 | list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { |
| @@ -1885,13 +1887,10 @@ startagain: | |||
| 1885 | ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); | 1887 | ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); |
| 1886 | 1888 | ||
| 1887 | trace_xfs_dqreclaim_want(dqp); | 1889 | trace_xfs_dqreclaim_want(dqp); |
| 1888 | |||
| 1889 | xfs_dqunlock(dqp); | ||
| 1890 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
| 1891 | if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | ||
| 1892 | return NULL; | ||
| 1893 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); | 1890 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); |
| 1894 | goto startagain; | 1891 | restarts++; |
| 1892 | startagain = 1; | ||
| 1893 | goto dqunlock; | ||
| 1895 | } | 1894 | } |
| 1896 | 1895 | ||
| 1897 | /* | 1896 | /* |
| @@ -1906,23 +1905,20 @@ startagain: | |||
| 1906 | ASSERT(list_empty(&dqp->q_mplist)); | 1905 | ASSERT(list_empty(&dqp->q_mplist)); |
| 1907 | list_del_init(&dqp->q_freelist); | 1906 | list_del_init(&dqp->q_freelist); |
| 1908 | xfs_Gqm->qm_dqfrlist_cnt--; | 1907 | xfs_Gqm->qm_dqfrlist_cnt--; |
| 1909 | xfs_dqunlock(dqp); | ||
| 1910 | dqpout = dqp; | 1908 | dqpout = dqp; |
| 1911 | XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); | 1909 | XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); |
| 1912 | break; | 1910 | goto dqunlock; |
| 1913 | } | 1911 | } |
| 1914 | 1912 | ||
| 1915 | ASSERT(dqp->q_hash); | 1913 | ASSERT(dqp->q_hash); |
| 1916 | ASSERT(!list_empty(&dqp->q_mplist)); | 1914 | ASSERT(!list_empty(&dqp->q_mplist)); |
| 1917 | 1915 | ||
| 1918 | /* | 1916 | /* |
| 1919 | * Try to grab the flush lock. If this dquot is in the process of | 1917 | * Try to grab the flush lock. If this dquot is in the process |
| 1920 | * getting flushed to disk, we don't want to reclaim it. | 1918 | * of getting flushed to disk, we don't want to reclaim it. |
| 1921 | */ | 1919 | */ |
| 1922 | if (!xfs_dqflock_nowait(dqp)) { | 1920 | if (!xfs_dqflock_nowait(dqp)) |
| 1923 | xfs_dqunlock(dqp); | 1921 | goto dqunlock; |
| 1924 | continue; | ||
| 1925 | } | ||
| 1926 | 1922 | ||
| 1927 | /* | 1923 | /* |
| 1928 | * We have the flush lock so we know that this is not in the | 1924 | * We have the flush lock so we know that this is not in the |
| @@ -1944,8 +1940,7 @@ startagain: | |||
| 1944 | xfs_fs_cmn_err(CE_WARN, mp, | 1940 | xfs_fs_cmn_err(CE_WARN, mp, |
| 1945 | "xfs_qm_dqreclaim: dquot %p flush failed", dqp); | 1941 | "xfs_qm_dqreclaim: dquot %p flush failed", dqp); |
| 1946 | } | 1942 | } |
| 1947 | xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ | 1943 | goto dqunlock; |
| 1948 | continue; | ||
| 1949 | } | 1944 | } |
| 1950 | 1945 | ||
| 1951 | /* | 1946 | /* |
| @@ -1967,13 +1962,8 @@ startagain: | |||
| 1967 | */ | 1962 | */ |
| 1968 | if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { | 1963 | if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { |
| 1969 | restarts++; | 1964 | restarts++; |
| 1970 | mutex_unlock(&dqp->q_hash->qh_lock); | 1965 | startagain = 1; |
| 1971 | xfs_dqfunlock(dqp); | 1966 | goto qhunlock; |
| 1972 | xfs_dqunlock(dqp); | ||
| 1973 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
| 1974 | if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS) | ||
| 1975 | return NULL; | ||
| 1976 | goto startagain; | ||
| 1977 | } | 1967 | } |
| 1978 | 1968 | ||
| 1979 | ASSERT(dqp->q_nrefs == 0); | 1969 | ASSERT(dqp->q_nrefs == 0); |
| @@ -1986,14 +1976,20 @@ startagain: | |||
| 1986 | xfs_Gqm->qm_dqfrlist_cnt--; | 1976 | xfs_Gqm->qm_dqfrlist_cnt--; |
| 1987 | dqpout = dqp; | 1977 | dqpout = dqp; |
| 1988 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); | 1978 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); |
| 1979 | qhunlock: | ||
| 1989 | mutex_unlock(&dqp->q_hash->qh_lock); | 1980 | mutex_unlock(&dqp->q_hash->qh_lock); |
| 1990 | dqfunlock: | 1981 | dqfunlock: |
| 1991 | xfs_dqfunlock(dqp); | 1982 | xfs_dqfunlock(dqp); |
| 1983 | dqunlock: | ||
| 1992 | xfs_dqunlock(dqp); | 1984 | xfs_dqunlock(dqp); |
| 1993 | if (dqpout) | 1985 | if (dqpout) |
| 1994 | break; | 1986 | break; |
| 1995 | if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | 1987 | if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) |
| 1996 | return NULL; | 1988 | break; |
| 1989 | if (startagain) { | ||
| 1990 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
| 1991 | goto again; | ||
| 1992 | } | ||
| 1997 | } | 1993 | } |
| 1998 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 1994 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); |
| 1999 | return dqpout; | 1995 | return dqpout; |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 0ab56b32c7eb..d0b3bc72005b 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
| @@ -75,6 +75,22 @@ typedef unsigned int xfs_alloctype_t; | |||
| 75 | #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) | 75 | #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) |
| 76 | 76 | ||
| 77 | /* | 77 | /* |
| 78 | * When deciding how much space to allocate out of an AG, we limit the | ||
| 79 | * allocation maximum size to the size the AG. However, we cannot use all the | ||
| 80 | * blocks in the AG - some are permanently used by metadata. These | ||
| 81 | * blocks are generally: | ||
| 82 | * - the AG superblock, AGF, AGI and AGFL | ||
| 83 | * - the AGF (bno and cnt) and AGI btree root blocks | ||
| 84 | * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits | ||
| 85 | * | ||
| 86 | * The AG headers are sector sized, so the amount of space they take up is | ||
| 87 | * dependent on filesystem geometry. The others are all single blocks. | ||
| 88 | */ | ||
| 89 | #define XFS_ALLOC_AG_MAX_USABLE(mp) \ | ||
| 90 | ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) | ||
| 91 | |||
| 92 | |||
| 93 | /* | ||
| 78 | * Argument structure for xfs_alloc routines. | 94 | * Argument structure for xfs_alloc routines. |
| 79 | * This is turned into a structure to avoid having 20 arguments passed | 95 | * This is turned into a structure to avoid having 20 arguments passed |
| 80 | * down several levels of the stack. | 96 | * down several levels of the stack. |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4111cd3966c7..dc3afd7739ff 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -1038,17 +1038,34 @@ xfs_bmap_add_extent_delay_real( | |||
| 1038 | * Filling in the middle part of a previous delayed allocation. | 1038 | * Filling in the middle part of a previous delayed allocation. |
| 1039 | * Contiguity is impossible here. | 1039 | * Contiguity is impossible here. |
| 1040 | * This case is avoided almost all the time. | 1040 | * This case is avoided almost all the time. |
| 1041 | * | ||
| 1042 | * We start with a delayed allocation: | ||
| 1043 | * | ||
| 1044 | * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+ | ||
| 1045 | * PREV @ idx | ||
| 1046 | * | ||
| 1047 | * and we are allocating: | ||
| 1048 | * +rrrrrrrrrrrrrrrrr+ | ||
| 1049 | * new | ||
| 1050 | * | ||
| 1051 | * and we set it up for insertion as: | ||
| 1052 | * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+ | ||
| 1053 | * new | ||
| 1054 | * PREV @ idx LEFT RIGHT | ||
| 1055 | * inserted at idx + 1 | ||
| 1041 | */ | 1056 | */ |
| 1042 | temp = new->br_startoff - PREV.br_startoff; | 1057 | temp = new->br_startoff - PREV.br_startoff; |
| 1043 | trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); | ||
| 1044 | xfs_bmbt_set_blockcount(ep, temp); | ||
| 1045 | r[0] = *new; | ||
| 1046 | r[1].br_state = PREV.br_state; | ||
| 1047 | r[1].br_startblock = 0; | ||
| 1048 | r[1].br_startoff = new_endoff; | ||
| 1049 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; | 1058 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; |
| 1050 | r[1].br_blockcount = temp2; | 1059 | trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); |
| 1051 | xfs_iext_insert(ip, idx + 1, 2, &r[0], state); | 1060 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ |
| 1061 | LEFT = *new; | ||
| 1062 | RIGHT.br_state = PREV.br_state; | ||
| 1063 | RIGHT.br_startblock = nullstartblock( | ||
| 1064 | (int)xfs_bmap_worst_indlen(ip, temp2)); | ||
| 1065 | RIGHT.br_startoff = new_endoff; | ||
| 1066 | RIGHT.br_blockcount = temp2; | ||
| 1067 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ | ||
| 1068 | xfs_iext_insert(ip, idx + 1, 2, &LEFT, state); | ||
| 1052 | ip->i_df.if_lastex = idx + 1; | 1069 | ip->i_df.if_lastex = idx + 1; |
| 1053 | ip->i_d.di_nextents++; | 1070 | ip->i_d.di_nextents++; |
| 1054 | if (cur == NULL) | 1071 | if (cur == NULL) |
| @@ -2430,7 +2447,7 @@ xfs_bmap_btalloc_nullfb( | |||
| 2430 | startag = ag = 0; | 2447 | startag = ag = 0; |
| 2431 | 2448 | ||
| 2432 | pag = xfs_perag_get(mp, ag); | 2449 | pag = xfs_perag_get(mp, ag); |
| 2433 | while (*blen < ap->alen) { | 2450 | while (*blen < args->maxlen) { |
| 2434 | if (!pag->pagf_init) { | 2451 | if (!pag->pagf_init) { |
| 2435 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 2452 | error = xfs_alloc_pagf_init(mp, args->tp, ag, |
| 2436 | XFS_ALLOC_FLAG_TRYLOCK); | 2453 | XFS_ALLOC_FLAG_TRYLOCK); |
| @@ -2452,7 +2469,7 @@ xfs_bmap_btalloc_nullfb( | |||
| 2452 | notinit = 1; | 2469 | notinit = 1; |
| 2453 | 2470 | ||
| 2454 | if (xfs_inode_is_filestream(ap->ip)) { | 2471 | if (xfs_inode_is_filestream(ap->ip)) { |
| 2455 | if (*blen >= ap->alen) | 2472 | if (*blen >= args->maxlen) |
| 2456 | break; | 2473 | break; |
| 2457 | 2474 | ||
| 2458 | if (ap->userdata) { | 2475 | if (ap->userdata) { |
| @@ -2498,14 +2515,14 @@ xfs_bmap_btalloc_nullfb( | |||
| 2498 | * If the best seen length is less than the request | 2515 | * If the best seen length is less than the request |
| 2499 | * length, use the best as the minimum. | 2516 | * length, use the best as the minimum. |
| 2500 | */ | 2517 | */ |
| 2501 | else if (*blen < ap->alen) | 2518 | else if (*blen < args->maxlen) |
| 2502 | args->minlen = *blen; | 2519 | args->minlen = *blen; |
| 2503 | /* | 2520 | /* |
| 2504 | * Otherwise we've seen an extent as big as alen, | 2521 | * Otherwise we've seen an extent as big as maxlen, |
| 2505 | * use that as the minimum. | 2522 | * use that as the minimum. |
| 2506 | */ | 2523 | */ |
| 2507 | else | 2524 | else |
| 2508 | args->minlen = ap->alen; | 2525 | args->minlen = args->maxlen; |
| 2509 | 2526 | ||
| 2510 | /* | 2527 | /* |
| 2511 | * set the failure fallback case to look in the selected | 2528 | * set the failure fallback case to look in the selected |
| @@ -2573,7 +2590,9 @@ xfs_bmap_btalloc( | |||
| 2573 | args.tp = ap->tp; | 2590 | args.tp = ap->tp; |
| 2574 | args.mp = mp; | 2591 | args.mp = mp; |
| 2575 | args.fsbno = ap->rval; | 2592 | args.fsbno = ap->rval; |
| 2576 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); | 2593 | |
| 2594 | /* Trim the allocation back to the maximum an AG can fit. */ | ||
| 2595 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | ||
| 2577 | args.firstblock = ap->firstblock; | 2596 | args.firstblock = ap->firstblock; |
| 2578 | blen = 0; | 2597 | blen = 0; |
| 2579 | if (nullfb) { | 2598 | if (nullfb) { |
| @@ -2621,7 +2640,7 @@ xfs_bmap_btalloc( | |||
| 2621 | /* | 2640 | /* |
| 2622 | * Adjust for alignment | 2641 | * Adjust for alignment |
| 2623 | */ | 2642 | */ |
| 2624 | if (blen > args.alignment && blen <= ap->alen) | 2643 | if (blen > args.alignment && blen <= args.maxlen) |
| 2625 | args.minlen = blen - args.alignment; | 2644 | args.minlen = blen - args.alignment; |
| 2626 | args.minalignslop = 0; | 2645 | args.minalignslop = 0; |
| 2627 | } else { | 2646 | } else { |
| @@ -2640,7 +2659,7 @@ xfs_bmap_btalloc( | |||
| 2640 | * of minlen+alignment+slop doesn't go up | 2659 | * of minlen+alignment+slop doesn't go up |
| 2641 | * between the calls. | 2660 | * between the calls. |
| 2642 | */ | 2661 | */ |
| 2643 | if (blen > mp->m_dalign && blen <= ap->alen) | 2662 | if (blen > mp->m_dalign && blen <= args.maxlen) |
| 2644 | nextminlen = blen - mp->m_dalign; | 2663 | nextminlen = blen - mp->m_dalign; |
| 2645 | else | 2664 | else |
| 2646 | nextminlen = args.minlen; | 2665 | nextminlen = args.minlen; |
| @@ -4485,6 +4504,16 @@ xfs_bmapi( | |||
| 4485 | /* Figure out the extent size, adjust alen */ | 4504 | /* Figure out the extent size, adjust alen */ |
| 4486 | extsz = xfs_get_extsz_hint(ip); | 4505 | extsz = xfs_get_extsz_hint(ip); |
| 4487 | if (extsz) { | 4506 | if (extsz) { |
| 4507 | /* | ||
| 4508 | * make sure we don't exceed a single | ||
| 4509 | * extent length when we align the | ||
| 4510 | * extent by reducing length we are | ||
| 4511 | * going to allocate by the maximum | ||
| 4512 | * amount extent size aligment may | ||
| 4513 | * require. | ||
| 4514 | */ | ||
| 4515 | alen = XFS_FILBLKS_MIN(len, | ||
| 4516 | MAXEXTLEN - (2 * extsz - 1)); | ||
| 4488 | error = xfs_bmap_extsize_align(mp, | 4517 | error = xfs_bmap_extsize_align(mp, |
| 4489 | &got, &prev, extsz, | 4518 | &got, &prev, extsz, |
| 4490 | rt, eof, | 4519 | rt, eof, |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 98c6f73b6752..6f8c21ce0d6d 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
| @@ -427,13 +427,15 @@ xfs_buf_item_unpin( | |||
| 427 | 427 | ||
| 428 | if (remove) { | 428 | if (remove) { |
| 429 | /* | 429 | /* |
| 430 | * We have to remove the log item from the transaction | 430 | * If we are in a transaction context, we have to |
| 431 | * as we are about to release our reference to the | 431 | * remove the log item from the transaction as we are |
| 432 | * buffer. If we don't, the unlock that occurs later | 432 | * about to release our reference to the buffer. If we |
| 433 | * in xfs_trans_uncommit() will ry to reference the | 433 | * don't, the unlock that occurs later in |
| 434 | * xfs_trans_uncommit() will try to reference the | ||
| 434 | * buffer which we no longer have a hold on. | 435 | * buffer which we no longer have a hold on. |
| 435 | */ | 436 | */ |
| 436 | xfs_trans_del_item(lip); | 437 | if (lip->li_desc) |
| 438 | xfs_trans_del_item(lip); | ||
| 437 | 439 | ||
| 438 | /* | 440 | /* |
| 439 | * Since the transaction no longer refers to the buffer, | 441 | * Since the transaction no longer refers to the buffer, |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 75f2ef60e579..d22e62623437 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
| @@ -138,7 +138,8 @@ xfs_efi_item_unpin( | |||
| 138 | 138 | ||
| 139 | if (remove) { | 139 | if (remove) { |
| 140 | ASSERT(!(lip->li_flags & XFS_LI_IN_AIL)); | 140 | ASSERT(!(lip->li_flags & XFS_LI_IN_AIL)); |
| 141 | xfs_trans_del_item(lip); | 141 | if (lip->li_desc) |
| 142 | xfs_trans_del_item(lip); | ||
| 142 | xfs_efi_item_free(efip); | 143 | xfs_efi_item_free(efip); |
| 143 | return; | 144 | return; |
| 144 | } | 145 | } |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 55582bd66659..8a0f044750c3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -337,7 +337,12 @@ xfs_iomap_prealloc_size( | |||
| 337 | int shift = 0; | 337 | int shift = 0; |
| 338 | int64_t freesp; | 338 | int64_t freesp; |
| 339 | 339 | ||
| 340 | alloc_blocks = XFS_B_TO_FSB(mp, ip->i_size); | 340 | /* |
| 341 | * rounddown_pow_of_two() returns an undefined result | ||
| 342 | * if we pass in alloc_blocks = 0. Hence the "+ 1" to | ||
| 343 | * ensure we always pass in a non-zero value. | ||
| 344 | */ | ||
| 345 | alloc_blocks = XFS_B_TO_FSB(mp, ip->i_size) + 1; | ||
| 341 | alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN, | 346 | alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN, |
| 342 | rounddown_pow_of_two(alloc_blocks)); | 347 | rounddown_pow_of_two(alloc_blocks)); |
| 343 | 348 | ||
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 916eb7db14d9..3bd3291ef8d2 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
| @@ -191,7 +191,7 @@ void xfs_log_ticket_put(struct xlog_ticket *ticket); | |||
| 191 | 191 | ||
| 192 | xlog_tid_t xfs_log_get_trans_ident(struct xfs_trans *tp); | 192 | xlog_tid_t xfs_log_get_trans_ident(struct xfs_trans *tp); |
| 193 | 193 | ||
| 194 | int xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, | 194 | void xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, |
| 195 | struct xfs_log_vec *log_vector, | 195 | struct xfs_log_vec *log_vector, |
| 196 | xfs_lsn_t *commit_lsn, int flags); | 196 | xfs_lsn_t *commit_lsn, int flags); |
| 197 | bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip); | 197 | bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip); |
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 9dc8125d04e5..9ca59be08977 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
| @@ -543,7 +543,7 @@ xlog_cil_push( | |||
| 543 | 543 | ||
| 544 | error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL, 0); | 544 | error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL, 0); |
| 545 | if (error) | 545 | if (error) |
| 546 | goto out_abort; | 546 | goto out_abort_free_ticket; |
| 547 | 547 | ||
| 548 | /* | 548 | /* |
| 549 | * now that we've written the checkpoint into the log, strictly | 549 | * now that we've written the checkpoint into the log, strictly |
| @@ -569,8 +569,9 @@ restart: | |||
| 569 | } | 569 | } |
| 570 | spin_unlock(&cil->xc_cil_lock); | 570 | spin_unlock(&cil->xc_cil_lock); |
| 571 | 571 | ||
| 572 | /* xfs_log_done always frees the ticket on error. */ | ||
| 572 | commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0); | 573 | commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0); |
| 573 | if (error || commit_lsn == -1) | 574 | if (commit_lsn == -1) |
| 574 | goto out_abort; | 575 | goto out_abort; |
| 575 | 576 | ||
| 576 | /* attach all the transactions w/ busy extents to iclog */ | 577 | /* attach all the transactions w/ busy extents to iclog */ |
| @@ -600,6 +601,8 @@ out_free_ticket: | |||
| 600 | kmem_free(new_ctx); | 601 | kmem_free(new_ctx); |
| 601 | return 0; | 602 | return 0; |
| 602 | 603 | ||
| 604 | out_abort_free_ticket: | ||
| 605 | xfs_log_ticket_put(tic); | ||
| 603 | out_abort: | 606 | out_abort: |
| 604 | xlog_cil_committed(ctx, XFS_LI_ABORTED); | 607 | xlog_cil_committed(ctx, XFS_LI_ABORTED); |
| 605 | return XFS_ERROR(EIO); | 608 | return XFS_ERROR(EIO); |
| @@ -622,7 +625,7 @@ out_abort: | |||
| 622 | * background commit, returns without it held once background commits are | 625 | * background commit, returns without it held once background commits are |
| 623 | * allowed again. | 626 | * allowed again. |
| 624 | */ | 627 | */ |
| 625 | int | 628 | void |
| 626 | xfs_log_commit_cil( | 629 | xfs_log_commit_cil( |
| 627 | struct xfs_mount *mp, | 630 | struct xfs_mount *mp, |
| 628 | struct xfs_trans *tp, | 631 | struct xfs_trans *tp, |
| @@ -637,11 +640,6 @@ xfs_log_commit_cil( | |||
| 637 | if (flags & XFS_TRANS_RELEASE_LOG_RES) | 640 | if (flags & XFS_TRANS_RELEASE_LOG_RES) |
| 638 | log_flags = XFS_LOG_REL_PERM_RESERV; | 641 | log_flags = XFS_LOG_REL_PERM_RESERV; |
| 639 | 642 | ||
| 640 | if (XLOG_FORCED_SHUTDOWN(log)) { | ||
| 641 | xlog_cil_free_logvec(log_vector); | ||
| 642 | return XFS_ERROR(EIO); | ||
| 643 | } | ||
| 644 | |||
| 645 | /* | 643 | /* |
| 646 | * do all the hard work of formatting items (including memory | 644 | * do all the hard work of formatting items (including memory |
| 647 | * allocation) outside the CIL context lock. This prevents stalling CIL | 645 | * allocation) outside the CIL context lock. This prevents stalling CIL |
| @@ -701,7 +699,6 @@ xfs_log_commit_cil( | |||
| 701 | */ | 699 | */ |
| 702 | if (push) | 700 | if (push) |
| 703 | xlog_cil_push(log, 0); | 701 | xlog_cil_push(log, 0); |
| 704 | return 0; | ||
| 705 | } | 702 | } |
| 706 | 703 | ||
| 707 | /* | 704 | /* |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 33dbc4e0ad62..76922793f64f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
| @@ -1446,6 +1446,14 @@ xfs_log_item_batch_insert( | |||
| 1446 | * Bulk operation version of xfs_trans_committed that takes a log vector of | 1446 | * Bulk operation version of xfs_trans_committed that takes a log vector of |
| 1447 | * items to insert into the AIL. This uses bulk AIL insertion techniques to | 1447 | * items to insert into the AIL. This uses bulk AIL insertion techniques to |
| 1448 | * minimise lock traffic. | 1448 | * minimise lock traffic. |
| 1449 | * | ||
| 1450 | * If we are called with the aborted flag set, it is because a log write during | ||
| 1451 | * a CIL checkpoint commit has failed. In this case, all the items in the | ||
| 1452 | * checkpoint have already gone through IOP_COMMITED and IOP_UNLOCK, which | ||
| 1453 | * means that checkpoint commit abort handling is treated exactly the same | ||
| 1454 | * as an iclog write error even though we haven't started any IO yet. Hence in | ||
| 1455 | * this case all we need to do is IOP_COMMITTED processing, followed by an | ||
| 1456 | * IOP_UNPIN(aborted) call. | ||
| 1449 | */ | 1457 | */ |
| 1450 | void | 1458 | void |
| 1451 | xfs_trans_committed_bulk( | 1459 | xfs_trans_committed_bulk( |
| @@ -1472,6 +1480,16 @@ xfs_trans_committed_bulk( | |||
| 1472 | if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) | 1480 | if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) |
| 1473 | continue; | 1481 | continue; |
| 1474 | 1482 | ||
| 1483 | /* | ||
| 1484 | * if we are aborting the operation, no point in inserting the | ||
| 1485 | * object into the AIL as we are in a shutdown situation. | ||
| 1486 | */ | ||
| 1487 | if (aborted) { | ||
| 1488 | ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount)); | ||
| 1489 | IOP_UNPIN(lip, 1); | ||
| 1490 | continue; | ||
| 1491 | } | ||
| 1492 | |||
| 1475 | if (item_lsn != commit_lsn) { | 1493 | if (item_lsn != commit_lsn) { |
| 1476 | 1494 | ||
| 1477 | /* | 1495 | /* |
| @@ -1503,20 +1521,24 @@ xfs_trans_committed_bulk( | |||
| 1503 | } | 1521 | } |
| 1504 | 1522 | ||
| 1505 | /* | 1523 | /* |
| 1506 | * Called from the trans_commit code when we notice that | 1524 | * Called from the trans_commit code when we notice that the filesystem is in |
| 1507 | * the filesystem is in the middle of a forced shutdown. | 1525 | * the middle of a forced shutdown. |
| 1526 | * | ||
| 1527 | * When we are called here, we have already pinned all the items in the | ||
| 1528 | * transaction. However, neither IOP_COMMITTING or IOP_UNLOCK has been called | ||
| 1529 | * so we can simply walk the items in the transaction, unpin them with an abort | ||
| 1530 | * flag and then free the items. Note that unpinning the items can result in | ||
| 1531 | * them being freed immediately, so we need to use a safe list traversal method | ||
| 1532 | * here. | ||
| 1508 | */ | 1533 | */ |
| 1509 | STATIC void | 1534 | STATIC void |
| 1510 | xfs_trans_uncommit( | 1535 | xfs_trans_uncommit( |
| 1511 | struct xfs_trans *tp, | 1536 | struct xfs_trans *tp, |
| 1512 | uint flags) | 1537 | uint flags) |
| 1513 | { | 1538 | { |
| 1514 | struct xfs_log_item_desc *lidp; | 1539 | struct xfs_log_item_desc *lidp, *n; |
| 1515 | 1540 | ||
| 1516 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { | 1541 | list_for_each_entry_safe(lidp, n, &tp->t_items, lid_trans) { |
| 1517 | /* | ||
| 1518 | * Unpin all but those that aren't dirty. | ||
| 1519 | */ | ||
| 1520 | if (lidp->lid_flags & XFS_LID_DIRTY) | 1542 | if (lidp->lid_flags & XFS_LID_DIRTY) |
| 1521 | IOP_UNPIN(lidp->lid_item, 1); | 1543 | IOP_UNPIN(lidp->lid_item, 1); |
| 1522 | } | 1544 | } |
| @@ -1733,7 +1755,6 @@ xfs_trans_commit_cil( | |||
| 1733 | int flags) | 1755 | int flags) |
| 1734 | { | 1756 | { |
| 1735 | struct xfs_log_vec *log_vector; | 1757 | struct xfs_log_vec *log_vector; |
| 1736 | int error; | ||
| 1737 | 1758 | ||
| 1738 | /* | 1759 | /* |
| 1739 | * Get each log item to allocate a vector structure for | 1760 | * Get each log item to allocate a vector structure for |
| @@ -1744,9 +1765,7 @@ xfs_trans_commit_cil( | |||
| 1744 | if (!log_vector) | 1765 | if (!log_vector) |
| 1745 | return ENOMEM; | 1766 | return ENOMEM; |
| 1746 | 1767 | ||
| 1747 | error = xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); | 1768 | xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); |
| 1748 | if (error) | ||
| 1749 | return error; | ||
| 1750 | 1769 | ||
| 1751 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 1770 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
| 1752 | xfs_trans_free(tp); | 1771 | xfs_trans_free(tp); |
