1217f752a5a93169f0d547a33c542d085d5f7a8d6plougher/*
2217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * Squashfs - a compressed read only filesystem for Linux
3217f752a5a93169f0d547a33c542d085d5f7a8d6plougher *
4217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * Phillip Lougher <phillip@lougher.demon.co.uk>
6217f752a5a93169f0d547a33c542d085d5f7a8d6plougher *
7217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * This program is free software; you can redistribute it and/or
8217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * modify it under the terms of the GNU General Public License
9217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * as published by the Free Software Foundation; either version 2,
10217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * or (at your option) any later version.
11217f752a5a93169f0d547a33c542d085d5f7a8d6plougher *
12217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * This program is distributed in the hope that it will be useful,
13217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * but WITHOUT ANY WARRANTY; without even the implied warranty of
14217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * GNU General Public License for more details.
16217f752a5a93169f0d547a33c542d085d5f7a8d6plougher *
17217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * You should have received a copy of the GNU General Public License
18217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * along with this program; if not, write to the Free Software
19a3e28ecaf227d2c03ec6724dd718e3c5a12b74efplougher * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20217f752a5a93169f0d547a33c542d085d5f7a8d6plougher *
21217f752a5a93169f0d547a33c542d085d5f7a8d6plougher * export.c
22217f752a5a93169f0d547a33c542d085d5f7a8d6plougher */
23217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
24426c85303bfb03fa8e343182f30d266dad621fccplougher/*
25426c85303bfb03fa8e343182f30d266dad621fccplougher * This file implements code to make Squashfs filesystems exportable (NFS etc.)
26426c85303bfb03fa8e343182f30d266dad621fccplougher *
27426c85303bfb03fa8e343182f30d266dad621fccplougher * The export code uses an inode lookup table to map inode numbers passed in
28426c85303bfb03fa8e343182f30d266dad621fccplougher * filehandles to an inode location on disk.  This table is stored compressed
29426c85303bfb03fa8e343182f30d266dad621fccplougher * into metadata blocks.  A second index table is used to locate these.  This
30426c85303bfb03fa8e343182f30d266dad621fccplougher * second index table for speed of access (and because it is small) is read at
31426c85303bfb03fa8e343182f30d266dad621fccplougher * mount time and cached in memory.
32426c85303bfb03fa8e343182f30d266dad621fccplougher *
33426c85303bfb03fa8e343182f30d266dad621fccplougher * The inode lookup table is used only by the export code, inode disk
34426c85303bfb03fa8e343182f30d266dad621fccplougher * locations are directly encoded in directories, enabling direct access
35426c85303bfb03fa8e343182f30d266dad621fccplougher * without an intermediate lookup for all operations except the export ops.
36426c85303bfb03fa8e343182f30d266dad621fccplougher */
37426c85303bfb03fa8e343182f30d266dad621fccplougher
38888fa2da07da843ed9daf53d4f0dfce95f90950aplougher#include <linux/fs.h>
39888fa2da07da843ed9daf53d4f0dfce95f90950aplougher#include <linux/vfs.h>
40888fa2da07da843ed9daf53d4f0dfce95f90950aplougher#include <linux/dcache.h>
41217f752a5a93169f0d547a33c542d085d5f7a8d6plougher#include <linux/exportfs.h>
42888fa2da07da843ed9daf53d4f0dfce95f90950aplougher#include <linux/zlib.h>
43217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
44a70c1cc4b995d559bcbdf2d3dda88c5bd1292c32plougher#include "squashfs_fs.h"
45a70c1cc4b995d559bcbdf2d3dda88c5bd1292c32plougher#include "squashfs_fs_sb.h"
46a70c1cc4b995d559bcbdf2d3dda88c5bd1292c32plougher#include "squashfs_fs_i.h"
47217f752a5a93169f0d547a33c542d085d5f7a8d6plougher#include "squashfs.h"
48ba92a3a7b1db2c04e2a031283fe7baa20eb45973plougher
49824cff29fd798cbd6cbfa18d93751c51ceabbd7fplougher/*
50824cff29fd798cbd6cbfa18d93751c51ceabbd7fplougher * Look-up inode number (ino) in table, returning the inode location.
51824cff29fd798cbd6cbfa18d93751c51ceabbd7fplougher */
528f0751cbf75de48392e0878456659393fe2fd6a4plougherstatic long long squashfs_inode_lookup(struct super_block *sb, int ino_num)
53217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
548f0751cbf75de48392e0878456659393fe2fd6a4plougher	struct squashfs_sb_info *msblk = sb->s_fs_info;
558f0751cbf75de48392e0878456659393fe2fd6a4plougher	int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1);
568f0751cbf75de48392e0878456659393fe2fd6a4plougher	int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1);
57f006b96e65d7092838983913afbd69fd8199d793plougher	u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]);
588f0751cbf75de48392e0878456659393fe2fd6a4plougher	__le64 ino;
5942d43d8a5d236bdae90e04b241ef5db631904ebfplougher	int err;
60217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
618f0751cbf75de48392e0878456659393fe2fd6a4plougher	TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num);
62217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
638f0751cbf75de48392e0878456659393fe2fd6a4plougher	err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino));
6442d43d8a5d236bdae90e04b241ef5db631904ebfplougher	if (err < 0)
6542d43d8a5d236bdae90e04b241ef5db631904ebfplougher		return err;
66217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
67b63b792093114e8e58d4232ce14408d1b80a4b63plougher	TRACE("squashfs_inode_lookup, inode = 0x%llx\n",
68f006b96e65d7092838983913afbd69fd8199d793plougher		(u64) le64_to_cpu(ino));
69b63b792093114e8e58d4232ce14408d1b80a4b63plougher
708f0751cbf75de48392e0878456659393fe2fd6a4plougher	return le64_to_cpu(ino);
71217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
72217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
73217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
748f0751cbf75de48392e0878456659393fe2fd6a4plougherstatic struct dentry *squashfs_export_iget(struct super_block *sb,
758f0751cbf75de48392e0878456659393fe2fd6a4plougher	unsigned int ino_num)
76217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
778f0751cbf75de48392e0878456659393fe2fd6a4plougher	long long ino;
78986989dabc3bf0c23f0c5b6450d5fa97f2abc445plougher	struct dentry *dentry = ERR_PTR(-ENOENT);
79217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
80217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	TRACE("Entered squashfs_export_iget\n");
81217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
828f0751cbf75de48392e0878456659393fe2fd6a4plougher	ino = squashfs_inode_lookup(sb, ino_num);
838f0751cbf75de48392e0878456659393fe2fd6a4plougher	if (ino >= 0)
848f0751cbf75de48392e0878456659393fe2fd6a4plougher		dentry = d_obtain_alias(squashfs_iget(sb, ino, ino_num));
85986989dabc3bf0c23f0c5b6450d5fa97f2abc445plougher
86217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	return dentry;
87217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
88217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
89217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
908f0751cbf75de48392e0878456659393fe2fd6a4plougherstatic struct dentry *squashfs_fh_to_dentry(struct super_block *sb,
91217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		struct fid *fid, int fh_len, int fh_type)
92217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
9356d24bf18e169cc9de1499e63a99809b8fed08fbplougher	if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT)
9456d24bf18e169cc9de1499e63a99809b8fed08fbplougher			|| fh_len < 2)
95217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		return NULL;
96217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
978f0751cbf75de48392e0878456659393fe2fd6a4plougher	return squashfs_export_iget(sb, fid->i32.ino);
98217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
99217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
100217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
1018f0751cbf75de48392e0878456659393fe2fd6a4plougherstatic struct dentry *squashfs_fh_to_parent(struct super_block *sb,
102217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		struct fid *fid, int fh_len, int fh_type)
103217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
10456d24bf18e169cc9de1499e63a99809b8fed08fbplougher	if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4)
105217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		return NULL;
106217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
1078f0751cbf75de48392e0878456659393fe2fd6a4plougher	return squashfs_export_iget(sb, fid->i32.parent_ino);
108217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
109217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
110217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
111217f752a5a93169f0d547a33c542d085d5f7a8d6plougherstatic struct dentry *squashfs_get_parent(struct dentry *child)
112217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
1135cd4d8c44ae78d119bfcc8dc8ee4d907a2ecfd11plougher	struct inode *inode = child->d_inode;
1145921b8d869f8d9a5a15a520eee1cfae06b1d9688plougher	unsigned int parent_ino = squashfs_i(inode)->parent;
115217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
1165cd4d8c44ae78d119bfcc8dc8ee4d907a2ecfd11plougher	return squashfs_export_iget(inode->i_sb, parent_ino);
117217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
118217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
119217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
120d7941bf6ba6663349f8feb099503133df001daa2plougher/*
121d7941bf6ba6663349f8feb099503133df001daa2plougher * Read uncompressed inode lookup table indexes off disk into memory
122d7941bf6ba6663349f8feb099503133df001daa2plougher */
123e5d56679a8f550513b2e8535e470af87d2679b82plougher__le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
124f006b96e65d7092838983913afbd69fd8199d793plougher		u64 lookup_table_start, unsigned int inodes)
125217f752a5a93169f0d547a33c542d085d5f7a8d6plougher{
1261c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher	unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
1271c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher	__le64 *inode_lookup_table;
12864fcf5e5c474932a049e6e91d9fd13b116743e83plougher	int err;
129217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
130217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	TRACE("In read_inode_lookup_table, length %d\n", length);
131217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
132d7941bf6ba6663349f8feb099503133df001daa2plougher	/* Allocate inode lookup table indexes */
1331c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher	inode_lookup_table = kmalloc(length, GFP_KERNEL);
1341c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher	if (inode_lookup_table == NULL) {
135217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		ERROR("Failed to allocate inode lookup table\n");
13664fcf5e5c474932a049e6e91d9fd13b116743e83plougher		return ERR_PTR(-ENOMEM);
137217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	}
13807e0310c61c277c87523afcf136e028524e24686plougher
139e631cb724d83f7e13be3008b2bd810f94aa77c67plougher	err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start,
140e631cb724d83f7e13be3008b2bd810f94aa77c67plougher			length);
14164fcf5e5c474932a049e6e91d9fd13b116743e83plougher	if (err < 0) {
142217f752a5a93169f0d547a33c542d085d5f7a8d6plougher		ERROR("unable to read inode lookup table\n");
1431c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher		kfree(inode_lookup_table);
14464fcf5e5c474932a049e6e91d9fd13b116743e83plougher		return ERR_PTR(err);
145217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	}
146217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
1471c56df122a02ddce05e5c1fafef10cb05ba8fe36plougher	return inode_lookup_table;
148217f752a5a93169f0d547a33c542d085d5f7a8d6plougher}
149217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
150217f752a5a93169f0d547a33c542d085d5f7a8d6plougher
151217f752a5a93169f0d547a33c542d085d5f7a8d6plougherconst struct export_operations squashfs_export_ops = {
152217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	.fh_to_dentry = squashfs_fh_to_dentry,
153217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	.fh_to_parent = squashfs_fh_to_parent,
154217f752a5a93169f0d547a33c542d085d5f7a8d6plougher	.get_parent = squashfs_get_parent
155217f752a5a93169f0d547a33c542d085d5f7a8d6plougher};
156