/****************************************************************** * NAME: OpenFilSys * * FUNCTION: Read the superblock into a buffer. * Extract various pieces of information. * Release the buffer. * * PARAMETERS: none * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 OpenFilSys( void ) { int32 rc; struct superblock *sb; buf_t *bp; /* * validate and retrieve fs parameters from superblock */ /* try to read the primary superblock */ rc = bRawRead(LVHandle, (int64)SUPER1_OFF, (int32)PAGESIZE, &bp); if (rc != 0) { /* try to read the secondary superblock */ rc = bRawRead(LVHandle, (int64)SUPER2_OFF, (int32)PAGESIZE, &bp); if (rc != 0) { #ifdef _JFS_DEBUG printf("OpenFilSys: i/o error: rc=%d\n", rc); #endif return CBBL_CANTREADSBLKS; } } sb = (struct superblock *)bp->b_data; /* check magic/version number */ if (strncmp(sb->s_magic,JFS_MAGIC,(unsigned)strlen(JFS_MAGIC)) || (sb->s_version != JFS_VERSION)) { return CBBL_INVALMAGORVERS; } if (sb->s_state & FM_DIRTY) { return CBBL_FSDIRTY; } fsMount->bsize = sb->s_bsize; fsMount->l2bsize = sb->s_l2bsize; fsMount->l2bfactor = sb->s_l2bfactor; fsMount->nbperpage = PAGESIZE >> fsMount->l2bsize; fsMount->l2nbperpage = log2shift(fsMount->nbperpage); fsMount->FSSize = sb->s_size >> sb->s_l2bfactor; fsMount->AGSize = sb->s_agsize; #ifdef _JFS_DEBUG printf("superblock: attribute:0x%08x state:0x%08x\n", sb->s_flag, sb->s_state); printf("superblock: bsize:%d FSSize:%lld\n", fsMount->bsize, fsMount->FSSize); #endif agg_recptr->fs_blksize = sb->s_bsize; /* aggregate block size */ agg_recptr->lv_blksize = sb->s_pbsize; /* device block size */ agg_recptr->fs_lv_ratio = sb->s_bsize / sb->s_pbsize; agg_recptr->fs_last_metablk = addressPXD( &sb->s_aim2 ) + lengthPXD( &sb->s_aim2); agg_recptr->fs_first_wspblk = addressPXD( &sb->s_fsckpxd ); bRelease(bp); return rc; } /* end OpenFilSys() */
static int jfs_open(struct inode *inode, struct file *file) { int rc; if ((rc = dquot_file_open(inode, file))) return rc; /* * We attempt to allow only one "active" file open per aggregate * group. Otherwise, appending to files in parallel can cause * fragmentation within the files. * * If the file is empty, it was probably just created and going * to be written to. If it has a size, we'll hold off until the * file is actually grown. */ if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE && (inode->i_size == 0)) { struct jfs_inode_info *ji = JFS_IP(inode); spin_lock_irq(&ji->ag_lock); if (ji->active_ag == -1) { struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb); ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb); atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]); } spin_unlock_irq(&ji->ag_lock); } return 0; }
void display_xtpage(xtpage_t *xtree) { char flag_names[64]; *flag_names = 0; if (xtree->header.flag & BT_ROOT) strcat(flag_names, "BT_ROOT "); if (xtree->header.flag & BT_LEAF) strcat(flag_names, "BT_LEAF "); if (xtree->header.flag & BT_INTERNAL) strcat(flag_names, "BT_INTERNAL "); if (xtree->header.flag & BT_RIGHTMOST) strcat(flag_names, "BT_RIGHTMOST "); if (xtree->header.flag & BT_LEFTMOST) strcat(flag_names, "BT_LEFTMOST "); printf("[1] flag\t0x%02x\t%s\n", xtree->header.flag, flag_names); printf("[2] nextindex\t%d\t\t", xtree->header.nextindex); printf("[5] self.addr1\t0x%02x\n", xtree->header.self.addr1); printf("[3] maxentry\t%d\t\t", xtree->header.maxentry); printf("[6] self.addr2\t0x%08x\n", xtree->header.self.addr2); printf("[4] self.len\t0x%06x\t", xtree->header.self.len); printf(" self.addr\t%lld\n", addressPXD(&xtree->header.self)); } /* end display_xtpage */
int sba_jfs_find_journal_entries(void) { char *data; if ((data = read_block(JFS_SUPER)) != NULL) { int i; struct jfs_superblock *jfs_sb = (struct jfs_superblock *)data; sba_debug(1, "magic number = %s\n", jfs_sb->s_magic); sba_debug(1, "block size = %d\n", jfs_sb->s_bsize); jfs_jour_start = addressPXD(&jfs_sb->s_logpxd); jfs_jour_size = lengthPXD(&jfs_sb->s_logpxd); sba_debug(1, "log address = %d\n", jfs_jour_start); sba_debug(1, "log size = %d\n", jfs_jour_size); for (i = 0; i < jfs_jour_size; i ++) { ht_add(h_sba_jfs_journal, i+jfs_jour_start); } sba_debug(1, "Added log blocks from %d to %d\n", jfs_jour_start, jfs_jour_start + jfs_jour_size - 1); free_page((int)data); } return 1; }
void walk_dtree( int device, uint64 block, uint32 length, int64 *total_nblocks) { int rc; dtpage_t dtree_buffer; uint8 *stbl; idtentry_t *cur_entry; uint64 first_block, cur_block, last_block; uint32 cur_length; int32 lastindex, index; int32 thisindex; /* * Read the page from disk */ rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize, length << sb.s_l2bsize, &dtree_buffer, GET ); if( dtree_buffer.header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Mark blocks for each entry and visit that page */ lastindex = dtree_buffer.header.nextindex; stbl = (uint8 *)&(dtree_buffer.slot[dtree_buffer.header.stblindex]); for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ thisindex = stbl[index]; cur_entry = (idtentry_t *)&(dtree_buffer.slot[thisindex]); first_block = addressPXD( &(cur_entry->xd) ); cur_length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += cur_length; last_block = first_block + cur_length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, cur_length, total_nblocks); } }
char display_internal_slots( dtslot_t *slot, int8 *stbl, int8 nextindex, int32 *changed) { int32 i; idtentry_t *entry; int64 node_address; char result; int32 slot_number; for (i = 0; i < nextindex; i++) { slot_number = stbl[i]; entry = (idtentry_t *)&(slot[slot_number]); node_address = addressPXD(&(entry->xd)); printf("stbl[%d] = %d\n", i, slot_number); printf("[1] xd.len\t 0x%06x\t\t", entry->xd.len); printf("[4] next\t%d\n", entry->next); printf("[2] xd.addr1\t 0x%02x\t\t\t", entry->xd.addr1); printf("[5] namlen\t%d\n", entry->namlen); printf("[3] xd.addr2\t 0x%08x\t\t", entry->xd.addr2); printf(" xd.addr\t%lld\n", node_address); #ifdef _JFS_UNICODE printf("[6] name\t%.11ls\n", entry->name); #else printf("[6] name\t%.22s\n", entry->name); #endif printf("addressPXD(xd)\t%lld\n", node_address); result = prompt("dtree: press enter for next or [u]p, [d]own or e[x]it > "); if (result == 'x' || result == 'u' ) return result; else if (result != 'd' && entry->next >= 0) { result = display_slot(slot, entry->next, 0, changed); if (result == 'x' || result == 'u' ) return result; } if (result == 'd') /* descend to the child node */ return(display_extent_page(node_address)); } return result; }
void walk_dir( int device, dtroot_t *root_header, int64 *total_nblocks) { int32 index, lastindex; uint64 first_block, cur_block, last_block; idtentry_t *cur_entry; uint32 length; if( root_header->header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Have root of directory inode btree. * Walk tree marking all blocks allocated. */ lastindex = root_header->header.nextindex; for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ cur_entry = (idtentry_t *)&(root_header->slot[root_header->header.stbl[index]]); first_block = addressPXD( &(cur_entry->xd) ); length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += length; last_block = first_block + length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, length, total_nblocks); } }
/* * 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; }
void directory() { char cmd_line[80]; dtpage_t dtree; int32 i; dinode_t inode; int64 inode_address; ino_t inum; int64 node_address; idtentry_t *node_entry; dtroot_t *root; dtslot_t *slot; uint8 *stbl; char *token; ino_t which_table = FILESYSTEM_I; token = strtok(0, " "); if (token == 0) { fputs("directory: Please enter: inum [fileset]\ndirectory> ", stdout); gets(cmd_line); token=strtok(cmd_line, " "); if (token == 0) return; } errno = 0; inum = strtoul(token, 0, 0); if (inum == 0 && errno) { fputs("directory: invalid inum\n\n", stderr); return; } token = strtok(0, " "); if (token) { if (token[0] != '0') { fputs("directory: invalid fileset\n\n", stderr); return; } } if (strtok(0, " ")) { fputs("directory: Too many arguments\n\n", stderr); return; } if (find_inode(inum, which_table, &inode_address) || xRead(inode_address, sizeof(dinode_t), (char *)&inode)) { fputs("directory: error reading inode\n\n", stderr); return; } if ((inode.di_mode & IFMT) != IFDIR) { fputs("directory: Not a directory!\n", stderr); return; } root = (dtroot_t *)&(inode.di_btroot); printf("idotdot = %d\n\n", root->header.idotdot); if (root->header.flag & BT_LEAF) { if (root->header.nextindex == 0) { fputs("Empty directory.\n", stdout); return; } for (i = 0; i < root->header.nextindex; i++) { print_direntry(root->slot, root->header.stbl[i]); } return; } /* Root is not a leaf node, we must descend to the leftmost leaf */ node_entry = (idtentry_t *)&(root->slot[root->header.stbl[0]]); descend: node_address = addressPXD(&(node_entry->xd)) << l2bsize; if (xRead(node_address, sizeof(dtpage_t), (char *)&dtree)) { fputs("Directory: Error reading dtree node\n", stderr); return; } stbl = (uint8 *)&(dtree.slot[dtree.header.stblindex]); if (!(dtree.header.flag & BT_LEAF)) { node_entry = (idtentry_t *)&(dtree.slot[stbl[0]]); goto descend; } /* dtree (contained in node) is the left-most leaf node */ next_leaf: for (i = 0; i < dtree.header.nextindex; i++) { print_direntry(dtree.slot, stbl[i]); } if (dtree.header.next) { if (xRead(dtree.header.next << l2bsize, sizeof(dtpage_t), (char *)&dtree)) { fputs("directory: Error reading leaf node\n", stderr); return; } stbl = (uint8 *)&(dtree.slot[dtree.header.stblindex]); goto next_leaf; } return; }
int32 display_super2( struct superblock *sb) { char *aix_platform; char *os2_platform; char cmdline[512]; int32 field; char *dir_posix; char *dir_unicode; int32 rc = XPEEK_OK; char *state; char *token; char *commit; char *groupcommit; char *lazycommit; char *tmpfs; char *inlinelog; char *inlinemove; char *badsait; char *sparse; /* @F1 */ char *dasdenabled; /* @F1 */ char *dasdprime; /* @F1 */ changed: switch (sb->s_state) { case FM_CLEAN: state="CLEAN"; break; case FM_MOUNT: state="MOUNT"; break; case FM_DIRTY: state="DIRTY"; break; case FM_LOGREDO: state="LOGREDO"; break; default: state="Unknown State"; break; } if (sb->s_flag & JFS_AIX) aix_platform="AIX"; else aix_platform=" "; if (sb->s_flag & JFS_OS2) os2_platform="OS2"; else os2_platform=" "; if (sb->s_flag & JFS_DFS) dir_posix="DFS"; else dir_posix=" "; if (sb->s_flag & JFS_UNICODE) dir_unicode="UNICODE"; else dir_unicode=" "; if (sb->s_flag & JFS_GROUPCOMMIT) groupcommit="GROUPCOMMIT"; else groupcommit=" "; if (sb->s_flag & JFS_LAZYCOMMIT) lazycommit="LAZYCOMMIT"; else lazycommit=" "; if (sb->s_flag & JFS_TMPFS) tmpfs="TMPFS"; else tmpfs=" "; if (sb->s_flag & JFS_INLINELOG) inlinelog="INLINELOG"; else inlinelog=" "; if (sb->s_flag & JFS_INLINEMOVE) inlinemove="INLINEMOVE"; else inlinemove=" "; if (sb->s_flag & JFS_BAD_SAIT) badsait="BAD_SAIT"; else badsait=" "; if (sb->s_flag & JFS_SPARSE) /* @F1 */ sparse="SPARSE"; /* @F1 */ else /* @F1 */ sparse=" "; /* @F1 */ if (sb->s_flag & JFS_DASD_ENABLED) /* @F1 */ dasdenabled="DASD_ENABLED"; /* @F1 */ else /* @F1 */ dasdenabled=" "; /* @F1 */ if (sb->s_flag & JFS_DASD_PRIME) /* @F1 */ dasdprime="DASD_PRIME"; /* @F1 */ else /* @F1 */ dasdprime=" "; /* @F1 */ printf("[1] s_magic:\t\t'%4.4s'\t\t", &(sb->s_magic)); printf("[16] s_aim2.len:\t%d\n", sb->s_aim2.len); printf("[2] s_version:\t\t%d\t\t", sb->s_version); printf("[17] s_aim2.addr1:\t0x%02x\n", sb->s_aim2.addr1); printf("[3] s_size:\t0x%016llx\t", sb->s_size); printf("[18] s_aim2.addr2:\t0x%08x\n", sb->s_aim2.addr2); printf("[4] s_bsize:\t\t%d\t\t", sb->s_bsize); printf(" s_aim2.address:\t%lld\n", addressPXD(&sb->s_aim2)); printf("[5] s_l2bsize:\t\t%d\t\t", sb->s_l2bsize); printf("[19] s_logdev:\t\t0x%08x\n", sb->s_logdev); printf("[6] s_l2bfactor:\t%d\t\t", sb->s_l2bfactor); printf("[20] s_logserial:\t0x%08x\n", sb->s_logserial); printf("[7] s_pbsize:\t\t%d\t\t", sb->s_pbsize); printf("[21] s_logpxd.len:\t%d\n", sb->s_logpxd.len); printf("[8] s_l2pbsize:\t\t%d\t\t", sb->s_l2pbsize); printf("[22] s_logpxd.addr1:\t0x%02x\n", sb->s_logpxd.addr1); printf("[9] s_agsize:\t\t0x%08x\t", sb->s_agsize); printf("[23] s_logpxd.addr2:\t0x%08x\n", sb->s_logpxd.addr2); printf("[10] s_flag:\t\t0x%08x\t", sb->s_flag); printf(" s_logpxd.address:\t%lld\n", addressPXD(&sb->s_logpxd)); printf(" %s %s %s %s %s\t", aix_platform, os2_platform, dir_posix, dir_unicode, tmpfs ); /* @F1 */ printf("[24] s_fsckpxd.len:\t%d\n", sb->s_fsckpxd.len); printf(" %s %s %s\t", groupcommit, lazycommit, badsait ); /* @F1 */ printf("[25] s_fsckpxd.addr1:\t0x%02x\n", sb->s_fsckpxd.addr1); printf(" %s %s %s\t", sparse, inlinelog, inlinemove ); /* @F1 */ printf("[26] s_fsckpxd.addr2:\t0x%08x\n", sb->s_fsckpxd.addr2); printf(" %s %s\t\t", dasdenabled, dasdprime); /* @F1 */ printf(" s_fsckpxd.address:\t%lld\n", addressPXD(&sb->s_fsckpxd)); printf("[11] s_state:\t\t0x%08x\t", sb->s_state); printf("[27] s_fsckloglen:\t%ld\t\n", sb->s_fsckloglen); printf("\t%13s\t\t\t", state); printf("[28] s_fscklog:\t\t%d\t\n", sb->s_fscklog); printf("[12] s_compress:\t%d\t\t",sb->s_compress); printf("[29] s_fpack:\t\t'%8s'\n", &(sb->s_fpack)); printf("[13] s_ait2.len:\t%d\t\t", sb->s_ait2.len); printf("[30] s_attach:\t\t%1d\n", sb->s_attach); printf("[14] s_ait2.addr1:\t0x%02x\t\t", sb->s_ait2.addr1); printf("[31] totalUsable: 0x%016llx\n", sb->totalUsable); printf("[15] s_ait2.addr2:\t0x%08x\t", sb->s_ait2.addr2); printf("[32] minFree:\t 0x%016llx\n", sb->minFree); printf(" s_ait2.address:\t%lld\t\t", addressPXD(&sb->s_ait2)); printf("[33] realFree:\t 0x%016llx\n", sb->realFree); retry: fputs("display_super: [m]odify or e[x]it: ", stdout); gets(cmdline); token = strtok(cmdline, " "); if (token == 0 || token[0] != 'm') return rc; field = m_parse(cmdline, 33, &token); if (field == 0) goto retry; switch (field) { case 1: strncpy(sb->s_magic, token, 4); break; case 2: sb->s_version = strtoul(token, 0, 0); break; case 3: sb->s_size = strtoll(token, 0, 16); break; case 4: sb->s_bsize = strtol(token, 0, 0); break; case 5: sb->s_l2bsize = strtol(token, 0, 0); break; case 6: sb->s_l2bfactor = strtol(token, 0, 0); break; case 7: sb->s_pbsize = strtol(token, 0, 0); break; case 8: sb->s_l2pbsize = strtol(token, 0, 0); break; case 9: sb->s_agsize = strtoul(token, 0, 16); break; case 10: sb->s_flag = strtoul(token, 0, 16); break; case 11: sb->s_state = strtoul(token, 0, 16); break; case 12: sb->s_compress = strtoul(token, 0, 0); break; case 13: sb->s_ait2.len = strtoul(token, 0, 0); break; case 14: sb->s_ait2.addr1 = strtoul(token, 0, 16); break; case 15: sb->s_ait2.addr2 = strtoul(token, 0, 16); break; case 16: sb->s_aim2.len = strtoul(token, 0, 0); break; case 17: sb->s_aim2.addr1 = strtoul(token, 0, 16); break; case 18: sb->s_aim2.addr2 = strtoul(token, 0, 16); break; case 19: sb->s_logdev = strtoul(token, 0, 16); break; case 20: sb->s_logserial = strtol(token, 0, 16); break; case 21: sb->s_logpxd.len = strtoul(token, 0, 0); break; case 22: sb->s_logpxd.addr1 = strtoul(token, 0, 16); break; case 23: sb->s_logpxd.addr2 = strtoul(token, 0, 16); break; case 24: sb->s_fsckpxd.len = strtoul(token, 0, 0); break; case 25: sb->s_fsckpxd.addr1 = strtoul(token, 0, 16); break; case 26: sb->s_fsckpxd.addr2 = strtoul(token, 0, 16); break; case 27: sb->s_fsckloglen = strtol(token, 0, 0); break; case 28: sb->s_fscklog = strtol(token, 0, 0); break; case 29: strncpy(sb->s_fpack, token, 8); break; case 30: sb->s_attach = strtol(token, 0, 0); break; case 31: sb->totalUsable = strtoull(token, 0, 16); break; case 32: sb->minFree = strtoull(token, 0, 16); break; case 33: sb->realFree = strtoull(token, 0, 16); break; default: fputs("display_super: Field number out of range\n", stderr); goto retry; } rc = XPEEK_CHANGED; goto changed; }
/**************************************************************************** * NAME: process_Inode_Dtree * * FUNCTION: Traverse the dtree of the given directory inode * looking for allocated extents containing bad blocks. * * PARAMETERS: * dip ptr to the owning disk inode in a buffer * * doRelocate 0 => this is not the JFS Bad Block inode * !0 => this is the JFS Bad Block inode * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 process_Inode_Dtree( dinode_t *dip, int8 doRelocate ) { int32 pid_rc = 0; int32 relocate_rc = 0; dtpage_t *p; int8 *stbl; int32 i; pxd_t *pxd; int64 xaddr, lmxaddr, xlastblk; int32 xlen; int8 didRelocate = 0; cbbl_bdblk_recptr bdblk_recptr = NULL; int32 pList; ULONG pListLen = 0; clrbblks_t pData; ULONG pDataLen = 0; int64 lmpg_addr; int32 lmxlen; dtpage_t next_dtpg; /* next dtpage to work on */ dtpage_t *pnext_dtpg; int32 ndtpg_inx; /* the next index in next_dtpg to work on */ /* * we start with the root */ pnext_dtpg = p = (dtpage_t *)&dip->di_btroot; /* * is it leaf, i.e., inode inline data ? */ if (p->header.flag & BT_LEAF) { goto out; } p->header.next = 0; /* * save leftmost dtpage xaddr */ lmpg_addr = 0; stbl = DT_GETSTBL(p); pxd = (pxd_t *)&p->slot[stbl[0]]; /* * save leftmost child dtpage extent */ lmxaddr = addressPXD(pxd); /* leftmost child xaddr */ lmxlen = lengthPXD(pxd); ndtpg_inx = 0; /* * scan each level of dtree */ while(1) { /* * scan each dtpage of current level of dtree */ while(1) { stbl = DT_GETSTBL(p); /* * scan each idtentry in current dtpage */ for (i = ndtpg_inx; i < p->header.nextindex; i++) { pxd = (pxd_t *)&p->slot[stbl[i]]; /* * does the extent contain at least 1 * bad block? */ xaddr = addressPXD(pxd); xlen = lengthPXD(pxd); pid_rc = baltree_search( xaddr, &bdblk_recptr ); if( pid_rc != 0 ) { /* something fatal on search */ return( pid_rc ); } else if( bdblk_recptr == NULL ) { /* hit end of tree w/o match */ continue; } /* end hit end of tree w/o match */ xlastblk = xaddr + xlen - 1; if( bdblk_recptr->fs_blkno <= xlastblk ) { /* * the extent contains at least 1 bad block */ #ifdef _JFS_DEBUG printf("bad block 0x0%llx found in dtree for inode %d\n", bdblk_recptr->fs_blkno, dip->di_number ); #endif if( !doRelocate ) { /* relocation not requested */ pid_rc = we_DidntTryTo_Relocate( xaddr, xlastblk, bdblk_recptr ); } /* end relocation not requested */ else { /* relocation is requested */ pDataLen = sizeof(clrbblks_t); pData.flag = CLRBBLKS_RELOCATE | IFDIR | DTPAGE; //PS24072004 pData.dev = lvMount->LVNumber; pData.dev = LVNumber; pData.fileset = dip->di_fileset; pData.inostamp = dip->di_inostamp; pData.ino = dip->di_number; pData.gen = dip->di_gen; pData.xoff = lmpg_addr; /* leftmost page * describing this level */ pData.old_xaddr = xaddr; pData.new_xaddr = 0; pData.xlen = xlen; pData.agg_blksize = agg_recptr->fs_blksize; /* * attempt to relocate the extent */ didRelocate = 0; relocate_rc = fscntl( JFSCTL_CLRBBLKS, (void *)&pList, &pListLen, (void *)&pData, &pDataLen ); if( (relocate_rc == 0) && (pData.new_xaddr != 0) ) { /* * extent has been relocated */ didRelocate = -1; } /* end extent has been relocated */ /* * Now handle the individual bad block(s) * in the extent */ if( didRelocate ) { /* * actually did relocate */ pid_rc = we_Did_Relocate( xaddr, xlastblk, bdblk_recptr ); } /* end actually did relocate */ else { /* tried but failed to relocate */ pid_rc = we_Couldnt_Relocate( xaddr, xlastblk, bdblk_recptr, relocate_rc ); } /* end else tried but failed to relocate */ } /* end else relocation is requested */ } /* end the extent contains at least 1 bad block */ } /* end for loop */ /* * read in next/right sibling dtpage */ if (p->header.next != 0) { xaddr = p->header.next; pid_rc = pRead(fsMount, xaddr, fsMount->nbperpage, &next_dtpg); if (pid_rc != 0) { return CBBL_CANTREADNEXTDTPG; /* i/o error */ } pnext_dtpg = p = &next_dtpg; ndtpg_inx = 0; } else break; } /* end while current level scan */ /* * descend: read leftmost dtpage of next lower level of dtree */ /* * the first child of the dtroot split may not have PSIZE */ pid_rc = pRead(fsMount, lmxaddr, lmxlen, &next_dtpg); if ( pid_rc != 0 ) { return CBBL_CANTREADLMDTCHILD; /* i/o error */ } pnext_dtpg = p = &next_dtpg; /* * for dir, the leaf contains data, its pxd info * has been reported by the parent page. so we stop here */ if (p->header.flag & BT_LEAF) { break; } /* * save leftmost dtpage xaddr */ lmpg_addr = lmxaddr; stbl = DT_GETSTBL(p); pxd = (pxd_t *)&p->slot[stbl[0]]; /* * save leftmost child dtpage extent */ lmxaddr = addressPXD(pxd); /* leftmost child xaddr */ lmxlen = lengthPXD(pxd); ndtpg_inx = 0; } /* end while scan each level of tree */ /* reset global state variable for the inode */ out: pnext_dtpg = NULL; return pid_rc; } /* end process_Inode_Dtree() */
/**************************************************************************** * NAME: process_FilesetInodes * * FUNCTION: Reads in the fileset inode extents, one by one, and for * each in-use inode, calls process_Inode() to scan for * blocks on the bad block list and handle any that are * detected. * * PARAMETERS: none * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 process_FilesetInodes ( ) { int32 pfsi_rc = 0; dinode_t *inoptr = NULL; dinomap_t *icp; int64 xaddr; int32 xlen; int8 isBadBlockInode = 0; /* * scan each IAG in the file set */ icp = (dinomap_t *)&IMap.ctl; for ( agg_recptr->iag_idx = 0; ( (agg_recptr->iag_idx < icp->in_nextiag) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->iag_idx++) { /* for each IAG */ /* * read in the next IAG */ pfsi_rc = readIMapSequential(&iagbuf); /* * process the extents described by the IAG */ for ( agg_recptr->extent_idx = 0; ( (agg_recptr->extent_idx < EXTSPERIAG) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->extent_idx++) { /* for each extent in the IAG */ /* * Get the address and length of the extent */ xaddr = addressPXD(&iagbuf.inoext[agg_recptr->extent_idx]); xlen = lengthPXD(&iagbuf.inoext[agg_recptr->extent_idx]); /* * If the extent isn't allocated, bump current inode number */ if( xaddr == 0 ) { /* not allocated */ agg_recptr->this_inonum += INOSPEREXT; } else { /* extent is allocated */ /* * Otherwise, read in the inode extent */ pfsi_rc = pRead(fsMount, xaddr, xlen, (void *)ixbuf); /* * process the inodes in the extent */ for ( agg_recptr->inode_idx = 0; ( (agg_recptr->inode_idx < INOSPEREXT) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->inode_idx++) { /* * for each inode in the extent */ inoptr = &ixbuf[agg_recptr->inode_idx]; /* * if the inode isn't in use, just * increment the inode number */ if( (inoptr->di_nlink == 0) || (inoptr->di_inostamp != DIIMap.di_inostamp) ) { agg_recptr->this_inonum += 1; } /* * otherwise, scan the inode for bad blocks * allocated to it and, if possible, relocate * their contents and get them transferred to * the JFS Bad Block Inode */ else { /* the inode is in use */ pfsi_rc = process_Inode( isBadBlockInode, inoptr ); /* * increment to the next inode */ agg_recptr->this_inonum += 1; } /* end else the inode is in use */ } /* end for each inode in the extent */ } /* end else extent is allocated */ } /* end for each extent in the IAG */ } /* end for each IAG */ return( pfsi_rc ); } /* end process_FilesetInodes() */
/* look at jfs_logredo() and logRead() from logredo in jfsutils */ int sba_jfs_handle_journal_block(int sector, char *data) { int off; int ret; struct logpage *lp; struct lrd *ld; char *log_data_ptr; void *ptr; int ld_flag; int nwords; int type = JOURNAL_DATA_BLOCK; if (sba_jfs_journal_super_block(sector)) { return JOURNAL_SUPER_BLOCK; } /* each log page that is written is of the form "struct logpage" */ lp = (struct logpage *)data; off = lp->h.eor & (LOGPSIZE - 1); sba_debug(0, "The end of log offset of last record write = %d (h), %d (t)\n", lp->h.eor, lp->t.eor); sba_debug(0, "offset is %d head %u tail %u\n", off, (unsigned int)&(lp->h), (unsigned int)&(lp->t)); ld = kmalloc(sizeof(struct logpage), GFP_KERNEL); log_data_ptr = kmalloc(4096, GFP_KERNEL); nwords = LOGRDSIZE/4; ret = sba_jfs_get_next_log_record(nwords, (int *)ld, data, &off); ld_flag = 1; while (ret >= 0) { if (ld_flag) { sba_debug(0, "Length = %d , Backchain = %d\n", ld->length, ld->backchain); long long blocknr = -1; switch (ld->type) { case LOG_COMMIT: sba_debug(0, "Found a LOG_COMMIT record\n"); type = JOURNAL_COMMIT_BLOCK; break; case LOG_MOUNT: sba_debug(0, "Found a LOG_MOUNT record\n"); break; case LOG_SYNCPT: sba_debug(0, "Found a LOG_SYNCPT record\n"); break; case LOG_REDOPAGE: sba_debug(0, "Found a LOG_REDOPAGE record (address %lld, length %d)\n", addressPXD(&ld->log.redopage.pxd), lengthPXD(&ld->log.redopage.pxd)); blocknr = addressPXD(&ld->log.redopage.pxd); break; case LOG_NOREDOPAGE: sba_debug(0, "Found a LOG_NOREDOPAGE record (address %lld length %d)\n", addressPXD(&ld->log.noredopage.pxd), lengthPXD(&ld->log.noredopage.pxd)); blocknr = addressPXD(&ld->log.noredopage.pxd); break; case LOG_NOREDOINOEXT: sba_debug(0, "Found a LOG_NOREDOINOEXT record (address %lld length %d)\n", addressPXD(&ld->log.noredoinoext.pxd), lengthPXD(&ld->log.noredoinoext.pxd)); blocknr = addressPXD(&ld->log.noredoinoext.pxd); break; case LOG_UPDATEMAP: sba_debug(0, "Found a LOG_UPDATEMAP record (address %lld length %d nxd %d)\n", addressPXD(&ld->log.updatemap.pxd), lengthPXD(&ld->log.updatemap.pxd), ld->log.updatemap.nxd); blocknr = addressPXD(&ld->log.updatemap.pxd); break; default: sba_debug(1, "Found an UNKNOWN record\n"); break; } if (blocknr != -1) { if (sba_jfs_insert_journaled_blocks(blocknr) == -1) { sba_debug(1, "Error: inserting blk=%lld into journaled blocks list\n", blocknr); } } sba_debug(0, "Next offset = %d\n", off); } else { sba_debug(0, "Skipping data = %d words\n", nwords); } if (ld_flag) { if (ld->length > 0) { nwords = (ld->length + 3) / 4; ptr = log_data_ptr; ld_flag = 0; } else { nwords = LOGRDSIZE/4; ptr = ld; ld_flag = 1; } } else { nwords = LOGRDSIZE/4; ptr = ld; ld_flag = 1; } ret = sba_jfs_get_next_log_record(nwords, (int *)ptr, data, &off); } return type; }
int32 validfs( HFILE device ) { uint64 num_log_blocks; int32 rc; uint64 first_block, last_block; uint32 length, inode_address; uint64 index; struct dinode inode_buffer; int64 total_nblocks; /* * Initialize internal block map */ num_log_blocks = sb.s_size >> sb.s_l2bfactor; rc = calc_map_size( num_log_blocks, sb.s_bsize, sb.s_agsize ); if( rc != 0 ) { printf("Failure creating internal block map.\n"); } /* * Mark fixed items allocated; these are only the items which aren't mapped * by one of the inode tables. */ /* * Reserved blocks */ length = AGGR_RSVD_BYTES >> sb.s_l2bsize; first_block = 0; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Primary superblock */ length = SIZE_OF_SUPER >> sb.s_l2bsize; first_block = SUPER1_OFF >> sb.s_l2bsize; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Secondary superblock */ first_block = SUPER2_OFF >> sb.s_l2bsize; last_block = first_block + length; for( index = first_block; index < last_block; index++ ) { markit( index, 0 ); } /* * Walk aggregate inode table; marking blocks seen */ rc = ujfs_rwinode( device, &inode_buffer, AGGREGATE_I, GET, sb.s_bsize, AGGREGATE_I ); if( rc != 0 ) return(rc); rc = walk_ait( device, &inode_buffer, TRUE ); if( rc != 0 ) { printf( "Failed walking aggregate inode table, or difference in inode maps.\n"); } /* * Walk secondary aggregate inode table; marking blocks seen */ inode_address = (AGGREGATE_I * sizeof(struct dinode)) + ( addressPXD(&(sb.s_ait2)) << sb.s_l2bsize ); rc = ujfs_rw_diskblocks( device, inode_address, sizeof(struct dinode), &inode_buffer, GET ); if( rc != 0 ) return(rc); rc = walk_ait( device, &inode_buffer, FALSE ); if( rc != 0 ) { printf( "Failed walking secondary inode table, or difference in inode maps.\n"); } /* * Since we don't walk the inodes of the secondary inode table we need to * be sure and mark the blocks for the map's addressing structure */ total_nblocks = 0; walk_inode_tree(device, (xtpage_t *)&inode_buffer.di_btroot, &total_nblocks, 0); if( inode_buffer.di_nblocks != total_nblocks ) { error++; printf( "Secondary AIT Inode %d (fileset: %d) nblocks bad, disk: %lld, actual: %lld\n", inode_buffer.di_number, inode_buffer.di_fileset, inode_buffer.di_nblocks, total_nblocks); } /* * Now the bitmaps are marked, fill in the rest of the maps and compare * with the maps on disk */ rc = compare_maps( device, num_log_blocks, sb.s_bsize ); return(rc); }
/* * Read the specified extent as an extent of IAG's * If its offset is 0 skip the first page since this is a control page. * For all other IAGs need to mark blocks: * - mark the blocks for any allocated extents for the IAG * - read the extent and mark blocks for any allocated inodes * Note: the blocks owned by the table itself will be marked when the inode for * the table is seen. */ void walk_iag_extent( int device, xad_t *extent, boolean_t is_primary, dinomap_t *control_page, dinomap_t *disk_cp, struct list_item **top_iagfree, struct list_item **top_inofree, struct list_item **top_extfree, int32 inostamp ) { uint64 offset, address, count, end; uint32 length, page_length; iag_t iag_buffer; int32 index, rc, extdx; pxd_t *inoext_ptr; uint32 map, found_map; uint32 agno; ino_t start_inum; uint32 mymap[EXTSPERIAG]; int16 seen_extent = 0, free_inodes = 0; offset = offsetXAD( extent ); address = addressXAD( extent ); length = lengthXAD( extent ); page_length = PSIZE >> sb.s_l2bsize; if( offset == 0 ) { /* * Read in the disk control page now. We will compare it after all the * other pages of the map have been processed. */ rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize, sizeof(dinomap_t), disk_cp, GET ); if( rc != 0 ) exit(rc); address += page_length; length -= page_length; } while( length > 0 ) { /* * Clear map to use for tracking inodes seen */ memset( mymap, 0, EXTSPERIAG * sizeof(uint32)); /* * Read next IAG */ rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize, PSIZE, &iag_buffer, GET ); if( rc != 0 ) exit(rc); length -= page_length; address += page_length; control_page->in_nextiag = iag_buffer.iagnum + 1; if( iag_buffer.iagfree != -1 ) { /* * We have an item on the iagfree list following this one. */ rc = search_and_add(top_iagfree, iag_buffer.iagfree, DISK_LIST); if( rc != 0 ) { printf("Bad iagfree item on-disk: %d\n", iag_buffer.iagfree); } } agno = iag_buffer.agstart / sb.s_agsize; if( iag_buffer.extfreefwd != -1 ) { /* * We have an item on the extfree list following this one. */ rc = search_and_add(&(top_extfree[agno]), iag_buffer.extfreefwd, DISK_LIST); if( rc != 0 ) { printf("Bad extfree[%d] item on-disk: %d\n", agno, iag_buffer.extfreefwd); } } if( iag_buffer.inofreefwd != -1 ) { /* * We have an item on the inofree list following this one. */ rc = search_and_add(&(top_inofree[agno]), iag_buffer.inofreefwd, DISK_LIST); if( rc != 0 ) { printf("Bad inofree[%d] item on-disk: %d\n", agno, iag_buffer.inofreefwd); } } /* * Mark blocks for any allocated inode extents */ for( index = 0; index < SMAPSZ; index++ ) { map = iag_buffer.extsmap[index]; inoext_ptr = iag_buffer.inoext + (index * EXTSPERSUM); for( extdx = 0; extdx < EXTSPERSUM, map != 0; extdx++, map <<= 1) { if( (map & HIGHORDER) != 0 ) { seen_extent++; /* * Count inodes for allocated inode extents */ control_page->in_numinos += NUM_INODE_PER_EXTENT; control_page->in_agctl[agno].numinos += NUM_INODE_PER_EXTENT; address = count = addressPXD(inoext_ptr + extdx); end = count + inoext_ptr[extdx].len; for( ; count < end; count++) { markit( count, 0 ); } if( is_primary == TRUE ) { /* * Now need to read inodes and mark blocks for them * Only do this for the primary inode table */ start_inum = (iag_buffer.iagnum << L2INOSPERIAG) + (index << (L2EXTSPERSUM + L2INOSPEREXT)) + (extdx << L2INOSPEREXT); walk_inoext( device, address, inoext_ptr[extdx].len, iag_buffer.wmap[(index * EXTSPERSUM) + extdx], control_page, agno, start_inum, &found_map, inostamp ); mymap[(index * EXTSPERSUM) + extdx] = found_map; if( ~found_map != 0 ) free_inodes = 1; } } } } if( seen_extent == 0 ) { /* * No extents for this IAG, add it to iagfree list */ rc = search_and_add(top_iagfree, iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad iagfree item found: %d\n", iag_buffer.iagnum); } } else if( seen_extent != EXTSPERIAG ) { /* * Have free extents in this IAG, add to AG free extent list */ rc = search_and_add(&(top_extfree[agno]), iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad extfree[%d] item found: %d\n", agno, iag_buffer.iagnum); } } if( free_inodes != 0 ) { /* * We have some free inodes in the extent */ rc = search_and_add(&(top_inofree[agno]), iag_buffer.iagnum, FOUND_LIST); if( rc != 0 ) { printf("Bad inofree[%d] item found: %d\n", agno, iag_buffer.iagnum); } } if( is_primary ) { /* * Compare map found by walking extents to the on-disk version */ rc = memcmp( mymap, iag_buffer.wmap, EXTSPERIAG * sizeof(uint32)); if( rc != 0 ) { error++; printf("Miscompare of inode wmap of IAG %d.\n", iag_buffer.iagnum); print_uint_array ("Found map:", mymap, EXTSPERIAG); print_uint_array ("Disk wmap:", iag_buffer.wmap, EXTSPERIAG); } rc = memcmp( mymap, iag_buffer.pmap, EXTSPERIAG * sizeof(uint32)); if( rc != 0 ) { error++; printf("Miscompare of inode pmap of IAG %d.\n", iag_buffer.iagnum); print_uint_array ("Found map:", mymap, EXTSPERIAG); print_uint_array ("Disk pmap:", iag_buffer.pmap, EXTSPERIAG); } } } }
void walk_inoext( int device, uint64 address, uint32 length, uint32 wmap, dinomap_t *control_page, uint32 agno, ino_t start_inum, uint32 *found_map, int32 inostamp ) { dinode_t *next_inode; uint32 left_to_read = length << sb.s_l2bsize; uint64 cur_address = address << sb.s_l2bsize; int32 index, rc; uint32 map = wmap; char page_buffer[PSIZE]; ino_t cur_inum = start_inum; uint32 mask = HIGHORDER; uint64 first_block, cur_block, last_block; uint32 num_blocks; int64 total_nblocks; *found_map = 0; while( (left_to_read > 0) ) { /* * Read next page of inodes for this extent */ rc = ujfs_rw_diskblocks( device, cur_address, PSIZE, page_buffer, GET ); cur_address += PSIZE; left_to_read -= PSIZE; next_inode = (dinode_t *)page_buffer; for( index = 0; index < INOSPERPAGE; index++, next_inode++, cur_inum++, map <<= 1, mask >>= 1 ) { /* * Initialize count for this inode's number of blocks */ total_nblocks = 0; /* * If this inode is allocated, mark blocks for its b-tree */ if( (map & HIGHORDER) != 0 ) { if( next_inode->di_nlink <= 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); } else { *found_map |= mask; } /* * Account for any blocks used by EA for this inode */ if( next_inode->di_ea.flag & DXD_EXTENT ) { first_block = addressDXD(&(next_inode->di_ea)); num_blocks = lengthDXD(&(next_inode->di_ea)); total_nblocks += num_blocks; last_block = first_block + num_blocks; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } } if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == FILESYSTEM_I) ) { /* * Need to account for inode map's blocks */ walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); /* * Need to walk this tree of inodes */ rc = walk_ait( device, next_inode, TRUE ); if( rc != 0 ) { error++; printf("Problem with Fileset Inode Allocation Map.\n"); } } else if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == BADBLOCK_I) ) { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, BADBLOCK); } else if( next_inode->di_mode & IFDIR ) { /* * Need to walk the extents as directory extents */ walk_dir( device, (dtroot_t *)&(next_inode->di_btroot), &total_nblocks); } else { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); } /* * Now total_nblocks contains the total number of blocks * actually allocated for this inode. Compare this to the * on-disk information. */ if( next_inode->di_nblocks != total_nblocks ) { error++; printf( "Inode %d (fileset: %d) nblocks bad, disk: %lld, actual: %lld\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nblocks, total_nblocks); } } else { if( next_inode->di_number == cur_inum && next_inode->di_inostamp == inostamp && addressPXD(&(next_inode->di_ixpxd)) == address && lengthPXD(&(next_inode->di_ixpxd)) == length && next_inode->di_nlink > 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); *found_map |= mask; } control_page->in_numfree++; control_page->in_agctl[agno].numfree++; } } } }
/* * jfs_extendfs() * * function: extend file system; * * |-------------------------------|----------|----------| * file system space fsck inline log * workspace space * * input: * new LVSize: in LV blocks (required) * new LogSize: in LV blocks (optional) * new FSSize: in LV blocks (optional) * * new configuration: * 1. set new LogSize as specified or default from new LVSize; * 2. compute new FSCKSize from new LVSize; * 3. set new FSSize as MIN(FSSize, LVSize-(LogSize+FSCKSize)) where * assert(new FSSize >= old FSSize), * i.e., file system must not be shrinked; */ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct inode *ipbmap = sbi->ipbmap; struct inode *ipbmap2; struct inode *ipimap = sbi->ipimap; struct jfs_log *log = sbi->log; struct bmap *bmp = sbi->bmap; s64 newLogAddress, newFSCKAddress; int newFSCKSize; s64 newMapSize = 0, mapSize; s64 XAddress, XSize, nblocks, xoff, xaddr, t64; s64 oldLVSize; s64 newFSSize; s64 VolumeSize; int newNpages = 0, nPages, newPage, xlen, t32; int tid; int log_formatted = 0; struct inode *iplist[1]; struct jfs_superblock *j_sb, *j_sb2; uint old_agsize; struct buffer_head *bh, *bh2; /* If the volume hasn't grown, get out now */ if (sbi->mntflag & JFS_INLINELOG) oldLVSize = addressPXD(&sbi->logpxd) + lengthPXD(&sbi->logpxd); else oldLVSize = addressPXD(&sbi->fsckpxd) + lengthPXD(&sbi->fsckpxd); if (oldLVSize >= newLVSize) { printk(KERN_WARNING "jfs_extendfs: volume hasn't grown, returning\n"); goto out; } VolumeSize = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; if (VolumeSize) { if (newLVSize > VolumeSize) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } } else { /* check the device */ bh = sb_bread(sb, newLVSize - 1); if (!bh) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } bforget(bh); } /* Can't extend write-protected drive */ if (isReadOnly(ipbmap)) { printk(KERN_WARNING "jfs_extendfs: read-only file system\n"); rc = -EROFS; goto out; } /* * reconfigure LV spaces * --------------------- * * validate new size, or, if not specified, determine new size */ /* * reconfigure inline log space: */ if ((sbi->mntflag & JFS_INLINELOG)) { if (newLogSize == 0) { /* * no size specified: default to 1/256 of aggregate * size; rounded up to a megabyte boundary; */ newLogSize = newLVSize >> 8; t32 = (1 << (20 - sbi->l2bsize)) - 1; newLogSize = (newLogSize + t32) & ~t32; newLogSize = min(newLogSize, MEGABYTE32 >> sbi->l2bsize); } else {
int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct inode *ipbmap = sbi->ipbmap; struct inode *ipbmap2; struct inode *ipimap = sbi->ipimap; struct jfs_log *log = sbi->log; struct bmap *bmp = sbi->bmap; s64 newLogAddress, newFSCKAddress; int newFSCKSize; s64 newMapSize = 0, mapSize; s64 XAddress, XSize, nblocks, xoff, xaddr, t64; s64 oldLVSize; s64 newFSSize; s64 VolumeSize; int newNpages = 0, nPages, newPage, xlen, t32; int tid; int log_formatted = 0; struct inode *iplist[1]; struct jfs_superblock *j_sb, *j_sb2; s64 old_agsize; int agsizechanged = 0; struct buffer_head *bh, *bh2; if (sbi->mntflag & JFS_INLINELOG) oldLVSize = addressPXD(&sbi->logpxd) + lengthPXD(&sbi->logpxd); else oldLVSize = addressPXD(&sbi->fsckpxd) + lengthPXD(&sbi->fsckpxd); if (oldLVSize >= newLVSize) { printk(KERN_WARNING "jfs_extendfs: volume hasn't grown, returning\n"); goto out; } VolumeSize = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; if (VolumeSize) { if (newLVSize > VolumeSize) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } } else { bh = sb_bread(sb, newLVSize - 1); if (!bh) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } bforget(bh); } if (isReadOnly(ipbmap)) { printk(KERN_WARNING "jfs_extendfs: read-only file system\n"); rc = -EROFS; goto out; } if ((sbi->mntflag & JFS_INLINELOG)) { if (newLogSize == 0) { newLogSize = newLVSize >> 8; t32 = (1 << (20 - sbi->l2bsize)) - 1; newLogSize = (newLogSize + t32) & ~t32; newLogSize = min(newLogSize, MEGABYTE32 >> sbi->l2bsize); } else {