1/* 2 * linux/fs/sysv/inode.c 3 * 4 * minix/inode.c 5 * Copyright (C) 1991, 1992 Linus Torvalds 6 * 7 * xenix/inode.c 8 * Copyright (C) 1992 Doug Evans 9 * 10 * coh/inode.c 11 * Copyright (C) 1993 Pascal Haible, Bruno Haible 12 * 13 * sysv/inode.c 14 * Copyright (C) 1993 Paul B. Monday 15 * 16 * sysv/inode.c 17 * Copyright (C) 1993 Bruno Haible 18 * Copyright (C) 1997, 1998 Krzysztof G. Baranowski 19 * 20 * This file contains code for read/parsing the superblock. 21 */ 22 23#include <linux/module.h> 24 25#include <linux/fs.h> 26#include <linux/sysv_fs.h> 27#include <linux/init.h> 28 29/* 30 * The following functions try to recognize specific filesystems. 31 * 32 * We recognize: 33 * - Xenix FS by its magic number. 34 * - SystemV FS by its magic number. 35 * - Coherent FS by its funny fname/fpack field. 36 * - SCO AFS by s_nfree == 0xffff 37 * - V7 FS has no distinguishing features. 38 * 39 * We discriminate among SystemV4 and SystemV2 FS by the assumption that 40 * the time stamp is not < 01-01-1980. 41 */ 42 43enum { 44 JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60 45}; 46 47static void detected_xenix(struct super_block *sb) 48{ 49 struct buffer_head *bh1 = sb->sv_bh1; 50 struct buffer_head *bh2 = sb->sv_bh2; 51 struct xenix_super_block * sbd1; 52 struct xenix_super_block * sbd2; 53 54 if (bh1 != bh2) 55 sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; 56 else { 57 /* block size = 512, so bh1 != bh2 */ 58 sbd1 = (struct xenix_super_block *) bh1->b_data; 59 sbd2 = (struct xenix_super_block *) (bh2->b_data - 512); 60 } 61 62 sb->sv_link_max = XENIX_LINK_MAX; 63 sb->sv_fic_size = XENIX_NICINOD; 64 sb->sv_flc_size = XENIX_NICFREE; 65 sb->sv_sbd1 = (char *) sbd1; 66 sb->sv_sbd2 = (char *) sbd2; 67 sb->sv_sb_fic_count = &sbd1->s_ninode; 68 sb->sv_sb_fic_inodes = &sbd1->s_inode[0]; 69 sb->sv_sb_total_free_inodes = &sbd2->s_tinode; 70 sb->sv_bcache_count = &sbd1->s_nfree; 71 sb->sv_bcache = &sbd1->s_free[0]; 72 sb->sv_free_blocks = &sbd2->s_tfree; 73 sb->sv_sb_time = &sbd2->s_time; 74 sb->sv_firstdatazone = fs16_to_cpu(sb, sbd1->s_isize); 75 sb->sv_nzones = fs32_to_cpu(sb, sbd1->s_fsize); 76} 77 78static void detected_sysv4(struct super_block *sb) 79{ 80 struct sysv4_super_block * sbd; 81 struct buffer_head *bh1 = sb->sv_bh1; 82 struct buffer_head *bh2 = sb->sv_bh2; 83 84 if (bh1 == bh2) 85 sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2); 86 else 87 sbd = (struct sysv4_super_block *) bh2->b_data; 88 89 sb->sv_link_max = SYSV_LINK_MAX; 90 sb->sv_fic_size = SYSV_NICINOD; 91 sb->sv_flc_size = SYSV_NICFREE; 92 sb->sv_sbd1 = (char *) sbd; 93 sb->sv_sbd2 = (char *) sbd; 94 sb->sv_sb_fic_count = &sbd->s_ninode; 95 sb->sv_sb_fic_inodes = &sbd->s_inode[0]; 96 sb->sv_sb_total_free_inodes = &sbd->s_tinode; 97 sb->sv_bcache_count = &sbd->s_nfree; 98 sb->sv_bcache = &sbd->s_free[0]; 99 sb->sv_free_blocks = &sbd->s_tfree; 100 sb->sv_sb_time = &sbd->s_time; 101 sb->sv_sb_state = &sbd->s_state; 102 sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); 103 sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); 104} 105 106static void detected_sysv2(struct super_block *sb) 107{ 108 struct sysv2_super_block * sbd; 109 struct buffer_head *bh1 = sb->sv_bh1; 110 struct buffer_head *bh2 = sb->sv_bh2; 111 112 if (bh1 == bh2) 113 sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2); 114 else 115 sbd = (struct sysv2_super_block *) bh2->b_data; 116 117 sb->sv_link_max = SYSV_LINK_MAX; 118 sb->sv_fic_size = SYSV_NICINOD; 119 sb->sv_flc_size = SYSV_NICFREE; 120 sb->sv_sbd1 = (char *) sbd; 121 sb->sv_sbd2 = (char *) sbd; 122 sb->sv_sb_fic_count = &sbd->s_ninode; 123 sb->sv_sb_fic_inodes = &sbd->s_inode[0]; 124 sb->sv_sb_total_free_inodes = &sbd->s_tinode; 125 sb->sv_bcache_count = &sbd->s_nfree; 126 sb->sv_bcache = &sbd->s_free[0]; 127 sb->sv_free_blocks = &sbd->s_tfree; 128 sb->sv_sb_time = &sbd->s_time; 129 sb->sv_sb_state = &sbd->s_state; 130 sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); 131 sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); 132} 133 134static void detected_coherent(struct super_block *sb) 135{ 136 struct coh_super_block * sbd; 137 struct buffer_head *bh1 = sb->sv_bh1; 138 139 sbd = (struct coh_super_block *) bh1->b_data; 140 141 sb->sv_link_max = COH_LINK_MAX; 142 sb->sv_fic_size = COH_NICINOD; 143 sb->sv_flc_size = COH_NICFREE; 144 sb->sv_sbd1 = (char *) sbd; 145 sb->sv_sbd2 = (char *) sbd; 146 sb->sv_sb_fic_count = &sbd->s_ninode; 147 sb->sv_sb_fic_inodes = &sbd->s_inode[0]; 148 sb->sv_sb_total_free_inodes = &sbd->s_tinode; 149 sb->sv_bcache_count = &sbd->s_nfree; 150 sb->sv_bcache = &sbd->s_free[0]; 151 sb->sv_free_blocks = &sbd->s_tfree; 152 sb->sv_sb_time = &sbd->s_time; 153 sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); 154 sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); 155} 156 157static void detected_v7(struct super_block *sb) 158{ 159 struct buffer_head *bh2 = sb->sv_bh2; 160 struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data; 161 162 sb->sv_link_max = V7_LINK_MAX; 163 sb->sv_fic_size = V7_NICINOD; 164 sb->sv_flc_size = V7_NICFREE; 165 sb->sv_sbd1 = (char *)sbd; 166 sb->sv_sbd2 = (char *)sbd; 167 sb->sv_sb_fic_count = &sbd->s_ninode; 168 sb->sv_sb_fic_inodes = &sbd->s_inode[0]; 169 sb->sv_sb_total_free_inodes = &sbd->s_tinode; 170 sb->sv_bcache_count = &sbd->s_nfree; 171 sb->sv_bcache = &sbd->s_free[0]; 172 sb->sv_free_blocks = &sbd->s_tfree; 173 sb->sv_sb_time = &sbd->s_time; 174 sb->sv_firstdatazone = fs16_to_cpu(sb, sbd->s_isize); 175 sb->sv_nzones = fs32_to_cpu(sb, sbd->s_fsize); 176} 177 178static int detect_xenix (struct super_block *sb, struct buffer_head *bh) 179{ 180 struct xenix_super_block * sbd = (struct xenix_super_block *)bh->b_data; 181 if (sbd->s_magic == cpu_to_le32(0x2b5544)) 182 sb->sv_bytesex = BYTESEX_LE; 183 else if (sbd->s_magic == cpu_to_be32(0x2b5544)) 184 sb->sv_bytesex = BYTESEX_BE; 185 else 186 return 0; 187 if (sbd->s_type > 2 || sbd->s_type < 1) 188 return 0; 189 sb->sv_type = FSTYPE_XENIX; 190 return sbd->s_type; 191} 192 193static int detect_sysv (struct super_block *sb, struct buffer_head *bh) 194{ 195 /* All relevant fields are at the same offsets in R2 and R4 */ 196 struct sysv4_super_block * sbd; 197 198 sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); 199 if (sbd->s_magic == cpu_to_le32(0xfd187e20)) 200 sb->sv_bytesex = BYTESEX_LE; 201 else if (sbd->s_magic == cpu_to_be32(0xfd187e20)) 202 sb->sv_bytesex = BYTESEX_BE; 203 else 204 return 0; 205 206 if (fs16_to_cpu(sb, sbd->s_nfree) == 0xffff) { 207 sb->sv_type = FSTYPE_AFS; 208 if (!(sb->s_flags & MS_RDONLY)) { 209 printk("SysV FS: SCO EAFS on %s detected, " 210 "forcing read-only mode.\n", 211 bdevname(sb->s_dev)); 212 sb->s_flags |= MS_RDONLY; 213 } 214 return sbd->s_type; 215 } 216 217 if (fs32_to_cpu(sb, sbd->s_time) < JAN_1_1980) { 218 /* this is likely to happen on SystemV2 FS */ 219 if (sbd->s_type > 3 || sbd->s_type < 1) 220 return 0; 221 sb->sv_type = FSTYPE_SYSV2; 222 return sbd->s_type; 223 } 224 if ((sbd->s_type > 3 || sbd->s_type < 1) && 225 (sbd->s_type > 0x30 || sbd->s_type < 0x10)) 226 return 0; 227 228 /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, 229 0x20 or 0x30 indicates that symbolic links and the 14-character 230 filename limit is gone. Due to lack of information about this 231 feature read-only mode seems to be a reasonable approach... -KGB */ 232 233 if (sbd->s_type >= 0x10) { 234 printk("SysV FS: can't handle long file names on %s, " 235 "forcing read-only mode.\n", kdevname(sb->s_dev)); 236 sb->s_flags |= MS_RDONLY; 237 } 238 239 sb->sv_type = FSTYPE_SYSV4; 240 return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type; 241} 242 243static int detect_coherent (struct super_block *sb, struct buffer_head *bh) 244{ 245 struct coh_super_block * sbd; 246 247 sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2); 248 if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) 249 || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) 250 return 0; 251 sb->sv_bytesex = BYTESEX_PDP; 252 sb->sv_type = FSTYPE_COH; 253 return 1; 254} 255 256static int detect_sysv_odd(struct super_block *sb, struct buffer_head *bh) 257{ 258 int size = detect_sysv(sb, bh); 259 260 return size>2 ? 0 : size; 261} 262 263static struct { 264 int block; 265 int (*test)(struct super_block *, struct buffer_head *); 266} flavours[] = { 267 {1, detect_xenix}, 268 {0, detect_sysv}, 269 {0, detect_coherent}, 270 {9, detect_sysv_odd}, 271 {15,detect_sysv_odd}, 272 {18,detect_sysv}, 273}; 274 275static char *flavour_names[] = { 276 [FSTYPE_XENIX] "Xenix", 277 [FSTYPE_SYSV4] "SystemV", 278 [FSTYPE_SYSV2] "SystemV Release 2", 279 [FSTYPE_COH] "Coherent", 280 [FSTYPE_V7] "V7", 281 [FSTYPE_AFS] "AFS", 282}; 283 284static void (*flavour_setup[])(struct super_block *) = { 285 [FSTYPE_XENIX] detected_xenix, 286 [FSTYPE_SYSV4] detected_sysv4, 287 [FSTYPE_SYSV2] detected_sysv2, 288 [FSTYPE_COH] detected_coherent, 289 [FSTYPE_V7] detected_v7, 290 [FSTYPE_AFS] detected_sysv4, 291}; 292 293static int complete_read_super(struct super_block *sb, int silent, int size) 294{ 295 struct inode *root_inode; 296 char *found = flavour_names[sb->sv_type]; 297 u_char n_bits = size+8; 298 int bsize = 1 << n_bits; 299 int bsize_4 = bsize >> 2; 300 301 sb->sv_firstinodezone = 2; 302 303 flavour_setup[sb->sv_type](sb); 304 305 sb->sv_truncate = 1; 306 sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; 307 sb->sv_inodes_per_block = bsize >> 6; 308 sb->sv_inodes_per_block_1 = (bsize >> 6)-1; 309 sb->sv_inodes_per_block_bits = n_bits-6; 310 sb->sv_ind_per_block = bsize_4; 311 sb->sv_ind_per_block_2 = bsize_4*bsize_4; 312 sb->sv_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4)); 313 sb->sv_ind_per_block_bits = n_bits-2; 314 315 sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) 316 << sb->sv_inodes_per_block_bits; 317 318 sb->s_blocksize = bsize; 319 sb->s_blocksize_bits = n_bits; 320 if (!silent) 321 printk("VFS: Found a %s FS (block size = %ld) on device %s\n", 322 found, sb->s_blocksize, bdevname(sb->s_dev)); 323 324 sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; 325 /* set up enough so that it can read an inode */ 326 sb->s_op = &sysv_sops; 327 root_inode = iget(sb,SYSV_ROOT_INO); 328 if (!root_inode || is_bad_inode(root_inode)) { 329 printk("SysV FS: get root inode failed\n"); 330 return 0; 331 } 332 sb->s_root = d_alloc_root(root_inode); 333 if (!sb->s_root) { 334 iput(root_inode); 335 printk("SysV FS: get root dentry failed\n"); 336 return 0; 337 } 338 if (sb->sv_truncate) 339 sb->s_root->d_op = &sysv_dentry_operations; 340 sb->s_flags |= MS_RDONLY; 341 sb->s_dirt = 1; 342 return 1; 343} 344 345static struct super_block *sysv_read_super(struct super_block *sb, 346 void *data, int silent) 347{ 348 struct buffer_head *bh1; 349 struct buffer_head *bh = NULL; 350 kdev_t dev = sb->s_dev; 351 unsigned long blocknr; 352 int size = 0; 353 int i; 354 355 if (1024 != sizeof (struct xenix_super_block)) 356 panic("Xenix FS: bad super-block size"); 357 if ((512 != sizeof (struct sysv4_super_block)) 358 || (512 != sizeof (struct sysv2_super_block))) 359 panic("SystemV FS: bad super-block size"); 360 if (500 != sizeof (struct coh_super_block)) 361 panic("Coherent FS: bad super-block size"); 362 if (64 != sizeof (struct sysv_inode)) 363 panic("sysv fs: bad i-node size"); 364 set_blocksize(dev,BLOCK_SIZE); 365 sb->s_blocksize = BLOCK_SIZE; 366 sb->sv_block_base = 0; 367 368 for (i = 0; i < sizeof(flavours)/sizeof(flavours[0]) && !size; i++) { 369 brelse(bh); 370 bh = sb_bread(sb, flavours[i].block); 371 if (!bh) 372 continue; 373 size = flavours[i].test(sb, bh); 374 } 375 376 if (!size) 377 goto Eunknown; 378 379 switch (size) { 380 case 1: 381 blocknr = bh->b_blocknr << 1; 382 brelse(bh); 383 set_blocksize(dev, 512); 384 sb->s_blocksize = 512; 385 bh1 = sb_bread(sb, blocknr); 386 bh = sb_bread(sb, blocknr + 1); 387 break; 388 case 2: 389 bh1 = bh; 390 break; 391 case 3: 392 blocknr = bh->b_blocknr >> 1; 393 brelse(bh); 394 set_blocksize(dev, 2048); 395 sb->s_blocksize = 2048; 396 bh1 = bh = sb_bread(sb, blocknr); 397 break; 398 default: 399 goto Ebadsize; 400 } 401 402 if (bh && bh1) { 403 sb->sv_bh1 = bh1; 404 sb->sv_bh2 = bh; 405 if (complete_read_super(sb, silent, size)) 406 return sb; 407 } 408 409 brelse(bh1); 410 brelse(bh); 411 set_blocksize(sb->s_dev,BLOCK_SIZE); 412 printk("oldfs: cannot read superblock\n"); 413failed: 414 return NULL; 415 416Eunknown: 417 brelse(bh); 418 if (!silent) 419 printk("VFS: unable to find oldfs superblock on device %s\n", 420 bdevname(dev)); 421 goto failed; 422Ebadsize: 423 brelse(bh); 424 if (!silent) 425 printk("VFS: oldfs: unsupported block size (%dKb)\n", 426 1<<(size-2)); 427 goto failed; 428} 429 430static struct super_block *v7_read_super(struct super_block *sb,void *data, 431 int silent) 432{ 433 struct buffer_head *bh, *bh2 = NULL; 434 kdev_t dev = sb->s_dev; 435 struct v7_super_block *v7sb; 436 struct sysv_inode *v7i; 437 438 if (440 != sizeof (struct v7_super_block)) 439 panic("V7 FS: bad super-block size"); 440 if (64 != sizeof (struct sysv_inode)) 441 panic("sysv fs: bad i-node size"); 442 443 sb->sv_type = FSTYPE_V7; 444 sb->sv_bytesex = BYTESEX_PDP; 445 446 set_blocksize(dev, 512); 447 sb->s_blocksize = 512; 448 449 if ((bh = sb_bread(sb, 1)) == NULL) { 450 if (!silent) 451 printk("VFS: unable to read V7 FS superblock on " 452 "device %s.\n", bdevname(dev)); 453 goto failed; 454 } 455 456 /* plausibility check on superblock */ 457 v7sb = (struct v7_super_block *) bh->b_data; 458 if (fs16_to_cpu(sb,v7sb->s_nfree) > V7_NICFREE || 459 fs16_to_cpu(sb,v7sb->s_ninode) > V7_NICINOD || 460 fs32_to_cpu(sb,v7sb->s_time) == 0) 461 goto failed; 462 463 /* plausibility check on root inode: it is a directory, 464 with a nonzero size that is a multiple of 16 */ 465 if ((bh2 = sb_bread(sb, 2)) == NULL) 466 goto failed; 467 v7i = (struct sysv_inode *)(bh2->b_data + 64); 468 if ((fs16_to_cpu(sb,v7i->i_mode) & ~0777) != S_IFDIR || 469 (fs32_to_cpu(sb,v7i->i_size) == 0) || 470 (fs32_to_cpu(sb,v7i->i_size) & 017) != 0) 471 goto failed; 472 brelse(bh2); 473 474 sb->sv_bh1 = bh; 475 sb->sv_bh2 = bh; 476 if (complete_read_super(sb, silent, 1)) 477 return sb; 478 479failed: 480 brelse(bh2); 481 brelse(bh); 482 return NULL; 483} 484 485/* Every kernel module contains stuff like this. */ 486 487static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super); 488static DECLARE_FSTYPE_DEV(v7_fs_type, "v7", v7_read_super); 489 490static int __init init_sysv_fs(void) 491{ 492 int err = register_filesystem(&sysv_fs_type); 493 if (!err) 494 err = register_filesystem(&v7_fs_type); 495 return err; 496} 497 498static void __exit exit_sysv_fs(void) 499{ 500 unregister_filesystem(&sysv_fs_type); 501 unregister_filesystem(&v7_fs_type); 502} 503 504EXPORT_NO_SYMBOLS; 505 506module_init(init_sysv_fs) 507module_exit(exit_sysv_fs) 508MODULE_LICENSE("GPL"); 509