11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/fs/sysv/inode.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * minix/inode.c 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * xenix/inode.c 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1992 Doug Evans 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * coh/inode.c 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1993 Pascal Haible, Bruno Haible 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysv/inode.c 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1993 Paul B. Monday 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sysv/inode.c 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1993 Bruno Haible 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997, 1998 Krzysztof G. Baranowski 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file contains code for read/parsing the superblock. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sysv.h" 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The following functions try to recognize specific filesystems. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We recognize: 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Xenix FS by its magic number. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - SystemV FS by its magic number. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Coherent FS by its funny fname/fpack field. 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - SCO AFS by s_nfree == 0xffff 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - V7 FS has no distinguishing features. 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We discriminate among SystemV4 and SystemV2 FS by the assumption that 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the time stamp is not < 01-01-1980. 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 478de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void detected_xenix(struct sysv_sb_info *sbi, unsigned *max_links) 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh1 = sbi->s_bh1; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh2 = sbi->s_bh2; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct xenix_super_block * sbd1; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct xenix_super_block * sbd2; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bh1 != bh2) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* block size = 512, so bh1 != bh2 */ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd1 = (struct xenix_super_block *) bh1->b_data; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd2 = (struct xenix_super_block *) (bh2->b_data - 512); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 628de52778798fe39660a8d6b26f290e0c93202761Al Viro *max_links = XENIX_LINK_MAX; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_fic_size = XENIX_NICINOD; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_flc_size = XENIX_NICFREE; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd1 = (char *)sbd1; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd2 = (char *)sbd2; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_count = &sbd1->s_ninode; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_inodes = &sbd1->s_inode[0]; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_total_free_inodes = &sbd2->s_tinode; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache_count = &sbd1->s_nfree; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache = &sbd1->s_free[0]; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_free_blocks = &sbd2->s_tfree; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_time = &sbd2->s_time; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd1->s_isize); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_nzones = fs32_to_cpu(sbi, sbd1->s_fsize); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 788de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void detected_sysv4(struct sysv_sb_info *sbi, unsigned *max_links) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv4_super_block * sbd; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh1 = sbi->s_bh1; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh2 = sbi->s_bh2; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bh1 == bh2) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct sysv4_super_block *) (bh1->b_data + BLOCK_SIZE/2); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct sysv4_super_block *) bh2->b_data; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 898de52778798fe39660a8d6b26f290e0c93202761Al Viro *max_links = SYSV_LINK_MAX; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_fic_size = SYSV_NICINOD; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_flc_size = SYSV_NICFREE; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd1 = (char *)sbd; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd2 = (char *)sbd; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_count = &sbd->s_ninode; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_inodes = &sbd->s_inode[0]; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_total_free_inodes = &sbd->s_tinode; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache_count = &sbd->s_nfree; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache = &sbd->s_free[0]; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_free_blocks = &sbd->s_tfree; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_time = &sbd->s_time; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_state = &sbd->s_state; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1068de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void detected_sysv2(struct sysv_sb_info *sbi, unsigned *max_links) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv2_super_block *sbd; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh1 = sbi->s_bh1; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh2 = sbi->s_bh2; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bh1 == bh2) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct sysv2_super_block *) (bh1->b_data + BLOCK_SIZE/2); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct sysv2_super_block *) bh2->b_data; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1178de52778798fe39660a8d6b26f290e0c93202761Al Viro *max_links = SYSV_LINK_MAX; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_fic_size = SYSV_NICINOD; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_flc_size = SYSV_NICFREE; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd1 = (char *)sbd; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd2 = (char *)sbd; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_count = &sbd->s_ninode; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_inodes = &sbd->s_inode[0]; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_total_free_inodes = &sbd->s_tinode; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache_count = &sbd->s_nfree; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache = &sbd->s_free[0]; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_free_blocks = &sbd->s_tfree; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_time = &sbd->s_time; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_state = &sbd->s_state; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1348de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void detected_coherent(struct sysv_sb_info *sbi, unsigned *max_links) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct coh_super_block * sbd; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh1 = sbi->s_bh1; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct coh_super_block *) bh1->b_data; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1418de52778798fe39660a8d6b26f290e0c93202761Al Viro *max_links = COH_LINK_MAX; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_fic_size = COH_NICINOD; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_flc_size = COH_NICFREE; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd1 = (char *)sbd; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd2 = (char *)sbd; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_count = &sbd->s_ninode; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_inodes = &sbd->s_inode[0]; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_total_free_inodes = &sbd->s_tinode; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache_count = &sbd->s_nfree; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache = &sbd->s_free[0]; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_free_blocks = &sbd->s_tfree; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_time = &sbd->s_time; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1578de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void detected_v7(struct sysv_sb_info *sbi, unsigned *max_links) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh2 = sbi->s_bh2; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1628de52778798fe39660a8d6b26f290e0c93202761Al Viro *max_links = V7_LINK_MAX; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_fic_size = V7_NICINOD; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_flc_size = V7_NICFREE; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd1 = (char *)sbd; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sbd2 = (char *)sbd; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_count = &sbd->s_ninode; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_fic_inodes = &sbd->s_inode[0]; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_total_free_inodes = &sbd->s_tinode; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache_count = &sbd->s_nfree; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bcache = &sbd->s_free[0]; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_free_blocks = &sbd->s_tfree; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb_time = &sbd->s_time; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstdatazone = fs16_to_cpu(sbi, sbd->s_isize); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0x2b5544)) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bytesex = BYTESEX_LE; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0x2b5544)) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bytesex = BYTESEX_BE; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fs32_to_cpu(sbi, sbd->s_type)) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_XENIX; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_XENIX; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct super_block *sb = sbi->s_sb; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All relevant fields are at the same offsets in R2 and R4 */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv4_super_block * sbd; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 type; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0xfd187e20)) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bytesex = BYTESEX_LE; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0xfd187e20)) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bytesex = BYTESEX_BE; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = fs32_to_cpu(sbi, sbd->s_type); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_AFS; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_forced_ro = 1; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(sb->s_flags & MS_RDONLY)) { 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SysV FS: SCO EAFS on %s detected, " 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "forcing read-only mode.\n", 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_id); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return type; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this is likely to happen on SystemV2 FS */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (type > 3 || type < 1) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_SYSV2; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return type; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((type > 3 || type < 1) && (type > 0x30 || type < 0x10)) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x20 or 0x30 indicates that symbolic links and the 14-character 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filename limit is gone. Due to lack of information about this 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds feature read-only mode seems to be a reasonable approach... -KGB */ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (type >= 0x10) { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SysV FS: can't handle long file names on %s, " 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "forcing read-only mode.\n", sb->s_id); 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_forced_ro = 1; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_SYSV4; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return type >= 0x10 ? type >> 4 : type; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct coh_super_block * sbd; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bytesex = BYTESEX_PDP; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_COH; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int detect_sysv_odd(struct sysv_sb_info *sbi, struct buffer_head *bh) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = detect_sysv(sbi, bh); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return size>2 ? 0 : size; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct { 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int block; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int (*test)(struct sysv_sb_info *, struct buffer_head *); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} flavours[] = { 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {1, detect_xenix}, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0, detect_sysv}, 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0, detect_coherent}, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {9, detect_sysv_odd}, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {15,detect_sysv_odd}, 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {18,detect_sysv}, 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *flavour_names[] = { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_XENIX] = "Xenix", 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_SYSV4] = "SystemV", 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_SYSV2] = "SystemV Release 2", 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_COH] = "Coherent", 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_V7] = "V7", 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_AFS] = "AFS", 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2938de52778798fe39660a8d6b26f290e0c93202761Al Virostatic void (*flavour_setup[])(struct sysv_sb_info *, unsigned *) = { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_XENIX] = detected_xenix, 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_SYSV4] = detected_sysv4, 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_SYSV2] = detected_sysv2, 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_COH] = detected_coherent, 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_V7] = detected_v7, 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [FSTYPE_AFS] = detected_sysv4, 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int complete_read_super(struct super_block *sb, int silent, int size) 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv_sb_info *sbi = SYSV_SB(sb); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct inode *root_inode; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *found = flavour_names[sbi->s_type]; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char n_bits = size+8; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bsize = 1 << n_bits; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bsize_4 = bsize >> 2; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_firstinodezone = 2; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3138de52778798fe39660a8d6b26f290e0c93202761Al Viro flavour_setup[sbi->s_type](sbi, &sb->s_max_links); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_truncate = 1; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_inodes_per_block = bsize >> 6; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_inodes_per_block_1 = (bsize >> 6)-1; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_inodes_per_block_bits = n_bits-6; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_ind_per_block = bsize_4; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_ind_per_block_2 = bsize_4*bsize_4; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_toobig_block = 10 + bsize_4 * (1 + bsize_4 * (1 + bsize_4)); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_ind_per_block_bits = n_bits-2; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_ninodes = (sbi->s_firstdatazone - sbi->s_firstinodezone) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds << sbi->s_inodes_per_block_bits; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!silent) 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("VFS: Found a %s FS (block size = %ld) on device %s\n", 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found, sb->s_blocksize, sb->s_id); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_magic = SYSV_MAGIC_BASE + sbi->s_type; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set up enough so that it can read an inode */ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_op = &sysv_sops; 33530304aba6a053f114092cea6643a96ac2902bc5aAl Viro if (sbi->s_forced_ro) 33630304aba6a053f114092cea6643a96ac2902bc5aAl Viro sb->s_flags |= MS_RDONLY; 33730304aba6a053f114092cea6643a96ac2902bc5aAl Viro if (sbi->s_truncate) 33830304aba6a053f114092cea6643a96ac2902bc5aAl Viro sb->s_d_op = &sysv_dentry_operations; 339b8e1343f67460554ca5321956c440cc064e9889bDavid Howells root_inode = sysv_iget(sb, SYSV_ROOT_INO); 340b8e1343f67460554ca5321956c440cc064e9889bDavid Howells if (IS_ERR(root_inode)) { 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SysV FS: get root inode failed\n"); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 34448fde701aff662559b38d9a609574068f22d00feAl Viro sb->s_root = d_make_root(root_inode); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sb->s_root) { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SysV FS: get root dentry failed\n"); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sysv_fill_super(struct super_block *sb, void *data, int silent) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh1, *bh = NULL; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv_sb_info *sbi; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long blocknr; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = 0, i; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3592ecd05ae68a903761e736e9e0aca40d6ace4319eAlexey Dobriyan BUILD_BUG_ON(1024 != sizeof (struct xenix_super_block)); 3602ecd05ae68a903761e736e9e0aca40d6ace4319eAlexey Dobriyan BUILD_BUG_ON(512 != sizeof (struct sysv4_super_block)); 3612ecd05ae68a903761e736e9e0aca40d6ace4319eAlexey Dobriyan BUILD_BUG_ON(512 != sizeof (struct sysv2_super_block)); 3622ecd05ae68a903761e736e9e0aca40d6ace4319eAlexey Dobriyan BUILD_BUG_ON(500 != sizeof (struct coh_super_block)); 3632ecd05ae68a903761e736e9e0aca40d6ace4319eAlexey Dobriyan BUILD_BUG_ON(64 != sizeof (struct sysv_inode)); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 365f8314dc60ccba7e41f425048c4160dc7f63377d5Panagiotis Issaris sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sbi) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb = sb; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_block_base = 0; 371c07cb01c45d6f5f80da63e0b17dca889dba48cc1Marco Stornelli mutex_init(&sbi->s_lock); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_fs_info = sbi; 373e8c96f8c29d89af0c13dc2819a9a00575846ca18Tobias Klauser 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_set_blocksize(sb, BLOCK_SIZE); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 376e8c96f8c29d89af0c13dc2819a9a00575846ca18Tobias Klauser for (i = 0; i < ARRAY_SIZE(flavours) && !size; i++) { 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh = sb_bread(sb, flavours[i].block); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bh) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = flavours[i].test(SYSV_SB(sb), bh); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!size) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto Eunknown; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (size) { 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blocknr = bh->b_blocknr << 1; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_set_blocksize(sb, 512); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh1 = sb_bread(sb, blocknr); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh = sb_bread(sb, blocknr + 1); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh1 = bh; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blocknr = bh->b_blocknr >> 1; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_set_blocksize(sb, 2048); 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh1 = bh = sb_bread(sb, blocknr); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto Ebadsize; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bh && bh1) { 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bh1 = bh1; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bh2 = bh; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (complete_read_super(sb, silent, size)) 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh1); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_set_blocksize(sb, BLOCK_SIZE); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("oldfs: cannot read superblock\n"); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed: 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(sbi); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEunknown: 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!silent) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("VFS: unable to find oldfs superblock on device %s\n", 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_id); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEbadsize: 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!silent) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("VFS: oldfs: unsupported block size (%dKb)\n", 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1<<(size-2)); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4376d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintelstatic int v7_sanity_check(struct super_block *sb, struct buffer_head *bh) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct v7_super_block *v7sb; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sysv_inode *v7i; 4416d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel struct buffer_head *bh2; 4426d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel struct sysv_sb_info *sbi; 4436d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4446d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel sbi = sb->s_fs_info; 4456d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4466d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel /* plausibility check on superblock */ 4476d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel v7sb = (struct v7_super_block *) bh->b_data; 4486d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE || 4496d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD || 4506d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE) 4516d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel return 0; 4526d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4536d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel /* plausibility check on root inode: it is a directory, 4546d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel with a nonzero size that is a multiple of 16 */ 4556d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel bh2 = sb_bread(sb, 2); 4566d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel if (bh2 == NULL) 4576d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel return 0; 4586d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4596d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel v7i = (struct sysv_inode *)(bh2->b_data + 64); 4606d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR || 4616d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel (fs32_to_cpu(sbi, v7i->i_size) == 0) || 4626d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel (fs32_to_cpu(sbi, v7i->i_size) & 017) || 4636d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES * 4646d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel sizeof(struct sysv_dir_entry))) { 4656d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel brelse(bh2); 4666d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel return 0; 4676d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel } 4686d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4696d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel brelse(bh2); 4706d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel return 1; 4716d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel} 4726d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 4736d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintelstatic int v7_fill_super(struct super_block *sb, void *data, int silent) 4746d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel{ 4756d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel struct sysv_sb_info *sbi; 4766d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel struct buffer_head *bh; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (440 != sizeof (struct v7_super_block)) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds panic("V7 FS: bad super-block size"); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (64 != sizeof (struct sysv_inode)) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds panic("sysv fs: bad i-node size"); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 483f8314dc60ccba7e41f425048c4160dc7f63377d5Panagiotis Issaris sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sbi) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_sb = sb; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_block_base = 0; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_type = FSTYPE_V7; 49049475555848d396a0c78fb2f8ecceb3f3f263ef1Lubomir Rintel mutex_init(&sbi->s_lock); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->s_fs_info = sbi; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_set_blocksize(sb, 512); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((bh = sb_bread(sb, 1)) == NULL) { 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!silent) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("VFS: unable to read V7 FS superblock on " 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "device %s.\n", sb->s_id); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5026d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel /* Try PDP-11 UNIX */ 5036d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel sbi->s_bytesex = BYTESEX_PDP; 5046d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel if (v7_sanity_check(sb, bh)) 5056d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel goto detected; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5076d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel /* Try PC/IX, v7/x86 */ 5086d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel sbi->s_bytesex = BYTESEX_LE; 5096d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel if (v7_sanity_check(sb, bh)) 5106d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel goto detected; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5126d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel goto failed; 5136d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel 5146d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rinteldetected: 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bh1 = bh; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->s_bh2 = bh; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (complete_read_super(sb, silent, 1)) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed: 5216d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel printk(KERN_ERR "VFS: could not find a valid V7 on %s.\n", 5226d0b5456e14ec19edae7c18de4d355c58b133bd6Lubomir Rintel sb->s_id); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(sbi); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Every kernel module contains stuff like this. */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 530152a08366671080f27b32e0c411ad620c5f88b57Al Virostatic struct dentry *sysv_mount(struct file_system_type *fs_type, 531152a08366671080f27b32e0c411ad620c5f88b57Al Viro int flags, const char *dev_name, void *data) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 533152a08366671080f27b32e0c411ad620c5f88b57Al Viro return mount_bdev(fs_type, flags, dev_name, data, sysv_fill_super); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 536152a08366671080f27b32e0c411ad620c5f88b57Al Virostatic struct dentry *v7_mount(struct file_system_type *fs_type, 537152a08366671080f27b32e0c411ad620c5f88b57Al Viro int flags, const char *dev_name, void *data) 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 539152a08366671080f27b32e0c411ad620c5f88b57Al Viro return mount_bdev(fs_type, flags, dev_name, data, v7_fill_super); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_system_type sysv_fs_type = { 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "sysv", 545152a08366671080f27b32e0c411ad620c5f88b57Al Viro .mount = sysv_mount, 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .kill_sb = kill_block_super, 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fs_flags = FS_REQUIRES_DEV, 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5497f78e0351394052e1a6293e175825eb5c7869507Eric W. BiedermanMODULE_ALIAS_FS("sysv"); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_system_type v7_fs_type = { 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "v7", 554152a08366671080f27b32e0c411ad620c5f88b57Al Viro .mount = v7_mount, 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .kill_sb = kill_block_super, 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fs_flags = FS_REQUIRES_DEV, 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5587f78e0351394052e1a6293e175825eb5c7869507Eric W. BiedermanMODULE_ALIAS_FS("v7"); 559fa7614ddd6c2368b8cd54cc67ab4b767af0a2a50Eric W. BiedermanMODULE_ALIAS("v7"); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_sysv_fs(void) 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = sysv_init_icache(); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = register_filesystem(&sysv_fs_type); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto destroy_icache; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = register_filesystem(&v7_fs_type); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto unregister; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunregister: 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_filesystem(&sysv_fs_type); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdestroy_icache: 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysv_destroy_icache(); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit exit_sysv_fs(void) 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_filesystem(&sysv_fs_type); 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_filesystem(&v7_fs_type); 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sysv_destroy_icache(); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_sysv_fs) 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(exit_sysv_fs) 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 594