Commit 98310e581e098514867573031b2bfa4ba89c0d93

Authored by David VomLehn
Committed by Linus Torvalds
1 parent 6e873ec71d

cramfs: propagate uncompression errors

Decompression errors can arise due to corruption of compressed blocks on
flash or in memory.  This patch propagates errors detected during
decompression back to the block layer.

Signed-off-by: David VomLehn <dvomlehn@cisco.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 27 additions and 11 deletions Inline Diff

1 /* 1 /*
2 * Compressed rom filesystem for Linux. 2 * Compressed rom filesystem for Linux.
3 * 3 *
4 * Copyright (C) 1999 Linus Torvalds. 4 * Copyright (C) 1999 Linus Torvalds.
5 * 5 *
6 * This file is released under the GPL. 6 * This file is released under the GPL.
7 */ 7 */
8 8
9 /* 9 /*
10 * These are the VFS interfaces to the compressed rom filesystem. 10 * These are the VFS interfaces to the compressed rom filesystem.
11 * The actual compression is based on zlib, see the other files. 11 * The actual compression is based on zlib, see the other files.
12 */ 12 */
13 13
14 #include <linux/module.h> 14 #include <linux/module.h>
15 #include <linux/fs.h> 15 #include <linux/fs.h>
16 #include <linux/pagemap.h> 16 #include <linux/pagemap.h>
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/string.h> 18 #include <linux/string.h>
19 #include <linux/blkdev.h> 19 #include <linux/blkdev.h>
20 #include <linux/cramfs_fs.h> 20 #include <linux/cramfs_fs.h>
21 #include <linux/slab.h> 21 #include <linux/slab.h>
22 #include <linux/cramfs_fs_sb.h> 22 #include <linux/cramfs_fs_sb.h>
23 #include <linux/buffer_head.h> 23 #include <linux/buffer_head.h>
24 #include <linux/vfs.h> 24 #include <linux/vfs.h>
25 #include <linux/mutex.h> 25 #include <linux/mutex.h>
26 26
27 #include <asm/uaccess.h> 27 #include <asm/uaccess.h>
28 28
29 static const struct super_operations cramfs_ops; 29 static const struct super_operations cramfs_ops;
30 static const struct inode_operations cramfs_dir_inode_operations; 30 static const struct inode_operations cramfs_dir_inode_operations;
31 static const struct file_operations cramfs_directory_operations; 31 static const struct file_operations cramfs_directory_operations;
32 static const struct address_space_operations cramfs_aops; 32 static const struct address_space_operations cramfs_aops;
33 33
34 static DEFINE_MUTEX(read_mutex); 34 static DEFINE_MUTEX(read_mutex);
35 35
36 36
37 /* These two macros may change in future, to provide better st_ino 37 /* These two macros may change in future, to provide better st_ino
38 semantics. */ 38 semantics. */
39 #define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1) 39 #define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
40 #define OFFSET(x) ((x)->i_ino) 40 #define OFFSET(x) ((x)->i_ino)
41 41
42 42
43 static int cramfs_iget5_test(struct inode *inode, void *opaque) 43 static int cramfs_iget5_test(struct inode *inode, void *opaque)
44 { 44 {
45 struct cramfs_inode *cramfs_inode = opaque; 45 struct cramfs_inode *cramfs_inode = opaque;
46 return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; 46 return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1;
47 } 47 }
48 48
49 static int cramfs_iget5_set(struct inode *inode, void *opaque) 49 static int cramfs_iget5_set(struct inode *inode, void *opaque)
50 { 50 {
51 struct cramfs_inode *cramfs_inode = opaque; 51 struct cramfs_inode *cramfs_inode = opaque;
52 inode->i_ino = CRAMINO(cramfs_inode); 52 inode->i_ino = CRAMINO(cramfs_inode);
53 return 0; 53 return 0;
54 } 54 }
55 55
56 static struct inode *get_cramfs_inode(struct super_block *sb, 56 static struct inode *get_cramfs_inode(struct super_block *sb,
57 struct cramfs_inode * cramfs_inode) 57 struct cramfs_inode * cramfs_inode)
58 { 58 {
59 struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), 59 struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
60 cramfs_iget5_test, cramfs_iget5_set, 60 cramfs_iget5_test, cramfs_iget5_set,
61 cramfs_inode); 61 cramfs_inode);
62 static struct timespec zerotime; 62 static struct timespec zerotime;
63 63
64 if (inode && (inode->i_state & I_NEW)) { 64 if (inode && (inode->i_state & I_NEW)) {
65 inode->i_mode = cramfs_inode->mode; 65 inode->i_mode = cramfs_inode->mode;
66 inode->i_uid = cramfs_inode->uid; 66 inode->i_uid = cramfs_inode->uid;
67 inode->i_size = cramfs_inode->size; 67 inode->i_size = cramfs_inode->size;
68 inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; 68 inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
69 inode->i_gid = cramfs_inode->gid; 69 inode->i_gid = cramfs_inode->gid;
70 /* Struct copy intentional */ 70 /* Struct copy intentional */
71 inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; 71 inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
72 /* inode->i_nlink is left 1 - arguably wrong for directories, 72 /* inode->i_nlink is left 1 - arguably wrong for directories,
73 but it's the best we can do without reading the directory 73 but it's the best we can do without reading the directory
74 contents. 1 yields the right result in GNU find, even 74 contents. 1 yields the right result in GNU find, even
75 without -noleaf option. */ 75 without -noleaf option. */
76 if (S_ISREG(inode->i_mode)) { 76 if (S_ISREG(inode->i_mode)) {
77 inode->i_fop = &generic_ro_fops; 77 inode->i_fop = &generic_ro_fops;
78 inode->i_data.a_ops = &cramfs_aops; 78 inode->i_data.a_ops = &cramfs_aops;
79 } else if (S_ISDIR(inode->i_mode)) { 79 } else if (S_ISDIR(inode->i_mode)) {
80 inode->i_op = &cramfs_dir_inode_operations; 80 inode->i_op = &cramfs_dir_inode_operations;
81 inode->i_fop = &cramfs_directory_operations; 81 inode->i_fop = &cramfs_directory_operations;
82 } else if (S_ISLNK(inode->i_mode)) { 82 } else if (S_ISLNK(inode->i_mode)) {
83 inode->i_op = &page_symlink_inode_operations; 83 inode->i_op = &page_symlink_inode_operations;
84 inode->i_data.a_ops = &cramfs_aops; 84 inode->i_data.a_ops = &cramfs_aops;
85 } else { 85 } else {
86 init_special_inode(inode, inode->i_mode, 86 init_special_inode(inode, inode->i_mode,
87 old_decode_dev(cramfs_inode->size)); 87 old_decode_dev(cramfs_inode->size));
88 } 88 }
89 unlock_new_inode(inode); 89 unlock_new_inode(inode);
90 } 90 }
91 return inode; 91 return inode;
92 } 92 }
93 93
94 static void cramfs_drop_inode(struct inode *inode) 94 static void cramfs_drop_inode(struct inode *inode)
95 { 95 {
96 if (inode->i_ino == 1) 96 if (inode->i_ino == 1)
97 generic_delete_inode(inode); 97 generic_delete_inode(inode);
98 else 98 else
99 generic_drop_inode(inode); 99 generic_drop_inode(inode);
100 } 100 }
101 101
102 /* 102 /*
103 * We have our own block cache: don't fill up the buffer cache 103 * We have our own block cache: don't fill up the buffer cache
104 * with the rom-image, because the way the filesystem is set 104 * with the rom-image, because the way the filesystem is set
105 * up the accesses should be fairly regular and cached in the 105 * up the accesses should be fairly regular and cached in the
106 * page cache and dentry tree anyway.. 106 * page cache and dentry tree anyway..
107 * 107 *
108 * This also acts as a way to guarantee contiguous areas of up to 108 * This also acts as a way to guarantee contiguous areas of up to
109 * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to 109 * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to
110 * worry about end-of-buffer issues even when decompressing a full 110 * worry about end-of-buffer issues even when decompressing a full
111 * page cache. 111 * page cache.
112 */ 112 */
113 #define READ_BUFFERS (2) 113 #define READ_BUFFERS (2)
114 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */ 114 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
115 #define NEXT_BUFFER(_ix) ((_ix) ^ 1) 115 #define NEXT_BUFFER(_ix) ((_ix) ^ 1)
116 116
117 /* 117 /*
118 * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed" 118 * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed"
119 * data that takes up more space than the original and with unlucky 119 * data that takes up more space than the original and with unlucky
120 * alignment. 120 * alignment.
121 */ 121 */
122 #define BLKS_PER_BUF_SHIFT (2) 122 #define BLKS_PER_BUF_SHIFT (2)
123 #define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT) 123 #define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
124 #define BUFFER_SIZE (BLKS_PER_BUF*PAGE_CACHE_SIZE) 124 #define BUFFER_SIZE (BLKS_PER_BUF*PAGE_CACHE_SIZE)
125 125
126 static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE]; 126 static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE];
127 static unsigned buffer_blocknr[READ_BUFFERS]; 127 static unsigned buffer_blocknr[READ_BUFFERS];
128 static struct super_block * buffer_dev[READ_BUFFERS]; 128 static struct super_block * buffer_dev[READ_BUFFERS];
129 static int next_buffer; 129 static int next_buffer;
130 130
131 /* 131 /*
132 * Returns a pointer to a buffer containing at least LEN bytes of 132 * Returns a pointer to a buffer containing at least LEN bytes of
133 * filesystem starting at byte offset OFFSET into the filesystem. 133 * filesystem starting at byte offset OFFSET into the filesystem.
134 */ 134 */
135 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len) 135 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
136 { 136 {
137 struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; 137 struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
138 struct page *pages[BLKS_PER_BUF]; 138 struct page *pages[BLKS_PER_BUF];
139 unsigned i, blocknr, buffer; 139 unsigned i, blocknr, buffer;
140 unsigned long devsize; 140 unsigned long devsize;
141 char *data; 141 char *data;
142 142
143 if (!len) 143 if (!len)
144 return NULL; 144 return NULL;
145 blocknr = offset >> PAGE_CACHE_SHIFT; 145 blocknr = offset >> PAGE_CACHE_SHIFT;
146 offset &= PAGE_CACHE_SIZE - 1; 146 offset &= PAGE_CACHE_SIZE - 1;
147 147
148 /* Check if an existing buffer already has the data.. */ 148 /* Check if an existing buffer already has the data.. */
149 for (i = 0; i < READ_BUFFERS; i++) { 149 for (i = 0; i < READ_BUFFERS; i++) {
150 unsigned int blk_offset; 150 unsigned int blk_offset;
151 151
152 if (buffer_dev[i] != sb) 152 if (buffer_dev[i] != sb)
153 continue; 153 continue;
154 if (blocknr < buffer_blocknr[i]) 154 if (blocknr < buffer_blocknr[i])
155 continue; 155 continue;
156 blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT; 156 blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
157 blk_offset += offset; 157 blk_offset += offset;
158 if (blk_offset + len > BUFFER_SIZE) 158 if (blk_offset + len > BUFFER_SIZE)
159 continue; 159 continue;
160 return read_buffers[i] + blk_offset; 160 return read_buffers[i] + blk_offset;
161 } 161 }
162 162
163 devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT; 163 devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
164 164
165 /* Ok, read in BLKS_PER_BUF pages completely first. */ 165 /* Ok, read in BLKS_PER_BUF pages completely first. */
166 for (i = 0; i < BLKS_PER_BUF; i++) { 166 for (i = 0; i < BLKS_PER_BUF; i++) {
167 struct page *page = NULL; 167 struct page *page = NULL;
168 168
169 if (blocknr + i < devsize) { 169 if (blocknr + i < devsize) {
170 page = read_mapping_page_async(mapping, blocknr + i, 170 page = read_mapping_page_async(mapping, blocknr + i,
171 NULL); 171 NULL);
172 /* synchronous error? */ 172 /* synchronous error? */
173 if (IS_ERR(page)) 173 if (IS_ERR(page))
174 page = NULL; 174 page = NULL;
175 } 175 }
176 pages[i] = page; 176 pages[i] = page;
177 } 177 }
178 178
179 for (i = 0; i < BLKS_PER_BUF; i++) { 179 for (i = 0; i < BLKS_PER_BUF; i++) {
180 struct page *page = pages[i]; 180 struct page *page = pages[i];
181 if (page) { 181 if (page) {
182 wait_on_page_locked(page); 182 wait_on_page_locked(page);
183 if (!PageUptodate(page)) { 183 if (!PageUptodate(page)) {
184 /* asynchronous error */ 184 /* asynchronous error */
185 page_cache_release(page); 185 page_cache_release(page);
186 pages[i] = NULL; 186 pages[i] = NULL;
187 } 187 }
188 } 188 }
189 } 189 }
190 190
191 buffer = next_buffer; 191 buffer = next_buffer;
192 next_buffer = NEXT_BUFFER(buffer); 192 next_buffer = NEXT_BUFFER(buffer);
193 buffer_blocknr[buffer] = blocknr; 193 buffer_blocknr[buffer] = blocknr;
194 buffer_dev[buffer] = sb; 194 buffer_dev[buffer] = sb;
195 195
196 data = read_buffers[buffer]; 196 data = read_buffers[buffer];
197 for (i = 0; i < BLKS_PER_BUF; i++) { 197 for (i = 0; i < BLKS_PER_BUF; i++) {
198 struct page *page = pages[i]; 198 struct page *page = pages[i];
199 if (page) { 199 if (page) {
200 memcpy(data, kmap(page), PAGE_CACHE_SIZE); 200 memcpy(data, kmap(page), PAGE_CACHE_SIZE);
201 kunmap(page); 201 kunmap(page);
202 page_cache_release(page); 202 page_cache_release(page);
203 } else 203 } else
204 memset(data, 0, PAGE_CACHE_SIZE); 204 memset(data, 0, PAGE_CACHE_SIZE);
205 data += PAGE_CACHE_SIZE; 205 data += PAGE_CACHE_SIZE;
206 } 206 }
207 return read_buffers[buffer] + offset; 207 return read_buffers[buffer] + offset;
208 } 208 }
209 209
210 static void cramfs_put_super(struct super_block *sb) 210 static void cramfs_put_super(struct super_block *sb)
211 { 211 {
212 kfree(sb->s_fs_info); 212 kfree(sb->s_fs_info);
213 sb->s_fs_info = NULL; 213 sb->s_fs_info = NULL;
214 } 214 }
215 215
216 static int cramfs_remount(struct super_block *sb, int *flags, char *data) 216 static int cramfs_remount(struct super_block *sb, int *flags, char *data)
217 { 217 {
218 *flags |= MS_RDONLY; 218 *flags |= MS_RDONLY;
219 return 0; 219 return 0;
220 } 220 }
221 221
222 static int cramfs_fill_super(struct super_block *sb, void *data, int silent) 222 static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
223 { 223 {
224 int i; 224 int i;
225 struct cramfs_super super; 225 struct cramfs_super super;
226 unsigned long root_offset; 226 unsigned long root_offset;
227 struct cramfs_sb_info *sbi; 227 struct cramfs_sb_info *sbi;
228 struct inode *root; 228 struct inode *root;
229 229
230 sb->s_flags |= MS_RDONLY; 230 sb->s_flags |= MS_RDONLY;
231 231
232 sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL); 232 sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
233 if (!sbi) 233 if (!sbi)
234 return -ENOMEM; 234 return -ENOMEM;
235 sb->s_fs_info = sbi; 235 sb->s_fs_info = sbi;
236 236
237 /* Invalidate the read buffers on mount: think disk change.. */ 237 /* Invalidate the read buffers on mount: think disk change.. */
238 mutex_lock(&read_mutex); 238 mutex_lock(&read_mutex);
239 for (i = 0; i < READ_BUFFERS; i++) 239 for (i = 0; i < READ_BUFFERS; i++)
240 buffer_blocknr[i] = -1; 240 buffer_blocknr[i] = -1;
241 241
242 /* Read the first block and get the superblock from it */ 242 /* Read the first block and get the superblock from it */
243 memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super)); 243 memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
244 mutex_unlock(&read_mutex); 244 mutex_unlock(&read_mutex);
245 245
246 /* Do sanity checks on the superblock */ 246 /* Do sanity checks on the superblock */
247 if (super.magic != CRAMFS_MAGIC) { 247 if (super.magic != CRAMFS_MAGIC) {
248 /* check for wrong endianess */ 248 /* check for wrong endianess */
249 if (super.magic == CRAMFS_MAGIC_WEND) { 249 if (super.magic == CRAMFS_MAGIC_WEND) {
250 if (!silent) 250 if (!silent)
251 printk(KERN_ERR "cramfs: wrong endianess\n"); 251 printk(KERN_ERR "cramfs: wrong endianess\n");
252 goto out; 252 goto out;
253 } 253 }
254 254
255 /* check at 512 byte offset */ 255 /* check at 512 byte offset */
256 mutex_lock(&read_mutex); 256 mutex_lock(&read_mutex);
257 memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); 257 memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
258 mutex_unlock(&read_mutex); 258 mutex_unlock(&read_mutex);
259 if (super.magic != CRAMFS_MAGIC) { 259 if (super.magic != CRAMFS_MAGIC) {
260 if (super.magic == CRAMFS_MAGIC_WEND && !silent) 260 if (super.magic == CRAMFS_MAGIC_WEND && !silent)
261 printk(KERN_ERR "cramfs: wrong endianess\n"); 261 printk(KERN_ERR "cramfs: wrong endianess\n");
262 else if (!silent) 262 else if (!silent)
263 printk(KERN_ERR "cramfs: wrong magic\n"); 263 printk(KERN_ERR "cramfs: wrong magic\n");
264 goto out; 264 goto out;
265 } 265 }
266 } 266 }
267 267
268 /* get feature flags first */ 268 /* get feature flags first */
269 if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { 269 if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
270 printk(KERN_ERR "cramfs: unsupported filesystem features\n"); 270 printk(KERN_ERR "cramfs: unsupported filesystem features\n");
271 goto out; 271 goto out;
272 } 272 }
273 273
274 /* Check that the root inode is in a sane state */ 274 /* Check that the root inode is in a sane state */
275 if (!S_ISDIR(super.root.mode)) { 275 if (!S_ISDIR(super.root.mode)) {
276 printk(KERN_ERR "cramfs: root is not a directory\n"); 276 printk(KERN_ERR "cramfs: root is not a directory\n");
277 goto out; 277 goto out;
278 } 278 }
279 root_offset = super.root.offset << 2; 279 root_offset = super.root.offset << 2;
280 if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { 280 if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
281 sbi->size=super.size; 281 sbi->size=super.size;
282 sbi->blocks=super.fsid.blocks; 282 sbi->blocks=super.fsid.blocks;
283 sbi->files=super.fsid.files; 283 sbi->files=super.fsid.files;
284 } else { 284 } else {
285 sbi->size=1<<28; 285 sbi->size=1<<28;
286 sbi->blocks=0; 286 sbi->blocks=0;
287 sbi->files=0; 287 sbi->files=0;
288 } 288 }
289 sbi->magic=super.magic; 289 sbi->magic=super.magic;
290 sbi->flags=super.flags; 290 sbi->flags=super.flags;
291 if (root_offset == 0) 291 if (root_offset == 0)
292 printk(KERN_INFO "cramfs: empty filesystem"); 292 printk(KERN_INFO "cramfs: empty filesystem");
293 else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && 293 else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
294 ((root_offset != sizeof(struct cramfs_super)) && 294 ((root_offset != sizeof(struct cramfs_super)) &&
295 (root_offset != 512 + sizeof(struct cramfs_super)))) 295 (root_offset != 512 + sizeof(struct cramfs_super))))
296 { 296 {
297 printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset); 297 printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset);
298 goto out; 298 goto out;
299 } 299 }
300 300
301 /* Set it all up.. */ 301 /* Set it all up.. */
302 sb->s_op = &cramfs_ops; 302 sb->s_op = &cramfs_ops;
303 root = get_cramfs_inode(sb, &super.root); 303 root = get_cramfs_inode(sb, &super.root);
304 if (!root) 304 if (!root)
305 goto out; 305 goto out;
306 sb->s_root = d_alloc_root(root); 306 sb->s_root = d_alloc_root(root);
307 if (!sb->s_root) { 307 if (!sb->s_root) {
308 iput(root); 308 iput(root);
309 goto out; 309 goto out;
310 } 310 }
311 return 0; 311 return 0;
312 out: 312 out:
313 kfree(sbi); 313 kfree(sbi);
314 sb->s_fs_info = NULL; 314 sb->s_fs_info = NULL;
315 return -EINVAL; 315 return -EINVAL;
316 } 316 }
317 317
318 static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) 318 static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
319 { 319 {
320 struct super_block *sb = dentry->d_sb; 320 struct super_block *sb = dentry->d_sb;
321 321
322 buf->f_type = CRAMFS_MAGIC; 322 buf->f_type = CRAMFS_MAGIC;
323 buf->f_bsize = PAGE_CACHE_SIZE; 323 buf->f_bsize = PAGE_CACHE_SIZE;
324 buf->f_blocks = CRAMFS_SB(sb)->blocks; 324 buf->f_blocks = CRAMFS_SB(sb)->blocks;
325 buf->f_bfree = 0; 325 buf->f_bfree = 0;
326 buf->f_bavail = 0; 326 buf->f_bavail = 0;
327 buf->f_files = CRAMFS_SB(sb)->files; 327 buf->f_files = CRAMFS_SB(sb)->files;
328 buf->f_ffree = 0; 328 buf->f_ffree = 0;
329 buf->f_namelen = CRAMFS_MAXPATHLEN; 329 buf->f_namelen = CRAMFS_MAXPATHLEN;
330 return 0; 330 return 0;
331 } 331 }
332 332
333 /* 333 /*
334 * Read a cramfs directory entry. 334 * Read a cramfs directory entry.
335 */ 335 */
336 static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) 336 static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
337 { 337 {
338 struct inode *inode = filp->f_path.dentry->d_inode; 338 struct inode *inode = filp->f_path.dentry->d_inode;
339 struct super_block *sb = inode->i_sb; 339 struct super_block *sb = inode->i_sb;
340 char *buf; 340 char *buf;
341 unsigned int offset; 341 unsigned int offset;
342 int copied; 342 int copied;
343 343
344 /* Offset within the thing. */ 344 /* Offset within the thing. */
345 offset = filp->f_pos; 345 offset = filp->f_pos;
346 if (offset >= inode->i_size) 346 if (offset >= inode->i_size)
347 return 0; 347 return 0;
348 /* Directory entries are always 4-byte aligned */ 348 /* Directory entries are always 4-byte aligned */
349 if (offset & 3) 349 if (offset & 3)
350 return -EINVAL; 350 return -EINVAL;
351 351
352 buf = kmalloc(CRAMFS_MAXPATHLEN, GFP_KERNEL); 352 buf = kmalloc(CRAMFS_MAXPATHLEN, GFP_KERNEL);
353 if (!buf) 353 if (!buf)
354 return -ENOMEM; 354 return -ENOMEM;
355 355
356 copied = 0; 356 copied = 0;
357 while (offset < inode->i_size) { 357 while (offset < inode->i_size) {
358 struct cramfs_inode *de; 358 struct cramfs_inode *de;
359 unsigned long nextoffset; 359 unsigned long nextoffset;
360 char *name; 360 char *name;
361 ino_t ino; 361 ino_t ino;
362 mode_t mode; 362 mode_t mode;
363 int namelen, error; 363 int namelen, error;
364 364
365 mutex_lock(&read_mutex); 365 mutex_lock(&read_mutex);
366 de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); 366 de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
367 name = (char *)(de+1); 367 name = (char *)(de+1);
368 368
369 /* 369 /*
370 * Namelengths on disk are shifted by two 370 * Namelengths on disk are shifted by two
371 * and the name padded out to 4-byte boundaries 371 * and the name padded out to 4-byte boundaries
372 * with zeroes. 372 * with zeroes.
373 */ 373 */
374 namelen = de->namelen << 2; 374 namelen = de->namelen << 2;
375 memcpy(buf, name, namelen); 375 memcpy(buf, name, namelen);
376 ino = CRAMINO(de); 376 ino = CRAMINO(de);
377 mode = de->mode; 377 mode = de->mode;
378 mutex_unlock(&read_mutex); 378 mutex_unlock(&read_mutex);
379 nextoffset = offset + sizeof(*de) + namelen; 379 nextoffset = offset + sizeof(*de) + namelen;
380 for (;;) { 380 for (;;) {
381 if (!namelen) { 381 if (!namelen) {
382 kfree(buf); 382 kfree(buf);
383 return -EIO; 383 return -EIO;
384 } 384 }
385 if (buf[namelen-1]) 385 if (buf[namelen-1])
386 break; 386 break;
387 namelen--; 387 namelen--;
388 } 388 }
389 error = filldir(dirent, buf, namelen, offset, ino, mode >> 12); 389 error = filldir(dirent, buf, namelen, offset, ino, mode >> 12);
390 if (error) 390 if (error)
391 break; 391 break;
392 392
393 offset = nextoffset; 393 offset = nextoffset;
394 filp->f_pos = offset; 394 filp->f_pos = offset;
395 copied++; 395 copied++;
396 } 396 }
397 kfree(buf); 397 kfree(buf);
398 return 0; 398 return 0;
399 } 399 }
400 400
401 /* 401 /*
402 * Lookup and fill in the inode data.. 402 * Lookup and fill in the inode data..
403 */ 403 */
404 static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) 404 static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
405 { 405 {
406 unsigned int offset = 0; 406 unsigned int offset = 0;
407 int sorted; 407 int sorted;
408 408
409 mutex_lock(&read_mutex); 409 mutex_lock(&read_mutex);
410 sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS; 410 sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS;
411 while (offset < dir->i_size) { 411 while (offset < dir->i_size) {
412 struct cramfs_inode *de; 412 struct cramfs_inode *de;
413 char *name; 413 char *name;
414 int namelen, retval; 414 int namelen, retval;
415 415
416 de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); 416 de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
417 name = (char *)(de+1); 417 name = (char *)(de+1);
418 418
419 /* Try to take advantage of sorted directories */ 419 /* Try to take advantage of sorted directories */
420 if (sorted && (dentry->d_name.name[0] < name[0])) 420 if (sorted && (dentry->d_name.name[0] < name[0]))
421 break; 421 break;
422 422
423 namelen = de->namelen << 2; 423 namelen = de->namelen << 2;
424 offset += sizeof(*de) + namelen; 424 offset += sizeof(*de) + namelen;
425 425
426 /* Quick check that the name is roughly the right length */ 426 /* Quick check that the name is roughly the right length */
427 if (((dentry->d_name.len + 3) & ~3) != namelen) 427 if (((dentry->d_name.len + 3) & ~3) != namelen)
428 continue; 428 continue;
429 429
430 for (;;) { 430 for (;;) {
431 if (!namelen) { 431 if (!namelen) {
432 mutex_unlock(&read_mutex); 432 mutex_unlock(&read_mutex);
433 return ERR_PTR(-EIO); 433 return ERR_PTR(-EIO);
434 } 434 }
435 if (name[namelen-1]) 435 if (name[namelen-1])
436 break; 436 break;
437 namelen--; 437 namelen--;
438 } 438 }
439 if (namelen != dentry->d_name.len) 439 if (namelen != dentry->d_name.len)
440 continue; 440 continue;
441 retval = memcmp(dentry->d_name.name, name, namelen); 441 retval = memcmp(dentry->d_name.name, name, namelen);
442 if (retval > 0) 442 if (retval > 0)
443 continue; 443 continue;
444 if (!retval) { 444 if (!retval) {
445 struct cramfs_inode entry = *de; 445 struct cramfs_inode entry = *de;
446 mutex_unlock(&read_mutex); 446 mutex_unlock(&read_mutex);
447 d_add(dentry, get_cramfs_inode(dir->i_sb, &entry)); 447 d_add(dentry, get_cramfs_inode(dir->i_sb, &entry));
448 return NULL; 448 return NULL;
449 } 449 }
450 /* else (retval < 0) */ 450 /* else (retval < 0) */
451 if (sorted) 451 if (sorted)
452 break; 452 break;
453 } 453 }
454 mutex_unlock(&read_mutex); 454 mutex_unlock(&read_mutex);
455 d_add(dentry, NULL); 455 d_add(dentry, NULL);
456 return NULL; 456 return NULL;
457 } 457 }
458 458
459 static int cramfs_readpage(struct file *file, struct page * page) 459 static int cramfs_readpage(struct file *file, struct page * page)
460 { 460 {
461 struct inode *inode = page->mapping->host; 461 struct inode *inode = page->mapping->host;
462 u32 maxblock, bytes_filled; 462 u32 maxblock;
463 int bytes_filled;
463 void *pgdata; 464 void *pgdata;
464 465
465 maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 466 maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
466 bytes_filled = 0; 467 bytes_filled = 0;
468 pgdata = kmap(page);
469
467 if (page->index < maxblock) { 470 if (page->index < maxblock) {
468 struct super_block *sb = inode->i_sb; 471 struct super_block *sb = inode->i_sb;
469 u32 blkptr_offset = OFFSET(inode) + page->index*4; 472 u32 blkptr_offset = OFFSET(inode) + page->index*4;
470 u32 start_offset, compr_len; 473 u32 start_offset, compr_len;
471 474
472 start_offset = OFFSET(inode) + maxblock*4; 475 start_offset = OFFSET(inode) + maxblock*4;
473 mutex_lock(&read_mutex); 476 mutex_lock(&read_mutex);
474 if (page->index) 477 if (page->index)
475 start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); 478 start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
476 compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); 479 4);
480 compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
481 start_offset);
477 mutex_unlock(&read_mutex); 482 mutex_unlock(&read_mutex);
478 pgdata = kmap(page); 483
479 if (compr_len == 0) 484 if (compr_len == 0)
480 ; /* hole */ 485 ; /* hole */
481 else if (compr_len > (PAGE_CACHE_SIZE << 1)) 486 else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) {
482 printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len); 487 pr_err("cramfs: bad compressed blocksize %u\n",
483 else { 488 compr_len);
489 goto err;
490 } else {
484 mutex_lock(&read_mutex); 491 mutex_lock(&read_mutex);
485 bytes_filled = cramfs_uncompress_block(pgdata, 492 bytes_filled = cramfs_uncompress_block(pgdata,
486 PAGE_CACHE_SIZE, 493 PAGE_CACHE_SIZE,
487 cramfs_read(sb, start_offset, compr_len), 494 cramfs_read(sb, start_offset, compr_len),
488 compr_len); 495 compr_len);
489 mutex_unlock(&read_mutex); 496 mutex_unlock(&read_mutex);
497 if (unlikely(bytes_filled < 0))
498 goto err;
490 } 499 }
491 } else 500 }
492 pgdata = kmap(page); 501
493 memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); 502 memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
494 kunmap(page);
495 flush_dcache_page(page); 503 flush_dcache_page(page);
504 kunmap(page);
496 SetPageUptodate(page); 505 SetPageUptodate(page);
506 unlock_page(page);
507 return 0;
508
509 err:
510 kunmap(page);
511 ClearPageUptodate(page);
512 SetPageError(page);
497 unlock_page(page); 513 unlock_page(page);
498 return 0; 514 return 0;
499 } 515 }
500 516
501 static const struct address_space_operations cramfs_aops = { 517 static const struct address_space_operations cramfs_aops = {
502 .readpage = cramfs_readpage 518 .readpage = cramfs_readpage
503 }; 519 };
504 520
505 /* 521 /*
506 * Our operations: 522 * Our operations:
507 */ 523 */
508 524
509 /* 525 /*
510 * A directory can only readdir 526 * A directory can only readdir
511 */ 527 */
512 static const struct file_operations cramfs_directory_operations = { 528 static const struct file_operations cramfs_directory_operations = {
513 .llseek = generic_file_llseek, 529 .llseek = generic_file_llseek,
514 .read = generic_read_dir, 530 .read = generic_read_dir,
515 .readdir = cramfs_readdir, 531 .readdir = cramfs_readdir,
516 }; 532 };
517 533
518 static const struct inode_operations cramfs_dir_inode_operations = { 534 static const struct inode_operations cramfs_dir_inode_operations = {
519 .lookup = cramfs_lookup, 535 .lookup = cramfs_lookup,
520 }; 536 };
521 537
522 static const struct super_operations cramfs_ops = { 538 static const struct super_operations cramfs_ops = {
523 .put_super = cramfs_put_super, 539 .put_super = cramfs_put_super,
524 .remount_fs = cramfs_remount, 540 .remount_fs = cramfs_remount,
525 .statfs = cramfs_statfs, 541 .statfs = cramfs_statfs,
526 .drop_inode = cramfs_drop_inode, 542 .drop_inode = cramfs_drop_inode,
527 }; 543 };
528 544
529 static int cramfs_get_sb(struct file_system_type *fs_type, 545 static int cramfs_get_sb(struct file_system_type *fs_type,
530 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 546 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
531 { 547 {
532 return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super, 548 return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super,
533 mnt); 549 mnt);
534 } 550 }
535 551
536 static struct file_system_type cramfs_fs_type = { 552 static struct file_system_type cramfs_fs_type = {
537 .owner = THIS_MODULE, 553 .owner = THIS_MODULE,
538 .name = "cramfs", 554 .name = "cramfs",
539 .get_sb = cramfs_get_sb, 555 .get_sb = cramfs_get_sb,
540 .kill_sb = kill_block_super, 556 .kill_sb = kill_block_super,
541 .fs_flags = FS_REQUIRES_DEV, 557 .fs_flags = FS_REQUIRES_DEV,
542 }; 558 };
543 559
544 static int __init init_cramfs_fs(void) 560 static int __init init_cramfs_fs(void)
545 { 561 {
546 int rv; 562 int rv;
547 563
548 rv = cramfs_uncompress_init(); 564 rv = cramfs_uncompress_init();
549 if (rv < 0) 565 if (rv < 0)
550 return rv; 566 return rv;
551 rv = register_filesystem(&cramfs_fs_type); 567 rv = register_filesystem(&cramfs_fs_type);
552 if (rv < 0) 568 if (rv < 0)
553 cramfs_uncompress_exit(); 569 cramfs_uncompress_exit();
554 return rv; 570 return rv;
555 } 571 }
556 572
557 static void __exit exit_cramfs_fs(void) 573 static void __exit exit_cramfs_fs(void)
558 { 574 {
559 cramfs_uncompress_exit(); 575 cramfs_uncompress_exit();
560 unregister_filesystem(&cramfs_fs_type); 576 unregister_filesystem(&cramfs_fs_type);
561 } 577 }
562 578
563 module_init(init_cramfs_fs) 579 module_init(init_cramfs_fs)
564 module_exit(exit_cramfs_fs) 580 module_exit(exit_cramfs_fs)
565 MODULE_LICENSE("GPL"); 581 MODULE_LICENSE("GPL");
fs/cramfs/uncompress.c
1 /* 1 /*
2 * uncompress.c 2 * uncompress.c
3 * 3 *
4 * (C) Copyright 1999 Linus Torvalds 4 * (C) Copyright 1999 Linus Torvalds
5 * 5 *
6 * cramfs interfaces to the uncompression library. There's really just 6 * cramfs interfaces to the uncompression library. There's really just
7 * three entrypoints: 7 * three entrypoints:
8 * 8 *
9 * - cramfs_uncompress_init() - called to initialize the thing. 9 * - cramfs_uncompress_init() - called to initialize the thing.
10 * - cramfs_uncompress_exit() - tell me when you're done 10 * - cramfs_uncompress_exit() - tell me when you're done
11 * - cramfs_uncompress_block() - uncompress a block. 11 * - cramfs_uncompress_block() - uncompress a block.
12 * 12 *
13 * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We 13 * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
14 * only have one stream, and we'll initialize it only once even if it 14 * only have one stream, and we'll initialize it only once even if it
15 * then is used by multiple filesystems. 15 * then is used by multiple filesystems.
16 */ 16 */
17 17
18 #include <linux/kernel.h> 18 #include <linux/kernel.h>
19 #include <linux/errno.h> 19 #include <linux/errno.h>
20 #include <linux/vmalloc.h> 20 #include <linux/vmalloc.h>
21 #include <linux/zlib.h> 21 #include <linux/zlib.h>
22 #include <linux/cramfs_fs.h> 22 #include <linux/cramfs_fs.h>
23 23
24 static z_stream stream; 24 static z_stream stream;
25 static int initialized; 25 static int initialized;
26 26
27 /* Returns length of decompressed data. */ 27 /* Returns length of decompressed data. */
28 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) 28 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
29 { 29 {
30 int err; 30 int err;
31 31
32 stream.next_in = src; 32 stream.next_in = src;
33 stream.avail_in = srclen; 33 stream.avail_in = srclen;
34 34
35 stream.next_out = dst; 35 stream.next_out = dst;
36 stream.avail_out = dstlen; 36 stream.avail_out = dstlen;
37 37
38 err = zlib_inflateReset(&stream); 38 err = zlib_inflateReset(&stream);
39 if (err != Z_OK) { 39 if (err != Z_OK) {
40 printk("zlib_inflateReset error %d\n", err); 40 printk("zlib_inflateReset error %d\n", err);
41 zlib_inflateEnd(&stream); 41 zlib_inflateEnd(&stream);
42 zlib_inflateInit(&stream); 42 zlib_inflateInit(&stream);
43 } 43 }
44 44
45 err = zlib_inflate(&stream, Z_FINISH); 45 err = zlib_inflate(&stream, Z_FINISH);
46 if (err != Z_STREAM_END) 46 if (err != Z_STREAM_END)
47 goto err; 47 goto err;
48 return stream.total_out; 48 return stream.total_out;
49 49
50 err: 50 err:
51 printk("Error %d while decompressing!\n", err); 51 printk("Error %d while decompressing!\n", err);
52 printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); 52 printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
53 return 0; 53 return -EIO;
54 } 54 }
55 55
56 int cramfs_uncompress_init(void) 56 int cramfs_uncompress_init(void)
57 { 57 {
58 if (!initialized++) { 58 if (!initialized++) {
59 stream.workspace = vmalloc(zlib_inflate_workspacesize()); 59 stream.workspace = vmalloc(zlib_inflate_workspacesize());
60 if ( !stream.workspace ) { 60 if ( !stream.workspace ) {
61 initialized = 0; 61 initialized = 0;
62 return -ENOMEM; 62 return -ENOMEM;
63 } 63 }
64 stream.next_in = NULL; 64 stream.next_in = NULL;
65 stream.avail_in = 0; 65 stream.avail_in = 0;
66 zlib_inflateInit(&stream); 66 zlib_inflateInit(&stream);
67 } 67 }
68 return 0; 68 return 0;
69 } 69 }
70 70
71 void cramfs_uncompress_exit(void) 71 void cramfs_uncompress_exit(void)
72 { 72 {
73 if (!--initialized) { 73 if (!--initialized) {
74 zlib_inflateEnd(&stream); 74 zlib_inflateEnd(&stream);
75 vfree(stream.workspace); 75 vfree(stream.workspace);
76 } 76 }
77 } 77 }
78 78