Introduce RWF_RECOVERY_DATA flag to preadv2() and pwritev2() for the purpose of recovering data loss due to dax media error. Hence the functionality ties to the underlying media and driver with capability to clear media error(s) on the fly. When this flag is provided with preadv2(), preadv2() will attempt to read as much data as possible until the poisoned page is encountered. When the flag is provided with pwritev2(), pwritev2() will attempt to clear media error within the user specified range and then write the user provided data to the range. Both the range and length parameters must be page aligned in order get the recovery process to work. Signed-off-by: Jane Chu <jane.chu@xxxxxxxxxx> --- fs/dax.c | 3 +++ include/linux/fs.h | 1 + include/linux/iomap.h | 1 + include/uapi/linux/fs.h | 5 ++++- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/dax.c b/fs/dax.c index 4e3e5a283a91..01118de00011 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1288,6 +1288,9 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter, if (iocb->ki_flags & IOCB_NOWAIT) iomi.flags |= IOMAP_NOWAIT; + if (iocb->ki_flags & IOCB_RECOVERY) + iomi.flags |= IOMAP_RECOVERY; + while ((ret = iomap_iter(&iomi, ops)) > 0) iomi.processed = dax_iomap_iter(&iomi, iter); diff --git a/include/linux/fs.h b/include/linux/fs.h index e7a633353fd2..ae138649cbe3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -311,6 +311,7 @@ enum rw_hint { #define IOCB_SYNC (__force int) RWF_SYNC #define IOCB_NOWAIT (__force int) RWF_NOWAIT #define IOCB_APPEND (__force int) RWF_APPEND +#define IOCB_RECOVERY (__force int) RWF_RECOVERY_DATA /* non-RWF related bits - start at 16 */ #define IOCB_EVENTFD (1 << 16) diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 24f8489583ca..c13d23328140 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -141,6 +141,7 @@ struct iomap_page_ops { #define IOMAP_NOWAIT (1 << 5) /* do not block */ #define IOMAP_OVERWRITE_ONLY (1 << 6) /* only pure overwrites allowed */ #define IOMAP_UNSHARE (1 << 7) /* unshare_file_range */ +#define IOMAP_RECOVERY (1 << 8) /* data recovery */ struct iomap_ops { /* diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index bdf7b404b3e7..febec55ea4b8 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -301,8 +301,11 @@ typedef int __bitwise __kernel_rwf_t; /* per-IO O_APPEND */ #define RWF_APPEND ((__force __kernel_rwf_t)0x00000010) +/* per-IO for data recovery */ +#define RWF_RECOVERY_DATA ((__force __kernel_rwf_t)0x00000020) + /* mask of flags supported by the kernel */ #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\ - RWF_APPEND) + RWF_APPEND | RWF_RECOVERY_DATA) #endif /* _UAPI_LINUX_FS_H */ -- 2.18.4