Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5720eec authored by David Chinner's avatar David Chinner Committed by Lachlan McIlroy
Browse files

[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: default avatarDavid Chinner <dgc@sgi.com>
Signed-off-by: default avatarNiv Sardi <xaiki@sgi.com>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent 3c1e2bbe
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -2392,9 +2392,9 @@ xfs_qm_write_sb_changes(
	}

	xfs_mod_sb(tp, flags);
	(void) xfs_trans_commit(tp, 0);
	error = xfs_trans_commit(tp, 0);

	return 0;
	return error;
}


+2 −2
Original line number Diff line number Diff line
@@ -734,12 +734,12 @@ xfs_qm_scall_setqlim(
	xfs_trans_log_dquot(tp, dqp);

	xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
	xfs_trans_commit(tp, 0);
	error = xfs_trans_commit(tp, 0);
	xfs_qm_dqprint(dqp);
	xfs_qm_dqrele(dqp);
	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));

	return (0);
	return error;
}

STATIC int
+22 −30
Original line number Diff line number Diff line
@@ -1699,33 +1699,16 @@ xfs_itruncate_finish(
			 * blocks in the file system, but oh well.
			 */
			xfs_bmap_cancel(&free_list);
			if (committed) {
				/*
				 * If the passed in transaction committed
				 * in xfs_bmap_finish(), then we want to
				 * add the inode to this one before returning.
				 * This keeps things simple for the higher
				 * level code, because it always knows that
				 * the inode is locked and held in the
				 * transaction that returns to it whether
				 * errors occur or not.  We don't mark the
				 * inode dirty so that this transaction can
				 * be easily aborted if possible.
				 */
				xfs_trans_ijoin(ntp, ip,
					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
				xfs_trans_ihold(ntp, ip);
			}
			if (committed)
				goto error_join;
			return error;
		}

		if (committed) {
			/*
			 * The first xact was committed,
			 * so add the inode to the new one.
			 * Mark it dirty so it will be logged
			 * and moved forward in the log as
			 * part of every commit.
			 * The first xact was committed, so add the inode to
			 * the new one.  Mark it dirty so it will be logged and
			 * moved forward in the log as part of every commit.
			 */
			xfs_trans_ijoin(ntp, ip,
					XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1733,19 +1716,16 @@ xfs_itruncate_finish(
			xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE);
		}
		ntp = xfs_trans_dup(ntp);
		(void) xfs_trans_commit(*tp, 0);
		error = xfs_trans_commit(*tp, 0);
		*tp = ntp;
		if (error)
			goto error_join;
		error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
					  XFS_TRANS_PERM_LOG_RES,
					  XFS_ITRUNCATE_LOG_COUNT);
		/*
		 * Add the inode being truncated to the next chained
		 * transaction.
		 */
		xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
		xfs_trans_ihold(ntp, ip);
		if (error)
			return (error);
			goto error_join;

	}
	/*
	 * Only update the size in the case of the data fork, but
@@ -1777,6 +1757,18 @@ xfs_itruncate_finish(
	       (ip->i_d.di_nextents == 0));
	xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0);
	return 0;

error_join:
	/*
	 * Add the inode being truncated to the next chained transaction.  This
	 * keeps things simple for the higher level code, because it always
	 * knows that the inode is locked and held in the transaction that
	 * returns to it whether errors occur or not.  We don't mark the inode
	 * dirty so that this transaction can be easily aborted if possible.
	 */
	xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
	xfs_trans_ihold(ntp, ip);
	return error;
}


+17 −10
Original line number Diff line number Diff line
@@ -3017,7 +3017,7 @@ xlog_recover_process_efi(
	}

	efip->efi_flags |= XFS_EFI_RECOVERED;
	xfs_trans_commit(tp, 0);
	error = xfs_trans_commit(tp, 0);
	return error;
}

@@ -3131,16 +3131,13 @@ xlog_recover_clear_agi_bucket(
		error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
				   XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
				   XFS_FSS_TO_BB(mp, 1), 0, &agibp);
	if (error) {
		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
		return;
	}
	if (error)
		goto out_abort;

	error = EINVAL;
	agi = XFS_BUF_TO_AGI(agibp);
	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC) {
		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
		return;
	}
	if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)
		goto out_abort;

	agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
	offset = offsetof(xfs_agi_t, agi_unlinked) +
@@ -3148,7 +3145,17 @@ xlog_recover_clear_agi_bucket(
	xfs_trans_log_buf(tp, agibp, offset,
			  (offset + sizeof(xfs_agino_t) - 1));

	(void) xfs_trans_commit(tp, 0);
	error = xfs_trans_commit(tp, 0);
	if (error)
		goto out_error;
	return;

out_abort:
	xfs_trans_cancel(tp, XFS_TRANS_ABORT);
out_error:
	xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
			"failed to clear agi %d. Continuing.", agno);
	return;
}

/*
+22 −13
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@
#include "xfs_fsops.h"
#include "xfs_utils.h"

STATIC void	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
STATIC int	xfs_mount_log_sb(xfs_mount_t *, __int64_t);
STATIC int	xfs_uuid_mount(xfs_mount_t *);
STATIC void	xfs_uuid_unmount(xfs_mount_t *mp);
STATIC void	xfs_unmountfs_wait(xfs_mount_t *);
@@ -1189,8 +1189,13 @@ xfs_mountfs(
	/*
	 * If fs is not mounted readonly, then update the superblock changes.
	 */
	if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
		xfs_mount_log_sb(mp, update_flags);
	if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
		error = xfs_mount_log_sb(mp, update_flags);
		if (error) {
			cmn_err(CE_WARN, "XFS: failed to write sb changes");
			goto error4;
		}
	}

	/*
	 * Initialise the XFS quota management subsystem for this mount
@@ -1320,8 +1325,10 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
		cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
				"Freespace may not be correct on next mount.");


	xfs_log_sbcount(mp, 1);
	error = xfs_log_sbcount(mp, 1);
	if (error)
		cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
				"Freespace may not be correct on next mount.");
	xfs_unmountfs_writesb(mp);
	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
	xfs_log_unmount(mp);			/* Done! No more fs ops. */
@@ -1413,9 +1420,8 @@ xfs_log_sbcount(
	xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
	if (sync)
		xfs_trans_set_sync(tp);
	xfs_trans_commit(tp, 0);

	return 0;
	error = xfs_trans_commit(tp, 0);
	return error;
}

STATIC void
@@ -1913,24 +1919,27 @@ xfs_uuid_unmount(
 * be altered by the mount options, as well as any potential sb_features2
 * fixup. Only the first superblock is updated.
 */
STATIC void
STATIC int
xfs_mount_log_sb(
	xfs_mount_t	*mp,
	__int64_t	fields)
{
	xfs_trans_t	*tp;
	int		error;

	ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
			 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2));

	tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
	if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
				XFS_DEFAULT_LOG_COUNT)) {
	error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
				XFS_DEFAULT_LOG_COUNT);
	if (error) {
		xfs_trans_cancel(tp, 0);
		return;
		return error;
	}
	xfs_mod_sb(tp, fields);
	xfs_trans_commit(tp, 0);
	error = xfs_trans_commit(tp, 0);
	return error;
}


Loading