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

Commit 645f9857 authored by Dave Chinner's avatar Dave Chinner
Browse files

Merge branch 'xfs-misc-fixes-3.17-2' into for-next

parents b076d872 4ef897a2
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -386,10 +386,11 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
	}
}

void
xfs_sb_from_disk(
static void
__xfs_sb_from_disk(
	struct xfs_sb	*to,
	xfs_dsb_t	*from)
	xfs_dsb_t	*from,
	bool		convert_xquota)
{
	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
@@ -445,6 +446,17 @@ xfs_sb_from_disk(
	to->sb_pad = 0;
	to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
	to->sb_lsn = be64_to_cpu(from->sb_lsn);
	/* Convert on-disk flags to in-memory flags? */
	if (convert_xquota)
		xfs_sb_quota_from_disk(to);
}

void
xfs_sb_from_disk(
	struct xfs_sb	*to,
	xfs_dsb_t	*from)
{
	__xfs_sb_from_disk(to, from, true);
}

static inline void
@@ -577,7 +589,11 @@ xfs_sb_verify(
	struct xfs_mount *mp = bp->b_target->bt_mount;
	struct xfs_sb	sb;

	xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp));
	/*
	 * Use call variant which doesn't convert quota flags from disk 
	 * format, because xfs_mount_validate_sb checks the on-disk flags.
	 */
	__xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false);

	/*
	 * Only check the in progress field for the primary superblock as
+48 −52
Original line number Diff line number Diff line
@@ -809,7 +809,7 @@ xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
	 * have speculative prealloc/delalloc blocks to remove.
	 */
	if (VFS_I(ip)->i_size == 0 &&
	    VN_CACHED(VFS_I(ip)) == 0 &&
	    VFS_I(ip)->i_mapping->nrpages == 0 &&
	    ip->i_delayed_blks == 0)
		return false;

@@ -1618,6 +1618,30 @@ xfs_swap_extents_check_format(
	return 0;
}

int
xfs_swap_extent_flush(
	struct xfs_inode	*ip)
{
	int	error;

	error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
	if (error)
		return error;
	truncate_pagecache_range(VFS_I(ip), 0, -1);

	/* Verify O_DIRECT for ftmp */
	if (VFS_I(ip)->i_mapping->nrpages)
		return -EINVAL;

	/*
	 * Don't try to swap extents on mmap()d files because we can't lock
	 * out races against page faults safely.
	 */
	if (mapping_mapped(VFS_I(ip)->i_mapping))
		return -EBUSY;
	return 0;
}

int
xfs_swap_extents(
	xfs_inode_t	*ip,	/* target inode */
@@ -1633,6 +1657,7 @@ xfs_swap_extents(
	int		aforkblks = 0;
	int		taforkblks = 0;
	__uint64_t	tmp;
	int		lock_flags;

	tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
	if (!tempifp) {
@@ -1641,13 +1666,13 @@ xfs_swap_extents(
	}

	/*
	 * we have to do two separate lock calls here to keep lockdep
	 * happy. If we try to get all the locks in one call, lock will
	 * report false positives when we drop the ILOCK and regain them
	 * below.
	 * Lock up the inodes against other IO and truncate to begin with.
	 * Then we can ensure the inodes are flushed and have no page cache
	 * safely. Once we have done this we can take the ilocks and do the rest
	 * of the checks.
	 */
	lock_flags = XFS_IOLOCK_EXCL;
	xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL);
	xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);

	/* Verify that both files have the same format */
	if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
@@ -1661,23 +1686,28 @@ xfs_swap_extents(
		goto out_unlock;
	}

	error = filemap_write_and_wait(VFS_I(tip)->i_mapping);
	error = xfs_swap_extent_flush(ip);
	if (error)
		goto out_unlock;
	error = xfs_swap_extent_flush(tip);
	if (error)
		goto out_unlock;
	truncate_pagecache_range(VFS_I(tip), 0, -1);

	/* Verify O_DIRECT for ftmp */
	if (VN_CACHED(VFS_I(tip)) != 0) {
		error = -EINVAL;
	tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
	if (error) {
		xfs_trans_cancel(tp, 0);
		goto out_unlock;
	}
	xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
	lock_flags |= XFS_ILOCK_EXCL;

	/* Verify all data are being swapped */
	if (sxp->sx_offset != 0 ||
	    sxp->sx_length != ip->i_d.di_size ||
	    sxp->sx_length != tip->i_d.di_size) {
		error = -EFAULT;
		goto out_unlock;
		goto out_trans_cancel;
	}

	trace_xfs_swap_extent_before(ip, 0);
@@ -1689,7 +1719,7 @@ xfs_swap_extents(
		xfs_notice(mp,
		    "%s: inode 0x%llx format is incompatible for exchanging.",
				__func__, ip->i_ino);
		goto out_unlock;
		goto out_trans_cancel;
	}

	/*
@@ -1704,42 +1734,8 @@ xfs_swap_extents(
	    (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) ||
	    (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) {
		error = -EBUSY;
		goto out_unlock;
	}

	/* We need to fail if the file is memory mapped.  Once we have tossed
	 * all existing pages, the page fault will have no option
	 * but to go to the filesystem for pages. By making the page fault call
	 * vop_read (or write in the case of autogrow) they block on the iolock
	 * until we have switched the extents.
	 */
	if (VN_MAPPED(VFS_I(ip))) {
		error = -EBUSY;
		goto out_unlock;
	}

	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(tip, XFS_ILOCK_EXCL);

	/*
	 * There is a race condition here since we gave up the
	 * ilock.  However, the data fork will not change since
	 * we have the iolock (locked for truncation too) so we
	 * are safe.  We don't really care if non-io related
	 * fields change.
	 */
	truncate_pagecache_range(VFS_I(ip), 0, -1);

	tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0);
	if (error) {
		xfs_iunlock(ip,  XFS_IOLOCK_EXCL);
		xfs_iunlock(tip, XFS_IOLOCK_EXCL);
		xfs_trans_cancel(tp, 0);
		goto out;
		goto out_trans_cancel;
	}
	xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);

	/*
	 * Count the number of extended attribute blocks
	 */
@@ -1757,8 +1753,8 @@ xfs_swap_extents(
			goto out_trans_cancel;
	}

	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
	xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
	xfs_trans_ijoin(tp, ip, lock_flags);
	xfs_trans_ijoin(tp, tip, lock_flags);

	/*
	 * Before we've swapped the forks, lets set the owners of the forks
@@ -1887,8 +1883,8 @@ xfs_swap_extents(
	return error;

out_unlock:
	xfs_iunlock(ip,  XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
	xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
	xfs_iunlock(ip, lock_flags);
	xfs_iunlock(tip, lock_flags);
	goto out;

out_trans_cancel:
+14 −0
Original line number Diff line number Diff line
@@ -1330,6 +1330,20 @@ _xfs_buf_ioapply(
						   SHUTDOWN_CORRUPT_INCORE);
				return;
			}
		} else if (bp->b_bn != XFS_BUF_DADDR_NULL) {
			struct xfs_mount *mp = bp->b_target->bt_mount;

			/*
			 * non-crc filesystems don't attach verifiers during
			 * log recovery, so don't warn for such filesystems.
			 */
			if (xfs_sb_version_hascrc(&mp->m_sb)) {
				xfs_warn(mp,
					"%s: no ops on block 0x%llx/0x%x",
					__func__, bp->b_bn, bp->b_length);
				xfs_hex_dump(bp->b_addr, 64);
				dump_stack();
			}
		}
	} else if (bp->b_flags & XBF_READ_AHEAD) {
		rw = READA;
+2 −1
Original line number Diff line number Diff line
@@ -974,7 +974,8 @@ xfs_qm_dqflush(
	 * Get the buffer containing the on-disk dquot
	 */
	error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
				   mp->m_quotainfo->qi_dqchunklen, 0, &bp, NULL);
				   mp->m_quotainfo->qi_dqchunklen, 0, &bp,
				   &xfs_dquot_buf_ops);
	if (error)
		goto out_unlock;

+5 −5
Original line number Diff line number Diff line
@@ -247,11 +247,11 @@ xfs_file_read_iter(
	XFS_STATS_INC(xs_read_calls);

	if (unlikely(file->f_flags & O_DIRECT))
		ioflags |= IO_ISDIRECT;
		ioflags |= XFS_IO_ISDIRECT;
	if (file->f_mode & FMODE_NOCMTIME)
		ioflags |= IO_INVIS;
		ioflags |= XFS_IO_INVIS;

	if (unlikely(ioflags & IO_ISDIRECT)) {
	if (unlikely(ioflags & XFS_IO_ISDIRECT)) {
		xfs_buftarg_t	*target =
			XFS_IS_REALTIME_INODE(ip) ?
				mp->m_rtdev_targp : mp->m_ddev_targp;
@@ -284,7 +284,7 @@ xfs_file_read_iter(
	 * proceeed concurrently without serialisation.
	 */
	xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
	if ((ioflags & IO_ISDIRECT) && inode->i_mapping->nrpages) {
	if ((ioflags & XFS_IO_ISDIRECT) && inode->i_mapping->nrpages) {
		xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
		xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);

@@ -326,7 +326,7 @@ xfs_file_splice_read(
	XFS_STATS_INC(xs_read_calls);

	if (infilp->f_mode & FMODE_NOCMTIME)
		ioflags |= IO_INVIS;
		ioflags |= XFS_IO_INVIS;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		return -EIO;
Loading