📄 inode.c
字号:
if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) goto bad_shift; sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; goto ok; } if ((found = detect_sysv2(sb,bh)) != NULL) { if (sb->sv_block_size>BLOCK_SIZE && (offsets[i] % 2)) goto bad_shift; sb->sv_block_base = (offsets[i] << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; goto ok; } brelse(bh); } } bad_shift: if (!silent) printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device " "%s\n", kdevname(dev)); failed: return NULL; ok: if (sb->sv_block_size >= BLOCK_SIZE) { if (sb->sv_block_size != BLOCK_SIZE) { brelse(bh); set_blocksize(dev, sb->sv_block_size); blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; if ((bh = bread(dev, blocknr, sb->sv_block_size)) == NULL) goto bad_superblock; } switch (sb->sv_type) { case FSTYPE_XENIX: if (!detected_xenix(sb,bh,bh)) goto bad_superblock; break; case FSTYPE_SYSV4: if (!detected_sysv4(sb,bh)) goto bad_superblock; break; case FSTYPE_SYSV2: if (!detected_sysv2(sb,bh)) goto bad_superblock; break; default: goto bad_superblock; goto superblock_ok; bad_superblock: brelse(bh); printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size); goto failed; superblock_ok: } } else { /* Switch to 512 block size. Unfortunately, we have to release the block bh and read it again. */ struct buffer_head *bh1, *bh2; unsigned long blocknr = (bh->b_blocknr << sb->sv_block_size_dec_bits) >> sb->sv_block_size_inc_bits; brelse(bh); set_blocksize(dev,sb->sv_block_size); bh1 = NULL; bh2 = NULL; switch (sb->sv_type) { case FSTYPE_XENIX: if ((bh1 = bread(dev, blocknr, sb->sv_block_size)) == NULL) goto bad_superblock2; if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) goto bad_superblock2; if (!detected_xenix(sb,bh1,bh2)) goto bad_superblock2; break; case FSTYPE_SYSV4: if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) goto bad_superblock2; if (!detected_sysv4(sb,bh2)) goto bad_superblock2; break; case FSTYPE_SYSV2: if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) goto bad_superblock2; if (!detected_sysv2(sb,bh2)) goto bad_superblock2; break; case FSTYPE_COH: if ((bh2 = bread(dev, blocknr+1, sb->sv_block_size)) == NULL) goto bad_superblock2; if (!detected_coherent(sb,bh2)) goto bad_superblock2; break; default: bad_superblock2: brelse(bh1); brelse(bh2); set_blocksize(sb->s_dev,BLOCK_SIZE); printk("SysV FS: cannot read superblock in 512 byte mode\n"); goto failed; } } sb->sv_ninodes = (sb->sv_firstdatazone - sb->sv_firstinodezone) << sb->sv_inodes_per_block_bits; if (!silent) printk("VFS: Found a %s FS (block size = %d) on device %s\n", found, sb->sv_block_size, kdevname(dev)); sb->s_magic = SYSV_MAGIC_BASE + sb->sv_type; /* The buffer code now supports block size 512 as well as 1024. */ sb->s_blocksize = sb->sv_block_size; sb->s_blocksize_bits = sb->sv_block_size_bits; /* set up enough so that it can read an inode */ sb->s_op = &sysv_sops; root_inode = iget(sb,SYSV_ROOT_INO); sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) { printk("SysV FS: get root inode failed\n"); sysv_put_super(sb); return NULL; }#ifndef CONFIG_SYSV_FS_WRITE sb->s_flags |= MS_RDONLY;#endif sb->s_dirt = 1; /* brelse(bh); resp. brelse(bh1); brelse(bh2); occurs when the disk is unmounted. */ return sb;}/* This is only called on sync() and umount(), when s_dirt=1. */static void sysv_write_super(struct super_block *sb){ if (buffer_dirty(sb->sv_bh1) || buffer_dirty(sb->sv_bh2)) { /* If we are going to write out the super block, then attach current time stamp. But if the filesystem was marked clean, keep it clean. */ unsigned long time = CURRENT_TIME; unsigned long old_time = *sb->sv_sb_time; if (sb->sv_convert) old_time = from_coh_ulong(old_time); if (sb->sv_type == FSTYPE_SYSV4) if (*sb->sv_sb_state == 0x7c269d38 - old_time) *sb->sv_sb_state = 0x7c269d38 - time; if (sb->sv_convert) time = to_coh_ulong(time); *sb->sv_sb_time = time; mark_buffer_dirty(sb->sv_bh2); } sb->s_dirt = 0;}static void sysv_put_super(struct super_block *sb){ /* we can assume sysv_write_super() has already been called, and that the superblock is locked */ brelse(sb->sv_bh1); if (sb->sv_bh1 != sb->sv_bh2) brelse(sb->sv_bh2); /* switch back to default block size */ if (sb->s_blocksize != BLOCK_SIZE) set_blocksize(sb->s_dev,BLOCK_SIZE);}static int sysv_statfs(struct super_block *sb, struct statfs *buf){ buf->f_type = sb->s_magic; /* type of filesystem */ buf->f_bsize = sb->sv_block_size; /* block size */ buf->f_blocks = sb->sv_ndatazones; /* total data blocks in file system */ buf->f_bfree = sysv_count_free_blocks(sb); /* free blocks in fs */ buf->f_bavail = buf->f_bfree; /* free blocks available to non-superuser */ buf->f_files = sb->sv_ninodes; /* total file nodes in file system */ buf->f_ffree = sysv_count_free_inodes(sb); /* free file nodes in fs */ buf->f_namelen = SYSV_NAMELEN; /* Don't know what value to put in buf->f_fsid */ /* file system id */ return 0;}/* bmap support for running executables and shared libraries. */static inline int inode_bmap(struct super_block * sb, struct inode * inode, int nr){ int tmp = inode->u.sysv_i.i_data[nr]; if (!tmp) return 0; return tmp + sb->sv_block_base;}static int block_bmap(struct super_block * sb, struct buffer_head * bh, int nr, int convert){ int tmp; if (!bh) return 0; tmp = ((sysv_zone_t *) bh->b_data) [nr]; if (convert) tmp = from_coh_ulong(tmp); brelse(bh); if (!tmp) return 0; return tmp + sb->sv_block_base;}static unsigned int sysv_block_map(struct inode *inode, unsigned int block){ struct super_block *sb; int i, ret, convert; ret = 0; lock_kernel(); sb = inode->i_sb; if (block < 10) { ret = inode_bmap(sb, inode, block); goto out; } block -= 10; convert = sb->sv_convert; if (block < sb->sv_ind_per_block) { i = inode_bmap(sb, inode, 10); if (!i) goto out; ret = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), block, convert); goto out; } block -= sb->sv_ind_per_block; if (block < sb->sv_ind_per_block_2) { i = inode_bmap(sb, inode, 11); if (!i) goto out; i = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), (block >> sb->sv_ind_per_block_bits), convert); if (!i) goto out; ret = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), (block & sb->sv_ind_per_block_1), convert); goto out; } block -= sb->sv_ind_per_block_2; if (block < sb->sv_ind_per_block_3) { i = inode_bmap(sb, inode, 12); if (!i) goto out; i = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), (block >> sb->sv_ind_per_block_2_bits), convert); if (!i) goto out; ret = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), ((block >> sb->sv_ind_per_block_bits) & sb->sv_ind_per_block_1), convert); if (!i) goto out; ret = block_bmap(sb, bread(inode->i_dev, i, sb->sv_block_size), (block & sb->sv_ind_per_block_1), convert); goto out; } if ((int)block < 0) printk("sysv_block_map: block < 0\n"); else printk("sysv_block_map: block > big\n");out: unlock_kernel(); return ret;}/* End of bmap support. *//* Access selected blocks of regular files (or directories) */static struct buffer_head *inode_getblk(struct inode *inode, int nr, int new_block, int *err, int metadata, long *phys, int *new){ struct super_block *sb; u32 tmp; u32 *p; struct buffer_head * result; sb = inode->i_sb; p = inode->u.sysv_i.i_data + nr;repeat: tmp = *p; if (tmp) { if (metadata) { result = sv_getblk(sb, inode->i_dev, tmp); if (tmp == *p) return result; brelse(result); goto repeat; } else { *phys = tmp; return NULL; } } tmp = sysv_new_block(sb); if (!tmp) { *err = -ENOSPC; return NULL; } if (metadata) { result = sv_getblk(sb, inode->i_dev, tmp); if (*p) { sysv_free_block(sb, tmp); brelse(result); goto repeat; } } else { if (*p) { /* * Nobody is allowed to change block allocation * state from under us: */ BUG(); sysv_free_block(sb, tmp); goto repeat; } *phys = tmp; result = NULL; *err = 0; *new = 1; } *p = tmp; inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); return result;}static struct buffer_head *block_getblk(struct inode *inode, struct buffer_head *bh, int nr, int new_block, int *err, int metadata, long *phys, int *new){ struct super_block *sb; u32 tmp, block; sysv_zone_t *p; struct buffer_head * result; result = NULL; if (!bh) goto out; if (!buffer_uptodate(bh)) { ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) goto out; } sb = inode->i_sb; p = nr + (sysv_zone_t *) bh->b_data;repeat: block = tmp = *p; if (sb->sv_convert) block = from_coh_ulong(block); if (tmp) { if (metadata) { result = sv_getblk(sb, bh->b_dev, block); if (tmp == *p) goto out; brelse(result); goto repeat; } else { *phys = tmp; goto out; } } block = sysv_new_block(sb); if (!block) goto out; if (metadata) { result = sv_getblk(sb, bh->b_dev, block); if (*p) { sysv_free_block(sb, block); brelse(result); goto repeat; } memset(result->b_data, 0, sb->sv_block_size); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result); } else { *phys = tmp; *new = 1; } if (*p) { sysv_free_block(sb, block); brelse(result); goto repeat; } *p = (sb->sv_convert ? to_coh_ulong(block) : block); mark_buffer_dirty(bh); *err = 0;out: brelse(bh); return result;}static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -