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