diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 45 |
1 files changed, 11 insertions, 34 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f675f3d9d7b3..86d5dc260464 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -327,7 +327,7 @@ xfs_file_aio_read( | |||
327 | mp->m_rtdev_targp : mp->m_ddev_targp; | 327 | mp->m_rtdev_targp : mp->m_ddev_targp; |
328 | if ((iocb->ki_pos & target->bt_smask) || | 328 | if ((iocb->ki_pos & target->bt_smask) || |
329 | (size & target->bt_smask)) { | 329 | (size & target->bt_smask)) { |
330 | if (iocb->ki_pos == ip->i_size) | 330 | if (iocb->ki_pos == i_size_read(inode)) |
331 | return 0; | 331 | return 0; |
332 | return -XFS_ERROR(EINVAL); | 332 | return -XFS_ERROR(EINVAL); |
333 | } | 333 | } |
@@ -412,30 +412,6 @@ xfs_file_splice_read( | |||
412 | return ret; | 412 | return ret; |
413 | } | 413 | } |
414 | 414 | ||
415 | STATIC void | ||
416 | xfs_aio_write_isize_update( | ||
417 | struct inode *inode, | ||
418 | loff_t *ppos, | ||
419 | ssize_t bytes_written) | ||
420 | { | ||
421 | struct xfs_inode *ip = XFS_I(inode); | ||
422 | xfs_fsize_t isize = i_size_read(inode); | ||
423 | |||
424 | if (bytes_written > 0) | ||
425 | XFS_STATS_ADD(xs_write_bytes, bytes_written); | ||
426 | |||
427 | if (unlikely(bytes_written < 0 && bytes_written != -EFAULT && | ||
428 | *ppos > isize)) | ||
429 | *ppos = isize; | ||
430 | |||
431 | if (*ppos > ip->i_size) { | ||
432 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | ||
433 | if (*ppos > ip->i_size) | ||
434 | ip->i_size = *ppos; | ||
435 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | /* | 415 | /* |
440 | * If this was a direct or synchronous I/O that failed (such as ENOSPC) then | 416 | * If this was a direct or synchronous I/O that failed (such as ENOSPC) then |
441 | * part of the I/O may have been written to disk before the error occurred. In | 417 | * part of the I/O may have been written to disk before the error occurred. In |
@@ -451,8 +427,8 @@ xfs_aio_write_newsize_update( | |||
451 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); | 427 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL); |
452 | if (new_size == ip->i_new_size) | 428 | if (new_size == ip->i_new_size) |
453 | ip->i_new_size = 0; | 429 | ip->i_new_size = 0; |
454 | if (ip->i_d.di_size > ip->i_size) | 430 | if (ip->i_d.di_size > i_size_read(VFS_I(ip))) |
455 | ip->i_d.di_size = ip->i_size; | 431 | ip->i_d.di_size = i_size_read(VFS_I(ip)); |
456 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); | 432 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL); |
457 | } | 433 | } |
458 | } | 434 | } |
@@ -492,15 +468,16 @@ xfs_file_splice_write( | |||
492 | new_size = *ppos + count; | 468 | new_size = *ppos + count; |
493 | 469 | ||
494 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 470 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
495 | if (new_size > ip->i_size) | 471 | if (new_size > i_size_read(inode)) |
496 | ip->i_new_size = new_size; | 472 | ip->i_new_size = new_size; |
497 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 473 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
498 | 474 | ||
499 | trace_xfs_file_splice_write(ip, count, *ppos, ioflags); | 475 | trace_xfs_file_splice_write(ip, count, *ppos, ioflags); |
500 | 476 | ||
501 | ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); | 477 | ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags); |
478 | if (ret > 0) | ||
479 | XFS_STATS_ADD(xs_write_bytes, ret); | ||
502 | 480 | ||
503 | xfs_aio_write_isize_update(inode, ppos, ret); | ||
504 | xfs_aio_write_newsize_update(ip, new_size); | 481 | xfs_aio_write_newsize_update(ip, new_size); |
505 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 482 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
506 | return ret; | 483 | return ret; |
@@ -728,14 +705,14 @@ restart: | |||
728 | * values are still valid. | 705 | * values are still valid. |
729 | */ | 706 | */ |
730 | if ((ip->i_new_size && *pos > ip->i_new_size) || | 707 | if ((ip->i_new_size && *pos > ip->i_new_size) || |
731 | (!ip->i_new_size && *pos > ip->i_size)) { | 708 | (!ip->i_new_size && *pos > i_size_read(inode))) { |
732 | if (*iolock == XFS_IOLOCK_SHARED) { | 709 | if (*iolock == XFS_IOLOCK_SHARED) { |
733 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); | 710 | xfs_rw_iunlock(ip, XFS_ILOCK_EXCL | *iolock); |
734 | *iolock = XFS_IOLOCK_EXCL; | 711 | *iolock = XFS_IOLOCK_EXCL; |
735 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); | 712 | xfs_rw_ilock(ip, XFS_ILOCK_EXCL | *iolock); |
736 | goto restart; | 713 | goto restart; |
737 | } | 714 | } |
738 | error = -xfs_zero_eof(ip, *pos, ip->i_size); | 715 | error = -xfs_zero_eof(ip, *pos, i_size_read(inode)); |
739 | } | 716 | } |
740 | 717 | ||
741 | /* | 718 | /* |
@@ -744,7 +721,7 @@ restart: | |||
744 | * ip->i_new_size if this IO ends beyond any other in-flight writes. | 721 | * ip->i_new_size if this IO ends beyond any other in-flight writes. |
745 | */ | 722 | */ |
746 | new_size = *pos + *count; | 723 | new_size = *pos + *count; |
747 | if (new_size > ip->i_size) { | 724 | if (new_size > i_size_read(inode)) { |
748 | if (new_size > ip->i_new_size) | 725 | if (new_size > ip->i_new_size) |
749 | ip->i_new_size = new_size; | 726 | ip->i_new_size = new_size; |
750 | *new_sizep = new_size; | 727 | *new_sizep = new_size; |
@@ -957,11 +934,11 @@ xfs_file_aio_write( | |||
957 | ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos, | 934 | ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos, |
958 | ocount, &new_size, &iolock); | 935 | ocount, &new_size, &iolock); |
959 | 936 | ||
960 | xfs_aio_write_isize_update(inode, &iocb->ki_pos, ret); | ||
961 | |||
962 | if (ret <= 0) | 937 | if (ret <= 0) |
963 | goto out_unlock; | 938 | goto out_unlock; |
964 | 939 | ||
940 | XFS_STATS_ADD(xs_write_bytes, ret); | ||
941 | |||
965 | /* Handle various SYNC-type writes */ | 942 | /* Handle various SYNC-type writes */ |
966 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { | 943 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { |
967 | loff_t end = pos + ret - 1; | 944 | loff_t end = pos + ret - 1; |