#include <linux/writeback.h>
#include <linux/swap.h>
#include <linux/migrate.h>
+#include <linux/fserror.h>
#include "internal.h"
#include "trace.h"
if (folio_test_uptodate(folio))
return 0;
- if (WARN_ON_ONCE(size > iomap->length))
+ if (WARN_ON_ONCE(size > iomap->length)) {
+ fserror_report_io(iter->inode, FSERR_BUFFERED_READ,
+ iomap->offset, size, -EIO, GFP_NOFS);
return -EIO;
+ }
if (offset > 0)
ifs_alloc(iter->inode, folio, iter->flags);
spin_unlock_irqrestore(&ifs->state_lock, flags);
}
+ if (error)
+ fserror_report_io(folio->mapping->host, FSERR_BUFFERED_READ,
+ folio_pos(folio) + off, len, error,
+ GFP_ATOMIC);
+
if (finished)
folio_end_read(folio, uptodate);
}
if (!*bytes_submitted)
iomap_read_init(folio);
ret = ctx->ops->read_folio_range(iter, ctx, plen);
+ if (ret < 0)
+ fserror_report_io(iter->inode,
+ FSERR_BUFFERED_READ, pos,
+ plen, ret, GFP_NOFS);
if (ret)
return ret;
*bytes_submitted += plen;
else
status = iomap_bio_read_folio_range_sync(iter,
folio, block_start, plen);
+ if (status < 0)
+ fserror_report_io(iter->inode,
+ FSERR_BUFFERED_READ, pos,
+ len, status, GFP_NOFS);
if (status)
return status;
}
u64 pos = folio_pos(folio);
u64 end_pos = pos + folio_size(folio);
u64 end_aligned = 0;
+ loff_t orig_pos = pos;
size_t bytes_submitted = 0;
int error = 0;
u32 rlen;
if (bytes_submitted)
wpc->nr_folios++;
+ if (error && pos > orig_pos)
+ fserror_report_io(inode, FSERR_BUFFERED_WRITE, orig_pos, 0,
+ error, GFP_NOFS);
/*
* We can have dirty bits set past end of file in page_mkwrite path
#include <linux/pagemap.h>
#include <linux/iomap.h>
#include <linux/task_io_accounting_ops.h>
+#include <linux/fserror.h>
#include "internal.h"
#include "trace.h"
}
}
+static inline enum fserror_type iomap_dio_err_type(const struct iomap_dio *dio)
+{
+ if (dio->flags & IOMAP_DIO_WRITE)
+ return FSERR_DIRECTIO_WRITE;
+ return FSERR_DIRECTIO_READ;
+}
+
ssize_t iomap_dio_complete(struct iomap_dio *dio)
{
const struct iomap_dio_ops *dops = dio->dops;
if (dops && dops->end_io)
ret = dops->end_io(iocb, dio->size, ret, dio->flags);
+ if (dio->error)
+ fserror_report_io(file_inode(iocb->ki_filp),
+ iomap_dio_err_type(dio), offset, dio->size,
+ dio->error, GFP_NOFS);
if (likely(!ret)) {
ret = dio->size;
#include <linux/list_sort.h>
#include <linux/pagemap.h>
#include <linux/writeback.h>
+#include <linux/fserror.h>
#include "internal.h"
#include "trace.h"
/* walk all folios in bio, ending page IO on them */
bio_for_each_folio_all(fi, bio) {
+ if (ioend->io_error)
+ fserror_report_io(inode, FSERR_BUFFERED_WRITE,
+ folio_pos(fi.folio) + fi.offset,
+ fi.length, ioend->io_error,
+ GFP_ATOMIC);
iomap_finish_folio_write(inode, fi.folio, fi.length);
folio_count++;
}