• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Squashfs - a compressed read only filesystem for Linux
3  *
4  * Copyright (c) 2002, 2003, 2004, 2005, 2006
5  * Phillip Lougher <phillip@lougher.demon.co.uk>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2,
10  * or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * inode.c
22  */
23 
24 #include <linux/types.h>
25 #include <linux/squashfs_fs.h>
26 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/slab.h>
29 #include <linux/zlib.h>
30 #include <linux/fs.h>
31 #include <linux/smp_lock.h>
32 #include <linux/locks.h>
33 #include <linux/init.h>
34 #include <linux/dcache.h>
35 #include <linux/wait.h>
36 #include <linux/blkdev.h>
37 #include <linux/vmalloc.h>
38 #include <asm/uaccess.h>
39 #include <asm/semaphore.h>
40 
41 #include "squashfs.h"
42 
43 static struct super_block *squashfs_read_super(struct super_block *, void *, int);
44 static void squashfs_put_super(struct super_block *);
45 static int squashfs_statfs(struct super_block *, struct statfs *);
46 static int squashfs_symlink_readpage(struct file *file, struct page *page);
47 static int squashfs_readpage(struct file *file, struct page *page);
48 static int squashfs_readpage4K(struct file *file, struct page *page);
49 static int squashfs_readdir(struct file *, void *, filldir_t);
50 static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
51 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
52 static long long read_blocklist(struct inode *inode, int index,
53 				int readahead_blks, char *block_list,
54 				unsigned short **block_p, unsigned int *bsize);
55 
56 static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
57 
58 static unsigned char squashfs_filetype_table[] = {
59 	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
60 };
61 
62 static struct super_operations squashfs_ops = {
63 	.statfs = squashfs_statfs,
64 	.put_super = squashfs_put_super,
65 };
66 
67 SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
68 	.readpage = squashfs_symlink_readpage
69 };
70 
71 SQSH_EXTERN struct address_space_operations squashfs_aops = {
72 	.readpage = squashfs_readpage
73 };
74 
75 SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
76 	.readpage = squashfs_readpage4K
77 };
78 
79 static struct file_operations squashfs_dir_ops = {
80 	.read = generic_read_dir,
81 	.readdir = squashfs_readdir
82 };
83 
84 static struct inode_operations squashfs_dir_inode_ops = {
85 	.lookup = squashfs_lookup
86 };
87 
get_block_length(struct super_block * s,int * cur_index,int * offset,int * c_byte)88 static struct buffer_head *get_block_length(struct super_block *s,
89 				int *cur_index, int *offset, int *c_byte)
90 {
91 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
92 	unsigned short temp;
93 	struct buffer_head *bh;
94 
95 	if (!(bh = sb_bread(s, *cur_index)))
96 		goto out;
97 
98 	if (msblk->devblksize - *offset == 1) {
99 		if (msblk->swap)
100 			((unsigned char *) &temp)[1] = *((unsigned char *)
101 				(bh->b_data + *offset));
102 		else
103 			((unsigned char *) &temp)[0] = *((unsigned char *)
104 				(bh->b_data + *offset));
105 		brelse(bh);
106 		if (!(bh = sb_bread(s, ++(*cur_index))))
107 			goto out;
108 		if (msblk->swap)
109 			((unsigned char *) &temp)[0] = *((unsigned char *)
110 				bh->b_data);
111 		else
112 			((unsigned char *) &temp)[1] = *((unsigned char *)
113 				bh->b_data);
114 		*c_byte = temp;
115 		*offset = 1;
116 	} else {
117 		if (msblk->swap) {
118 			((unsigned char *) &temp)[1] = *((unsigned char *)
119 				(bh->b_data + *offset));
120 			((unsigned char *) &temp)[0] = *((unsigned char *)
121 				(bh->b_data + *offset + 1));
122 		} else {
123 			((unsigned char *) &temp)[0] = *((unsigned char *)
124 				(bh->b_data + *offset));
125 			((unsigned char *) &temp)[1] = *((unsigned char *)
126 				(bh->b_data + *offset + 1));
127 		}
128 		*c_byte = temp;
129 		*offset += 2;
130 	}
131 
132 	if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
133 		if (*offset == msblk->devblksize) {
134 			brelse(bh);
135 			if (!(bh = sb_bread(s, ++(*cur_index))))
136 				goto out;
137 			*offset = 0;
138 		}
139 		if (*((unsigned char *) (bh->b_data + *offset)) !=
140 						SQUASHFS_MARKER_BYTE) {
141 			ERROR("Metadata block marker corrupt @ %x\n",
142 						*cur_index);
143 			brelse(bh);
144 			goto out;
145 		}
146 		(*offset)++;
147 	}
148 	return bh;
149 
150 out:
151 	return NULL;
152 }
153 
154 
squashfs_read_data(struct super_block * s,char * buffer,long long index,unsigned int length,long long * next_index)155 SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
156 			long long index, unsigned int length,
157 			long long *next_index)
158 {
159 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
160 	struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
161 			msblk->devblksize_log2) + 2];
162 	unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
163 	unsigned int cur_index = index >> msblk->devblksize_log2;
164 	int bytes, avail_bytes, b = 0, k;
165 	char *c_buffer;
166 	unsigned int compressed;
167 	unsigned int c_byte = length;
168 
169 	if (c_byte) {
170 		bytes = msblk->devblksize - offset;
171 		compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
172 		c_buffer = compressed ? msblk->read_data : buffer;
173 		c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
174 
175 		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
176 					? "" : "un", (unsigned int) c_byte);
177 
178 		if (!(bh[0] = sb_getblk(s, cur_index)))
179 			goto block_release;
180 
181 		for (b = 1; bytes < c_byte; b++) {
182 			if (!(bh[b] = sb_getblk(s, ++cur_index)))
183 				goto block_release;
184 			bytes += msblk->devblksize;
185 		}
186 		ll_rw_block(READ, b, bh);
187 	} else {
188 		if (!(bh[0] = get_block_length(s, &cur_index, &offset,
189 								&c_byte)))
190 			goto read_failure;
191 
192 		bytes = msblk->devblksize - offset;
193 		compressed = SQUASHFS_COMPRESSED(c_byte);
194 		c_buffer = compressed ? msblk->read_data : buffer;
195 		c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
196 
197 		TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
198 					? "" : "un", (unsigned int) c_byte);
199 
200 		for (b = 1; bytes < c_byte; b++) {
201 			if (!(bh[b] = sb_getblk(s, ++cur_index)))
202 				goto block_release;
203 			bytes += msblk->devblksize;
204 		}
205 		ll_rw_block(READ, b - 1, bh + 1);
206 	}
207 
208 	if (compressed)
209 		down(&msblk->read_data_mutex);
210 
211 	for (bytes = 0, k = 0; k < b; k++) {
212 		avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
213 					msblk->devblksize - offset :
214 					c_byte - bytes;
215 		wait_on_buffer(bh[k]);
216 		if (!buffer_uptodate(bh[k]))
217 			goto block_release;
218 		memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
219 		bytes += avail_bytes;
220 		offset = 0;
221 		brelse(bh[k]);
222 	}
223 
224 	/*
225 	 * uncompress block
226 	 */
227 	if (compressed) {
228 		int zlib_err;
229 
230 		msblk->stream.next_in = c_buffer;
231 		msblk->stream.avail_in = c_byte;
232 		msblk->stream.next_out = buffer;
233 		msblk->stream.avail_out = msblk->read_size;
234 
235 		if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) ||
236 				((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH))
237 				 != Z_STREAM_END) || ((zlib_err =
238 				zlib_inflateEnd(&msblk->stream)) != Z_OK)) {
239 			ERROR("zlib_fs returned unexpected result 0x%x\n",
240 				zlib_err);
241 			bytes = 0;
242 		} else
243 			bytes = msblk->stream.total_out;
244 
245 		up(&msblk->read_data_mutex);
246 	}
247 
248 	if (next_index)
249 		*next_index = index + c_byte + (length ? 0 :
250 				(SQUASHFS_CHECK_DATA(msblk->sblk.flags)
251 				 ? 3 : 2));
252 	return bytes;
253 
254 block_release:
255 	while (--b >= 0)
256 		brelse(bh[b]);
257 
258 read_failure:
259 	ERROR("sb_bread failed reading block 0x%x\n", cur_index);
260 	return 0;
261 }
262 
263 
squashfs_get_cached_block(struct super_block * s,char * buffer,long long block,unsigned int offset,int length,long long * next_block,unsigned int * next_offset)264 SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
265 				long long block, unsigned int offset,
266 				int length, long long *next_block,
267 				unsigned int *next_offset)
268 {
269 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
270 	int n, i, bytes, return_length = length;
271 	long long next_index;
272 
273 	TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
274 
275 	while ( 1 ) {
276 		for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
277 			if (msblk->block_cache[i].block == block)
278 				break;
279 
280 		down(&msblk->block_cache_mutex);
281 
282 		if (i == SQUASHFS_CACHED_BLKS) {
283 			/* read inode header block */
284 			for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
285 					n ; n --, i = (i + 1) %
286 					SQUASHFS_CACHED_BLKS)
287 				if (msblk->block_cache[i].block !=
288 							SQUASHFS_USED_BLK)
289 					break;
290 
291 			if (n == 0) {
292 				wait_queue_t wait;
293 
294 				init_waitqueue_entry(&wait, current);
295 				add_wait_queue(&msblk->waitq, &wait);
296 				set_current_state(TASK_UNINTERRUPTIBLE);
297  				up(&msblk->block_cache_mutex);
298 				schedule();
299 				set_current_state(TASK_RUNNING);
300 				remove_wait_queue(&msblk->waitq, &wait);
301 				continue;
302 			}
303 			msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
304 
305 			if (msblk->block_cache[i].block ==
306 							SQUASHFS_INVALID_BLK) {
307 				if (!(msblk->block_cache[i].data =
308 						kmalloc(SQUASHFS_METADATA_SIZE,
309 						GFP_KERNEL))) {
310 					ERROR("Failed to allocate cache"
311 							"block\n");
312 					up(&msblk->block_cache_mutex);
313 					goto out;
314 				}
315 			}
316 
317 			msblk->block_cache[i].block = SQUASHFS_USED_BLK;
318 			up(&msblk->block_cache_mutex);
319 
320 			if (!(msblk->block_cache[i].length =
321 						squashfs_read_data(s,
322 						msblk->block_cache[i].data,
323 						block, 0, &next_index))) {
324 				ERROR("Unable to read cache block [%llx:%x]\n",
325 						block, offset);
326 				goto out;
327 			}
328 
329 			down(&msblk->block_cache_mutex);
330 			wake_up(&msblk->waitq);
331 			msblk->block_cache[i].block = block;
332 			msblk->block_cache[i].next_index = next_index;
333 			TRACE("Read cache block [%llx:%x]\n", block, offset);
334 		}
335 
336 		if (msblk->block_cache[i].block != block) {
337 			up(&msblk->block_cache_mutex);
338 			continue;
339 		}
340 
341 		if ((bytes = msblk->block_cache[i].length - offset) >= length) {
342 			if (buffer)
343 				memcpy(buffer, msblk->block_cache[i].data +
344 						offset, length);
345 			if (msblk->block_cache[i].length - offset == length) {
346 				*next_block = msblk->block_cache[i].next_index;
347 				*next_offset = 0;
348 			} else {
349 				*next_block = block;
350 				*next_offset = offset + length;
351 			}
352 			up(&msblk->block_cache_mutex);
353 			goto finish;
354 		} else {
355 			if (buffer) {
356 				memcpy(buffer, msblk->block_cache[i].data +
357 						offset, bytes);
358 				buffer += bytes;
359 			}
360 			block = msblk->block_cache[i].next_index;
361 			up(&msblk->block_cache_mutex);
362 			length -= bytes;
363 			offset = 0;
364 		}
365 	}
366 
367 finish:
368 	return return_length;
369 out:
370 	return 0;
371 }
372 
373 
get_fragment_location(struct super_block * s,unsigned int fragment,long long * fragment_start_block,unsigned int * fragment_size)374 static int get_fragment_location(struct super_block *s, unsigned int fragment,
375 				long long *fragment_start_block,
376 				unsigned int *fragment_size)
377 {
378 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
379 	long long start_block =
380 		msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
381 	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
382 	struct squashfs_fragment_entry fragment_entry;
383 
384 	if (msblk->swap) {
385 		struct squashfs_fragment_entry sfragment_entry;
386 
387 		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
388 					start_block, offset,
389 					sizeof(sfragment_entry), &start_block,
390 					&offset))
391 			goto out;
392 		SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
393 	} else
394 		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
395 					start_block, offset,
396 					sizeof(fragment_entry), &start_block,
397 					&offset))
398 			goto out;
399 
400 	*fragment_start_block = fragment_entry.start_block;
401 	*fragment_size = fragment_entry.size;
402 
403 	return 1;
404 
405 out:
406 	return 0;
407 }
408 
409 
release_cached_fragment(struct squashfs_sb_info * msblk,struct squashfs_fragment_cache * fragment)410 SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
411 					squashfs_fragment_cache *fragment)
412 {
413 	down(&msblk->fragment_mutex);
414 	fragment->locked --;
415 	wake_up(&msblk->fragment_wait_queue);
416 	up(&msblk->fragment_mutex);
417 }
418 
419 
get_cached_fragment(struct super_block * s,long long start_block,int length)420 SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
421 					*s, long long start_block,
422 					int length)
423 {
424 	int i, n;
425 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
426 
427 	while ( 1 ) {
428 		down(&msblk->fragment_mutex);
429 
430 		for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
431 				msblk->fragment[i].block != start_block; i++);
432 
433 		if (i == SQUASHFS_CACHED_FRAGMENTS) {
434 			for (i = msblk->next_fragment, n =
435 				SQUASHFS_CACHED_FRAGMENTS; n &&
436 				msblk->fragment[i].locked; n--, i = (i + 1) %
437 				SQUASHFS_CACHED_FRAGMENTS);
438 
439 			if (n == 0) {
440 				wait_queue_t wait;
441 
442 				init_waitqueue_entry(&wait, current);
443 				add_wait_queue(&msblk->fragment_wait_queue,
444 									&wait);
445 				set_current_state(TASK_UNINTERRUPTIBLE);
446 				up(&msblk->fragment_mutex);
447 				schedule();
448 				set_current_state(TASK_RUNNING);
449 				remove_wait_queue(&msblk->fragment_wait_queue,
450 									&wait);
451 				continue;
452 			}
453 			msblk->next_fragment = (msblk->next_fragment + 1) %
454 				SQUASHFS_CACHED_FRAGMENTS;
455 
456 			if (msblk->fragment[i].data == NULL)
457 				if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
458 						(SQUASHFS_FILE_MAX_SIZE))) {
459 					ERROR("Failed to allocate fragment "
460 							"cache block\n");
461 					up(&msblk->fragment_mutex);
462 					goto out;
463 				}
464 
465 			msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
466 			msblk->fragment[i].locked = 1;
467 			up(&msblk->fragment_mutex);
468 
469 			if (!(msblk->fragment[i].length = squashfs_read_data(s,
470 						msblk->fragment[i].data,
471 						start_block, length, NULL))) {
472 				ERROR("Unable to read fragment cache block "
473 							"[%llx]\n", start_block);
474 				msblk->fragment[i].locked = 0;
475 				goto out;
476 			}
477 
478 			msblk->fragment[i].block = start_block;
479 			TRACE("New fragment %d, start block %lld, locked %d\n",
480 						i, msblk->fragment[i].block,
481 						msblk->fragment[i].locked);
482 			break;
483 		}
484 
485 		msblk->fragment[i].locked++;
486 		up(&msblk->fragment_mutex);
487 		TRACE("Got fragment %d, start block %lld, locked %d\n", i,
488 						msblk->fragment[i].block,
489 						msblk->fragment[i].locked);
490 		break;
491 	}
492 
493 	return &msblk->fragment[i];
494 
495 out:
496 	return NULL;
497 }
498 
499 
squashfs_new_inode(struct super_block * s,struct squashfs_base_inode_header * inodeb)500 static struct inode *squashfs_new_inode(struct super_block *s,
501 		struct squashfs_base_inode_header *inodeb)
502 {
503 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
504 	struct inode *i = new_inode(s);
505 
506 	if (i) {
507 		i->i_ino = inodeb->inode_number;
508 		i->i_mtime = inodeb->mtime;
509 		i->i_atime = inodeb->mtime;
510 		i->i_ctime = inodeb->mtime;
511 		i->i_uid = msblk->uid[inodeb->uid];
512 		i->i_mode = inodeb->mode;
513 		i->i_size = 0;
514 		if (inodeb->guid == SQUASHFS_GUIDS)
515 			i->i_gid = i->i_uid;
516 		else
517 			i->i_gid = msblk->guid[inodeb->guid];
518 	}
519 
520 	return i;
521 }
522 
523 
squashfs_iget(struct super_block * s,squashfs_inode_t inode)524 static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode)
525 {
526 	struct inode *i;
527 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
528 	struct squashfs_super_block *sblk = &msblk->sblk;
529 	long long block = SQUASHFS_INODE_BLK(inode) +
530 		sblk->inode_table_start;
531 	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
532 	long long next_block;
533 	unsigned int next_offset;
534 	union squashfs_inode_header id, sid;
535 	struct squashfs_base_inode_header *inodeb = &id.base,
536 					  *sinodeb = &sid.base;
537 
538 	TRACE("Entered squashfs_iget\n");
539 
540 	if (msblk->swap) {
541 		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
542 					offset, sizeof(*sinodeb), &next_block,
543 					&next_offset))
544 			goto failed_read;
545 		SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
546 					sizeof(*sinodeb));
547 	} else
548 		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
549 					offset, sizeof(*inodeb), &next_block,
550 					&next_offset))
551 			goto failed_read;
552 
553 	switch(inodeb->inode_type) {
554 		case SQUASHFS_FILE_TYPE: {
555 			unsigned int frag_size;
556 			long long frag_blk;
557 			struct squashfs_reg_inode_header *inodep = &id.reg;
558 			struct squashfs_reg_inode_header *sinodep = &sid.reg;
559 
560 			if (msblk->swap) {
561 				if (!squashfs_get_cached_block(s, (char *)
562 						sinodep, block, offset,
563 						sizeof(*sinodep), &next_block,
564 						&next_offset))
565 					goto failed_read;
566 				SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
567 			} else
568 				if (!squashfs_get_cached_block(s, (char *)
569 						inodep, block, offset,
570 						sizeof(*inodep), &next_block,
571 						&next_offset))
572 					goto failed_read;
573 
574 			frag_blk = SQUASHFS_INVALID_BLK;
575 			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
576 					!get_fragment_location(s,
577 					inodep->fragment, &frag_blk, &frag_size))
578 				goto failed_read;
579 
580 			if((i = squashfs_new_inode(s, inodeb)) == NULL)
581 				goto failed_read1;
582 
583 			i->i_nlink = 1;
584 			i->i_size = inodep->file_size;
585 			i->i_fop = &generic_ro_fops;
586 			i->i_mode |= S_IFREG;
587 			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
588 			i->i_blksize = PAGE_CACHE_SIZE;
589 			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
590 			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
591 			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
592 			SQUASHFS_I(i)->start_block = inodep->start_block;
593 			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
594 			SQUASHFS_I(i)->offset = next_offset;
595 			if (sblk->block_size > 4096)
596 				i->i_data.a_ops = &squashfs_aops;
597 			else
598 				i->i_data.a_ops = &squashfs_aops_4K;
599 
600 			TRACE("File inode %x:%x, start_block %llx, "
601 					"block_list_start %llx, offset %x\n",
602 					SQUASHFS_INODE_BLK(inode), offset,
603 					inodep->start_block, next_block,
604 					next_offset);
605 			break;
606 		}
607 		case SQUASHFS_LREG_TYPE: {
608 			unsigned int frag_size;
609 			long long frag_blk;
610 			struct squashfs_lreg_inode_header *inodep = &id.lreg;
611 			struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
612 
613 			if (msblk->swap) {
614 				if (!squashfs_get_cached_block(s, (char *)
615 						sinodep, block, offset,
616 						sizeof(*sinodep), &next_block,
617 						&next_offset))
618 					goto failed_read;
619 				SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
620 			} else
621 				if (!squashfs_get_cached_block(s, (char *)
622 						inodep, block, offset,
623 						sizeof(*inodep), &next_block,
624 						&next_offset))
625 					goto failed_read;
626 
627 			frag_blk = SQUASHFS_INVALID_BLK;
628 			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
629 					!get_fragment_location(s,
630 					inodep->fragment, &frag_blk, &frag_size))
631 				goto failed_read;
632 
633 			if((i = squashfs_new_inode(s, inodeb)) == NULL)
634 				goto failed_read1;
635 
636 			i->i_nlink = inodep->nlink;
637 			i->i_size = inodep->file_size;
638 			i->i_fop = &generic_ro_fops;
639 			i->i_mode |= S_IFREG;
640 			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
641 			i->i_blksize = PAGE_CACHE_SIZE;
642 			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
643 			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
644 			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
645 			SQUASHFS_I(i)->start_block = inodep->start_block;
646 			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
647 			SQUASHFS_I(i)->offset = next_offset;
648 			if (sblk->block_size > 4096)
649 				i->i_data.a_ops = &squashfs_aops;
650 			else
651 				i->i_data.a_ops = &squashfs_aops_4K;
652 
653 			TRACE("File inode %x:%x, start_block %llx, "
654 					"block_list_start %llx, offset %x\n",
655 					SQUASHFS_INODE_BLK(inode), offset,
656 					inodep->start_block, next_block,
657 					next_offset);
658 			break;
659 		}
660 		case SQUASHFS_DIR_TYPE: {
661 			struct squashfs_dir_inode_header *inodep = &id.dir;
662 			struct squashfs_dir_inode_header *sinodep = &sid.dir;
663 
664 			if (msblk->swap) {
665 				if (!squashfs_get_cached_block(s, (char *)
666 						sinodep, block, offset,
667 						sizeof(*sinodep), &next_block,
668 						&next_offset))
669 					goto failed_read;
670 				SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
671 			} else
672 				if (!squashfs_get_cached_block(s, (char *)
673 						inodep, block, offset,
674 						sizeof(*inodep), &next_block,
675 						&next_offset))
676 					goto failed_read;
677 
678 			if((i = squashfs_new_inode(s, inodeb)) == NULL)
679 				goto failed_read1;
680 
681 			i->i_nlink = inodep->nlink;
682 			i->i_size = inodep->file_size;
683 			i->i_op = &squashfs_dir_inode_ops;
684 			i->i_fop = &squashfs_dir_ops;
685 			i->i_mode |= S_IFDIR;
686 			SQUASHFS_I(i)->start_block = inodep->start_block;
687 			SQUASHFS_I(i)->offset = inodep->offset;
688 			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
689 			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
690 
691 			TRACE("Directory inode %x:%x, start_block %x, offset "
692 					"%x\n", SQUASHFS_INODE_BLK(inode),
693 					offset, inodep->start_block,
694 					inodep->offset);
695 			break;
696 		}
697 		case SQUASHFS_LDIR_TYPE: {
698 			struct squashfs_ldir_inode_header *inodep = &id.ldir;
699 			struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
700 
701 			if (msblk->swap) {
702 				if (!squashfs_get_cached_block(s, (char *)
703 						sinodep, block, offset,
704 						sizeof(*sinodep), &next_block,
705 						&next_offset))
706 					goto failed_read;
707 				SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
708 						sinodep);
709 			} else
710 				if (!squashfs_get_cached_block(s, (char *)
711 						inodep, block, offset,
712 						sizeof(*inodep), &next_block,
713 						&next_offset))
714 					goto failed_read;
715 
716 			if((i = squashfs_new_inode(s, inodeb)) == NULL)
717 				goto failed_read1;
718 
719 			i->i_nlink = inodep->nlink;
720 			i->i_size = inodep->file_size;
721 			i->i_op = &squashfs_dir_inode_ops;
722 			i->i_fop = &squashfs_dir_ops;
723 			i->i_mode |= S_IFDIR;
724 			SQUASHFS_I(i)->start_block = inodep->start_block;
725 			SQUASHFS_I(i)->offset = inodep->offset;
726 			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
727 			SQUASHFS_I(i)->u.s2.directory_index_offset =
728 								next_offset;
729 			SQUASHFS_I(i)->u.s2.directory_index_count =
730 								inodep->i_count;
731 			SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
732 
733 			TRACE("Long directory inode %x:%x, start_block %x, "
734 					"offset %x\n",
735 					SQUASHFS_INODE_BLK(inode), offset,
736 					inodep->start_block, inodep->offset);
737 			break;
738 		}
739 		case SQUASHFS_SYMLINK_TYPE: {
740 			struct squashfs_symlink_inode_header *inodep =
741 								&id.symlink;
742 			struct squashfs_symlink_inode_header *sinodep =
743 								&sid.symlink;
744 
745 			if (msblk->swap) {
746 				if (!squashfs_get_cached_block(s, (char *)
747 						sinodep, block, offset,
748 						sizeof(*sinodep), &next_block,
749 						&next_offset))
750 					goto failed_read;
751 				SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
752 								sinodep);
753 			} else
754 				if (!squashfs_get_cached_block(s, (char *)
755 						inodep, block, offset,
756 						sizeof(*inodep), &next_block,
757 						&next_offset))
758 					goto failed_read;
759 
760 			if((i = squashfs_new_inode(s, inodeb)) == NULL)
761 				goto failed_read1;
762 
763 			i->i_nlink = inodep->nlink;
764 			i->i_size = inodep->symlink_size;
765 			i->i_op = &page_symlink_inode_operations;
766 			i->i_data.a_ops = &squashfs_symlink_aops;
767 			i->i_mode |= S_IFLNK;
768 			SQUASHFS_I(i)->start_block = next_block;
769 			SQUASHFS_I(i)->offset = next_offset;
770 
771 			TRACE("Symbolic link inode %x:%x, start_block %llx, "
772 					"offset %x\n",
773 					SQUASHFS_INODE_BLK(inode), offset,
774 					next_block, next_offset);
775 			break;
776 		 }
777 		 case SQUASHFS_BLKDEV_TYPE:
778 		 case SQUASHFS_CHRDEV_TYPE: {
779 			struct squashfs_dev_inode_header *inodep = &id.dev;
780 			struct squashfs_dev_inode_header *sinodep = &sid.dev;
781 
782 			if (msblk->swap) {
783 				if (!squashfs_get_cached_block(s, (char *)
784 						sinodep, block, offset,
785 						sizeof(*sinodep), &next_block,
786 						&next_offset))
787 					goto failed_read;
788 				SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
789 			} else
790 				if (!squashfs_get_cached_block(s, (char *)
791 						inodep, block, offset,
792 						sizeof(*inodep), &next_block,
793 						&next_offset))
794 					goto failed_read;
795 
796 			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
797 				goto failed_read1;
798 
799 			i->i_nlink = inodep->nlink;
800 			i->i_mode |= (inodeb->inode_type ==
801 					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
802 					S_IFBLK;
803 			init_special_inode(i, i->i_mode, inodep->rdev);
804 
805 			TRACE("Device inode %x:%x, rdev %x\n",
806 					SQUASHFS_INODE_BLK(inode), offset,
807 					inodep->rdev);
808 			break;
809 		 }
810 		 case SQUASHFS_FIFO_TYPE:
811 		 case SQUASHFS_SOCKET_TYPE: {
812 			struct squashfs_ipc_inode_header *inodep = &id.ipc;
813 			struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
814 
815 			if (msblk->swap) {
816 				if (!squashfs_get_cached_block(s, (char *)
817 						sinodep, block, offset,
818 						sizeof(*sinodep), &next_block,
819 						&next_offset))
820 					goto failed_read;
821 				SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
822 			} else
823 				if (!squashfs_get_cached_block(s, (char *)
824 						inodep, block, offset,
825 						sizeof(*inodep), &next_block,
826 						&next_offset))
827 					goto failed_read;
828 
829 			if ((i = squashfs_new_inode(s, inodeb)) == NULL)
830 				goto failed_read1;
831 
832 			i->i_nlink = inodep->nlink;
833 			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
834 							? S_IFIFO : S_IFSOCK;
835 			init_special_inode(i, i->i_mode, 0);
836 			break;
837 		 }
838 		 default:
839 			ERROR("Unknown inode type %d in squashfs_iget!\n",
840 					inodeb->inode_type);
841 			goto failed_read1;
842 	}
843 
844 	insert_inode_hash(i);
845 	return i;
846 
847 failed_read:
848 	ERROR("Unable to read inode [%llx:%x]\n", block, offset);
849 
850 failed_read1:
851 	return NULL;
852 }
853 
854 
read_fragment_index_table(struct super_block * s)855 int read_fragment_index_table(struct super_block *s)
856 {
857 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
858 	struct squashfs_super_block *sblk = &msblk->sblk;
859 
860 	if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
861 					(sblk->fragments), GFP_KERNEL))) {
862 		ERROR("Failed to allocate uid/gid table\n");
863 		return 0;
864 	}
865 
866 	if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
867 					!squashfs_read_data(s, (char *)
868 					msblk->fragment_index,
869 					sblk->fragment_table_start,
870 					SQUASHFS_FRAGMENT_INDEX_BYTES
871 					(sblk->fragments) |
872 					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
873 		ERROR("unable to read fragment index table\n");
874 		return 0;
875 	}
876 
877 	if (msblk->swap) {
878 		int i;
879 		long long fragment;
880 
881 		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments);
882 									i++) {
883 			SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
884 						&msblk->fragment_index[i], 1);
885 			msblk->fragment_index[i] = fragment;
886 		}
887 	}
888 
889 	return 1;
890 }
891 
892 
supported_squashfs_filesystem(struct squashfs_sb_info * msblk,int silent)893 static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
894 {
895 	struct squashfs_super_block *sblk = &msblk->sblk;
896 
897 	msblk->iget = squashfs_iget;
898 	msblk->read_blocklist = read_blocklist;
899 	msblk->read_fragment_index_table = read_fragment_index_table;
900 
901 	if (sblk->s_major == 1) {
902 		if (!squashfs_1_0_supported(msblk)) {
903 			SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
904 				"are unsupported\n");
905 			SERROR("Please recompile with "
906 				"Squashfs 1.0 support enabled\n");
907 			return 0;
908 		}
909 	} else if (sblk->s_major == 2) {
910 		if (!squashfs_2_0_supported(msblk)) {
911 			SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
912 				"are unsupported\n");
913 			SERROR("Please recompile with "
914 				"Squashfs 2.0 support enabled\n");
915 			return 0;
916 		}
917 	} else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
918 			SQUASHFS_MINOR) {
919 		SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
920 				"filesystem\n", sblk->s_major, sblk->s_minor);
921 		SERROR("Please update your kernel\n");
922 		return 0;
923 	}
924 
925 	return 1;
926 }
927 
928 
squashfs_read_super(struct super_block * s,void * data,int silent)929 static struct super_block *squashfs_read_super(struct super_block *s,
930 		void *data, int silent)
931 {
932 	kdev_t dev = s->s_dev;
933 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
934 	struct squashfs_super_block *sblk = &msblk->sblk;
935 	int i;
936 	struct inode *root;
937 
938 	if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
939 		ERROR("Failed to allocate zlib workspace\n");
940 		goto failed_mount;
941 	}
942 
943 	msblk->devblksize = get_hardsect_size(dev);
944 	if(msblk->devblksize < BLOCK_SIZE)
945 		msblk->devblksize = BLOCK_SIZE;
946 	msblk->devblksize_log2 = ffz(~msblk->devblksize);
947         set_blocksize(dev, msblk->devblksize);
948 	s->s_blocksize = msblk->devblksize;
949 	s->s_blocksize_bits = msblk->devblksize_log2;
950 
951 	init_MUTEX(&msblk->read_data_mutex);
952 	init_MUTEX(&msblk->read_page_mutex);
953 	init_MUTEX(&msblk->block_cache_mutex);
954 	init_MUTEX(&msblk->fragment_mutex);
955 
956 	init_waitqueue_head(&msblk->waitq);
957 	init_waitqueue_head(&msblk->fragment_wait_queue);
958 
959 	if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
960 					sizeof(struct squashfs_super_block) |
961 					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
962 		SERROR("unable to read superblock\n");
963 		goto failed_mount;
964 	}
965 
966 	/* Check it is a SQUASHFS superblock */
967 	msblk->swap = 0;
968 	if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
969 		if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
970 			struct squashfs_super_block ssblk;
971 
972 			WARNING("Mounting a different endian SQUASHFS "
973 				"filesystem on %s\n", bdevname(dev));
974 
975 			SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
976 			memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
977 			msblk->swap = 1;
978 		} else  {
979 			SERROR("Can't find a SQUASHFS superblock on %s\n",
980 							bdevname(dev));
981 			goto failed_mount;
982 		}
983 	}
984 
985 	/* Check the MAJOR & MINOR versions */
986 	if(!supported_squashfs_filesystem(msblk, silent))
987 		goto failed_mount;
988 
989 	TRACE("Found valid superblock on %s\n", bdevname(dev));
990 	TRACE("Inodes are %scompressed\n",
991 					SQUASHFS_UNCOMPRESSED_INODES
992 					(sblk->flags) ? "un" : "");
993 	TRACE("Data is %scompressed\n",
994 					SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
995 					? "un" : "");
996 	TRACE("Check data is %s present in the filesystem\n",
997 					SQUASHFS_CHECK_DATA(sblk->flags) ?
998 					"" : "not");
999 	TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
1000 	TRACE("Block size %d\n", sblk->block_size);
1001 	TRACE("Number of inodes %d\n", sblk->inodes);
1002 	if (sblk->s_major > 1)
1003 		TRACE("Number of fragments %d\n", sblk->fragments);
1004 	TRACE("Number of uids %d\n", sblk->no_uids);
1005 	TRACE("Number of gids %d\n", sblk->no_guids);
1006 	TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
1007 	TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
1008 	if (sblk->s_major > 1)
1009 		TRACE("sblk->fragment_table_start %llx\n",
1010 					sblk->fragment_table_start);
1011 	TRACE("sblk->uid_start %llx\n", sblk->uid_start);
1012 
1013 	s->s_flags |= MS_RDONLY;
1014 	s->s_op = &squashfs_ops;
1015 
1016 	/* Init inode_table block pointer array */
1017 	if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
1018 					SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
1019 		ERROR("Failed to allocate block cache\n");
1020 		goto failed_mount;
1021 	}
1022 
1023 	for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1024 		msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
1025 
1026 	msblk->next_cache = 0;
1027 
1028 	/* Allocate read_data block */
1029 	msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ?
1030 					SQUASHFS_METADATA_SIZE :
1031 					sblk->block_size;
1032 
1033 	if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) {
1034 		ERROR("Failed to allocate read_data block\n");
1035 		goto failed_mount;
1036 	}
1037 
1038 	/* Allocate read_page block */
1039 	if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
1040 		ERROR("Failed to allocate read_page block\n");
1041 		goto failed_mount;
1042 	}
1043 
1044 	/* Allocate uid and gid tables */
1045 	if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
1046 					sizeof(unsigned int), GFP_KERNEL))) {
1047 		ERROR("Failed to allocate uid/gid table\n");
1048 		goto failed_mount;
1049 	}
1050 	msblk->guid = msblk->uid + sblk->no_uids;
1051 
1052 	if (msblk->swap) {
1053 		unsigned int suid[sblk->no_uids + sblk->no_guids];
1054 
1055 		if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
1056 					((sblk->no_uids + sblk->no_guids) *
1057 					 sizeof(unsigned int)) |
1058 					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1059 			ERROR("unable to read uid/gid table\n");
1060 			goto failed_mount;
1061 		}
1062 
1063 		SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
1064 			sblk->no_guids), (sizeof(unsigned int) * 8));
1065 	} else
1066 		if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
1067 					((sblk->no_uids + sblk->no_guids) *
1068 					 sizeof(unsigned int)) |
1069 					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
1070 			ERROR("unable to read uid/gid table\n");
1071 			goto failed_mount;
1072 		}
1073 
1074 
1075 	if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
1076 		goto allocate_root;
1077 
1078 	if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
1079 				SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
1080 		ERROR("Failed to allocate fragment block cache\n");
1081 		goto failed_mount;
1082 	}
1083 
1084 	for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
1085 		msblk->fragment[i].locked = 0;
1086 		msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
1087 		msblk->fragment[i].data = NULL;
1088 	}
1089 
1090 	msblk->next_fragment = 0;
1091 
1092 	/* Allocate fragment index table */
1093 	if(msblk->read_fragment_index_table(s) == 0)
1094 		goto failed_mount;
1095 
1096 allocate_root:
1097 	if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL)
1098 		goto failed_mount;
1099 
1100 	if ((s->s_root = d_alloc_root(root)) == NULL) {
1101 		ERROR("Root inode create failed\n");
1102 		iput(root);
1103 		goto failed_mount;
1104 	}
1105 
1106 	TRACE("Leaving squashfs_read_super\n");
1107 	return s;
1108 
1109 failed_mount:
1110 	kfree(msblk->fragment_index);
1111 	kfree(msblk->fragment);
1112 	kfree(msblk->uid);
1113 	kfree(msblk->read_page);
1114 	kfree(msblk->read_data);
1115 	kfree(msblk->block_cache);
1116 	kfree(msblk->fragment_index_2);
1117 	vfree(msblk->stream.workspace);
1118 	return NULL;
1119 }
1120 
1121 
squashfs_statfs(struct super_block * s,struct statfs * buf)1122 static int squashfs_statfs(struct super_block *s, struct statfs *buf)
1123 {
1124 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1125 	struct squashfs_super_block *sblk = &msblk->sblk;
1126 
1127 	TRACE("Entered squashfs_statfs\n");
1128 
1129 	buf->f_type = SQUASHFS_MAGIC;
1130 	buf->f_bsize = sblk->block_size;
1131 	buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
1132 	buf->f_bfree = buf->f_bavail = 0;
1133 	buf->f_files = sblk->inodes;
1134 	buf->f_ffree = 0;
1135 	buf->f_namelen = SQUASHFS_NAME_LEN;
1136 
1137 	return 0;
1138 }
1139 
1140 
squashfs_symlink_readpage(struct file * file,struct page * page)1141 static int squashfs_symlink_readpage(struct file *file, struct page *page)
1142 {
1143 	struct inode *inode = page->mapping->host;
1144 	int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
1145 	long long block = SQUASHFS_I(inode)->start_block;
1146 	int offset = SQUASHFS_I(inode)->offset;
1147 	void *pageaddr = kmap(page);
1148 
1149 	TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
1150 				"%llx, offset %x\n", page->index,
1151 				SQUASHFS_I(inode)->start_block,
1152 				SQUASHFS_I(inode)->offset);
1153 
1154 	for (length = 0; length < index; length += bytes) {
1155 		if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
1156 				block, offset, PAGE_CACHE_SIZE, &block,
1157 				&offset))) {
1158 			ERROR("Unable to read symbolic link [%llx:%x]\n", block,
1159 					offset);
1160 			goto skip_read;
1161 		}
1162 	}
1163 
1164 	if (length != index) {
1165 		ERROR("(squashfs_symlink_readpage) length != index\n");
1166 		bytes = 0;
1167 		goto skip_read;
1168 	}
1169 
1170 	bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
1171 					i_size_read(inode) - length;
1172 
1173 	if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
1174 					offset, bytes, &block, &offset)))
1175 		ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
1176 
1177 skip_read:
1178 	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1179 	kunmap(page);
1180 	SetPageUptodate(page);
1181 	UnlockPage(page);
1182 
1183 	return 0;
1184 }
1185 
1186 
locate_meta_index(struct inode * inode,int index,int offset)1187 struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
1188 {
1189 	struct meta_index *meta = NULL;
1190 	struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1191 	int i;
1192 
1193 	down(&msblk->meta_index_mutex);
1194 
1195 	TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
1196 
1197 	if(msblk->meta_index == NULL)
1198 		goto not_allocated;
1199 
1200 	for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
1201 		if (msblk->meta_index[i].inode_number == inode->i_ino &&
1202 				msblk->meta_index[i].offset >= offset &&
1203 				msblk->meta_index[i].offset <= index &&
1204 				msblk->meta_index[i].locked == 0) {
1205 			TRACE("locate_meta_index: entry %d, offset %d\n", i,
1206 					msblk->meta_index[i].offset);
1207 			meta = &msblk->meta_index[i];
1208 			offset = meta->offset;
1209 		}
1210 
1211 	if (meta)
1212 		meta->locked = 1;
1213 
1214 not_allocated:
1215 	up(&msblk->meta_index_mutex);
1216 
1217 	return meta;
1218 }
1219 
1220 
empty_meta_index(struct inode * inode,int offset,int skip)1221 struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
1222 {
1223 	struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1224 	struct meta_index *meta = NULL;
1225 	int i;
1226 
1227 	down(&msblk->meta_index_mutex);
1228 
1229 	TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
1230 
1231 	if(msblk->meta_index == NULL) {
1232 		if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
1233 					SQUASHFS_META_NUMBER, GFP_KERNEL))) {
1234 			ERROR("Failed to allocate meta_index\n");
1235 			goto failed;
1236 		}
1237 		for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
1238 			msblk->meta_index[i].inode_number = 0;
1239 			msblk->meta_index[i].locked = 0;
1240 		}
1241 		msblk->next_meta_index = 0;
1242 	}
1243 
1244 	for(i = SQUASHFS_META_NUMBER; i &&
1245 			msblk->meta_index[msblk->next_meta_index].locked; i --)
1246 		msblk->next_meta_index = (msblk->next_meta_index + 1) %
1247 			SQUASHFS_META_NUMBER;
1248 
1249 	if(i == 0) {
1250 		TRACE("empty_meta_index: failed!\n");
1251 		goto failed;
1252 	}
1253 
1254 	TRACE("empty_meta_index: returned meta entry %d, %p\n",
1255 			msblk->next_meta_index,
1256 			&msblk->meta_index[msblk->next_meta_index]);
1257 
1258 	meta = &msblk->meta_index[msblk->next_meta_index];
1259 	msblk->next_meta_index = (msblk->next_meta_index + 1) %
1260 			SQUASHFS_META_NUMBER;
1261 
1262 	meta->inode_number = inode->i_ino;
1263 	meta->offset = offset;
1264 	meta->skip = skip;
1265 	meta->entries = 0;
1266 	meta->locked = 1;
1267 
1268 failed:
1269 	up(&msblk->meta_index_mutex);
1270 	return meta;
1271 }
1272 
1273 
release_meta_index(struct inode * inode,struct meta_index * meta)1274 void release_meta_index(struct inode *inode, struct meta_index *meta)
1275 {
1276 	meta->locked = 0;
1277 }
1278 
1279 
read_block_index(struct super_block * s,int blocks,char * block_list,long long * start_block,int * offset)1280 static int read_block_index(struct super_block *s, int blocks, char *block_list,
1281 		long long *start_block, int *offset)
1282 {
1283 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1284 	unsigned int *block_listp;
1285 	int block = 0;
1286 
1287 	if (msblk->swap) {
1288 		char sblock_list[blocks << 2];
1289 
1290 		if (!squashfs_get_cached_block(s, sblock_list, *start_block,
1291 				*offset, blocks << 2, start_block, offset)) {
1292 			ERROR("Unable to read block list [%llx:%x]\n",
1293 				*start_block, *offset);
1294 			goto failure;
1295 		}
1296 		SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
1297 				((unsigned int *)sblock_list), blocks);
1298 	} else
1299 		if (!squashfs_get_cached_block(s, block_list, *start_block,
1300 				*offset, blocks << 2, start_block, offset)) {
1301 			ERROR("Unable to read block list [%llx:%x]\n",
1302 				*start_block, *offset);
1303 			goto failure;
1304 		}
1305 
1306 	for (block_listp = (unsigned int *) block_list; blocks;
1307 				block_listp++, blocks --)
1308 		block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
1309 
1310 	return block;
1311 
1312 failure:
1313 	return -1;
1314 }
1315 
1316 
1317 #define SIZE 256
1318 
calculate_skip(int blocks)1319 static inline int calculate_skip(int blocks) {
1320 	int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
1321 	return skip >= 7 ? 7 : skip + 1;
1322 }
1323 
1324 
get_meta_index(struct inode * inode,int index,long long * index_block,int * index_offset,long long * data_block,char * block_list)1325 static int get_meta_index(struct inode *inode, int index,
1326 		long long *index_block, int *index_offset,
1327 		long long *data_block, char *block_list)
1328 {
1329 	struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1330 	struct squashfs_super_block *sblk = &msblk->sblk;
1331 	int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
1332 	int offset = 0;
1333 	struct meta_index *meta;
1334 	struct meta_entry *meta_entry;
1335 	long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
1336 	int cur_offset = SQUASHFS_I(inode)->offset;
1337 	long long cur_data_block = SQUASHFS_I(inode)->start_block;
1338 	int i;
1339 
1340 	index /= SQUASHFS_META_INDEXES * skip;
1341 
1342 	while ( offset < index ) {
1343 		meta = locate_meta_index(inode, index, offset + 1);
1344 
1345 		if (meta == NULL) {
1346 			if ((meta = empty_meta_index(inode, offset + 1,
1347 							skip)) == NULL)
1348 				goto all_done;
1349 		} else {
1350 			offset = index < meta->offset + meta->entries ? index :
1351 				meta->offset + meta->entries - 1;
1352 			meta_entry = &meta->meta_entry[offset - meta->offset];
1353 			cur_index_block = meta_entry->index_block + sblk->inode_table_start;
1354 			cur_offset = meta_entry->offset;
1355 			cur_data_block = meta_entry->data_block;
1356 			TRACE("get_meta_index: offset %d, meta->offset %d, "
1357 				"meta->entries %d\n", offset, meta->offset,
1358 				meta->entries);
1359 			TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
1360 				" data_block 0x%llx\n", cur_index_block,
1361 				cur_offset, cur_data_block);
1362 		}
1363 
1364 		for (i = meta->offset + meta->entries; i <= index &&
1365 				i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
1366 			int blocks = skip * SQUASHFS_META_INDEXES;
1367 
1368 			while (blocks) {
1369 				int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
1370 					blocks;
1371 				int res = read_block_index(inode->i_sb, block,
1372 					block_list, &cur_index_block,
1373 					&cur_offset);
1374 
1375 				if (res == -1)
1376 					goto failed;
1377 
1378 				cur_data_block += res;
1379 				blocks -= block;
1380 			}
1381 
1382 			meta_entry = &meta->meta_entry[i - meta->offset];
1383 			meta_entry->index_block = cur_index_block - sblk->inode_table_start;
1384 			meta_entry->offset = cur_offset;
1385 			meta_entry->data_block = cur_data_block;
1386 			meta->entries ++;
1387 			offset ++;
1388 		}
1389 
1390 		TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
1391 				meta->offset, meta->entries);
1392 
1393 		release_meta_index(inode, meta);
1394 	}
1395 
1396 all_done:
1397 	*index_block = cur_index_block;
1398 	*index_offset = cur_offset;
1399 	*data_block = cur_data_block;
1400 
1401 	return offset * SQUASHFS_META_INDEXES * skip;
1402 
1403 failed:
1404 	release_meta_index(inode, meta);
1405 	return -1;
1406 }
1407 
1408 
read_blocklist(struct inode * inode,int index,int readahead_blks,char * block_list,unsigned short ** block_p,unsigned int * bsize)1409 static long long read_blocklist(struct inode *inode, int index,
1410 				int readahead_blks, char *block_list,
1411 				unsigned short **block_p, unsigned int *bsize)
1412 {
1413 	long long block_ptr;
1414 	int offset;
1415 	long long block;
1416 	int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
1417 		block_list);
1418 
1419 	TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
1420 		       " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
1421 		       block);
1422 
1423 	if(res == -1)
1424 		goto failure;
1425 
1426 	index -= res;
1427 
1428 	while ( index ) {
1429 		int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
1430 		int res = read_block_index(inode->i_sb, blocks, block_list,
1431 			&block_ptr, &offset);
1432 		if (res == -1)
1433 			goto failure;
1434 		block += res;
1435 		index -= blocks;
1436 	}
1437 
1438 	if (read_block_index(inode->i_sb, 1, block_list,
1439 			&block_ptr, &offset) == -1)
1440 		goto failure;
1441 	*bsize = *((unsigned int *) block_list);
1442 
1443 	return block;
1444 
1445 failure:
1446 	return 0;
1447 }
1448 
1449 
squashfs_readpage(struct file * file,struct page * page)1450 static int squashfs_readpage(struct file *file, struct page *page)
1451 {
1452 	struct inode *inode = page->mapping->host;
1453 	struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1454 	struct squashfs_super_block *sblk = &msblk->sblk;
1455 	unsigned char block_list[SIZE];
1456 	long long block;
1457 	unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
1458 	int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
1459  	void *pageaddr;
1460 	struct squashfs_fragment_cache *fragment = NULL;
1461 	char *data_ptr = msblk->read_page;
1462 
1463 	int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
1464 	int start_index = page->index & ~mask;
1465 	int end_index = start_index | mask;
1466 
1467 	TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
1468 					page->index,
1469 					SQUASHFS_I(inode)->start_block);
1470 
1471 	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1472 					PAGE_CACHE_SHIFT))
1473 		goto skip_read;
1474 
1475 	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1476 					|| index < (i_size_read(inode) >>
1477 					sblk->block_log)) {
1478 		if ((block = (msblk->read_blocklist)(inode, index, 1,
1479 					block_list, NULL, &bsize)) == 0)
1480 			goto skip_read;
1481 
1482 		down(&msblk->read_page_mutex);
1483 
1484 		if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
1485 					block, bsize, NULL))) {
1486 			ERROR("Unable to read page, block %llx, size %x\n", block,
1487 					bsize);
1488 			up(&msblk->read_page_mutex);
1489 			goto skip_read;
1490 		}
1491 	} else {
1492 		if ((fragment = get_cached_fragment(inode->i_sb,
1493 					SQUASHFS_I(inode)->
1494 					u.s1.fragment_start_block,
1495 					SQUASHFS_I(inode)->u.s1.fragment_size))
1496 					== NULL) {
1497 			ERROR("Unable to read page, block %llx, size %x\n",
1498 					SQUASHFS_I(inode)->
1499 					u.s1.fragment_start_block,
1500 					(int) SQUASHFS_I(inode)->
1501 					u.s1.fragment_size);
1502 			goto skip_read;
1503 		}
1504 		bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
1505 					(i_size_read(inode) & (sblk->block_size
1506 					- 1));
1507 		byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
1508 		data_ptr = fragment->data;
1509 	}
1510 
1511 	for (i = start_index; i <= end_index && byte_offset < bytes;
1512 					i++, byte_offset += PAGE_CACHE_SIZE) {
1513 		struct page *push_page;
1514 		int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
1515 					PAGE_CACHE_SIZE : bytes - byte_offset;
1516 
1517 		TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
1518 					bytes, i, byte_offset, available_bytes);
1519 
1520 		if (i == page->index)  {
1521 			pageaddr = kmap_atomic(page, KM_USER0);
1522 			memcpy(pageaddr, data_ptr + byte_offset,
1523 					available_bytes);
1524 			memset(pageaddr + available_bytes, 0,
1525 					PAGE_CACHE_SIZE - available_bytes);
1526 			kunmap_atomic(pageaddr, KM_USER0);
1527 			flush_dcache_page(page);
1528 			SetPageUptodate(page);
1529 			UnlockPage(page);
1530 		} else if ((push_page =
1531 				grab_cache_page_nowait(page->mapping, i))) {
1532  			pageaddr = kmap_atomic(push_page, KM_USER0);
1533 
1534 			memcpy(pageaddr, data_ptr + byte_offset,
1535 					available_bytes);
1536 			memset(pageaddr + available_bytes, 0,
1537 					PAGE_CACHE_SIZE - available_bytes);
1538 			kunmap_atomic(pageaddr, KM_USER0);
1539 			flush_dcache_page(push_page);
1540 			SetPageUptodate(push_page);
1541 			UnlockPage(push_page);
1542 			page_cache_release(push_page);
1543 		}
1544 	}
1545 
1546 	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1547 					|| index < (i_size_read(inode) >>
1548 					sblk->block_log))
1549 		up(&msblk->read_page_mutex);
1550 	else
1551 		release_cached_fragment(msblk, fragment);
1552 
1553 	return 0;
1554 
1555 skip_read:
1556 	pageaddr = kmap_atomic(page, KM_USER0);
1557 	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1558 	kunmap_atomic(pageaddr, KM_USER0);
1559 	flush_dcache_page(page);
1560 	SetPageUptodate(page);
1561 	UnlockPage(page);
1562 
1563 	return 0;
1564 }
1565 
1566 
squashfs_readpage4K(struct file * file,struct page * page)1567 static int squashfs_readpage4K(struct file *file, struct page *page)
1568 {
1569 	struct inode *inode = page->mapping->host;
1570 	struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb;
1571 	struct squashfs_super_block *sblk = &msblk->sblk;
1572 	unsigned char block_list[SIZE];
1573 	long long block;
1574 	unsigned int bsize, bytes = 0;
1575  	void *pageaddr;
1576 
1577 	TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
1578 					page->index,
1579 					SQUASHFS_I(inode)->start_block);
1580 
1581 	if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1582 					PAGE_CACHE_SHIFT)) {
1583 		pageaddr = kmap_atomic(page, KM_USER0);
1584 		goto skip_read;
1585 	}
1586 
1587 	if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1588 					|| page->index < (i_size_read(inode) >>
1589 					sblk->block_log)) {
1590 		block = (msblk->read_blocklist)(inode, page->index, 1,
1591 					block_list, NULL, &bsize);
1592 
1593 		down(&msblk->read_page_mutex);
1594 		bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
1595 					bsize, NULL);
1596 		pageaddr = kmap_atomic(page, KM_USER0);
1597 		if (bytes)
1598 			memcpy(pageaddr, msblk->read_page, bytes);
1599 		else
1600 			ERROR("Unable to read page, block %llx, size %x\n",
1601 					block, bsize);
1602 		up(&msblk->read_page_mutex);
1603 	} else {
1604 		struct squashfs_fragment_cache *fragment =
1605 			get_cached_fragment(inode->i_sb,
1606 					SQUASHFS_I(inode)->
1607 					u.s1.fragment_start_block,
1608 					SQUASHFS_I(inode)-> u.s1.fragment_size);
1609 		pageaddr = kmap_atomic(page, KM_USER0);
1610 		if (fragment) {
1611 			bytes = i_size_read(inode) & (sblk->block_size - 1);
1612 			memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
1613 					u.s1.fragment_offset, bytes);
1614 			release_cached_fragment(msblk, fragment);
1615 		} else
1616 			ERROR("Unable to read page, block %llx, size %x\n",
1617 					SQUASHFS_I(inode)->
1618 					u.s1.fragment_start_block, (int)
1619 					SQUASHFS_I(inode)-> u.s1.fragment_size);
1620 	}
1621 
1622 skip_read:
1623 	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1624 	kunmap_atomic(pageaddr, KM_USER0);
1625 	flush_dcache_page(page);
1626 	SetPageUptodate(page);
1627 	UnlockPage(page);
1628 
1629 	return 0;
1630 }
1631 
1632 
get_dir_index_using_offset(struct super_block * s,long long * next_block,unsigned int * next_offset,long long index_start,unsigned int index_offset,int i_count,long long f_pos)1633 static int get_dir_index_using_offset(struct super_block *s, long long
1634 				*next_block, unsigned int *next_offset,
1635 				long long index_start,
1636 				unsigned int index_offset, int i_count,
1637 				long long f_pos)
1638 {
1639 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1640 	struct squashfs_super_block *sblk = &msblk->sblk;
1641 	int i, length = 0;
1642 	struct squashfs_dir_index index;
1643 
1644 	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
1645 					i_count, (unsigned int) f_pos);
1646 
1647 	f_pos -= 3;
1648 	if (f_pos == 0)
1649 		goto finish;
1650 
1651 	for (i = 0; i < i_count; i++) {
1652 		if (msblk->swap) {
1653 			struct squashfs_dir_index sindex;
1654 			squashfs_get_cached_block(s, (char *) &sindex,
1655 					index_start, index_offset,
1656 					sizeof(sindex), &index_start,
1657 					&index_offset);
1658 			SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
1659 		} else
1660 			squashfs_get_cached_block(s, (char *) &index,
1661 					index_start, index_offset,
1662 					sizeof(index), &index_start,
1663 					&index_offset);
1664 
1665 		if (index.index > f_pos)
1666 			break;
1667 
1668 		squashfs_get_cached_block(s, NULL, index_start, index_offset,
1669 					index.size + 1, &index_start,
1670 					&index_offset);
1671 
1672 		length = index.index;
1673 		*next_block = index.start_block + sblk->directory_table_start;
1674 	}
1675 
1676 	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1677 
1678 finish:
1679 	return length + 3;
1680 }
1681 
1682 
get_dir_index_using_name(struct super_block * s,long long * next_block,unsigned int * next_offset,long long index_start,unsigned int index_offset,int i_count,const char * name,int size)1683 static int get_dir_index_using_name(struct super_block *s, long long
1684 				*next_block, unsigned int *next_offset,
1685 				long long index_start,
1686 				unsigned int index_offset, int i_count,
1687 				const char *name, int size)
1688 {
1689 	struct squashfs_sb_info *msblk = &s->u.squashfs_sb;
1690 	struct squashfs_super_block *sblk = &msblk->sblk;
1691 	int i, length = 0;
1692 	char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];
1693 	struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer;
1694 	char str[SQUASHFS_NAME_LEN + 1];
1695 
1696 	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
1697 
1698 	strncpy(str, name, size);
1699 	str[size] = '\0';
1700 
1701 	for (i = 0; i < i_count; i++) {
1702 		if (msblk->swap) {
1703 			struct squashfs_dir_index sindex;
1704 			squashfs_get_cached_block(s, (char *) &sindex,
1705 					index_start, index_offset,
1706 					sizeof(sindex), &index_start,
1707 					&index_offset);
1708 			SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
1709 		} else
1710 			squashfs_get_cached_block(s, (char *) index,
1711 					index_start, index_offset,
1712 					sizeof(struct squashfs_dir_index),
1713 					&index_start, &index_offset);
1714 
1715 		squashfs_get_cached_block(s, index->name, index_start,
1716 					index_offset, index->size + 1,
1717 					&index_start, &index_offset);
1718 
1719 		index->name[index->size + 1] = '\0';
1720 
1721 		if (strcmp(index->name, str) > 0)
1722 			break;
1723 
1724 		length = index->index;
1725 		*next_block = index->start_block + sblk->directory_table_start;
1726 	}
1727 
1728 	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1729 	return length + 3;
1730 }
1731 
1732 
squashfs_readdir(struct file * file,void * dirent,filldir_t filldir)1733 static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
1734 {
1735 	struct inode *i = file->f_dentry->d_inode;
1736 	struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
1737 	struct squashfs_super_block *sblk = &msblk->sblk;
1738 	long long next_block = SQUASHFS_I(i)->start_block +
1739 		sblk->directory_table_start;
1740 	int next_offset = SQUASHFS_I(i)->offset, length = 0,
1741 		dir_count;
1742 	struct squashfs_dir_header dirh;
1743 	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
1744 	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
1745 
1746 	TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
1747 
1748 	while(file->f_pos < 3) {
1749 		char *name;
1750 		int size, i_ino;
1751 
1752 		if(file->f_pos == 0) {
1753 			name = ".";
1754 			size = 1;
1755 			i_ino = i->i_ino;
1756 		} else {
1757 			name = "..";
1758 			size = 2;
1759 			i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
1760 		}
1761 		TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
1762 				(unsigned int) dirent, name, size, (int)
1763 				file->f_pos, i_ino,
1764 				squashfs_filetype_table[1]);
1765 
1766 		if (filldir(dirent, name, size,
1767 				file->f_pos, i_ino,
1768 				squashfs_filetype_table[1]) < 0) {
1769 				TRACE("Filldir returned less than 0\n");
1770 				goto finish;
1771 		}
1772 		file->f_pos += size;
1773 	}
1774 
1775 	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
1776 				SQUASHFS_I(i)->u.s2.directory_index_start,
1777 				SQUASHFS_I(i)->u.s2.directory_index_offset,
1778 				SQUASHFS_I(i)->u.s2.directory_index_count,
1779 				file->f_pos);
1780 
1781 	while (length < i_size_read(i)) {
1782 		/* read directory header */
1783 		if (msblk->swap) {
1784 			struct squashfs_dir_header sdirh;
1785 
1786 			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
1787 					next_block, next_offset, sizeof(sdirh),
1788 					&next_block, &next_offset))
1789 				goto failed_read;
1790 
1791 			length += sizeof(sdirh);
1792 			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
1793 		} else {
1794 			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
1795 					next_block, next_offset, sizeof(dirh),
1796 					&next_block, &next_offset))
1797 				goto failed_read;
1798 
1799 			length += sizeof(dirh);
1800 		}
1801 
1802 		dir_count = dirh.count + 1;
1803 		while (dir_count--) {
1804 			if (msblk->swap) {
1805 				struct squashfs_dir_entry sdire;
1806 				if (!squashfs_get_cached_block(i->i_sb, (char *)
1807 						&sdire, next_block, next_offset,
1808 						sizeof(sdire), &next_block,
1809 						&next_offset))
1810 					goto failed_read;
1811 
1812 				length += sizeof(sdire);
1813 				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
1814 			} else {
1815 				if (!squashfs_get_cached_block(i->i_sb, (char *)
1816 						dire, next_block, next_offset,
1817 						sizeof(*dire), &next_block,
1818 						&next_offset))
1819 					goto failed_read;
1820 
1821 				length += sizeof(*dire);
1822 			}
1823 
1824 			if (!squashfs_get_cached_block(i->i_sb, dire->name,
1825 						next_block, next_offset,
1826 						dire->size + 1, &next_block,
1827 						&next_offset))
1828 				goto failed_read;
1829 
1830 			length += dire->size + 1;
1831 
1832 			if (file->f_pos >= length)
1833 				continue;
1834 
1835 			dire->name[dire->size + 1] = '\0';
1836 
1837 			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
1838 					(unsigned int) dirent, dire->name,
1839 					dire->size + 1, (int) file->f_pos,
1840 					dirh.start_block, dire->offset,
1841 					dirh.inode_number + dire->inode_number,
1842 					squashfs_filetype_table[dire->type]);
1843 
1844 			if (filldir(dirent, dire->name, dire->size + 1,
1845 					file->f_pos,
1846 					dirh.inode_number + dire->inode_number,
1847 					squashfs_filetype_table[dire->type])
1848 					< 0) {
1849 				TRACE("Filldir returned less than 0\n");
1850 				goto finish;
1851 			}
1852 			file->f_pos = length;
1853 		}
1854 	}
1855 
1856 finish:
1857 	return 0;
1858 
1859 failed_read:
1860 	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1861 		next_offset);
1862 	return 0;
1863 }
1864 
1865 
squashfs_lookup(struct inode * i,struct dentry * dentry)1866 static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry)
1867 {
1868 	const unsigned char *name = dentry->d_name.name;
1869 	int len = dentry->d_name.len;
1870 	struct inode *inode = NULL;
1871 	struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb;
1872 	struct squashfs_super_block *sblk = &msblk->sblk;
1873 	long long next_block = SQUASHFS_I(i)->start_block +
1874 				sblk->directory_table_start;
1875 	int next_offset = SQUASHFS_I(i)->offset, length = 0,
1876 				dir_count;
1877 	struct squashfs_dir_header dirh;
1878 	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN];
1879 	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
1880 
1881 	TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
1882 
1883 	if (len > SQUASHFS_NAME_LEN)
1884 		goto exit_loop;
1885 
1886 	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
1887 				SQUASHFS_I(i)->u.s2.directory_index_start,
1888 				SQUASHFS_I(i)->u.s2.directory_index_offset,
1889 				SQUASHFS_I(i)->u.s2.directory_index_count, name,
1890 				len);
1891 
1892 	while (length < i_size_read(i)) {
1893 		/* read directory header */
1894 		if (msblk->swap) {
1895 			struct squashfs_dir_header sdirh;
1896 			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
1897 					next_block, next_offset, sizeof(sdirh),
1898 					&next_block, &next_offset))
1899 				goto failed_read;
1900 
1901 			length += sizeof(sdirh);
1902 			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
1903 		} else {
1904 			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
1905 					next_block, next_offset, sizeof(dirh),
1906 					&next_block, &next_offset))
1907 				goto failed_read;
1908 
1909 			length += sizeof(dirh);
1910 		}
1911 
1912 		dir_count = dirh.count + 1;
1913 		while (dir_count--) {
1914 			if (msblk->swap) {
1915 				struct squashfs_dir_entry sdire;
1916 				if (!squashfs_get_cached_block(i->i_sb, (char *)
1917 						&sdire, next_block,next_offset,
1918 						sizeof(sdire), &next_block,
1919 						&next_offset))
1920 					goto failed_read;
1921 
1922 				length += sizeof(sdire);
1923 				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
1924 			} else {
1925 				if (!squashfs_get_cached_block(i->i_sb, (char *)
1926 						dire, next_block,next_offset,
1927 						sizeof(*dire), &next_block,
1928 						&next_offset))
1929 					goto failed_read;
1930 
1931 				length += sizeof(*dire);
1932 			}
1933 
1934 			if (!squashfs_get_cached_block(i->i_sb, dire->name,
1935 					next_block, next_offset, dire->size + 1,
1936 					&next_block, &next_offset))
1937 				goto failed_read;
1938 
1939 			length += dire->size + 1;
1940 
1941 			if (name[0] < dire->name[0])
1942 				goto exit_loop;
1943 
1944 			if ((len == dire->size + 1) && !strncmp(name,
1945 						dire->name, len)) {
1946 				squashfs_inode_t ino =
1947 					SQUASHFS_MKINODE(dirh.start_block,
1948 					dire->offset);
1949 
1950 				TRACE("calling squashfs_iget for directory "
1951 					"entry %s, inode %x:%x, %d\n", name,
1952 					dirh.start_block, dire->offset,
1953 					dirh.inode_number + dire->inode_number);
1954 
1955 				inode = (msblk->iget)(i->i_sb, ino);
1956 
1957 				goto exit_loop;
1958 			}
1959 		}
1960 	}
1961 
1962 exit_loop:
1963 	d_add(dentry, inode);
1964 	return ERR_PTR(0);
1965 
1966 failed_read:
1967 	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1968 		next_offset);
1969 	goto exit_loop;
1970 }
1971 
1972 
squashfs_put_super(struct super_block * s)1973 static void squashfs_put_super(struct super_block *s)
1974 {
1975 	int i;
1976 
1977 		struct squashfs_sb_info *sbi = &s->u.squashfs_sb;
1978 		if (sbi->block_cache)
1979 			for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1980 				if (sbi->block_cache[i].block !=
1981 							SQUASHFS_INVALID_BLK)
1982 					kfree(sbi->block_cache[i].data);
1983 		if (sbi->fragment)
1984 			for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
1985 				SQUASHFS_FREE(sbi->fragment[i].data);
1986 		kfree(sbi->fragment);
1987 		kfree(sbi->block_cache);
1988 		kfree(sbi->read_data);
1989 		kfree(sbi->read_page);
1990 		kfree(sbi->uid);
1991 		kfree(sbi->fragment_index);
1992 		kfree(sbi->fragment_index_2);
1993 		kfree(sbi->meta_index);
1994 		vfree(sbi->stream.workspace);
1995 		sbi->block_cache = NULL;
1996 		sbi->uid = NULL;
1997 		sbi->read_data = NULL;
1998 		sbi->read_page = NULL;
1999 		sbi->fragment = NULL;
2000 		sbi->fragment_index = NULL;
2001 		sbi->fragment_index_2 = NULL;
2002 		sbi->meta_index = NULL;
2003 		sbi->stream.workspace = NULL;
2004 }
2005 
2006 
init_squashfs_fs(void)2007 static int __init init_squashfs_fs(void)
2008 {
2009 
2010 	printk(KERN_INFO "squashfs: version 3.1 (2006/08/15) "
2011 		"Phillip Lougher\n");
2012 
2013 	return register_filesystem(&squashfs_fs_type);
2014 }
2015 
2016 
exit_squashfs_fs(void)2017 static void __exit exit_squashfs_fs(void)
2018 {
2019 	unregister_filesystem(&squashfs_fs_type);
2020 }
2021 
2022 
2023 EXPORT_NO_SYMBOLS;
2024 
2025 module_init(init_squashfs_fs);
2026 module_exit(exit_squashfs_fs);
2027 MODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem");
2028 MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
2029 MODULE_LICENSE("GPL");
2030