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
43static struct super_block *squashfs_read_super(struct super_block *, void *, int);
44static void squashfs_put_super(struct super_block *);
45static int squashfs_statfs(struct super_block *, struct statfs *);
46static int squashfs_symlink_readpage(struct file *file, struct page *page);
47static int squashfs_readpage(struct file *file, struct page *page);
48static int squashfs_readpage4K(struct file *file, struct page *page);
49static int squashfs_readdir(struct file *, void *, filldir_t);
50static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
51static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode);
52static 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
56static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
57
58static unsigned char squashfs_filetype_table[] = {
59	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
60};
61
62static struct super_operations squashfs_ops = {
63	.statfs = squashfs_statfs,
64	.put_super = squashfs_put_super,
65};
66
67SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = {
68	.readpage = squashfs_symlink_readpage
69};
70
71SQSH_EXTERN struct address_space_operations squashfs_aops = {
72	.readpage = squashfs_readpage
73};
74
75SQSH_EXTERN struct address_space_operations squashfs_aops_4K = {
76	.readpage = squashfs_readpage4K
77};
78
79static struct file_operations squashfs_dir_ops = {
80	.read = generic_read_dir,
81	.readdir = squashfs_readdir
82};
83
84static struct inode_operations squashfs_dir_inode_ops = {
85	.lookup = squashfs_lookup
86};
87
88static 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
150out:
151	return NULL;
152}
153
154
155SQSH_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
254block_release:
255	while (--b >= 0)
256		brelse(bh[b]);
257
258read_failure:
259	ERROR("sb_bread failed reading block 0x%x\n", cur_index);
260	return 0;
261}
262
263
264SQSH_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
367finish:
368	return return_length;
369out:
370	return 0;
371}
372
373
374static 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
405out:
406	return 0;
407}
408
409
410SQSH_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
420SQSH_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
495out:
496	return NULL;
497}
498
499
500static 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
524static 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
847failed_read:
848	ERROR("Unable to read inode [%llx:%x]\n", block, offset);
849
850failed_read1:
851	return NULL;
852}
853
854
855int 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
893static 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
929static 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
1096allocate_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
1109failed_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
1122static 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
1141static 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
1177skip_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
1187struct 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
1214not_allocated:
1215	up(&msblk->meta_index_mutex);
1216
1217	return meta;
1218}
1219
1220
1221struct 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
1268failed:
1269	up(&msblk->meta_index_mutex);
1270	return meta;
1271}
1272
1273
1274void release_meta_index(struct inode *inode, struct meta_index *meta)
1275{
1276	meta->locked = 0;
1277}
1278
1279
1280static 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
1312failure:
1313	return -1;
1314}
1315
1316
1317#define SIZE 256
1318
1319static 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
1325static 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
1396all_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
1403failed:
1404	release_meta_index(inode, meta);
1405	return -1;
1406}
1407
1408
1409static 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
1445failure:
1446	return 0;
1447}
1448
1449
1450static 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
1555skip_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
1567static 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
1622skip_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
1633static 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
1678finish:
1679	return length + 3;
1680}
1681
1682
1683static 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
1733static 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
1856finish:
1857	return 0;
1858
1859failed_read:
1860	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1861		next_offset);
1862	return 0;
1863}
1864
1865
1866static 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
1962exit_loop:
1963	d_add(dentry, inode);
1964	return ERR_PTR(0);
1965
1966failed_read:
1967	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
1968		next_offset);
1969	goto exit_loop;
1970}
1971
1972
1973static 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
2007static 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
2017static void __exit exit_squashfs_fs(void)
2018{
2019	unregister_filesystem(&squashfs_fs_type);
2020}
2021
2022
2023EXPORT_NO_SYMBOLS;
2024
2025module_init(init_squashfs_fs);
2026module_exit(exit_squashfs_fs);
2027MODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem");
2028MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
2029MODULE_LICENSE("GPL");
2030