📄 super.c
字号:
/* N.B. after this point bh must be released */got_root: root_block = s->u.affs_sb.s_root_block; s->u.affs_sb.s_partition_size = size; s->s_blocksize_bits = blocksize == 512 ? 9 : blocksize == 1024 ? 10 : blocksize == 2048 ? 11 : 12; /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); if (!bb) goto out_no_root_block; chksum = be32_to_cpu(*(u32 *)bb->b_data); affs_brelse(bb); /* Dircache filesystems are compatible with non-dircache ones * when reading. As long as they aren't supported, writing is * not recommended. */ if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", kdevname(dev)); s->s_flags |= MS_RDONLY; s->u.affs_sb.s_flags |= SF_READONLY; } switch (chksum) { case MUFS_FS: case MUFS_INTLFFS: s->u.affs_sb.s_flags |= SF_MUFS; /* fall thru */ case FS_INTLFFS: s->u.affs_sb.s_flags |= SF_INTL; break; case MUFS_DCFFS: case MUFS_FFS: s->u.affs_sb.s_flags |= SF_MUFS; break; case FS_DCFFS: case FS_FFS: break; case MUFS_OFS: s->u.affs_sb.s_flags |= SF_MUFS; /* fall thru */ case FS_OFS: s->u.affs_sb.s_flags |= SF_OFS; s->s_flags |= MS_NOEXEC; break; case MUFS_DCOFS: case MUFS_INTLOFS: s->u.affs_sb.s_flags |= SF_MUFS; case FS_DCOFS: case FS_INTLOFS: s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; s->s_flags |= MS_NOEXEC; break; default: goto out_unknown_fs; } if (mount_flags & SF_VERBOSE) { chksum = cpu_to_be32(chksum); printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[0], &GET_END_PTR(struct root_end,bh->b_data,blocksize)->disk_name[1], (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } s->s_flags |= MS_NODEV | MS_NOSUID; /* Keep super block in cache */ bb = affs_bread(dev,root_block,s->s_blocksize); if (!bb) goto out_no_root_block; s->u.affs_sb.s_root_bh = bb; /* N.B. after this point s_root_bh must be released */ /* Allocate space for bitmaps, zones and others */ size = s->u.affs_sb.s_partition_size - reserved; num_bm = (size + s->s_blocksize * 8 - 32 - 1) / (s->s_blocksize * 8 - 32); az_no = (size + AFFS_ZONE_SIZE - 1) / (AFFS_ZONE_SIZE - 32); ptype = num_bm * sizeof(struct affs_bm_info) + az_no * sizeof(struct affs_alloc_zone) + MAX_ZONES * sizeof(struct affs_zone); pr_debug("AFFS: num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype, GFP_KERNEL))) goto out_no_bitmap; memset(s->u.affs_sb.s_bitmap,0,ptype); /* N.B. after the point s_bitmap must be released */ s->u.affs_sb.s_zones = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm]; s->u.affs_sb.s_alloc = (struct affs_alloc_zone *)&s->u.affs_sb.s_zones[MAX_ZONES]; s->u.affs_sb.s_num_az = az_no; mapidx = 0; if (ROOT_END_S(bh->b_data,s)->bm_flag == 0) { if (!(s->s_flags & MS_RDONLY)) { printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n", kdevname(dev)); s->s_flags |= MS_RDONLY; } affs_brelse(bh); bh = NULL; goto nobitmap; } /* The following section is ugly, I know. Especially because of the * reuse of some variables that are not named properly. */ key = root_block; ptype = s->s_blocksize / 4 - 49; stype = ptype + 25; offset = s->u.affs_sb.s_reserved; az_no = 0; while (bh) { bm = (u32 *)bh->b_data; for (i = ptype; i < stype && bm[i]; i++, mapidx++) { if (mapidx >= num_bm) { printk(KERN_ERR "AFFS: Extraneous bitmap pointer - " "mounting %s read only.\n",kdevname(dev)); s->s_flags |= MS_RDONLY; s->u.affs_sb.s_flags |= SF_READONLY; continue; } bb = affs_bread(dev,be32_to_cpu(bm[i]),s->s_blocksize); if (!bb) goto out_no_read_bm; if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && !(s->s_flags & MS_RDONLY)) { printk(KERN_WARNING "AFFS: Bitmap (%d,key=%u) invalid - " "mounting %s read only.\n",mapidx,be32_to_cpu(bm[i]), kdevname(dev)); s->s_flags |= MS_RDONLY; s->u.affs_sb.s_flags |= SF_READONLY; } /* Mark unused bits in the last word as allocated */ if (size <= s->s_blocksize * 8 - 32) { /* last bitmap */ ptype = size / 32 + 1; /* word number */ key = size & 0x1F; /* used bits */ if (key && !(s->s_flags & MS_RDONLY)) { chksum = cpu_to_be32(0x7FFFFFFF >> (31 - key)); ((u32 *)bb->b_data)[ptype] &= chksum; affs_fix_checksum(s->s_blocksize,bb->b_data,0); mark_buffer_dirty(bb); bmalt = 1; } ptype = (size + 31) & ~0x1F; size = 0; s->u.affs_sb.s_flags |= SF_BM_VALID; } else { ptype = s->s_blocksize * 8 - 32; size -= ptype; } s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset; s->u.affs_sb.s_bitmap[mapidx].bm_bh = NULL; s->u.affs_sb.s_bitmap[mapidx].bm_key = be32_to_cpu(bm[i]); s->u.affs_sb.s_bitmap[mapidx].bm_count = 0; offset += ptype; for (j = 0; ptype > 0; j++, az_no++, ptype -= key) { key = MIN(ptype,AFFS_ZONE_SIZE); /* size in bits */ s->u.affs_sb.s_alloc[az_no].az_size = key / 32; s->u.affs_sb.s_alloc[az_no].az_free = affs_count_free_bits(key / 8,bb->b_data + j * (AFFS_ZONE_SIZE / 8) + 4); } affs_brelse(bb); } key = be32_to_cpu(bm[stype]); /* Next block of bitmap pointers */ ptype = 0; stype = s->s_blocksize / 4 - 1; affs_brelse(bh); bh = NULL; if (key) { bh = affs_bread(dev,key,s->s_blocksize); if (!bh) goto out_no_bm_ext; } } if (mapidx < num_bm) goto out_bad_num;nobitmap: s->u.affs_sb.s_bm_count = num_bm; /* set up enough so that it can read an inode */ s->s_dirt = 1; root_inode = iget(s,root_block); if (!root_inode) goto out_no_root; s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root; s->s_root->d_op = &affs_dentry_operations; /* Record date of last change if the bitmap was truncated and * create data zones if the volume is writable. */ if (!(s->s_flags & MS_RDONLY)) { if (bmalt) { secs_to_datestamp(CURRENT_TIME,&ROOT_END( s->u.affs_sb.s_root_bh->b_data,root_inode)->disk_altered); affs_fix_checksum(s->s_blocksize,s->u.affs_sb.s_root_bh->b_data,5); mark_buffer_dirty(s->u.affs_sb.s_root_bh); } affs_make_zones(s); } pr_debug("AFFS: s_flags=%lX\n",s->s_flags); return s;out_bad_opts: printk(KERN_ERR "AFFS: Error parsing options\n"); goto out_fail;out_bad_size: printk(KERN_ERR "AFFS: Could not determine device size\n"); goto out_free_prefix;out_no_valid_block: if (!silent) printk(KERN_ERR "AFFS: No valid root block on device %s\n", kdevname(dev)); goto out_restore;out_unknown_fs: printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", kdevname(dev), chksum); goto out_free_bh;out_no_root_block: printk(KERN_ERR "AFFS: Cannot read root block\n"); goto out_free_bh;out_no_bitmap: printk(KERN_ERR "AFFS: Bitmap allocation failed\n"); goto out_free_root_block;out_no_read_bm: printk(KERN_ERR "AFFS: Cannot read bitmap\n"); goto out_free_bitmap;out_no_bm_ext: printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); goto out_free_bitmap;out_bad_num: printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n", mapidx, num_bm); goto out_free_bitmap;out_no_root: printk(KERN_ERR "AFFS: Get root inode failed\n"); /* * Begin the cascaded cleanup ... */ iput(root_inode);out_free_bitmap: kfree(s->u.affs_sb.s_bitmap);out_free_root_block: affs_brelse(s->u.affs_sb.s_root_bh);out_free_bh: affs_brelse(bh);out_restore: set_blocksize(dev, s->u.affs_sb.s_blksize);out_free_prefix: if (s->u.affs_sb.s_prefix) kfree(s->u.affs_sb.s_prefix);out_fail: return NULL;}static intaffs_remount(struct super_block *sb, int *flags, char *data){ int blocksize; uid_t uid; gid_t gid; int mode; int reserved; int root_block; unsigned long mount_flags; unsigned long read_only = sb->u.affs_sb.s_flags & SF_READONLY; pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block, &blocksize,&sb->u.affs_sb.s_prefix,sb->u.affs_sb.s_volume,&mount_flags)) return -EINVAL; sb->u.affs_sb.s_flags = mount_flags | read_only; sb->u.affs_sb.s_mode = mode; sb->u.affs_sb.s_uid = uid; sb->u.affs_sb.s_gid = gid; if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (*flags & MS_RDONLY) { sb->s_dirt = 1; while (sb->s_dirt) affs_write_super(sb); sb->s_flags |= MS_RDONLY; } else if (!(sb->u.affs_sb.s_flags & SF_READONLY)) { sb->s_flags &= ~MS_RDONLY; affs_make_zones(sb); } else { affs_warning(sb,"remount","Cannot remount fs read/write because of errors"); return -EINVAL; } return 0;}static intaffs_statfs(struct super_block *sb, struct statfs *buf){ int free; pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size, sb->u.affs_sb.s_reserved); free = affs_count_free_blocks(sb); buf->f_type = AFFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved; buf->f_bfree = free; buf->f_bavail = free; return 0;}static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);static int __init init_affs_fs(void){ return register_filesystem(&affs_fs_type);}static void __exit exit_affs_fs(void){ unregister_filesystem(&affs_fs_type);}EXPORT_NO_SYMBOLS;module_init(init_affs_fs)module_exit(exit_affs_fs)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -