Skip to content

Commit c6503f1

Browse files
committed
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
2 parents 9df0ef6 + 2032a8a commit c6503f1

File tree

5 files changed

+49
-17
lines changed

5 files changed

+49
-17
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,10 @@ xfs_iread_extents(
11911191
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
11921192
*/
11931193
level = be16_to_cpu(block->bb_level);
1194-
ASSERT(level > 0);
1194+
if (unlikely(level == 0)) {
1195+
XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
1196+
return -EFSCORRUPTED;
1197+
}
11951198
pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes);
11961199
bno = be64_to_cpu(*pp);
11971200

@@ -4249,9 +4252,13 @@ xfs_bmapi_write(
42494252
struct xfs_bmbt_irec *mval, /* output: map values */
42504253
int *nmap) /* i/o: mval size/count */
42514254
{
4255+
struct xfs_bmalloca bma = {
4256+
.tp = tp,
4257+
.ip = ip,
4258+
.total = total,
4259+
};
42524260
struct xfs_mount *mp = ip->i_mount;
42534261
struct xfs_ifork *ifp;
4254-
struct xfs_bmalloca bma = { NULL }; /* args for xfs_bmap_alloc */
42554262
xfs_fileoff_t end; /* end of mapped file region */
42564263
bool eof = false; /* after the end of extents */
42574264
int error; /* error return */
@@ -4319,10 +4326,6 @@ xfs_bmapi_write(
43194326
eof = true;
43204327
if (!xfs_iext_peek_prev_extent(ifp, &bma.icur, &bma.prev))
43214328
bma.prev.br_startoff = NULLFILEOFF;
4322-
bma.tp = tp;
4323-
bma.ip = ip;
4324-
bma.total = total;
4325-
bma.datatype = 0;
43264329
bma.minleft = xfs_bmapi_minleft(tp, ip, whichfork);
43274330

43284331
n = 0;

fs/xfs/scrub/btree.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,17 @@ xchk_btree_check_owner(
415415
struct xfs_btree_cur *cur = bs->cur;
416416
struct check_owner *co;
417417

418-
if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && bp == NULL)
418+
/*
419+
* In theory, xfs_btree_get_block should only give us a null buffer
420+
* pointer for the root of a root-in-inode btree type, but we need
421+
* to check defensively here in case the cursor state is also screwed
422+
* up.
423+
*/
424+
if (bp == NULL) {
425+
if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE))
426+
xchk_btree_set_corrupt(bs->sc, bs->cur, level);
419427
return 0;
428+
}
420429

421430
/*
422431
* We want to cross-reference each btree block with the bnobt

fs/xfs/scrub/dabtree.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,11 @@ xchk_da_btree(
574574
/* Drill another level deeper. */
575575
blkno = be32_to_cpu(key->before);
576576
level++;
577+
if (level >= XFS_DA_NODE_MAXDEPTH) {
578+
/* Too deep! */
579+
xchk_da_set_corrupt(&ds, level - 1);
580+
break;
581+
}
577582
ds.tree_level--;
578583
error = xchk_da_btree_block(&ds, level, blkno);
579584
if (error)

fs/xfs/xfs_discard.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ xfs_ioc_trim(
161161
return -EPERM;
162162
if (!blk_queue_discard(q))
163163
return -EOPNOTSUPP;
164+
165+
/*
166+
* We haven't recovered the log, so we cannot use our bnobt-guided
167+
* storage zapping commands.
168+
*/
169+
if (mp->m_flags & XFS_MOUNT_NORECOVERY)
170+
return -EROFS;
171+
164172
if (copy_from_user(&range, urange, sizeof(range)))
165173
return -EFAULT;
166174

fs/xfs/xfs_file.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -529,25 +529,32 @@ xfs_file_dio_aio_write(
529529
count = iov_iter_count(from);
530530

531531
/*
532-
* If we are doing unaligned IO, wait for all other IO to drain,
533-
* otherwise demote the lock if we had to take the exclusive lock
534-
* for other reasons in xfs_file_aio_write_checks.
532+
* If we are doing unaligned IO, we can't allow any other overlapping IO
533+
* in-flight at the same time or we risk data corruption. Wait for all
534+
* other IO to drain before we submit. If the IO is aligned, demote the
535+
* iolock if we had to take the exclusive lock in
536+
* xfs_file_aio_write_checks() for other reasons.
535537
*/
536538
if (unaligned_io) {
537-
/* If we are going to wait for other DIO to finish, bail */
538-
if (iocb->ki_flags & IOCB_NOWAIT) {
539-
if (atomic_read(&inode->i_dio_count))
540-
return -EAGAIN;
541-
} else {
542-
inode_dio_wait(inode);
543-
}
539+
/* unaligned dio always waits, bail */
540+
if (iocb->ki_flags & IOCB_NOWAIT)
541+
return -EAGAIN;
542+
inode_dio_wait(inode);
544543
} else if (iolock == XFS_IOLOCK_EXCL) {
545544
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
546545
iolock = XFS_IOLOCK_SHARED;
547546
}
548547

549548
trace_xfs_file_direct_write(ip, count, iocb->ki_pos);
550549
ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io);
550+
551+
/*
552+
* If unaligned, this is the only IO in-flight. If it has not yet
553+
* completed, wait on it before we release the iolock to prevent
554+
* subsequent overlapping IO.
555+
*/
556+
if (ret == -EIOCBQUEUED && unaligned_io)
557+
inode_dio_wait(inode);
551558
out:
552559
xfs_iunlock(ip, iolock);
553560

0 commit comments

Comments
 (0)