mm: tiny-shmem nommu fix

The previous patch db203d53d474aa068984e409d807628f5841da1b ("mm:
tiny-shmem fix lock ordering: mmap_sem vs i_mutex") to fix the lock
ordering in tiny-shmem breaks shared anonymous and IPC memory on NOMMU
architectures because it was using the expanding truncate to signal ramfs
to allocate a physically contiguous RAM backing the inode (otherwise it is
unusable for "memory mapping" it to userspace).

However do_truncate is what caused the lock ordering error, due to it
taking i_mutex. In this case, we can actually just call ramfs directly to
allocate memory for the mapping, rather than go via truncate.

Acked-by: David Howells <dhowells@redhat.com>
Acked-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Nick Piggin and committed by Linus Torvalds 4b19de6d 6c1b7f68

+8 -1
+1 -1
fs/ramfs/file-nommu.c
··· 58 * size 0 on the assumption that it's going to be used for an mmap of shared 59 * memory 60 */ 61 - static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) 62 { 63 struct pagevec lru_pvec; 64 unsigned long npages, xpages, loop, limit;
··· 58 * size 0 on the assumption that it's going to be used for an mmap of shared 59 * memory 60 */ 61 + int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) 62 { 63 struct pagevec lru_pvec; 64 unsigned long npages, xpages, loop, limit;
+1
include/linux/ramfs.h
··· 6 int flags, const char *dev_name, void *data, struct vfsmount *mnt); 7 8 #ifndef CONFIG_MMU 9 extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, 10 unsigned long addr, 11 unsigned long len,
··· 6 int flags, const char *dev_name, void *data, struct vfsmount *mnt); 7 8 #ifndef CONFIG_MMU 9 + extern int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize); 10 extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, 11 unsigned long addr, 12 unsigned long len,
+6
mm/tiny-shmem.c
··· 80 inode->i_nlink = 0; /* It is unlinked */ 81 init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, 82 &ramfs_file_operations); 83 return file; 84 85 close_file:
··· 80 inode->i_nlink = 0; /* It is unlinked */ 81 init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, 82 &ramfs_file_operations); 83 + 84 + #ifndef CONFIG_MMU 85 + error = ramfs_nommu_expand_for_mapping(inode, size); 86 + if (error) 87 + goto close_file; 88 + #endif 89 return file; 90 91 close_file: