super.c revision 1aef9e4f12365714fd95ac9a7a059ea4c7d6d846
1cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen/*
2cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * Squashfs - a compressed read only filesystem for Linux
3cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen *
4cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * Phillip Lougher <phillip@lougher.demon.co.uk>
6cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen *
7cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * This program is free software; you can redistribute it and/or
8cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * modify it under the terms of the GNU General Public License
9cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * as published by the Free Software Foundation; either version 2,
10cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * or (at your option) any later version.
11cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen *
12cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * This program is distributed in the hope that it will be useful,
13cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * GNU General Public License for more details.
16dd479e9769eceee9fcc34e2173376024f3aa3c5fJakob Stoklund Olesen *
175907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen * You should have received a copy of the GNU General Public License
18cfafc54040cc9722995558124f253d05a038176bJakob Stoklund Olesen * along with this program; if not, write to the Free Software
19f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesen * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen *
21cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * super.c
22b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen */
23d0bb5e2ca05d9c942223bf05e5940bb0c6cc9d3fJakob Stoklund Olesen
24cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen/*
250db841f9c2b9a25fb5ecb36e350d3a802c35654cJakob Stoklund Olesen * This file implements code to read the superblock, read and initialise
26cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * in-memory structures at mount time, and all the VFS glue code to register
27cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen * the filesystem.
28cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen */
29cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
30b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen#include <linux/fs.h>
31cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/vfs.h>
32cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/slab.h>
33f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesen#include <linux/vmalloc.h>
34cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/mutex.h>
35cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/pagemap.h>
36cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/init.h>
37cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/module.h>
38cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/zlib.h>
39cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/squashfs_fs.h>
4000005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen#include <linux/squashfs_fs_sb.h>
41cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include <linux/squashfs_fs_i.h>
42cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
43cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen#include "squashfs.h"
44533f58ecdd8a4732c2f0e149387c4d8d8d4142deJakob Stoklund Olesen
45cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic struct file_system_type squashfs_fs_type;
4698d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesenstatic struct super_operations squashfs_super_ops;
4798d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen
48cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic int supported_squashfs_filesystem(short major, short minor, short comp)
49cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen{
500db841f9c2b9a25fb5ecb36e350d3a802c35654cJakob Stoklund Olesen	int err = 0;
510db841f9c2b9a25fb5ecb36e350d3a802c35654cJakob Stoklund Olesen
520db841f9c2b9a25fb5ecb36e350d3a802c35654cJakob Stoklund Olesen	if (major < SQUASHFS_MAJOR) {
530db841f9c2b9a25fb5ecb36e350d3a802c35654cJakob Stoklund Olesen		ERROR("Major/Minor mismatch, older Squashfs %d.%d "
54a67f14bf53737f9bb0afefa28e08c4aac6ec4804Benjamin Kramer			"filesystems are unsupported\n", major, minor);
5500005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		err = -EINVAL;
56708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen	} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
57708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen		ERROR("Major/Minor mismatch, trying to mount newer "
58708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen			"%d.%d filesystem\n", major, minor);
59708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen		ERROR("Please update your kernel\n");
60708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen		err = -EINVAL;
61708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen	}
62708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen
63708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen	if (comp != ZLIB_COMPRESSION)
64708d06f7fb5dfd9c8559aea07b042a88c65645f8Jakob Stoklund Olesen		err = -EINVAL;
65cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
66cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	return err;
67cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen}
68cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
6992a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
7092a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesenstatic int squashfs_fill_super(struct super_block *sb, void *data, int silent)
7192a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen{
7292a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen	struct squashfs_sb_info *msblk;
73cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	struct squashfs_super_block *sblk = NULL;
74cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	char b[BDEVNAME_SIZE];
75cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	struct inode *root;
76cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	long long root_inode;
77b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen	unsigned short flags;
78cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	unsigned int fragments;
79f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesen	long long lookup_table_start;
80d0bb5e2ca05d9c942223bf05e5940bb0c6cc9d3fJakob Stoklund Olesen	int err;
81b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen
82b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen	TRACE("Entered squashfs_fill_superblock\n");
83f42b66169d75301346e3685fd2b3e45e47806367Jakob Stoklund Olesen
84f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesen	sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
85cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	if (sb->s_fs_info == NULL) {
86cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		ERROR("Failed to allocate squashfs_sb_info\n");
8798d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen		goto failure2;
881a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	}
8922a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	msblk = sb->s_fs_info;
9022a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen
9122a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize());
9222a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	if (msblk->stream.workspace == NULL) {
9322a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		ERROR("Failed to allocate zlib workspace\n");
9422a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		goto failure;
9522a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	}
9622a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen
9722a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
9822a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	if (sblk == NULL) {
9922a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		ERROR("Failed to allocate squashfs_super_block\n");
10022a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		goto failure;
10122a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	}
10222a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen
10322a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
104fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	msblk->devblksize_log2 = ffz(~msblk->devblksize);
105fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen
106fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	mutex_init(&msblk->read_data_mutex);
107fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	mutex_init(&msblk->read_page_mutex);
108fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	mutex_init(&msblk->meta_index_mutex);
109fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen
110fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	/*
111fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	 * msblk->bytes_used is checked in squashfs_read_data to ensure reads
112fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	 * are not beyond filesystem end.  But as we're using squashfs_read_data
11349743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesen	 * here to read the superblock (including the value of
11449743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesen	 * bytes_used) we need to set it to an initial sensible dummy value
11549743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesen	 */
11649743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesen	msblk->bytes_used = sizeof(*sblk);
11749743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesen	err = squashfs_read_data(sb, sblk, SQUASHFS_START, sizeof(*sblk) |
118fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen			SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(*sblk));
119fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen
120fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	if (err < 0) {
121fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen		ERROR("unable to read squashfs_super_block\n");
122fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen		goto failed_mount;
123fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	}
12422a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen
12522a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	/* Check it is a SQUASHFS superblock */
126b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesen	sb->s_magic = le32_to_cpu(sblk->s_magic);
127b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesen	if (sb->s_magic != SQUASHFS_MAGIC) {
1281a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen		if (!silent)
1291a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen			ERROR("Can't find a SQUASHFS superblock on %s\n",
1301a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen						bdevname(sb->s_bdev, b));
1311a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen		err = -EINVAL;
1321a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen		goto failed_mount;
1331a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	}
1341a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
1351a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	/* Check the MAJOR & MINOR versions and compression type */
1361a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
1371a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen			le16_to_cpu(sblk->s_minor),
1381a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen			le16_to_cpu(sblk->compression));
13922a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	if (err < 0)
14022a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		goto failed_mount;
1411a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
1421a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	err = -EINVAL;
1431a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
1441a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	/* Check the filesystem does not extend beyond the end of the
1451a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	   block device */
1461a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
14722a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	if (msblk->bytes_used < 0 || msblk->bytes_used >
14822a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen			i_size_read(sb->s_bdev->bd_inode))
14922a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen		goto failed_mount;
15022a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen
1511a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	/* Check block size for sanity */
152f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen	msblk->block_size = le32_to_cpu(sblk->block_size);
153f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen	if (msblk->block_size > SQUASHFS_FILE_SIZE)
1541a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen		goto failed_mount;
1551a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
156f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen	msblk->block_log = le16_to_cpu(sblk->block_log);
15722a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen	if (msblk->block_log > SQUASHFS_FILE_LOG)
158cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		goto failed_mount;
15951458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen
16051458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	/* Check the root inode for sanity */
16151458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	root_inode = le64_to_cpu(sblk->root_inode);
16251458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
16351458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen		goto failed_mount;
16451458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen
16551458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
16651458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
16751458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	msblk->inodes = le32_to_cpu(sblk->inodes);
16851458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	flags = le16_to_cpu(sblk->flags);
16951458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen
17051458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
17151458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen	TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(flags)
17251458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen				? "un" : "");
173b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen	TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(flags)
17422a1df6bf24c188dd637a0bb2cf9a2648806b6b1Jakob Stoklund Olesen				? "un" : "");
175bece06f0c6936527e2b1c72d09f7d3a949af9a47Jakob Stoklund Olesen	TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
176b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen	TRACE("Block size %d\n", msblk->block_size);
177eda0fe8d58b0aaff5f18e7f13edfda3022384e70Jakob Stoklund Olesen	TRACE("Number of inodes %d\n", msblk->inodes);
178eda0fe8d58b0aaff5f18e7f13edfda3022384e70Jakob Stoklund Olesen	TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
179eda0fe8d58b0aaff5f18e7f13edfda3022384e70Jakob Stoklund Olesen	TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
1807b41fbe87234f3ceef6ae11209730cbed4b69092Jakob Stoklund Olesen	TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
18196dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	TRACE("sblk->directory_table_start %llx\n",
182b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen				msblk->directory_table_start);
18396dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	TRACE("sblk->fragment_table_start %llx\n",
18496dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen				le64_to_cpu(sblk->fragment_table_start));
18500005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	TRACE("sblk->id_table_start %llx\n", le64_to_cpu(sblk->id_table_start));
18696dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen
18700005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	sb->s_maxbytes = MAX_LFS_FILESIZE;
18800005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	sb->s_flags |= MS_RDONLY;
18900005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	sb->s_op = &squashfs_super_ops;
19000005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen
19100005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	err = -ENOMEM;
192c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen
19300005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	msblk->block_cache = squashfs_cache_init("metadata",
19400005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen			SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE, 0);
19596dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	if (msblk->block_cache == NULL)
1965db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen		goto failed_mount;
1975db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen
198c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen	/* Allocate read_page block */
1995db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen	msblk->read_page = vmalloc(msblk->block_size);
20000005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	if (msblk->read_page == NULL) {
201c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen		ERROR("Failed to allocate read_page block\n");
2025db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen		goto failed_mount;
2035db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen	}
2045db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen
20500005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	/* Allocate and read id index table */
20600005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	msblk->id_table = read_id_index_table(sb,
20700005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
20800005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	if (IS_ERR(msblk->id_table)) {
20900005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		err = PTR_ERR(msblk->id_table);
21000005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		msblk->id_table = NULL;
21100005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		goto failed_mount;
21200005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	}
21300005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen
21400005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	fragments = le32_to_cpu(sblk->fragments);
21500005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	if (fragments == 0)
21600005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		goto allocate_lookup_table;
21796dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen
21896dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	msblk->fragment_cache = squashfs_cache_init("fragment",
21996dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen		SQUASHFS_CACHED_FRAGMENTS, msblk->block_size, 1);
22096dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	if (msblk->fragment_cache == NULL) {
22196dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen		err = -ENOMEM;
22296dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen		goto failed_mount;
22396dcd95a45968de6cb05864cf91aae33169cf179Jakob Stoklund Olesen	}
22400005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen
22500005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	/* Allocate and read fragment index table */
22600005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	msblk->fragment_index = read_fragment_index_table(sb,
22700005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		le64_to_cpu(sblk->fragment_table_start), fragments);
22800005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	if (IS_ERR(msblk->fragment_index)) {
22900005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen		err = PTR_ERR(msblk->fragment_index);
230cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		msblk->fragment_index = NULL;
231cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		goto failed_mount;
232cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	}
233cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
234cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenallocate_lookup_table:
235533f58ecdd8a4732c2f0e149387c4d8d8d4142deJakob Stoklund Olesen	lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
236cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	if (lookup_table_start == SQUASHFS_INVALID_BLK)
237cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		goto allocate_root;
238cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
239cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	/* Allocate and read inode lookup table */
240cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	msblk->inode_lookup_table = read_inode_lookup_table(sb,
241cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		lookup_table_start, msblk->inodes);
24298d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen	if (IS_ERR(msblk->inode_lookup_table)) {
24398d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen		err = PTR_ERR(msblk->inode_lookup_table);
244ccdb3fcef9aeb9f683cd738afbe1cd961bb0c1efJakob Stoklund Olesen		msblk->inode_lookup_table = NULL;
245ccdb3fcef9aeb9f683cd738afbe1cd961bb0c1efJakob Stoklund Olesen		goto failed_mount;
246cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	}
247cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
248cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	sb->s_export_op = &squashfs_export_ops;
249cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
250cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenallocate_root:
251b853e6c3702149cdbbd6fa404334e3ba0055641aAndrew Trick	root = new_inode(sb);
252b853e6c3702149cdbbd6fa404334e3ba0055641aAndrew Trick	if (!root) {
25392a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen		err = -ENOMEM;
2547792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen		goto failed_mount;
2551d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen	}
256f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen
25792a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen	err = squashfs_read_inode(root, root_inode);
258200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen	if (err) {
259f4afdfc501b7185d24a0ef184fe3d0c0bbe22e0cJakob Stoklund Olesen		iget_failed(root);
260f4afdfc501b7185d24a0ef184fe3d0c0bbe22e0cJakob Stoklund Olesen		goto failed_mount;
261c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen	}
262c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen	insert_inode_hash(root);
26387972fa63f0e2631778166e0c258c456ec12db7cJakob Stoklund Olesen
26400005782fa860f4b48b3b5261d92541c61ee2495Jakob Stoklund Olesen	sb->s_root = d_alloc_root(root);
265034a80d065358b412cdd270e08fb6f1986e65e50Jakob Stoklund Olesen	if (sb->s_root == NULL) {
26651458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen		ERROR("Root inode create failed\n");
26751458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen		err = -ENOMEM;
26851458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen		iput(root);
26951458ed09e6db0e424cd528e10b879f59915abe4Jakob Stoklund Olesen		goto failed_mount;
270b64d92e29f38002e52a22fe36ea2d488968e3537Jakob Stoklund Olesen	}
2716bfba2e5af163442a1c6b11fe14aa9df9101cfd7Jakob Stoklund Olesen
2726bfba2e5af163442a1c6b11fe14aa9df9101cfd7Jakob Stoklund Olesen	TRACE("Leaving squashfs_fill_super\n");
27398c8141b6d8fcbb9bd258ebcdd4171f55c5a8e9dJakob Stoklund Olesen	kfree(sblk);
2746bfba2e5af163442a1c6b11fe14aa9df9101cfd7Jakob Stoklund Olesen	return 0;
275b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen
276b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesenfailed_mount:
277dab35d33ae17353cb01aaaa42abbcb28b33eb98aJakob Stoklund Olesen	squashfs_cache_delete(msblk->block_cache);
278dab35d33ae17353cb01aaaa42abbcb28b33eb98aJakob Stoklund Olesen	squashfs_cache_delete(msblk->fragment_cache);
279034a80d065358b412cdd270e08fb6f1986e65e50Jakob Stoklund Olesen	kfree(msblk->inode_lookup_table);
280034a80d065358b412cdd270e08fb6f1986e65e50Jakob Stoklund Olesen	kfree(msblk->fragment_index);
281b64d92e29f38002e52a22fe36ea2d488968e3537Jakob Stoklund Olesen	kfree(msblk->id_table);
282b64d92e29f38002e52a22fe36ea2d488968e3537Jakob Stoklund Olesen	vfree(msblk->read_page);
283cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	vfree(msblk->stream.workspace);
284cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	kfree(sb->s_fs_info);
285cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	sb->s_fs_info = NULL;
286cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	kfree(sblk);
287cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	return err;
288b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesen
289b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesenfailure:
290fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	vfree(msblk->stream.workspace);
291fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	kfree(sb->s_fs_info);
292fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	sb->s_fs_info = NULL;
29349743b18f50ac0f7e065f4754a26965d4db388deJakob Stoklund Olesenfailure2:
294fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	return -ENOMEM;
295fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen}
296b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesen
297b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesen
298b8d936bc179ddf31b6350015d74900b74db6b450Jakob Stoklund Olesenstatic int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
299200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen{
300200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen	struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
301200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen
302200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen	TRACE("Entered squashfs_statfs\n");
303200729882a47535d4c2496283d26600171531fadJakob Stoklund Olesen
304cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	buf->f_type = SQUASHFS_MAGIC;
305cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	buf->f_bsize = msblk->block_size;
306cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
307cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	buf->f_bfree = buf->f_bavail = 0;
3081a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	buf->f_files = msblk->inodes;
309cfafc54040cc9722995558124f253d05a038176bJakob Stoklund Olesen	buf->f_ffree = 0;
310b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen	buf->f_namelen = SQUASHFS_NAME_LEN;
311cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
312cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	return 0;
313cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen}
3145b220213bfe9c37c2bb41a7ae0804e06a14f1007Rafael Espindola
315cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
316cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic int squashfs_remount(struct super_block *sb, int *flags, char *data)
317cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen{
318cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	*flags |= MS_RDONLY;
319cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	return 0;
320b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen}
321b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen
322cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
323cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic void squashfs_put_super(struct super_block *sb)
324cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen{
325cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	if (sb->s_fs_info) {
326cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		struct squashfs_sb_info *sbi = sb->s_fs_info;
327cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		squashfs_cache_delete(sbi->block_cache);
328cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		squashfs_cache_delete(sbi->fragment_cache);
329b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen		vfree(sbi->read_page);
330cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		kfree(sbi->id_table);
331cfafc54040cc9722995558124f253d05a038176bJakob Stoklund Olesen		kfree(sbi->fragment_index);
332cfafc54040cc9722995558124f253d05a038176bJakob Stoklund Olesen		kfree(sbi->meta_index);
333cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		vfree(sbi->stream.workspace);
334cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen		kfree(sb->s_fs_info);
33527215676c7114132a0374f7b5c9ea73d9354d329Jakob Stoklund Olesen		sb->s_fs_info = NULL;
336cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	}
337cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen}
338cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
339f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesen
340f428eb6c1b09a2322b7a577b0bf2e49dd107bceaJakob Stoklund Olesenstatic int squashfs_get_sb(struct file_system_type *fs_type, int flags,
341cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen				const char *dev_name, void *data,
342cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen				struct vfsmount *mnt)
343cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen{
344cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen	return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
345b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen				mnt);
346b5fa9333431673aac2ced8dea80152349a85cf6fJakob Stoklund Olesen}
347cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
348cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
349cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic struct kmem_cache *squashfs_inode_cachep;
35092a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
35192a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
35292a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesenstatic void init_once(void *foo)
35392a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen{
35492a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen	struct squashfs_inode_info *ei = foo;
35592a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
35692a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen	inode_init_once(&ei->vfs_inode);
35792a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen}
35892a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
35992a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
3607792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesenstatic int __init init_inodecache(void)
3617792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen{
3627792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen	squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
3637792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen		sizeof(struct squashfs_inode_info), 0,
3647792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen		SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
3657792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen
3667792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen	return squashfs_inode_cachep ? 0 : -ENOMEM;
3677792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen}
3687792e980c43536814ea42448db9799b4da32fef6Jakob Stoklund Olesen
36992a55f4bdd120cdd3bb5a004c792d4d24a940311Jakob Stoklund Olesen
3701d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesenstatic void destroy_inodecache(void)
3711d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen{
3721d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen	kmem_cache_destroy(squashfs_inode_cachep);
3731d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen}
3741d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen
3751d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen
3761d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesenstatic int __init init_squashfs_fs(void)
3771d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen{
3781d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen	int err = init_inodecache();
3791d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen
3801d5b84508173b93faf513032b3847152e6060791Jakob Stoklund Olesen	if (err)
381f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen		goto out;
382f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen
383165e231c4295deb5cabd124d08e231b551bcc0b2Jakob Stoklund Olesen	err = register_filesystem(&squashfs_fs_type);
384165e231c4295deb5cabd124d08e231b551bcc0b2Jakob Stoklund Olesen	if (err) {
385f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen		destroy_inodecache();
386165e231c4295deb5cabd124d08e231b551bcc0b2Jakob Stoklund Olesen		goto out;
3871a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	}
3881a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
389f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen	printk(KERN_INFO "squashfs: version 4.0 (2008/10/20) "
390f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen		"Phillip Lougher\n");
391cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
392cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenout:
3931a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen	return err;
3945db4289e404d76664f8aabe2675a4cc2d7b0e98eJakob Stoklund Olesen}
395cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
396cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesen
397cba2e06d525b723849cd8e1f083eb1e59a494b4eJakob Stoklund Olesenstatic void __exit exit_squashfs_fs(void)
39898d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen{
39998d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen	unregister_filesystem(&squashfs_fs_type);
40098d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen	destroy_inodecache();
401107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen}
402107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen
40398d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen
40498d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesenstatic struct inode *squashfs_alloc_inode(struct super_block *sb)
405107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen{
40690c1d7ddfc65654f7efe72d56cad65d1af9e6b2aJakob Stoklund Olesen	struct squashfs_inode_info *ei =
4071a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen		kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
4081a988004dba412deb5d6b8e93b955dfc837065f0Jakob Stoklund Olesen
409fa89a0344bba7a0ae87d3de204d18bb1ecaa5955Jakob Stoklund Olesen	return ei ? &ei->vfs_inode : NULL;
410f22ca3fe5f0cfbb832cf41270f97cf5c0134fd7bJakob Stoklund Olesen}
411cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesen
412eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen
413eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesenstatic void squashfs_destroy_inode(struct inode *inode)
414eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen{
415cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesen	kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
416cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesen}
417cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesen
418cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesen
419cc07e04262fe4bc35469fbadc53d2ec7bfd02fe2Jakob Stoklund Olesenstatic struct file_system_type squashfs_fs_type = {
420eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen	.owner = THIS_MODULE,
421eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen	.name = "squashfs",
422107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen	.get_sb = squashfs_get_sb,
423d2a50734234a80893ad71da90d9f32032c47e000Jakob Stoklund Olesen	.kill_sb = kill_block_super,
424eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen	.fs_flags = FS_REQUIRES_DEV
425eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen};
426eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesen
427eb29157d80847c207b77910bcd40a6a6c91ca5c5Jakob Stoklund Olesenstatic struct super_operations squashfs_super_ops = {
428107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen	.alloc_inode = squashfs_alloc_inode,
429107d366df762c18294dc00f5de916f62672353ffJakob Stoklund Olesen	.destroy_inode = squashfs_destroy_inode,
43090c1d7ddfc65654f7efe72d56cad65d1af9e6b2aJakob Stoklund Olesen	.statfs = squashfs_statfs,
43190c1d7ddfc65654f7efe72d56cad65d1af9e6b2aJakob Stoklund Olesen	.put_super = squashfs_put_super,
43298d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen	.remount_fs = squashfs_remount
43398d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen};
43498d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesen
43598d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesenmodule_init(init_squashfs_fs);
43698d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund Olesenmodule_exit(exit_squashfs_fs);
43798d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund OlesenMODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
43898d9648de7d571b2e6d139b65961a70d1833b0d7Jakob Stoklund OlesenMODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
439770d42de3b7643b2b4f835f32e3a16275b9fbdbaJakob Stoklund OlesenMODULE_LICENSE("GPL");
4406bfba2e5af163442a1c6b11fe14aa9df9101cfd7Jakob Stoklund Olesen