Beispiel #1
0
/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ioend->io_error = -EIO;
		goto done;
	}
	if (ioend->io_error)
		goto done;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 */
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						  ioend->io_size);
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize_ioend(ioend);
	} else {
		ASSERT(!xfs_ioend_is_append(ioend));
	}

done:
	if (error)
		ioend->io_error = error;
	xfs_destroy_ioend(ioend);
}
Beispiel #2
0
/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	struct xfs_ioend	*ioend =
		container_of(work, struct xfs_ioend, io_work);
	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
	int			error = ioend->io_bio->bi_error;

	/*
	 * Set an error if the mount has shut down and proceed with end I/O
	 * processing so it can perform whatever cleanups are necessary.
	 */
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		error = -EIO;

	/*
	 * For a CoW extent, we need to move the mapping from the CoW fork
	 * to the data fork.  If instead an error happened, just dump the
	 * new blocks.
	 */
	if (ioend->io_type == XFS_IO_COW) {
		if (error)
			goto done;
		if (ioend->io_bio->bi_error) {
			error = xfs_reflink_cancel_cow_range(ip,
					ioend->io_offset, ioend->io_size);
			goto done;
		}
		error = xfs_reflink_end_cow(ip, ioend->io_offset,
				ioend->io_size);
		if (error)
			goto done;
	}

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 * Detecting and handling completion IO errors is done individually
	 * for each case as different cleanup operations need to be performed
	 * on error.
	 */
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		if (error)
			goto done;
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						  ioend->io_size);
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize_ioend(ioend, error);
	} else {
		ASSERT(!xfs_ioend_is_append(ioend) ||
		       ioend->io_type == XFS_IO_COW);
	}

done:
	xfs_destroy_ioend(ioend, error);
}
Beispiel #3
0
static int
xfs_dio_write_end_io(
	struct kiocb		*iocb,
	ssize_t			size,
	unsigned		flags)
{
	struct inode		*inode = file_inode(iocb->ki_filp);
	struct xfs_inode	*ip = XFS_I(inode);
	loff_t			offset = iocb->ki_pos;
	int			error = 0;

	trace_xfs_end_io_direct_write(ip, offset, size);

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

	if (size <= 0)
		return size;

	if (flags & IOMAP_DIO_COW) {
		error = xfs_reflink_end_cow(ip, offset, size);
		if (error)
			return error;
	}

	/*
	 * Unwritten conversion updates the in-core isize after extent
	 * conversion but before updating the on-disk size. Updating isize any
	 * earlier allows a racing dio read to find unwritten extents before
	 * they are converted.
	 */
	if (flags & IOMAP_DIO_UNWRITTEN)
		return xfs_iomap_write_unwritten(ip, offset, size, true);

	/*
	 * We need to update the in-core inode size here so that we don't end up
	 * with the on-disk inode size being outside the in-core inode size. We
	 * have no other method of updating EOF for AIO, so always do it here
	 * if necessary.
	 *
	 * We need to lock the test/set EOF update as we can be racing with
	 * other IO completions here to update the EOF. Failing to serialise
	 * here can result in EOF moving backwards and Bad Things Happen when
	 * that occurs.
	 */
	spin_lock(&ip->i_flags_lock);
	if (offset + size > i_size_read(inode)) {
		i_size_write(inode, offset + size);
		spin_unlock(&ip->i_flags_lock);
		error = xfs_setfilesize(ip, offset, size);
	} else {
		spin_unlock(&ip->i_flags_lock);
	}

	return error;
}
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ioend->io_error = -EIO;
		goto done;
	}
	if (ioend->io_error)
		goto done;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 */
	if (ioend->io_type == IO_UNWRITTEN) {
		/*
		 * For buffered I/O we never preallocate a transaction when
		 * doing the unwritten extent conversion, but for direct I/O
		 * we do not know if we are converting an unwritten extent
		 * or not at the point where we preallocate the transaction.
		 */
		if (ioend->io_append_trans) {
			ASSERT(ioend->io_isdirect);

			current_set_flags_nested(
				&ioend->io_append_trans->t_pflags, PF_FSTRANS);
			xfs_trans_cancel(ioend->io_append_trans, 0);
		}

		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						 ioend->io_size);
		if (error) {
			ioend->io_error = -error;
			goto done;
		}
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize(ioend);
		if (error)
			ioend->io_error = -error;
	} else {
		ASSERT(!xfs_ioend_is_append(ioend));
	}

done:
	xfs_destroy_ioend(ioend);
}
Beispiel #5
0
/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		error = -EIO;
		goto done;
	}
	if (ioend->io_error)
		goto done;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 */
	if (ioend->io_type == IO_UNWRITTEN) {
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						 ioend->io_size);
		if (error) {
			ioend->io_error = -error;
			goto done;
		}
	}

	/*
	 * We might have to update the on-disk file size after extending
	 * writes.
	 */
	error = xfs_setfilesize(ioend);
	ASSERT(!error || error == EAGAIN);

done:
	/*
	 * If we didn't complete processing of the ioend, requeue it to the
	 * tail of the workqueue for another attempt later. Otherwise destroy
	 * it.
	 */
	if (error == EAGAIN) {
		atomic_inc(&ioend->io_remaining);
		xfs_finish_ioend(ioend);
		/* ensure we don't spin on blocked ioends */
		delay(1);
	} else {
		xfs_destroy_ioend(ioend);
	}
}
Beispiel #6
0
/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ioend->io_error = -EIO;
		goto done;
	}
	if (ioend->io_error)
		goto done;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 */
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						  ioend->io_size);
	} else if (ioend->io_isdirect && xfs_ioend_is_append(ioend)) {
		/*
		 * For direct I/O we do not know if we need to allocate blocks
		 * or not so we can't preallocate an append transaction as that
		 * results in nested reservations and log space deadlocks. Hence
		 * allocate the transaction here. While this is sub-optimal and
		 * can block IO completion for some time, we're stuck with doing
		 * it this way until we can pass the ioend to the direct IO
		 * allocation callbacks and avoid nesting that way.
		 */
		error = xfs_setfilesize_trans_alloc(ioend);
		if (error)
			goto done;
		error = xfs_setfilesize(ioend);
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize(ioend);
	} else {
		ASSERT(!xfs_ioend_is_append(ioend));
	}

done:
	if (error)
		ioend->io_error = -error;
	xfs_destroy_ioend(ioend);
}
Beispiel #7
0
/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	/*
	 * Set an error if the mount has shut down and proceed with end I/O
	 * processing so it can perform whatever cleanups are necessary.
	 */
	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		ioend->io_error = -EIO;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 * Detecting and handling completion IO errors is done individually
	 * for each case as different cleanup operations need to be performed
	 * on error.
	 */
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		if (ioend->io_error)
			goto done;
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						  ioend->io_size);
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize_ioend(ioend);
	} else {
		ASSERT(!xfs_ioend_is_append(ioend));
	}

done:
	if (error)
		ioend->io_error = error;
	xfs_destroy_ioend(ioend);
}
Beispiel #8
0
/*
 * Make sure the blocks described by maps are stable on disk.  This includes
 * converting any unwritten extents, flushing the disk cache and updating the
 * time stamps.
 *
 * Note that we rely on the caller to always send us a timestamp update so that
 * we always commit a transaction here.  If that stops being true we will have
 * to manually flush the cache here similar to what the fsync code path does
 * for datasyncs on files that have no dirty metadata.
 */
int
xfs_fs_commit_blocks(
	struct inode		*inode,
	struct iomap		*maps,
	int			nr_maps,
	struct iattr		*iattr)
{
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_trans	*tp;
	bool			update_isize = false;
	int			error, i;
	loff_t			size;

	ASSERT(iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME));

	xfs_ilock(ip, XFS_IOLOCK_EXCL);

	size = i_size_read(inode);
	if ((iattr->ia_valid & ATTR_SIZE) && iattr->ia_size > size) {
		update_isize = true;
		size = iattr->ia_size;
	}

	for (i = 0; i < nr_maps; i++) {
		u64 start, length, end;

		start = maps[i].offset;
		if (start > size)
			continue;

		end = start + maps[i].length;
		if (end > size)
			end = size;

		length = end - start;
		if (!length)
			continue;
	
		/*
		 * Make sure reads through the pagecache see the new data.
		 */
		error = invalidate_inode_pages2_range(inode->i_mapping,
					start >> PAGE_SHIFT,
					(end - 1) >> PAGE_SHIFT);
		WARN_ON_ONCE(error);

		error = xfs_iomap_write_unwritten(ip, start, length);
		if (error)
			goto out_drop_iolock;
	}

	if (update_isize) {
		error = xfs_pnfs_validate_isize(ip, size);
		if (error)
			goto out_drop_iolock;
	}

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
	if (error)
		goto out_drop_iolock;

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	xfs_setattr_time(ip, iattr);
	if (update_isize) {
		i_size_write(inode, iattr->ia_size);
		ip->i_d.di_size = iattr->ia_size;
	}

	xfs_trans_set_sync(tp);
	error = xfs_trans_commit(tp);

out_drop_iolock:
	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
	return error;
}