1 /* 2 * inode.c 3 * 4 * Copyright (c) 1999 Al Smith 5 * 6 * Portions derived from work (c) 1995,1996 Christian Vogelgsang, 7 * and from work (c) 1998 Mike Shaver. 8 */ 9 10 #include <linux/efs_fs.h> 11 #include <linux/efs_fs_sb.h> 12 #include <linux/module.h> 13 14 15 extern int efs_get_block(struct inode *, long, struct buffer_head *, int); 16 static int efs_readpage(struct file *file, struct page *page) 17 { 18 return block_read_full_page(page,efs_get_block); 19 } 20 static int _efs_bmap(struct address_space *mapping, long block) 21 { 22 return generic_block_bmap(mapping,block,efs_get_block); 23 } 24 struct address_space_operations efs_aops = { 25 readpage: efs_readpage, 26 sync_page: block_sync_page, 27 bmap: _efs_bmap 28 }; 29 30 static inline void extent_copy(efs_extent *src, efs_extent *dst) { 31 /* 32 * this is slightly evil. it doesn't just copy 33 * efs_extent from src to dst, it also mangles 34 * the bits so that dst ends up in cpu byte-order. 35 */ 36 37 dst->cooked.ex_magic = (unsigned int) src->raw[0]; 38 dst->cooked.ex_bn = ((unsigned int) src->raw[1] << 16) | 39 ((unsigned int) src->raw[2] << 8) | 40 ((unsigned int) src->raw[3] << 0); 41 dst->cooked.ex_length = (unsigned int) src->raw[4]; 42 dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) | 43 ((unsigned int) src->raw[6] << 8) | 44 ((unsigned int) src->raw[7] << 0); 45 return; 46 } 47 48 void efs_read_inode(struct inode *inode) { 49 int i, inode_index; 50 dev_t device; 51 struct buffer_head *bh; 52 struct efs_sb_info *sb = SUPER_INFO(inode->i_sb); 53 struct efs_inode_info *in = INODE_INFO(inode); 54 efs_block_t block, offset; 55 struct efs_dinode *efs_inode; 56 57 /* 58 ** EFS layout: 59 ** 60 ** | cylinder group | cylinder group | cylinder group ..etc 61 ** |inodes|data |inodes|data |inodes|data ..etc 62 ** 63 ** work out the inode block index, (considering initially that the 64 ** inodes are stored as consecutive blocks). then work out the block 65 ** number of that inode given the above layout, and finally the 66 ** offset of the inode within that block. 67 */ 68 69 inode_index = inode->i_ino / 70 (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); 71 72 block = sb->fs_start + sb->first_block + 73 (sb->group_size * (inode_index / sb->inode_blocks)) + 74 (inode_index % sb->inode_blocks); 75 76 offset = (inode->i_ino % 77 (EFS_BLOCKSIZE / sizeof(struct efs_dinode))) * 78 sizeof(struct efs_dinode); 79 80 bh = sb_bread(inode->i_sb, block); 81 if (!bh) { 82 printk(KERN_WARNING "EFS: bread() failed at block %d\n", block); 83 goto read_inode_error; 84 } 85 86 efs_inode = (struct efs_dinode *) (bh->b_data + offset); 87 88 inode->i_mode = be16_to_cpu(efs_inode->di_mode); 89 inode->i_nlink = be16_to_cpu(efs_inode->di_nlink); 90 inode->i_uid = (uid_t)be16_to_cpu(efs_inode->di_uid); 91 inode->i_gid = (gid_t)be16_to_cpu(efs_inode->di_gid); 92 inode->i_size = be32_to_cpu(efs_inode->di_size); 93 inode->i_atime = be32_to_cpu(efs_inode->di_atime); 94 inode->i_mtime = be32_to_cpu(efs_inode->di_mtime); 95 inode->i_ctime = be32_to_cpu(efs_inode->di_ctime); 96 97 /* this is the number of blocks in the file */ 98 if (inode->i_size == 0) { 99 inode->i_blocks = 0; 100 } else { 101 inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1; 102 } 103 104 /* 105 * BUG: irix dev_t is 32-bits. linux dev_t is only 16-bits. 106 * 107 * apparently linux will change to 32-bit dev_t sometime during 108 * linux 2.3. 109 * 110 * as is, this code maps devices that can't be represented in 111 * 16-bits (ie major > 255 or minor > 255) to major = minor = 255. 112 * 113 * during 2.3 when 32-bit dev_t become available, we should test 114 * to see whether odev contains 65535. if this is the case then we 115 * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev). 116 */ 117 device = be16_to_cpu(efs_inode->di_u.di_dev.odev); 118 119 /* get the number of extents for this object */ 120 in->numextents = be16_to_cpu(efs_inode->di_numextents); 121 in->lastextent = 0; 122 123 /* copy the extents contained within the inode to memory */ 124 for(i = 0; i < EFS_DIRECTEXTENTS; i++) { 125 extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i])); 126 if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) { 127 printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino); 128 brelse(bh); 129 goto read_inode_error; 130 } 131 } 132 133 brelse(bh); 134 135 #ifdef DEBUG 136 printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n", 137 inode->i_ino, in->numextents, inode->i_mode); 138 #endif 139 140 switch (inode->i_mode & S_IFMT) { 141 case S_IFDIR: 142 inode->i_op = &efs_dir_inode_operations; 143 inode->i_fop = &efs_dir_operations; 144 break; 145 case S_IFREG: 146 inode->i_fop = &generic_ro_fops; 147 inode->i_data.a_ops = &efs_aops; 148 break; 149 case S_IFLNK: 150 inode->i_op = &page_symlink_inode_operations; 151 inode->i_data.a_ops = &efs_symlink_aops; 152 break; 153 case S_IFCHR: 154 case S_IFBLK: 155 case S_IFIFO: 156 init_special_inode(inode, inode->i_mode, device); 157 break; 158 default: 159 printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode); 160 goto read_inode_error; 161 break; 162 } 163 164 return; 165 166 read_inode_error: 167 printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino); 168 make_bad_inode(inode); 169 170 return; 171 } 172 173 static inline efs_block_t 174 efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) { 175 efs_block_t start; 176 efs_block_t length; 177 efs_block_t offset; 178 179 /* 180 * given an extent and a logical block within a file, 181 * can this block be found within this extent ? 182 */ 183 start = ptr->cooked.ex_bn; 184 length = ptr->cooked.ex_length; 185 offset = ptr->cooked.ex_offset; 186 187 if ((block >= offset) && (block < offset+length)) { 188 return(sb->fs_start + start + block - offset); 189 } else { 190 return 0; 191 } 192 } 193 194 efs_block_t efs_map_block(struct inode *inode, efs_block_t block) { 195 struct efs_sb_info *sb = SUPER_INFO(inode->i_sb); 196 struct efs_inode_info *in = INODE_INFO(inode); 197 struct buffer_head *bh = NULL; 198 199 int cur, last, first = 1; 200 int ibase, ioffset, dirext, direxts, indext, indexts; 201 efs_block_t iblock, result = 0, lastblock = 0; 202 efs_extent ext, *exts; 203 204 last = in->lastextent; 205 206 if (in->numextents <= EFS_DIRECTEXTENTS) { 207 /* first check the last extent we returned */ 208 if ((result = efs_extent_check(&in->extents[last], block, sb))) 209 return result; 210 211 /* if we only have one extent then nothing can be found */ 212 if (in->numextents == 1) { 213 printk(KERN_ERR "EFS: map_block() failed to map (1 extent)\n"); 214 return 0; 215 } 216 217 direxts = in->numextents; 218 219 /* 220 * check the stored extents in the inode 221 * start with next extent and check forwards 222 */ 223 for(dirext = 1; dirext < direxts; dirext++) { 224 cur = (last + dirext) % in->numextents; 225 if ((result = efs_extent_check(&in->extents[cur], block, sb))) { 226 in->lastextent = cur; 227 return result; 228 } 229 } 230 231 printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)\n", block); 232 return 0; 233 } 234 235 #ifdef DEBUG 236 printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %u\n", block); 237 #endif 238 direxts = in->extents[0].cooked.ex_offset; 239 indexts = in->numextents; 240 241 for(indext = 0; indext < indexts; indext++) { 242 cur = (last + indext) % indexts; 243 244 /* 245 * work out which direct extent contains `cur'. 246 * 247 * also compute ibase: i.e. the number of the first 248 * indirect extent contained within direct extent `cur'. 249 * 250 */ 251 ibase = 0; 252 for(dirext = 0; cur < ibase && dirext < direxts; dirext++) { 253 ibase += in->extents[dirext].cooked.ex_length * 254 (EFS_BLOCKSIZE / sizeof(efs_extent)); 255 } 256 257 if (dirext == direxts) { 258 /* should never happen */ 259 printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)\n", cur, block); 260 if (bh) brelse(bh); 261 return 0; 262 } 263 264 /* work out block number and offset of this indirect extent */ 265 iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn + 266 (cur - ibase) / 267 (EFS_BLOCKSIZE / sizeof(efs_extent)); 268 ioffset = (cur - ibase) % 269 (EFS_BLOCKSIZE / sizeof(efs_extent)); 270 271 if (first || lastblock != iblock) { 272 if (bh) brelse(bh); 273 274 bh = sb_bread(inode->i_sb, iblock); 275 if (!bh) { 276 printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock); 277 return 0; 278 } 279 #ifdef DEBUG 280 printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock); 281 #endif 282 first = 0; 283 lastblock = iblock; 284 } 285 286 exts = (efs_extent *) bh->b_data; 287 288 extent_copy(&(exts[ioffset]), &ext); 289 290 if (ext.cooked.ex_magic != 0) { 291 printk(KERN_ERR "EFS: extent %d has bad magic number in block %d\n", cur, iblock); 292 if (bh) brelse(bh); 293 return 0; 294 } 295 296 if ((result = efs_extent_check(&ext, block, sb))) { 297 if (bh) brelse(bh); 298 in->lastextent = cur; 299 return result; 300 } 301 } 302 if (bh) brelse(bh); 303 printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)\n", block); 304 return 0; 305 } 306 307 MODULE_LICENSE("GPL"); 308
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.