aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/shm.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-06-07 17:21:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-07 17:43:55 -0400
commit7d8a45695cc8f9fcdf4121fcbd897ecb63f758e4 (patch)
treeba315d40c8b0457d132ea155d0db651275af6822 /ipc/shm.c
parent4e791c98ae7ff889121ca93b7bd97206e4a8d793 (diff)
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>
Diffstat (limited to 'ipc/shm.c')
-rw-r--r--ipc/shm.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index 5e2cbfdab6fc..41c1285d697a 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -393,6 +393,16 @@ static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync)
393 return sfd->file->f_op->fsync(sfd->file, start, end, datasync); 393 return sfd->file->f_op->fsync(sfd->file, start, end, datasync);
394} 394}
395 395
396static 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
396static unsigned long shm_get_unmapped_area(struct file *file, 406static unsigned long shm_get_unmapped_area(struct file *file,
397 unsigned long addr, unsigned long len, unsigned long pgoff, 407 unsigned long addr, unsigned long len, unsigned long pgoff,
398 unsigned long flags) 408 unsigned long flags)
@@ -410,6 +420,7 @@ static const struct file_operations shm_file_operations = {
410 .get_unmapped_area = shm_get_unmapped_area, 420 .get_unmapped_area = shm_get_unmapped_area,
411#endif 421#endif
412 .llseek = noop_llseek, 422 .llseek = noop_llseek,
423 .fallocate = shm_fallocate,
413}; 424};
414 425
415static const struct file_operations shm_file_operations_huge = { 426static const struct file_operations shm_file_operations_huge = {
@@ -418,6 +429,7 @@ static const struct file_operations shm_file_operations_huge = {
418 .release = shm_release, 429 .release = shm_release,
419 .get_unmapped_area = shm_get_unmapped_area, 430 .get_unmapped_area = shm_get_unmapped_area,
420 .llseek = noop_llseek, 431 .llseek = noop_llseek,
432 .fallocate = shm_fallocate,
421}; 433};
422 434
423int is_file_shm_hugepages(struct file *file) 435int is_file_shm_hugepages(struct file *file)