1122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher/* 2122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * Squashfs - a compressed read only filesystem for Linux 3122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 4122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 5d7f2ff6718efa155fd92e481a5960496d084c63fPhillip Lougher * Phillip Lougher <phillip@squashfs.org.uk> 6122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 7122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * This program is free software; you can redistribute it and/or 8122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * modify it under the terms of the GNU General Public License 9122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * as published by the Free Software Foundation; either version 2, 10122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * or (at your option) any later version. 11122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 12122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * This program is distributed in the hope that it will be useful, 13122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * but WITHOUT ANY WARRANTY; without even the implied warranty of 14122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * GNU General Public License for more details. 16122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 17122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * You should have received a copy of the GNU General Public License 18122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * along with this program; if not, write to the Free Software 19122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 21122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * export.c 22122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher */ 23122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 24122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher/* 25122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * This file implements code to make Squashfs filesystems exportable (NFS etc.) 26122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 27122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * The export code uses an inode lookup table to map inode numbers passed in 28122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * filehandles to an inode location on disk. This table is stored compressed 29122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * into metadata blocks. A second index table is used to locate these. This 30122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * second index table for speed of access (and because it is small) is read at 31122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * mount time and cached in memory. 32122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * 33122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * The inode lookup table is used only by the export code, inode disk 34122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * locations are directly encoded in directories, enabling direct access 35122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * without an intermediate lookup for all operations except the export ops. 36122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher */ 37122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 38122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include <linux/fs.h> 39122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include <linux/vfs.h> 40122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include <linux/dcache.h> 41122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include <linux/exportfs.h> 4223516dc709914845f18fbe379b3524b8156e5c85Pekka Enberg#include <linux/slab.h> 43122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 44122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include "squashfs_fs.h" 45122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include "squashfs_fs_sb.h" 46122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include "squashfs_fs_i.h" 47122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher#include "squashfs.h" 48122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 49122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher/* 50122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * Look-up inode number (ino) in table, returning the inode location. 51122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher */ 52122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherstatic long long squashfs_inode_lookup(struct super_block *sb, int ino_num) 53122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 54122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher struct squashfs_sb_info *msblk = sb->s_fs_info; 55122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1); 56122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1); 57122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]); 58122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher __le64 ino; 59122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher int err; 60122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 61122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num); 62122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 63122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino)); 64122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher if (err < 0) 65122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return err; 66122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 67122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher TRACE("squashfs_inode_lookup, inode = 0x%llx\n", 68122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher (u64) le64_to_cpu(ino)); 69122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 70122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return le64_to_cpu(ino); 71122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 72122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 73122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 74122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherstatic struct dentry *squashfs_export_iget(struct super_block *sb, 75122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher unsigned int ino_num) 76122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 77122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher long long ino; 78122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher struct dentry *dentry = ERR_PTR(-ENOENT); 79122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 80122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher TRACE("Entered squashfs_export_iget\n"); 81122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 82122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher ino = squashfs_inode_lookup(sb, ino_num); 83122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher if (ino >= 0) 84122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher dentry = d_obtain_alias(squashfs_iget(sb, ino, ino_num)); 85122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 86122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return dentry; 87122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 88122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 89122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 90122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherstatic struct dentry *squashfs_fh_to_dentry(struct super_block *sb, 91122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher struct fid *fid, int fh_len, int fh_type) 92122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 93122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher if ((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) 94122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher || fh_len < 2) 95122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return NULL; 96122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 97122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return squashfs_export_iget(sb, fid->i32.ino); 98122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 99122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 100122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 101122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherstatic struct dentry *squashfs_fh_to_parent(struct super_block *sb, 102122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher struct fid *fid, int fh_len, int fh_type) 103122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 104122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher if (fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) 105122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return NULL; 106122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 107122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return squashfs_export_iget(sb, fid->i32.parent_ino); 108122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 109122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 110122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 111122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherstatic struct dentry *squashfs_get_parent(struct dentry *child) 112122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 113122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher struct inode *inode = child->d_inode; 114122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher unsigned int parent_ino = squashfs_i(inode)->parent; 115122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 116122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher return squashfs_export_iget(inode->i_sb, parent_ino); 117122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 118122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 119122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 120122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher/* 121122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher * Read uncompressed inode lookup table indexes off disk into memory 122122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher */ 123122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher__le64 *squashfs_read_inode_lookup_table(struct super_block *sb, 124ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher u64 lookup_table_start, u64 next_table, unsigned int inodes) 125122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher{ 126122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); 127ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher __le64 *table; 128122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 129122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher TRACE("In read_inode_lookup_table, length %d\n", length); 130122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 131ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher /* Sanity check values */ 132ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher 133ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher /* there should always be at least one inode */ 134ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher if (inodes == 0) 135ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher return ERR_PTR(-EINVAL); 136ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher 137ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher /* length bytes should not extend into the next table - this check 138ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher * also traps instances where lookup_table_start is incorrectly larger 139ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher * than the next table start 140ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher */ 141ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher if (lookup_table_start + length > next_table) 142ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher return ERR_PTR(-EINVAL); 143ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher 144ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher table = squashfs_read_table(sb, lookup_table_start, length); 145ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher 146ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher /* 147ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher * table[0] points to the first inode lookup table metadata block, 148ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher * this should be less than lookup_table_start 149ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher */ 150d5b72ce15ea99a0b8f0d1973074c584daf92d70ePhillip Lougher if (!IS_ERR(table) && le64_to_cpu(table[0]) >= lookup_table_start) { 151ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher kfree(table); 152ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher return ERR_PTR(-EINVAL); 153ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher } 154ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher 155ac51a0a7139aa93bf1176b701c86fa3d2bdf6106Phillip Lougher return table; 156122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher} 157122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 158122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher 159122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougherconst struct export_operations squashfs_export_ops = { 160122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher .fh_to_dentry = squashfs_fh_to_dentry, 161122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher .fh_to_parent = squashfs_fh_to_parent, 162122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher .get_parent = squashfs_get_parent 163122601408d20c77704268f1dea9f9ce4abf997c2Phillip Lougher}; 164