Blame view

fs/squashfs/super.c 13.5 KB
0aa666190   Phillip Lougher   Squashfs: super b...
1
2
3
4
  /*
   * Squashfs - a compressed read only filesystem for Linux
   *
   * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
d7f2ff671   Phillip Lougher   Squashfs: update ...
5
   * Phillip Lougher <phillip@squashfs.org.uk>
0aa666190   Phillip Lougher   Squashfs: super b...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2,
   * or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   *
   * super.c
   */
  
  /*
   * This file implements code to read the superblock, read and initialise
   * in-memory structures at mount time, and all the VFS glue code to register
   * the filesystem.
   */
  
  #include <linux/fs.h>
  #include <linux/vfs.h>
  #include <linux/slab.h>
  #include <linux/mutex.h>
  #include <linux/pagemap.h>
  #include <linux/init.h>
  #include <linux/module.h>
1bcbf3133   Qinghuang Feng   btrfs & squashfs:...
37
  #include <linux/magic.h>
4b5397dc2   Phillip Lougher   squashfs: add xat...
38
  #include <linux/xattr.h>
0aa666190   Phillip Lougher   Squashfs: super b...
39
40
41
42
43
  
  #include "squashfs_fs.h"
  #include "squashfs_fs_sb.h"
  #include "squashfs_fs_i.h"
  #include "squashfs.h"
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
44
  #include "decompressor.h"
01e5b4e4e   Phillip Lougher   squashfs: add xat...
45
  #include "xattr.h"
0aa666190   Phillip Lougher   Squashfs: super b...
46
47
  
  static struct file_system_type squashfs_fs_type;
b87221de6   Alexey Dobriyan   const: mark remai...
48
  static const struct super_operations squashfs_super_ops;
0aa666190   Phillip Lougher   Squashfs: super b...
49

4c0f0bb23   Phillip Lougher   Squashfs: add a d...
50
51
  static const struct squashfs_decompressor *supported_squashfs_filesystem(short
  	major, short minor, short id)
0aa666190   Phillip Lougher   Squashfs: super b...
52
  {
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
53
  	const struct squashfs_decompressor *decompressor;
0aa666190   Phillip Lougher   Squashfs: super b...
54
55
56
57
  	if (major < SQUASHFS_MAJOR) {
  		ERROR("Major/Minor mismatch, older Squashfs %d.%d "
  			"filesystems are unsupported
  ", major, minor);
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
58
  		return NULL;
0aa666190   Phillip Lougher   Squashfs: super b...
59
60
61
62
63
64
  	} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
  		ERROR("Major/Minor mismatch, trying to mount newer "
  			"%d.%d filesystem
  ", major, minor);
  		ERROR("Please update your kernel
  ");
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
65
  		return NULL;
0aa666190   Phillip Lougher   Squashfs: super b...
66
  	}
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
67
68
69
70
71
72
73
  	decompressor = squashfs_lookup_decompressor(id);
  	if (!decompressor->supported) {
  		ERROR("Filesystem uses \"%s\" compression. This is not "
  			"supported
  ", decompressor->name);
  		return NULL;
  	}
0aa666190   Phillip Lougher   Squashfs: super b...
74

4c0f0bb23   Phillip Lougher   Squashfs: add a d...
75
  	return decompressor;
0aa666190   Phillip Lougher   Squashfs: super b...
76
77
78
79
80
81
82
83
84
85
86
87
  }
  
  
  static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct squashfs_sb_info *msblk;
  	struct squashfs_super_block *sblk = NULL;
  	char b[BDEVNAME_SIZE];
  	struct inode *root;
  	long long root_inode;
  	unsigned short flags;
  	unsigned int fragments;
37986f63c   Phillip Lougher   Squashfs: add san...
88
  	u64 lookup_table_start, xattr_id_table_start, next_table;
0aa666190   Phillip Lougher   Squashfs: super b...
89
90
91
92
93
94
95
96
97
98
99
100
  	int err;
  
  	TRACE("Entered squashfs_fill_superblock
  ");
  
  	sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL);
  	if (sb->s_fs_info == NULL) {
  		ERROR("Failed to allocate squashfs_sb_info
  ");
  		return -ENOMEM;
  	}
  	msblk = sb->s_fs_info;
7657cacf4   Phillip Lougher   Squashfs: Add an ...
101
  	msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE);
0aa666190   Phillip Lougher   Squashfs: super b...
102
103
104
105
106
107
108
109
110
111
112
113
  	msblk->devblksize_log2 = ffz(~msblk->devblksize);
  
  	mutex_init(&msblk->read_data_mutex);
  	mutex_init(&msblk->meta_index_mutex);
  
  	/*
  	 * msblk->bytes_used is checked in squashfs_read_table to ensure reads
  	 * are not beyond filesystem end.  But as we're using
  	 * squashfs_read_table here to read the superblock (including the value
  	 * of bytes_used) we need to set it to an initial sensible dummy value
  	 */
  	msblk->bytes_used = sizeof(*sblk);
82de647e1   Phillip Lougher   Squashfs: move ta...
114
  	sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk));
0aa666190   Phillip Lougher   Squashfs: super b...
115

82de647e1   Phillip Lougher   Squashfs: move ta...
116
  	if (IS_ERR(sblk)) {
0aa666190   Phillip Lougher   Squashfs: super b...
117
118
  		ERROR("unable to read squashfs_super_block
  ");
82de647e1   Phillip Lougher   Squashfs: move ta...
119
120
  		err = PTR_ERR(sblk);
  		sblk = NULL;
0aa666190   Phillip Lougher   Squashfs: super b...
121
122
  		goto failed_mount;
  	}
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
123
  	err = -EINVAL;
0aa666190   Phillip Lougher   Squashfs: super b...
124
125
126
127
128
129
130
  	/* Check it is a SQUASHFS superblock */
  	sb->s_magic = le32_to_cpu(sblk->s_magic);
  	if (sb->s_magic != SQUASHFS_MAGIC) {
  		if (!silent)
  			ERROR("Can't find a SQUASHFS superblock on %s
  ",
  						bdevname(sb->s_bdev, b));
0aa666190   Phillip Lougher   Squashfs: super b...
131
132
  		goto failed_mount;
  	}
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
133
134
135
  	/* Check the MAJOR & MINOR versions and lookup compression type */
  	msblk->decompressor = supported_squashfs_filesystem(
  			le16_to_cpu(sblk->s_major),
0aa666190   Phillip Lougher   Squashfs: super b...
136
137
  			le16_to_cpu(sblk->s_minor),
  			le16_to_cpu(sblk->compression));
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
138
  	if (msblk->decompressor == NULL)
0aa666190   Phillip Lougher   Squashfs: super b...
139
  		goto failed_mount;
0aa666190   Phillip Lougher   Squashfs: super b...
140
141
142
143
144
145
146
147
148
149
150
  	/* Check the filesystem does not extend beyond the end of the
  	   block device */
  	msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
  	if (msblk->bytes_used < 0 || msblk->bytes_used >
  			i_size_read(sb->s_bdev->bd_inode))
  		goto failed_mount;
  
  	/* Check block size for sanity */
  	msblk->block_size = le32_to_cpu(sblk->block_size);
  	if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
  		goto failed_mount;
fffb47b80   Phillip Lougher   Squashfs: check p...
151
152
153
154
155
156
157
158
159
160
  	/*
  	 * Check the system page size is not larger than the filesystem
  	 * block size (by default 128K).  This is currently not supported.
  	 */
  	if (PAGE_CACHE_SIZE > msblk->block_size) {
  		ERROR("Page size > filesystem block size (%d).  This is "
  			"currently not supported!
  ", msblk->block_size);
  		goto failed_mount;
  	}
0aa666190   Phillip Lougher   Squashfs: super b...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  	msblk->block_log = le16_to_cpu(sblk->block_log);
  	if (msblk->block_log > SQUASHFS_FILE_MAX_LOG)
  		goto failed_mount;
  
  	/* Check the root inode for sanity */
  	root_inode = le64_to_cpu(sblk->root_inode);
  	if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
  		goto failed_mount;
  
  	msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
  	msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
  	msblk->inodes = le32_to_cpu(sblk->inodes);
  	flags = le16_to_cpu(sblk->flags);
  
  	TRACE("Found valid superblock on %s
  ", bdevname(sb->s_bdev, b));
  	TRACE("Inodes are %scompressed
  ", SQUASHFS_UNCOMPRESSED_INODES(flags)
  				? "un" : "");
  	TRACE("Data is %scompressed
  ", SQUASHFS_UNCOMPRESSED_DATA(flags)
  				? "un" : "");
  	TRACE("Filesystem size %lld bytes
  ", msblk->bytes_used);
  	TRACE("Block size %d
  ", msblk->block_size);
  	TRACE("Number of inodes %d
  ", msblk->inodes);
  	TRACE("Number of fragments %d
  ", le32_to_cpu(sblk->fragments));
  	TRACE("Number of ids %d
  ", le16_to_cpu(sblk->no_ids));
  	TRACE("sblk->inode_table_start %llx
  ", msblk->inode_table);
  	TRACE("sblk->directory_table_start %llx
  ", msblk->directory_table);
  	TRACE("sblk->fragment_table_start %llx
  ",
  		(u64) le64_to_cpu(sblk->fragment_table_start));
  	TRACE("sblk->id_table_start %llx
  ",
  		(u64) le64_to_cpu(sblk->id_table_start));
  
  	sb->s_maxbytes = MAX_LFS_FILESIZE;
  	sb->s_flags |= MS_RDONLY;
  	sb->s_op = &squashfs_super_ops;
  
  	err = -ENOMEM;
  
  	msblk->block_cache = squashfs_cache_init("metadata",
  			SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
  	if (msblk->block_cache == NULL)
  		goto failed_mount;
  
  	/* Allocate read_page block */
  	msblk->read_page = squashfs_cache_init("data", 1, msblk->block_size);
  	if (msblk->read_page == NULL) {
  		ERROR("Failed to allocate read_page block
  ");
  		goto failed_mount;
  	}
b7fc0ff09   Phillip Lougher   Squashfs: extend ...
222
223
224
225
226
227
  	msblk->stream = squashfs_decompressor_init(sb, flags);
  	if (IS_ERR(msblk->stream)) {
  		err = PTR_ERR(msblk->stream);
  		msblk->stream = NULL;
  		goto failed_mount;
  	}
76e002f75   Phillip Lougher   Squashfs: reverse...
228
229
230
  	/* Handle xattrs */
  	sb->s_xattr = squashfs_xattr_handlers;
  	xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
37986f63c   Phillip Lougher   Squashfs: add san...
231
232
  	if (xattr_id_table_start == SQUASHFS_INVALID_BLK) {
  		next_table = msblk->bytes_used;
76e002f75   Phillip Lougher   Squashfs: reverse...
233
  		goto allocate_id_index_table;
37986f63c   Phillip Lougher   Squashfs: add san...
234
  	}
76e002f75   Phillip Lougher   Squashfs: reverse...
235
236
237
238
239
240
241
242
243
244
245
246
  
  	/* Allocate and read xattr id lookup table */
  	msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
  		xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
  	if (IS_ERR(msblk->xattr_id_table)) {
  		ERROR("unable to read xattr id index table
  ");
  		err = PTR_ERR(msblk->xattr_id_table);
  		msblk->xattr_id_table = NULL;
  		if (err != -ENOTSUPP)
  			goto failed_mount;
  	}
37986f63c   Phillip Lougher   Squashfs: add san...
247
  	next_table = msblk->xattr_table;
76e002f75   Phillip Lougher   Squashfs: reverse...
248
249
  
  allocate_id_index_table:
0aa666190   Phillip Lougher   Squashfs: super b...
250
251
  	/* Allocate and read id index table */
  	msblk->id_table = squashfs_read_id_index_table(sb,
37986f63c   Phillip Lougher   Squashfs: add san...
252
253
  		le64_to_cpu(sblk->id_table_start), next_table,
  		le16_to_cpu(sblk->no_ids));
0aa666190   Phillip Lougher   Squashfs: super b...
254
  	if (IS_ERR(msblk->id_table)) {
82de647e1   Phillip Lougher   Squashfs: move ta...
255
256
  		ERROR("unable to read id index table
  ");
0aa666190   Phillip Lougher   Squashfs: super b...
257
258
259
260
  		err = PTR_ERR(msblk->id_table);
  		msblk->id_table = NULL;
  		goto failed_mount;
  	}
d5b72ce15   Phillip Lougher   Squashfs: Fix san...
261
  	next_table = le64_to_cpu(msblk->id_table[0]);
0aa666190   Phillip Lougher   Squashfs: super b...
262

76e002f75   Phillip Lougher   Squashfs: reverse...
263
264
265
266
267
268
269
  	/* Handle inode lookup table */
  	lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
  	if (lookup_table_start == SQUASHFS_INVALID_BLK)
  		goto handle_fragments;
  
  	/* Allocate and read inode lookup table */
  	msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
ac51a0a71   Phillip Lougher   Squashfs: add san...
270
  		lookup_table_start, next_table, msblk->inodes);
76e002f75   Phillip Lougher   Squashfs: reverse...
271
272
273
274
275
276
277
  	if (IS_ERR(msblk->inode_lookup_table)) {
  		ERROR("unable to read inode lookup table
  ");
  		err = PTR_ERR(msblk->inode_lookup_table);
  		msblk->inode_lookup_table = NULL;
  		goto failed_mount;
  	}
d5b72ce15   Phillip Lougher   Squashfs: Fix san...
278
  	next_table = le64_to_cpu(msblk->inode_lookup_table[0]);
76e002f75   Phillip Lougher   Squashfs: reverse...
279
280
281
282
  
  	sb->s_export_op = &squashfs_export_ops;
  
  handle_fragments:
0aa666190   Phillip Lougher   Squashfs: super b...
283
284
  	fragments = le32_to_cpu(sblk->fragments);
  	if (fragments == 0)
1094a4a61   Phillip Lougher   Squashfs: add ext...
285
  		goto check_directory_table;
0aa666190   Phillip Lougher   Squashfs: super b...
286
287
288
289
290
291
292
293
294
295
  
  	msblk->fragment_cache = squashfs_cache_init("fragment",
  		SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
  	if (msblk->fragment_cache == NULL) {
  		err = -ENOMEM;
  		goto failed_mount;
  	}
  
  	/* Allocate and read fragment index table */
  	msblk->fragment_index = squashfs_read_fragment_index_table(sb,
1cac63cc9   Phillip Lougher   Squashfs: add san...
296
  		le64_to_cpu(sblk->fragment_table_start), next_table, fragments);
0aa666190   Phillip Lougher   Squashfs: super b...
297
  	if (IS_ERR(msblk->fragment_index)) {
82de647e1   Phillip Lougher   Squashfs: move ta...
298
299
  		ERROR("unable to read fragment index table
  ");
0aa666190   Phillip Lougher   Squashfs: super b...
300
301
302
303
  		err = PTR_ERR(msblk->fragment_index);
  		msblk->fragment_index = NULL;
  		goto failed_mount;
  	}
d5b72ce15   Phillip Lougher   Squashfs: Fix san...
304
  	next_table = le64_to_cpu(msblk->fragment_index[0]);
0aa666190   Phillip Lougher   Squashfs: super b...
305

1094a4a61   Phillip Lougher   Squashfs: add ext...
306
307
  check_directory_table:
  	/* Sanity check directory_table */
cc37f75a9   Phillip Lougher   Squashfs: fix mou...
308
  	if (msblk->directory_table > next_table) {
1094a4a61   Phillip Lougher   Squashfs: add ext...
309
310
311
312
313
314
315
316
317
318
319
  		err = -EINVAL;
  		goto failed_mount;
  	}
  
  	/* Sanity check inode_table */
  	if (msblk->inode_table >= msblk->directory_table) {
  		err = -EINVAL;
  		goto failed_mount;
  	}
  
  	/* allocate root */
0aa666190   Phillip Lougher   Squashfs: super b...
320
321
322
323
324
325
326
327
  	root = new_inode(sb);
  	if (!root) {
  		err = -ENOMEM;
  		goto failed_mount;
  	}
  
  	err = squashfs_read_inode(root, root_inode);
  	if (err) {
1cb08e973   Phillip Lougher   squashfs: fix war...
328
329
  		make_bad_inode(root);
  		iput(root);
0aa666190   Phillip Lougher   Squashfs: super b...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  		goto failed_mount;
  	}
  	insert_inode_hash(root);
  
  	sb->s_root = d_alloc_root(root);
  	if (sb->s_root == NULL) {
  		ERROR("Root inode create failed
  ");
  		err = -ENOMEM;
  		iput(root);
  		goto failed_mount;
  	}
  
  	TRACE("Leaving squashfs_fill_super
  ");
  	kfree(sblk);
  	return 0;
  
  failed_mount:
  	squashfs_cache_delete(msblk->block_cache);
  	squashfs_cache_delete(msblk->fragment_cache);
  	squashfs_cache_delete(msblk->read_page);
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
352
  	squashfs_decompressor_free(msblk, msblk->stream);
0aa666190   Phillip Lougher   Squashfs: super b...
353
354
355
  	kfree(msblk->inode_lookup_table);
  	kfree(msblk->fragment_index);
  	kfree(msblk->id_table);
4b5397dc2   Phillip Lougher   squashfs: add xat...
356
  	kfree(msblk->xattr_id_table);
0aa666190   Phillip Lougher   Squashfs: super b...
357
358
359
360
  	kfree(sb->s_fs_info);
  	sb->s_fs_info = NULL;
  	kfree(sblk);
  	return err;
0aa666190   Phillip Lougher   Squashfs: super b...
361
362
363
364
365
366
  }
  
  
  static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
  	struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
2fc7f562b   Coly Li   fs/squashfs: retu...
367
  	u64 id = huge_encode_dev(dentry->d_sb->s_bdev->bd_dev);
0aa666190   Phillip Lougher   Squashfs: super b...
368
369
370
371
372
373
374
375
376
377
378
  
  	TRACE("Entered squashfs_statfs
  ");
  
  	buf->f_type = SQUASHFS_MAGIC;
  	buf->f_bsize = msblk->block_size;
  	buf->f_blocks = ((msblk->bytes_used - 1) >> msblk->block_log) + 1;
  	buf->f_bfree = buf->f_bavail = 0;
  	buf->f_files = msblk->inodes;
  	buf->f_ffree = 0;
  	buf->f_namelen = SQUASHFS_NAME_LEN;
2fc7f562b   Coly Li   fs/squashfs: retu...
379
380
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
0aa666190   Phillip Lougher   Squashfs: super b...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
  
  	return 0;
  }
  
  
  static int squashfs_remount(struct super_block *sb, int *flags, char *data)
  {
  	*flags |= MS_RDONLY;
  	return 0;
  }
  
  
  static void squashfs_put_super(struct super_block *sb)
  {
  	if (sb->s_fs_info) {
  		struct squashfs_sb_info *sbi = sb->s_fs_info;
  		squashfs_cache_delete(sbi->block_cache);
  		squashfs_cache_delete(sbi->fragment_cache);
  		squashfs_cache_delete(sbi->read_page);
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
400
  		squashfs_decompressor_free(sbi, sbi->stream);
0aa666190   Phillip Lougher   Squashfs: super b...
401
402
403
  		kfree(sbi->id_table);
  		kfree(sbi->fragment_index);
  		kfree(sbi->meta_index);
370ec3d1e   Phillip Lougher   squashfs: add mis...
404
  		kfree(sbi->inode_lookup_table);
4b5397dc2   Phillip Lougher   squashfs: add xat...
405
  		kfree(sbi->xattr_id_table);
0aa666190   Phillip Lougher   Squashfs: super b...
406
407
408
409
  		kfree(sb->s_fs_info);
  		sb->s_fs_info = NULL;
  	}
  }
003a3194d   Phillip Lougher   Squashfs: wrap sq...
410
411
  static struct dentry *squashfs_mount(struct file_system_type *fs_type,
  				int flags, const char *dev_name, void *data)
0aa666190   Phillip Lougher   Squashfs: super b...
412
  {
152a08366   Al Viro   new helper: mount...
413
  	return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
0aa666190   Phillip Lougher   Squashfs: super b...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  }
  
  
  static struct kmem_cache *squashfs_inode_cachep;
  
  
  static void init_once(void *foo)
  {
  	struct squashfs_inode_info *ei = foo;
  
  	inode_init_once(&ei->vfs_inode);
  }
  
  
  static int __init init_inodecache(void)
  {
  	squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
  		sizeof(struct squashfs_inode_info), 0,
  		SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once);
  
  	return squashfs_inode_cachep ? 0 : -ENOMEM;
  }
  
  
  static void destroy_inodecache(void)
  {
  	kmem_cache_destroy(squashfs_inode_cachep);
  }
  
  
  static int __init init_squashfs_fs(void)
  {
  	int err = init_inodecache();
  
  	if (err)
  		return err;
  
  	err = register_filesystem(&squashfs_fs_type);
  	if (err) {
  		destroy_inodecache();
  		return err;
  	}
118e1ef6f   Phillip Lougher   Squashfs: Fix oop...
456
  	printk(KERN_INFO "squashfs: version 4.0 (2009/01/31) "
0aa666190   Phillip Lougher   Squashfs: super b...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
  		"Phillip Lougher
  ");
  
  	return 0;
  }
  
  
  static void __exit exit_squashfs_fs(void)
  {
  	unregister_filesystem(&squashfs_fs_type);
  	destroy_inodecache();
  }
  
  
  static struct inode *squashfs_alloc_inode(struct super_block *sb)
  {
  	struct squashfs_inode_info *ei =
  		kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
  
  	return ei ? &ei->vfs_inode : NULL;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
478
  static void squashfs_i_callback(struct rcu_head *head)
0aa666190   Phillip Lougher   Squashfs: super b...
479
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
480
  	struct inode *inode = container_of(head, struct inode, i_rcu);
0aa666190   Phillip Lougher   Squashfs: super b...
481
482
  	kmem_cache_free(squashfs_inode_cachep, squashfs_i(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
483
484
485
486
  static void squashfs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, squashfs_i_callback);
  }
0aa666190   Phillip Lougher   Squashfs: super b...
487
488
489
490
  
  static struct file_system_type squashfs_fs_type = {
  	.owner = THIS_MODULE,
  	.name = "squashfs",
152a08366   Al Viro   new helper: mount...
491
  	.mount = squashfs_mount,
0aa666190   Phillip Lougher   Squashfs: super b...
492
493
494
  	.kill_sb = kill_block_super,
  	.fs_flags = FS_REQUIRES_DEV
  };
b87221de6   Alexey Dobriyan   const: mark remai...
495
  static const struct super_operations squashfs_super_ops = {
0aa666190   Phillip Lougher   Squashfs: super b...
496
497
498
499
500
501
502
503
504
505
  	.alloc_inode = squashfs_alloc_inode,
  	.destroy_inode = squashfs_destroy_inode,
  	.statfs = squashfs_statfs,
  	.put_super = squashfs_put_super,
  	.remount_fs = squashfs_remount
  };
  
  module_init(init_squashfs_fs);
  module_exit(exit_squashfs_fs);
  MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
d7f2ff671   Phillip Lougher   Squashfs: update ...
506
  MODULE_AUTHOR("Phillip Lougher <phillip@squashfs.org.uk>");
0aa666190   Phillip Lougher   Squashfs: super b...
507
  MODULE_LICENSE("GPL");