===================================================================
@@ -628,6 +628,7 @@ const struct file_operations def_blk_fop
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = blkdev_fallocate,
+ .fallocate_supported_flags = BLKDEV_FALLOC_FL_SUPPORTED,
};
static __init int blkdev_init(void)
===================================================================
@@ -3688,6 +3688,8 @@ const struct file_operations btrfs_file_
.release = btrfs_release_file,
.fsync = btrfs_sync_file,
.fallocate = btrfs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE,
.unlocked_ioctl = btrfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = btrfs_compat_ioctl,
===================================================================
@@ -2492,5 +2492,6 @@ const struct file_operations ceph_file_f
.unlocked_ioctl = ceph_ioctl,
.compat_ioctl = compat_ptr_ioctl,
.fallocate = ceph_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
.copy_file_range = ceph_copy_file_range,
};
===================================================================
@@ -1281,6 +1281,9 @@ const struct file_operations cifs_file_o
.remap_file_range = cifs_remap_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_file_strict_ops = {
@@ -1301,6 +1304,9 @@ const struct file_operations cifs_file_s
.remap_file_range = cifs_remap_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_file_direct_ops = {
@@ -1321,6 +1327,9 @@ const struct file_operations cifs_file_d
.llseek = cifs_llseek,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_file_nobrl_ops = {
@@ -1339,6 +1348,9 @@ const struct file_operations cifs_file_n
.remap_file_range = cifs_remap_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_file_strict_nobrl_ops = {
@@ -1357,6 +1369,9 @@ const struct file_operations cifs_file_s
.remap_file_range = cifs_remap_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_file_direct_nobrl_ops = {
@@ -1375,6 +1390,9 @@ const struct file_operations cifs_file_d
.llseek = cifs_llseek,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct file_operations cifs_dir_ops = {
===================================================================
@@ -929,6 +929,9 @@ const struct file_operations ext4_file_o
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = ext4_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE,
};
const struct inode_operations ext4_file_inode_operations = {
===================================================================
@@ -4499,6 +4499,9 @@ const struct file_operations f2fs_file_o
.flush = f2fs_file_flush,
.fsync = f2fs_sync_file,
.fallocate = f2fs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE |
+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE,
.unlocked_ioctl = f2fs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = f2fs_compat_ioctl,
===================================================================
@@ -211,6 +211,7 @@ const struct file_operations fat_file_op
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = fat_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE,
};
static int fat_cont_expand(struct inode *inode, loff_t size)
===================================================================
@@ -3147,6 +3147,8 @@ static const struct file_operations fuse
.compat_ioctl = fuse_file_compat_ioctl,
.poll = fuse_file_poll,
.fallocate = fuse_file_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE,
.copy_file_range = fuse_copy_file_range,
};
===================================================================
@@ -1366,6 +1366,7 @@ const struct file_operations gfs2_file_f
.splice_write = gfs2_file_splice_write,
.setlease = simple_nosetlease,
.fallocate = gfs2_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
};
const struct file_operations gfs2_dir_fops = {
===================================================================
@@ -1163,6 +1163,7 @@ const struct file_operations hugetlbfs_f
.get_unmapped_area = hugetlb_get_unmapped_area,
.llseek = default_llseek,
.fallocate = hugetlbfs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
};
static const struct inode_operations hugetlbfs_dir_inode_operations = {
===================================================================
@@ -457,6 +457,7 @@ const struct file_operations nfs4_file_o
.copy_file_range = nfs4_copy_file_range,
.llseek = nfs4_file_llseek,
.fallocate = nfs42_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
.remap_file_range = nfs42_remap_file_range,
#else
.llseek = nfs_file_llseek,
===================================================================
@@ -1246,6 +1246,8 @@ const struct file_operations ntfs_file_o
.fsync = generic_file_fsync,
.splice_write = iter_file_splice_write,
.fallocate = ntfs_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE |
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE,
.release = ntfs_file_release,
};
// clang-format on
===================================================================
@@ -2746,6 +2746,7 @@ const struct file_operations ocfs2_fops
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = ocfs2_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
.remap_file_range = ocfs2_remap_file_range,
};
@@ -2792,6 +2793,7 @@ const struct file_operations ocfs2_fops_
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = ocfs2_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
.remap_file_range = ocfs2_remap_file_range,
};
===================================================================
@@ -658,6 +658,7 @@ const struct file_operations ovl_file_op
.fsync = ovl_fsync,
.mmap = ovl_mmap,
.fallocate = ovl_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_SUPPORTED_MASK,
.fadvise = ovl_fadvise,
.flush = ovl_flush,
.splice_read = generic_file_splice_read,
===================================================================
@@ -1464,6 +1464,7 @@ const struct file_operations xfs_file_op
.fsync = xfs_file_fsync,
.get_unmapped_area = thp_get_unmapped_area,
.fallocate = xfs_file_fallocate,
+ .fallocate_supported_flags = XFS_FALLOC_FL_SUPPORTED,
.fadvise = xfs_file_fadvise,
.remap_file_range = xfs_file_remap_range,
};
===================================================================
@@ -2098,6 +2098,7 @@ struct file_operations {
int (*setlease)(struct file *, long, struct file_lock **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
+ unsigned fallocate_supported_flags;
void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
unsigned (*mmap_capabilities)(struct file *);
===================================================================
@@ -44,6 +44,7 @@
#include <linux/mount.h>
#include <linux/ipc_namespace.h>
#include <linux/rhashtable.h>
+#include <linux/falloc.h>
#include <linux/uaccess.h>
@@ -558,6 +559,7 @@ static const struct file_operations shm_
.get_unmapped_area = shm_get_unmapped_area,
.llseek = noop_llseek,
.fallocate = shm_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
};
/*
@@ -571,6 +573,7 @@ static const struct file_operations shm_
.get_unmapped_area = shm_get_unmapped_area,
.llseek = noop_llseek,
.fallocate = shm_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
};
bool is_file_shm_hugepages(struct file *file)
===================================================================
@@ -3797,6 +3797,7 @@ static const struct file_operations shme
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = shmem_fallocate,
+ .fallocate_supported_flags = FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
#endif
};
===================================================================
@@ -947,7 +947,10 @@ static void loop_config_discard(struct l
* encryption is enabled, because it may give an attacker
* useful information.
*/
- } else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) {
+ } else if ((file->f_op->fallocate_supported_flags &
+ (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) !=
+ (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE) ||
+ lo->lo_encrypt_key_size) {
max_discard_sectors = 0;
granularity = 0;
@@ -959,7 +962,10 @@ static void loop_config_discard(struct l
if (max_discard_sectors) {
q->limits.discard_granularity = granularity;
blk_queue_max_discard_sectors(q, max_discard_sectors);
- blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
+ if (file->f_op->fallocate_supported_flags & FALLOC_FL_ZERO_RANGE)
+ blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
+ else
+ blk_queue_max_write_zeroes_sectors(q, 0);
blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
} else {
q->limits.discard_granularity = 0;