u32_t read_fat_index(struct mfs_volume* volume, u128 index) { struct mfs_sb_info sb; read_sb(volume, &sb); u32_t start_position = 0; u32_t end_position = 0; u128 read_position = 0; u32_t value = 0; start_position = (sb.fat_sector * sb.bytes_per_sector); end_position = (sb.fat_sector + (sb.sectors_of_fat * sb.copies_of_fat)) * sb.bytes_per_sector; // Volume에서 읽을 위치를 계산한다. FAT Begin Address + FAT Index Address(Index - 2는 Index 0,1은 쓰이지 않기 때문이다. 시작이 2부터이다.) read_position = start_position + (sb.fat_index_size * (index - 2)); if(read_position > end_position) return FALSE; #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, &value, sizeof(u8_t), sb.fat_index_size); return value; }
BOOL write_in_fat_index(struct mfs_volume* volume, u32_t index, u64_t value) { struct mfs_sb_info sb; read_sb(volume, &sb); u32_t start_position = 0; u32_t end_position = 0; u128 write_position = 0; start_position = (sb.fat_sector * sb.bytes_per_sector); end_position = (sb.fat_sector + (sb.sectors_of_fat * sb.copies_of_fat)) * sb.bytes_per_sector; // Volume에 적을 위치를 계산한다. FAT Begin Address + FAT Index Address(Index - 2는 Index 0,1은 쓰이지 않기 때문이다. 시작이 2부터이다.) write_position = start_position + (sb.fat_index_size * (index - 2)); if(write_position > end_position) return FALSE; #ifdef __KERNEL__ seek_volume(volume, write_position); #else seek_volume(volume, write_position, SEEK_SET); #endif write_volume(volume, &value, sizeof(sb.fat_index_size), 1); return TRUE; }
/* lock given inode with flag I_BUSY * read the inode form disk if necessary * non-ref inode can not be lock (ref = 0) */ void ilock(struct inode *ip) { struct buf *bp; struct d_inode *d_ip; struct super_block sb; read_sb(ip->dev, &sb); int timeout = 20000; while (ip->flags & I_BUSY) { timeout--; hlt(); } ip->flags |= I_BUSY; /* need to be read form disk */ if (!(ip->flags & I_VALID)) { bp = bread(ip->dev, IBLK(sb, ip->ino)); d_ip = (struct d_inode *)bp->data + (ip->ino - 1)%IPB; /* ip -> dip */ ip->mode = d_ip->mode; ip->uid = d_ip->uid; ip->size = d_ip->size; ip->mtime = d_ip->mtime; ip->gid = d_ip->gid; ip->nlinks = d_ip->nlinks; memcpy(ip->zone, d_ip->zone, sizeof(d_ip->zone)); brelse(bp); ip->flags |= I_VALID; } }
void print_volume_status(struct mfs_volume* volume) { struct mfs_sb_info sb; memset(&sb, 0, sizeof(struct mfs_sb_info)); read_sb(volume, &sb); printf("Volume label : %s\n", sb.volume_label); printf("Serial number : %s\n", sb.volume_serial_number); printf("Bytes per sector : %d\n", sb.bytes_per_sector); printf("Sectors per cluster : %d\n", sb.sectors_per_cluster); printf("Copies of FAT : %d\n", sb.copies_of_fat); printf("Sectors of FAT : %d\n", sb.sectors_of_fat); printf("Reserved : %d\n", sb.reserved_bytes); printf("MFS version : %d.%d.%d\n", sb.version_major, sb.version_minor, sb.version_build); printf("FAT sector position : %d\n", sb.fat_sector); printf("Data cluster position : %d\n", sb.data_cluster_sector); printf("FAT index size : %d\n", sb.fat_index_size); printf("Total sectors HIGH : %llu\n", sb.total_sectors_high); printf("Total sectors LOW : %llu\n", sb.total_sectors_low); printf("Is used total sectors HIGH : %d\n", sb.flag_total_sectors_high); printf("Total data cluster sectors HIGH : %llu\n", sb.total_data_cluster_sectors_high); printf("Total data cluster sectors LOW : %llu\n", sb.total_data_cluster_sectors_low); printf("Is used total data cluster sectors HIGH : %d\n", sb.flag_total_data_cluster_sectors_high); printf("Reserved : %s\n", sb.reserved_bytes2); printf("The end : %d\n", sb.end_of_sb); }
u128 get_bad_cluster(struct mfs_volume* volume) { struct mfs_sb_info sb; u16_t fat_index_size = 0; read_sb(volume, &sb); fat_index_size = sb.fat_index_size; switch(fat_index_size) { case 1: return 0xFE; case 2: return 0xFFFE; case 4: return 0xFFFFFFFE; case 8: return 0xFFFFFFFFFFFFFFFE; default: #ifdef __KERNEL__ printk("ERROR: Can't get bad cluster. The fat index size is incorrect."); BUG_ON(1); #else printf("ERROR: Can't get bad cluster. The fat index size is incorrect."); exit(1); #endif break; } }
u128 read_cluster(struct mfs_volume* volume, u128 cluster_number) { struct mfs_sb_info sb; read_sb(volume, &sb); // Volume에서 읽을 위치를 계산한다. DataCluster Begin Address + 건내져온 클러스터 수치까지의 크기(nCurClusterNumber - 2는 Index 0,1은 쓰이지 않기 때문이다. 시작이 2부터이다.) return ((sb.data_cluster_sector * sb.bytes_per_sector) + ((cluster_number - 2) * CLUSTER_SIZE)); }
/* copy a in-memory inode to disk */ void iupdate(struct inode *ip) { struct buf *bp; struct d_inode *d_ip; struct super_block sb; read_sb(ip->dev , &sb); bp = bread(ip->dev, IBLK(sb, ip->ino)); d_ip = (struct d_inode *)bp->data + (ip->ino - 1)%IPB; /* ip -> d_ip */ d_ip->mode = ip->mode; d_ip->uid = ip->uid; d_ip->size = ip->size; d_ip->mtime= ip->mtime; d_ip->gid = ip->gid; d_ip->nlinks = ip->nlinks; memcpy(d_ip->zone, ip->zone, sizeof(ip->zone)); bwrite(bp); brelse(bp); }
u32_t find_empty_fat_index(struct mfs_volume* volume) { u8_t sector[BYTES_PER_SECTOR] = {0, }; u32_t start_position = 0; u32_t end_position = 0; u32_t read_position = 0; u32_t fat_index_value = 0; u32_t index = 0; struct mfs_sb_info sb; read_sb(volume, &sb); u32_t fat_index_size = sb.fat_index_size; start_position = (sb.fat_sector * sb.bytes_per_sector); end_position = (sb.fat_sector + (sb.sectors_of_fat * sb.copies_of_fat)) * sb.bytes_per_sector; for(read_position = start_position; read_position < end_position; read_position += BYTES_PER_SECTOR) { #ifdef __KERNEL__ seek_volume(volume, read_position); #else seek_volume(volume, read_position, SEEK_SET); #endif read_volume(volume, §or, sizeof(u8_t), sizeof(sector)); for(index = 0; index < BYTES_PER_SECTOR; index += fat_index_size) { fat_index_value = *((u32_t *)(sector + index)); if (fat_index_value == 0) { return (((read_position - start_position) / fat_index_size) + (index / fat_index_size) + 2); } } } // FAT안에 비어있는 Index가 존재하지 않는다. return FALSE; }
static int rtems_rfs_fs_read_superblock (rtems_rfs_file_system* fs) { rtems_rfs_buffer_handle handle; uint8_t* sb; int group; int rc; rc = rtems_rfs_buffer_handle_open (fs, &handle); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: handle open failed: %d: %s\n", rc, strerror (rc)); return rc; } rc = rtems_rfs_buffer_handle_request (fs, &handle, 0, true); if (rc > 0) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: request failed%d: %s\n", rc, strerror (rc)); return rc; } sb = rtems_rfs_buffer_data (&handle); #define read_sb(_o) rtems_rfs_read_u32 (sb + (_o)) if (read_sb (RTEMS_RFS_SB_OFFSET_MAGIC) != RTEMS_RFS_SB_MAGIC) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: invalid superblock, bad magic\n"); rtems_rfs_buffer_handle_close (fs, &handle); return EIO; } fs->blocks = read_sb (RTEMS_RFS_SB_OFFSET_BLOCKS); fs->block_size = read_sb (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE); if (rtems_rfs_fs_size(fs) > rtems_rfs_fs_media_size (fs)) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: invalid superblock block/size count\n"); rtems_rfs_buffer_handle_close (fs, &handle); return EIO; } if ((read_sb (RTEMS_RFS_SB_OFFSET_VERSION) & RTEMS_RFS_VERSION_MASK) != (RTEMS_RFS_VERSION * RTEMS_RFS_VERSION_MASK)) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: incompatible version: %08" PRIx32 " (%08" PRIx32 ")\n", read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK); rtems_rfs_buffer_handle_close (fs, &handle); return EIO; } if (read_sb (RTEMS_RFS_SB_OFFSET_INODE_SIZE) != RTEMS_RFS_INODE_SIZE) { if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: inode size mismatch: fs:%" PRId32 " target:%" PRId32 "\n", read_sb (RTEMS_RFS_SB_OFFSET_VERSION), RTEMS_RFS_VERSION_MASK); rtems_rfs_buffer_handle_close (fs, &handle); return EIO; } fs->bad_blocks = read_sb (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS); fs->max_name_length = read_sb (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH); fs->group_count = read_sb (RTEMS_RFS_SB_OFFSET_GROUPS); fs->group_blocks = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS); fs->group_inodes = read_sb (RTEMS_RFS_SB_OFFSET_GROUP_INODES); fs->blocks_per_block = rtems_rfs_fs_block_size (fs) / sizeof (rtems_rfs_inode_block); fs->block_map_singly_blocks = fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS; fs->block_map_doubly_blocks = fs->blocks_per_block * fs->blocks_per_block * RTEMS_RFS_INODE_BLOCKS; fs->inodes = fs->group_count * fs->group_inodes; fs->inodes_per_block = fs->block_size / RTEMS_RFS_INODE_SIZE; if (fs->group_blocks > rtems_rfs_bitmap_numof_bits (rtems_rfs_fs_block_size (fs))) { rtems_rfs_buffer_handle_close (fs, &handle); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: groups blocks larger than block bits\n"); return EIO; } rtems_rfs_buffer_handle_close (fs, &handle); /* * Change the block size to the value in the superblock. */ rc = rtems_rfs_buffer_setblksize (fs, rtems_rfs_fs_block_size (fs)); if (rc > 0) { rtems_rfs_buffer_handle_close (fs, &handle); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: invalid superblock block size%d: %s\n", rc, strerror (rc)); return rc; } fs->groups = calloc (fs->group_count, sizeof (rtems_rfs_group)); if (!fs->groups) { rtems_rfs_buffer_handle_close (fs, &handle); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: no memory for group table\n"); return ENOMEM; } /* * Perform each phase of group initialisation at the same time. This way we * know how far the initialisation has gone if an error occurs and we need to * close everything. */ for (group = 0; group < fs->group_count; group++) { rc = rtems_rfs_group_open (fs, rtems_rfs_fs_block (fs, group, 0), fs->group_blocks, fs->group_inodes, &fs->groups[group]); if (rc > 0) { int g; for (g = 0; g < group; g++) rtems_rfs_group_close (fs, &fs->groups[g]); rtems_rfs_buffer_handle_close (fs, &handle); if (rtems_rfs_trace (RTEMS_RFS_TRACE_OPEN)) printf ("rtems-rfs: read-superblock: no memory for group table%d: %s\n", rc, strerror (rc)); return rc; } } return 0; }
int main(int argc, char *argv[]) { struct gfs2_sbd sbd, *sdp = &sbd; int rindex_fd; int error = EXIT_SUCCESS; int devflags = (test ? O_RDONLY : O_RDWR) | O_CLOEXEC; setlocale(LC_ALL, ""); textdomain("gfs2-utils"); srandom(time(NULL) ^ getpid()); memset(sdp, 0, sizeof(struct gfs2_sbd)); sdp->bsize = GFS2_DEFAULT_BSIZE; sdp->rgsize = -1; sdp->jsize = GFS2_DEFAULT_JSIZE; sdp->qcsize = GFS2_DEFAULT_QCSIZE; sdp->md.journals = 1; decode_arguments(argc, argv, sdp); for(; (argc - optind) > 0; optind++) { struct metafs mfs = {0}; struct mntent *mnt; unsigned rgcount; unsigned old_rg_count; lgfs2_rgrps_t rgs; error = lgfs2_open_mnt(argv[optind], O_RDONLY|O_CLOEXEC, &sdp->path_fd, devflags, &sdp->device_fd, &mnt); if (error != 0) { fprintf(stderr, _("Error looking up mount '%s': %s\n"), argv[optind], strerror(errno)); exit(EXIT_FAILURE); } if (mnt == NULL) { fprintf(stderr, _("%s: not a mounted gfs2 file system\n"), argv[optind]); continue; } if (lgfs2_get_dev_info(sdp->device_fd, &sdp->dinfo) < 0) { perror(mnt->mnt_fsname); exit(EXIT_FAILURE); } sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE; sdp->bsize = sdp->sd_sb.sb_bsize; if (compute_constants(sdp)) { log_crit("%s\n", _("Failed to compute file system constants")); exit(EXIT_FAILURE); } if (read_sb(sdp) < 0) { fprintf(stderr, _("Error reading superblock.\n")); exit(EXIT_FAILURE); } if (sdp->gfs1) { fprintf(stderr, _("cannot grow gfs1 filesystem\n")); exit(EXIT_FAILURE); } fix_device_geometry(sdp); mfs.context = copy_context_opt(mnt); if (mount_gfs2_meta(&mfs, mnt->mnt_dir, (print_level > MSG_NOTICE))) { perror(_("Failed to mount GFS2 meta file system")); exit(EXIT_FAILURE); } rindex_fd = open_rindex(mfs.path, (test ? O_RDONLY : O_RDWR)); if (rindex_fd < 0) { cleanup_metafs(&mfs); exit(EXIT_FAILURE); } /* Get master dinode */ sdp->master_dir = lgfs2_inode_read(sdp, sdp->sd_sb.sb_master_dir.no_addr); if (sdp->master_dir == NULL) { perror(_("Could not read master directory")); exit(EXIT_FAILURE); } rgs = rgrps_init(sdp); if (rgs == NULL) { perror(_("Could not initialise resource groups")); error = -1; goto out; } /* Fetch the rindex from disk. We aren't using gfs2 here, */ /* which means that the bitmaps will most likely be cached */ /* and therefore out of date. It shouldn't matter because */ /* we're only going to write out new RG information after */ /* the existing RGs, and only write to the index at EOF. */ log_info(_("Gathering resource group information for %s\n"), argv[optind]); old_rg_count = lgfs2_rindex_read_fd(rindex_fd, rgs); if (old_rg_count == 0) { perror(_("Failed to scan existing resource groups")); error = -EXIT_FAILURE; goto out; } if (metafs_interrupted) goto out; fssize = lgfs2_rgrp_align_addr(rgs, filesystem_size(rgs) + 1); /* We're done with the old rgs now that we have the fssize and rg count */ lgfs2_rgrps_free(&rgs); /* Now lets set up the new ones with alignment and all */ rgs = rgrps_init(sdp); if (rgs == NULL) { perror(_("Could not initialise new resource groups")); error = -1; goto out; } fsgrowth = (sdp->device.length - fssize); rgcount = lgfs2_rgrps_plan(rgs, fsgrowth, ((GFS2_MAX_RGSIZE << 20) / sdp->bsize)); if (rgcount == 0) { log_err( _("The calculated resource group size is too small.\n")); log_err( _("%s has not grown.\n"), argv[optind]); error = -1; goto out; } print_info(sdp, mnt->mnt_fsname, mnt->mnt_dir); rgcount = initialize_new_portion(sdp, rgs); if (rgcount == 0 || metafs_interrupted) goto out; fsync(sdp->device_fd); fix_rindex(rindex_fd, rgs, old_rg_count, rgcount); out: lgfs2_rgrps_free(&rgs); close(rindex_fd); cleanup_metafs(&mfs); close(sdp->device_fd); if (metafs_interrupted) break; } close(sdp->path_fd); sync(); if (metafs_interrupted) { log_notice( _("gfs2_grow interrupted.\n")); exit(1); } log_notice( _("gfs2_grow complete.\n")); return error; }