Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipc: shm: restore MADV_REMOVE functionality on shared memory segments

Commit 17cf28afea2a ("mm/fs: remove truncate_range") removed the
truncate_range inode operation in favour of the fallocate file
operation.

When using SYSV IPC shared memory segments, calling madvise with the
MADV_REMOVE advice on an area of shared memory will attempt to invoke
the .fallocate function for the shm_file_operations, which is NULL and
therefore returns -EOPNOTSUPP to userspace. The previous behaviour
would inherit the inode_operations from the underlying tmpfs file and
invoke truncate_range there.

This patch restores the previous behaviour by wrapping the underlying
fallocate function in shm_fallocate, as we do for fsync.

[hughd@google.com: use -ENOTSUPP in shm_fallocate()]
Signed-off-by: Will Deacon <will.deacon@arm.com>
Acked-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Will Deacon and committed by
Linus Torvalds
7d8a4569 4e791c98

+12
+12
ipc/shm.c
··· 393 393 return sfd->file->f_op->fsync(sfd->file, start, end, datasync); 394 394 } 395 395 396 + static long shm_fallocate(struct file *file, int mode, loff_t offset, 397 + loff_t len) 398 + { 399 + struct shm_file_data *sfd = shm_file_data(file); 400 + 401 + if (!sfd->file->f_op->fallocate) 402 + return -EOPNOTSUPP; 403 + return sfd->file->f_op->fallocate(file, mode, offset, len); 404 + } 405 + 396 406 static unsigned long shm_get_unmapped_area(struct file *file, 397 407 unsigned long addr, unsigned long len, unsigned long pgoff, 398 408 unsigned long flags) ··· 420 410 .get_unmapped_area = shm_get_unmapped_area, 421 411 #endif 422 412 .llseek = noop_llseek, 413 + .fallocate = shm_fallocate, 423 414 }; 424 415 425 416 static const struct file_operations shm_file_operations_huge = { ··· 429 418 .release = shm_release, 430 419 .get_unmapped_area = shm_get_unmapped_area, 431 420 .llseek = noop_llseek, 421 + .fallocate = shm_fallocate, 432 422 }; 433 423 434 424 int is_file_shm_hugepages(struct file *file)