]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/xfs/xfs_file.c
Merge tag 'xfs-5.4-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux.git] / fs / xfs / xfs_file.c
index 28101bbc0b78fb814da4c1d5d345912db505a466..1ffb179f35d23ab5ae3bb12d98106430f6381034 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/falloc.h>
 #include <linux/backing-dev.h>
 #include <linux/mman.h>
+#include <linux/fadvise.h>
 
 static const struct vm_operations_struct xfs_file_vm_ops;
 
@@ -369,21 +370,23 @@ static int
 xfs_dio_write_end_io(
        struct kiocb            *iocb,
        ssize_t                 size,
+       int                     error,
        unsigned                flags)
 {
        struct inode            *inode = file_inode(iocb->ki_filp);
        struct xfs_inode        *ip = XFS_I(inode);
        loff_t                  offset = iocb->ki_pos;
        unsigned int            nofs_flag;
-       int                     error = 0;
 
        trace_xfs_end_io_direct_write(ip, offset, size);
 
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return -EIO;
 
-       if (size <= 0)
-               return size;
+       if (error)
+               return error;
+       if (!size)
+               return 0;
 
        /*
         * Capture amount written on completion as we can't reliably account
@@ -440,6 +443,10 @@ xfs_dio_write_end_io(
        return error;
 }
 
+static const struct iomap_dio_ops xfs_dio_write_ops = {
+       .end_io         = xfs_dio_write_end_io,
+};
+
 /*
  * xfs_file_dio_aio_write - handle direct IO writes
  *
@@ -540,7 +547,7 @@ xfs_file_dio_aio_write(
        }
 
        trace_xfs_file_direct_write(ip, count, iocb->ki_pos);
-       ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, xfs_dio_write_end_io);
+       ret = iomap_dio_rw(iocb, from, &xfs_iomap_ops, &xfs_dio_write_ops);
 
        /*
         * If unaligned, this is the only IO in-flight. If it has not yet
@@ -933,6 +940,30 @@ xfs_file_fallocate(
        return error;
 }
 
+STATIC int
+xfs_file_fadvise(
+       struct file     *file,
+       loff_t          start,
+       loff_t          end,
+       int             advice)
+{
+       struct xfs_inode *ip = XFS_I(file_inode(file));
+       int ret;
+       int lockflags = 0;
+
+       /*
+        * Operations creating pages in page cache need protection from hole
+        * punching and similar ops
+        */
+       if (advice == POSIX_FADV_WILLNEED) {
+               lockflags = XFS_IOLOCK_SHARED;
+               xfs_ilock(ip, lockflags);
+       }
+       ret = generic_fadvise(file, start, end, advice);
+       if (lockflags)
+               xfs_iunlock(ip, lockflags);
+       return ret;
+}
 
 STATIC loff_t
 xfs_file_remap_range(
@@ -1232,6 +1263,7 @@ const struct file_operations xfs_file_operations = {
        .fsync          = xfs_file_fsync,
        .get_unmapped_area = thp_get_unmapped_area,
        .fallocate      = xfs_file_fallocate,
+       .fadvise        = xfs_file_fadvise,
        .remap_file_range = xfs_file_remap_range,
 };