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

Commit d9457dc0 authored by Jan Kara's avatar Jan Kara Committed by Al Viro
Browse files

xfs: Convert to new freezing code



Generic code now blocks all writers from standard write paths. So we add
blocking of all writers coming from ioctl (we get a protection of ioctl against
racing remount read-only as a bonus) and convert xfs_file_aio_write() to a
non-racy freeze protection. We also keep freeze protection on transaction
start to block internal filesystem writes such as removal of preallocated
blocks.

CC: Ben Myers <bpm@sgi.com>
CC: Alex Elder <elder@kernel.org>
CC: xfs@oss.sgi.com
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8e8ad8a5
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -123,6 +123,12 @@ xfs_setfilesize_trans_alloc(

	ioend->io_append_trans = tp;

	/*
	 * We will pass freeze protection with a transaction.  So tell lockdep
	 * we released it.
	 */
	rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
		      1, _THIS_IP_);
	/*
	 * We hand off the transaction to the completion thread now, so
	 * clear the flag here.
@@ -199,6 +205,15 @@ xfs_end_io(
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (ioend->io_append_trans) {
		/*
		 * We've got freeze protection passed with the transaction.
		 * Tell lockdep about it.
		 */
		rwsem_acquire_read(
			&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
			0, 1, _THIS_IP_);
	}
	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ioend->io_error = -EIO;
		goto done;
@@ -1410,6 +1425,9 @@ xfs_vm_direct_IO(
	if (ioend->io_append_trans) {
		current_set_flags_nested(&ioend->io_append_trans->t_pflags,
					 PF_FSTRANS);
		rwsem_acquire_read(
			&inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
			0, 1, _THIS_IP_);
		xfs_trans_cancel(ioend->io_append_trans, 0);
	}
out_destroy_ioend:
+7 −3
Original line number Diff line number Diff line
@@ -781,10 +781,12 @@ xfs_file_aio_write(
	if (ocount == 0)
		return 0;

	xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE);
	sb_start_write(inode->i_sb);

	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		return -EIO;
	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ret = -EIO;
		goto out;
	}

	if (unlikely(file->f_flags & O_DIRECT))
		ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount);
@@ -803,6 +805,8 @@ xfs_file_aio_write(
			ret = err;
	}

out:
	sb_end_write(inode->i_sb);
	return ret;
}

+52 −3
Original line number Diff line number Diff line
@@ -364,9 +364,15 @@ xfs_fssetdm_by_handle(
	if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
		return -XFS_ERROR(EFAULT);

	error = mnt_want_write_file(parfilp);
	if (error)
		return error;

	dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq);
	if (IS_ERR(dentry))
	if (IS_ERR(dentry)) {
		mnt_drop_write_file(parfilp);
		return PTR_ERR(dentry);
	}

	if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
		error = -XFS_ERROR(EPERM);
@@ -382,6 +388,7 @@ xfs_fssetdm_by_handle(
				 fsd.fsd_dmstate);

 out:
	mnt_drop_write_file(parfilp);
	dput(dentry);
	return error;
}
@@ -634,7 +641,11 @@ xfs_ioc_space(
	if (ioflags & IO_INVIS)
		attr_flags |= XFS_ATTR_DMI;

	error = mnt_want_write_file(filp);
	if (error)
		return error;
	error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
	mnt_drop_write_file(filp);
	return -error;
}

@@ -1163,6 +1174,7 @@ xfs_ioc_fssetxattr(
{
	struct fsxattr		fa;
	unsigned int		mask;
	int error;

	if (copy_from_user(&fa, arg, sizeof(fa)))
		return -EFAULT;
@@ -1171,7 +1183,12 @@ xfs_ioc_fssetxattr(
	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
		mask |= FSX_NONBLOCK;

	return -xfs_ioctl_setattr(ip, &fa, mask);
	error = mnt_want_write_file(filp);
	if (error)
		return error;
	error = xfs_ioctl_setattr(ip, &fa, mask);
	mnt_drop_write_file(filp);
	return -error;
}

STATIC int
@@ -1196,6 +1213,7 @@ xfs_ioc_setxflags(
	struct fsxattr		fa;
	unsigned int		flags;
	unsigned int		mask;
	int error;

	if (copy_from_user(&flags, arg, sizeof(flags)))
		return -EFAULT;
@@ -1210,7 +1228,12 @@ xfs_ioc_setxflags(
		mask |= FSX_NONBLOCK;
	fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));

	return -xfs_ioctl_setattr(ip, &fa, mask);
	error = mnt_want_write_file(filp);
	if (error)
		return error;
	error = xfs_ioctl_setattr(ip, &fa, mask);
	mnt_drop_write_file(filp);
	return -error;
}

STATIC int
@@ -1385,8 +1408,13 @@ xfs_file_ioctl(
		if (copy_from_user(&dmi, arg, sizeof(dmi)))
			return -XFS_ERROR(EFAULT);

		error = mnt_want_write_file(filp);
		if (error)
			return error;

		error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
				dmi.fsd_dmstate);
		mnt_drop_write_file(filp);
		return -error;
	}

@@ -1434,7 +1462,11 @@ xfs_file_ioctl(

		if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
			return -XFS_ERROR(EFAULT);
		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_swapext(&sxp);
		mnt_drop_write_file(filp);
		return -error;
	}

@@ -1463,9 +1495,14 @@ xfs_file_ioctl(
		if (copy_from_user(&inout, arg, sizeof(inout)))
			return -XFS_ERROR(EFAULT);

		error = mnt_want_write_file(filp);
		if (error)
			return error;

		/* input parameter is passed in resblks field of structure */
		in = inout.resblks;
		error = xfs_reserve_blocks(mp, &in, &inout);
		mnt_drop_write_file(filp);
		if (error)
			return -error;

@@ -1496,7 +1533,11 @@ xfs_file_ioctl(
		if (copy_from_user(&in, arg, sizeof(in)))
			return -XFS_ERROR(EFAULT);

		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_growfs_data(mp, &in);
		mnt_drop_write_file(filp);
		return -error;
	}

@@ -1506,7 +1547,11 @@ xfs_file_ioctl(
		if (copy_from_user(&in, arg, sizeof(in)))
			return -XFS_ERROR(EFAULT);

		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_growfs_log(mp, &in);
		mnt_drop_write_file(filp);
		return -error;
	}

@@ -1516,7 +1561,11 @@ xfs_file_ioctl(
		if (copy_from_user(&in, arg, sizeof(in)))
			return -XFS_ERROR(EFAULT);

		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_growfs_rt(mp, &in);
		mnt_drop_write_file(filp);
		return -error;
	}

+12 −0
Original line number Diff line number Diff line
@@ -600,7 +600,11 @@ xfs_file_compat_ioctl(

		if (xfs_compat_growfs_data_copyin(&in, arg))
			return -XFS_ERROR(EFAULT);
		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_growfs_data(mp, &in);
		mnt_drop_write_file(filp);
		return -error;
	}
	case XFS_IOC_FSGROWFSRT_32: {
@@ -608,7 +612,11 @@ xfs_file_compat_ioctl(

		if (xfs_compat_growfs_rt_copyin(&in, arg))
			return -XFS_ERROR(EFAULT);
		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_growfs_rt(mp, &in);
		mnt_drop_write_file(filp);
		return -error;
	}
#endif
@@ -627,7 +635,11 @@ xfs_file_compat_ioctl(
				   offsetof(struct xfs_swapext, sx_stat)) ||
		    xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))
			return -XFS_ERROR(EFAULT);
		error = mnt_want_write_file(filp);
		if (error)
			return error;
		error = xfs_swapext(&sxp);
		mnt_drop_write_file(filp);
		return -error;
	}
	case XFS_IOC_FSBULKSTAT_32:
+2 −2
Original line number Diff line number Diff line
@@ -680,9 +680,9 @@ xfs_iomap_write_unwritten(
		 * the same inode that we complete here and might deadlock
		 * on the iolock.
		 */
		xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
		sb_start_intwrite(mp->m_super);
		tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS);
		tp->t_flags |= XFS_TRANS_RESERVE;
		tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT;
		error = xfs_trans_reserve(tp, resblks,
				XFS_WRITE_LOG_RES(mp), 0,
				XFS_TRANS_PERM_LOG_RES,
Loading