📄 inode.c
字号:
/* * linux/fs/sysv/inode.c * * minix/inode.c * Copyright (C) 1991, 1992 Linus Torvalds * * xenix/inode.c * Copyright (C) 1992 Doug Evans * * coh/inode.c * Copyright (C) 1993 Pascal Haible, Bruno Haible * * sysv/inode.c * Copyright (C) 1993 Paul B. Monday * * sysv/inode.c * Copyright (C) 1993 Bruno Haible * Copyright (C) 1997, 1998 Krzysztof G. Baranowski * * This file contains code for allocating/freeing inodes and for read/writing * the superblock. */#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/sysv_fs.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/highuid.h>#include <asm/byteorder.h>#include <asm/uaccess.h>#if 0void sysv_print_inode(struct inode * inode){ printk("ino %lu mode 0%6.6o lk %d uid %d gid %d" " sz %lu blks %lu cnt %u\n", inode->i_ino, inode->i_mode, inode->i_nlink, inode->i_uid, inode->i_gid, inode->i_size, inode->i_blocks, atomic_read(&inode->i_count)); printk(" db <0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx" " 0x%lx 0x%lx>\n", inode->u.sysv_i.i_data[0], inode->u.sysv_i.i_data[1], inode->u.sysv_i.i_data[2], inode->u.sysv_i.i_data[3], inode->u.sysv_i.i_data[4], inode->u.sysv_i.i_data[5], inode->u.sysv_i.i_data[6], inode->u.sysv_i.i_data[7], inode->u.sysv_i.i_data[8], inode->u.sysv_i.i_data[9]); printk(" ib <0x%lx 0x%lx 0x%lx>\n", inode->u.sysv_i.i_data[10], inode->u.sysv_i.i_data[11], inode->u.sysv_i.i_data[12]);}#endifstatic void sysv_delete_inode(struct inode *inode){ lock_kernel(); inode->i_size = 0; sysv_truncate(inode); sysv_free_inode(inode); unlock_kernel();}static void sysv_put_super(struct super_block *);static void sysv_write_super(struct super_block *);static void sysv_read_inode(struct inode *);static int sysv_statfs(struct super_block *, struct statfs *);static struct super_operations sysv_sops = { read_inode: sysv_read_inode, write_inode: sysv_write_inode, delete_inode: sysv_delete_inode, put_super: sysv_put_super, write_super: sysv_write_super, statfs: sysv_statfs,};/* The following functions try to recognize specific filesystems. * We recognize: * - Xenix FS by its magic number. * - SystemV FS by its magic number. * - Coherent FS by its funny fname/fpack field. * We discriminate among SystemV4 and SystemV2 FS by the assumption that * the time stamp is not < 01-01-1980. */static void detected_bs (u_char type, struct super_block *sb){ u_char n_bits = type+8; int bsize = 1 << n_bits; int bsize_4 = bsize >> 2; sb->sv_block_size = bsize; sb->sv_block_size_1 = bsize-1; sb->sv_block_size_bits = n_bits; sb->sv_block_size_dec_bits = (bsize==512) ? 1 : 0; sb->sv_block_size_inc_bits = (bsize==2048) ? 1 : 0; sb->sv_inodes_per_block = bsize >> 6; sb->sv_inodes_per_block_1 = (bsize >> 6)-1; sb->sv_inodes_per_block_bits = n_bits-6; sb->sv_toobig_block = 10 + (sb->sv_ind_per_block = bsize_4) + (sb->sv_ind_per_block_2 = bsize_4*bsize_4) + (sb->sv_ind_per_block_3 = bsize_4*bsize_4*bsize_4); sb->sv_ind_per_block_1 = bsize_4-1; sb->sv_ind_per_block_2_1 = bsize_4*bsize_4-1; sb->sv_ind_per_block_2_bits = 2 * (sb->sv_ind_per_block_bits = n_bits-2); sb->sv_ind_per_block_block_size_1 = bsize_4*bsize-1; sb->sv_ind_per_block_block_size_bits = 2*n_bits-2; sb->sv_ind_per_block_2_block_size_1 = bsize_4*bsize_4*bsize-1; sb->sv_ind_per_block_2_block_size_bits = 3*n_bits-4; sb->sv_ind0_size = 10 * bsize; sb->sv_ind1_size = (10 + bsize_4)* bsize; sb->sv_ind2_size = (10 + bsize_4 + bsize_4*bsize_4) * bsize;}static const char* detect_xenix (struct super_block *sb, struct buffer_head *bh){ struct xenix_super_block * sbd; sbd = (struct xenix_super_block *) bh->b_data; if (sbd->s_magic != 0x2b5544) return NULL; if (sbd->s_type > 2 || sbd->s_type < 1) return NULL; detected_bs(sbd->s_type, sb); sb->sv_type = FSTYPE_XENIX; return "Xenix";}static struct super_block * detected_xenix (struct super_block *sb, struct buffer_head *bh1, struct buffer_head *bh2){ struct xenix_super_block * sbd1; struct xenix_super_block * sbd2; if (sb->sv_block_size >= BLOCK_SIZE) /* block size >= 1024, so bh1 = bh2 */ sbd1 = sbd2 = (struct xenix_super_block *) bh1->b_data; else { /* block size = 512, so bh1 != bh2 */ sbd1 = (struct xenix_super_block *) bh1->b_data; sbd2 = (struct xenix_super_block *) (bh2->b_data - BLOCK_SIZE/2); /* sanity check */ if (sbd2->s_magic != 0x2b5544) return NULL; } sb->sv_convert = 0; sb->sv_kludge_symlinks = 1; sb->sv_truncate = 1; sb->sv_link_max = XENIX_LINK_MAX; sb->sv_fic_size = XENIX_NICINOD; sb->sv_flc_size = XENIX_NICFREE; sb->sv_bh1 = bh1; sb->sv_bh2 = bh2; sb->sv_sbd1 = (char *) sbd1; sb->sv_sbd2 = (char *) sbd2; sb->sv_sb_fic_count = &sbd1->s_ninode; sb->sv_sb_fic_inodes = &sbd1->s_inode[0]; sb->sv_sb_total_free_inodes = &sbd2->s_tinode; sb->sv_sb_flc_count = &sbd1->s_nfree; sb->sv_sb_flc_blocks = &sbd1->s_free[0]; sb->sv_sb_total_free_blocks = &sbd2->s_tfree; sb->sv_sb_time = &sbd2->s_time; sb->sv_firstinodezone = 2; sb->sv_firstdatazone = sbd1->s_isize; sb->sv_nzones = sbd1->s_fsize; sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; return sb;}static const char* detect_sysv4 (struct super_block *sb, struct buffer_head *bh){ struct sysv4_super_block * sbd; sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); if (sbd->s_magic != 0xfd187e20) return NULL; if (sbd->s_time < 315532800) /* this is likely to happen on SystemV2 FS */ return NULL; if ((sbd->s_type > 3 || sbd->s_type < 1) && (sbd->s_type > 0x30 || sbd->s_type < 0x10)) return NULL; /* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10, 0x20 or 0x30 indicates that symbolic links and the 14-character filename limit is gone. Due to lack of information about this feature read-only mode seems to be a reasonable approach... -KGB */ if (sbd->s_type >= 0x10) { printk("SysV FS: can't handle long file names on %s, " "forcing read-only mode.\n", kdevname(sb->s_dev)); sb->s_flags |= MS_RDONLY; } detected_bs(sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type, sb); sb->sv_type = FSTYPE_SYSV4; return "SystemV";}static struct super_block * detected_sysv4 (struct super_block *sb, struct buffer_head *bh){ struct sysv4_super_block * sbd; if (sb->sv_block_size >= BLOCK_SIZE) sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2); else { sbd = (struct sysv4_super_block *) bh->b_data; /* sanity check */ if (sbd->s_magic != 0xfd187e20) return NULL; if (sbd->s_time < 315532800) return NULL; } sb->sv_convert = 0; sb->sv_kludge_symlinks = 0; /* ?? */ sb->sv_truncate = 1; sb->sv_link_max = SYSV_LINK_MAX; sb->sv_fic_size = SYSV_NICINOD; sb->sv_flc_size = SYSV_NICFREE; sb->sv_bh1 = bh; sb->sv_bh2 = bh; sb->sv_sbd1 = (char *) sbd; sb->sv_sbd2 = (char *) sbd; sb->sv_sb_fic_count = &sbd->s_ninode; sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sb->sv_sb_total_free_inodes = &sbd->s_tinode; sb->sv_sb_flc_count = &sbd->s_nfree; sb->sv_sb_flc_blocks = &sbd->s_free[0]; sb->sv_sb_total_free_blocks = &sbd->s_tfree; sb->sv_sb_time = &sbd->s_time; sb->sv_sb_state = &sbd->s_state; sb->sv_firstinodezone = 2; sb->sv_firstdatazone = sbd->s_isize; sb->sv_nzones = sbd->s_fsize; sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; return sb;}static const char* detect_sysv2 (struct super_block *sb, struct buffer_head *bh){ struct sysv2_super_block * sbd; sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2); if (sbd->s_magic != 0xfd187e20) return NULL; if (sbd->s_time < 315532800) /* this is likely to happen on SystemV4 FS */ return NULL; if (sbd->s_type > 3 || sbd->s_type < 1) return NULL; detected_bs(sbd->s_type, sb); sb->sv_type = FSTYPE_SYSV2; return "SystemV Release 2";}static struct super_block * detected_sysv2 (struct super_block *sb, struct buffer_head *bh){ struct sysv2_super_block * sbd; if (sb->sv_block_size >= BLOCK_SIZE) sbd = (struct sysv2_super_block *) (bh->b_data + BLOCK_SIZE/2); else { sbd = (struct sysv2_super_block *) bh->b_data; /* sanity check */ if (sbd->s_magic != 0xfd187e20) return NULL; if (sbd->s_time < 315532800) return NULL; } sb->sv_convert = 0; sb->sv_kludge_symlinks = 0; /* ?? */ sb->sv_truncate = 1; sb->sv_link_max = SYSV_LINK_MAX; sb->sv_fic_size = SYSV_NICINOD; sb->sv_flc_size = SYSV_NICFREE; sb->sv_bh1 = bh; sb->sv_bh2 = bh; sb->sv_sbd1 = (char *) sbd; sb->sv_sbd2 = (char *) sbd; sb->sv_sb_fic_count = &sbd->s_ninode; sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sb->sv_sb_total_free_inodes = &sbd->s_tinode; sb->sv_sb_flc_count = &sbd->s_nfree; sb->sv_sb_flc_blocks = &sbd->s_free[0]; sb->sv_sb_total_free_blocks = &sbd->s_tfree; sb->sv_sb_time = &sbd->s_time; sb->sv_sb_state = &sbd->s_state; sb->sv_firstinodezone = 2; sb->sv_firstdatazone = sbd->s_isize; sb->sv_nzones = sbd->s_fsize; sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; return sb;}static const char* detect_coherent (struct super_block *sb, struct buffer_head *bh){ struct coh_super_block * sbd; sbd = (struct coh_super_block *) (bh->b_data + BLOCK_SIZE/2); if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) return NULL; detected_bs(1, sb); sb->sv_type = FSTYPE_COH; return "Coherent";}static struct super_block * detected_coherent (struct super_block *sb, struct buffer_head *bh){ struct coh_super_block * sbd; sbd = (struct coh_super_block *) bh->b_data; /* sanity check */ if ((memcmp(sbd->s_fname,"noname",6) && memcmp(sbd->s_fname,"xxxxx ",6)) || (memcmp(sbd->s_fpack,"nopack",6) && memcmp(sbd->s_fpack,"xxxxx\n",6))) return NULL; sb->sv_convert = 1; sb->sv_kludge_symlinks = 1; sb->sv_truncate = 1; sb->sv_link_max = COH_LINK_MAX; sb->sv_fic_size = COH_NICINOD; sb->sv_flc_size = COH_NICFREE; sb->sv_bh1 = bh; sb->sv_bh2 = bh; sb->sv_sbd1 = (char *) sbd; sb->sv_sbd2 = (char *) sbd; sb->sv_sb_fic_count = &sbd->s_ninode; sb->sv_sb_fic_inodes = &sbd->s_inode[0]; sb->sv_sb_total_free_inodes = &sbd->s_tinode; sb->sv_sb_flc_count = &sbd->s_nfree; sb->sv_sb_flc_blocks = &sbd->s_free[0]; sb->sv_sb_total_free_blocks = &sbd->s_tfree; sb->sv_sb_time = &sbd->s_time; sb->sv_firstinodezone = 2; sb->sv_firstdatazone = sbd->s_isize; sb->sv_nzones = from_coh_ulong(sbd->s_fsize); sb->sv_ndatazones = sb->sv_nzones - sb->sv_firstdatazone; return sb;}static struct super_block *sysv_read_super(struct super_block *sb, void *data, int silent){ struct buffer_head *bh; const char *found; kdev_t dev = sb->s_dev; struct inode *root_inode; unsigned long blocknr; if (1024 != sizeof (struct xenix_super_block)) panic("Xenix FS: bad super-block size"); if ((512 != sizeof (struct sysv4_super_block)) || (512 != sizeof (struct sysv2_super_block))) panic("SystemV FS: bad super-block size"); if (500 != sizeof (struct coh_super_block)) panic("Coherent FS: bad super-block size"); if (64 != sizeof (struct sysv_inode)) panic("sysv fs: bad i-node size"); set_blocksize(dev,BLOCK_SIZE); sb->sv_block_base = 0; /* Try to read Xenix superblock */ if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) { if ((found = detect_xenix(sb,bh)) != NULL) goto ok; brelse(bh); } if ((bh = bread(dev, 0, BLOCK_SIZE)) != NULL) { /* Try to recognize SystemV superblock */ if ((found = detect_sysv4(sb,bh)) != NULL) goto ok; if ((found = detect_sysv2(sb,bh)) != NULL) goto ok; /* Try to recognize Coherent superblock */ if ((found = detect_coherent(sb,bh)) != NULL) goto ok; brelse(bh); } /* Try to recognize SystemV superblock */ /* Offset by 1 track, i.e. most probably 9, 15, or 18 kilobytes. */ /* 2kB blocks with offset of 9 and 15 kilobytes are not supported. */ /* Maybe we should also check the device geometry ? */ { static int offsets[] = { 9, 15, 18, }; int i; for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) { /* Try to recognize SystemV superblock */ if ((found = detect_sysv4(sb,bh)) != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -