10aeb6601e77c348064513052bf90a11952a190d0plougher/* 20aeb6601e77c348064513052bf90a11952a190d0plougher * Squashfs - a compressed read only filesystem for Linux 30aeb6601e77c348064513052bf90a11952a190d0plougher * 40aeb6601e77c348064513052bf90a11952a190d0plougher * Copyright (c) 2002, 2003, 2004, 2005, 2006 5f6cd337f8de328e2b448b9f29c00d9132748f7feplougher * Phillip Lougher <phillip@lougher.demon.co.uk> 60aeb6601e77c348064513052bf90a11952a190d0plougher * 70aeb6601e77c348064513052bf90a11952a190d0plougher * This program is free software; you can redistribute it and/or 80aeb6601e77c348064513052bf90a11952a190d0plougher * modify it under the terms of the GNU General Public License 90aeb6601e77c348064513052bf90a11952a190d0plougher * as published by the Free Software Foundation; either version 2, 100aeb6601e77c348064513052bf90a11952a190d0plougher * or (at your option) any later version. 110aeb6601e77c348064513052bf90a11952a190d0plougher * 120aeb6601e77c348064513052bf90a11952a190d0plougher * This program is distributed in the hope that it will be useful, 130aeb6601e77c348064513052bf90a11952a190d0plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 140aeb6601e77c348064513052bf90a11952a190d0plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150aeb6601e77c348064513052bf90a11952a190d0plougher * GNU General Public License for more details. 160aeb6601e77c348064513052bf90a11952a190d0plougher * 170aeb6601e77c348064513052bf90a11952a190d0plougher * You should have received a copy of the GNU General Public License 180aeb6601e77c348064513052bf90a11952a190d0plougher * along with this program; if not, write to the Free Software 190aeb6601e77c348064513052bf90a11952a190d0plougher * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 200aeb6601e77c348064513052bf90a11952a190d0plougher * 210aeb6601e77c348064513052bf90a11952a190d0plougher * inode.c 220aeb6601e77c348064513052bf90a11952a190d0plougher */ 230aeb6601e77c348064513052bf90a11952a190d0plougher 240aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/types.h> 250aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/squashfs_fs.h> 260aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/module.h> 270aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/errno.h> 280aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/slab.h> 29410dd958c15c73d91e877a0afe085bfaee37d9ffplougher#include <linux/zlib.h> 300aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/fs.h> 310aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/smp_lock.h> 320aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/locks.h> 330aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/init.h> 340aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/dcache.h> 350aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/wait.h> 360aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/blkdev.h> 370aeb6601e77c348064513052bf90a11952a190d0plougher#include <linux/vmalloc.h> 380aeb6601e77c348064513052bf90a11952a190d0plougher#include <asm/uaccess.h> 390aeb6601e77c348064513052bf90a11952a190d0plougher#include <asm/semaphore.h> 400aeb6601e77c348064513052bf90a11952a190d0plougher 410aeb6601e77c348064513052bf90a11952a190d0plougher#include "squashfs.h" 420aeb6601e77c348064513052bf90a11952a190d0plougher 430aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct super_block *squashfs_read_super(struct super_block *, void *, int); 440aeb6601e77c348064513052bf90a11952a190d0plougherstatic void squashfs_put_super(struct super_block *); 450aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_statfs(struct super_block *, struct statfs *); 460aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_symlink_readpage(struct file *file, struct page *page); 470aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readpage(struct file *file, struct page *page); 480aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readpage4K(struct file *file, struct page *page); 490aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readdir(struct file *, void *, filldir_t); 500aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct dentry *squashfs_lookup(struct inode *, struct dentry *); 510aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode); 520aeb6601e77c348064513052bf90a11952a190d0plougherstatic long long read_blocklist(struct inode *inode, int index, 530aeb6601e77c348064513052bf90a11952a190d0plougher int readahead_blks, char *block_list, 540aeb6601e77c348064513052bf90a11952a190d0plougher unsigned short **block_p, unsigned int *bsize); 550aeb6601e77c348064513052bf90a11952a190d0plougher 560aeb6601e77c348064513052bf90a11952a190d0plougherstatic DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super); 570aeb6601e77c348064513052bf90a11952a190d0plougher 580aeb6601e77c348064513052bf90a11952a190d0plougherstatic unsigned char squashfs_filetype_table[] = { 590aeb6601e77c348064513052bf90a11952a190d0plougher DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK 600aeb6601e77c348064513052bf90a11952a190d0plougher}; 610aeb6601e77c348064513052bf90a11952a190d0plougher 620aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct super_operations squashfs_ops = { 630aeb6601e77c348064513052bf90a11952a190d0plougher .statfs = squashfs_statfs, 640aeb6601e77c348064513052bf90a11952a190d0plougher .put_super = squashfs_put_super, 650aeb6601e77c348064513052bf90a11952a190d0plougher}; 660aeb6601e77c348064513052bf90a11952a190d0plougher 670aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { 680aeb6601e77c348064513052bf90a11952a190d0plougher .readpage = squashfs_symlink_readpage 690aeb6601e77c348064513052bf90a11952a190d0plougher}; 700aeb6601e77c348064513052bf90a11952a190d0plougher 710aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN struct address_space_operations squashfs_aops = { 720aeb6601e77c348064513052bf90a11952a190d0plougher .readpage = squashfs_readpage 730aeb6601e77c348064513052bf90a11952a190d0plougher}; 740aeb6601e77c348064513052bf90a11952a190d0plougher 750aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN struct address_space_operations squashfs_aops_4K = { 760aeb6601e77c348064513052bf90a11952a190d0plougher .readpage = squashfs_readpage4K 770aeb6601e77c348064513052bf90a11952a190d0plougher}; 780aeb6601e77c348064513052bf90a11952a190d0plougher 790aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct file_operations squashfs_dir_ops = { 800aeb6601e77c348064513052bf90a11952a190d0plougher .read = generic_read_dir, 810aeb6601e77c348064513052bf90a11952a190d0plougher .readdir = squashfs_readdir 820aeb6601e77c348064513052bf90a11952a190d0plougher}; 830aeb6601e77c348064513052bf90a11952a190d0plougher 840aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct inode_operations squashfs_dir_inode_ops = { 850aeb6601e77c348064513052bf90a11952a190d0plougher .lookup = squashfs_lookup 860aeb6601e77c348064513052bf90a11952a190d0plougher}; 870aeb6601e77c348064513052bf90a11952a190d0plougher 880aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct buffer_head *get_block_length(struct super_block *s, 890aeb6601e77c348064513052bf90a11952a190d0plougher int *cur_index, int *offset, int *c_byte) 900aeb6601e77c348064513052bf90a11952a190d0plougher{ 910aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 920aeb6601e77c348064513052bf90a11952a190d0plougher unsigned short temp; 930aeb6601e77c348064513052bf90a11952a190d0plougher struct buffer_head *bh; 940aeb6601e77c348064513052bf90a11952a190d0plougher 950aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh = sb_bread(s, *cur_index))) 960aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 970aeb6601e77c348064513052bf90a11952a190d0plougher 980aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->devblksize - *offset == 1) { 990aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) 1000aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[1] = *((unsigned char *) 1010aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset)); 1020aeb6601e77c348064513052bf90a11952a190d0plougher else 1030aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[0] = *((unsigned char *) 1040aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset)); 1050aeb6601e77c348064513052bf90a11952a190d0plougher brelse(bh); 1060aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh = sb_bread(s, ++(*cur_index)))) 1070aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 1080aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) 1090aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[0] = *((unsigned char *) 1100aeb6601e77c348064513052bf90a11952a190d0plougher bh->b_data); 1110aeb6601e77c348064513052bf90a11952a190d0plougher else 1120aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[1] = *((unsigned char *) 1130aeb6601e77c348064513052bf90a11952a190d0plougher bh->b_data); 1140aeb6601e77c348064513052bf90a11952a190d0plougher *c_byte = temp; 1150aeb6601e77c348064513052bf90a11952a190d0plougher *offset = 1; 1160aeb6601e77c348064513052bf90a11952a190d0plougher } else { 1170aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 1180aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[1] = *((unsigned char *) 1190aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset)); 1200aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[0] = *((unsigned char *) 1210aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset + 1)); 1220aeb6601e77c348064513052bf90a11952a190d0plougher } else { 1230aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[0] = *((unsigned char *) 1240aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset)); 1250aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned char *) &temp)[1] = *((unsigned char *) 1260aeb6601e77c348064513052bf90a11952a190d0plougher (bh->b_data + *offset + 1)); 1270aeb6601e77c348064513052bf90a11952a190d0plougher } 1280aeb6601e77c348064513052bf90a11952a190d0plougher *c_byte = temp; 1290aeb6601e77c348064513052bf90a11952a190d0plougher *offset += 2; 1300aeb6601e77c348064513052bf90a11952a190d0plougher } 1310aeb6601e77c348064513052bf90a11952a190d0plougher 1320aeb6601e77c348064513052bf90a11952a190d0plougher if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { 1330aeb6601e77c348064513052bf90a11952a190d0plougher if (*offset == msblk->devblksize) { 1340aeb6601e77c348064513052bf90a11952a190d0plougher brelse(bh); 1350aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh = sb_bread(s, ++(*cur_index)))) 1360aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 1370aeb6601e77c348064513052bf90a11952a190d0plougher *offset = 0; 1380aeb6601e77c348064513052bf90a11952a190d0plougher } 1390aeb6601e77c348064513052bf90a11952a190d0plougher if (*((unsigned char *) (bh->b_data + *offset)) != 1400aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_MARKER_BYTE) { 1410aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Metadata block marker corrupt @ %x\n", 1420aeb6601e77c348064513052bf90a11952a190d0plougher *cur_index); 1430aeb6601e77c348064513052bf90a11952a190d0plougher brelse(bh); 1440aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 1450aeb6601e77c348064513052bf90a11952a190d0plougher } 1460aeb6601e77c348064513052bf90a11952a190d0plougher (*offset)++; 1470aeb6601e77c348064513052bf90a11952a190d0plougher } 1480aeb6601e77c348064513052bf90a11952a190d0plougher return bh; 1490aeb6601e77c348064513052bf90a11952a190d0plougher 1500aeb6601e77c348064513052bf90a11952a190d0plougherout: 1510aeb6601e77c348064513052bf90a11952a190d0plougher return NULL; 1520aeb6601e77c348064513052bf90a11952a190d0plougher} 1530aeb6601e77c348064513052bf90a11952a190d0plougher 1540aeb6601e77c348064513052bf90a11952a190d0plougher 1550aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, 1560aeb6601e77c348064513052bf90a11952a190d0plougher long long index, unsigned int length, 1570aeb6601e77c348064513052bf90a11952a190d0plougher long long *next_index) 1580aeb6601e77c348064513052bf90a11952a190d0plougher{ 1590aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 1600aeb6601e77c348064513052bf90a11952a190d0plougher struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> 1610aeb6601e77c348064513052bf90a11952a190d0plougher msblk->devblksize_log2) + 2]; 1620aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); 1630aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int cur_index = index >> msblk->devblksize_log2; 1640aeb6601e77c348064513052bf90a11952a190d0plougher int bytes, avail_bytes, b = 0, k; 1650aeb6601e77c348064513052bf90a11952a190d0plougher char *c_buffer; 1660aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int compressed; 1670aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int c_byte = length; 1680aeb6601e77c348064513052bf90a11952a190d0plougher 1690aeb6601e77c348064513052bf90a11952a190d0plougher if (c_byte) { 1700aeb6601e77c348064513052bf90a11952a190d0plougher bytes = msblk->devblksize - offset; 1710aeb6601e77c348064513052bf90a11952a190d0plougher compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); 1720aeb6601e77c348064513052bf90a11952a190d0plougher c_buffer = compressed ? msblk->read_data : buffer; 1730aeb6601e77c348064513052bf90a11952a190d0plougher c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); 1740aeb6601e77c348064513052bf90a11952a190d0plougher 1750aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed 1760aeb6601e77c348064513052bf90a11952a190d0plougher ? "" : "un", (unsigned int) c_byte); 1770aeb6601e77c348064513052bf90a11952a190d0plougher 1780aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh[0] = sb_getblk(s, cur_index))) 1790aeb6601e77c348064513052bf90a11952a190d0plougher goto block_release; 1800aeb6601e77c348064513052bf90a11952a190d0plougher 1810aeb6601e77c348064513052bf90a11952a190d0plougher for (b = 1; bytes < c_byte; b++) { 1820aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh[b] = sb_getblk(s, ++cur_index))) 1830aeb6601e77c348064513052bf90a11952a190d0plougher goto block_release; 1840aeb6601e77c348064513052bf90a11952a190d0plougher bytes += msblk->devblksize; 1850aeb6601e77c348064513052bf90a11952a190d0plougher } 1860aeb6601e77c348064513052bf90a11952a190d0plougher ll_rw_block(READ, b, bh); 1870aeb6601e77c348064513052bf90a11952a190d0plougher } else { 1880aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh[0] = get_block_length(s, &cur_index, &offset, 1890aeb6601e77c348064513052bf90a11952a190d0plougher &c_byte))) 1900aeb6601e77c348064513052bf90a11952a190d0plougher goto read_failure; 1910aeb6601e77c348064513052bf90a11952a190d0plougher 1920aeb6601e77c348064513052bf90a11952a190d0plougher bytes = msblk->devblksize - offset; 1930aeb6601e77c348064513052bf90a11952a190d0plougher compressed = SQUASHFS_COMPRESSED(c_byte); 1940aeb6601e77c348064513052bf90a11952a190d0plougher c_buffer = compressed ? msblk->read_data : buffer; 1950aeb6601e77c348064513052bf90a11952a190d0plougher c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); 1960aeb6601e77c348064513052bf90a11952a190d0plougher 1970aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed 1980aeb6601e77c348064513052bf90a11952a190d0plougher ? "" : "un", (unsigned int) c_byte); 1990aeb6601e77c348064513052bf90a11952a190d0plougher 2000aeb6601e77c348064513052bf90a11952a190d0plougher for (b = 1; bytes < c_byte; b++) { 2010aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bh[b] = sb_getblk(s, ++cur_index))) 2020aeb6601e77c348064513052bf90a11952a190d0plougher goto block_release; 2030aeb6601e77c348064513052bf90a11952a190d0plougher bytes += msblk->devblksize; 2040aeb6601e77c348064513052bf90a11952a190d0plougher } 2050aeb6601e77c348064513052bf90a11952a190d0plougher ll_rw_block(READ, b - 1, bh + 1); 2060aeb6601e77c348064513052bf90a11952a190d0plougher } 2070aeb6601e77c348064513052bf90a11952a190d0plougher 2080aeb6601e77c348064513052bf90a11952a190d0plougher if (compressed) 2090aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->read_data_mutex); 2100aeb6601e77c348064513052bf90a11952a190d0plougher 2110aeb6601e77c348064513052bf90a11952a190d0plougher for (bytes = 0, k = 0; k < b; k++) { 2120aeb6601e77c348064513052bf90a11952a190d0plougher avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? 2130aeb6601e77c348064513052bf90a11952a190d0plougher msblk->devblksize - offset : 2140aeb6601e77c348064513052bf90a11952a190d0plougher c_byte - bytes; 2150aeb6601e77c348064513052bf90a11952a190d0plougher wait_on_buffer(bh[k]); 2160aeb6601e77c348064513052bf90a11952a190d0plougher if (!buffer_uptodate(bh[k])) 2170aeb6601e77c348064513052bf90a11952a190d0plougher goto block_release; 2180aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes); 2190aeb6601e77c348064513052bf90a11952a190d0plougher bytes += avail_bytes; 2200aeb6601e77c348064513052bf90a11952a190d0plougher offset = 0; 2210aeb6601e77c348064513052bf90a11952a190d0plougher brelse(bh[k]); 2220aeb6601e77c348064513052bf90a11952a190d0plougher } 2230aeb6601e77c348064513052bf90a11952a190d0plougher 2240aeb6601e77c348064513052bf90a11952a190d0plougher /* 2250aeb6601e77c348064513052bf90a11952a190d0plougher * uncompress block 2260aeb6601e77c348064513052bf90a11952a190d0plougher */ 2270aeb6601e77c348064513052bf90a11952a190d0plougher if (compressed) { 2280aeb6601e77c348064513052bf90a11952a190d0plougher int zlib_err; 2290aeb6601e77c348064513052bf90a11952a190d0plougher 230410dd958c15c73d91e877a0afe085bfaee37d9ffplougher msblk->stream.next_in = c_buffer; 231410dd958c15c73d91e877a0afe085bfaee37d9ffplougher msblk->stream.avail_in = c_byte; 232410dd958c15c73d91e877a0afe085bfaee37d9ffplougher msblk->stream.next_out = buffer; 233410dd958c15c73d91e877a0afe085bfaee37d9ffplougher msblk->stream.avail_out = msblk->read_size; 2340aeb6601e77c348064513052bf90a11952a190d0plougher 235410dd958c15c73d91e877a0afe085bfaee37d9ffplougher if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) || 236410dd958c15c73d91e877a0afe085bfaee37d9ffplougher ((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH)) 2370aeb6601e77c348064513052bf90a11952a190d0plougher != Z_STREAM_END) || ((zlib_err = 238410dd958c15c73d91e877a0afe085bfaee37d9ffplougher zlib_inflateEnd(&msblk->stream)) != Z_OK)) { 2390aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("zlib_fs returned unexpected result 0x%x\n", 2400aeb6601e77c348064513052bf90a11952a190d0plougher zlib_err); 2410aeb6601e77c348064513052bf90a11952a190d0plougher bytes = 0; 2420aeb6601e77c348064513052bf90a11952a190d0plougher } else 243410dd958c15c73d91e877a0afe085bfaee37d9ffplougher bytes = msblk->stream.total_out; 2440aeb6601e77c348064513052bf90a11952a190d0plougher 2450aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->read_data_mutex); 2460aeb6601e77c348064513052bf90a11952a190d0plougher } 2470aeb6601e77c348064513052bf90a11952a190d0plougher 2480aeb6601e77c348064513052bf90a11952a190d0plougher if (next_index) 2490aeb6601e77c348064513052bf90a11952a190d0plougher *next_index = index + c_byte + (length ? 0 : 2500aeb6601e77c348064513052bf90a11952a190d0plougher (SQUASHFS_CHECK_DATA(msblk->sblk.flags) 2510aeb6601e77c348064513052bf90a11952a190d0plougher ? 3 : 2)); 2520aeb6601e77c348064513052bf90a11952a190d0plougher return bytes; 2530aeb6601e77c348064513052bf90a11952a190d0plougher 2540aeb6601e77c348064513052bf90a11952a190d0plougherblock_release: 2550aeb6601e77c348064513052bf90a11952a190d0plougher while (--b >= 0) 2560aeb6601e77c348064513052bf90a11952a190d0plougher brelse(bh[b]); 2570aeb6601e77c348064513052bf90a11952a190d0plougher 2580aeb6601e77c348064513052bf90a11952a190d0plougherread_failure: 2590aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("sb_bread failed reading block 0x%x\n", cur_index); 2600aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 2610aeb6601e77c348064513052bf90a11952a190d0plougher} 2620aeb6601e77c348064513052bf90a11952a190d0plougher 2630aeb6601e77c348064513052bf90a11952a190d0plougher 2640aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer, 2650aeb6601e77c348064513052bf90a11952a190d0plougher long long block, unsigned int offset, 2660aeb6601e77c348064513052bf90a11952a190d0plougher int length, long long *next_block, 2670aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int *next_offset) 2680aeb6601e77c348064513052bf90a11952a190d0plougher{ 2690aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 2700aeb6601e77c348064513052bf90a11952a190d0plougher int n, i, bytes, return_length = length; 2710aeb6601e77c348064513052bf90a11952a190d0plougher long long next_index; 2720aeb6601e77c348064513052bf90a11952a190d0plougher 2730aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); 2740aeb6601e77c348064513052bf90a11952a190d0plougher 2750aeb6601e77c348064513052bf90a11952a190d0plougher while ( 1 ) { 2760aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 2770aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->block_cache[i].block == block) 2780aeb6601e77c348064513052bf90a11952a190d0plougher break; 2790aeb6601e77c348064513052bf90a11952a190d0plougher 2800aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->block_cache_mutex); 2810aeb6601e77c348064513052bf90a11952a190d0plougher 2820aeb6601e77c348064513052bf90a11952a190d0plougher if (i == SQUASHFS_CACHED_BLKS) { 2830aeb6601e77c348064513052bf90a11952a190d0plougher /* read inode header block */ 2840aeb6601e77c348064513052bf90a11952a190d0plougher for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS; 2850aeb6601e77c348064513052bf90a11952a190d0plougher n ; n --, i = (i + 1) % 2860aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_BLKS) 2870aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->block_cache[i].block != 2880aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_USED_BLK) 2890aeb6601e77c348064513052bf90a11952a190d0plougher break; 2900aeb6601e77c348064513052bf90a11952a190d0plougher 2910aeb6601e77c348064513052bf90a11952a190d0plougher if (n == 0) { 2920aeb6601e77c348064513052bf90a11952a190d0plougher wait_queue_t wait; 2930aeb6601e77c348064513052bf90a11952a190d0plougher 2940aeb6601e77c348064513052bf90a11952a190d0plougher init_waitqueue_entry(&wait, current); 2950aeb6601e77c348064513052bf90a11952a190d0plougher add_wait_queue(&msblk->waitq, &wait); 2960aeb6601e77c348064513052bf90a11952a190d0plougher set_current_state(TASK_UNINTERRUPTIBLE); 2970aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 2980aeb6601e77c348064513052bf90a11952a190d0plougher schedule(); 2990aeb6601e77c348064513052bf90a11952a190d0plougher set_current_state(TASK_RUNNING); 3000aeb6601e77c348064513052bf90a11952a190d0plougher remove_wait_queue(&msblk->waitq, &wait); 3010aeb6601e77c348064513052bf90a11952a190d0plougher continue; 3020aeb6601e77c348064513052bf90a11952a190d0plougher } 3030aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS; 3040aeb6601e77c348064513052bf90a11952a190d0plougher 3050aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->block_cache[i].block == 3060aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INVALID_BLK) { 3070aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->block_cache[i].data = 3080aeb6601e77c348064513052bf90a11952a190d0plougher kmalloc(SQUASHFS_METADATA_SIZE, 3090aeb6601e77c348064513052bf90a11952a190d0plougher GFP_KERNEL))) { 3100aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate cache" 3110aeb6601e77c348064513052bf90a11952a190d0plougher "block\n"); 3120aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 3130aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 3140aeb6601e77c348064513052bf90a11952a190d0plougher } 3150aeb6601e77c348064513052bf90a11952a190d0plougher } 3160aeb6601e77c348064513052bf90a11952a190d0plougher 3170aeb6601e77c348064513052bf90a11952a190d0plougher msblk->block_cache[i].block = SQUASHFS_USED_BLK; 3180aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 3190aeb6601e77c348064513052bf90a11952a190d0plougher 3200aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->block_cache[i].length = 3210aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_read_data(s, 3220aeb6601e77c348064513052bf90a11952a190d0plougher msblk->block_cache[i].data, 3230aeb6601e77c348064513052bf90a11952a190d0plougher block, 0, &next_index))) { 3240aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read cache block [%llx:%x]\n", 3250aeb6601e77c348064513052bf90a11952a190d0plougher block, offset); 3260aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 3270aeb6601e77c348064513052bf90a11952a190d0plougher } 3280aeb6601e77c348064513052bf90a11952a190d0plougher 3290aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->block_cache_mutex); 3300aeb6601e77c348064513052bf90a11952a190d0plougher wake_up(&msblk->waitq); 3310aeb6601e77c348064513052bf90a11952a190d0plougher msblk->block_cache[i].block = block; 3320aeb6601e77c348064513052bf90a11952a190d0plougher msblk->block_cache[i].next_index = next_index; 3330aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Read cache block [%llx:%x]\n", block, offset); 3340aeb6601e77c348064513052bf90a11952a190d0plougher } 3350aeb6601e77c348064513052bf90a11952a190d0plougher 3360aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->block_cache[i].block != block) { 3370aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 3380aeb6601e77c348064513052bf90a11952a190d0plougher continue; 3390aeb6601e77c348064513052bf90a11952a190d0plougher } 3400aeb6601e77c348064513052bf90a11952a190d0plougher 3410aeb6601e77c348064513052bf90a11952a190d0plougher if ((bytes = msblk->block_cache[i].length - offset) >= length) { 3420aeb6601e77c348064513052bf90a11952a190d0plougher if (buffer) 3430aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(buffer, msblk->block_cache[i].data + 3440aeb6601e77c348064513052bf90a11952a190d0plougher offset, length); 3450aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->block_cache[i].length - offset == length) { 3460aeb6601e77c348064513052bf90a11952a190d0plougher *next_block = msblk->block_cache[i].next_index; 3470aeb6601e77c348064513052bf90a11952a190d0plougher *next_offset = 0; 3480aeb6601e77c348064513052bf90a11952a190d0plougher } else { 3490aeb6601e77c348064513052bf90a11952a190d0plougher *next_block = block; 3500aeb6601e77c348064513052bf90a11952a190d0plougher *next_offset = offset + length; 3510aeb6601e77c348064513052bf90a11952a190d0plougher } 3520aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 3530aeb6601e77c348064513052bf90a11952a190d0plougher goto finish; 3540aeb6601e77c348064513052bf90a11952a190d0plougher } else { 3550aeb6601e77c348064513052bf90a11952a190d0plougher if (buffer) { 3560aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(buffer, msblk->block_cache[i].data + 3570aeb6601e77c348064513052bf90a11952a190d0plougher offset, bytes); 3580aeb6601e77c348064513052bf90a11952a190d0plougher buffer += bytes; 3590aeb6601e77c348064513052bf90a11952a190d0plougher } 3600aeb6601e77c348064513052bf90a11952a190d0plougher block = msblk->block_cache[i].next_index; 3610aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->block_cache_mutex); 3620aeb6601e77c348064513052bf90a11952a190d0plougher length -= bytes; 3630aeb6601e77c348064513052bf90a11952a190d0plougher offset = 0; 3640aeb6601e77c348064513052bf90a11952a190d0plougher } 3650aeb6601e77c348064513052bf90a11952a190d0plougher } 3660aeb6601e77c348064513052bf90a11952a190d0plougher 3670aeb6601e77c348064513052bf90a11952a190d0plougherfinish: 3680aeb6601e77c348064513052bf90a11952a190d0plougher return return_length; 3690aeb6601e77c348064513052bf90a11952a190d0plougherout: 3700aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 3710aeb6601e77c348064513052bf90a11952a190d0plougher} 3720aeb6601e77c348064513052bf90a11952a190d0plougher 3730aeb6601e77c348064513052bf90a11952a190d0plougher 3740aeb6601e77c348064513052bf90a11952a190d0plougherstatic int get_fragment_location(struct super_block *s, unsigned int fragment, 3750aeb6601e77c348064513052bf90a11952a190d0plougher long long *fragment_start_block, 3760aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int *fragment_size) 3770aeb6601e77c348064513052bf90a11952a190d0plougher{ 3780aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 3790aeb6601e77c348064513052bf90a11952a190d0plougher long long start_block = 3800aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; 3810aeb6601e77c348064513052bf90a11952a190d0plougher int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); 3820aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_fragment_entry fragment_entry; 3830aeb6601e77c348064513052bf90a11952a190d0plougher 3840aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 3850aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_fragment_entry sfragment_entry; 3860aeb6601e77c348064513052bf90a11952a190d0plougher 3870aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, 3880aeb6601e77c348064513052bf90a11952a190d0plougher start_block, offset, 3890aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(sfragment_entry), &start_block, 3900aeb6601e77c348064513052bf90a11952a190d0plougher &offset)) 3910aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 3920aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); 3930aeb6601e77c348064513052bf90a11952a190d0plougher } else 3940aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) &fragment_entry, 3950aeb6601e77c348064513052bf90a11952a190d0plougher start_block, offset, 3960aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(fragment_entry), &start_block, 3970aeb6601e77c348064513052bf90a11952a190d0plougher &offset)) 3980aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 3990aeb6601e77c348064513052bf90a11952a190d0plougher 4000aeb6601e77c348064513052bf90a11952a190d0plougher *fragment_start_block = fragment_entry.start_block; 4010aeb6601e77c348064513052bf90a11952a190d0plougher *fragment_size = fragment_entry.size; 4020aeb6601e77c348064513052bf90a11952a190d0plougher 4030aeb6601e77c348064513052bf90a11952a190d0plougher return 1; 4040aeb6601e77c348064513052bf90a11952a190d0plougher 4050aeb6601e77c348064513052bf90a11952a190d0plougherout: 4060aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 4070aeb6601e77c348064513052bf90a11952a190d0plougher} 4080aeb6601e77c348064513052bf90a11952a190d0plougher 4090aeb6601e77c348064513052bf90a11952a190d0plougher 4100aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct 4110aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_fragment_cache *fragment) 4120aeb6601e77c348064513052bf90a11952a190d0plougher{ 4130aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->fragment_mutex); 4140aeb6601e77c348064513052bf90a11952a190d0plougher fragment->locked --; 4150aeb6601e77c348064513052bf90a11952a190d0plougher wake_up(&msblk->fragment_wait_queue); 4160aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->fragment_mutex); 4170aeb6601e77c348064513052bf90a11952a190d0plougher} 4180aeb6601e77c348064513052bf90a11952a190d0plougher 4190aeb6601e77c348064513052bf90a11952a190d0plougher 4200aeb6601e77c348064513052bf90a11952a190d0plougherSQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block 4210aeb6601e77c348064513052bf90a11952a190d0plougher *s, long long start_block, 4220aeb6601e77c348064513052bf90a11952a190d0plougher int length) 4230aeb6601e77c348064513052bf90a11952a190d0plougher{ 4240aeb6601e77c348064513052bf90a11952a190d0plougher int i, n; 4250aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 4260aeb6601e77c348064513052bf90a11952a190d0plougher 4270aeb6601e77c348064513052bf90a11952a190d0plougher while ( 1 ) { 4280aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->fragment_mutex); 4290aeb6601e77c348064513052bf90a11952a190d0plougher 4300aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && 4310aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].block != start_block; i++); 4320aeb6601e77c348064513052bf90a11952a190d0plougher 4330aeb6601e77c348064513052bf90a11952a190d0plougher if (i == SQUASHFS_CACHED_FRAGMENTS) { 4340aeb6601e77c348064513052bf90a11952a190d0plougher for (i = msblk->next_fragment, n = 4350aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_FRAGMENTS; n && 4360aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked; n--, i = (i + 1) % 4370aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_FRAGMENTS); 4380aeb6601e77c348064513052bf90a11952a190d0plougher 4390aeb6601e77c348064513052bf90a11952a190d0plougher if (n == 0) { 4400aeb6601e77c348064513052bf90a11952a190d0plougher wait_queue_t wait; 4410aeb6601e77c348064513052bf90a11952a190d0plougher 4420aeb6601e77c348064513052bf90a11952a190d0plougher init_waitqueue_entry(&wait, current); 4430aeb6601e77c348064513052bf90a11952a190d0plougher add_wait_queue(&msblk->fragment_wait_queue, 4440aeb6601e77c348064513052bf90a11952a190d0plougher &wait); 4450aeb6601e77c348064513052bf90a11952a190d0plougher set_current_state(TASK_UNINTERRUPTIBLE); 4460aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->fragment_mutex); 4470aeb6601e77c348064513052bf90a11952a190d0plougher schedule(); 4480aeb6601e77c348064513052bf90a11952a190d0plougher set_current_state(TASK_RUNNING); 4490aeb6601e77c348064513052bf90a11952a190d0plougher remove_wait_queue(&msblk->fragment_wait_queue, 4500aeb6601e77c348064513052bf90a11952a190d0plougher &wait); 4510aeb6601e77c348064513052bf90a11952a190d0plougher continue; 4520aeb6601e77c348064513052bf90a11952a190d0plougher } 4530aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_fragment = (msblk->next_fragment + 1) % 4540aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_FRAGMENTS; 4550aeb6601e77c348064513052bf90a11952a190d0plougher 4560aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->fragment[i].data == NULL) 457af371d91a8865df5ab3079887b86c76a48b6e405plougher if (!(msblk->fragment[i].data = SQUASHFS_ALLOC 458af371d91a8865df5ab3079887b86c76a48b6e405plougher (SQUASHFS_FILE_MAX_SIZE))) { 4590aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate fragment " 4600aeb6601e77c348064513052bf90a11952a190d0plougher "cache block\n"); 4610aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->fragment_mutex); 4620aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 4630aeb6601e77c348064513052bf90a11952a190d0plougher } 4640aeb6601e77c348064513052bf90a11952a190d0plougher 4650aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].block = SQUASHFS_INVALID_BLK; 4660aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked = 1; 4670aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->fragment_mutex); 4680aeb6601e77c348064513052bf90a11952a190d0plougher 4690aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->fragment[i].length = squashfs_read_data(s, 4700aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].data, 4710aeb6601e77c348064513052bf90a11952a190d0plougher start_block, length, NULL))) { 4720aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read fragment cache block " 4730aeb6601e77c348064513052bf90a11952a190d0plougher "[%llx]\n", start_block); 4740aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked = 0; 4750aeb6601e77c348064513052bf90a11952a190d0plougher goto out; 4760aeb6601e77c348064513052bf90a11952a190d0plougher } 4770aeb6601e77c348064513052bf90a11952a190d0plougher 4780aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].block = start_block; 4790aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("New fragment %d, start block %lld, locked %d\n", 4800aeb6601e77c348064513052bf90a11952a190d0plougher i, msblk->fragment[i].block, 4810aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked); 4820aeb6601e77c348064513052bf90a11952a190d0plougher break; 4830aeb6601e77c348064513052bf90a11952a190d0plougher } 4840aeb6601e77c348064513052bf90a11952a190d0plougher 4850aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked++; 4860aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->fragment_mutex); 4870aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Got fragment %d, start block %lld, locked %d\n", i, 4880aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].block, 4890aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked); 4900aeb6601e77c348064513052bf90a11952a190d0plougher break; 4910aeb6601e77c348064513052bf90a11952a190d0plougher } 4920aeb6601e77c348064513052bf90a11952a190d0plougher 4930aeb6601e77c348064513052bf90a11952a190d0plougher return &msblk->fragment[i]; 4940aeb6601e77c348064513052bf90a11952a190d0plougher 4950aeb6601e77c348064513052bf90a11952a190d0plougherout: 4960aeb6601e77c348064513052bf90a11952a190d0plougher return NULL; 4970aeb6601e77c348064513052bf90a11952a190d0plougher} 4980aeb6601e77c348064513052bf90a11952a190d0plougher 4990aeb6601e77c348064513052bf90a11952a190d0plougher 5000aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct inode *squashfs_new_inode(struct super_block *s, 5010aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_base_inode_header *inodeb) 5020aeb6601e77c348064513052bf90a11952a190d0plougher{ 5030aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 5040aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *i = new_inode(s); 5050aeb6601e77c348064513052bf90a11952a190d0plougher 5060aeb6601e77c348064513052bf90a11952a190d0plougher if (i) { 5070aeb6601e77c348064513052bf90a11952a190d0plougher i->i_ino = inodeb->inode_number; 5080aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mtime = inodeb->mtime; 5090aeb6601e77c348064513052bf90a11952a190d0plougher i->i_atime = inodeb->mtime; 5100aeb6601e77c348064513052bf90a11952a190d0plougher i->i_ctime = inodeb->mtime; 5110aeb6601e77c348064513052bf90a11952a190d0plougher i->i_uid = msblk->uid[inodeb->uid]; 5120aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode = inodeb->mode; 5130aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = 0; 5140aeb6601e77c348064513052bf90a11952a190d0plougher if (inodeb->guid == SQUASHFS_GUIDS) 5150aeb6601e77c348064513052bf90a11952a190d0plougher i->i_gid = i->i_uid; 5160aeb6601e77c348064513052bf90a11952a190d0plougher else 5170aeb6601e77c348064513052bf90a11952a190d0plougher i->i_gid = msblk->guid[inodeb->guid]; 5180aeb6601e77c348064513052bf90a11952a190d0plougher } 5190aeb6601e77c348064513052bf90a11952a190d0plougher 5200aeb6601e77c348064513052bf90a11952a190d0plougher return i; 5210aeb6601e77c348064513052bf90a11952a190d0plougher} 5220aeb6601e77c348064513052bf90a11952a190d0plougher 5230aeb6601e77c348064513052bf90a11952a190d0plougher 5240aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode) 5250aeb6601e77c348064513052bf90a11952a190d0plougher{ 5260aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *i; 5270aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 5280aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 5290aeb6601e77c348064513052bf90a11952a190d0plougher long long block = SQUASHFS_INODE_BLK(inode) + 5300aeb6601e77c348064513052bf90a11952a190d0plougher sblk->inode_table_start; 5310aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int offset = SQUASHFS_INODE_OFFSET(inode); 5320aeb6601e77c348064513052bf90a11952a190d0plougher long long next_block; 5330aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int next_offset; 5340aeb6601e77c348064513052bf90a11952a190d0plougher union squashfs_inode_header id, sid; 5350aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_base_inode_header *inodeb = &id.base, 5360aeb6601e77c348064513052bf90a11952a190d0plougher *sinodeb = &sid.base; 5370aeb6601e77c348064513052bf90a11952a190d0plougher 5380aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_iget\n"); 5390aeb6601e77c348064513052bf90a11952a190d0plougher 5400aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 5410aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) sinodeb, block, 5420aeb6601e77c348064513052bf90a11952a190d0plougher offset, sizeof(*sinodeb), &next_block, 5430aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 5440aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 5450aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, 5460aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodeb)); 5470aeb6601e77c348064513052bf90a11952a190d0plougher } else 5480aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) inodeb, block, 5490aeb6601e77c348064513052bf90a11952a190d0plougher offset, sizeof(*inodeb), &next_block, 5500aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 5510aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 5520aeb6601e77c348064513052bf90a11952a190d0plougher 5530aeb6601e77c348064513052bf90a11952a190d0plougher switch(inodeb->inode_type) { 5540aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_FILE_TYPE: { 5550aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int frag_size; 5560aeb6601e77c348064513052bf90a11952a190d0plougher long long frag_blk; 5570aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_reg_inode_header *inodep = &id.reg; 5580aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_reg_inode_header *sinodep = &sid.reg; 5590aeb6601e77c348064513052bf90a11952a190d0plougher 5600aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 5610aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 5620aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 5630aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 5640aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 5650aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 5660aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); 5670aeb6601e77c348064513052bf90a11952a190d0plougher } else 5680aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 5690aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 5700aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 5710aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 5720aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 5730aeb6601e77c348064513052bf90a11952a190d0plougher 5740aeb6601e77c348064513052bf90a11952a190d0plougher frag_blk = SQUASHFS_INVALID_BLK; 5750aeb6601e77c348064513052bf90a11952a190d0plougher if (inodep->fragment != SQUASHFS_INVALID_FRAG && 5760aeb6601e77c348064513052bf90a11952a190d0plougher !get_fragment_location(s, 5770aeb6601e77c348064513052bf90a11952a190d0plougher inodep->fragment, &frag_blk, &frag_size)) 5780aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 5790aeb6601e77c348064513052bf90a11952a190d0plougher 5800aeb6601e77c348064513052bf90a11952a190d0plougher if((i = squashfs_new_inode(s, inodeb)) == NULL) 5810aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 5820aeb6601e77c348064513052bf90a11952a190d0plougher 5830aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = 1; 5840aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = inodep->file_size; 5850aeb6601e77c348064513052bf90a11952a190d0plougher i->i_fop = &generic_ro_fops; 5860aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= S_IFREG; 5870aeb6601e77c348064513052bf90a11952a190d0plougher i->i_blocks = ((i->i_size - 1) >> 9) + 1; 5880aeb6601e77c348064513052bf90a11952a190d0plougher i->i_blksize = PAGE_CACHE_SIZE; 5890aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; 5900aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_size = frag_size; 5910aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; 5920aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->start_block = inodep->start_block; 5930aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.block_list_start = next_block; 5940aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->offset = next_offset; 5950aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->block_size > 4096) 5960aeb6601e77c348064513052bf90a11952a190d0plougher i->i_data.a_ops = &squashfs_aops; 5970aeb6601e77c348064513052bf90a11952a190d0plougher else 5980aeb6601e77c348064513052bf90a11952a190d0plougher i->i_data.a_ops = &squashfs_aops_4K; 5990aeb6601e77c348064513052bf90a11952a190d0plougher 6000aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("File inode %x:%x, start_block %llx, " 6010aeb6601e77c348064513052bf90a11952a190d0plougher "block_list_start %llx, offset %x\n", 6020aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INODE_BLK(inode), offset, 6030aeb6601e77c348064513052bf90a11952a190d0plougher inodep->start_block, next_block, 6040aeb6601e77c348064513052bf90a11952a190d0plougher next_offset); 6050aeb6601e77c348064513052bf90a11952a190d0plougher break; 6060aeb6601e77c348064513052bf90a11952a190d0plougher } 6070aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_LREG_TYPE: { 6080aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int frag_size; 6090aeb6601e77c348064513052bf90a11952a190d0plougher long long frag_blk; 6100aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_lreg_inode_header *inodep = &id.lreg; 6110aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_lreg_inode_header *sinodep = &sid.lreg; 6120aeb6601e77c348064513052bf90a11952a190d0plougher 6130aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 6140aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 6150aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 6160aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 6170aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 6180aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 6190aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); 6200aeb6601e77c348064513052bf90a11952a190d0plougher } else 6210aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 6220aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 6230aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 6240aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 6250aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 6260aeb6601e77c348064513052bf90a11952a190d0plougher 6270aeb6601e77c348064513052bf90a11952a190d0plougher frag_blk = SQUASHFS_INVALID_BLK; 6280aeb6601e77c348064513052bf90a11952a190d0plougher if (inodep->fragment != SQUASHFS_INVALID_FRAG && 6290aeb6601e77c348064513052bf90a11952a190d0plougher !get_fragment_location(s, 6300aeb6601e77c348064513052bf90a11952a190d0plougher inodep->fragment, &frag_blk, &frag_size)) 6310aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 6320aeb6601e77c348064513052bf90a11952a190d0plougher 6330aeb6601e77c348064513052bf90a11952a190d0plougher if((i = squashfs_new_inode(s, inodeb)) == NULL) 6340aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 6350aeb6601e77c348064513052bf90a11952a190d0plougher 6360aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 6370aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = inodep->file_size; 6380aeb6601e77c348064513052bf90a11952a190d0plougher i->i_fop = &generic_ro_fops; 6390aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= S_IFREG; 6400aeb6601e77c348064513052bf90a11952a190d0plougher i->i_blocks = ((i->i_size - 1) >> 9) + 1; 6410aeb6601e77c348064513052bf90a11952a190d0plougher i->i_blksize = PAGE_CACHE_SIZE; 6420aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; 6430aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_size = frag_size; 6440aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; 6450aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->start_block = inodep->start_block; 6460aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s1.block_list_start = next_block; 6470aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->offset = next_offset; 6480aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->block_size > 4096) 6490aeb6601e77c348064513052bf90a11952a190d0plougher i->i_data.a_ops = &squashfs_aops; 6500aeb6601e77c348064513052bf90a11952a190d0plougher else 6510aeb6601e77c348064513052bf90a11952a190d0plougher i->i_data.a_ops = &squashfs_aops_4K; 6520aeb6601e77c348064513052bf90a11952a190d0plougher 6530aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("File inode %x:%x, start_block %llx, " 6540aeb6601e77c348064513052bf90a11952a190d0plougher "block_list_start %llx, offset %x\n", 6550aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INODE_BLK(inode), offset, 6560aeb6601e77c348064513052bf90a11952a190d0plougher inodep->start_block, next_block, 6570aeb6601e77c348064513052bf90a11952a190d0plougher next_offset); 6580aeb6601e77c348064513052bf90a11952a190d0plougher break; 6590aeb6601e77c348064513052bf90a11952a190d0plougher } 6600aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_DIR_TYPE: { 6610aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_inode_header *inodep = &id.dir; 6620aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_inode_header *sinodep = &sid.dir; 6630aeb6601e77c348064513052bf90a11952a190d0plougher 6640aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 6650aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 6660aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 6670aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 6680aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 6690aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 6700aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); 6710aeb6601e77c348064513052bf90a11952a190d0plougher } else 6720aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 6730aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 6740aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 6750aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 6760aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 6770aeb6601e77c348064513052bf90a11952a190d0plougher 6780aeb6601e77c348064513052bf90a11952a190d0plougher if((i = squashfs_new_inode(s, inodeb)) == NULL) 6790aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 6800aeb6601e77c348064513052bf90a11952a190d0plougher 6810aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 6820aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = inodep->file_size; 6830aeb6601e77c348064513052bf90a11952a190d0plougher i->i_op = &squashfs_dir_inode_ops; 6840aeb6601e77c348064513052bf90a11952a190d0plougher i->i_fop = &squashfs_dir_ops; 6850aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= S_IFDIR; 6860aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->start_block = inodep->start_block; 6870aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->offset = inodep->offset; 6880aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_count = 0; 6890aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; 6900aeb6601e77c348064513052bf90a11952a190d0plougher 6910aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Directory inode %x:%x, start_block %x, offset " 6920aeb6601e77c348064513052bf90a11952a190d0plougher "%x\n", SQUASHFS_INODE_BLK(inode), 6930aeb6601e77c348064513052bf90a11952a190d0plougher offset, inodep->start_block, 6940aeb6601e77c348064513052bf90a11952a190d0plougher inodep->offset); 6950aeb6601e77c348064513052bf90a11952a190d0plougher break; 6960aeb6601e77c348064513052bf90a11952a190d0plougher } 6970aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_LDIR_TYPE: { 6980aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_ldir_inode_header *inodep = &id.ldir; 6990aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_ldir_inode_header *sinodep = &sid.ldir; 7000aeb6601e77c348064513052bf90a11952a190d0plougher 7010aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 7020aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7030aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 7040aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 7050aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7060aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7070aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, 7080aeb6601e77c348064513052bf90a11952a190d0plougher sinodep); 7090aeb6601e77c348064513052bf90a11952a190d0plougher } else 7100aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7110aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 7120aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 7130aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7140aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7150aeb6601e77c348064513052bf90a11952a190d0plougher 7160aeb6601e77c348064513052bf90a11952a190d0plougher if((i = squashfs_new_inode(s, inodeb)) == NULL) 7170aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 7180aeb6601e77c348064513052bf90a11952a190d0plougher 7190aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 7200aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = inodep->file_size; 7210aeb6601e77c348064513052bf90a11952a190d0plougher i->i_op = &squashfs_dir_inode_ops; 7220aeb6601e77c348064513052bf90a11952a190d0plougher i->i_fop = &squashfs_dir_ops; 7230aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= S_IFDIR; 7240aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->start_block = inodep->start_block; 7250aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->offset = inodep->offset; 7260aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_start = next_block; 7270aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_offset = 7280aeb6601e77c348064513052bf90a11952a190d0plougher next_offset; 7290aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_count = 7300aeb6601e77c348064513052bf90a11952a190d0plougher inodep->i_count; 7310aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; 7320aeb6601e77c348064513052bf90a11952a190d0plougher 7330aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Long directory inode %x:%x, start_block %x, " 7340aeb6601e77c348064513052bf90a11952a190d0plougher "offset %x\n", 7350aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INODE_BLK(inode), offset, 7360aeb6601e77c348064513052bf90a11952a190d0plougher inodep->start_block, inodep->offset); 7370aeb6601e77c348064513052bf90a11952a190d0plougher break; 7380aeb6601e77c348064513052bf90a11952a190d0plougher } 7390aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_SYMLINK_TYPE: { 7400aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_symlink_inode_header *inodep = 7410aeb6601e77c348064513052bf90a11952a190d0plougher &id.symlink; 7420aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_symlink_inode_header *sinodep = 7430aeb6601e77c348064513052bf90a11952a190d0plougher &sid.symlink; 7440aeb6601e77c348064513052bf90a11952a190d0plougher 7450aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 7460aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7470aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 7480aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 7490aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7500aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7510aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, 7520aeb6601e77c348064513052bf90a11952a190d0plougher sinodep); 7530aeb6601e77c348064513052bf90a11952a190d0plougher } else 7540aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7550aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 7560aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 7570aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7580aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7590aeb6601e77c348064513052bf90a11952a190d0plougher 7600aeb6601e77c348064513052bf90a11952a190d0plougher if((i = squashfs_new_inode(s, inodeb)) == NULL) 7610aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 7620aeb6601e77c348064513052bf90a11952a190d0plougher 7630aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 7640aeb6601e77c348064513052bf90a11952a190d0plougher i->i_size = inodep->symlink_size; 7650aeb6601e77c348064513052bf90a11952a190d0plougher i->i_op = &page_symlink_inode_operations; 7660aeb6601e77c348064513052bf90a11952a190d0plougher i->i_data.a_ops = &squashfs_symlink_aops; 7670aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= S_IFLNK; 7680aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->start_block = next_block; 7690aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->offset = next_offset; 7700aeb6601e77c348064513052bf90a11952a190d0plougher 7710aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Symbolic link inode %x:%x, start_block %llx, " 7720aeb6601e77c348064513052bf90a11952a190d0plougher "offset %x\n", 7730aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INODE_BLK(inode), offset, 7740aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset); 7750aeb6601e77c348064513052bf90a11952a190d0plougher break; 7760aeb6601e77c348064513052bf90a11952a190d0plougher } 7770aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_BLKDEV_TYPE: 7780aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_CHRDEV_TYPE: { 7790aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dev_inode_header *inodep = &id.dev; 7800aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dev_inode_header *sinodep = &sid.dev; 7810aeb6601e77c348064513052bf90a11952a190d0plougher 7820aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 7830aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7840aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 7850aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 7860aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7870aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7880aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); 7890aeb6601e77c348064513052bf90a11952a190d0plougher } else 7900aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 7910aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 7920aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 7930aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 7940aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 7950aeb6601e77c348064513052bf90a11952a190d0plougher 7960aeb6601e77c348064513052bf90a11952a190d0plougher if ((i = squashfs_new_inode(s, inodeb)) == NULL) 7970aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 7980aeb6601e77c348064513052bf90a11952a190d0plougher 7990aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 8000aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= (inodeb->inode_type == 8010aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : 8020aeb6601e77c348064513052bf90a11952a190d0plougher S_IFBLK; 803244f83fd9ba894f8aafbc409b3ea97a492c67ca2plougher init_special_inode(i, i->i_mode, inodep->rdev); 8040aeb6601e77c348064513052bf90a11952a190d0plougher 8050aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Device inode %x:%x, rdev %x\n", 8060aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INODE_BLK(inode), offset, 8070aeb6601e77c348064513052bf90a11952a190d0plougher inodep->rdev); 8080aeb6601e77c348064513052bf90a11952a190d0plougher break; 8090aeb6601e77c348064513052bf90a11952a190d0plougher } 8100aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_FIFO_TYPE: 8110aeb6601e77c348064513052bf90a11952a190d0plougher case SQUASHFS_SOCKET_TYPE: { 8120aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_ipc_inode_header *inodep = &id.ipc; 8130aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_ipc_inode_header *sinodep = &sid.ipc; 8140aeb6601e77c348064513052bf90a11952a190d0plougher 8150aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 8160aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 8170aeb6601e77c348064513052bf90a11952a190d0plougher sinodep, block, offset, 8180aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*sinodep), &next_block, 8190aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 8200aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 8210aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); 8220aeb6601e77c348064513052bf90a11952a190d0plougher } else 8230aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, (char *) 8240aeb6601e77c348064513052bf90a11952a190d0plougher inodep, block, offset, 8250aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*inodep), &next_block, 8260aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 8270aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 8280aeb6601e77c348064513052bf90a11952a190d0plougher 8290aeb6601e77c348064513052bf90a11952a190d0plougher if ((i = squashfs_new_inode(s, inodeb)) == NULL) 8300aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 8310aeb6601e77c348064513052bf90a11952a190d0plougher 8320aeb6601e77c348064513052bf90a11952a190d0plougher i->i_nlink = inodep->nlink; 8330aeb6601e77c348064513052bf90a11952a190d0plougher i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) 8340aeb6601e77c348064513052bf90a11952a190d0plougher ? S_IFIFO : S_IFSOCK; 8350aeb6601e77c348064513052bf90a11952a190d0plougher init_special_inode(i, i->i_mode, 0); 8360aeb6601e77c348064513052bf90a11952a190d0plougher break; 8370aeb6601e77c348064513052bf90a11952a190d0plougher } 8380aeb6601e77c348064513052bf90a11952a190d0plougher default: 8390aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unknown inode type %d in squashfs_iget!\n", 8400aeb6601e77c348064513052bf90a11952a190d0plougher inodeb->inode_type); 8410aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read1; 8420aeb6601e77c348064513052bf90a11952a190d0plougher } 8430aeb6601e77c348064513052bf90a11952a190d0plougher 8440aeb6601e77c348064513052bf90a11952a190d0plougher insert_inode_hash(i); 8450aeb6601e77c348064513052bf90a11952a190d0plougher return i; 8460aeb6601e77c348064513052bf90a11952a190d0plougher 8470aeb6601e77c348064513052bf90a11952a190d0plougherfailed_read: 8480aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read inode [%llx:%x]\n", block, offset); 8490aeb6601e77c348064513052bf90a11952a190d0plougher 8500aeb6601e77c348064513052bf90a11952a190d0plougherfailed_read1: 8510aeb6601e77c348064513052bf90a11952a190d0plougher return NULL; 8520aeb6601e77c348064513052bf90a11952a190d0plougher} 8530aeb6601e77c348064513052bf90a11952a190d0plougher 8540aeb6601e77c348064513052bf90a11952a190d0plougher 8550aeb6601e77c348064513052bf90a11952a190d0plougherint read_fragment_index_table(struct super_block *s) 8560aeb6601e77c348064513052bf90a11952a190d0plougher{ 8570aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 8580aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 8590aeb6601e77c348064513052bf90a11952a190d0plougher 8600aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES 8610aeb6601e77c348064513052bf90a11952a190d0plougher (sblk->fragments), GFP_KERNEL))) { 8620aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate uid/gid table\n"); 8630aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 8640aeb6601e77c348064513052bf90a11952a190d0plougher } 8650aeb6601e77c348064513052bf90a11952a190d0plougher 8660aeb6601e77c348064513052bf90a11952a190d0plougher if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && 8670aeb6601e77c348064513052bf90a11952a190d0plougher !squashfs_read_data(s, (char *) 8680aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment_index, 8690aeb6601e77c348064513052bf90a11952a190d0plougher sblk->fragment_table_start, 8700aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_FRAGMENT_INDEX_BYTES 8710aeb6601e77c348064513052bf90a11952a190d0plougher (sblk->fragments) | 8720aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 8730aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("unable to read fragment index table\n"); 8740aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 8750aeb6601e77c348064513052bf90a11952a190d0plougher } 8760aeb6601e77c348064513052bf90a11952a190d0plougher 8770aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 8780aeb6601e77c348064513052bf90a11952a190d0plougher int i; 8790aeb6601e77c348064513052bf90a11952a190d0plougher long long fragment; 8800aeb6601e77c348064513052bf90a11952a190d0plougher 8810aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); 8820aeb6601e77c348064513052bf90a11952a190d0plougher i++) { 8830aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), 8840aeb6601e77c348064513052bf90a11952a190d0plougher &msblk->fragment_index[i], 1); 8850aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment_index[i] = fragment; 8860aeb6601e77c348064513052bf90a11952a190d0plougher } 8870aeb6601e77c348064513052bf90a11952a190d0plougher } 8880aeb6601e77c348064513052bf90a11952a190d0plougher 8890aeb6601e77c348064513052bf90a11952a190d0plougher return 1; 8900aeb6601e77c348064513052bf90a11952a190d0plougher} 8910aeb6601e77c348064513052bf90a11952a190d0plougher 8920aeb6601e77c348064513052bf90a11952a190d0plougher 8930aeb6601e77c348064513052bf90a11952a190d0plougherstatic int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) 8940aeb6601e77c348064513052bf90a11952a190d0plougher{ 8950aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 8960aeb6601e77c348064513052bf90a11952a190d0plougher 8970aeb6601e77c348064513052bf90a11952a190d0plougher msblk->iget = squashfs_iget; 8980aeb6601e77c348064513052bf90a11952a190d0plougher msblk->read_blocklist = read_blocklist; 8990aeb6601e77c348064513052bf90a11952a190d0plougher msblk->read_fragment_index_table = read_fragment_index_table; 9000aeb6601e77c348064513052bf90a11952a190d0plougher 9010aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->s_major == 1) { 9020aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_1_0_supported(msblk)) { 9030aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " 9040aeb6601e77c348064513052bf90a11952a190d0plougher "are unsupported\n"); 9050aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Please recompile with " 9060aeb6601e77c348064513052bf90a11952a190d0plougher "Squashfs 1.0 support enabled\n"); 9070aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 9080aeb6601e77c348064513052bf90a11952a190d0plougher } 9090aeb6601e77c348064513052bf90a11952a190d0plougher } else if (sblk->s_major == 2) { 9100aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_2_0_supported(msblk)) { 9110aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " 9120aeb6601e77c348064513052bf90a11952a190d0plougher "are unsupported\n"); 9130aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Please recompile with " 9140aeb6601e77c348064513052bf90a11952a190d0plougher "Squashfs 2.0 support enabled\n"); 9150aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 9160aeb6601e77c348064513052bf90a11952a190d0plougher } 9170aeb6601e77c348064513052bf90a11952a190d0plougher } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > 9180aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_MINOR) { 9190aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Major/Minor mismatch, trying to mount newer %d.%d " 9200aeb6601e77c348064513052bf90a11952a190d0plougher "filesystem\n", sblk->s_major, sblk->s_minor); 9210aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Please update your kernel\n"); 9220aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 9230aeb6601e77c348064513052bf90a11952a190d0plougher } 9240aeb6601e77c348064513052bf90a11952a190d0plougher 9250aeb6601e77c348064513052bf90a11952a190d0plougher return 1; 9260aeb6601e77c348064513052bf90a11952a190d0plougher} 9270aeb6601e77c348064513052bf90a11952a190d0plougher 9280aeb6601e77c348064513052bf90a11952a190d0plougher 9290aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct super_block *squashfs_read_super(struct super_block *s, 9300aeb6601e77c348064513052bf90a11952a190d0plougher void *data, int silent) 9310aeb6601e77c348064513052bf90a11952a190d0plougher{ 9320aeb6601e77c348064513052bf90a11952a190d0plougher kdev_t dev = s->s_dev; 9330aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 9340aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 9350aeb6601e77c348064513052bf90a11952a190d0plougher int i; 9360aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *root; 937410dd958c15c73d91e877a0afe085bfaee37d9ffplougher 938410dd958c15c73d91e877a0afe085bfaee37d9ffplougher if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { 939410dd958c15c73d91e877a0afe085bfaee37d9ffplougher ERROR("Failed to allocate zlib workspace\n"); 940410dd958c15c73d91e877a0afe085bfaee37d9ffplougher goto failed_mount; 941410dd958c15c73d91e877a0afe085bfaee37d9ffplougher } 942410dd958c15c73d91e877a0afe085bfaee37d9ffplougher 9430aeb6601e77c348064513052bf90a11952a190d0plougher msblk->devblksize = get_hardsect_size(dev); 9440aeb6601e77c348064513052bf90a11952a190d0plougher if(msblk->devblksize < BLOCK_SIZE) 9450aeb6601e77c348064513052bf90a11952a190d0plougher msblk->devblksize = BLOCK_SIZE; 9460aeb6601e77c348064513052bf90a11952a190d0plougher msblk->devblksize_log2 = ffz(~msblk->devblksize); 9470aeb6601e77c348064513052bf90a11952a190d0plougher set_blocksize(dev, msblk->devblksize); 9480aeb6601e77c348064513052bf90a11952a190d0plougher s->s_blocksize = msblk->devblksize; 9490aeb6601e77c348064513052bf90a11952a190d0plougher s->s_blocksize_bits = msblk->devblksize_log2; 9500aeb6601e77c348064513052bf90a11952a190d0plougher 9510aeb6601e77c348064513052bf90a11952a190d0plougher init_MUTEX(&msblk->read_data_mutex); 9520aeb6601e77c348064513052bf90a11952a190d0plougher init_MUTEX(&msblk->read_page_mutex); 9530aeb6601e77c348064513052bf90a11952a190d0plougher init_MUTEX(&msblk->block_cache_mutex); 9540aeb6601e77c348064513052bf90a11952a190d0plougher init_MUTEX(&msblk->fragment_mutex); 9550aeb6601e77c348064513052bf90a11952a190d0plougher 9560aeb6601e77c348064513052bf90a11952a190d0plougher init_waitqueue_head(&msblk->waitq); 9570aeb6601e77c348064513052bf90a11952a190d0plougher init_waitqueue_head(&msblk->fragment_wait_queue); 9580aeb6601e77c348064513052bf90a11952a190d0plougher 9590aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, 9600aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(struct squashfs_super_block) | 9610aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 9620aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("unable to read superblock\n"); 9630aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 9640aeb6601e77c348064513052bf90a11952a190d0plougher } 9650aeb6601e77c348064513052bf90a11952a190d0plougher 9660aeb6601e77c348064513052bf90a11952a190d0plougher /* Check it is a SQUASHFS superblock */ 9670aeb6601e77c348064513052bf90a11952a190d0plougher msblk->swap = 0; 9680aeb6601e77c348064513052bf90a11952a190d0plougher if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { 9690aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { 9700aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block ssblk; 9710aeb6601e77c348064513052bf90a11952a190d0plougher 9720aeb6601e77c348064513052bf90a11952a190d0plougher WARNING("Mounting a different endian SQUASHFS " 9730aeb6601e77c348064513052bf90a11952a190d0plougher "filesystem on %s\n", bdevname(dev)); 9740aeb6601e77c348064513052bf90a11952a190d0plougher 9750aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); 9760aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); 9770aeb6601e77c348064513052bf90a11952a190d0plougher msblk->swap = 1; 9780aeb6601e77c348064513052bf90a11952a190d0plougher } else { 9790aeb6601e77c348064513052bf90a11952a190d0plougher SERROR("Can't find a SQUASHFS superblock on %s\n", 9800aeb6601e77c348064513052bf90a11952a190d0plougher bdevname(dev)); 9810aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 9820aeb6601e77c348064513052bf90a11952a190d0plougher } 9830aeb6601e77c348064513052bf90a11952a190d0plougher } 9840aeb6601e77c348064513052bf90a11952a190d0plougher 9850aeb6601e77c348064513052bf90a11952a190d0plougher /* Check the MAJOR & MINOR versions */ 9860aeb6601e77c348064513052bf90a11952a190d0plougher if(!supported_squashfs_filesystem(msblk, silent)) 9870aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 9880aeb6601e77c348064513052bf90a11952a190d0plougher 9890aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Found valid superblock on %s\n", bdevname(dev)); 9900aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Inodes are %scompressed\n", 9910aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_UNCOMPRESSED_INODES 9920aeb6601e77c348064513052bf90a11952a190d0plougher (sblk->flags) ? "un" : ""); 9930aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Data is %scompressed\n", 9940aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) 9950aeb6601e77c348064513052bf90a11952a190d0plougher ? "un" : ""); 9960aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Check data is %s present in the filesystem\n", 9970aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CHECK_DATA(sblk->flags) ? 9980aeb6601e77c348064513052bf90a11952a190d0plougher "" : "not"); 9990aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); 10000aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Block size %d\n", sblk->block_size); 10010aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Number of inodes %d\n", sblk->inodes); 10020aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->s_major > 1) 10030aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Number of fragments %d\n", sblk->fragments); 10040aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Number of uids %d\n", sblk->no_uids); 10050aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Number of gids %d\n", sblk->no_guids); 10060aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); 10070aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); 10080aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->s_major > 1) 10090aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("sblk->fragment_table_start %llx\n", 10100aeb6601e77c348064513052bf90a11952a190d0plougher sblk->fragment_table_start); 10110aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("sblk->uid_start %llx\n", sblk->uid_start); 10120aeb6601e77c348064513052bf90a11952a190d0plougher 10130aeb6601e77c348064513052bf90a11952a190d0plougher s->s_flags |= MS_RDONLY; 10140aeb6601e77c348064513052bf90a11952a190d0plougher s->s_op = &squashfs_ops; 10150aeb6601e77c348064513052bf90a11952a190d0plougher 10160aeb6601e77c348064513052bf90a11952a190d0plougher /* Init inode_table block pointer array */ 10170aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * 10180aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_BLKS, GFP_KERNEL))) { 10190aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate block cache\n"); 10200aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10210aeb6601e77c348064513052bf90a11952a190d0plougher } 10220aeb6601e77c348064513052bf90a11952a190d0plougher 10230aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 10240aeb6601e77c348064513052bf90a11952a190d0plougher msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; 10250aeb6601e77c348064513052bf90a11952a190d0plougher 10260aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_cache = 0; 10270aeb6601e77c348064513052bf90a11952a190d0plougher 10280aeb6601e77c348064513052bf90a11952a190d0plougher /* Allocate read_data block */ 10290aeb6601e77c348064513052bf90a11952a190d0plougher msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ? 10300aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_METADATA_SIZE : 10310aeb6601e77c348064513052bf90a11952a190d0plougher sblk->block_size; 10320aeb6601e77c348064513052bf90a11952a190d0plougher 10330aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) { 10340aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate read_data block\n"); 10350aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10360aeb6601e77c348064513052bf90a11952a190d0plougher } 10370aeb6601e77c348064513052bf90a11952a190d0plougher 10380aeb6601e77c348064513052bf90a11952a190d0plougher /* Allocate read_page block */ 10390aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) { 10400aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate read_page block\n"); 10410aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10420aeb6601e77c348064513052bf90a11952a190d0plougher } 10430aeb6601e77c348064513052bf90a11952a190d0plougher 10440aeb6601e77c348064513052bf90a11952a190d0plougher /* Allocate uid and gid tables */ 10450aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * 10460aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(unsigned int), GFP_KERNEL))) { 10470aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate uid/gid table\n"); 10480aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10490aeb6601e77c348064513052bf90a11952a190d0plougher } 10500aeb6601e77c348064513052bf90a11952a190d0plougher msblk->guid = msblk->uid + sblk->no_uids; 10510aeb6601e77c348064513052bf90a11952a190d0plougher 10520aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 10530aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int suid[sblk->no_uids + sblk->no_guids]; 10540aeb6601e77c348064513052bf90a11952a190d0plougher 10550aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, 10560aeb6601e77c348064513052bf90a11952a190d0plougher ((sblk->no_uids + sblk->no_guids) * 10570aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(unsigned int)) | 10580aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 10590aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("unable to read uid/gid table\n"); 10600aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10610aeb6601e77c348064513052bf90a11952a190d0plougher } 10620aeb6601e77c348064513052bf90a11952a190d0plougher 10630aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + 10640aeb6601e77c348064513052bf90a11952a190d0plougher sblk->no_guids), (sizeof(unsigned int) * 8)); 10650aeb6601e77c348064513052bf90a11952a190d0plougher } else 10660aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, 10670aeb6601e77c348064513052bf90a11952a190d0plougher ((sblk->no_uids + sblk->no_guids) * 10680aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(unsigned int)) | 10690aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { 10700aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("unable to read uid/gid table\n"); 10710aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10720aeb6601e77c348064513052bf90a11952a190d0plougher } 10730aeb6601e77c348064513052bf90a11952a190d0plougher 10740aeb6601e77c348064513052bf90a11952a190d0plougher 10750aeb6601e77c348064513052bf90a11952a190d0plougher if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) 10760aeb6601e77c348064513052bf90a11952a190d0plougher goto allocate_root; 10770aeb6601e77c348064513052bf90a11952a190d0plougher 10780aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) * 10790aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) { 10800aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate fragment block cache\n"); 10810aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10820aeb6601e77c348064513052bf90a11952a190d0plougher } 10830aeb6601e77c348064513052bf90a11952a190d0plougher 10840aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { 10850aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].locked = 0; 10860aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].block = SQUASHFS_INVALID_BLK; 10870aeb6601e77c348064513052bf90a11952a190d0plougher msblk->fragment[i].data = NULL; 10880aeb6601e77c348064513052bf90a11952a190d0plougher } 10890aeb6601e77c348064513052bf90a11952a190d0plougher 10900aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_fragment = 0; 10910aeb6601e77c348064513052bf90a11952a190d0plougher 10920aeb6601e77c348064513052bf90a11952a190d0plougher /* Allocate fragment index table */ 10930aeb6601e77c348064513052bf90a11952a190d0plougher if(msblk->read_fragment_index_table(s) == 0) 10940aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10950aeb6601e77c348064513052bf90a11952a190d0plougher 10960aeb6601e77c348064513052bf90a11952a190d0plougherallocate_root: 10970aeb6601e77c348064513052bf90a11952a190d0plougher if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL) 10980aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 10990aeb6601e77c348064513052bf90a11952a190d0plougher 11000aeb6601e77c348064513052bf90a11952a190d0plougher if ((s->s_root = d_alloc_root(root)) == NULL) { 11010aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Root inode create failed\n"); 11020aeb6601e77c348064513052bf90a11952a190d0plougher iput(root); 11030aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_mount; 11040aeb6601e77c348064513052bf90a11952a190d0plougher } 11050aeb6601e77c348064513052bf90a11952a190d0plougher 11060aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Leaving squashfs_read_super\n"); 11070aeb6601e77c348064513052bf90a11952a190d0plougher return s; 11080aeb6601e77c348064513052bf90a11952a190d0plougher 11090aeb6601e77c348064513052bf90a11952a190d0plougherfailed_mount: 11100aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->fragment_index); 11110aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->fragment); 11120aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->uid); 11130aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->read_page); 11140aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->read_data); 11150aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->block_cache); 11160aeb6601e77c348064513052bf90a11952a190d0plougher kfree(msblk->fragment_index_2); 1117410dd958c15c73d91e877a0afe085bfaee37d9ffplougher vfree(msblk->stream.workspace); 11180aeb6601e77c348064513052bf90a11952a190d0plougher return NULL; 11190aeb6601e77c348064513052bf90a11952a190d0plougher} 11200aeb6601e77c348064513052bf90a11952a190d0plougher 11210aeb6601e77c348064513052bf90a11952a190d0plougher 11220aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_statfs(struct super_block *s, struct statfs *buf) 11230aeb6601e77c348064513052bf90a11952a190d0plougher{ 11240aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 11250aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 11260aeb6601e77c348064513052bf90a11952a190d0plougher 11270aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_statfs\n"); 11280aeb6601e77c348064513052bf90a11952a190d0plougher 11290aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_type = SQUASHFS_MAGIC; 11300aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_bsize = sblk->block_size; 11310aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; 11320aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_bfree = buf->f_bavail = 0; 11330aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_files = sblk->inodes; 11340aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_ffree = 0; 11350aeb6601e77c348064513052bf90a11952a190d0plougher buf->f_namelen = SQUASHFS_NAME_LEN; 11360aeb6601e77c348064513052bf90a11952a190d0plougher 11370aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 11380aeb6601e77c348064513052bf90a11952a190d0plougher} 11390aeb6601e77c348064513052bf90a11952a190d0plougher 11400aeb6601e77c348064513052bf90a11952a190d0plougher 11410aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_symlink_readpage(struct file *file, struct page *page) 11420aeb6601e77c348064513052bf90a11952a190d0plougher{ 11430aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *inode = page->mapping->host; 11440aeb6601e77c348064513052bf90a11952a190d0plougher int index = page->index << PAGE_CACHE_SHIFT, length, bytes; 11450aeb6601e77c348064513052bf90a11952a190d0plougher long long block = SQUASHFS_I(inode)->start_block; 11460aeb6601e77c348064513052bf90a11952a190d0plougher int offset = SQUASHFS_I(inode)->offset; 11470aeb6601e77c348064513052bf90a11952a190d0plougher void *pageaddr = kmap(page); 11480aeb6601e77c348064513052bf90a11952a190d0plougher 11490aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " 11500aeb6601e77c348064513052bf90a11952a190d0plougher "%llx, offset %x\n", page->index, 11510aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)->start_block, 11520aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)->offset); 11530aeb6601e77c348064513052bf90a11952a190d0plougher 11540aeb6601e77c348064513052bf90a11952a190d0plougher for (length = 0; length < index; length += bytes) { 11550aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, 11560aeb6601e77c348064513052bf90a11952a190d0plougher block, offset, PAGE_CACHE_SIZE, &block, 11570aeb6601e77c348064513052bf90a11952a190d0plougher &offset))) { 11580aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read symbolic link [%llx:%x]\n", block, 11590aeb6601e77c348064513052bf90a11952a190d0plougher offset); 11600aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 11610aeb6601e77c348064513052bf90a11952a190d0plougher } 11620aeb6601e77c348064513052bf90a11952a190d0plougher } 11630aeb6601e77c348064513052bf90a11952a190d0plougher 11640aeb6601e77c348064513052bf90a11952a190d0plougher if (length != index) { 11650aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("(squashfs_symlink_readpage) length != index\n"); 11660aeb6601e77c348064513052bf90a11952a190d0plougher bytes = 0; 11670aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 11680aeb6601e77c348064513052bf90a11952a190d0plougher } 11690aeb6601e77c348064513052bf90a11952a190d0plougher 11700aeb6601e77c348064513052bf90a11952a190d0plougher bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : 11710aeb6601e77c348064513052bf90a11952a190d0plougher i_size_read(inode) - length; 11720aeb6601e77c348064513052bf90a11952a190d0plougher 11730aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, 11740aeb6601e77c348064513052bf90a11952a190d0plougher offset, bytes, &block, &offset))) 11750aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); 11760aeb6601e77c348064513052bf90a11952a190d0plougher 11770aeb6601e77c348064513052bf90a11952a190d0plougherskip_read: 11780aeb6601e77c348064513052bf90a11952a190d0plougher memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 11790aeb6601e77c348064513052bf90a11952a190d0plougher kunmap(page); 11800aeb6601e77c348064513052bf90a11952a190d0plougher SetPageUptodate(page); 11810aeb6601e77c348064513052bf90a11952a190d0plougher UnlockPage(page); 11820aeb6601e77c348064513052bf90a11952a190d0plougher 11830aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 11840aeb6601e77c348064513052bf90a11952a190d0plougher} 11850aeb6601e77c348064513052bf90a11952a190d0plougher 11860aeb6601e77c348064513052bf90a11952a190d0plougher 11870aeb6601e77c348064513052bf90a11952a190d0plougherstruct meta_index *locate_meta_index(struct inode *inode, int index, int offset) 11880aeb6601e77c348064513052bf90a11952a190d0plougher{ 11890aeb6601e77c348064513052bf90a11952a190d0plougher struct meta_index *meta = NULL; 11900aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb; 11910aeb6601e77c348064513052bf90a11952a190d0plougher int i; 11920aeb6601e77c348064513052bf90a11952a190d0plougher 11930aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->meta_index_mutex); 11940aeb6601e77c348064513052bf90a11952a190d0plougher 11950aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("locate_meta_index: index %d, offset %d\n", index, offset); 11960aeb6601e77c348064513052bf90a11952a190d0plougher 11970aeb6601e77c348064513052bf90a11952a190d0plougher if(msblk->meta_index == NULL) 11980aeb6601e77c348064513052bf90a11952a190d0plougher goto not_allocated; 11990aeb6601e77c348064513052bf90a11952a190d0plougher 12000aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_META_NUMBER; i ++) 12010aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->meta_index[i].inode_number == inode->i_ino && 12020aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].offset >= offset && 12030aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].offset <= index && 12040aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].locked == 0) { 12050aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("locate_meta_index: entry %d, offset %d\n", i, 12060aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].offset); 12070aeb6601e77c348064513052bf90a11952a190d0plougher meta = &msblk->meta_index[i]; 12080aeb6601e77c348064513052bf90a11952a190d0plougher offset = meta->offset; 12090aeb6601e77c348064513052bf90a11952a190d0plougher } 12100aeb6601e77c348064513052bf90a11952a190d0plougher 12110aeb6601e77c348064513052bf90a11952a190d0plougher if (meta) 12120aeb6601e77c348064513052bf90a11952a190d0plougher meta->locked = 1; 12130aeb6601e77c348064513052bf90a11952a190d0plougher 12140aeb6601e77c348064513052bf90a11952a190d0ploughernot_allocated: 12150aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->meta_index_mutex); 12160aeb6601e77c348064513052bf90a11952a190d0plougher 12170aeb6601e77c348064513052bf90a11952a190d0plougher return meta; 12180aeb6601e77c348064513052bf90a11952a190d0plougher} 12190aeb6601e77c348064513052bf90a11952a190d0plougher 12200aeb6601e77c348064513052bf90a11952a190d0plougher 12210aeb6601e77c348064513052bf90a11952a190d0plougherstruct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) 12220aeb6601e77c348064513052bf90a11952a190d0plougher{ 12230aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb; 12240aeb6601e77c348064513052bf90a11952a190d0plougher struct meta_index *meta = NULL; 12250aeb6601e77c348064513052bf90a11952a190d0plougher int i; 12260aeb6601e77c348064513052bf90a11952a190d0plougher 12270aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->meta_index_mutex); 12280aeb6601e77c348064513052bf90a11952a190d0plougher 12290aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); 12300aeb6601e77c348064513052bf90a11952a190d0plougher 12310aeb6601e77c348064513052bf90a11952a190d0plougher if(msblk->meta_index == NULL) { 12320aeb6601e77c348064513052bf90a11952a190d0plougher if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) * 12330aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_META_NUMBER, GFP_KERNEL))) { 12340aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Failed to allocate meta_index\n"); 12350aeb6601e77c348064513052bf90a11952a190d0plougher goto failed; 12360aeb6601e77c348064513052bf90a11952a190d0plougher } 12370aeb6601e77c348064513052bf90a11952a190d0plougher for(i = 0; i < SQUASHFS_META_NUMBER; i++) { 12380aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].inode_number = 0; 12390aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[i].locked = 0; 12400aeb6601e77c348064513052bf90a11952a190d0plougher } 12410aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_meta_index = 0; 12420aeb6601e77c348064513052bf90a11952a190d0plougher } 12430aeb6601e77c348064513052bf90a11952a190d0plougher 12440aeb6601e77c348064513052bf90a11952a190d0plougher for(i = SQUASHFS_META_NUMBER; i && 12450aeb6601e77c348064513052bf90a11952a190d0plougher msblk->meta_index[msblk->next_meta_index].locked; i --) 12460aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_meta_index = (msblk->next_meta_index + 1) % 12470aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_META_NUMBER; 12480aeb6601e77c348064513052bf90a11952a190d0plougher 12490aeb6601e77c348064513052bf90a11952a190d0plougher if(i == 0) { 12500aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("empty_meta_index: failed!\n"); 12510aeb6601e77c348064513052bf90a11952a190d0plougher goto failed; 12520aeb6601e77c348064513052bf90a11952a190d0plougher } 12530aeb6601e77c348064513052bf90a11952a190d0plougher 12540aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("empty_meta_index: returned meta entry %d, %p\n", 12550aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_meta_index, 12560aeb6601e77c348064513052bf90a11952a190d0plougher &msblk->meta_index[msblk->next_meta_index]); 12570aeb6601e77c348064513052bf90a11952a190d0plougher 12580aeb6601e77c348064513052bf90a11952a190d0plougher meta = &msblk->meta_index[msblk->next_meta_index]; 12590aeb6601e77c348064513052bf90a11952a190d0plougher msblk->next_meta_index = (msblk->next_meta_index + 1) % 12600aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_META_NUMBER; 12610aeb6601e77c348064513052bf90a11952a190d0plougher 12620aeb6601e77c348064513052bf90a11952a190d0plougher meta->inode_number = inode->i_ino; 12630aeb6601e77c348064513052bf90a11952a190d0plougher meta->offset = offset; 12640aeb6601e77c348064513052bf90a11952a190d0plougher meta->skip = skip; 12650aeb6601e77c348064513052bf90a11952a190d0plougher meta->entries = 0; 12660aeb6601e77c348064513052bf90a11952a190d0plougher meta->locked = 1; 12670aeb6601e77c348064513052bf90a11952a190d0plougher 12680aeb6601e77c348064513052bf90a11952a190d0plougherfailed: 12690aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->meta_index_mutex); 12700aeb6601e77c348064513052bf90a11952a190d0plougher return meta; 12710aeb6601e77c348064513052bf90a11952a190d0plougher} 12720aeb6601e77c348064513052bf90a11952a190d0plougher 12730aeb6601e77c348064513052bf90a11952a190d0plougher 12740aeb6601e77c348064513052bf90a11952a190d0ploughervoid release_meta_index(struct inode *inode, struct meta_index *meta) 12750aeb6601e77c348064513052bf90a11952a190d0plougher{ 12760aeb6601e77c348064513052bf90a11952a190d0plougher meta->locked = 0; 12770aeb6601e77c348064513052bf90a11952a190d0plougher} 12780aeb6601e77c348064513052bf90a11952a190d0plougher 12790aeb6601e77c348064513052bf90a11952a190d0plougher 12800aeb6601e77c348064513052bf90a11952a190d0plougherstatic int read_block_index(struct super_block *s, int blocks, char *block_list, 12810aeb6601e77c348064513052bf90a11952a190d0plougher long long *start_block, int *offset) 12820aeb6601e77c348064513052bf90a11952a190d0plougher{ 12830aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 12840aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int *block_listp; 12850aeb6601e77c348064513052bf90a11952a190d0plougher int block = 0; 12860aeb6601e77c348064513052bf90a11952a190d0plougher 12870aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 12880aeb6601e77c348064513052bf90a11952a190d0plougher char sblock_list[blocks << 2]; 12890aeb6601e77c348064513052bf90a11952a190d0plougher 12900aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, sblock_list, *start_block, 12910aeb6601e77c348064513052bf90a11952a190d0plougher *offset, blocks << 2, start_block, offset)) { 12920aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read block list [%llx:%x]\n", 12930aeb6601e77c348064513052bf90a11952a190d0plougher *start_block, *offset); 12940aeb6601e77c348064513052bf90a11952a190d0plougher goto failure; 12950aeb6601e77c348064513052bf90a11952a190d0plougher } 12960aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_INTS(((unsigned int *)block_list), 12970aeb6601e77c348064513052bf90a11952a190d0plougher ((unsigned int *)sblock_list), blocks); 12980aeb6601e77c348064513052bf90a11952a190d0plougher } else 12990aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(s, block_list, *start_block, 13000aeb6601e77c348064513052bf90a11952a190d0plougher *offset, blocks << 2, start_block, offset)) { 13010aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read block list [%llx:%x]\n", 13020aeb6601e77c348064513052bf90a11952a190d0plougher *start_block, *offset); 13030aeb6601e77c348064513052bf90a11952a190d0plougher goto failure; 13040aeb6601e77c348064513052bf90a11952a190d0plougher } 13050aeb6601e77c348064513052bf90a11952a190d0plougher 13060aeb6601e77c348064513052bf90a11952a190d0plougher for (block_listp = (unsigned int *) block_list; blocks; 13070aeb6601e77c348064513052bf90a11952a190d0plougher block_listp++, blocks --) 13080aeb6601e77c348064513052bf90a11952a190d0plougher block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); 13090aeb6601e77c348064513052bf90a11952a190d0plougher 13100aeb6601e77c348064513052bf90a11952a190d0plougher return block; 13110aeb6601e77c348064513052bf90a11952a190d0plougher 13120aeb6601e77c348064513052bf90a11952a190d0plougherfailure: 13130aeb6601e77c348064513052bf90a11952a190d0plougher return -1; 13140aeb6601e77c348064513052bf90a11952a190d0plougher} 13150aeb6601e77c348064513052bf90a11952a190d0plougher 13160aeb6601e77c348064513052bf90a11952a190d0plougher 13170aeb6601e77c348064513052bf90a11952a190d0plougher#define SIZE 256 13180aeb6601e77c348064513052bf90a11952a190d0plougher 13190aeb6601e77c348064513052bf90a11952a190d0plougherstatic inline int calculate_skip(int blocks) { 13200aeb6601e77c348064513052bf90a11952a190d0plougher int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); 13210aeb6601e77c348064513052bf90a11952a190d0plougher return skip >= 7 ? 7 : skip + 1; 13220aeb6601e77c348064513052bf90a11952a190d0plougher} 13230aeb6601e77c348064513052bf90a11952a190d0plougher 13240aeb6601e77c348064513052bf90a11952a190d0plougher 13250aeb6601e77c348064513052bf90a11952a190d0plougherstatic int get_meta_index(struct inode *inode, int index, 13260aeb6601e77c348064513052bf90a11952a190d0plougher long long *index_block, int *index_offset, 13270aeb6601e77c348064513052bf90a11952a190d0plougher long long *data_block, char *block_list) 13280aeb6601e77c348064513052bf90a11952a190d0plougher{ 13290aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb; 13300aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 13310aeb6601e77c348064513052bf90a11952a190d0plougher int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); 13320aeb6601e77c348064513052bf90a11952a190d0plougher int offset = 0; 13330aeb6601e77c348064513052bf90a11952a190d0plougher struct meta_index *meta; 13340aeb6601e77c348064513052bf90a11952a190d0plougher struct meta_entry *meta_entry; 13350aeb6601e77c348064513052bf90a11952a190d0plougher long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; 13360aeb6601e77c348064513052bf90a11952a190d0plougher int cur_offset = SQUASHFS_I(inode)->offset; 13370aeb6601e77c348064513052bf90a11952a190d0plougher long long cur_data_block = SQUASHFS_I(inode)->start_block; 13380aeb6601e77c348064513052bf90a11952a190d0plougher int i; 13390aeb6601e77c348064513052bf90a11952a190d0plougher 13400aeb6601e77c348064513052bf90a11952a190d0plougher index /= SQUASHFS_META_INDEXES * skip; 13410aeb6601e77c348064513052bf90a11952a190d0plougher 13420aeb6601e77c348064513052bf90a11952a190d0plougher while ( offset < index ) { 13430aeb6601e77c348064513052bf90a11952a190d0plougher meta = locate_meta_index(inode, index, offset + 1); 13440aeb6601e77c348064513052bf90a11952a190d0plougher 13450aeb6601e77c348064513052bf90a11952a190d0plougher if (meta == NULL) { 13460aeb6601e77c348064513052bf90a11952a190d0plougher if ((meta = empty_meta_index(inode, offset + 1, 13470aeb6601e77c348064513052bf90a11952a190d0plougher skip)) == NULL) 13480aeb6601e77c348064513052bf90a11952a190d0plougher goto all_done; 13490aeb6601e77c348064513052bf90a11952a190d0plougher } else { 13500aeb6601e77c348064513052bf90a11952a190d0plougher offset = index < meta->offset + meta->entries ? index : 13510aeb6601e77c348064513052bf90a11952a190d0plougher meta->offset + meta->entries - 1; 13520aeb6601e77c348064513052bf90a11952a190d0plougher meta_entry = &meta->meta_entry[offset - meta->offset]; 13530aeb6601e77c348064513052bf90a11952a190d0plougher cur_index_block = meta_entry->index_block + sblk->inode_table_start; 13540aeb6601e77c348064513052bf90a11952a190d0plougher cur_offset = meta_entry->offset; 13550aeb6601e77c348064513052bf90a11952a190d0plougher cur_data_block = meta_entry->data_block; 13560aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("get_meta_index: offset %d, meta->offset %d, " 13570aeb6601e77c348064513052bf90a11952a190d0plougher "meta->entries %d\n", offset, meta->offset, 13580aeb6601e77c348064513052bf90a11952a190d0plougher meta->entries); 13590aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" 13600aeb6601e77c348064513052bf90a11952a190d0plougher " data_block 0x%llx\n", cur_index_block, 13610aeb6601e77c348064513052bf90a11952a190d0plougher cur_offset, cur_data_block); 13620aeb6601e77c348064513052bf90a11952a190d0plougher } 13630aeb6601e77c348064513052bf90a11952a190d0plougher 13640aeb6601e77c348064513052bf90a11952a190d0plougher for (i = meta->offset + meta->entries; i <= index && 13650aeb6601e77c348064513052bf90a11952a190d0plougher i < meta->offset + SQUASHFS_META_ENTRIES; i++) { 13660aeb6601e77c348064513052bf90a11952a190d0plougher int blocks = skip * SQUASHFS_META_INDEXES; 13670aeb6601e77c348064513052bf90a11952a190d0plougher 13680aeb6601e77c348064513052bf90a11952a190d0plougher while (blocks) { 13690aeb6601e77c348064513052bf90a11952a190d0plougher int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : 13700aeb6601e77c348064513052bf90a11952a190d0plougher blocks; 13710aeb6601e77c348064513052bf90a11952a190d0plougher int res = read_block_index(inode->i_sb, block, 13720aeb6601e77c348064513052bf90a11952a190d0plougher block_list, &cur_index_block, 13730aeb6601e77c348064513052bf90a11952a190d0plougher &cur_offset); 13740aeb6601e77c348064513052bf90a11952a190d0plougher 13750aeb6601e77c348064513052bf90a11952a190d0plougher if (res == -1) 13760aeb6601e77c348064513052bf90a11952a190d0plougher goto failed; 13770aeb6601e77c348064513052bf90a11952a190d0plougher 13780aeb6601e77c348064513052bf90a11952a190d0plougher cur_data_block += res; 13790aeb6601e77c348064513052bf90a11952a190d0plougher blocks -= block; 13800aeb6601e77c348064513052bf90a11952a190d0plougher } 13810aeb6601e77c348064513052bf90a11952a190d0plougher 13820aeb6601e77c348064513052bf90a11952a190d0plougher meta_entry = &meta->meta_entry[i - meta->offset]; 13830aeb6601e77c348064513052bf90a11952a190d0plougher meta_entry->index_block = cur_index_block - sblk->inode_table_start; 13840aeb6601e77c348064513052bf90a11952a190d0plougher meta_entry->offset = cur_offset; 13850aeb6601e77c348064513052bf90a11952a190d0plougher meta_entry->data_block = cur_data_block; 13860aeb6601e77c348064513052bf90a11952a190d0plougher meta->entries ++; 13870aeb6601e77c348064513052bf90a11952a190d0plougher offset ++; 13880aeb6601e77c348064513052bf90a11952a190d0plougher } 13890aeb6601e77c348064513052bf90a11952a190d0plougher 13900aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", 13910aeb6601e77c348064513052bf90a11952a190d0plougher meta->offset, meta->entries); 13920aeb6601e77c348064513052bf90a11952a190d0plougher 13930aeb6601e77c348064513052bf90a11952a190d0plougher release_meta_index(inode, meta); 13940aeb6601e77c348064513052bf90a11952a190d0plougher } 13950aeb6601e77c348064513052bf90a11952a190d0plougher 13960aeb6601e77c348064513052bf90a11952a190d0plougherall_done: 13970aeb6601e77c348064513052bf90a11952a190d0plougher *index_block = cur_index_block; 13980aeb6601e77c348064513052bf90a11952a190d0plougher *index_offset = cur_offset; 13990aeb6601e77c348064513052bf90a11952a190d0plougher *data_block = cur_data_block; 14000aeb6601e77c348064513052bf90a11952a190d0plougher 14010aeb6601e77c348064513052bf90a11952a190d0plougher return offset * SQUASHFS_META_INDEXES * skip; 14020aeb6601e77c348064513052bf90a11952a190d0plougher 14030aeb6601e77c348064513052bf90a11952a190d0plougherfailed: 14040aeb6601e77c348064513052bf90a11952a190d0plougher release_meta_index(inode, meta); 14050aeb6601e77c348064513052bf90a11952a190d0plougher return -1; 14060aeb6601e77c348064513052bf90a11952a190d0plougher} 14070aeb6601e77c348064513052bf90a11952a190d0plougher 14080aeb6601e77c348064513052bf90a11952a190d0plougher 14090aeb6601e77c348064513052bf90a11952a190d0plougherstatic long long read_blocklist(struct inode *inode, int index, 14100aeb6601e77c348064513052bf90a11952a190d0plougher int readahead_blks, char *block_list, 14110aeb6601e77c348064513052bf90a11952a190d0plougher unsigned short **block_p, unsigned int *bsize) 14120aeb6601e77c348064513052bf90a11952a190d0plougher{ 14130aeb6601e77c348064513052bf90a11952a190d0plougher long long block_ptr; 14140aeb6601e77c348064513052bf90a11952a190d0plougher int offset; 14150aeb6601e77c348064513052bf90a11952a190d0plougher long long block; 14160aeb6601e77c348064513052bf90a11952a190d0plougher int res = get_meta_index(inode, index, &block_ptr, &offset, &block, 14170aeb6601e77c348064513052bf90a11952a190d0plougher block_list); 14180aeb6601e77c348064513052bf90a11952a190d0plougher 14190aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" 14200aeb6601e77c348064513052bf90a11952a190d0plougher " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, 14210aeb6601e77c348064513052bf90a11952a190d0plougher block); 14220aeb6601e77c348064513052bf90a11952a190d0plougher 14230aeb6601e77c348064513052bf90a11952a190d0plougher if(res == -1) 14240aeb6601e77c348064513052bf90a11952a190d0plougher goto failure; 14250aeb6601e77c348064513052bf90a11952a190d0plougher 14260aeb6601e77c348064513052bf90a11952a190d0plougher index -= res; 14270aeb6601e77c348064513052bf90a11952a190d0plougher 14280aeb6601e77c348064513052bf90a11952a190d0plougher while ( index ) { 14290aeb6601e77c348064513052bf90a11952a190d0plougher int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; 14300aeb6601e77c348064513052bf90a11952a190d0plougher int res = read_block_index(inode->i_sb, blocks, block_list, 14310aeb6601e77c348064513052bf90a11952a190d0plougher &block_ptr, &offset); 14320aeb6601e77c348064513052bf90a11952a190d0plougher if (res == -1) 14330aeb6601e77c348064513052bf90a11952a190d0plougher goto failure; 14340aeb6601e77c348064513052bf90a11952a190d0plougher block += res; 14350aeb6601e77c348064513052bf90a11952a190d0plougher index -= blocks; 14360aeb6601e77c348064513052bf90a11952a190d0plougher } 14370aeb6601e77c348064513052bf90a11952a190d0plougher 14380aeb6601e77c348064513052bf90a11952a190d0plougher if (read_block_index(inode->i_sb, 1, block_list, 14390aeb6601e77c348064513052bf90a11952a190d0plougher &block_ptr, &offset) == -1) 14400aeb6601e77c348064513052bf90a11952a190d0plougher goto failure; 14410aeb6601e77c348064513052bf90a11952a190d0plougher *bsize = *((unsigned int *) block_list); 14420aeb6601e77c348064513052bf90a11952a190d0plougher 14430aeb6601e77c348064513052bf90a11952a190d0plougher return block; 14440aeb6601e77c348064513052bf90a11952a190d0plougher 14450aeb6601e77c348064513052bf90a11952a190d0plougherfailure: 14460aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 14470aeb6601e77c348064513052bf90a11952a190d0plougher} 14480aeb6601e77c348064513052bf90a11952a190d0plougher 14490aeb6601e77c348064513052bf90a11952a190d0plougher 14500aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readpage(struct file *file, struct page *page) 14510aeb6601e77c348064513052bf90a11952a190d0plougher{ 14520aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *inode = page->mapping->host; 14530aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb; 14540aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 14550aeb6601e77c348064513052bf90a11952a190d0plougher unsigned char block_list[SIZE]; 14560aeb6601e77c348064513052bf90a11952a190d0plougher long long block; 14570aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int bsize, i = 0, bytes = 0, byte_offset = 0; 14580aeb6601e77c348064513052bf90a11952a190d0plougher int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); 14590aeb6601e77c348064513052bf90a11952a190d0plougher void *pageaddr; 14600aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_fragment_cache *fragment = NULL; 14610aeb6601e77c348064513052bf90a11952a190d0plougher char *data_ptr = msblk->read_page; 14620aeb6601e77c348064513052bf90a11952a190d0plougher 14630aeb6601e77c348064513052bf90a11952a190d0plougher int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; 14640aeb6601e77c348064513052bf90a11952a190d0plougher int start_index = page->index & ~mask; 14650aeb6601e77c348064513052bf90a11952a190d0plougher int end_index = start_index | mask; 14660aeb6601e77c348064513052bf90a11952a190d0plougher 14670aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", 14680aeb6601e77c348064513052bf90a11952a190d0plougher page->index, 14690aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)->start_block); 14700aeb6601e77c348064513052bf90a11952a190d0plougher 14710aeb6601e77c348064513052bf90a11952a190d0plougher if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> 14720aeb6601e77c348064513052bf90a11952a190d0plougher PAGE_CACHE_SHIFT)) 14730aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 14740aeb6601e77c348064513052bf90a11952a190d0plougher 14750aeb6601e77c348064513052bf90a11952a190d0plougher if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 14760aeb6601e77c348064513052bf90a11952a190d0plougher || index < (i_size_read(inode) >> 14770aeb6601e77c348064513052bf90a11952a190d0plougher sblk->block_log)) { 14780aeb6601e77c348064513052bf90a11952a190d0plougher if ((block = (msblk->read_blocklist)(inode, index, 1, 14790aeb6601e77c348064513052bf90a11952a190d0plougher block_list, NULL, &bsize)) == 0) 14800aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 14810aeb6601e77c348064513052bf90a11952a190d0plougher 14820aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->read_page_mutex); 14830aeb6601e77c348064513052bf90a11952a190d0plougher 14840aeb6601e77c348064513052bf90a11952a190d0plougher if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, 14850aeb6601e77c348064513052bf90a11952a190d0plougher block, bsize, NULL))) { 14860aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read page, block %llx, size %x\n", block, 14870aeb6601e77c348064513052bf90a11952a190d0plougher bsize); 14880aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->read_page_mutex); 14890aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 14900aeb6601e77c348064513052bf90a11952a190d0plougher } 14910aeb6601e77c348064513052bf90a11952a190d0plougher } else { 14920aeb6601e77c348064513052bf90a11952a190d0plougher if ((fragment = get_cached_fragment(inode->i_sb, 14930aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> 14940aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_start_block, 14950aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)->u.s1.fragment_size)) 14960aeb6601e77c348064513052bf90a11952a190d0plougher == NULL) { 14970aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read page, block %llx, size %x\n", 14980aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> 14990aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_start_block, 15000aeb6601e77c348064513052bf90a11952a190d0plougher (int) SQUASHFS_I(inode)-> 15010aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_size); 15020aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 15030aeb6601e77c348064513052bf90a11952a190d0plougher } 15040aeb6601e77c348064513052bf90a11952a190d0plougher bytes = SQUASHFS_I(inode)->u.s1.fragment_offset + 15050aeb6601e77c348064513052bf90a11952a190d0plougher (i_size_read(inode) & (sblk->block_size 15060aeb6601e77c348064513052bf90a11952a190d0plougher - 1)); 15070aeb6601e77c348064513052bf90a11952a190d0plougher byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset; 15080aeb6601e77c348064513052bf90a11952a190d0plougher data_ptr = fragment->data; 15090aeb6601e77c348064513052bf90a11952a190d0plougher } 15100aeb6601e77c348064513052bf90a11952a190d0plougher 15110aeb6601e77c348064513052bf90a11952a190d0plougher for (i = start_index; i <= end_index && byte_offset < bytes; 15120aeb6601e77c348064513052bf90a11952a190d0plougher i++, byte_offset += PAGE_CACHE_SIZE) { 15130aeb6601e77c348064513052bf90a11952a190d0plougher struct page *push_page; 15140aeb6601e77c348064513052bf90a11952a190d0plougher int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? 15150aeb6601e77c348064513052bf90a11952a190d0plougher PAGE_CACHE_SIZE : bytes - byte_offset; 15160aeb6601e77c348064513052bf90a11952a190d0plougher 15170aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", 15180aeb6601e77c348064513052bf90a11952a190d0plougher bytes, i, byte_offset, available_bytes); 15190aeb6601e77c348064513052bf90a11952a190d0plougher 15200aeb6601e77c348064513052bf90a11952a190d0plougher if (i == page->index) { 15210aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(page, KM_USER0); 15220aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(pageaddr, data_ptr + byte_offset, 15230aeb6601e77c348064513052bf90a11952a190d0plougher available_bytes); 15240aeb6601e77c348064513052bf90a11952a190d0plougher memset(pageaddr + available_bytes, 0, 15250aeb6601e77c348064513052bf90a11952a190d0plougher PAGE_CACHE_SIZE - available_bytes); 15260aeb6601e77c348064513052bf90a11952a190d0plougher kunmap_atomic(pageaddr, KM_USER0); 15270aeb6601e77c348064513052bf90a11952a190d0plougher flush_dcache_page(page); 15280aeb6601e77c348064513052bf90a11952a190d0plougher SetPageUptodate(page); 15290aeb6601e77c348064513052bf90a11952a190d0plougher UnlockPage(page); 15300aeb6601e77c348064513052bf90a11952a190d0plougher } else if ((push_page = 15310aeb6601e77c348064513052bf90a11952a190d0plougher grab_cache_page_nowait(page->mapping, i))) { 15320aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(push_page, KM_USER0); 15330aeb6601e77c348064513052bf90a11952a190d0plougher 15340aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(pageaddr, data_ptr + byte_offset, 15350aeb6601e77c348064513052bf90a11952a190d0plougher available_bytes); 15360aeb6601e77c348064513052bf90a11952a190d0plougher memset(pageaddr + available_bytes, 0, 15370aeb6601e77c348064513052bf90a11952a190d0plougher PAGE_CACHE_SIZE - available_bytes); 15380aeb6601e77c348064513052bf90a11952a190d0plougher kunmap_atomic(pageaddr, KM_USER0); 15390aeb6601e77c348064513052bf90a11952a190d0plougher flush_dcache_page(push_page); 15400aeb6601e77c348064513052bf90a11952a190d0plougher SetPageUptodate(push_page); 15410aeb6601e77c348064513052bf90a11952a190d0plougher UnlockPage(push_page); 15420aeb6601e77c348064513052bf90a11952a190d0plougher page_cache_release(push_page); 15430aeb6601e77c348064513052bf90a11952a190d0plougher } 15440aeb6601e77c348064513052bf90a11952a190d0plougher } 15450aeb6601e77c348064513052bf90a11952a190d0plougher 15460aeb6601e77c348064513052bf90a11952a190d0plougher if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 15470aeb6601e77c348064513052bf90a11952a190d0plougher || index < (i_size_read(inode) >> 15480aeb6601e77c348064513052bf90a11952a190d0plougher sblk->block_log)) 15490aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->read_page_mutex); 15500aeb6601e77c348064513052bf90a11952a190d0plougher else 15510aeb6601e77c348064513052bf90a11952a190d0plougher release_cached_fragment(msblk, fragment); 15520aeb6601e77c348064513052bf90a11952a190d0plougher 15530aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 15540aeb6601e77c348064513052bf90a11952a190d0plougher 15550aeb6601e77c348064513052bf90a11952a190d0plougherskip_read: 15560aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(page, KM_USER0); 15570aeb6601e77c348064513052bf90a11952a190d0plougher memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 15580aeb6601e77c348064513052bf90a11952a190d0plougher kunmap_atomic(pageaddr, KM_USER0); 15590aeb6601e77c348064513052bf90a11952a190d0plougher flush_dcache_page(page); 15600aeb6601e77c348064513052bf90a11952a190d0plougher SetPageUptodate(page); 15610aeb6601e77c348064513052bf90a11952a190d0plougher UnlockPage(page); 15620aeb6601e77c348064513052bf90a11952a190d0plougher 15630aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 15640aeb6601e77c348064513052bf90a11952a190d0plougher} 15650aeb6601e77c348064513052bf90a11952a190d0plougher 15660aeb6601e77c348064513052bf90a11952a190d0plougher 15670aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readpage4K(struct file *file, struct page *page) 15680aeb6601e77c348064513052bf90a11952a190d0plougher{ 15690aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *inode = page->mapping->host; 15700aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &inode->i_sb->u.squashfs_sb; 15710aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 15720aeb6601e77c348064513052bf90a11952a190d0plougher unsigned char block_list[SIZE]; 15730aeb6601e77c348064513052bf90a11952a190d0plougher long long block; 15740aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int bsize, bytes = 0; 15750aeb6601e77c348064513052bf90a11952a190d0plougher void *pageaddr; 15760aeb6601e77c348064513052bf90a11952a190d0plougher 15770aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n", 15780aeb6601e77c348064513052bf90a11952a190d0plougher page->index, 15790aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)->start_block); 15800aeb6601e77c348064513052bf90a11952a190d0plougher 15810aeb6601e77c348064513052bf90a11952a190d0plougher if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> 15820aeb6601e77c348064513052bf90a11952a190d0plougher PAGE_CACHE_SHIFT)) { 15830aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(page, KM_USER0); 15840aeb6601e77c348064513052bf90a11952a190d0plougher goto skip_read; 15850aeb6601e77c348064513052bf90a11952a190d0plougher } 15860aeb6601e77c348064513052bf90a11952a190d0plougher 15870aeb6601e77c348064513052bf90a11952a190d0plougher if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK 15880aeb6601e77c348064513052bf90a11952a190d0plougher || page->index < (i_size_read(inode) >> 15890aeb6601e77c348064513052bf90a11952a190d0plougher sblk->block_log)) { 15900aeb6601e77c348064513052bf90a11952a190d0plougher block = (msblk->read_blocklist)(inode, page->index, 1, 15910aeb6601e77c348064513052bf90a11952a190d0plougher block_list, NULL, &bsize); 15920aeb6601e77c348064513052bf90a11952a190d0plougher 15930aeb6601e77c348064513052bf90a11952a190d0plougher down(&msblk->read_page_mutex); 15940aeb6601e77c348064513052bf90a11952a190d0plougher bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, 15950aeb6601e77c348064513052bf90a11952a190d0plougher bsize, NULL); 15960aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(page, KM_USER0); 15970aeb6601e77c348064513052bf90a11952a190d0plougher if (bytes) 15980aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(pageaddr, msblk->read_page, bytes); 15990aeb6601e77c348064513052bf90a11952a190d0plougher else 16000aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read page, block %llx, size %x\n", 16010aeb6601e77c348064513052bf90a11952a190d0plougher block, bsize); 16020aeb6601e77c348064513052bf90a11952a190d0plougher up(&msblk->read_page_mutex); 16030aeb6601e77c348064513052bf90a11952a190d0plougher } else { 16040aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_fragment_cache *fragment = 16050aeb6601e77c348064513052bf90a11952a190d0plougher get_cached_fragment(inode->i_sb, 16060aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> 16070aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_start_block, 16080aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> u.s1.fragment_size); 16090aeb6601e77c348064513052bf90a11952a190d0plougher pageaddr = kmap_atomic(page, KM_USER0); 16100aeb6601e77c348064513052bf90a11952a190d0plougher if (fragment) { 16110aeb6601e77c348064513052bf90a11952a190d0plougher bytes = i_size_read(inode) & (sblk->block_size - 1); 16120aeb6601e77c348064513052bf90a11952a190d0plougher memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> 16130aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_offset, bytes); 16140aeb6601e77c348064513052bf90a11952a190d0plougher release_cached_fragment(msblk, fragment); 16150aeb6601e77c348064513052bf90a11952a190d0plougher } else 16160aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read page, block %llx, size %x\n", 16170aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> 16180aeb6601e77c348064513052bf90a11952a190d0plougher u.s1.fragment_start_block, (int) 16190aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(inode)-> u.s1.fragment_size); 16200aeb6601e77c348064513052bf90a11952a190d0plougher } 16210aeb6601e77c348064513052bf90a11952a190d0plougher 16220aeb6601e77c348064513052bf90a11952a190d0plougherskip_read: 16230aeb6601e77c348064513052bf90a11952a190d0plougher memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); 16240aeb6601e77c348064513052bf90a11952a190d0plougher kunmap_atomic(pageaddr, KM_USER0); 16250aeb6601e77c348064513052bf90a11952a190d0plougher flush_dcache_page(page); 16260aeb6601e77c348064513052bf90a11952a190d0plougher SetPageUptodate(page); 16270aeb6601e77c348064513052bf90a11952a190d0plougher UnlockPage(page); 16280aeb6601e77c348064513052bf90a11952a190d0plougher 16290aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 16300aeb6601e77c348064513052bf90a11952a190d0plougher} 16310aeb6601e77c348064513052bf90a11952a190d0plougher 16320aeb6601e77c348064513052bf90a11952a190d0plougher 16330aeb6601e77c348064513052bf90a11952a190d0plougherstatic int get_dir_index_using_offset(struct super_block *s, long long 16340aeb6601e77c348064513052bf90a11952a190d0plougher *next_block, unsigned int *next_offset, 16350aeb6601e77c348064513052bf90a11952a190d0plougher long long index_start, 16360aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int index_offset, int i_count, 16370aeb6601e77c348064513052bf90a11952a190d0plougher long long f_pos) 16380aeb6601e77c348064513052bf90a11952a190d0plougher{ 16390aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 16400aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 16410aeb6601e77c348064513052bf90a11952a190d0plougher int i, length = 0; 16420aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_index index; 16430aeb6601e77c348064513052bf90a11952a190d0plougher 16440aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", 16450aeb6601e77c348064513052bf90a11952a190d0plougher i_count, (unsigned int) f_pos); 16460aeb6601e77c348064513052bf90a11952a190d0plougher 16470aeb6601e77c348064513052bf90a11952a190d0plougher f_pos -= 3; 16480aeb6601e77c348064513052bf90a11952a190d0plougher if (f_pos == 0) 16490aeb6601e77c348064513052bf90a11952a190d0plougher goto finish; 16500aeb6601e77c348064513052bf90a11952a190d0plougher 16510aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < i_count; i++) { 16520aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 16530aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_index sindex; 16540aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, (char *) &sindex, 16550aeb6601e77c348064513052bf90a11952a190d0plougher index_start, index_offset, 16560aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(sindex), &index_start, 16570aeb6601e77c348064513052bf90a11952a190d0plougher &index_offset); 16580aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); 16590aeb6601e77c348064513052bf90a11952a190d0plougher } else 16600aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, (char *) &index, 16610aeb6601e77c348064513052bf90a11952a190d0plougher index_start, index_offset, 16620aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(index), &index_start, 16630aeb6601e77c348064513052bf90a11952a190d0plougher &index_offset); 16640aeb6601e77c348064513052bf90a11952a190d0plougher 16650aeb6601e77c348064513052bf90a11952a190d0plougher if (index.index > f_pos) 16660aeb6601e77c348064513052bf90a11952a190d0plougher break; 16670aeb6601e77c348064513052bf90a11952a190d0plougher 16680aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, NULL, index_start, index_offset, 16690aeb6601e77c348064513052bf90a11952a190d0plougher index.size + 1, &index_start, 16700aeb6601e77c348064513052bf90a11952a190d0plougher &index_offset); 16710aeb6601e77c348064513052bf90a11952a190d0plougher 16720aeb6601e77c348064513052bf90a11952a190d0plougher length = index.index; 16730aeb6601e77c348064513052bf90a11952a190d0plougher *next_block = index.start_block + sblk->directory_table_start; 16740aeb6601e77c348064513052bf90a11952a190d0plougher } 16750aeb6601e77c348064513052bf90a11952a190d0plougher 16760aeb6601e77c348064513052bf90a11952a190d0plougher *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 16770aeb6601e77c348064513052bf90a11952a190d0plougher 16780aeb6601e77c348064513052bf90a11952a190d0plougherfinish: 16790aeb6601e77c348064513052bf90a11952a190d0plougher return length + 3; 16800aeb6601e77c348064513052bf90a11952a190d0plougher} 16810aeb6601e77c348064513052bf90a11952a190d0plougher 16820aeb6601e77c348064513052bf90a11952a190d0plougher 16830aeb6601e77c348064513052bf90a11952a190d0plougherstatic int get_dir_index_using_name(struct super_block *s, long long 16840aeb6601e77c348064513052bf90a11952a190d0plougher *next_block, unsigned int *next_offset, 16850aeb6601e77c348064513052bf90a11952a190d0plougher long long index_start, 16860aeb6601e77c348064513052bf90a11952a190d0plougher unsigned int index_offset, int i_count, 16870aeb6601e77c348064513052bf90a11952a190d0plougher const char *name, int size) 16880aeb6601e77c348064513052bf90a11952a190d0plougher{ 16890aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &s->u.squashfs_sb; 16900aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 16910aeb6601e77c348064513052bf90a11952a190d0plougher int i, length = 0; 16920aeb6601e77c348064513052bf90a11952a190d0plougher char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1]; 16930aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer; 16940aeb6601e77c348064513052bf90a11952a190d0plougher char str[SQUASHFS_NAME_LEN + 1]; 16950aeb6601e77c348064513052bf90a11952a190d0plougher 16960aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); 16970aeb6601e77c348064513052bf90a11952a190d0plougher 16980aeb6601e77c348064513052bf90a11952a190d0plougher strncpy(str, name, size); 16990aeb6601e77c348064513052bf90a11952a190d0plougher str[size] = '\0'; 17000aeb6601e77c348064513052bf90a11952a190d0plougher 17010aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < i_count; i++) { 17020aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 17030aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_index sindex; 17040aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, (char *) &sindex, 17050aeb6601e77c348064513052bf90a11952a190d0plougher index_start, index_offset, 17060aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(sindex), &index_start, 17070aeb6601e77c348064513052bf90a11952a190d0plougher &index_offset); 17080aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_INDEX(index, &sindex); 17090aeb6601e77c348064513052bf90a11952a190d0plougher } else 17100aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, (char *) index, 17110aeb6601e77c348064513052bf90a11952a190d0plougher index_start, index_offset, 17120aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(struct squashfs_dir_index), 17130aeb6601e77c348064513052bf90a11952a190d0plougher &index_start, &index_offset); 17140aeb6601e77c348064513052bf90a11952a190d0plougher 17150aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_get_cached_block(s, index->name, index_start, 17160aeb6601e77c348064513052bf90a11952a190d0plougher index_offset, index->size + 1, 17170aeb6601e77c348064513052bf90a11952a190d0plougher &index_start, &index_offset); 17180aeb6601e77c348064513052bf90a11952a190d0plougher 17190aeb6601e77c348064513052bf90a11952a190d0plougher index->name[index->size + 1] = '\0'; 17200aeb6601e77c348064513052bf90a11952a190d0plougher 17210aeb6601e77c348064513052bf90a11952a190d0plougher if (strcmp(index->name, str) > 0) 17220aeb6601e77c348064513052bf90a11952a190d0plougher break; 17230aeb6601e77c348064513052bf90a11952a190d0plougher 17240aeb6601e77c348064513052bf90a11952a190d0plougher length = index->index; 17250aeb6601e77c348064513052bf90a11952a190d0plougher *next_block = index->start_block + sblk->directory_table_start; 17260aeb6601e77c348064513052bf90a11952a190d0plougher } 17270aeb6601e77c348064513052bf90a11952a190d0plougher 17280aeb6601e77c348064513052bf90a11952a190d0plougher *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; 17290aeb6601e77c348064513052bf90a11952a190d0plougher return length + 3; 17300aeb6601e77c348064513052bf90a11952a190d0plougher} 17310aeb6601e77c348064513052bf90a11952a190d0plougher 17320aeb6601e77c348064513052bf90a11952a190d0plougher 17330aeb6601e77c348064513052bf90a11952a190d0plougherstatic int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) 17340aeb6601e77c348064513052bf90a11952a190d0plougher{ 17350aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *i = file->f_dentry->d_inode; 17360aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb; 17370aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 17380aeb6601e77c348064513052bf90a11952a190d0plougher long long next_block = SQUASHFS_I(i)->start_block + 17390aeb6601e77c348064513052bf90a11952a190d0plougher sblk->directory_table_start; 174067bd5ed1112f4240f5ec66cbbc169bd802abe52cplougher int next_offset = SQUASHFS_I(i)->offset, length = 0, 17410aeb6601e77c348064513052bf90a11952a190d0plougher dir_count; 17420aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_header dirh; 17430aeb6601e77c348064513052bf90a11952a190d0plougher char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; 17440aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; 17450aeb6601e77c348064513052bf90a11952a190d0plougher 17460aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); 17470aeb6601e77c348064513052bf90a11952a190d0plougher 17480aeb6601e77c348064513052bf90a11952a190d0plougher while(file->f_pos < 3) { 17490aeb6601e77c348064513052bf90a11952a190d0plougher char *name; 17500aeb6601e77c348064513052bf90a11952a190d0plougher int size, i_ino; 17510aeb6601e77c348064513052bf90a11952a190d0plougher 17520aeb6601e77c348064513052bf90a11952a190d0plougher if(file->f_pos == 0) { 17530aeb6601e77c348064513052bf90a11952a190d0plougher name = "."; 17540aeb6601e77c348064513052bf90a11952a190d0plougher size = 1; 17550aeb6601e77c348064513052bf90a11952a190d0plougher i_ino = i->i_ino; 17560aeb6601e77c348064513052bf90a11952a190d0plougher } else { 17570aeb6601e77c348064513052bf90a11952a190d0plougher name = ".."; 17580aeb6601e77c348064513052bf90a11952a190d0plougher size = 2; 17590aeb6601e77c348064513052bf90a11952a190d0plougher i_ino = SQUASHFS_I(i)->u.s2.parent_inode; 17600aeb6601e77c348064513052bf90a11952a190d0plougher } 17610aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", 17620aeb6601e77c348064513052bf90a11952a190d0plougher (unsigned int) dirent, name, size, (int) 17630aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos, i_ino, 17640aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_filetype_table[1]); 17650aeb6601e77c348064513052bf90a11952a190d0plougher 17660aeb6601e77c348064513052bf90a11952a190d0plougher if (filldir(dirent, name, size, 17670aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos, i_ino, 17680aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_filetype_table[1]) < 0) { 17690aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Filldir returned less than 0\n"); 17700aeb6601e77c348064513052bf90a11952a190d0plougher goto finish; 17710aeb6601e77c348064513052bf90a11952a190d0plougher } 17720aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos += size; 17730aeb6601e77c348064513052bf90a11952a190d0plougher } 17740aeb6601e77c348064513052bf90a11952a190d0plougher 17750aeb6601e77c348064513052bf90a11952a190d0plougher length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, 17760aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_start, 17770aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_offset, 17780aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_count, 17790aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos); 17800aeb6601e77c348064513052bf90a11952a190d0plougher 17810aeb6601e77c348064513052bf90a11952a190d0plougher while (length < i_size_read(i)) { 17820aeb6601e77c348064513052bf90a11952a190d0plougher /* read directory header */ 17830aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 17840aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_header sdirh; 17850aeb6601e77c348064513052bf90a11952a190d0plougher 17860aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 17870aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, sizeof(sdirh), 17880aeb6601e77c348064513052bf90a11952a190d0plougher &next_block, &next_offset)) 17890aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 17900aeb6601e77c348064513052bf90a11952a190d0plougher 17910aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(sdirh); 17920aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 17930aeb6601e77c348064513052bf90a11952a190d0plougher } else { 17940aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 17950aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, sizeof(dirh), 17960aeb6601e77c348064513052bf90a11952a190d0plougher &next_block, &next_offset)) 17970aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 17980aeb6601e77c348064513052bf90a11952a190d0plougher 17990aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(dirh); 18000aeb6601e77c348064513052bf90a11952a190d0plougher } 18010aeb6601e77c348064513052bf90a11952a190d0plougher 18020aeb6601e77c348064513052bf90a11952a190d0plougher dir_count = dirh.count + 1; 18030aeb6601e77c348064513052bf90a11952a190d0plougher while (dir_count--) { 18040aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 18050aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_entry sdire; 18060aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) 18070aeb6601e77c348064513052bf90a11952a190d0plougher &sdire, next_block, next_offset, 18080aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(sdire), &next_block, 18090aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 18100aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 18110aeb6601e77c348064513052bf90a11952a190d0plougher 18120aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(sdire); 18130aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 18140aeb6601e77c348064513052bf90a11952a190d0plougher } else { 18150aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) 18160aeb6601e77c348064513052bf90a11952a190d0plougher dire, next_block, next_offset, 18170aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*dire), &next_block, 18180aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 18190aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 18200aeb6601e77c348064513052bf90a11952a190d0plougher 18210aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(*dire); 18220aeb6601e77c348064513052bf90a11952a190d0plougher } 18230aeb6601e77c348064513052bf90a11952a190d0plougher 18240aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, dire->name, 18250aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, 18260aeb6601e77c348064513052bf90a11952a190d0plougher dire->size + 1, &next_block, 18270aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 18280aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 18290aeb6601e77c348064513052bf90a11952a190d0plougher 18300aeb6601e77c348064513052bf90a11952a190d0plougher length += dire->size + 1; 18310aeb6601e77c348064513052bf90a11952a190d0plougher 18320aeb6601e77c348064513052bf90a11952a190d0plougher if (file->f_pos >= length) 18330aeb6601e77c348064513052bf90a11952a190d0plougher continue; 18340aeb6601e77c348064513052bf90a11952a190d0plougher 18350aeb6601e77c348064513052bf90a11952a190d0plougher dire->name[dire->size + 1] = '\0'; 18360aeb6601e77c348064513052bf90a11952a190d0plougher 18370aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", 18380aeb6601e77c348064513052bf90a11952a190d0plougher (unsigned int) dirent, dire->name, 18390aeb6601e77c348064513052bf90a11952a190d0plougher dire->size + 1, (int) file->f_pos, 18400aeb6601e77c348064513052bf90a11952a190d0plougher dirh.start_block, dire->offset, 18410aeb6601e77c348064513052bf90a11952a190d0plougher dirh.inode_number + dire->inode_number, 18420aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_filetype_table[dire->type]); 18430aeb6601e77c348064513052bf90a11952a190d0plougher 18440aeb6601e77c348064513052bf90a11952a190d0plougher if (filldir(dirent, dire->name, dire->size + 1, 18450aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos, 18460aeb6601e77c348064513052bf90a11952a190d0plougher dirh.inode_number + dire->inode_number, 18470aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_filetype_table[dire->type]) 18480aeb6601e77c348064513052bf90a11952a190d0plougher < 0) { 18490aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Filldir returned less than 0\n"); 18500aeb6601e77c348064513052bf90a11952a190d0plougher goto finish; 18510aeb6601e77c348064513052bf90a11952a190d0plougher } 18520aeb6601e77c348064513052bf90a11952a190d0plougher file->f_pos = length; 18530aeb6601e77c348064513052bf90a11952a190d0plougher } 18540aeb6601e77c348064513052bf90a11952a190d0plougher } 18550aeb6601e77c348064513052bf90a11952a190d0plougher 18560aeb6601e77c348064513052bf90a11952a190d0plougherfinish: 185767bd5ed1112f4240f5ec66cbbc169bd802abe52cplougher return 0; 18580aeb6601e77c348064513052bf90a11952a190d0plougher 18590aeb6601e77c348064513052bf90a11952a190d0plougherfailed_read: 18600aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read directory block [%llx:%x]\n", next_block, 18610aeb6601e77c348064513052bf90a11952a190d0plougher next_offset); 18620aeb6601e77c348064513052bf90a11952a190d0plougher return 0; 18630aeb6601e77c348064513052bf90a11952a190d0plougher} 18640aeb6601e77c348064513052bf90a11952a190d0plougher 18650aeb6601e77c348064513052bf90a11952a190d0plougher 18660aeb6601e77c348064513052bf90a11952a190d0plougherstatic struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry) 18670aeb6601e77c348064513052bf90a11952a190d0plougher{ 18680aeb6601e77c348064513052bf90a11952a190d0plougher const unsigned char *name = dentry->d_name.name; 18690aeb6601e77c348064513052bf90a11952a190d0plougher int len = dentry->d_name.len; 18700aeb6601e77c348064513052bf90a11952a190d0plougher struct inode *inode = NULL; 18710aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *msblk = &i->i_sb->u.squashfs_sb; 18720aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_super_block *sblk = &msblk->sblk; 18730aeb6601e77c348064513052bf90a11952a190d0plougher long long next_block = SQUASHFS_I(i)->start_block + 18740aeb6601e77c348064513052bf90a11952a190d0plougher sblk->directory_table_start; 18750aeb6601e77c348064513052bf90a11952a190d0plougher int next_offset = SQUASHFS_I(i)->offset, length = 0, 18760aeb6601e77c348064513052bf90a11952a190d0plougher dir_count; 18770aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_header dirh; 18780aeb6601e77c348064513052bf90a11952a190d0plougher char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN]; 18790aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; 18800aeb6601e77c348064513052bf90a11952a190d0plougher 18810aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); 18820aeb6601e77c348064513052bf90a11952a190d0plougher 18830aeb6601e77c348064513052bf90a11952a190d0plougher if (len > SQUASHFS_NAME_LEN) 18840aeb6601e77c348064513052bf90a11952a190d0plougher goto exit_loop; 18850aeb6601e77c348064513052bf90a11952a190d0plougher 18860aeb6601e77c348064513052bf90a11952a190d0plougher length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, 18870aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_start, 18880aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_offset, 18890aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_I(i)->u.s2.directory_index_count, name, 18900aeb6601e77c348064513052bf90a11952a190d0plougher len); 18910aeb6601e77c348064513052bf90a11952a190d0plougher 18920aeb6601e77c348064513052bf90a11952a190d0plougher while (length < i_size_read(i)) { 18930aeb6601e77c348064513052bf90a11952a190d0plougher /* read directory header */ 18940aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 18950aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_header sdirh; 18960aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, 18970aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, sizeof(sdirh), 18980aeb6601e77c348064513052bf90a11952a190d0plougher &next_block, &next_offset)) 18990aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 19000aeb6601e77c348064513052bf90a11952a190d0plougher 19010aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(sdirh); 19020aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); 19030aeb6601e77c348064513052bf90a11952a190d0plougher } else { 19040aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, 19050aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, sizeof(dirh), 19060aeb6601e77c348064513052bf90a11952a190d0plougher &next_block, &next_offset)) 19070aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 19080aeb6601e77c348064513052bf90a11952a190d0plougher 19090aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(dirh); 19100aeb6601e77c348064513052bf90a11952a190d0plougher } 19110aeb6601e77c348064513052bf90a11952a190d0plougher 19120aeb6601e77c348064513052bf90a11952a190d0plougher dir_count = dirh.count + 1; 19130aeb6601e77c348064513052bf90a11952a190d0plougher while (dir_count--) { 19140aeb6601e77c348064513052bf90a11952a190d0plougher if (msblk->swap) { 19150aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_dir_entry sdire; 19160aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) 19170aeb6601e77c348064513052bf90a11952a190d0plougher &sdire, next_block,next_offset, 19180aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(sdire), &next_block, 19190aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 19200aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 19210aeb6601e77c348064513052bf90a11952a190d0plougher 19220aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(sdire); 19230aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); 19240aeb6601e77c348064513052bf90a11952a190d0plougher } else { 19250aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, (char *) 19260aeb6601e77c348064513052bf90a11952a190d0plougher dire, next_block,next_offset, 19270aeb6601e77c348064513052bf90a11952a190d0plougher sizeof(*dire), &next_block, 19280aeb6601e77c348064513052bf90a11952a190d0plougher &next_offset)) 19290aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 19300aeb6601e77c348064513052bf90a11952a190d0plougher 19310aeb6601e77c348064513052bf90a11952a190d0plougher length += sizeof(*dire); 19320aeb6601e77c348064513052bf90a11952a190d0plougher } 19330aeb6601e77c348064513052bf90a11952a190d0plougher 19340aeb6601e77c348064513052bf90a11952a190d0plougher if (!squashfs_get_cached_block(i->i_sb, dire->name, 19350aeb6601e77c348064513052bf90a11952a190d0plougher next_block, next_offset, dire->size + 1, 19360aeb6601e77c348064513052bf90a11952a190d0plougher &next_block, &next_offset)) 19370aeb6601e77c348064513052bf90a11952a190d0plougher goto failed_read; 19380aeb6601e77c348064513052bf90a11952a190d0plougher 19390aeb6601e77c348064513052bf90a11952a190d0plougher length += dire->size + 1; 19400aeb6601e77c348064513052bf90a11952a190d0plougher 19410aeb6601e77c348064513052bf90a11952a190d0plougher if (name[0] < dire->name[0]) 19420aeb6601e77c348064513052bf90a11952a190d0plougher goto exit_loop; 19430aeb6601e77c348064513052bf90a11952a190d0plougher 19440aeb6601e77c348064513052bf90a11952a190d0plougher if ((len == dire->size + 1) && !strncmp(name, 19450aeb6601e77c348064513052bf90a11952a190d0plougher dire->name, len)) { 19460aeb6601e77c348064513052bf90a11952a190d0plougher squashfs_inode_t ino = 19470aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_MKINODE(dirh.start_block, 19480aeb6601e77c348064513052bf90a11952a190d0plougher dire->offset); 19490aeb6601e77c348064513052bf90a11952a190d0plougher 19500aeb6601e77c348064513052bf90a11952a190d0plougher TRACE("calling squashfs_iget for directory " 19510aeb6601e77c348064513052bf90a11952a190d0plougher "entry %s, inode %x:%x, %d\n", name, 19520aeb6601e77c348064513052bf90a11952a190d0plougher dirh.start_block, dire->offset, 19530aeb6601e77c348064513052bf90a11952a190d0plougher dirh.inode_number + dire->inode_number); 19540aeb6601e77c348064513052bf90a11952a190d0plougher 19550aeb6601e77c348064513052bf90a11952a190d0plougher inode = (msblk->iget)(i->i_sb, ino); 19560aeb6601e77c348064513052bf90a11952a190d0plougher 19570aeb6601e77c348064513052bf90a11952a190d0plougher goto exit_loop; 19580aeb6601e77c348064513052bf90a11952a190d0plougher } 19590aeb6601e77c348064513052bf90a11952a190d0plougher } 19600aeb6601e77c348064513052bf90a11952a190d0plougher } 19610aeb6601e77c348064513052bf90a11952a190d0plougher 19620aeb6601e77c348064513052bf90a11952a190d0plougherexit_loop: 19630aeb6601e77c348064513052bf90a11952a190d0plougher d_add(dentry, inode); 19640aeb6601e77c348064513052bf90a11952a190d0plougher return ERR_PTR(0); 19650aeb6601e77c348064513052bf90a11952a190d0plougher 19660aeb6601e77c348064513052bf90a11952a190d0plougherfailed_read: 19670aeb6601e77c348064513052bf90a11952a190d0plougher ERROR("Unable to read directory block [%llx:%x]\n", next_block, 19680aeb6601e77c348064513052bf90a11952a190d0plougher next_offset); 19690aeb6601e77c348064513052bf90a11952a190d0plougher goto exit_loop; 19700aeb6601e77c348064513052bf90a11952a190d0plougher} 19710aeb6601e77c348064513052bf90a11952a190d0plougher 19720aeb6601e77c348064513052bf90a11952a190d0plougher 19730aeb6601e77c348064513052bf90a11952a190d0plougherstatic void squashfs_put_super(struct super_block *s) 19740aeb6601e77c348064513052bf90a11952a190d0plougher{ 19750aeb6601e77c348064513052bf90a11952a190d0plougher int i; 19760aeb6601e77c348064513052bf90a11952a190d0plougher 19770aeb6601e77c348064513052bf90a11952a190d0plougher struct squashfs_sb_info *sbi = &s->u.squashfs_sb; 19780aeb6601e77c348064513052bf90a11952a190d0plougher if (sbi->block_cache) 19790aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) 19800aeb6601e77c348064513052bf90a11952a190d0plougher if (sbi->block_cache[i].block != 19810aeb6601e77c348064513052bf90a11952a190d0plougher SQUASHFS_INVALID_BLK) 19820aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->block_cache[i].data); 19830aeb6601e77c348064513052bf90a11952a190d0plougher if (sbi->fragment) 19840aeb6601e77c348064513052bf90a11952a190d0plougher for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 1985af371d91a8865df5ab3079887b86c76a48b6e405plougher SQUASHFS_FREE(sbi->fragment[i].data); 19860aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->fragment); 19870aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->block_cache); 19880aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->read_data); 19890aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->read_page); 19900aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->uid); 19910aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->fragment_index); 19920aeb6601e77c348064513052bf90a11952a190d0plougher kfree(sbi->fragment_index_2); 1993410dd958c15c73d91e877a0afe085bfaee37d9ffplougher kfree(sbi->meta_index); 1994410dd958c15c73d91e877a0afe085bfaee37d9ffplougher vfree(sbi->stream.workspace); 19950aeb6601e77c348064513052bf90a11952a190d0plougher sbi->block_cache = NULL; 19960aeb6601e77c348064513052bf90a11952a190d0plougher sbi->uid = NULL; 19970aeb6601e77c348064513052bf90a11952a190d0plougher sbi->read_data = NULL; 19980aeb6601e77c348064513052bf90a11952a190d0plougher sbi->read_page = NULL; 19990aeb6601e77c348064513052bf90a11952a190d0plougher sbi->fragment = NULL; 20000aeb6601e77c348064513052bf90a11952a190d0plougher sbi->fragment_index = NULL; 20010aeb6601e77c348064513052bf90a11952a190d0plougher sbi->fragment_index_2 = NULL; 2002410dd958c15c73d91e877a0afe085bfaee37d9ffplougher sbi->meta_index = NULL; 2003410dd958c15c73d91e877a0afe085bfaee37d9ffplougher sbi->stream.workspace = NULL; 20040aeb6601e77c348064513052bf90a11952a190d0plougher} 20050aeb6601e77c348064513052bf90a11952a190d0plougher 20060aeb6601e77c348064513052bf90a11952a190d0plougher 20070aeb6601e77c348064513052bf90a11952a190d0plougherstatic int __init init_squashfs_fs(void) 20080aeb6601e77c348064513052bf90a11952a190d0plougher{ 20090aeb6601e77c348064513052bf90a11952a190d0plougher 2010d09dc28507a55fa82ba904224caea5da2f432360plougher printk(KERN_INFO "squashfs: version 3.1 (2006/08/15) " 20110aeb6601e77c348064513052bf90a11952a190d0plougher "Phillip Lougher\n"); 20120aeb6601e77c348064513052bf90a11952a190d0plougher 20130aeb6601e77c348064513052bf90a11952a190d0plougher return register_filesystem(&squashfs_fs_type); 20140aeb6601e77c348064513052bf90a11952a190d0plougher} 20150aeb6601e77c348064513052bf90a11952a190d0plougher 20160aeb6601e77c348064513052bf90a11952a190d0plougher 20170aeb6601e77c348064513052bf90a11952a190d0plougherstatic void __exit exit_squashfs_fs(void) 20180aeb6601e77c348064513052bf90a11952a190d0plougher{ 20190aeb6601e77c348064513052bf90a11952a190d0plougher unregister_filesystem(&squashfs_fs_type); 20200aeb6601e77c348064513052bf90a11952a190d0plougher} 20210aeb6601e77c348064513052bf90a11952a190d0plougher 20220aeb6601e77c348064513052bf90a11952a190d0plougher 20230aeb6601e77c348064513052bf90a11952a190d0plougherEXPORT_NO_SYMBOLS; 20240aeb6601e77c348064513052bf90a11952a190d0plougher 20250aeb6601e77c348064513052bf90a11952a190d0ploughermodule_init(init_squashfs_fs); 20260aeb6601e77c348064513052bf90a11952a190d0ploughermodule_exit(exit_squashfs_fs); 2027aa8954128ab96f6cb57193e6943c61f1bc6cd631plougherMODULE_DESCRIPTION("squashfs 3.1, a compressed read-only filesystem"); 2028f6cd337f8de328e2b448b9f29c00d9132748f7feplougherMODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>"); 20290aeb6601e77c348064513052bf90a11952a190d0plougherMODULE_LICENSE("GPL"); 2030