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, |