2 * Squashfs - a compressed read only filesystem for Linux
4 * Copyright (c) 2002, 2003, 2004, 2005 Phillip Lougher <phillip@lougher.demon.co.uk>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2,
9 * or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #define SQUASHFS_1_0_COMPATIBILITY
25 #include <linux/types.h>
26 #include <linux/squashfs_fs.h>
27 #include <linux/module.h>
28 #include <linux/errno.h>
29 #include <linux/slab.h>
31 #include <linux/smp_lock.h>
32 #include <linux/slab.h>
33 #include <linux/squashfs_fs_sb.h>
34 #include <linux/squashfs_fs_i.h>
35 #include <linux/buffer_head.h>
36 #include <linux/vfs.h>
37 #include <linux/init.h>
38 #include <linux/dcache.h>
39 #include <asm/uaccess.h>
40 #include <linux/wait.h>
41 #include <asm/semaphore.h>
43 #ifdef CONFIG_SQUASHFS_LZMA
44 #include "LzmaWrapper.h"
46 #include <linux/zlib.h>
49 #include <linux/blkdev.h>
50 #include <linux/vmalloc.h>
53 #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
55 #define TRACE(s, args...) {}
58 #define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
60 #define SERROR(s, args...) if(!silent) printk(KERN_ERR "SQUASHFS error: "s, ## args)
61 #define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
63 static void squashfs_put_super(struct super_block
*);
64 static int squashfs_statfs(struct dentry
*, struct kstatfs
*);
65 static int squashfs_symlink_readpage(struct file
*file
, struct page
*page
);
66 static int squashfs_readpage(struct file
*file
, struct page
*page
);
67 static int squashfs_readpage4K(struct file
*file
, struct page
*page
);
68 static int squashfs_readdir(struct file
*, void *, filldir_t
);
69 static struct dentry
*squashfs_lookup(struct inode
*, struct dentry
*, struct nameidata
*);
70 static unsigned int read_data(struct super_block
*s
, char *buffer
,
71 unsigned int index
, unsigned int length
, unsigned int *next_index
);
72 static int squashfs_get_cached_block(struct super_block
*s
, char *buffer
,
73 unsigned int block
, unsigned int offset
, int length
,
74 unsigned int *next_block
, unsigned int *next_offset
);
75 static struct inode
*squashfs_iget(struct super_block
*s
, squashfs_inode inode
);
76 static unsigned int read_blocklist(struct inode
*inode
, int index
, int readahead_blks
,
77 char *block_list
, unsigned short **block_p
, unsigned int *bsize
);
78 static void squashfs_put_super(struct super_block
*s
);
79 static int squashfs_get_sb(struct file_system_type
*, int, const char *, void *, struct vfsmount
*);
80 static struct inode
*squashfs_alloc_inode(struct super_block
*sb
);
81 static void squashfs_destroy_inode(struct inode
*inode
);
82 static int init_inodecache(void);
83 static void destroy_inodecache(void);
85 #ifdef SQUASHFS_1_0_COMPATIBILITY
86 static int squashfs_readpage_lessthan4K(struct file
*file
, struct page
*page
);
87 static struct inode
*squashfs_iget_1(struct super_block
*s
, squashfs_inode inode
);
88 static unsigned int read_blocklist_1(struct inode
*inode
, int index
, int readahead_blks
,
89 char *block_list
, unsigned short **block_p
, unsigned int *bsize
);
92 DECLARE_MUTEX(read_data_mutex
);
94 #ifdef CONFIG_SQUASHFS_LZMA
95 static char *lzma_data
;
97 static z_stream stream
;
100 static struct file_system_type squashfs_fs_type
= {
101 .owner
= THIS_MODULE
,
103 .get_sb
= squashfs_get_sb
,
104 .kill_sb
= kill_block_super
,
105 .fs_flags
= FS_REQUIRES_DEV
108 static unsigned char squashfs_filetype_table
[] = {
109 DT_UNKNOWN
, DT_DIR
, DT_REG
, DT_LNK
, DT_BLK
, DT_CHR
, DT_FIFO
, DT_SOCK
112 static struct super_operations squashfs_ops
= {
113 .alloc_inode
= squashfs_alloc_inode
,
114 .destroy_inode
= squashfs_destroy_inode
,
115 .statfs
= squashfs_statfs
,
116 .put_super
= squashfs_put_super
,
119 static struct address_space_operations squashfs_symlink_aops
= {
120 .readpage
= squashfs_symlink_readpage
123 static struct address_space_operations squashfs_aops
= {
124 .readpage
= squashfs_readpage
127 static struct address_space_operations squashfs_aops_4K
= {
128 .readpage
= squashfs_readpage4K
131 #ifdef SQUASHFS_1_0_COMPATIBILITY
132 static struct address_space_operations squashfs_aops_lessthan4K
= {
133 .readpage
= squashfs_readpage_lessthan4K
137 static struct file_operations squashfs_dir_ops
= {
138 .read
= generic_read_dir
,
139 .readdir
= squashfs_readdir
142 static struct inode_operations squashfs_dir_inode_ops
= {
143 .lookup
= squashfs_lookup
147 static inline struct squashfs_inode_info
*SQUASHFS_I(struct inode
*inode
)
149 return list_entry(inode
, struct squashfs_inode_info
, vfs_inode
);
153 static struct buffer_head
*get_block_length(struct super_block
*s
,
154 int *cur_index
, int *offset
, int *c_byte
)
156 squashfs_sb_info
*msblk
= s
->s_fs_info
;
158 struct buffer_head
*bh
;
160 if (!(bh
= sb_bread(s
, *cur_index
)))
163 if (msblk
->devblksize
- *offset
== 1) {
165 ((unsigned char *) &temp
)[1] = *((unsigned char *)
166 (bh
->b_data
+ *offset
));
168 ((unsigned char *) &temp
)[0] = *((unsigned char *)
169 (bh
->b_data
+ *offset
));
171 if (!(bh
= sb_bread(s
, ++(*cur_index
))))
174 ((unsigned char *) &temp
)[0] = *((unsigned char *)
177 ((unsigned char *) &temp
)[1] = *((unsigned char *)
183 ((unsigned char *) &temp
)[1] = *((unsigned char *)
184 (bh
->b_data
+ *offset
));
185 ((unsigned char *) &temp
)[0] = *((unsigned char *)
186 (bh
->b_data
+ *offset
+ 1));
188 ((unsigned char *) &temp
)[0] = *((unsigned char *)
189 (bh
->b_data
+ *offset
));
190 ((unsigned char *) &temp
)[1] = *((unsigned char *)
191 (bh
->b_data
+ *offset
+ 1));
197 if (SQUASHFS_CHECK_DATA(msblk
->sBlk
.flags
)) {
198 if (*offset
== msblk
->devblksize
) {
200 if (!(bh
= sb_bread(s
, ++(*cur_index
))))
204 if (*((unsigned char *) (bh
->b_data
+ *offset
)) !=
205 SQUASHFS_MARKER_BYTE
) {
206 ERROR("Metadata block marker corrupt @ %x\n",
220 static unsigned int read_data(struct super_block
*s
, char *buffer
,
221 unsigned int index
, unsigned int length
, unsigned int *next_index
)
223 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
224 struct buffer_head
*bh
[((SQUASHFS_FILE_MAX_SIZE
- 1) >> msBlk
->devblksize_log2
) + 2];
225 unsigned int offset
= index
& ((1 << msBlk
->devblksize_log2
) - 1);
226 unsigned int cur_index
= index
>> msBlk
->devblksize_log2
;
227 int bytes
, avail_bytes
, b
= 0, k
;
229 unsigned int compressed
;
230 unsigned int c_byte
= length
;
233 bytes
= msBlk
->devblksize
- offset
;
234 compressed
= SQUASHFS_COMPRESSED_BLOCK(c_byte
);
235 c_buffer
= compressed
? msBlk
->read_data
: buffer
;
236 c_byte
= SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte
);
238 TRACE("Block @ 0x%x, %scompressed size %d\n", index
, compressed
? "" : "un", (unsigned int) c_byte
);
240 if(!(bh
[0] = sb_getblk(s
, cur_index
)))
242 for(b
= 1; bytes
< c_byte
; b
++) {
243 if(!(bh
[b
] = sb_getblk(s
, ++cur_index
)))
245 bytes
+= msBlk
->devblksize
;
247 ll_rw_block(READ
, b
, bh
);
249 if(!(bh
[0] = get_block_length(s
, &cur_index
, &offset
, &c_byte
)))
252 bytes
= msBlk
->devblksize
- offset
;
253 compressed
= SQUASHFS_COMPRESSED(c_byte
);
254 c_buffer
= compressed
? msBlk
->read_data
: buffer
;
255 c_byte
= SQUASHFS_COMPRESSED_SIZE(c_byte
);
257 TRACE("Block @ 0x%x, %scompressed size %d\n", index
, compressed
? "" : "un", (unsigned int) c_byte
);
259 for(b
= 1; bytes
< c_byte
; b
++) {
260 if(!(bh
[b
] = sb_getblk(s
, ++cur_index
)))
262 bytes
+= msBlk
->devblksize
;
264 ll_rw_block(READ
, b
- 1, bh
+ 1);
268 down(&read_data_mutex
);
270 for(bytes
= 0, k
= 0; k
< b
; k
++) {
271 avail_bytes
= (c_byte
- bytes
) > (msBlk
->devblksize
- offset
) ? msBlk
->devblksize
- offset
: c_byte
- bytes
;
272 wait_on_buffer(bh
[k
]);
273 if (!buffer_uptodate(bh
[k
]))
275 memcpy(c_buffer
+ bytes
, bh
[k
]->b_data
+ offset
, avail_bytes
);
276 bytes
+= avail_bytes
;
285 #ifdef CONFIG_SQUASHFS_LZMA
288 out_size
=msBlk
->read_size
;
290 if((lzma_err
=lzma_inflate(c_buffer
, c_byte
, buffer
, &out_size
))){
291 ERROR("lzma returned unexpected result 0x%x\n", lzma_err
);
295 // printk("out size = %d, processed = %d\n", msBlk->read_size, out_size);
299 stream
.next_in
= c_buffer
;
300 stream
.avail_in
= c_byte
;
301 stream
.next_out
= buffer
;
302 stream
.avail_out
= msBlk
->read_size
;
303 if(((zlib_err
= zlib_inflateInit(&stream
)) != Z_OK
) ||
304 ((zlib_err
= zlib_inflate(&stream
, Z_FINISH
)) != Z_STREAM_END
) ||
305 ((zlib_err
= zlib_inflateEnd(&stream
)) != Z_OK
)) {
306 ERROR("zlib_fs returned unexpected result 0x%x\n", zlib_err
);
309 bytes
= stream
.total_out
;
311 up(&read_data_mutex
);
315 *next_index
= index
+ c_byte
+ (length
? 0 : (SQUASHFS_CHECK_DATA(msBlk
->sBlk
.flags
) ? 3 : 2));
320 while(--b
>= 0) brelse(bh
[b
]);
323 ERROR("sb_bread failed reading block 0x%x\n", cur_index
);
328 static int squashfs_get_cached_block(struct super_block
*s
, char *buffer
,
329 unsigned int block
, unsigned int offset
, int length
,
330 unsigned int *next_block
, unsigned int *next_offset
)
332 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
333 int n
, i
, bytes
, return_length
= length
;
334 unsigned int next_index
;
336 TRACE("Entered squashfs_get_cached_block [%x:%x]\n", block
, offset
);
339 for(i
= 0; i
< SQUASHFS_CACHED_BLKS
; i
++)
340 if(msBlk
->block_cache
[i
].block
== block
)
343 down(&msBlk
->block_cache_mutex
);
344 if(i
== SQUASHFS_CACHED_BLKS
) {
345 /* read inode header block */
346 for(i
= msBlk
->next_cache
, n
= SQUASHFS_CACHED_BLKS
; n
; n
--, i
= (i
+ 1) % SQUASHFS_CACHED_BLKS
)
347 if(msBlk
->block_cache
[i
].block
!= SQUASHFS_USED_BLK
)
352 init_waitqueue_entry(&wait
, current
);
353 add_wait_queue(&msBlk
->waitq
, &wait
);
354 up(&msBlk
->block_cache_mutex
);
355 set_current_state(TASK_UNINTERRUPTIBLE
);
357 set_current_state(TASK_RUNNING
);
358 remove_wait_queue(&msBlk
->waitq
, &wait
);
361 msBlk
->next_cache
= (i
+ 1) % SQUASHFS_CACHED_BLKS
;
363 if(msBlk
->block_cache
[i
].block
== SQUASHFS_INVALID_BLK
) {
364 if(!(msBlk
->block_cache
[i
].data
= (unsigned char *)
365 kmalloc(SQUASHFS_METADATA_SIZE
, GFP_KERNEL
))) {
366 ERROR("Failed to allocate cache block\n");
367 up(&msBlk
->block_cache_mutex
);
372 msBlk
->block_cache
[i
].block
= SQUASHFS_USED_BLK
;
373 up(&msBlk
->block_cache_mutex
);
374 if(!(msBlk
->block_cache
[i
].length
= read_data(s
, msBlk
->block_cache
[i
].data
, block
, 0,
376 ERROR("Unable to read cache block [%x:%x]\n", block
, offset
);
379 down(&msBlk
->block_cache_mutex
);
380 wake_up(&msBlk
->waitq
);
381 msBlk
->block_cache
[i
].block
= block
;
382 msBlk
->block_cache
[i
].next_index
= next_index
;
383 TRACE("Read cache block [%x:%x]\n", block
, offset
);
386 if(msBlk
->block_cache
[i
].block
!= block
) {
387 up(&msBlk
->block_cache_mutex
);
391 if((bytes
= msBlk
->block_cache
[i
].length
- offset
) >= length
) {
393 memcpy(buffer
, msBlk
->block_cache
[i
].data
+ offset
, length
);
394 if(msBlk
->block_cache
[i
].length
- offset
== length
) {
395 *next_block
= msBlk
->block_cache
[i
].next_index
;
399 *next_offset
= offset
+ length
;
402 up(&msBlk
->block_cache_mutex
);
403 return return_length
;
406 memcpy(buffer
, msBlk
->block_cache
[i
].data
+ offset
, bytes
);
409 block
= msBlk
->block_cache
[i
].next_index
;
410 up(&msBlk
->block_cache_mutex
);
418 static int get_fragment_location(struct super_block
*s
, unsigned int fragment
, unsigned int *fragment_start_block
, unsigned int *fragment_size
)
420 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
421 unsigned int start_block
= msBlk
->fragment_index
[SQUASHFS_FRAGMENT_INDEX(fragment
)];
422 int offset
= SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment
);
423 squashfs_fragment_entry fragment_entry
;
426 squashfs_fragment_entry sfragment_entry
;
428 if(!squashfs_get_cached_block(s
, (char *) &sfragment_entry
, start_block
, offset
,
429 sizeof(sfragment_entry
), &start_block
, &offset
))
431 SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry
, &sfragment_entry
);
433 if(!squashfs_get_cached_block(s
, (char *) &fragment_entry
, start_block
, offset
,
434 sizeof(fragment_entry
), &start_block
, &offset
))
437 *fragment_start_block
= fragment_entry
.start_block
;
438 *fragment_size
= fragment_entry
.size
;
444 void release_cached_fragment(squashfs_sb_info
*msBlk
, struct squashfs_fragment_cache
*fragment
)
446 down(&msBlk
->fragment_mutex
);
448 wake_up(&msBlk
->fragment_wait_queue
);
449 up(&msBlk
->fragment_mutex
);
453 struct squashfs_fragment_cache
*get_cached_fragment(struct super_block
*s
, unsigned int start_block
, int length
)
456 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
459 down(&msBlk
->fragment_mutex
);
460 for(i
= 0; i
< SQUASHFS_CACHED_FRAGMENTS
&& msBlk
->fragment
[i
].block
!= start_block
; i
++);
461 if(i
== SQUASHFS_CACHED_FRAGMENTS
) {
462 for(i
= msBlk
->next_fragment
, n
= SQUASHFS_CACHED_FRAGMENTS
;
463 n
&& msBlk
->fragment
[i
].locked
; n
--, i
= (i
+ 1) % SQUASHFS_CACHED_FRAGMENTS
);
468 init_waitqueue_entry(&wait
, current
);
469 add_wait_queue(&msBlk
->fragment_wait_queue
, &wait
);
470 up(&msBlk
->fragment_mutex
);
471 set_current_state(TASK_UNINTERRUPTIBLE
);
473 set_current_state(TASK_RUNNING
);
474 remove_wait_queue(&msBlk
->fragment_wait_queue
, &wait
);
477 msBlk
->next_fragment
= (msBlk
->next_fragment
+ 1) % SQUASHFS_CACHED_FRAGMENTS
;
479 if(msBlk
->fragment
[i
].data
== NULL
)
480 if(!(msBlk
->fragment
[i
].data
= (unsigned char *)
481 SQUASHFS_ALLOC(SQUASHFS_FILE_MAX_SIZE
))) {
482 ERROR("Failed to allocate fragment cache block\n");
483 up(&msBlk
->fragment_mutex
);
487 msBlk
->fragment
[i
].block
= SQUASHFS_INVALID_BLK
;
488 msBlk
->fragment
[i
].locked
= 1;
489 up(&msBlk
->fragment_mutex
);
490 if(!(msBlk
->fragment
[i
].length
= read_data(s
, msBlk
->fragment
[i
].data
, start_block
, length
,
492 ERROR("Unable to read fragment cache block [%x]\n", start_block
);
493 msBlk
->fragment
[i
].locked
= 0;
496 msBlk
->fragment
[i
].block
= start_block
;
497 TRACE("New fragment %d, start block %d, locked %d\n", i
, msBlk
->fragment
[i
].block
, msBlk
->fragment
[i
].locked
);
498 return &msBlk
->fragment
[i
];
501 msBlk
->fragment
[i
].locked
++;
502 up(&msBlk
->fragment_mutex
);
504 TRACE("Got fragment %d, start block %d, locked %d\n", i
, msBlk
->fragment
[i
].block
, msBlk
->fragment
[i
].locked
);
505 return &msBlk
->fragment
[i
];
510 #ifdef SQUASHFS_1_0_COMPATIBILITY
511 static struct inode
*squashfs_iget_1(struct super_block
*s
, squashfs_inode inode
)
513 struct inode
*i
= new_inode(s
);
514 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
515 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
516 unsigned int block
= SQUASHFS_INODE_BLK(inode
) + sBlk
->inode_table_start
;
517 unsigned int offset
= SQUASHFS_INODE_OFFSET(inode
);
518 unsigned int next_block
, next_offset
;
519 squashfs_base_inode_header_1 inodeb
;
521 TRACE("Entered squashfs_iget_1\n");
524 squashfs_base_inode_header_1 sinodeb
;
526 if(!squashfs_get_cached_block(s
, (char *) &sinodeb
, block
, offset
,
527 sizeof(sinodeb
), &next_block
, &next_offset
))
529 SQUASHFS_SWAP_BASE_INODE_HEADER_1(&inodeb
, &sinodeb
, sizeof(sinodeb
));
531 if(!squashfs_get_cached_block(s
, (char *) &inodeb
, block
, offset
,
532 sizeof(inodeb
), &next_block
, &next_offset
))
537 i
->i_mtime
.tv_sec
= sBlk
->mkfs_time
;
538 i
->i_atime
.tv_sec
= sBlk
->mkfs_time
;
539 i
->i_ctime
.tv_sec
= sBlk
->mkfs_time
;
541 if(inodeb
.inode_type
!= SQUASHFS_IPC_TYPE
)
542 i
->i_uid
= msBlk
->uid
[((inodeb
.inode_type
- 1) / SQUASHFS_TYPES
) * 16 + inodeb
.uid
];
543 i
->i_ino
= SQUASHFS_MK_VFS_INODE(block
- sBlk
->inode_table_start
, offset
);
545 i
->i_mode
= inodeb
.mode
;
547 switch(inodeb
.inode_type
== SQUASHFS_IPC_TYPE
? SQUASHFS_IPC_TYPE
: (inodeb
.inode_type
- 1) % SQUASHFS_TYPES
+ 1) {
548 case SQUASHFS_FILE_TYPE
: {
549 squashfs_reg_inode_header_1 inodep
;
552 squashfs_reg_inode_header_1 sinodep
;
554 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
555 &next_block
, &next_offset
))
557 SQUASHFS_SWAP_REG_INODE_HEADER_1(&inodep
, &sinodep
);
559 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
560 &next_block
, &next_offset
))
563 i
->i_size
= inodep
.file_size
;
564 i
->i_fop
= &generic_ro_fops
;
565 if(sBlk
->block_size
> 4096)
566 i
->i_data
.a_ops
= &squashfs_aops
;
567 else if(sBlk
->block_size
== 4096)
568 i
->i_data
.a_ops
= &squashfs_aops_4K
;
570 i
->i_data
.a_ops
= &squashfs_aops_lessthan4K
;
571 i
->i_mode
|= S_IFREG
;
572 i
->i_mtime
.tv_sec
= inodep
.mtime
;
573 i
->i_atime
.tv_sec
= inodep
.mtime
;
574 i
->i_ctime
.tv_sec
= inodep
.mtime
;
575 i
->i_blocks
= ((i
->i_size
- 1) >> 9) + 1;
576 SQUASHFS_I(i
)->u
.s1
.fragment_start_block
= SQUASHFS_INVALID_BLK
;
577 SQUASHFS_I(i
)->u
.s1
.fragment_offset
= 0;
578 SQUASHFS_I(i
)->start_block
= inodep
.start_block
;
579 SQUASHFS_I(i
)->block_list_start
= next_block
;
580 SQUASHFS_I(i
)->offset
= next_offset
;
581 TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
582 SQUASHFS_INODE_BLK(inode
), offset
, inodep
.start_block
, next_block
, next_offset
);
585 case SQUASHFS_DIR_TYPE
: {
586 squashfs_dir_inode_header_1 inodep
;
589 squashfs_dir_inode_header_1 sinodep
;
591 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
592 &next_block
, &next_offset
))
594 SQUASHFS_SWAP_DIR_INODE_HEADER_1(&inodep
, &sinodep
);
596 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
597 &next_block
, &next_offset
))
600 i
->i_size
= inodep
.file_size
;
601 i
->i_op
= &squashfs_dir_inode_ops
;
602 i
->i_fop
= &squashfs_dir_ops
;
603 i
->i_mode
|= S_IFDIR
;
604 i
->i_mtime
.tv_sec
= inodep
.mtime
;
605 i
->i_atime
.tv_sec
= inodep
.mtime
;
606 i
->i_ctime
.tv_sec
= inodep
.mtime
;
607 SQUASHFS_I(i
)->start_block
= inodep
.start_block
;
608 SQUASHFS_I(i
)->offset
= inodep
.offset
;
609 SQUASHFS_I(i
)->u
.s2
.directory_index_count
= 0;
610 TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode
), offset
,
611 inodep
.start_block
, inodep
.offset
);
614 case SQUASHFS_SYMLINK_TYPE
: {
615 squashfs_symlink_inode_header_1 inodep
;
618 squashfs_symlink_inode_header_1 sinodep
;
620 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
621 &next_block
, &next_offset
))
623 SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(&inodep
, &sinodep
);
625 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
626 &next_block
, &next_offset
))
629 i
->i_size
= inodep
.symlink_size
;
630 i
->i_op
= &page_symlink_inode_operations
;
631 i
->i_data
.a_ops
= &squashfs_symlink_aops
;
632 i
->i_mode
|= S_IFLNK
;
633 SQUASHFS_I(i
)->start_block
= next_block
;
634 SQUASHFS_I(i
)->offset
= next_offset
;
635 TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
636 SQUASHFS_INODE_BLK(inode
), offset
, next_block
, next_offset
);
639 case SQUASHFS_BLKDEV_TYPE
:
640 case SQUASHFS_CHRDEV_TYPE
: {
641 squashfs_dev_inode_header_1 inodep
;
644 squashfs_dev_inode_header_1 sinodep
;
646 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
647 &next_block
, &next_offset
))
649 SQUASHFS_SWAP_DEV_INODE_HEADER_1(&inodep
, &sinodep
);
651 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
652 &next_block
, &next_offset
))
656 i
->i_mode
|= (inodeb
.inode_type
== SQUASHFS_CHRDEV_TYPE
) ? S_IFCHR
: S_IFBLK
;
657 init_special_inode(i
, i
->i_mode
, old_decode_dev(inodep
.rdev
));
658 TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode
), offset
, inodep
.rdev
);
661 case SQUASHFS_IPC_TYPE
: {
662 squashfs_ipc_inode_header_1 inodep
;
665 squashfs_ipc_inode_header_1 sinodep
;
667 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
668 &next_block
, &next_offset
))
670 SQUASHFS_SWAP_IPC_INODE_HEADER_1(&inodep
, &sinodep
);
672 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
673 &next_block
, &next_offset
))
677 i
->i_mode
|= (inodep
.type
== SQUASHFS_FIFO_TYPE
) ? S_IFIFO
: S_IFSOCK
;
678 i
->i_uid
= msBlk
->uid
[inodep
.offset
* 16 + inodeb
.uid
];
679 init_special_inode(i
, i
->i_mode
, 0);
683 ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb
.inode_type
);
687 if(inodeb
.guid
== 15)
690 i
->i_gid
= msBlk
->guid
[inodeb
.guid
];
692 insert_inode_hash(i
);
696 ERROR("Unable to read inode [%x:%x]\n", block
, offset
);
704 static struct inode
*squashfs_iget(struct super_block
*s
, squashfs_inode inode
)
706 struct inode
*i
= new_inode(s
);
707 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
708 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
709 unsigned int block
= SQUASHFS_INODE_BLK(inode
) + sBlk
->inode_table_start
;
710 unsigned int offset
= SQUASHFS_INODE_OFFSET(inode
);
711 unsigned int next_block
, next_offset
;
712 squashfs_base_inode_header inodeb
;
714 TRACE("Entered squashfs_iget\n");
717 squashfs_base_inode_header sinodeb
;
719 if(!squashfs_get_cached_block(s
, (char *) &sinodeb
, block
, offset
,
720 sizeof(sinodeb
), &next_block
, &next_offset
))
722 SQUASHFS_SWAP_BASE_INODE_HEADER(&inodeb
, &sinodeb
, sizeof(sinodeb
));
724 if(!squashfs_get_cached_block(s
, (char *) &inodeb
, block
, offset
,
725 sizeof(inodeb
), &next_block
, &next_offset
))
730 i
->i_mtime
.tv_sec
= sBlk
->mkfs_time
;
731 i
->i_atime
.tv_sec
= sBlk
->mkfs_time
;
732 i
->i_ctime
.tv_sec
= sBlk
->mkfs_time
;
734 i
->i_uid
= msBlk
->uid
[inodeb
.uid
];
735 i
->i_ino
= SQUASHFS_MK_VFS_INODE(block
- sBlk
->inode_table_start
, offset
);
737 i
->i_mode
= inodeb
.mode
;
739 switch(inodeb
.inode_type
) {
740 case SQUASHFS_FILE_TYPE
: {
741 squashfs_reg_inode_header inodep
;
744 squashfs_reg_inode_header sinodep
;
746 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
747 &next_block
, &next_offset
))
749 SQUASHFS_SWAP_REG_INODE_HEADER(&inodep
, &sinodep
);
751 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
752 &next_block
, &next_offset
))
755 SQUASHFS_I(i
)->u
.s1
.fragment_start_block
= SQUASHFS_INVALID_BLK
;
756 if(inodep
.fragment
!= SQUASHFS_INVALID_BLK
&& !get_fragment_location(s
, inodep
.fragment
,
757 &SQUASHFS_I(i
)->u
.s1
.fragment_start_block
, &SQUASHFS_I(i
)->u
.s1
.fragment_size
))
760 SQUASHFS_I(i
)->u
.s1
.fragment_offset
= inodep
.offset
;
761 i
->i_size
= inodep
.file_size
;
762 i
->i_fop
= &generic_ro_fops
;
763 if(sBlk
->block_size
> 4096)
764 i
->i_data
.a_ops
= &squashfs_aops
;
766 i
->i_data
.a_ops
= &squashfs_aops_4K
;
767 i
->i_mode
|= S_IFREG
;
768 i
->i_mtime
.tv_sec
= inodep
.mtime
;
769 i
->i_atime
.tv_sec
= inodep
.mtime
;
770 i
->i_ctime
.tv_sec
= inodep
.mtime
;
771 i
->i_blocks
= ((i
->i_size
- 1) >> 9) + 1;
772 SQUASHFS_I(i
)->start_block
= inodep
.start_block
;
773 SQUASHFS_I(i
)->block_list_start
= next_block
;
774 SQUASHFS_I(i
)->offset
= next_offset
;
775 TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
776 SQUASHFS_INODE_BLK(inode
), offset
, inodep
.start_block
, next_block
, next_offset
);
779 case SQUASHFS_DIR_TYPE
: {
780 squashfs_dir_inode_header inodep
;
783 squashfs_dir_inode_header sinodep
;
785 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
786 &next_block
, &next_offset
))
788 SQUASHFS_SWAP_DIR_INODE_HEADER(&inodep
, &sinodep
);
790 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
791 &next_block
, &next_offset
))
794 i
->i_size
= inodep
.file_size
;
795 i
->i_op
= &squashfs_dir_inode_ops
;
796 i
->i_fop
= &squashfs_dir_ops
;
797 i
->i_mode
|= S_IFDIR
;
798 i
->i_mtime
.tv_sec
= inodep
.mtime
;
799 i
->i_atime
.tv_sec
= inodep
.mtime
;
800 i
->i_ctime
.tv_sec
= inodep
.mtime
;
801 SQUASHFS_I(i
)->start_block
= inodep
.start_block
;
802 SQUASHFS_I(i
)->offset
= inodep
.offset
;
803 SQUASHFS_I(i
)->u
.s2
.directory_index_count
= 0;
804 TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode
), offset
,
805 inodep
.start_block
, inodep
.offset
);
808 case SQUASHFS_LDIR_TYPE
: {
809 squashfs_ldir_inode_header inodep
;
812 squashfs_ldir_inode_header sinodep
;
814 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
815 &next_block
, &next_offset
))
817 SQUASHFS_SWAP_LDIR_INODE_HEADER(&inodep
, &sinodep
);
819 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
820 &next_block
, &next_offset
))
823 i
->i_size
= inodep
.file_size
;
824 i
->i_op
= &squashfs_dir_inode_ops
;
825 i
->i_fop
= &squashfs_dir_ops
;
826 i
->i_mode
|= S_IFDIR
;
827 i
->i_mtime
.tv_sec
= inodep
.mtime
;
828 i
->i_atime
.tv_sec
= inodep
.mtime
;
829 i
->i_ctime
.tv_sec
= inodep
.mtime
;
830 SQUASHFS_I(i
)->start_block
= inodep
.start_block
;
831 SQUASHFS_I(i
)->offset
= inodep
.offset
;
832 SQUASHFS_I(i
)->u
.s2
.directory_index_start
= next_block
;
833 SQUASHFS_I(i
)->u
.s2
.directory_index_offset
= next_offset
;
834 SQUASHFS_I(i
)->u
.s2
.directory_index_count
= inodep
.i_count
;
835 TRACE("Long directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode
), offset
,
836 inodep
.start_block
, inodep
.offset
);
839 case SQUASHFS_SYMLINK_TYPE
: {
840 squashfs_symlink_inode_header inodep
;
843 squashfs_symlink_inode_header sinodep
;
845 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
846 &next_block
, &next_offset
))
848 SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep
, &sinodep
);
850 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
851 &next_block
, &next_offset
))
854 i
->i_size
= inodep
.symlink_size
;
855 i
->i_op
= &page_symlink_inode_operations
;
856 i
->i_data
.a_ops
= &squashfs_symlink_aops
;
857 i
->i_mode
|= S_IFLNK
;
858 SQUASHFS_I(i
)->start_block
= next_block
;
859 SQUASHFS_I(i
)->offset
= next_offset
;
860 TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
861 SQUASHFS_INODE_BLK(inode
), offset
, next_block
, next_offset
);
864 case SQUASHFS_BLKDEV_TYPE
:
865 case SQUASHFS_CHRDEV_TYPE
: {
866 squashfs_dev_inode_header inodep
;
869 squashfs_dev_inode_header sinodep
;
871 if(!squashfs_get_cached_block(s
, (char *) &sinodep
, block
, offset
, sizeof(sinodep
),
872 &next_block
, &next_offset
))
874 SQUASHFS_SWAP_DEV_INODE_HEADER(&inodep
, &sinodep
);
876 if(!squashfs_get_cached_block(s
, (char *) &inodep
, block
, offset
, sizeof(inodep
),
877 &next_block
, &next_offset
))
881 i
->i_mode
|= (inodeb
.inode_type
== SQUASHFS_CHRDEV_TYPE
) ? S_IFCHR
: S_IFBLK
;
882 init_special_inode(i
, i
->i_mode
, old_decode_dev(inodep
.rdev
));
883 TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode
), offset
, inodep
.rdev
);
886 case SQUASHFS_FIFO_TYPE
:
887 case SQUASHFS_SOCKET_TYPE
: {
889 i
->i_mode
|= (inodeb
.inode_type
== SQUASHFS_FIFO_TYPE
) ? S_IFIFO
: S_IFSOCK
;
890 init_special_inode(i
, i
->i_mode
, 0);
894 ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb
.inode_type
);
898 if(inodeb
.guid
== SQUASHFS_GUIDS
)
901 i
->i_gid
= msBlk
->guid
[inodeb
.guid
];
903 insert_inode_hash(i
);
907 ERROR("Unable to read inode [%x:%x]\n", block
, offset
);
914 static int squashfs_fill_super(struct super_block
*s
,
915 void *data
, int silent
)
917 squashfs_sb_info
*msBlk
;
918 squashfs_super_block
*sBlk
;
920 char b
[BDEVNAME_SIZE
];
922 TRACE("Entered squashfs_read_superblock\n");
924 if(!(s
->s_fs_info
= (void *) kmalloc(sizeof(squashfs_sb_info
), GFP_KERNEL
))) {
925 ERROR("Failed to allocate superblock\n");
928 msBlk
= (squashfs_sb_info
*) s
->s_fs_info
;
931 msBlk
->devblksize
= sb_min_blocksize(s
, BLOCK_SIZE
);
932 msBlk
->devblksize_log2
= ffz(~msBlk
->devblksize
);
934 init_MUTEX(&msBlk
->read_page_mutex
);
935 init_MUTEX(&msBlk
->block_cache_mutex
);
936 init_MUTEX(&msBlk
->fragment_mutex
);
938 init_waitqueue_head(&msBlk
->waitq
);
939 init_waitqueue_head(&msBlk
->fragment_wait_queue
);
941 if(!read_data(s
, (char *) sBlk
, SQUASHFS_START
, sizeof(squashfs_super_block
) | SQUASHFS_COMPRESSED_BIT_BLOCK
, NULL
)) {
942 SERROR("unable to read superblock\n");
946 /* Check it is a SQUASHFS superblock */
948 if((s
->s_magic
= sBlk
->s_magic
) != SQUASHFS_MAGIC
) {
949 if(sBlk
->s_magic
== SQUASHFS_MAGIC_SWAP
) {
950 squashfs_super_block sblk
;
951 WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", bdevname(s
->s_bdev
, b
));
952 SQUASHFS_SWAP_SUPER_BLOCK(&sblk
, sBlk
);
953 memcpy(sBlk
, &sblk
, sizeof(squashfs_super_block
));
956 SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(s
->s_bdev
, b
));
961 /* Check the MAJOR & MINOR versions */
962 #ifdef SQUASHFS_1_0_COMPATIBILITY
963 if((sBlk
->s_major
!= 1) && (sBlk
->s_major
!= 2 || sBlk
->s_minor
> SQUASHFS_MINOR
)) {
964 SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (1 : x) or (2 : <= %d)\n",
965 sBlk
->s_major
, sBlk
->s_minor
, SQUASHFS_MINOR
);
968 if(sBlk
->s_major
== 1)
969 sBlk
->block_size
= sBlk
->block_size_1
;
971 if(sBlk
->s_major
!= SQUASHFS_MAJOR
|| sBlk
->s_minor
> SQUASHFS_MINOR
) {
972 SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (%d: <= %d)\n",
973 sBlk
->s_major
, sBlk
->s_minor
, SQUASHFS_MAJOR
, SQUASHFS_MINOR
);
978 TRACE("Found valid superblock on %s\n", bdevname(s
->s_bdev
, b
));
979 TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk
->flags
) ? "un" : "");
980 TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk
->flags
) ? "un" : "");
981 TRACE("Check data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk
->flags
) ? "" : "not");
982 TRACE("Filesystem size %d bytes\n", sBlk
->bytes_used
);
983 TRACE("Block size %d\n", sBlk
->block_size
);
984 TRACE("Number of inodes %d\n", sBlk
->inodes
);
985 if(sBlk
->s_major
> 1)
986 TRACE("Number of fragments %d\n", sBlk
->fragments
);
987 TRACE("Number of uids %d\n", sBlk
->no_uids
);
988 TRACE("Number of gids %d\n", sBlk
->no_guids
);
989 TRACE("sBlk->inode_table_start %x\n", sBlk
->inode_table_start
);
990 TRACE("sBlk->directory_table_start %x\n", sBlk
->directory_table_start
);
991 if(sBlk
->s_major
> 1)
992 TRACE("sBlk->fragment_table_start %x\n", sBlk
->fragment_table_start
);
993 TRACE("sBlk->uid_start %x\n", sBlk
->uid_start
);
995 s
->s_flags
|= MS_RDONLY
;
996 s
->s_op
= &squashfs_ops
;
998 /* Init inode_table block pointer array */
999 if(!(msBlk
->block_cache
= (squashfs_cache
*) kmalloc(sizeof(squashfs_cache
) * SQUASHFS_CACHED_BLKS
, GFP_KERNEL
))) {
1000 ERROR("Failed to allocate block cache\n");
1004 for(i
= 0; i
< SQUASHFS_CACHED_BLKS
; i
++)
1005 msBlk
->block_cache
[i
].block
= SQUASHFS_INVALID_BLK
;
1007 msBlk
->next_cache
= 0;
1009 /* Allocate read_data block */
1010 msBlk
->read_size
= (sBlk
->block_size
< SQUASHFS_METADATA_SIZE
) ? SQUASHFS_METADATA_SIZE
: sBlk
->block_size
;
1011 if(!(msBlk
->read_data
= (char *) kmalloc(msBlk
->read_size
, GFP_KERNEL
))) {
1012 ERROR("Failed to allocate read_data block\n");
1016 /* Allocate read_page block */
1017 if(sBlk
->block_size
> PAGE_CACHE_SIZE
) {
1018 if(!(msBlk
->read_page
= (char *) kmalloc(sBlk
->block_size
, GFP_KERNEL
))) {
1019 ERROR("Failed to allocate read_page block\n");
1023 msBlk
->read_page
= NULL
;
1025 /* Allocate uid and gid tables */
1026 if(!(msBlk
->uid
= (squashfs_uid
*) kmalloc((sBlk
->no_uids
+
1027 sBlk
->no_guids
) * sizeof(squashfs_uid
), GFP_KERNEL
))) {
1028 ERROR("Failed to allocate uid/gid table\n");
1031 msBlk
->guid
= msBlk
->uid
+ sBlk
->no_uids
;
1034 squashfs_uid suid
[sBlk
->no_uids
+ sBlk
->no_guids
];
1036 if(!read_data(s
, (char *) &suid
, sBlk
->uid_start
, ((sBlk
->no_uids
+ sBlk
->no_guids
) *
1037 sizeof(squashfs_uid
)) | SQUASHFS_COMPRESSED_BIT_BLOCK
, NULL
)) {
1038 SERROR("unable to read uid/gid table\n");
1041 SQUASHFS_SWAP_DATA(msBlk
->uid
, suid
, (sBlk
->no_uids
+ sBlk
->no_guids
), (sizeof(squashfs_uid
) * 8));
1043 if(!read_data(s
, (char *) msBlk
->uid
, sBlk
->uid_start
, ((sBlk
->no_uids
+ sBlk
->no_guids
) *
1044 sizeof(squashfs_uid
)) | SQUASHFS_COMPRESSED_BIT_BLOCK
, NULL
)) {
1045 SERROR("unable to read uid/gid table\n");
1050 #ifdef SQUASHFS_1_0_COMPATIBILITY
1051 if(sBlk
->s_major
== 1) {
1052 msBlk
->iget
= squashfs_iget_1
;
1053 msBlk
->read_blocklist
= read_blocklist_1
;
1054 msBlk
->fragment
= NULL
;
1055 msBlk
->fragment_index
= NULL
;
1059 msBlk
->iget
= squashfs_iget
;
1060 msBlk
->read_blocklist
= read_blocklist
;
1062 if(!(msBlk
->fragment
= (struct squashfs_fragment_cache
*) kmalloc(sizeof(struct squashfs_fragment_cache
) * SQUASHFS_CACHED_FRAGMENTS
, GFP_KERNEL
))) {
1063 ERROR("Failed to allocate fragment block cache\n");
1067 for(i
= 0; i
< SQUASHFS_CACHED_FRAGMENTS
; i
++) {
1068 msBlk
->fragment
[i
].locked
= 0;
1069 msBlk
->fragment
[i
].block
= SQUASHFS_INVALID_BLK
;
1070 msBlk
->fragment
[i
].data
= NULL
;
1073 msBlk
->next_fragment
= 0;
1075 /* Allocate fragment index table */
1076 if(!(msBlk
->fragment_index
= (squashfs_fragment_index
*) kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk
->fragments
), GFP_KERNEL
))) {
1077 ERROR("Failed to allocate uid/gid table\n");
1081 if(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk
->fragments
) &&
1082 !read_data(s
, (char *) msBlk
->fragment_index
, sBlk
->fragment_table_start
,
1083 SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk
->fragments
) | SQUASHFS_COMPRESSED_BIT_BLOCK
, NULL
)) {
1084 SERROR("unable to read fragment index table\n");
1090 squashfs_fragment_index fragment
;
1092 for(i
= 0; i
< SQUASHFS_FRAGMENT_INDEXES(sBlk
->fragments
); i
++) {
1093 SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment
), &msBlk
->fragment_index
[i
], 1);
1094 msBlk
->fragment_index
[i
] = fragment
;
1098 #ifdef SQUASHFS_1_0_COMPATIBILITY
1101 if(!(s
->s_root
= d_alloc_root((msBlk
->iget
)(s
, sBlk
->root_inode
)))) {
1102 ERROR("Root inode create failed\n");
1106 TRACE("Leaving squashfs_read_super\n");
1110 kfree(msBlk
->fragment_index
);
1112 kfree(msBlk
->fragment
);
1116 kfree(msBlk
->read_page
);
1118 kfree(msBlk
->read_data
);
1120 kfree(msBlk
->block_cache
);
1122 kfree(s
->s_fs_info
);
1123 s
->s_fs_info
= NULL
;
1128 static int squashfs_statfs(struct dentry
*dentry
, struct kstatfs
*buf
)
1130 struct super_block
*s
= dentry
->d_sb
;
1131 squashfs_super_block
*sBlk
= &((squashfs_sb_info
*)s
->s_fs_info
)->sBlk
;
1133 TRACE("Entered squashfs_statfs\n");
1134 buf
->f_type
= SQUASHFS_MAGIC
;
1135 buf
->f_bsize
= sBlk
->block_size
;
1136 buf
->f_blocks
= ((sBlk
->bytes_used
- 1) >> sBlk
->block_log
) + 1;
1137 buf
->f_bfree
= buf
->f_bavail
= 0;
1138 buf
->f_files
= sBlk
->inodes
;
1140 buf
->f_namelen
= SQUASHFS_NAME_LEN
;
1145 static int squashfs_symlink_readpage(struct file
*file
, struct page
*page
)
1147 struct inode
*inode
= page
->mapping
->host
;
1148 int index
= page
->index
<< PAGE_CACHE_SHIFT
, length
, bytes
;
1149 unsigned int block
= SQUASHFS_I(inode
)->start_block
;
1150 int offset
= SQUASHFS_I(inode
)->offset
;
1151 void *pageaddr
= kmap(page
);
1153 TRACE("Entered squashfs_symlink_readpage, page index %d, start block %x, offset %x\n",
1154 page
->index
, SQUASHFS_I(inode
)->start_block
, SQUASHFS_I(inode
)->offset
);
1156 for(length
= 0; length
< index
; length
+= bytes
) {
1157 if(!(bytes
= squashfs_get_cached_block(inode
->i_sb
, NULL
, block
, offset
,
1158 PAGE_CACHE_SIZE
, &block
, &offset
))) {
1159 ERROR("Unable to read symbolic link [%x:%x]\n", block
, offset
);
1164 if(length
!= index
) {
1165 ERROR("(squashfs_symlink_readpage) length != index\n");
1170 bytes
= (inode
->i_size
- length
) > PAGE_CACHE_SIZE
? PAGE_CACHE_SIZE
: inode
->i_size
- length
;
1171 if(!(bytes
= squashfs_get_cached_block(inode
->i_sb
, pageaddr
, block
, offset
, bytes
, &block
, &offset
)))
1172 ERROR("Unable to read symbolic link [%x:%x]\n", block
, offset
);
1175 memset(pageaddr
+ bytes
, 0, PAGE_CACHE_SIZE
- bytes
);
1177 flush_dcache_page(page
);
1178 SetPageUptodate(page
);
1187 #ifdef SQUASHFS_1_0_COMPATIBILITY
1188 static unsigned int read_blocklist_1(struct inode
*inode
, int index
, int readahead_blks
,
1189 char *block_list
, unsigned short **block_p
, unsigned int *bsize
)
1191 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)inode
->i_sb
->s_fs_info
;
1192 unsigned short *block_listp
;
1194 int block_ptr
= SQUASHFS_I(inode
)->block_list_start
;
1195 int offset
= SQUASHFS_I(inode
)->offset
;
1196 unsigned int block
= SQUASHFS_I(inode
)->start_block
;
1199 int blocks
= (index
+ readahead_blks
- i
);
1200 if(blocks
> (SIZE
>> 1)) {
1201 if((index
- i
) <= (SIZE
>> 1))
1208 unsigned char sblock_list
[SIZE
];
1209 if(!squashfs_get_cached_block(inode
->i_sb
, (char *) sblock_list
, block_ptr
, offset
, blocks
<< 1, &block_ptr
, &offset
)) {
1210 ERROR("Unable to read block list [%d:%x]\n", block_ptr
, offset
);
1213 SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list
), ((unsigned short *)sblock_list
), blocks
);
1215 if(!squashfs_get_cached_block(inode
->i_sb
, (char *) block_list
, block_ptr
, offset
, blocks
<< 1, &block_ptr
, &offset
)) {
1216 ERROR("Unable to read block list [%d:%x]\n", block_ptr
, offset
);
1219 for(block_listp
= (unsigned short *) block_list
; i
< index
&& blocks
; i
++, block_listp
++, blocks
--)
1220 block
+= SQUASHFS_COMPRESSED_SIZE(*block_listp
);
1221 if(blocks
>= readahead_blks
)
1226 *bsize
= SQUASHFS_COMPRESSED_SIZE(*block_listp
) | (!SQUASHFS_COMPRESSED(*block_listp
) ? SQUASHFS_COMPRESSED_BIT_BLOCK
: 0);
1228 *block_p
= block_listp
;
1234 static unsigned int read_blocklist(struct inode
*inode
, int index
, int readahead_blks
,
1235 char *block_list
, unsigned short **block_p
, unsigned int *bsize
)
1237 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)inode
->i_sb
->s_fs_info
;
1238 unsigned int *block_listp
;
1240 int block_ptr
= SQUASHFS_I(inode
)->block_list_start
;
1241 int offset
= SQUASHFS_I(inode
)->offset
;
1242 unsigned int block
= SQUASHFS_I(inode
)->start_block
;
1245 int blocks
= (index
+ readahead_blks
- i
);
1246 if(blocks
> (SIZE
>> 2)) {
1247 if((index
- i
) <= (SIZE
>> 2))
1254 unsigned char sblock_list
[SIZE
];
1255 if(!squashfs_get_cached_block(inode
->i_sb
, (char *) sblock_list
, block_ptr
, offset
, blocks
<< 2, &block_ptr
, &offset
)) {
1256 ERROR("Unable to read block list [%d:%x]\n", block_ptr
, offset
);
1259 SQUASHFS_SWAP_INTS(((unsigned int *)block_list
), ((unsigned int *)sblock_list
), blocks
);
1261 if(!squashfs_get_cached_block(inode
->i_sb
, (char *) block_list
, block_ptr
, offset
, blocks
<< 2, &block_ptr
, &offset
)) {
1262 ERROR("Unable to read block list [%d:%x]\n", block_ptr
, offset
);
1265 for(block_listp
= (unsigned int *) block_list
; i
< index
&& blocks
; i
++, block_listp
++, blocks
--)
1266 block
+= SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp
);
1267 if(blocks
>= readahead_blks
)
1271 *bsize
= *block_listp
;
1276 static int squashfs_readpage(struct file
*file
, struct page
*page
)
1278 struct inode
*inode
= page
->mapping
->host
;
1279 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)inode
->i_sb
->s_fs_info
;
1280 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1281 unsigned char block_list
[SIZE
];
1282 unsigned int bsize
, block
, i
= 0, bytes
= 0, byte_offset
= 0;
1283 int index
= page
->index
>> (sBlk
->block_log
- PAGE_CACHE_SHIFT
);
1284 void *pageaddr
= kmap(page
);
1285 struct squashfs_fragment_cache
*fragment
= NULL
;
1286 char *data_ptr
= msBlk
->read_page
;
1288 int mask
= (1 << (sBlk
->block_log
- PAGE_CACHE_SHIFT
)) - 1;
1289 int start_index
= page
->index
& ~mask
;
1290 int end_index
= start_index
| mask
;
1292 TRACE("Entered squashfs_readpage, page index %x, start block %x\n", (unsigned int) page
->index
,
1293 SQUASHFS_I(inode
)->start_block
);
1295 if(page
->index
>= ((inode
->i_size
+ PAGE_CACHE_SIZE
- 1) >> PAGE_CACHE_SHIFT
)) {
1299 if(SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
== SQUASHFS_INVALID_BLK
|| index
< (inode
->i_size
>> sBlk
->block_log
)) {
1300 if((block
= (msBlk
->read_blocklist
)(inode
, index
, 1, block_list
, NULL
, &bsize
)) == 0)
1303 down(&msBlk
->read_page_mutex
);
1304 if(!(bytes
= read_data(inode
->i_sb
, msBlk
->read_page
, block
, bsize
, NULL
))) {
1305 ERROR("Unable to read page, block %x, size %x\n", block
, bsize
);
1306 up(&msBlk
->read_page_mutex
);
1310 if((fragment
= get_cached_fragment(inode
->i_sb
, SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
, SQUASHFS_I(inode
)->u
.s1
.fragment_size
)) == NULL
) {
1311 ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
, (int) SQUASHFS_I(inode
)->u
.s1
.fragment_size
);
1314 bytes
= SQUASHFS_I(inode
)->u
.s1
.fragment_offset
+ (inode
->i_size
& (sBlk
->block_size
- 1));
1315 byte_offset
= SQUASHFS_I(inode
)->u
.s1
.fragment_offset
;
1316 data_ptr
= fragment
->data
;
1319 for(i
= start_index
; i
<= end_index
&& byte_offset
< bytes
; i
++, byte_offset
+= PAGE_CACHE_SIZE
) {
1320 struct page
*push_page
;
1321 int available_bytes
= (bytes
- byte_offset
) > PAGE_CACHE_SIZE
? PAGE_CACHE_SIZE
: bytes
- byte_offset
;
1323 TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", bytes
, i
, byte_offset
, available_bytes
);
1325 if(i
== page
->index
) {
1326 memcpy(pageaddr
, data_ptr
+ byte_offset
, available_bytes
);
1327 memset(pageaddr
+ available_bytes
, 0, PAGE_CACHE_SIZE
- available_bytes
);
1329 flush_dcache_page(page
);
1330 SetPageUptodate(page
);
1332 } else if((push_page
= grab_cache_page_nowait(page
->mapping
, i
))) {
1333 void *pageaddr
= kmap(push_page
);
1334 memcpy(pageaddr
, data_ptr
+ byte_offset
, available_bytes
);
1335 memset(pageaddr
+ available_bytes
, 0, PAGE_CACHE_SIZE
- available_bytes
);
1337 flush_dcache_page(push_page
);
1338 SetPageUptodate(push_page
);
1339 unlock_page(push_page
);
1340 page_cache_release(push_page
);
1344 if(SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
== SQUASHFS_INVALID_BLK
|| index
< (inode
->i_size
>> sBlk
->block_log
))
1345 up(&msBlk
->read_page_mutex
);
1347 release_cached_fragment(msBlk
, fragment
);
1352 memset(pageaddr
+ bytes
, 0, PAGE_CACHE_SIZE
- bytes
);
1354 flush_dcache_page(page
);
1355 SetPageUptodate(page
);
1362 static int squashfs_readpage4K(struct file
*file
, struct page
*page
)
1364 struct inode
*inode
= page
->mapping
->host
;
1365 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)inode
->i_sb
->s_fs_info
;
1366 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1367 unsigned char block_list
[SIZE
];
1368 unsigned int bsize
, block
, bytes
= 0;
1369 void *pageaddr
= kmap(page
);
1371 TRACE("Entered squashfs_readpage4K, page index %x, start block %x\n", (unsigned int) page
->index
,
1372 SQUASHFS_I(inode
)->start_block
);
1374 if(page
->index
>= ((inode
->i_size
+ PAGE_CACHE_SIZE
- 1) >> PAGE_CACHE_SHIFT
)) {
1378 if(SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
== SQUASHFS_INVALID_BLK
|| page
->index
< (inode
->i_size
>> sBlk
->block_log
)) {
1379 block
= (msBlk
->read_blocklist
)(inode
, page
->index
, 1, block_list
, NULL
, &bsize
);
1381 if(!(bytes
= read_data(inode
->i_sb
, pageaddr
, block
, bsize
, NULL
)))
1382 ERROR("Unable to read page, block %x, size %x\n", block
, bsize
);
1384 struct squashfs_fragment_cache
*fragment
;
1386 if((fragment
= get_cached_fragment(inode
->i_sb
, SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
, SQUASHFS_I(inode
)->u
.s1
.fragment_size
)) == NULL
)
1387 ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode
)->u
.s1
.fragment_start_block
, (int) SQUASHFS_I(inode
)->u
.s1
.fragment_size
);
1389 bytes
= inode
->i_size
& (sBlk
->block_size
- 1);
1390 memcpy(pageaddr
, fragment
->data
+ SQUASHFS_I(inode
)->u
.s1
.fragment_offset
, bytes
);
1391 release_cached_fragment(msBlk
, fragment
);
1396 memset(pageaddr
+ bytes
, 0, PAGE_CACHE_SIZE
- bytes
);
1398 flush_dcache_page(page
);
1399 SetPageUptodate(page
);
1406 #ifdef SQUASHFS_1_0_COMPATIBILITY
1407 static int squashfs_readpage_lessthan4K(struct file
*file
, struct page
*page
)
1409 struct inode
*inode
= page
->mapping
->host
;
1410 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)inode
->i_sb
->s_fs_info
;
1411 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1412 unsigned char block_list
[SIZE
];
1413 unsigned short *block_listp
, block
, bytes
= 0;
1414 int index
= page
->index
<< (PAGE_CACHE_SHIFT
- sBlk
->block_log
);
1415 int file_blocks
= ((inode
->i_size
- 1) >> sBlk
->block_log
) + 1;
1416 int readahead_blks
= 1 << (PAGE_CACHE_SHIFT
- sBlk
->block_log
);
1417 void *pageaddr
= kmap(page
);
1419 int i_end
= index
+ (1 << (PAGE_CACHE_SHIFT
- sBlk
->block_log
));
1422 TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start block %x\n", (unsigned int) page
->index
,
1423 SQUASHFS_I(inode
)->start_block
);
1425 block
= read_blocklist_1(inode
, index
, readahead_blks
, block_list
, &block_listp
, NULL
);
1427 if(i_end
> file_blocks
)
1428 i_end
= file_blocks
;
1430 while(index
< i_end
) {
1431 int c_byte
= !SQUASHFS_COMPRESSED(*block_listp
) ? SQUASHFS_COMPRESSED_SIZE(*block_listp
) | SQUASHFS_COMPRESSED_BIT_BLOCK
: *block_listp
;
1432 if(!(byte
= read_data(inode
->i_sb
, pageaddr
, block
, c_byte
, NULL
))) {
1433 ERROR("Unable to read page, block %x, size %x\n", block
, *block_listp
);
1436 block
+= SQUASHFS_COMPRESSED_SIZE(*block_listp
);
1444 memset(pageaddr
, 0, PAGE_CACHE_SIZE
- bytes
);
1446 flush_dcache_page(page
);
1447 SetPageUptodate(page
);
1455 static int get_dir_index_using_offset(struct super_block
*s
, unsigned int *next_block
,
1456 unsigned int *next_offset
, unsigned int index_start
, unsigned int index_offset
,
1457 int i_count
, long long f_pos
)
1459 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
1460 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1462 squashfs_dir_index index
;
1464 TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", i_count
, (unsigned int) f_pos
);
1469 for(i
= 0; i
< i_count
; i
++) {
1471 squashfs_dir_index sindex
;
1472 squashfs_get_cached_block(s
, (char *) &sindex
, index_start
, index_offset
,
1473 sizeof(sindex
), &index_start
, &index_offset
);
1474 SQUASHFS_SWAP_DIR_INDEX(&index
, &sindex
);
1476 squashfs_get_cached_block(s
, (char *) &index
, index_start
, index_offset
,
1477 sizeof(index
), &index_start
, &index_offset
);
1479 if(index
.index
> f_pos
)
1482 squashfs_get_cached_block(s
, NULL
, index_start
, index_offset
,
1483 index
.size
+ 1, &index_start
, &index_offset
);
1485 length
= index
.index
;
1486 *next_block
= index
.start_block
+ sBlk
->directory_table_start
;
1489 *next_offset
= (length
+ *next_offset
) % SQUASHFS_METADATA_SIZE
;
1494 static int get_dir_index_using_name(struct super_block
*s
, unsigned int *next_block
,
1495 unsigned int *next_offset
, unsigned int index_start
, unsigned int index_offset
,
1496 int i_count
, const char *name
, int size
)
1498 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)s
->s_fs_info
;
1499 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1501 char buffer
[sizeof(squashfs_dir_index
) + SQUASHFS_NAME_LEN
+ 1];
1502 squashfs_dir_index
*index
= (squashfs_dir_index
*) buffer
;
1503 char str
[SQUASHFS_NAME_LEN
+ 1];
1505 TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count
);
1507 if (size
> SQUASHFS_NAME_LEN
) {
1508 ERROR("Filename length %d > SQUASHFS_NAME_LEN\n", size
);
1509 size
= SQUASHFS_NAME_LEN
;
1512 strncpy(str
, name
, size
);
1515 for(i
= 0; i
< i_count
; i
++) {
1517 squashfs_dir_index sindex
;
1518 squashfs_get_cached_block(s
, (char *) &sindex
, index_start
, index_offset
,
1519 sizeof(sindex
), &index_start
, &index_offset
);
1520 SQUASHFS_SWAP_DIR_INDEX(index
, &sindex
);
1522 squashfs_get_cached_block(s
, (char *) index
, index_start
, index_offset
,
1523 sizeof(squashfs_dir_index
), &index_start
, &index_offset
);
1525 squashfs_get_cached_block(s
, index
->name
, index_start
, index_offset
,
1526 index
->size
+ 1, &index_start
, &index_offset
);
1528 index
->name
[index
->size
+ 1] = '\0';
1530 if(strcmp(index
->name
, str
) > 0)
1533 length
= index
->index
;
1534 *next_block
= index
->start_block
+ sBlk
->directory_table_start
;
1537 *next_offset
= (length
+ *next_offset
) % SQUASHFS_METADATA_SIZE
;
1542 static int squashfs_readdir(struct file
*file
, void *dirent
, filldir_t filldir
)
1544 struct inode
*i
= file
->f_dentry
->d_inode
;
1545 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)i
->i_sb
->s_fs_info
;
1546 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1547 int next_block
= SQUASHFS_I(i
)->start_block
+ sBlk
->directory_table_start
, next_offset
=
1548 SQUASHFS_I(i
)->offset
, length
= 0, dirs_read
= 0, dir_count
;
1549 squashfs_dir_header dirh
;
1550 char buffer
[sizeof(squashfs_dir_entry
) + SQUASHFS_NAME_LEN
+ 1];
1551 squashfs_dir_entry
*dire
= (squashfs_dir_entry
*) buffer
;
1553 TRACE("Entered squashfs_readdir [%x:%x]\n", next_block
, next_offset
);
1557 length
= get_dir_index_using_offset(i
->i_sb
, &next_block
, &next_offset
, SQUASHFS_I(i
)->u
.s2
.directory_index_start
,
1558 SQUASHFS_I(i
)->u
.s2
.directory_index_offset
, SQUASHFS_I(i
)->u
.s2
.directory_index_count
, file
->f_pos
);
1560 while(length
< i
->i_size
) {
1561 /* read directory header */
1563 squashfs_dir_header sdirh
;
1564 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &sdirh
, next_block
,
1565 next_offset
, sizeof(sdirh
), &next_block
, &next_offset
))
1567 length
+= sizeof(sdirh
);
1568 SQUASHFS_SWAP_DIR_HEADER(&dirh
, &sdirh
);
1570 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &dirh
, next_block
,
1571 next_offset
, sizeof(dirh
), &next_block
, &next_offset
))
1573 length
+= sizeof(dirh
);
1576 dir_count
= dirh
.count
+ 1;
1577 while(dir_count
--) {
1579 squashfs_dir_entry sdire
;
1580 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &sdire
, next_block
,
1581 next_offset
, sizeof(sdire
), &next_block
, &next_offset
))
1583 length
+= sizeof(sdire
);
1584 SQUASHFS_SWAP_DIR_ENTRY(dire
, &sdire
);
1586 if(!squashfs_get_cached_block(i
->i_sb
, (char *) dire
, next_block
,
1587 next_offset
, sizeof(*dire
), &next_block
, &next_offset
))
1589 length
+= sizeof(*dire
);
1592 if(!squashfs_get_cached_block(i
->i_sb
, dire
->name
, next_block
,
1593 next_offset
, dire
->size
+ 1, &next_block
, &next_offset
))
1595 length
+= dire
->size
+ 1;
1597 if(file
->f_pos
>= length
)
1600 dire
->name
[dire
->size
+ 1] = '\0';
1602 TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent
,
1603 dire
->name
, dire
->size
+ 1, (int) file
->f_pos
,
1604 dirh
.start_block
, dire
->offset
, squashfs_filetype_table
[dire
->type
]);
1606 if(filldir(dirent
, dire
->name
, dire
->size
+ 1, file
->f_pos
, SQUASHFS_MK_VFS_INODE(dirh
.start_block
,
1607 dire
->offset
), squashfs_filetype_table
[dire
->type
]) < 0) {
1608 TRACE("Filldir returned less than 0\n");
1613 file
->f_pos
= length
;
1623 ERROR("Unable to read directory block [%x:%x]\n", next_block
, next_offset
);
1628 static struct dentry
*squashfs_lookup(struct inode
*i
, struct dentry
*dentry
, struct nameidata
*nd
)
1630 const unsigned char *name
=dentry
->d_name
.name
;
1631 int len
= dentry
->d_name
.len
;
1632 struct inode
*inode
= NULL
;
1633 squashfs_sb_info
*msBlk
= (squashfs_sb_info
*)i
->i_sb
->s_fs_info
;
1634 squashfs_super_block
*sBlk
= &msBlk
->sBlk
;
1635 int next_block
= SQUASHFS_I(i
)->start_block
+ sBlk
->directory_table_start
, next_offset
=
1636 SQUASHFS_I(i
)->offset
, length
= 0, dir_count
;
1637 squashfs_dir_header dirh
;
1638 char buffer
[sizeof(squashfs_dir_entry
) + SQUASHFS_NAME_LEN
];
1639 squashfs_dir_entry
*dire
= (squashfs_dir_entry
*) buffer
;
1640 int squashfs_2_1
= sBlk
->s_major
== 2 && sBlk
->s_minor
== 1;
1642 TRACE("Entered squashfs_lookup [%x:%x]\n", next_block
, next_offset
);
1644 if (len
> SQUASHFS_NAME_LEN
) return ERR_PTR(-ENAMETOOLONG
);
1648 length
= get_dir_index_using_name(i
->i_sb
, &next_block
, &next_offset
, SQUASHFS_I(i
)->u
.s2
.directory_index_start
,
1649 SQUASHFS_I(i
)->u
.s2
.directory_index_offset
, SQUASHFS_I(i
)->u
.s2
.directory_index_count
, name
, len
);
1651 while(length
< i
->i_size
) {
1652 /* read directory header */
1654 squashfs_dir_header sdirh
;
1655 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &sdirh
, next_block
, next_offset
,
1656 sizeof(sdirh
), &next_block
, &next_offset
))
1658 length
+= sizeof(sdirh
);
1659 SQUASHFS_SWAP_DIR_HEADER(&dirh
, &sdirh
);
1661 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &dirh
, next_block
, next_offset
,
1662 sizeof(dirh
), &next_block
, &next_offset
))
1664 length
+= sizeof(dirh
);
1667 dir_count
= dirh
.count
+ 1;
1668 while(dir_count
--) {
1670 squashfs_dir_entry sdire
;
1671 if(!squashfs_get_cached_block(i
->i_sb
, (char *) &sdire
,
1672 next_block
,next_offset
, sizeof(sdire
), &next_block
, &next_offset
))
1674 length
+= sizeof(sdire
);
1675 SQUASHFS_SWAP_DIR_ENTRY(dire
, &sdire
);
1677 if(!squashfs_get_cached_block(i
->i_sb
, (char *) dire
,
1678 next_block
,next_offset
, sizeof(*dire
), &next_block
, &next_offset
))
1680 length
+= sizeof(*dire
);
1683 if(!squashfs_get_cached_block(i
->i_sb
, dire
->name
,
1684 next_block
, next_offset
, dire
->size
+ 1, &next_block
, &next_offset
))
1686 length
+= dire
->size
+ 1;
1688 if(squashfs_2_1
&& name
[0] < dire
->name
[0])
1691 if((len
== dire
->size
+ 1) && !strncmp(name
, dire
->name
, len
)) {
1692 squashfs_inode ino
= SQUASHFS_MKINODE(dirh
.start_block
, dire
->offset
);
1694 TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n",
1695 name
, dirh
.start_block
, dire
->offset
);
1697 inode
= (msBlk
->iget
)(i
->i_sb
, ino
);
1705 d_add(dentry
, inode
);
1710 ERROR("Unable to read directory block [%x:%x]\n", next_block
, next_offset
);
1715 static void squashfs_put_super(struct super_block
*s
)
1720 squashfs_sb_info
*sbi
= (squashfs_sb_info
*) s
->s_fs_info
;
1721 if(sbi
->block_cache
) {
1722 for(i
= 0; i
< SQUASHFS_CACHED_BLKS
; i
++)
1723 if(sbi
->block_cache
[i
].block
!= SQUASHFS_INVALID_BLK
)
1724 kfree(sbi
->block_cache
[i
].data
);
1725 kfree(sbi
->block_cache
);
1727 if(sbi
->read_data
) kfree(sbi
->read_data
);
1728 if(sbi
->read_page
) kfree(sbi
->read_page
);
1729 if(sbi
->uid
) kfree(sbi
->uid
);
1731 for(i
= 0; i
< SQUASHFS_CACHED_FRAGMENTS
; i
++)
1732 if(sbi
->fragment
[i
].data
!= NULL
)
1733 SQUASHFS_FREE(sbi
->fragment
[i
].data
);
1734 kfree(sbi
->fragment
);
1736 if(sbi
->fragment_index
) kfree(sbi
->fragment_index
);
1737 kfree(s
->s_fs_info
);
1738 s
->s_fs_info
= NULL
;
1743 static int squashfs_get_sb(struct file_system_type
*fs_type
, int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
1745 return get_sb_bdev(fs_type
, flags
, dev_name
, data
, squashfs_fill_super
, mnt
);
1749 static int __init
init_squashfs_fs(void)
1751 int err
= init_inodecache();
1755 printk(KERN_INFO
"Squashfs 2.2-r2 (released 2005/09/08) (C) 2002-2005 Phillip Lougher\n");
1757 #ifdef CONFIG_SQUASHFS_LZMA
1758 printk(KERN_INFO
"Squashfs 2.2 includes LZMA decompression support\n");
1759 if(!(lzma_data
= (char *) vmalloc(lzma_workspace_size()))) {
1760 ERROR("Failed to allocate lzma workspace\n");
1763 lzma_init(lzma_data
, lzma_workspace_size());
1765 if(!(stream
.workspace
= (char *) vmalloc(zlib_inflate_workspacesize()))) {
1766 ERROR("Failed to allocate zlib workspace\n");
1767 destroy_inodecache();
1772 if((err
= register_filesystem(&squashfs_fs_type
))) {
1773 #ifndef CONFIG_SQUASHFS_LZMA
1774 vfree(stream
.workspace
);
1776 destroy_inodecache();
1783 static void __exit
exit_squashfs_fs(void)
1785 #ifdef CONFIG_SQUASHFS_LZMA
1788 vfree(stream
.workspace
);
1790 unregister_filesystem(&squashfs_fs_type
);
1791 destroy_inodecache();
1795 static kmem_cache_t
* squashfs_inode_cachep
;
1798 static struct inode
*squashfs_alloc_inode(struct super_block
*sb
)
1800 struct squashfs_inode_info
*ei
;
1801 ei
= (struct squashfs_inode_info
*)kmem_cache_alloc(squashfs_inode_cachep
, SLAB_KERNEL
);
1804 return &ei
->vfs_inode
;
1808 static void squashfs_destroy_inode(struct inode
*inode
)
1810 kmem_cache_free(squashfs_inode_cachep
, SQUASHFS_I(inode
));
1814 static void init_once(void * foo
, kmem_cache_t
* cachep
, unsigned long flags
)
1816 struct squashfs_inode_info
*ei
= (struct squashfs_inode_info
*) foo
;
1818 if ((flags
& (SLAB_CTOR_VERIFY
|SLAB_CTOR_CONSTRUCTOR
)) ==
1819 SLAB_CTOR_CONSTRUCTOR
)
1820 inode_init_once(&ei
->vfs_inode
);
1824 static int init_inodecache(void)
1826 squashfs_inode_cachep
= kmem_cache_create("squashfs_inode_cache",
1827 sizeof(struct squashfs_inode_info
),
1828 0, SLAB_HWCACHE_ALIGN
|SLAB_RECLAIM_ACCOUNT
,
1830 if (squashfs_inode_cachep
== NULL
)
1836 static void destroy_inodecache(void)
1838 kmem_cache_destroy(squashfs_inode_cachep
);
1842 module_init(init_squashfs_fs
);
1843 module_exit(exit_squashfs_fs
);
1844 MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
1845 MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
1846 MODULE_LICENSE("GPL");