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

Commit 962bf3ea authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xfs-for-linus-3.15-rc2' of git://oss.sgi.com/xfs/xfs

Pull xfs bug fixes from Dave Chinner:
 "The fixes are for data corruption issues, memory corruption and
  regressions for changes merged in -rc1.

  Data corruption fixes:
   - fix a bunch of delayed allocation state mismatches
   - fix collapse/zero range bugs
   - fix a direct IO block mapping bug @ EOF

  Other fixes:
   - fix a use after free on metadata IO error
   - fix a use after free on IO error during unmount
   - fix an incorrect error sign on direct IO write errors
   - add missing O_TMPFILE inode security context initialisation"

* tag 'xfs-for-linus-3.15-rc2' of git://oss.sgi.com/xfs/xfs:
  xfs: fix tmpfile/selinux deadlock and initialize security
  xfs: fix buffer use after free on IO error
  xfs: wrong error sign conversion during failed DIO writes
  xfs: unmount does not wait for shutdown during unmount
  xfs: collapse range is delalloc challenged
  xfs: don't map ranges that span EOF for direct IO
  xfs: zeroing space needs to punch delalloc blocks
  xfs: xfs_vm_write_end truncates too much on failure
  xfs: write failure beyond EOF truncates too much data
  xfs: kill buffers over failed write ranges properly
parents 7d77879b 330033d6
Loading
Loading
Loading
Loading
+45 −6
Original line number Diff line number Diff line
@@ -1344,6 +1344,14 @@ __xfs_get_blocks(
	/*
	 * If this is O_DIRECT or the mpage code calling tell them how large
	 * the mapping is, so that we can avoid repeated get_blocks calls.
	 *
	 * If the mapping spans EOF, then we have to break the mapping up as the
	 * mapping for blocks beyond EOF must be marked new so that sub block
	 * regions can be correctly zeroed. We can't do this for mappings within
	 * EOF unless the mapping was just allocated or is unwritten, otherwise
	 * the callers would overwrite existing data with zeros. Hence we have
	 * to split the mapping into a range up to and including EOF, and a
	 * second mapping for beyond EOF.
	 */
	if (direct || size > (1 << inode->i_blkbits)) {
		xfs_off_t		mapping_size;
@@ -1354,6 +1362,12 @@ __xfs_get_blocks(
		ASSERT(mapping_size > 0);
		if (mapping_size > size)
			mapping_size = size;
		if (offset < i_size_read(inode) &&
		    offset + mapping_size >= i_size_read(inode)) {
			/* limit mapping to block that spans EOF */
			mapping_size = roundup_64(i_size_read(inode) - offset,
						  1 << inode->i_blkbits);
		}
		if (mapping_size > LONG_MAX)
			mapping_size = LONG_MAX;

@@ -1566,6 +1580,16 @@ xfs_vm_write_failed(

		xfs_vm_kill_delalloc_range(inode, block_offset,
					   block_offset + bh->b_size);

		/*
		 * This buffer does not contain data anymore. make sure anyone
		 * who finds it knows that for certain.
		 */
		clear_buffer_delay(bh);
		clear_buffer_uptodate(bh);
		clear_buffer_mapped(bh);
		clear_buffer_new(bh);
		clear_buffer_dirty(bh);
	}

}
@@ -1599,12 +1623,21 @@ xfs_vm_write_begin(
	status = __block_write_begin(page, pos, len, xfs_get_blocks);
	if (unlikely(status)) {
		struct inode	*inode = mapping->host;
		size_t		isize = i_size_read(inode);

		xfs_vm_write_failed(inode, page, pos, len);
		unlock_page(page);

		if (pos + len > i_size_read(inode))
			truncate_pagecache(inode, i_size_read(inode));
		/*
		 * If the write is beyond EOF, we only want to kill blocks
		 * allocated in this write, not blocks that were previously
		 * written successfully.
		 */
		if (pos + len > isize) {
			ssize_t start = max_t(ssize_t, pos, isize);

			truncate_pagecache_range(inode, start, pos + len);
		}

		page_cache_release(page);
		page = NULL;
@@ -1615,9 +1648,12 @@ xfs_vm_write_begin(
}

/*
 * On failure, we only need to kill delalloc blocks beyond EOF because they
 * will never be written. For blocks within EOF, generic_write_end() zeros them
 * so they are safe to leave alone and be written with all the other valid data.
 * On failure, we only need to kill delalloc blocks beyond EOF in the range of
 * this specific write because they will never be written. Previous writes
 * beyond EOF where block allocation succeeded do not need to be trashed, so
 * only new blocks from this write should be trashed. For blocks within
 * EOF, generic_write_end() zeros them so they are safe to leave alone and be
 * written with all the other valid data.
 */
STATIC int
xfs_vm_write_end(
@@ -1640,8 +1676,11 @@ xfs_vm_write_end(
		loff_t		to = pos + len;

		if (to > isize) {
			truncate_pagecache(inode, isize);
			/* only kill blocks in this write beyond EOF */
			if (pos > isize)
				isize = pos;
			xfs_vm_kill_delalloc_range(inode, isize, to);
			truncate_pagecache_range(inode, isize, to);
		}
	}
	return ret;
+11 −6
Original line number Diff line number Diff line
@@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents(
	int				whichfork = XFS_DATA_FORK;
	int				logflags;
	xfs_filblks_t			blockcount = 0;
	int				total_extents;

	if (unlikely(XFS_TEST_ERROR(
	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents(
	ASSERT(current_ext != NULL);

	ifp = XFS_IFORK_PTR(ip, whichfork);

	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
		/* Read in all the extents */
		error = xfs_iread_extents(tp, ip, whichfork);
@@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents(

	/* We are going to change core inode */
	logflags = XFS_ILOG_CORE;

	if (ifp->if_flags & XFS_IFBROOT) {
		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
		cur->bc_private.b.firstblock = *firstblock;
@@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents(
		logflags |= XFS_ILOG_DEXT;
	}

	while (nexts++ < num_exts &&
	       *current_ext <  XFS_IFORK_NEXTENTS(ip, whichfork)) {
	/*
	 * There may be delalloc extents in the data fork before the range we
	 * are collapsing out, so we cannot
	 * use the count of real extents here. Instead we have to calculate it
	 * from the incore fork.
	 */
	total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
	while (nexts++ < num_exts && *current_ext < total_extents) {

		gotp = xfs_iext_get_ext(ifp, *current_ext);
		xfs_bmbt_get_all(gotp, &got);
@@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents(
		}

		(*current_ext)++;
		total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
	}

	/* Check if we are done */
	if (*current_ext ==  XFS_IFORK_NEXTENTS(ip, whichfork))
	if (*current_ext == total_extents)
		*done = 1;

del_cursor:
@@ -5568,6 +5574,5 @@ xfs_bmap_shift_extents(
			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);

	xfs_trans_log_inode(tp, ip, logflags);

	return error;
}
+12 −1
Original line number Diff line number Diff line
@@ -1418,6 +1418,8 @@ xfs_zero_file_space(
	xfs_off_t		end_boundary;
	int			error;

	trace_xfs_zero_file_space(ip);

	granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);

	/*
@@ -1432,9 +1434,18 @@ xfs_zero_file_space(
	ASSERT(end_boundary <= offset + len);

	if (start_boundary < end_boundary - 1) {
		/* punch out the page cache over the conversion range */
		/*
		 * punch out delayed allocation blocks and the page cache over
		 * the conversion range
		 */
		xfs_ilock(ip, XFS_ILOCK_EXCL);
		error = xfs_bmap_punch_delalloc_range(ip,
				XFS_B_TO_FSBT(mp, start_boundary),
				XFS_B_TO_FSB(mp, end_boundary - start_boundary));
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
		truncate_pagecache_range(VFS_I(ip), start_boundary,
					 end_boundary - 1);

		/* convert the blocks */
		error = xfs_alloc_file_space(ip, start_boundary,
					end_boundary - start_boundary - 1,
+12 −4
Original line number Diff line number Diff line
@@ -1372,21 +1372,29 @@ xfs_buf_iorequest(
		xfs_buf_wait_unpin(bp);
	xfs_buf_hold(bp);

	/* Set the count to 1 initially, this will stop an I/O
	/*
	 * Set the count to 1 initially, this will stop an I/O
	 * completion callout which happens before we have started
	 * all the I/O from calling xfs_buf_ioend too early.
	 */
	atomic_set(&bp->b_io_remaining, 1);
	_xfs_buf_ioapply(bp);
	_xfs_buf_ioend(bp, 1);
	/*
	 * If _xfs_buf_ioapply failed, we'll get back here with
	 * only the reference we took above.  _xfs_buf_ioend will
	 * drop it to zero, so we'd better not queue it for later,
	 * or we'll free it before it's done.
	 */
	_xfs_buf_ioend(bp, bp->b_error ? 0 : 1);

	xfs_buf_rele(bp);
}

/*
 * Waits for I/O to complete on the buffer supplied.  It returns immediately if
 * no I/O is pending or there is already a pending error on the buffer.  It
 * returns the I/O error code, if any, or 0 if there was no error.
 * no I/O is pending or there is already a pending error on the buffer, in which
 * case nothing will ever complete.  It returns the I/O error code, if any, or
 * 0 if there was no error.
 */
int
xfs_buf_iowait(
+1 −1
Original line number Diff line number Diff line
@@ -679,7 +679,7 @@ xfs_file_dio_aio_write(
		goto out;

	if (mapping->nrpages) {
		ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
		ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
						    pos, -1);
		if (ret)
			goto out;
Loading