@@ -241,13 +241,22 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
struct inode *inode = file_inode(file);
long ret;
- if (offset < 0 || len <= 0)
+ if ((offset < 0 || len <= 0) && !(mode & FALLOC_FL_QUERY_SUPPORT))
return -EINVAL;
/* Return error if mode is not supported */
if (mode & ~FALLOC_FL_SUPPORTED_MASK)
return -EOPNOTSUPP;
+ /* offset and length are not used in query support */
+ if ((mode & FALLOC_FL_QUERY_SUPPORT) && (offset != 0 || len != 0))
+ return -EINVAL;
+
+ /* Query support should only be used exclusively */
+ if ((mode & FALLOC_FL_QUERY_SUPPORT) &&
+ (mode & ~FALLOC_FL_QUERY_SUPPORT))
+ return -EINVAL;
+
/* Punch hole and zero range are mutually exclusive */
if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) ==
(FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
@@ -328,6 +337,13 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (ret == 0)
fsnotify_modify(file);
+ /*
+ * Let's not allow file systems return any random data, just fallocate
+ * modes.
+ */
+ if ((ret > 0) && (mode & FALLOC_FL_QUERY_SUPPORT))
+ ret &= FALLOC_FL_SUPPORTED_MASK;
+
file_end_write(file);
return ret;
}
@@ -26,6 +26,8 @@ struct space_resv {
FALLOC_FL_COLLAPSE_RANGE | \
FALLOC_FL_ZERO_RANGE | \
FALLOC_FL_INSERT_RANGE | \
- FALLOC_FL_UNSHARE_RANGE)
+ FALLOC_FL_QUERY_SUPPORT | \
+ FALLOC_FL_UNSHARE_RANGE | \
+ FALLOC_FL_PREALLOC_RANGE)
#endif /* _FALLOC_H_ */
@@ -76,4 +76,17 @@
*/
#define FALLOC_FL_UNSHARE_RANGE 0x40
+/*
+ * FALLOC_FL_QUERY_SUPPORT is used to query file system, or block device
+ * for a supported fallocate flags.
+ */
+#define FALLOC_FL_QUERY_SUPPORT 0x80
+
+/*
+ * FALLOC_FL_PREALLOC_RANGE is a placeholder for a default preallocation
+ * mode. It has the same effect as not specifying any flag at all. We need
+ * this to report back support for this particular mode,
+ */
+#define FALLOC_FL_PREALLOC_RANGE 0x100
+
#endif /* _UAPI_FALLOC_H_ */
Filesystems are free to implement any subset of fallocate modes and there is currently no way of telling what modes are actually supported by the file system other than trying them all. Change this by introducing new fallocate mode FALLOC_FL_QUERY_SUPPORT that is supposed to return all supported modes. FALLOC_FL_QUERY_SUPPORT mode can be only used exclusively with offset and length set to zero. Signed-off-by: Lukas Czerner <lczerner@redhat.com> --- fs/open.c | 18 +++++++++++++++++- include/linux/falloc.h | 4 +++- include/uapi/linux/falloc.h | 13 +++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-)