int FreeBlk(int dev, int blk) { char buf[BLKSIZE * 2]; struct SupBlock* sptr= (struct SupBlock*) buf; readSuper(dev,sptr); sptr->sb_nfreeblk++; //if list is already full if (sptr->sb_freeblkindex==1) { //then copy (empty) the list into given blk and store its address at index 0 in the list WriteBlock(dev,DATA_BLK_STARTS_AT+blk,(char*)sptr->sb_freeblks); sptr->sb_freeblks[0]=blk; sptr->sb_freeblkindex= BLKSIZE/sizeof(short); writeSuper(dev,sptr); return 0;//success } else { sptr->sb_freeblkindex--; sptr->sb_freeblks[sptr->sb_freeblkindex]=blk; writeSuper(dev,sptr); } return 0;//success }
int AllocBlk(int dev) { char buf[BLKSIZE * 2]; struct SupBlock* sptr= (struct SupBlock*) buf; readSuper(dev,buf); if (sptr->sb_nfreeblk==0) { //no free blks available return -1; } sptr->sb_nfreeblk--; if (sptr->sb_freeblkindex==BLKSIZE/sizeof(short))//if it is the last entry { // this will be executed if super-blk free-blk-list becoms empty..now copy the whole block pointed by pointer in list // at index 0 to the super-blk free-blk list int blkno=sptr->sb_freeblks[0]; ReadBlock(dev,DATA_BLK_STARTS_AT+blkno,sptr->sb_freeblks); //update superblk and freeze the changes sptr->sb_freeblkindex=1; writeSuper(dev,sptr); //now return this block as free block return blkno; } int freeblk=sptr->sb_freeblks[sptr->sb_freeblkindex]; sptr->sb_freeblkindex++; // Freeze the changes in super-block writeSuper(dev,sptr); return freeblk; }
int AllocInode(int dev) { char buf[BLKSIZE * 2]; struct SupBlock* sptr= (struct SupBlock*) buf; readSuper(dev,sptr); if (sptr->sb_nfreeino==0) { //no free inos available return -1; } sptr->sb_nfreeino--; if (sptr->sb_freeinoindex==(BLKSIZE-54)/sizeof(short))//if list becomes empty { // then scan the inode block to search free inodes and fill again the list in superblk int i; char buff[BLKSIZE]; int done=0; for (i=0; i< 8 && done==0 ; i++) { ReadBlock(dev,INODE_BLK_STARTS_AT+i,buff); struct INode* iptr=(struct INode*) buff; int j; for (j=0; j< BLKSIZE/sizeof(struct INode) && done==0 ; j++,iptr++) { if (iptr->i_lnk ==0) // no of hardlinks==0 { int ino_of_this_inode = i* (BLKSIZE/sizeof(struct INode)) + j + 1; sptr->sb_freeinoindex--; sptr->sb_freeinos[sptr->sb_freeinoindex]=ino_of_this_inode; // if list is full now if (sptr->sb_freeinoindex==0) done=1; } } } } int free_inode= sptr->sb_freeinos[sptr->sb_freeinoindex]; // Freeze the changes in super block sptr->sb_freeinoindex++; writeSuper(dev,buf); return free_inode; }
/* * updateSuper() * * update synchronously superblock if it is mounted read-write. */ int updateSuper(struct super_block *sb, uint state) { struct jfs_superblock *j_sb; struct jfs_sb_info *sbi = JFS_SBI(sb); struct buffer_head *bh; int rc; if (sbi->flag & JFS_NOINTEGRITY) { if (state == FM_DIRTY) { sbi->p_state = state; return 0; } else if (state == FM_MOUNT) { sbi->p_state = sbi->state; state = FM_DIRTY; } else if (state == FM_CLEAN) { state = sbi->p_state; } else jfs_err("updateSuper: bad state"); } else if (sbi->state == FM_DIRTY) return 0; if ((rc = readSuper(sb, &bh))) return rc; j_sb = (struct jfs_superblock *)bh->b_data; j_sb->s_state = cpu_to_le32(state); sbi->state = state; if (state == FM_MOUNT) { /* record log's dev_t and mount serial number */ j_sb->s_logdev = cpu_to_le32(sbi->log->bdev->bd_dev); j_sb->s_logserial = cpu_to_le32(sbi->log->serial); } else if (state == FM_CLEAN) { /* * If this volume is shared with OS/2, OS/2 will need to * recalculate DASD usage, since we don't deal with it. */ if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED)) j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME); } mark_buffer_dirty(bh); ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); brelse(bh); return 0; }
int updateSuper(struct super_block *sb, uint state) { struct jfs_superblock *j_sb; struct jfs_sb_info *sbi = JFS_SBI(sb); struct buffer_head *bh; int rc; if (sbi->flag & JFS_NOINTEGRITY) { if (state == FM_DIRTY) { sbi->p_state = state; return 0; } else if (state == FM_MOUNT) { sbi->p_state = sbi->state; state = FM_DIRTY; } else if (state == FM_CLEAN) { state = sbi->p_state; } else jfs_err("updateSuper: bad state"); } else if (sbi->state == FM_DIRTY) return 0; if ((rc = readSuper(sb, &bh))) return rc; j_sb = (struct jfs_superblock *)bh->b_data; j_sb->s_state = cpu_to_le32(state); sbi->state = state; if (state == FM_MOUNT) { j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev)); j_sb->s_logserial = cpu_to_le32(sbi->log->serial); } else if (state == FM_CLEAN) { if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED)) j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME); } mark_buffer_dirty(bh); sync_dirty_buffer(bh); brelse(bh); return 0; }
/* * chkSuper() * * validate the superblock of the file system to be mounted and * get the file system parameters. * * returns * 0 with fragsize set if check successful * error code if not successful */ static int chkSuper(struct super_block *sb) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_superblock *j_sb; struct buffer_head *bh; int AIM_bytesize, AIT_bytesize; int expected_AIM_bytesize, expected_AIT_bytesize; s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr; s64 byte_addr_diff0, byte_addr_diff1; s32 bsize; if ((rc = readSuper(sb, &bh))) return rc; j_sb = (struct jfs_superblock *)bh->b_data; /* * validate superblock */ /* validate fs signature */ if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || le32_to_cpu(j_sb->s_version) > JFS_VERSION) { rc = -EINVAL; goto out; } bsize = le32_to_cpu(j_sb->s_bsize); #ifdef _JFS_4K if (bsize != PSIZE) { jfs_err("Currently only 4K block size supported!"); rc = -EINVAL; goto out; } #endif /* _JFS_4K */ jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), (unsigned long long) le64_to_cpu(j_sb->s_size)); /* validate the descriptors for Secondary AIM and AIT */ if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != cpu_to_le32(JFS_BAD_SAIT)) { expected_AIM_bytesize = 2 * PSIZE; AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; expected_AIT_bytesize = 4 * PSIZE; AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; if ((AIM_bytesize != expected_AIM_bytesize) || (AIT_bytesize != expected_AIT_bytesize) || (byte_addr_diff0 != AIM_bytesize) || (byte_addr_diff1 <= AIT_bytesize)) j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); } if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != cpu_to_le32(JFS_GROUPCOMMIT)) j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); /* validate fs state */ if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && !(sb->s_flags & MS_RDONLY)) { jfs_err("jfs_mount: Mount Failure: File System Dirty."); rc = -EINVAL; goto out; } sbi->state = le32_to_cpu(j_sb->s_state); sbi->mntflag = le32_to_cpu(j_sb->s_flag); /* * JFS always does I/O by 4K pages. Don't tell the buffer cache * that we use anything else (leave s_blocksize alone). */ sbi->bsize = bsize; sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); /* * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer * cache. */ sbi->nbperpage = PSIZE >> sbi->l2bsize; sbi->l2nbperpage = L2PSIZE - sbi->l2bsize; sbi->l2niperblk = sbi->l2bsize - L2DISIZE; if (sbi->mntflag & JFS_INLINELOG) sbi->logpxd = j_sb->s_logpxd; else { sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev)); memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); } sbi->fsckpxd = j_sb->s_fsckpxd; sbi->ait2 = j_sb->s_ait2; out: brelse(bh); return rc; }
/* * NAME: jfs_statfs(vfsp, sfsp, crp) * * FUNCTION: get file system status <sfsp> from vfs <vfsp> * * PARAMETER: vfsp - virtual file system * sfsp - file status information structure * crp - credential * * RETURN: zero on success, non-zero on failure * * serialization: statfs() and extendfs() serializes by inode lock * of the inode map for both inode map and block allocation map. * All other access to fragment allocation map is serialized * under VMM locking. * * note: percolation of file system information: * support struct statfs (sys/statfs.h) for get file system status * service call statfs(). * (XPG4.2 defines struct statvfs in sys/statvfs.h for statvfs() * which requires statfs() and additional information) */ jfs_statfs( register struct vfs *vfsp, register struct statfs *statfsp, struct ucred *crp) { register int32 rc; register inode_t *ipmnt; /* mount inode */ inode_t *ipimap, *ipbmap; cbuf_t *bpsuper; struct superblock *sb = NULL; int32 fsck_length, log_length; NOISE(1,("jfs_statfs: vfs:0x%08x\n", vfsp)); /* * get the file system stats from the superblock */ ipimap = (struct inode *)vfsp->vfs_data; ipmnt = ipimap->i_ipmnt; if (rc = readSuper(ipmnt, &bpsuper)) goto out; sb = (struct superblock *)(bpsuper->cm_cdata); /* bcopy(sb->s_fname, statfsp->f_fname, sizeof(sb->s_fname)); */ bcopy(sb->s_fpack, statfsp->f_fpack, sizeof(sb->s_fpack)); statfsp->f_bsize = PSIZE; /* preferred i/o block size */ statfsp->f_fsize = sb->s_bsize; /* fundamental block size */ fsck_length = lengthPXD(&(sb->s_fsckpxd)); log_length = lengthPXD(&(sb->s_logpxd)); rawRelease(bpsuper); /* statfs()/extendfs() serialized by inode lock of the inode map * for both inode map and block allocation map. */ IREAD_LOCK(ipimap); /* * get the block stats from the bmap */ ipbmap = ipmnt->i_ipbmap; statfsp->f_blocks = (ipbmap->i_bmap->db_mapsize + fsck_length + log_length) >> ipbmap->i_bmap->db_l2nbperpage; statfsp->f_bfree = statfsp->f_bavail = ipbmap->i_bmap->db_nfree >> ipbmap->i_bmap->db_l2nbperpage; /* * get the file stats from the ipimap */ statfsp->f_files = ipimap->i_imap->im_numinos; statfsp->f_ffree = ipimap->i_imap->im_numfree; /* * fill in from vfs */ statfsp->f_fsid = vfsp->vfs_fsid; statfsp->f_vfstype = MNT_XJFS; statfsp->f_vfsnumber = vfsp->vfs_number; statfsp->f_name_max = JFS_NAME_MAX; /* * fields in the statfs structure that we don't fill in ... * long f_version; version/type of statfs, 0 for now long f_type; type of info, 0 for now long f_vfsoff; reserved, for vfs specific data offset long f_vfslen; reserved, for len of vfs specific data long f_vfsvers; reserved, for vers of vfs specific data */ out: IREAD_UNLOCK(ipimap); return rc; }