Enable zone-append using existing O_APPEND and RWF_APPEND. Zone-append is similar to appending writes, but requires written-location to be returned, in order to be effective. Returning completion-result requires bit of additional processing in common path. Also, we guarantee that zone-append does not cause a short write, which is not the case with regular appending-write. Therefore make the feature opt-in by introducing new FMODE_ZONE_APPEND mode (kernel-only) and IOCB_ZONE_APPEND flag. When a file is opened, it can opt in for zone-append by setting FMODE_ZONE_APPEND. If file has opted in, and receives write that meets file-append criteria (RWF_APPEND write or O_APPEND open), set IOCB_ZONE_APPEND in kiocb->ki_flag, apart from existing IOCB_APPEND. IOCB_ZONE_APPEND is meant to isolate the code that returns written-location with appending write. Signed-off-by: Kanchan Joshi <joshi.k@xxxxxxxxxxx> Signed-off-by: Selvakumar S <selvakuma.s1@xxxxxxxxxxx> Signed-off-by: Nitesh Shetty <nj.shetty@xxxxxxxxxxx> Signed-off-by: Javier Gonzalez <javier.gonz@xxxxxxxxxxx> --- include/linux/fs.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 6c4ab4d..ef13df4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -175,6 +175,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* File does not contribute to nr_files count */ #define FMODE_NOACCOUNT ((__force fmode_t)0x20000000) +/* File can support zone-append */ +#define FMODE_ZONE_APPEND ((__force fmode_t)0x40000000) + /* * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector * that indicates that they should check the contents of the iovec are @@ -315,6 +318,7 @@ enum rw_hint { #define IOCB_SYNC (1 << 5) #define IOCB_WRITE (1 << 6) #define IOCB_NOWAIT (1 << 7) +#define IOCB_ZONE_APPEND (1 << 8) struct kiocb { struct file *ki_filp; @@ -3427,8 +3431,11 @@ static inline bool vma_is_fsdax(struct vm_area_struct *vma) static inline int iocb_flags(struct file *file) { int res = 0; - if (file->f_flags & O_APPEND) + if (file->f_flags & O_APPEND) { res |= IOCB_APPEND; + if (file->f_mode & FMODE_ZONE_APPEND) + res |= IOCB_ZONE_APPEND; + } if (file->f_flags & O_DIRECT) res |= IOCB_DIRECT; if ((file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host)) @@ -3454,8 +3461,11 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags) ki->ki_flags |= IOCB_DSYNC; if (flags & RWF_SYNC) ki->ki_flags |= (IOCB_DSYNC | IOCB_SYNC); - if (flags & RWF_APPEND) + if (flags & RWF_APPEND) { ki->ki_flags |= IOCB_APPEND; + if (ki->ki_filp->f_mode & FMODE_ZONE_APPEND) + ki->ki_flags |= IOCB_ZONE_APPEND; + } return 0; } -- 2.7.4