📄 fsckino.c
字号:
/* * Copyright (C) International Business Machines Corp., 2000-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* defines and includes common among the fsck.jfs modules */#include "xfsckint.h"#include "jfs_byteorder.h"#include "jfs_unicode.h"#include "unicode_to_utf8.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */extern UniChar uni_message_parm[];extern UniChar *uni_msgprm;extern char *verbose_msg_ptr;extern char *Vol_Label; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * defined in xchkdsk.c */extern HFILE Dev_IOPort;extern uint32_t Dev_blksize;extern int32_t Uni_Name_len;extern UniChar Uni_Name[];extern int32_t Str_Name_len;extern char Str_Name[];/***************************************************************************** * NAME: backout_ACL * * FUNCTION: Unrecord all storage allocated for the access control list * (ACL) of the current inode. * * PARAMETERS: * ino_ptr - input - pointer to the current inode * ino_recptr - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * success: FSCK_OK * failure: something else */int backout_ACL(struct dinode *ino_ptr, struct fsck_inode_record *ino_recptr){ int bacl_rc = FSCK_OK; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 0; int8_t is_ACL = 1; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* * if the ACL is in an out-of-line extent, release the blocks * allocated for it. */ if (ino_ptr->di_acl.flag == DXD_EXTENT) { extent_length = lengthDXD(&(ino_ptr->di_acl)); extent_address = addressDXD(&(ino_ptr->di_acl)); bacl_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); } /* * backout the blocks in the ACL extent from the running totals for * fileset and inode, but not for the object * represented by the object (because they were never added to that). */ agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; return (bacl_rc);}/***************************************************************************** * NAME: backout_EA * * FUNCTION: Unrecord all storage allocated for the extended attributes * (ea) of the current inode. * * PARAMETERS: * ino_ptr - input - pointer to the current inode * ino_recptr - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * success: FSCK_OK * failure: something else */int backout_EA(struct dinode *ino_ptr, struct fsck_inode_record *ino_recptr){ int bea_rc = FSCK_OK; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 1; int8_t is_ACL = 0; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* * if the EA is in an out-of-line extent, release the blocks * allocated for it. */ if (ino_ptr->di_ea.flag == DXD_EXTENT) { extent_length = lengthDXD(&(ino_ptr->di_ea)); extent_address = addressDXD(&(ino_ptr->di_ea)); bea_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); } /* * backout the blocks in the EA extent from the running totals for * fileset and inode, but not for the object * represented by the object (because they were never added to that). */ agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; return (bea_rc);}/***************************************************************************** * NAME: calculate_dasd_used * * FUNCTION: Calculate the cumulative amount of dasd used for each directory * in the file system. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */int calculate_dasd_used(){ int cdu_rc = FSCK_OK; uint32_t ino_idx; struct fsck_inode_record *this_inorec; struct fsck_inode_record *this_child_inorec; struct fsck_inode_record *this_parent_inorec; struct fsck_inode_record *next_parent_inorec; int aggregate_inode = 0; int alloc_ifnull = 0; int32_t this_level; /* * In the first step we make a single pass on the inode records: * * if the inode represents a file which is not an orphan then the * number of blocks used by the file is added to the cummulative * total for the parent inode. * * if the inode represents a directory then we figure out the * distance, in the fileset directory tree, between this inode and * the root directory inode. */ cdu_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); if ((cdu_rc != FSCK_OK) || (this_inorec == NULL)) goto out; while (ino_idx < FILESET_OBJECT_I) { /* * not interesting until we get past the root inode * and the special fileset inodes. */ cdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); if ((cdu_rc != FSCK_OK) || (this_inorec == NULL)) goto out; } while (this_inorec != NULL) { if ((!this_inorec->in_use) || this_inorec->selected_to_rls) goto next_inode; if (this_inorec->inode_type != directory_inode) { /* it's a file */ if (this_inorec->parent_inonum == 0) /* orphan */ goto next_inode; cdu_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &this_parent_inorec); if ((cdu_rc == FSCK_OK) && (this_parent_inorec == NULL)) cdu_rc = FSCK_INTERNAL_ERROR_63; if (cdu_rc != FSCK_OK) goto out; this_parent_inorec->cumm_blocks += this_inorec->cumm_blocks; goto next_inode; } /* it's a directory */ if (this_inorec->dtree_level != -1) /* distance already known */ goto next_inode; if (this_inorec->parent_inonum == 0) { /* it's an orphan */ this_inorec->dtree_level = 0; if (this_inorec->dtree_level > agg_recptr->tree_height) agg_recptr->tree_height = this_inorec->dtree_level; goto next_inode; } /* it's not an orphan */ cdu_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &this_parent_inorec); if ((cdu_rc == FSCK_OK) && (this_parent_inorec == NULL)) cdu_rc = FSCK_INTERNAL_ERROR_64; if (cdu_rc != FSCK_OK) goto out; agg_recptr->treeStack = NULL; cdu_rc = treeStack_push(this_inorec); while (this_parent_inorec->dtree_level == -1) { if (this_parent_inorec->parent_inonum == 0) { /* orphan */ this_parent_inorec->dtree_level = 0; } else { /* not an orphan */ cdu_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_parent_inorec-> parent_inonum, &next_parent_inorec); if ((cdu_rc == FSCK_OK) && (next_parent_inorec == NULL)) cdu_rc = FSCK_INTERNAL_ERROR_65; if (cdu_rc == FSCK_OK) { /* located next parent's inode rec */ cdu_rc = treeStack_push(this_parent_inorec); this_parent_inorec = next_parent_inorec; } if (cdu_rc != FSCK_OK) goto out; } } this_level = this_parent_inorec->dtree_level; /* * this is the first known level number * (distance) in the chain of directories * from here to the root. */ while (agg_recptr->treeStack != NULL) { this_level++; cdu_rc = treeStack_pop(&this_child_inorec); this_child_inorec->dtree_level = this_level; if (this_child_inorec->dtree_level > agg_recptr->tree_height) { agg_recptr->tree_height = this_child_inorec->dtree_level; } } next_inode: cdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); if (cdu_rc != FSCK_OK) goto out; } /* * * In the second step we make one pass on the inode records for each * level in the fileset directory tree, since we must accumulate the * dasd used values from the bottom up. * */ this_level = agg_recptr->tree_height; while (this_level > 0) { cdu_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); if (cdu_rc != FSCK_OK) goto out; while ((this_inorec != NULL) && (ino_idx < FILESET_OBJECT_I)) { /* * not interesting until we get past the root inode * and the special fileset inodes. */ cdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); if (cdu_rc != FSCK_OK) goto out; } while (this_inorec != NULL) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (this_inorec->inode_type == directory_inode) && (this_inorec->dtree_level == this_level)) { /* * inode in use and not selected to release and * type directory and dtree level is a match */ cdu_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &this_parent_inorec); if ((cdu_rc == FSCK_OK) && (this_parent_inorec == NULL)) cdu_rc = FSCK_INTERNAL_ERROR_66; if (cdu_rc != FSCK_OK) goto out; this_parent_inorec->cumm_blocks += this_inorec->cumm_blocks; } cdu_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); if (cdu_rc != FSCK_OK) goto out; } this_level--; } out: return (cdu_rc);}/***************************************************************************** * NAME: clear_ACL_field * * FUNCTION: Unrecord all storage allocated for the access control list * (ACL) of the current inode. Clear the inode ACL field to show * the inode owns no ACL. * * PARAMETERS: * ino_recptr - input - pointer to an fsck inode record describing the * current inode * ino_ptr - input - pointer to the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int clear_ACL_field(struct fsck_inode_record *ino_recptr, struct dinode *ino_ptr){ int caf_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 0; int8_t is_ACL = -1; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* locate the EA field in the inode */ dxd_ptr = &(ino_ptr->di_acl); /* * if the ACL is in an out-of-line extent, release the blocks * allocated for it. */ if ((dxd_ptr->flag == DXD_EXTENT) && (!ino_recptr->ignore_acl_blks) && (!ino_recptr->ignore_alloc_blks)) { /* out of line single extent and not flagged to ignore */ extent_length = lengthDXD(dxd_ptr); extent_address = addressDXD(dxd_ptr); caf_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); ino_ptr->di_nblocks -= block_count; agg_recptr->blocks_for_acls -= block_count; } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -