Commit c6503f12 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull xfs fixes from Darrick Wong:
 "Here are a few fixes for some corruption bugs and uninitialized
  variable problems. The few patches here have gone through a few days
  worth of fstest runs with no new problems observed.

  Changes since last update:

   - Fix a bunch of static checker complaints about uninitialized
     variables and insufficient range checks.

   - Avoid a crash when incore extent map data are corrupt.

   - Disallow FITRIM when we haven't recovered the log and know the
     metadata are stale.

   - Fix a data corruption when doing unaligned overlapping dio writes"

* tag 'xfs-5.1-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: serialize unaligned dio writes against all other dio writes
  xfs: prohibit fstrim in norecovery mode
  xfs: always init bma in xfs_bmapi_write
  xfs: fix btree scrub checking with regards to root-in-inode
  xfs: dabtree scrub needs to range-check level
  xfs: don't trip over uninitialized buffer on extent read of corrupted inode
parents 9df0ef6c 2032a8a2
...@@ -1191,7 +1191,10 @@ xfs_iread_extents( ...@@ -1191,7 +1191,10 @@ xfs_iread_extents(
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out. * Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
*/ */
level = be16_to_cpu(block->bb_level); level = be16_to_cpu(block->bb_level);
ASSERT(level > 0); if (unlikely(level == 0)) {
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
return -EFSCORRUPTED;
}
pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
bno = be64_to_cpu(*pp); bno = be64_to_cpu(*pp);
...@@ -4249,9 +4252,13 @@ xfs_bmapi_write( ...@@ -4249,9 +4252,13 @@ xfs_bmapi_write(
struct xfs_bmbt_irec *mval, /* output: map values */ struct xfs_bmbt_irec *mval, /* output: map values */
int *nmap) /* i/o: mval size/count */ int *nmap) /* i/o: mval size/count */
{ {
struct xfs_bmalloca bma = {
.tp = tp,
.ip = ip,
.total = total,
};
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp; struct xfs_ifork *ifp;
struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */
xfs_fileoff_t end; /* end of mapped file region */ xfs_fileoff_t end; /* end of mapped file region */
bool eof = false; /* after the end of extents */ bool eof = false; /* after the end of extents */
int error; /* error return */ int error; /* error return */
...@@ -4319,10 +4326,6 @@ xfs_bmapi_write( ...@@ -4319,10 +4326,6 @@ xfs_bmapi_write(
eof = true; eof = true;
if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev)) if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev))
bma.prev.br_startoff = NULLFILEOFF; bma.prev.br_startoff = NULLFILEOFF;
bma.tp = tp;
bma.ip = ip;
bma.total = total;
bma.datatype = 0;
bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork); bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);
n = 0; n = 0;
......
...@@ -415,8 +415,17 @@ xchk_btree_check_owner( ...@@ -415,8 +415,17 @@ xchk_btree_check_owner(
struct xfs_btree_cur *cur = bs->cur; struct xfs_btree_cur *cur = bs->cur;
struct check_owner *co; struct check_owner *co;
if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && bp == NULL) /*
* In theory, xfs_btree_get_block should only give us a null buffer
* pointer for the root of a root-in-inode btree type, but we need
* to check defensively here in case the cursor state is also screwed
* up.
*/
if (bp == NULL) {
if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE))
xchk_btree_set_corrupt(bs->sc, bs->cur, level);
return 0; return 0;
}
/* /*
* We want to cross-reference each btree block with the bnobt * We want to cross-reference each btree block with the bnobt
......
...@@ -574,6 +574,11 @@ xchk_da_btree( ...@@ -574,6 +574,11 @@ xchk_da_btree(
/* Drill another level deeper. */ /* Drill another level deeper. */
blkno = be32_to_cpu(key->before); blkno = be32_to_cpu(key->before);
level++; level++;
if (level >= XFS_DA_NODE_MAXDEPTH) {
/* Too deep! */
xchk_da_set_corrupt(&ds, level - 1);
break;
}
ds.tree_level--; ds.tree_level--;
error = xchk_da_btree_block(&ds, level, blkno); error = xchk_da_btree_block(&ds, level, blkno);
if (error) if (error)
......
...@@ -161,6 +161,14 @@ xfs_ioc_trim( ...@@ -161,6 +161,14 @@ xfs_ioc_trim(
return -EPERM; return -EPERM;
if (!blk_queue_discard(q)) if (!blk_queue_discard(q))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/*
* We haven't recovered the log, so we cannot use our bnobt-guided
* storage zapping commands.
*/
if (mp->m_flags & XFS_MOUNT_NORECOVERY)
return -EROFS;
if (copy_from_user(&range, urange, sizeof(range))) if (copy_from_user(&range, urange, sizeof(range)))
return -EFAULT; return -EFAULT;
......
...@@ -529,18 +529,17 @@ xfs_file_dio_aio_write( ...@@ -529,18 +529,17 @@ xfs_file_dio_aio_write(
count = iov_iter_count(from); count = iov_iter_count(from);
/* /*
* If we are doing unaligned IO, wait for all other IO to drain, * If we are doing unaligned IO, we can't allow any other overlapping IO
* otherwise demote the lock if we had to take the exclusive lock * in-flight at the same time or we risk data corruption. Wait for all
* for other reasons in xfs_file_aio_write_checks. * other IO to drain before we submit. If the IO is aligned, demote the
* iolock if we had to take the exclusive lock in
* xfs_file_aio_write_checks() for other reasons.
*/ */
if (unaligned_io) { if (unaligned_io) {
/* If we are going to wait for other DIO to finish, bail */ /* unaligned dio always waits, bail */
if (iocb->ki_flags & IOCB_NOWAIT) { if (iocb->ki_flags & IOCB_NOWAIT)
if (atomic_read(&inode->i_dio_count))
return -EAGAIN; return -EAGAIN;
} else {
inode_dio_wait(inode); inode_dio_wait(inode);
}
} else if (iolock == XFS_IOLOCK_EXCL) { } else if (iolock == XFS_IOLOCK_EXCL) {
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
iolock = XFS_IOLOCK_SHARED; iolock = XFS_IOLOCK_SHARED;
...@@ -548,6 +547,14 @@ xfs_file_dio_aio_write( ...@@ -548,6 +547,14 @@ xfs_file_dio_aio_write(
trace_xfs_file_direct_write(ip, count, iocb->ki_pos); trace_xfs_file_direct_write(ip, count, iocb->ki_pos);
ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io); ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io);
/*
* If unaligned, this is the only IO in-flight. If it has not yet
* completed, wait on it before we release the iolock to prevent
* subsequent overlapping IO.
*/
if (ret == -EIOCBQUEUED && unaligned_io)
inode_dio_wait(inode);
out: out:
xfs_iunlock(ip, iolock); xfs_iunlock(ip, iolock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment