aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2008-04-09 22:21:18 -0400
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-04-17 21:58:17 -0400
commite5720eec0548c08943d759e39db0388d8fe59287 (patch)
treee38b474f0dbac30aee7141878953223a2a588c69
parent3c1e2bbe5bcdcd435510a05eb121fa74b848e24f (diff)
[XFS] Propagate errors from xfs_trans_commit().
xfs_trans_commit() can return errors when there are problems in the transaction subsystem. They are indicative that the entire transaction may be incomplete, and hence the error should be propagated as there is a good possibility that there is something fatally wrong in the filesystem. Catch and propagate or warn about commit errors in the places where they are currently ignored. SGI-PV: 980084 SGI-Modid: xfs-linux-melb:xfs-kern:30795a Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Niv Sardi <xaiki@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/quota/xfs_qm.c4
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c4
-rw-r--r--fs/xfs/xfs_inode.c52
-rw-r--r--fs/xfs/xfs_log_recover.c27
-rw-r--r--fs/xfs/xfs_mount.c35
-rw-r--r--fs/xfs/xfs_rtalloc.c38
-rw-r--r--fs/xfs/xfs_vfsops.c15
-rw-r--r--fs/xfs/xfs_vnodeops.c28
8 files changed, 115 insertions, 88 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 6aa3445cabad..40ea56409561 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -2392,9 +2392,9 @@ xfs_qm_write_sb_changes(
2392 } 2392 }
2393 2393
2394 xfs_mod_sb(tp, flags); 2394 xfs_mod_sb(tp, flags);
2395 (void) xfs_trans_commit(tp, 0); 2395 error = xfs_trans_commit(tp, 0);
2396 2396
2397 return 0; 2397 return error;
2398} 2398}
2399 2399
2400 2400
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 556018d24cad..8342823dbdc3 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -734,12 +734,12 @@ xfs_qm_scall_setqlim(
734 xfs_trans_log_dquot(tp, dqp); 734 xfs_trans_log_dquot(tp, dqp);
735 735
736 xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT"); 736 xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
737 xfs_trans_commit(tp, 0); 737 error = xfs_trans_commit(tp, 0);
738 xfs_qm_dqprint(dqp); 738 xfs_qm_dqprint(dqp);
739 xfs_qm_dqrele(dqp); 739 xfs_qm_dqrele(dqp);
740 mutex_unlock(&(XFS_QI_QOFFLOCK(mp))); 740 mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
741 741
742 return (0); 742 return error;
743} 743}
744 744
745STATIC int 745STATIC int
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index d7514f8317df..63e66890f063 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1699,33 +1699,16 @@ xfs_itruncate_finish(
1699 * blocks in the file system, but oh well. 1699 * blocks in the file system, but oh well.
1700 */ 1700 */
1701 xfs_bmap_cancel(&free_list); 1701 xfs_bmap_cancel(&free_list);
1702 if (committed) { 1702 if (committed)
1703 /* 1703 goto error_join;
1704 * If the passed in transaction committed
1705 * in xfs_bmap_finish(), then we want to
1706 * add the inode to this one before returning.
1707 * This keeps things simple for the higher
1708 * level code, because it always knows that
1709 * the inode is locked and held in the
1710 * transaction that returns to it whether
1711 * errors occur or not. We don't mark the
1712 * inode dirty so that this transaction can
1713 * be easily aborted if possible.
1714 */
1715 xfs_trans_ijoin(ntp, ip,
1716 XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1717 xfs_trans_ihold(ntp, ip);
1718 }
1719 return error; 1704 return error;
1720 } 1705 }
1721 1706
1722 if (committed) { 1707 if (committed) {
1723 /* 1708 /*
1724 * The first xact was committed, 1709 * The first xact was committed, so add the inode to
1725 * so add the inode to the new one. 1710 * the new one. Mark it dirty so it will be logged and
1726 * Mark it dirty so it will be logged 1711 * moved forward in the log as part of every commit.
1727 * and moved forward in the log as
1728 * part of every commit.
1729 */ 1712 */
1730 xfs_trans_ijoin(ntp, ip, 1713 xfs_trans_ijoin(ntp, ip,
1731 XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 1714 XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1733,19 +1716,16 @@ xfs_itruncate_finish(
1733 xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE); 1716 xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
1734 } 1717 }
1735 ntp = xfs_trans_dup(ntp); 1718 ntp = xfs_trans_dup(ntp);
1736 (void) xfs_trans_commit(*tp, 0); 1719 error = xfs_trans_commit(*tp, 0);
1737 *tp = ntp; 1720 *tp = ntp;
1721 if (error)
1722 goto error_join;
1738 error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 1723 error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
1739 XFS_TRANS_PERM_LOG_RES, 1724 XFS_TRANS_PERM_LOG_RES,
1740 XFS_ITRUNCATE_LOG_COUNT); 1725 XFS_ITRUNCATE_LOG_COUNT);
1741 /*
1742 * Add the inode being truncated to the next chained
1743 * transaction.
1744 */
1745 xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1746 xfs_trans_ihold(ntp, ip);
1747 if (error) 1726 if (error)
1748 return (error); 1727 goto error_join;
1728
1749 } 1729 }
1750 /* 1730 /*
1751 * Only update the size in the case of the data fork, but 1731 * Only update the size in the case of the data fork, but
@@ -1777,6 +1757,18 @@ xfs_itruncate_finish(
1777 (ip->i_d.di_nextents == 0)); 1757 (ip->i_d.di_nextents == 0));
1778 xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0); 1758 xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0);
1779 return 0; 1759 return 0;
1760
1761error_join:
1762 /*
1763 * Add the inode being truncated to the next chained transaction. This
1764 * keeps things simple for the higher level code, because it always
1765 * knows that the inode is locked and held in the transaction that
1766 * returns to it whether errors occur or not. We don't mark the inode
1767 * dirty so that this transaction can be easily aborted if possible.
1768 */
1769 xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
1770 xfs_trans_ihold(ntp, ip);
1771 return error;
1780} 1772}
1781 1773
1782 1774
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 957b8caddf1e..418582b709eb 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3017,7 +3017,7 @@ xlog_recover_process_efi(
3017 } 3017 }
3018 3018
3019 efip->efi_flags |= XFS_EFI_RECOVERED; 3019 efip->efi_flags |= XFS_EFI_RECOVERED;
3020 xfs_trans_commit(tp, 0); 3020 error = xfs_trans_commit(tp, 0);
3021 return error; 3021 return error;
3022} 3022}
3023 3023
@@ -3131,16 +3131,13 @@ xlog_recover_clear_agi_bucket(
3131 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, 3131 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
3132 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), 3132 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
3133 XFS_FSS_TO_BB(mp, 1), 0, &agibp); 3133 XFS_FSS_TO_BB(mp, 1), 0, &agibp);
3134 if (error) { 3134 if (error)
3135 xfs_trans_cancel(tp, XFS_TRANS_ABORT); 3135 goto out_abort;
3136 return;
3137 }
3138 3136
3137 error = EINVAL;
3139 agi = XFS_BUF_TO_AGI(agibp); 3138 agi = XFS_BUF_TO_AGI(agibp);
3140 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) { 3139 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)
3141 xfs_trans_cancel(tp, XFS_TRANS_ABORT); 3140 goto out_abort;
3142 return;
3143 }
3144 3141
3145 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); 3142 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
3146 offset = offsetof(xfs_agi_t, agi_unlinked) + 3143 offset = offsetof(xfs_agi_t, agi_unlinked) +
@@ -3148,7 +3145,17 @@ xlog_recover_clear_agi_bucket(
3148 xfs_trans_log_buf(tp, agibp, offset, 3145 xfs_trans_log_buf(tp, agibp, offset,
3149 (offset + sizeof(xfs_agino_t) - 1)); 3146 (offset + sizeof(xfs_agino_t) - 1));
3150 3147
3151 (void) xfs_trans_commit(tp, 0); 3148 error = xfs_trans_commit(tp, 0);
3149 if (error)
3150 goto out_error;
3151 return;
3152
3153out_abort:
3154 xfs_trans_cancel(tp, XFS_TRANS_ABORT);
3155out_error:
3156 xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
3157 "failed to clear agi %d. Continuing.", agno);
3158 return;
3152} 3159}
3153 3160
3154/* 3161/*
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 244aa1b9f134..2d03fe194c2c 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -45,7 +45,7 @@
45#include "xfs_fsops.h" 45#include "xfs_fsops.h"
46#include "xfs_utils.h" 46#include "xfs_utils.h"
47 47
48STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t); 48STATIC int xfs_mount_log_sb(xfs_mount_t *, __int64_t);
49STATIC int xfs_uuid_mount(xfs_mount_t *); 49STATIC int xfs_uuid_mount(xfs_mount_t *);
50STATIC void xfs_uuid_unmount(xfs_mount_t *mp); 50STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
51STATIC void xfs_unmountfs_wait(xfs_mount_t *); 51STATIC void xfs_unmountfs_wait(xfs_mount_t *);
@@ -1189,8 +1189,13 @@ xfs_mountfs(
1189 /* 1189 /*
1190 * If fs is not mounted readonly, then update the superblock changes. 1190 * If fs is not mounted readonly, then update the superblock changes.
1191 */ 1191 */
1192 if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) 1192 if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
1193 xfs_mount_log_sb(mp, update_flags); 1193 error = xfs_mount_log_sb(mp, update_flags);
1194 if (error) {
1195 cmn_err(CE_WARN, "XFS: failed to write sb changes");
1196 goto error4;
1197 }
1198 }
1194 1199
1195 /* 1200 /*
1196 * Initialise the XFS quota management subsystem for this mount 1201 * Initialise the XFS quota management subsystem for this mount
@@ -1320,8 +1325,10 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1320 cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. " 1325 cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
1321 "Freespace may not be correct on next mount."); 1326 "Freespace may not be correct on next mount.");
1322 1327
1323 1328 error = xfs_log_sbcount(mp, 1);
1324 xfs_log_sbcount(mp, 1); 1329 if (error)
1330 cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
1331 "Freespace may not be correct on next mount.");
1325 xfs_unmountfs_writesb(mp); 1332 xfs_unmountfs_writesb(mp);
1326 xfs_unmountfs_wait(mp); /* wait for async bufs */ 1333 xfs_unmountfs_wait(mp); /* wait for async bufs */
1327 xfs_log_unmount(mp); /* Done! No more fs ops. */ 1334 xfs_log_unmount(mp); /* Done! No more fs ops. */
@@ -1413,9 +1420,8 @@ xfs_log_sbcount(
1413 xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); 1420 xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
1414 if (sync) 1421 if (sync)
1415 xfs_trans_set_sync(tp); 1422 xfs_trans_set_sync(tp);
1416 xfs_trans_commit(tp, 0); 1423 error = xfs_trans_commit(tp, 0);
1417 1424 return error;
1418 return 0;
1419} 1425}
1420 1426
1421STATIC void 1427STATIC void
@@ -1913,24 +1919,27 @@ xfs_uuid_unmount(
1913 * be altered by the mount options, as well as any potential sb_features2 1919 * be altered by the mount options, as well as any potential sb_features2
1914 * fixup. Only the first superblock is updated. 1920 * fixup. Only the first superblock is updated.
1915 */ 1921 */
1916STATIC void 1922STATIC int
1917xfs_mount_log_sb( 1923xfs_mount_log_sb(
1918 xfs_mount_t *mp, 1924 xfs_mount_t *mp,
1919 __int64_t fields) 1925 __int64_t fields)
1920{ 1926{
1921 xfs_trans_t *tp; 1927 xfs_trans_t *tp;
1928 int error;
1922 1929
1923 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID | 1930 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1924 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2)); 1931 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2));
1925 1932
1926 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); 1933 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1927 if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 1934 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1928 XFS_DEFAULT_LOG_COUNT)) { 1935 XFS_DEFAULT_LOG_COUNT);
1936 if (error) {
1929 xfs_trans_cancel(tp, 0); 1937 xfs_trans_cancel(tp, 0);
1930 return; 1938 return error;
1931 } 1939 }
1932 xfs_mod_sb(tp, fields); 1940 xfs_mod_sb(tp, fields);
1933 xfs_trans_commit(tp, 0); 1941 error = xfs_trans_commit(tp, 0);
1942 return error;
1934} 1943}
1935 1944
1936 1945
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 9cd6471cd60f..a0dc6e5bc5b9 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -124,14 +124,14 @@ xfs_growfs_rt_alloc(
124 XFS_GROWRTALLOC_LOG_RES(mp), 0, 124 XFS_GROWRTALLOC_LOG_RES(mp), 0,
125 XFS_TRANS_PERM_LOG_RES, 125 XFS_TRANS_PERM_LOG_RES,
126 XFS_DEFAULT_PERM_LOG_COUNT))) 126 XFS_DEFAULT_PERM_LOG_COUNT)))
127 goto error_exit; 127 goto error_cancel;
128 cancelflags = XFS_TRANS_RELEASE_LOG_RES; 128 cancelflags = XFS_TRANS_RELEASE_LOG_RES;
129 /* 129 /*
130 * Lock the inode. 130 * Lock the inode.
131 */ 131 */
132 if ((error = xfs_trans_iget(mp, tp, ino, 0, 132 if ((error = xfs_trans_iget(mp, tp, ino, 0,
133 XFS_ILOCK_EXCL, &ip))) 133 XFS_ILOCK_EXCL, &ip)))
134 goto error_exit; 134 goto error_cancel;
135 XFS_BMAP_INIT(&flist, &firstblock); 135 XFS_BMAP_INIT(&flist, &firstblock);
136 /* 136 /*
137 * Allocate blocks to the bitmap file. 137 * Allocate blocks to the bitmap file.
@@ -144,14 +144,16 @@ xfs_growfs_rt_alloc(
144 if (!error && nmap < 1) 144 if (!error && nmap < 1)
145 error = XFS_ERROR(ENOSPC); 145 error = XFS_ERROR(ENOSPC);
146 if (error) 146 if (error)
147 goto error_exit; 147 goto error_cancel;
148 /* 148 /*
149 * Free any blocks freed up in the transaction, then commit. 149 * Free any blocks freed up in the transaction, then commit.
150 */ 150 */
151 error = xfs_bmap_finish(&tp, &flist, &committed); 151 error = xfs_bmap_finish(&tp, &flist, &committed);
152 if (error) 152 if (error)
153 goto error_exit; 153 goto error_cancel;
154 xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 154 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
155 if (error)
156 goto error;
155 /* 157 /*
156 * Now we need to clear the allocated blocks. 158 * Now we need to clear the allocated blocks.
157 * Do this one block per transaction, to keep it simple. 159 * Do this one block per transaction, to keep it simple.
@@ -166,13 +168,13 @@ xfs_growfs_rt_alloc(
166 */ 168 */
167 if ((error = xfs_trans_reserve(tp, 0, 169 if ((error = xfs_trans_reserve(tp, 0,
168 XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0))) 170 XFS_GROWRTZERO_LOG_RES(mp), 0, 0, 0)))
169 goto error_exit; 171 goto error_cancel;
170 /* 172 /*
171 * Lock the bitmap inode. 173 * Lock the bitmap inode.
172 */ 174 */
173 if ((error = xfs_trans_iget(mp, tp, ino, 0, 175 if ((error = xfs_trans_iget(mp, tp, ino, 0,
174 XFS_ILOCK_EXCL, &ip))) 176 XFS_ILOCK_EXCL, &ip)))
175 goto error_exit; 177 goto error_cancel;
176 /* 178 /*
177 * Get a buffer for the block. 179 * Get a buffer for the block.
178 */ 180 */
@@ -181,14 +183,16 @@ xfs_growfs_rt_alloc(
181 mp->m_bsize, 0); 183 mp->m_bsize, 0);
182 if (bp == NULL) { 184 if (bp == NULL) {
183 error = XFS_ERROR(EIO); 185 error = XFS_ERROR(EIO);
184 goto error_exit; 186 goto error_cancel;
185 } 187 }
186 memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize); 188 memset(XFS_BUF_PTR(bp), 0, mp->m_sb.sb_blocksize);
187 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); 189 xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
188 /* 190 /*
189 * Commit the transaction. 191 * Commit the transaction.
190 */ 192 */
191 xfs_trans_commit(tp, 0); 193 error = xfs_trans_commit(tp, 0);
194 if (error)
195 goto error;
192 } 196 }
193 /* 197 /*
194 * Go on to the next extent, if any. 198 * Go on to the next extent, if any.
@@ -196,8 +200,9 @@ xfs_growfs_rt_alloc(
196 oblocks = map.br_startoff + map.br_blockcount; 200 oblocks = map.br_startoff + map.br_blockcount;
197 } 201 }
198 return 0; 202 return 0;
199error_exit: 203error_cancel:
200 xfs_trans_cancel(tp, cancelflags); 204 xfs_trans_cancel(tp, cancelflags);
205error:
201 return error; 206 return error;
202} 207}
203 208
@@ -1876,6 +1881,7 @@ xfs_growfs_rt(
1876 xfs_trans_t *tp; /* transaction pointer */ 1881 xfs_trans_t *tp; /* transaction pointer */
1877 1882
1878 sbp = &mp->m_sb; 1883 sbp = &mp->m_sb;
1884 cancelflags = 0;
1879 /* 1885 /*
1880 * Initial error checking. 1886 * Initial error checking.
1881 */ 1887 */
@@ -2042,13 +2048,15 @@ xfs_growfs_rt(
2042 */ 2048 */
2043 mp->m_rsumlevels = nrsumlevels; 2049 mp->m_rsumlevels = nrsumlevels;
2044 mp->m_rsumsize = nrsumsize; 2050 mp->m_rsumsize = nrsumsize;
2045 /* 2051
2046 * Commit the transaction. 2052 error = xfs_trans_commit(tp, 0);
2047 */ 2053 if (error) {
2048 xfs_trans_commit(tp, 0); 2054 tp = NULL;
2055 break;
2056 }
2049 } 2057 }
2050 2058
2051 if (error) 2059 if (error && tp)
2052 xfs_trans_cancel(tp, cancelflags); 2060 xfs_trans_cancel(tp, cancelflags);
2053 2061
2054 /* 2062 /*
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 6351efb569c7..09e186d02c11 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -672,6 +672,8 @@ void
672xfs_attr_quiesce( 672xfs_attr_quiesce(
673 xfs_mount_t *mp) 673 xfs_mount_t *mp)
674{ 674{
675 int error = 0;
676
675 /* wait for all modifications to complete */ 677 /* wait for all modifications to complete */
676 while (atomic_read(&mp->m_active_trans) > 0) 678 while (atomic_read(&mp->m_active_trans) > 0)
677 delay(100); 679 delay(100);
@@ -682,7 +684,11 @@ xfs_attr_quiesce(
682 ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0); 684 ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
683 685
684 /* Push the superblock and write an unmount record */ 686 /* Push the superblock and write an unmount record */
685 xfs_log_sbcount(mp, 1); 687 error = xfs_log_sbcount(mp, 1);
688 if (error)
689 xfs_fs_cmn_err(CE_WARN, mp,
690 "xfs_attr_quiesce: failed to log sb changes. "
691 "Frozen image may not be consistent.");
686 xfs_log_unmount_write(mp); 692 xfs_log_unmount_write(mp);
687 xfs_unmountfs_writesb(mp); 693 xfs_unmountfs_writesb(mp);
688} 694}
@@ -1316,8 +1322,11 @@ xfs_syncsub(
1316 * of sync if we crash or get a forced shutdown. We don't want to force 1322 * of sync if we crash or get a forced shutdown. We don't want to force
1317 * this to disk, just get a transaction into the iclogs.... 1323 * this to disk, just get a transaction into the iclogs....
1318 */ 1324 */
1319 if (flags & SYNC_SUPER) 1325 if (flags & SYNC_SUPER) {
1320 xfs_log_sbcount(mp, 0); 1326 error = xfs_log_sbcount(mp, 0);
1327 if (error)
1328 last_error = error;
1329 }
1321 1330
1322 /* 1331 /*
1323 * Now check to see if the log needs a "dummy" transaction. 1332 * Now check to see if the log needs a "dummy" transaction.
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index d46f24c68498..bc0a4707189a 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1447,28 +1447,22 @@ xfs_inactive_attrs(
1447 tp = *tpp; 1447 tp = *tpp;
1448 mp = ip->i_mount; 1448 mp = ip->i_mount;
1449 ASSERT(ip->i_d.di_forkoff != 0); 1449 ASSERT(ip->i_d.di_forkoff != 0);
1450 xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 1450 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
1451 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1451 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1452 if (error)
1453 goto error_unlock;
1452 1454
1453 error = xfs_attr_inactive(ip); 1455 error = xfs_attr_inactive(ip);
1454 if (error) { 1456 if (error)
1455 *tpp = NULL; 1457 goto error_unlock;
1456 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1457 return error; /* goto out */
1458 }
1459 1458
1460 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 1459 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
1461 error = xfs_trans_reserve(tp, 0, 1460 error = xfs_trans_reserve(tp, 0,
1462 XFS_IFREE_LOG_RES(mp), 1461 XFS_IFREE_LOG_RES(mp),
1463 0, XFS_TRANS_PERM_LOG_RES, 1462 0, XFS_TRANS_PERM_LOG_RES,
1464 XFS_INACTIVE_LOG_COUNT); 1463 XFS_INACTIVE_LOG_COUNT);
1465 if (error) { 1464 if (error)
1466 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 1465 goto error_cancel;
1467 xfs_trans_cancel(tp, 0);
1468 *tpp = NULL;
1469 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1470 return error;
1471 }
1472 1466
1473 xfs_ilock(ip, XFS_ILOCK_EXCL); 1467 xfs_ilock(ip, XFS_ILOCK_EXCL);
1474 xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); 1468 xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
@@ -1479,6 +1473,14 @@ xfs_inactive_attrs(
1479 1473
1480 *tpp = tp; 1474 *tpp = tp;
1481 return 0; 1475 return 0;
1476
1477error_cancel:
1478 ASSERT(XFS_FORCED_SHUTDOWN(mp));
1479 xfs_trans_cancel(tp, 0);
1480error_unlock:
1481 *tpp = NULL;
1482 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
1483 return error;
1482} 1484}
1483 1485
1484int 1486int