@@ -560,6 +560,72 @@ xfs_zoned_write_space_reserve(
560560 flags , ac );
561561}
562562
563+ /*
564+ * We need to lock the test/set EOF update as we can be racing with
565+ * other IO completions here to update the EOF. Failing to serialise
566+ * here can result in EOF moving backwards and Bad Things Happen when
567+ * that occurs.
568+ *
569+ * As IO completion only ever extends EOF, we can do an unlocked check
570+ * here to avoid taking the spinlock. If we land within the current EOF,
571+ * then we do not need to do an extending update at all, and we don't
572+ * need to take the lock to check this. If we race with an update moving
573+ * EOF, then we'll either still be beyond EOF and need to take the lock,
574+ * or we'll be within EOF and we don't need to take it at all.
575+ */
576+ static int
577+ xfs_dio_endio_set_isize (
578+ struct inode * inode ,
579+ loff_t offset ,
580+ ssize_t size )
581+ {
582+ struct xfs_inode * ip = XFS_I (inode );
583+
584+ if (offset + size <= i_size_read (inode ))
585+ return 0 ;
586+
587+ spin_lock (& ip -> i_flags_lock );
588+ if (offset + size <= i_size_read (inode )) {
589+ spin_unlock (& ip -> i_flags_lock );
590+ return 0 ;
591+ }
592+
593+ i_size_write (inode , offset + size );
594+ spin_unlock (& ip -> i_flags_lock );
595+
596+ return xfs_setfilesize (ip , offset , size );
597+ }
598+
599+ static int
600+ xfs_zoned_dio_write_end_io (
601+ struct kiocb * iocb ,
602+ ssize_t size ,
603+ int error ,
604+ unsigned flags )
605+ {
606+ struct inode * inode = file_inode (iocb -> ki_filp );
607+ struct xfs_inode * ip = XFS_I (inode );
608+ unsigned int nofs_flag ;
609+
610+ ASSERT (!(flags & (IOMAP_DIO_UNWRITTEN | IOMAP_DIO_COW )));
611+
612+ trace_xfs_end_io_direct_write (ip , iocb -> ki_pos , size );
613+
614+ if (xfs_is_shutdown (ip -> i_mount ))
615+ return - EIO ;
616+
617+ if (error || !size )
618+ return error ;
619+
620+ XFS_STATS_ADD (ip -> i_mount , xs_write_bytes , size );
621+
622+ nofs_flag = memalloc_nofs_save ();
623+ error = xfs_dio_endio_set_isize (inode , iocb -> ki_pos , size );
624+ memalloc_nofs_restore (nofs_flag );
625+
626+ return error ;
627+ }
628+
563629static int
564630xfs_dio_write_end_io (
565631 struct kiocb * iocb ,
@@ -572,8 +638,7 @@ xfs_dio_write_end_io(
572638 loff_t offset = iocb -> ki_pos ;
573639 unsigned int nofs_flag ;
574640
575- ASSERT (!xfs_is_zoned_inode (ip ) ||
576- !(flags & (IOMAP_DIO_UNWRITTEN | IOMAP_DIO_COW )));
641+ ASSERT (!xfs_is_zoned_inode (ip ));
577642
578643 trace_xfs_end_io_direct_write (ip , offset , size );
579644
@@ -623,30 +688,8 @@ xfs_dio_write_end_io(
623688 * with the on-disk inode size being outside the in-core inode size. We
624689 * have no other method of updating EOF for AIO, so always do it here
625690 * if necessary.
626- *
627- * We need to lock the test/set EOF update as we can be racing with
628- * other IO completions here to update the EOF. Failing to serialise
629- * here can result in EOF moving backwards and Bad Things Happen when
630- * that occurs.
631- *
632- * As IO completion only ever extends EOF, we can do an unlocked check
633- * here to avoid taking the spinlock. If we land within the current EOF,
634- * then we do not need to do an extending update at all, and we don't
635- * need to take the lock to check this. If we race with an update moving
636- * EOF, then we'll either still be beyond EOF and need to take the lock,
637- * or we'll be within EOF and we don't need to take it at all.
638691 */
639- if (offset + size <= i_size_read (inode ))
640- goto out ;
641-
642- spin_lock (& ip -> i_flags_lock );
643- if (offset + size > i_size_read (inode )) {
644- i_size_write (inode , offset + size );
645- spin_unlock (& ip -> i_flags_lock );
646- error = xfs_setfilesize (ip , offset , size );
647- } else {
648- spin_unlock (& ip -> i_flags_lock );
649- }
692+ error = xfs_dio_endio_set_isize (inode , offset , size );
650693
651694out :
652695 memalloc_nofs_restore (nofs_flag );
@@ -688,7 +731,7 @@ xfs_dio_zoned_submit_io(
688731static const struct iomap_dio_ops xfs_dio_zoned_write_ops = {
689732 .bio_set = & iomap_ioend_bioset ,
690733 .submit_io = xfs_dio_zoned_submit_io ,
691- .end_io = xfs_dio_write_end_io ,
734+ .end_io = xfs_zoned_dio_write_end_io ,
692735};
693736
694737/*
0 commit comments