diff options
author | Nick Piggin <npiggin@suse.de> | 2008-09-22 16:57:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-09-23 11:09:14 -0400 |
commit | db203d53d474aa068984e409d807628f5841da1b (patch) | |
tree | 7c4352513d8a108b916d2cbe16234346addf179c /mm/tiny-shmem.c | |
parent | 2d4c8266774188cda7f7e612e6dfb8ad12c579d5 (diff) |
mm: tiny-shmem fix lock ordering: mmap_sem vs i_mutex
tiny-shmem calls do_truncate in shmem_file_setup. do_truncate takes
i_mutex, and shmem_file_setup is called with mmap_sem held. However
i_mutex nests outside mmap_sem.
Copy the code in shmem.c to avoid this problem.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Nick Piggin <npiggin@suse.de>
Reported-and-tested-by: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Matt Mackall <mpm@selenic.com>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/tiny-shmem.c')
-rw-r--r-- | mm/tiny-shmem.c | 24 |
1 files changed, 9 insertions, 15 deletions
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c index ae532f501943..d17cb6f6ab10 100644 --- a/mm/tiny-shmem.c +++ b/mm/tiny-shmem.c | |||
@@ -65,31 +65,25 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) | |||
65 | if (!dentry) | 65 | if (!dentry) |
66 | goto put_memory; | 66 | goto put_memory; |
67 | 67 | ||
68 | error = -ENOSPC; | ||
69 | inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); | ||
70 | if (!inode) | ||
71 | goto put_dentry; | ||
72 | |||
73 | d_instantiate(dentry, inode); | ||
74 | error = -ENFILE; | 68 | error = -ENFILE; |
75 | file = alloc_file(shm_mnt, dentry, FMODE_WRITE | FMODE_READ, | 69 | file = get_empty_filp(); |
76 | &ramfs_file_operations); | ||
77 | if (!file) | 70 | if (!file) |
78 | goto put_dentry; | 71 | goto put_dentry; |
79 | 72 | ||
80 | inode->i_nlink = 0; /* It is unlinked */ | 73 | error = -ENOSPC; |
81 | 74 | inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0); | |
82 | /* notify everyone as to the change of file size */ | 75 | if (!inode) |
83 | error = do_truncate(dentry, size, 0, file); | ||
84 | if (error < 0) | ||
85 | goto close_file; | 76 | goto close_file; |
86 | 77 | ||
78 | d_instantiate(dentry, inode); | ||
79 | inode->i_size = size; | ||
80 | inode->i_nlink = 0; /* It is unlinked */ | ||
81 | init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ, | ||
82 | &ramfs_file_operations); | ||
87 | return file; | 83 | return file; |
88 | 84 | ||
89 | close_file: | 85 | close_file: |
90 | put_filp(file); | 86 | put_filp(file); |
91 | return ERR_PTR(error); | ||
92 | |||
93 | put_dentry: | 87 | put_dentry: |
94 | dput(dentry); | 88 | dput(dentry); |
95 | put_memory: | 89 | put_memory: |