Commit f11901ed authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xfs-5.10-merge-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
 "Two bug fixes that trickled in during the merge window:

   - Make fallocate check the alignment of its arguments against the
     fundamental allocation unit of the volume the file lives on, so
     that we don't trigger the fs' alignment checks.

   - Cancel unprocessed log intents immediately when log recovery fails,
     to avoid a log deadlock"

* tag 'xfs-5.10-merge-7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: cancel intents immediately if process_intents fails
  xfs: fix fallocate functions when rtextsize is larger than 1
parents c80e42a4 2e76f188
Loading
Loading
Loading
Loading
+5 −13
Original line number Diff line number Diff line
@@ -947,11 +947,11 @@ xfs_free_file_space(
	endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len);

	/* We can only free complete realtime extents. */
	if (XFS_IS_REALTIME_INODE(ip)) {
		xfs_extlen_t	extsz = xfs_get_extsz_hint(ip);

		if ((startoffset_fsb | endoffset_fsb) & (extsz - 1))
			return -EINVAL;
	if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
		startoffset_fsb = roundup_64(startoffset_fsb,
					     mp->m_sb.sb_rextsize);
		endoffset_fsb = rounddown_64(endoffset_fsb,
					     mp->m_sb.sb_rextsize);
	}

	/*
@@ -1147,14 +1147,6 @@ xfs_insert_file_space(

	trace_xfs_insert_file_space(ip);

	/* We can only insert complete realtime extents. */
	if (XFS_IS_REALTIME_INODE(ip)) {
		xfs_extlen_t	extsz = xfs_get_extsz_hint(ip);

		if ((stop_fsb | shift_fsb) & (extsz - 1))
			return -EINVAL;
	}

	error = xfs_bmap_can_insert_extents(ip, stop_fsb, shift_fsb);
	if (error)
		return error;
+35 −5
Original line number Diff line number Diff line
@@ -32,6 +32,39 @@

static const struct vm_operations_struct xfs_file_vm_ops;

/*
 * Decide if the given file range is aligned to the size of the fundamental
 * allocation unit for the file.
 */
static bool
xfs_is_falloc_aligned(
	struct xfs_inode	*ip,
	loff_t			pos,
	long long int		len)
{
	struct xfs_mount	*mp = ip->i_mount;
	uint64_t		mask;

	if (XFS_IS_REALTIME_INODE(ip)) {
		if (!is_power_of_2(mp->m_sb.sb_rextsize)) {
			u64	rextbytes;
			u32	mod;

			rextbytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
			div_u64_rem(pos, rextbytes, &mod);
			if (mod)
				return false;
			div_u64_rem(len, rextbytes, &mod);
			return mod == 0;
		}
		mask = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize) - 1;
	} else {
		mask = mp->m_sb.sb_blocksize - 1;
	}

	return !((pos | len) & mask);
}

int
xfs_update_prealloc_flags(
	struct xfs_inode	*ip,
@@ -850,9 +883,7 @@ xfs_file_fallocate(
		if (error)
			goto out_unlock;
	} else if (mode & FALLOC_FL_COLLAPSE_RANGE) {
		unsigned int blksize_mask = i_blocksize(inode) - 1;

		if (offset & blksize_mask || len & blksize_mask) {
		if (!xfs_is_falloc_aligned(ip, offset, len)) {
			error = -EINVAL;
			goto out_unlock;
		}
@@ -872,10 +903,9 @@ xfs_file_fallocate(
		if (error)
			goto out_unlock;
	} else if (mode & FALLOC_FL_INSERT_RANGE) {
		unsigned int	blksize_mask = i_blocksize(inode) - 1;
		loff_t		isize = i_size_read(inode);

		if (offset & blksize_mask || len & blksize_mask) {
		if (!xfs_is_falloc_aligned(ip, offset, len)) {
			error = -EINVAL;
			goto out_unlock;
		}
+6 −0
Original line number Diff line number Diff line
@@ -175,6 +175,12 @@ static inline xfs_dev_t linux_to_xfs_dev_t(dev_t dev)
#define xfs_sort(a,n,s,fn)	sort(a,n,s,fn,NULL)
#define xfs_stack_trace()	dump_stack()

static inline uint64_t rounddown_64(uint64_t x, uint32_t y)
{
	do_div(x, y);
	return x * y;
}

static inline uint64_t roundup_64(uint64_t x, uint32_t y)
{
	x += y - 1;
+8 −0
Original line number Diff line number Diff line
@@ -3446,6 +3446,14 @@ xlog_recover_finish(
		int	error;
		error = xlog_recover_process_intents(log);
		if (error) {
			/*
			 * Cancel all the unprocessed intent items now so that
			 * we don't leave them pinned in the AIL.  This can
			 * cause the AIL to livelock on the pinned item if
			 * anyone tries to push the AIL (inode reclaim does
			 * this) before we get around to xfs_log_mount_cancel.
			 */
			xlog_recover_cancel_intents(log);
			xfs_alert(log->l_mp, "Failed to recover intents");
			return error;
		}