[PATCH v2 1/7] fs: add new flag(FALLOC_FL_COLLAPSE_RANGE) for fallocate
From: Namjae Jeon Add new flag(FALLOC_FL_COLLAPSE_RANGE) for fallocate. updated detailed semantics in comments. Signed-off-by: Namjae Jeon Signed-off-by: Ashish Sangwan --- fs/open.c | 24 +--- include/uapi/linux/falloc.h | 17 + 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fs/open.c b/fs/open.c index 7931f76..85d243a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -225,12 +225,14 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret; + unsigned blksize_mask = (1 << inode->i_blkbits) - 1; if (offset < 0 || len <= 0) return -EINVAL; /* Return error if mode is not supported */ - if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) + if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | +FALLOC_FL_COLLAPSE_RANGE)) return -EOPNOTSUPP; /* Punch hole must have keep size set */ @@ -241,8 +243,12 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(file->f_mode & FMODE_WRITE)) return -EBADF; - /* It's not possible punch hole on append only file */ - if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode)) + /* +* It's not possible to punch hole or perform collapse range +* on append only file +*/ + if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE) + && IS_APPEND(inode)) return -EPERM; if (IS_IMMUTABLE(inode)) @@ -270,6 +276,18 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) return -EFBIG; + /* +* Collapse range works only on fs block size aligned offsets. +* Check if collapse range is contained within (aligned)i_size. +* Collapse range can only be used exclusively. +*/ + if ((mode & FALLOC_FL_COLLAPSE_RANGE) && + (offset & blksize_mask || len & blksize_mask || +mode & ~FALLOC_FL_COLLAPSE_RANGE || +(offset + len > + round_up(i_size_read(inode), (blksize_mask + 1) + return -EINVAL; + if (!file->f_op->fallocate) return -EOPNOTSUPP; diff --git a/include/uapi/linux/falloc.h b/include/uapi/linux/falloc.h index 990c4cc..9614b72 100644 --- a/include/uapi/linux/falloc.h +++ b/include/uapi/linux/falloc.h @@ -4,6 +4,23 @@ #define FALLOC_FL_KEEP_SIZE0x01 /* default is extend size */ #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ #define FALLOC_FL_NO_HIDE_STALE0x04 /* reserved codepoint */ +/* + * FALLOC_FL_COLLAPSE_RANGE: + * This flag works in 2 steps. + * Firstly, it deallocates any data blocks present between [offset, offset+len) + * This step is same as punch hole and leaves a hole in the place from where + * the blocks are removed. + * Next, it eliminates the hole created by moving data blocks into it. + * For extent based file systems, we achieve this functionality simply by + * updating the starting logical offset of each extent which appears beyond + * the hole. As this flag works on blocks of filesystem, the offset and len + * provided to fallocate should be aligned with block size of filesystem. + * The semantics of this flag are: + * 1) It should be used exclusively. No other fallocate flag in combination. + * 2) Offset and len supplied to fallocate should be aligned with block size. + * 3) (offset + len) could not be greater than file size. + */ +#define FALLOC_FL_COLLAPSE_RANGE 0x08 /* it does not leave a hole */ #endif /* _UAPI_FALLOC_H_ */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/7] fs: add new flag(FALLOC_FL_COLLAPSE_RANGE) for fallocate
From: Namjae Jeon namjae.j...@samsung.com Add new flag(FALLOC_FL_COLLAPSE_RANGE) for fallocate. updated detailed semantics in comments. Signed-off-by: Namjae Jeon namjae.j...@samsung.com Signed-off-by: Ashish Sangwan a.sang...@samsung.com --- fs/open.c | 24 +--- include/uapi/linux/falloc.h | 17 + 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fs/open.c b/fs/open.c index 7931f76..85d243a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -225,12 +225,14 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret; + unsigned blksize_mask = (1 inode-i_blkbits) - 1; if (offset 0 || len = 0) return -EINVAL; /* Return error if mode is not supported */ - if (mode ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) + if (mode ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | +FALLOC_FL_COLLAPSE_RANGE)) return -EOPNOTSUPP; /* Punch hole must have keep size set */ @@ -241,8 +243,12 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(file-f_mode FMODE_WRITE)) return -EBADF; - /* It's not possible punch hole on append only file */ - if (mode FALLOC_FL_PUNCH_HOLE IS_APPEND(inode)) + /* +* It's not possible to punch hole or perform collapse range +* on append only file +*/ + if (mode (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE) +IS_APPEND(inode)) return -EPERM; if (IS_IMMUTABLE(inode)) @@ -270,6 +276,18 @@ int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (((offset + len) inode-i_sb-s_maxbytes) || ((offset + len) 0)) return -EFBIG; + /* +* Collapse range works only on fs block size aligned offsets. +* Check if collapse range is contained within (aligned)i_size. +* Collapse range can only be used exclusively. +*/ + if ((mode FALLOC_FL_COLLAPSE_RANGE) + (offset blksize_mask || len blksize_mask || +mode ~FALLOC_FL_COLLAPSE_RANGE || +(offset + len + round_up(i_size_read(inode), (blksize_mask + 1) + return -EINVAL; + if (!file-f_op-fallocate) return -EOPNOTSUPP; diff --git a/include/uapi/linux/falloc.h b/include/uapi/linux/falloc.h index 990c4cc..9614b72 100644 --- a/include/uapi/linux/falloc.h +++ b/include/uapi/linux/falloc.h @@ -4,6 +4,23 @@ #define FALLOC_FL_KEEP_SIZE0x01 /* default is extend size */ #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ #define FALLOC_FL_NO_HIDE_STALE0x04 /* reserved codepoint */ +/* + * FALLOC_FL_COLLAPSE_RANGE: + * This flag works in 2 steps. + * Firstly, it deallocates any data blocks present between [offset, offset+len) + * This step is same as punch hole and leaves a hole in the place from where + * the blocks are removed. + * Next, it eliminates the hole created by moving data blocks into it. + * For extent based file systems, we achieve this functionality simply by + * updating the starting logical offset of each extent which appears beyond + * the hole. As this flag works on blocks of filesystem, the offset and len + * provided to fallocate should be aligned with block size of filesystem. + * The semantics of this flag are: + * 1) It should be used exclusively. No other fallocate flag in combination. + * 2) Offset and len supplied to fallocate should be aligned with block size. + * 3) (offset + len) could not be greater than file size. + */ +#define FALLOC_FL_COLLAPSE_RANGE 0x08 /* it does not leave a hole */ #endif /* _UAPI_FALLOC_H_ */ -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/