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

Commit 788c1da0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xfs-4.15-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
 "Here are some bug fixes for 4.15-rc2.

   - fix memory leaks that appeared after removing ifork inline data
     buffer

   - recover deferred rmap update log items in correct order

   - fix memory leaks when buffer construction fails

   - fix memory leaks when bmbt is corrupt

   - fix some uninitialized variables and math problems in the quota
     scrubber

   - add some omitted attribution tags on the log replay commit

   - fix some UBSAN complaints about integer overflows with large sparse
     files

   - implement an effective inode mode check in online fsck

   - fix log's inability to retry quota item writeout due to transient
     errors"

* tag 'xfs-4.15-fixes-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: Properly retry failed dquot items in case of error during buffer writeback
  xfs: scrub inode mode properly
  xfs: remove unused parameter from xfs_writepage_map
  xfs: ubsan fixes
  xfs: calculate correct offset in xfs_scrub_quota_item
  xfs: fix uninitialized variable in xfs_scrub_quota
  xfs: fix leaks on corruption errors in xfs_bmap.c
  xfs: fortify xfs_alloc_buftarg error handling
  xfs: log recovery should replay deferred ops in order
  xfs: always free inline data before resetting inode fork during ifree
parents e1ba1c99 373b0589
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -5662,7 +5662,8 @@ xfs_bmap_collapse_extents(
		*done = true;
		goto del_cursor;
	}
	XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
	XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock),
				del_cursor);

	new_startoff = got.br_startoff - offset_shift_fsb;
	if (xfs_iext_peek_prev_extent(ifp, &icur, &prev)) {
@@ -5767,7 +5768,8 @@ xfs_bmap_insert_extents(
			goto del_cursor;
		}
	}
	XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
	XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock),
				del_cursor);

	if (stop_fsb >= got.br_startoff + got.br_blockcount) {
		error = -EIO;
+13 −1
Original line number Diff line number Diff line
@@ -318,8 +318,20 @@ xfs_scrub_dinode(

	/* di_mode */
	mode = be16_to_cpu(dip->di_mode);
	if (mode & ~(S_IALLUGO | S_IFMT))
	switch (mode & S_IFMT) {
	case S_IFLNK:
	case S_IFREG:
	case S_IFDIR:
	case S_IFCHR:
	case S_IFBLK:
	case S_IFIFO:
	case S_IFSOCK:
		/* mode is recognized */
		break;
	default:
		xfs_scrub_ino_set_corrupt(sc, ino, bp);
		break;
	}

	/* v1/v2 fields */
	switch (dip->di_version) {
+2 −2
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ xfs_scrub_quota_item(
	unsigned long long		rcount;
	xfs_ino_t			fs_icount;

	offset = id * qi->qi_dqperchunk;
	offset = id / qi->qi_dqperchunk;

	/*
	 * We fed $id and DQNEXT into the xfs_qm_dqget call, which means
@@ -207,7 +207,7 @@ xfs_scrub_quota(
	xfs_dqid_t			id = 0;
	uint				dqtype;
	int				nimaps;
	int				error;
	int				error = 0;

	if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
		return -ENOENT;
+6 −6
Original line number Diff line number Diff line
@@ -399,7 +399,7 @@ xfs_map_blocks(
	       (ip->i_df.if_flags & XFS_IFEXTENTS));
	ASSERT(offset <= mp->m_super->s_maxbytes);

	if (offset + count > mp->m_super->s_maxbytes)
	if ((xfs_ufsize_t)offset + count > mp->m_super->s_maxbytes)
		count = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
@@ -896,13 +896,13 @@ xfs_writepage_map(
	struct writeback_control *wbc,
	struct inode		*inode,
	struct page		*page,
	loff_t			offset,
	uint64_t		end_offset)
{
	LIST_HEAD(submit_list);
	struct xfs_ioend	*ioend, *next;
	struct buffer_head	*bh, *head;
	ssize_t			len = i_blocksize(inode);
	uint64_t		offset;
	int			error = 0;
	int			count = 0;
	int			uptodate = 1;
@@ -1146,7 +1146,7 @@ xfs_do_writepage(
		end_offset = offset;
	}

	return xfs_writepage_map(wpc, wbc, inode, page, offset, end_offset);
	return xfs_writepage_map(wpc, wbc, inode, page, end_offset);

redirty:
	redirty_page_for_writepage(wbc, page);
@@ -1265,7 +1265,7 @@ xfs_map_trim_size(
	if (mapping_size > size)
		mapping_size = size;
	if (offset < i_size_read(inode) &&
	    offset + mapping_size >= i_size_read(inode)) {
	    (xfs_ufsize_t)offset + mapping_size >= i_size_read(inode)) {
		/* limit mapping to block that spans EOF */
		mapping_size = roundup_64(i_size_read(inode) - offset,
					  i_blocksize(inode));
@@ -1312,7 +1312,7 @@ xfs_get_blocks(
	lockmode = xfs_ilock_data_map_shared(ip);

	ASSERT(offset <= mp->m_super->s_maxbytes);
	if (offset + size > mp->m_super->s_maxbytes)
	if ((xfs_ufsize_t)offset + size > mp->m_super->s_maxbytes)
		size = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
+7 −16
Original line number Diff line number Diff line
@@ -389,7 +389,8 @@ xfs_bud_init(
int
xfs_bui_recover(
	struct xfs_mount		*mp,
	struct xfs_bui_log_item		*buip)
	struct xfs_bui_log_item		*buip,
	struct xfs_defer_ops		*dfops)
{
	int				error = 0;
	unsigned int			bui_type;
@@ -404,9 +405,7 @@ xfs_bui_recover(
	xfs_exntst_t			state;
	struct xfs_trans		*tp;
	struct xfs_inode		*ip = NULL;
	struct xfs_defer_ops		dfops;
	struct xfs_bmbt_irec		irec;
	xfs_fsblock_t			firstfsb;

	ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags));

@@ -464,7 +463,6 @@ xfs_bui_recover(

	if (VFS_I(ip)->i_nlink == 0)
		xfs_iflags_set(ip, XFS_IRECOVERY);
	xfs_defer_init(&dfops, &firstfsb);

	/* Process deferred bmap item. */
	state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
@@ -479,16 +477,16 @@ xfs_bui_recover(
		break;
	default:
		error = -EFSCORRUPTED;
		goto err_dfops;
		goto err_inode;
	}
	xfs_trans_ijoin(tp, ip, 0);

	count = bmap->me_len;
	error = xfs_trans_log_finish_bmap_update(tp, budp, &dfops, type,
	error = xfs_trans_log_finish_bmap_update(tp, budp, dfops, type,
			ip, whichfork, bmap->me_startoff,
			bmap->me_startblock, &count, state);
	if (error)
		goto err_dfops;
		goto err_inode;

	if (count > 0) {
		ASSERT(type == XFS_BMAP_UNMAP);
@@ -496,16 +494,11 @@ xfs_bui_recover(
		irec.br_blockcount = count;
		irec.br_startoff = bmap->me_startoff;
		irec.br_state = state;
		error = xfs_bmap_unmap_extent(tp->t_mountp, &dfops, ip, &irec);
		error = xfs_bmap_unmap_extent(tp->t_mountp, dfops, ip, &irec);
		if (error)
			goto err_dfops;
			goto err_inode;
	}

	/* Finish transaction, free inodes. */
	error = xfs_defer_finish(&tp, &dfops);
	if (error)
		goto err_dfops;

	set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
	error = xfs_trans_commit(tp);
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -513,8 +506,6 @@ xfs_bui_recover(

	return error;

err_dfops:
	xfs_defer_cancel(&dfops);
err_inode:
	xfs_trans_cancel(tp);
	if (ip) {
Loading