Ignore:
Timestamp:
Mar 12, 2017, 3:18:59 PM (4 months ago)
Author:
brainslayer
Message:

new fs is compatible with standard squashfs, just smaller

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/linux/universal/linux-4.9/fs/squashfs/inode.c

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