diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-28 16:27:23 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-28 16:27:23 -0400 |
| commit | 02a2b05395dde2f49e7777b67b51a5fbc6606943 (patch) | |
| tree | 5d1aceee6e5a987772db092b27c49be67360fdb0 | |
| parent | e49aa15ef6c179f69e5578a271801f31a09e9a3f (diff) | |
| parent | 5e5c943c1f257c2b3424fc3f8a7b18570152dab3 (diff) | |
Merge tag 'xfs-4.14-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong:
- fix various problems with the copy-on-write extent maps getting freed
at the wrong time
- fix printk format specifier problems
- report zeroing operation outcomes instead of dropping them on the
floor
- fix some crashes when dio operations partially fail
- fix a race condition between unwritten extent conversion & dio read
- fix some incorrect tests in the inode log item processing
- correct the delayed allocation space reservations on rmap filesystems
- fix some problems checking for dax support
* tag 'xfs-4.14-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: revert "xfs: factor rmap btree size into the indlen calculations"
xfs: Capture state of the right inode in xfs_iflush_done
xfs: perag initialization should only touch m_ag_max_usable for AG 0
xfs: update i_size after unwritten conversion in dio completion
iomap_dio_rw: Allocate AIO completion queue before submitting dio
xfs: validate bdev support for DAX inode flag
xfs: remove redundant re-initialization of total_nr_pages
xfs: Output warning message when discard option was enabled even though the device does not support discard
xfs: report zeroed or not correctly in xfs_zero_range()
xfs: kill meaningless variable 'zero'
fs/xfs: Use %pS printk format for direct addresses
xfs: evict CoW fork extents when performing finsert/fcollapse
xfs: don't unconditionally clear the reflink flag on zero-block files
| -rw-r--r-- | fs/iomap.c | 14 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ag_resv.c | 12 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 17 | ||||
| -rw-r--r-- | fs/xfs/xfs_aops.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap_util.c | 14 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_error.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 39 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 8 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode_item.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_pnfs.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 10 |
15 files changed, 81 insertions, 56 deletions
diff --git a/fs/iomap.c b/fs/iomap.c index 8194d30bdca0..be61cf742b5e 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
| @@ -1009,6 +1009,13 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 1009 | WARN_ON_ONCE(ret); | 1009 | WARN_ON_ONCE(ret); |
| 1010 | ret = 0; | 1010 | ret = 0; |
| 1011 | 1011 | ||
| 1012 | if (iov_iter_rw(iter) == WRITE && !is_sync_kiocb(iocb) && | ||
| 1013 | !inode->i_sb->s_dio_done_wq) { | ||
| 1014 | ret = sb_init_dio_done_wq(inode->i_sb); | ||
| 1015 | if (ret < 0) | ||
| 1016 | goto out_free_dio; | ||
| 1017 | } | ||
| 1018 | |||
| 1012 | inode_dio_begin(inode); | 1019 | inode_dio_begin(inode); |
| 1013 | 1020 | ||
| 1014 | blk_start_plug(&plug); | 1021 | blk_start_plug(&plug); |
| @@ -1031,13 +1038,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, | |||
| 1031 | if (ret < 0) | 1038 | if (ret < 0) |
| 1032 | iomap_dio_set_error(dio, ret); | 1039 | iomap_dio_set_error(dio, ret); |
| 1033 | 1040 | ||
| 1034 | if (ret >= 0 && iov_iter_rw(iter) == WRITE && !is_sync_kiocb(iocb) && | ||
| 1035 | !inode->i_sb->s_dio_done_wq) { | ||
| 1036 | ret = sb_init_dio_done_wq(inode->i_sb); | ||
| 1037 | if (ret < 0) | ||
| 1038 | iomap_dio_set_error(dio, ret); | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | if (!atomic_dec_and_test(&dio->ref)) { | 1041 | if (!atomic_dec_and_test(&dio->ref)) { |
| 1042 | if (!is_sync_kiocb(iocb)) | 1042 | if (!is_sync_kiocb(iocb)) |
| 1043 | return -EIOCBQUEUED; | 1043 | return -EIOCBQUEUED; |
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c index b008ff3250eb..df3e600835e8 100644 --- a/fs/xfs/libxfs/xfs_ag_resv.c +++ b/fs/xfs/libxfs/xfs_ag_resv.c | |||
| @@ -156,7 +156,8 @@ __xfs_ag_resv_free( | |||
| 156 | trace_xfs_ag_resv_free(pag, type, 0); | 156 | trace_xfs_ag_resv_free(pag, type, 0); |
| 157 | 157 | ||
| 158 | resv = xfs_perag_resv(pag, type); | 158 | resv = xfs_perag_resv(pag, type); |
| 159 | pag->pag_mount->m_ag_max_usable += resv->ar_asked; | 159 | if (pag->pag_agno == 0) |
| 160 | pag->pag_mount->m_ag_max_usable += resv->ar_asked; | ||
| 160 | /* | 161 | /* |
| 161 | * AGFL blocks are always considered "free", so whatever | 162 | * AGFL blocks are always considered "free", so whatever |
| 162 | * was reserved at mount time must be given back at umount. | 163 | * was reserved at mount time must be given back at umount. |
| @@ -216,7 +217,14 @@ __xfs_ag_resv_init( | |||
| 216 | return error; | 217 | return error; |
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | mp->m_ag_max_usable -= ask; | 220 | /* |
| 221 | * Reduce the maximum per-AG allocation length by however much we're | ||
| 222 | * trying to reserve for an AG. Since this is a filesystem-wide | ||
| 223 | * counter, we only make the adjustment for AG 0. This assumes that | ||
| 224 | * there aren't any AGs hungrier for per-AG reservation than AG 0. | ||
| 225 | */ | ||
| 226 | if (pag->pag_agno == 0) | ||
| 227 | mp->m_ag_max_usable -= ask; | ||
| 220 | 228 | ||
| 221 | resv = xfs_perag_resv(pag, type); | 229 | resv = xfs_perag_resv(pag, type); |
| 222 | resv->ar_asked = ask; | 230 | resv->ar_asked = ask; |
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 459f4b4f08fe..044a363119be 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
| @@ -49,7 +49,6 @@ | |||
| 49 | #include "xfs_rmap.h" | 49 | #include "xfs_rmap.h" |
| 50 | #include "xfs_ag_resv.h" | 50 | #include "xfs_ag_resv.h" |
| 51 | #include "xfs_refcount.h" | 51 | #include "xfs_refcount.h" |
| 52 | #include "xfs_rmap_btree.h" | ||
| 53 | #include "xfs_icache.h" | 52 | #include "xfs_icache.h" |
| 54 | 53 | ||
| 55 | 54 | ||
| @@ -192,12 +191,8 @@ xfs_bmap_worst_indlen( | |||
| 192 | int maxrecs; /* maximum record count at this level */ | 191 | int maxrecs; /* maximum record count at this level */ |
| 193 | xfs_mount_t *mp; /* mount structure */ | 192 | xfs_mount_t *mp; /* mount structure */ |
| 194 | xfs_filblks_t rval; /* return value */ | 193 | xfs_filblks_t rval; /* return value */ |
| 195 | xfs_filblks_t orig_len; | ||
| 196 | 194 | ||
| 197 | mp = ip->i_mount; | 195 | mp = ip->i_mount; |
| 198 | |||
| 199 | /* Calculate the worst-case size of the bmbt. */ | ||
| 200 | orig_len = len; | ||
| 201 | maxrecs = mp->m_bmap_dmxr[0]; | 196 | maxrecs = mp->m_bmap_dmxr[0]; |
| 202 | for (level = 0, rval = 0; | 197 | for (level = 0, rval = 0; |
| 203 | level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK); | 198 | level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK); |
| @@ -205,20 +200,12 @@ xfs_bmap_worst_indlen( | |||
| 205 | len += maxrecs - 1; | 200 | len += maxrecs - 1; |
| 206 | do_div(len, maxrecs); | 201 | do_div(len, maxrecs); |
| 207 | rval += len; | 202 | rval += len; |
| 208 | if (len == 1) { | 203 | if (len == 1) |
| 209 | rval += XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - | 204 | return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - |
| 210 | level - 1; | 205 | level - 1; |
| 211 | break; | ||
| 212 | } | ||
| 213 | if (level == 0) | 206 | if (level == 0) |
| 214 | maxrecs = mp->m_bmap_dmxr[1]; | 207 | maxrecs = mp->m_bmap_dmxr[1]; |
| 215 | } | 208 | } |
| 216 | |||
| 217 | /* Calculate the worst-case size of the rmapbt. */ | ||
| 218 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) | ||
| 219 | rval += 1 + xfs_rmapbt_calc_size(mp, orig_len) + | ||
| 220 | mp->m_rmap_maxlevels; | ||
| 221 | |||
| 222 | return rval; | 209 | return rval; |
| 223 | } | 210 | } |
| 224 | 211 | ||
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 29172609f2a3..f18e5932aec4 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
| @@ -343,7 +343,8 @@ xfs_end_io( | |||
| 343 | error = xfs_reflink_end_cow(ip, offset, size); | 343 | error = xfs_reflink_end_cow(ip, offset, size); |
| 344 | break; | 344 | break; |
| 345 | case XFS_IO_UNWRITTEN: | 345 | case XFS_IO_UNWRITTEN: |
| 346 | error = xfs_iomap_write_unwritten(ip, offset, size); | 346 | /* writeback should never update isize */ |
| 347 | error = xfs_iomap_write_unwritten(ip, offset, size, false); | ||
| 347 | break; | 348 | break; |
| 348 | default: | 349 | default: |
| 349 | ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans); | 350 | ASSERT(!xfs_ioend_is_append(ioend) || ioend->io_append_trans); |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index cd9a5400ba4f..bc6c6e10a969 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
| @@ -1459,7 +1459,19 @@ xfs_shift_file_space( | |||
| 1459 | return error; | 1459 | return error; |
| 1460 | 1460 | ||
| 1461 | /* | 1461 | /* |
| 1462 | * The extent shiting code works on extent granularity. So, if | 1462 | * Clean out anything hanging around in the cow fork now that |
| 1463 | * we've flushed all the dirty data out to disk to avoid having | ||
| 1464 | * CoW extents at the wrong offsets. | ||
| 1465 | */ | ||
| 1466 | if (xfs_is_reflink_inode(ip)) { | ||
| 1467 | error = xfs_reflink_cancel_cow_range(ip, offset, NULLFILEOFF, | ||
| 1468 | true); | ||
| 1469 | if (error) | ||
| 1470 | return error; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | /* | ||
| 1474 | * The extent shifting code works on extent granularity. So, if | ||
| 1463 | * stop_fsb is not the starting block of extent, we need to split | 1475 | * stop_fsb is not the starting block of extent, we need to split |
| 1464 | * the extent at stop_fsb. | 1476 | * the extent at stop_fsb. |
| 1465 | */ | 1477 | */ |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index da14658da310..2f97c12ca75e 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -1258,8 +1258,6 @@ xfs_buf_ioapply_map( | |||
| 1258 | int size; | 1258 | int size; |
| 1259 | int offset; | 1259 | int offset; |
| 1260 | 1260 | ||
| 1261 | total_nr_pages = bp->b_page_count; | ||
| 1262 | |||
| 1263 | /* skip the pages in the buffer before the start offset */ | 1261 | /* skip the pages in the buffer before the start offset */ |
| 1264 | page_index = 0; | 1262 | page_index = 0; |
| 1265 | offset = *buf_offset; | 1263 | offset = *buf_offset; |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index bd786a9ac2c3..eaf86f55b7f2 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
| @@ -347,7 +347,7 @@ xfs_verifier_error( | |||
| 347 | { | 347 | { |
| 348 | struct xfs_mount *mp = bp->b_target->bt_mount; | 348 | struct xfs_mount *mp = bp->b_target->bt_mount; |
| 349 | 349 | ||
| 350 | xfs_alert(mp, "Metadata %s detected at %pF, %s block 0x%llx", | 350 | xfs_alert(mp, "Metadata %s detected at %pS, %s block 0x%llx", |
| 351 | bp->b_error == -EFSBADCRC ? "CRC error" : "corruption", | 351 | bp->b_error == -EFSBADCRC ? "CRC error" : "corruption", |
| 352 | __return_address, bp->b_ops->name, bp->b_bn); | 352 | __return_address, bp->b_ops->name, bp->b_bn); |
| 353 | 353 | ||
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ebdd0bd2b261..309e26c9dddb 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -58,7 +58,7 @@ xfs_zero_range( | |||
| 58 | xfs_off_t count, | 58 | xfs_off_t count, |
| 59 | bool *did_zero) | 59 | bool *did_zero) |
| 60 | { | 60 | { |
| 61 | return iomap_zero_range(VFS_I(ip), pos, count, NULL, &xfs_iomap_ops); | 61 | return iomap_zero_range(VFS_I(ip), pos, count, did_zero, &xfs_iomap_ops); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | int | 64 | int |
| @@ -377,8 +377,6 @@ restart: | |||
| 377 | */ | 377 | */ |
| 378 | spin_lock(&ip->i_flags_lock); | 378 | spin_lock(&ip->i_flags_lock); |
| 379 | if (iocb->ki_pos > i_size_read(inode)) { | 379 | if (iocb->ki_pos > i_size_read(inode)) { |
| 380 | bool zero = false; | ||
| 381 | |||
| 382 | spin_unlock(&ip->i_flags_lock); | 380 | spin_unlock(&ip->i_flags_lock); |
| 383 | if (!drained_dio) { | 381 | if (!drained_dio) { |
| 384 | if (*iolock == XFS_IOLOCK_SHARED) { | 382 | if (*iolock == XFS_IOLOCK_SHARED) { |
| @@ -399,7 +397,7 @@ restart: | |||
| 399 | drained_dio = true; | 397 | drained_dio = true; |
| 400 | goto restart; | 398 | goto restart; |
| 401 | } | 399 | } |
| 402 | error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero); | 400 | error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), NULL); |
| 403 | if (error) | 401 | if (error) |
| 404 | return error; | 402 | return error; |
| 405 | } else | 403 | } else |
| @@ -436,7 +434,6 @@ xfs_dio_write_end_io( | |||
| 436 | struct inode *inode = file_inode(iocb->ki_filp); | 434 | struct inode *inode = file_inode(iocb->ki_filp); |
| 437 | struct xfs_inode *ip = XFS_I(inode); | 435 | struct xfs_inode *ip = XFS_I(inode); |
| 438 | loff_t offset = iocb->ki_pos; | 436 | loff_t offset = iocb->ki_pos; |
| 439 | bool update_size = false; | ||
| 440 | int error = 0; | 437 | int error = 0; |
| 441 | 438 | ||
| 442 | trace_xfs_end_io_direct_write(ip, offset, size); | 439 | trace_xfs_end_io_direct_write(ip, offset, size); |
| @@ -447,6 +444,21 @@ xfs_dio_write_end_io( | |||
| 447 | if (size <= 0) | 444 | if (size <= 0) |
| 448 | return size; | 445 | return size; |
| 449 | 446 | ||
| 447 | if (flags & IOMAP_DIO_COW) { | ||
| 448 | error = xfs_reflink_end_cow(ip, offset, size); | ||
| 449 | if (error) | ||
| 450 | return error; | ||
| 451 | } | ||
| 452 | |||
| 453 | /* | ||
| 454 | * Unwritten conversion updates the in-core isize after extent | ||
| 455 | * conversion but before updating the on-disk size. Updating isize any | ||
| 456 | * earlier allows a racing dio read to find unwritten extents before | ||
| 457 | * they are converted. | ||
| 458 | */ | ||
| 459 | if (flags & IOMAP_DIO_UNWRITTEN) | ||
| 460 | return xfs_iomap_write_unwritten(ip, offset, size, true); | ||
| 461 | |||
| 450 | /* | 462 | /* |
| 451 | * We need to update the in-core inode size here so that we don't end up | 463 | * We need to update the in-core inode size here so that we don't end up |
| 452 | * with the on-disk inode size being outside the in-core inode size. We | 464 | * with the on-disk inode size being outside the in-core inode size. We |
| @@ -461,20 +473,11 @@ xfs_dio_write_end_io( | |||
| 461 | spin_lock(&ip->i_flags_lock); | 473 | spin_lock(&ip->i_flags_lock); |
| 462 | if (offset + size > i_size_read(inode)) { | 474 | if (offset + size > i_size_read(inode)) { |
| 463 | i_size_write(inode, offset + size); | 475 | i_size_write(inode, offset + size); |
| 464 | update_size = true; | 476 | spin_unlock(&ip->i_flags_lock); |
| 465 | } | ||
| 466 | spin_unlock(&ip->i_flags_lock); | ||
| 467 | |||
| 468 | if (flags & IOMAP_DIO_COW) { | ||
| 469 | error = xfs_reflink_end_cow(ip, offset, size); | ||
| 470 | if (error) | ||
| 471 | return error; | ||
| 472 | } | ||
| 473 | |||
| 474 | if (flags & IOMAP_DIO_UNWRITTEN) | ||
| 475 | error = xfs_iomap_write_unwritten(ip, offset, size); | ||
| 476 | else if (update_size) | ||
| 477 | error = xfs_setfilesize(ip, offset, size); | 477 | error = xfs_setfilesize(ip, offset, size); |
| 478 | } else { | ||
| 479 | spin_unlock(&ip->i_flags_lock); | ||
| 480 | } | ||
| 478 | 481 | ||
| 479 | return error; | 482 | return error; |
| 480 | } | 483 | } |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5599dda4727a..4ec5b7f45401 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -1624,10 +1624,12 @@ xfs_itruncate_extents( | |||
| 1624 | goto out; | 1624 | goto out; |
| 1625 | 1625 | ||
| 1626 | /* | 1626 | /* |
| 1627 | * Clear the reflink flag if we truncated everything. | 1627 | * Clear the reflink flag if there are no data fork blocks and |
| 1628 | * there are no extents staged in the cow fork. | ||
| 1628 | */ | 1629 | */ |
| 1629 | if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip)) { | 1630 | if (xfs_is_reflink_inode(ip) && ip->i_cnextents == 0) { |
| 1630 | ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; | 1631 | if (ip->i_d.di_nblocks == 0) |
| 1632 | ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; | ||
| 1631 | xfs_inode_clear_cowblocks_tag(ip); | 1633 | xfs_inode_clear_cowblocks_tag(ip); |
| 1632 | } | 1634 | } |
| 1633 | 1635 | ||
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 6d0f74ec31e8..a705f34b58fa 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
| @@ -745,7 +745,7 @@ xfs_iflush_done( | |||
| 745 | */ | 745 | */ |
| 746 | iip = INODE_ITEM(blip); | 746 | iip = INODE_ITEM(blip); |
| 747 | if ((iip->ili_logged && blip->li_lsn == iip->ili_flush_lsn) || | 747 | if ((iip->ili_logged && blip->li_lsn == iip->ili_flush_lsn) || |
| 748 | lip->li_flags & XFS_LI_FAILED) | 748 | (blip->li_flags & XFS_LI_FAILED)) |
| 749 | need_ail++; | 749 | need_ail++; |
| 750 | 750 | ||
| 751 | blip = next; | 751 | blip = next; |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 5049e8ab6e30..aa75389be8cf 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -1088,6 +1088,7 @@ xfs_ioctl_setattr_dax_invalidate( | |||
| 1088 | int *join_flags) | 1088 | int *join_flags) |
| 1089 | { | 1089 | { |
| 1090 | struct inode *inode = VFS_I(ip); | 1090 | struct inode *inode = VFS_I(ip); |
| 1091 | struct super_block *sb = inode->i_sb; | ||
| 1091 | int error; | 1092 | int error; |
| 1092 | 1093 | ||
| 1093 | *join_flags = 0; | 1094 | *join_flags = 0; |
| @@ -1100,7 +1101,7 @@ xfs_ioctl_setattr_dax_invalidate( | |||
| 1100 | if (fa->fsx_xflags & FS_XFLAG_DAX) { | 1101 | if (fa->fsx_xflags & FS_XFLAG_DAX) { |
| 1101 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) | 1102 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) |
| 1102 | return -EINVAL; | 1103 | return -EINVAL; |
| 1103 | if (ip->i_mount->m_sb.sb_blocksize != PAGE_SIZE) | 1104 | if (bdev_dax_supported(sb, sb->s_blocksize) < 0) |
| 1104 | return -EINVAL; | 1105 | return -EINVAL; |
| 1105 | } | 1106 | } |
| 1106 | 1107 | ||
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index a1909bc064e9..f179bdf1644d 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -829,7 +829,8 @@ int | |||
| 829 | xfs_iomap_write_unwritten( | 829 | xfs_iomap_write_unwritten( |
| 830 | xfs_inode_t *ip, | 830 | xfs_inode_t *ip, |
| 831 | xfs_off_t offset, | 831 | xfs_off_t offset, |
| 832 | xfs_off_t count) | 832 | xfs_off_t count, |
| 833 | bool update_isize) | ||
| 833 | { | 834 | { |
| 834 | xfs_mount_t *mp = ip->i_mount; | 835 | xfs_mount_t *mp = ip->i_mount; |
| 835 | xfs_fileoff_t offset_fsb; | 836 | xfs_fileoff_t offset_fsb; |
| @@ -840,6 +841,7 @@ xfs_iomap_write_unwritten( | |||
| 840 | xfs_trans_t *tp; | 841 | xfs_trans_t *tp; |
| 841 | xfs_bmbt_irec_t imap; | 842 | xfs_bmbt_irec_t imap; |
| 842 | struct xfs_defer_ops dfops; | 843 | struct xfs_defer_ops dfops; |
| 844 | struct inode *inode = VFS_I(ip); | ||
| 843 | xfs_fsize_t i_size; | 845 | xfs_fsize_t i_size; |
| 844 | uint resblks; | 846 | uint resblks; |
| 845 | int error; | 847 | int error; |
| @@ -899,7 +901,8 @@ xfs_iomap_write_unwritten( | |||
| 899 | i_size = XFS_FSB_TO_B(mp, offset_fsb + count_fsb); | 901 | i_size = XFS_FSB_TO_B(mp, offset_fsb + count_fsb); |
| 900 | if (i_size > offset + count) | 902 | if (i_size > offset + count) |
| 901 | i_size = offset + count; | 903 | i_size = offset + count; |
| 902 | 904 | if (update_isize && i_size > i_size_read(inode)) | |
| 905 | i_size_write(inode, i_size); | ||
| 903 | i_size = xfs_new_eof(ip, i_size); | 906 | i_size = xfs_new_eof(ip, i_size); |
| 904 | if (i_size) { | 907 | if (i_size) { |
| 905 | ip->i_d.di_size = i_size; | 908 | ip->i_d.di_size = i_size; |
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 00db3ecea084..ee535065c5d0 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
| @@ -27,7 +27,7 @@ int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, | |||
| 27 | struct xfs_bmbt_irec *, int); | 27 | struct xfs_bmbt_irec *, int); |
| 28 | int xfs_iomap_write_allocate(struct xfs_inode *, int, xfs_off_t, | 28 | int xfs_iomap_write_allocate(struct xfs_inode *, int, xfs_off_t, |
| 29 | struct xfs_bmbt_irec *); | 29 | struct xfs_bmbt_irec *); |
| 30 | int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t); | 30 | int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t, bool); |
| 31 | 31 | ||
| 32 | void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, | 32 | void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, |
| 33 | struct xfs_bmbt_irec *); | 33 | struct xfs_bmbt_irec *); |
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index 2f2dc3c09ad0..4246876df7b7 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c | |||
| @@ -274,7 +274,7 @@ xfs_fs_commit_blocks( | |||
| 274 | (end - 1) >> PAGE_SHIFT); | 274 | (end - 1) >> PAGE_SHIFT); |
| 275 | WARN_ON_ONCE(error); | 275 | WARN_ON_ONCE(error); |
| 276 | 276 | ||
| 277 | error = xfs_iomap_write_unwritten(ip, start, length); | 277 | error = xfs_iomap_write_unwritten(ip, start, length, false); |
| 278 | if (error) | 278 | if (error) |
| 279 | goto out_drop_iolock; | 279 | goto out_drop_iolock; |
| 280 | } | 280 | } |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index c996f4ae4a5f..584cf2d573ba 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
| @@ -1654,6 +1654,16 @@ xfs_fs_fill_super( | |||
| 1654 | "DAX and reflink have not been tested together!"); | 1654 | "DAX and reflink have not been tested together!"); |
| 1655 | } | 1655 | } |
| 1656 | 1656 | ||
| 1657 | if (mp->m_flags & XFS_MOUNT_DISCARD) { | ||
| 1658 | struct request_queue *q = bdev_get_queue(sb->s_bdev); | ||
| 1659 | |||
| 1660 | if (!blk_queue_discard(q)) { | ||
| 1661 | xfs_warn(mp, "mounting with \"discard\" option, but " | ||
| 1662 | "the device does not support discard"); | ||
| 1663 | mp->m_flags &= ~XFS_MOUNT_DISCARD; | ||
| 1664 | } | ||
| 1665 | } | ||
| 1666 | |||
| 1657 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { | 1667 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { |
| 1658 | if (mp->m_sb.sb_rblocks) { | 1668 | if (mp->m_sb.sb_rblocks) { |
| 1659 | xfs_alert(mp, | 1669 | xfs_alert(mp, |
