Example #1
0
/*****************************************************************************
 * NAME: exec_clrbdblks
 *
 * FUNCTION:	Start clrbblks in a child process and wait for it to complete.
 *
 * PARAMETERS:  none
 *
 * NOTES:	
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t exec_clrbdblks( )
{
  retcode_t ec_rc = FSCK_OK;
  CHAR szFailName[CCHMAXPATH];
  RESULTCODES resc;
  CHAR szCommandLine[] = "clrbblks\0\0\0\0\0\0\0\0\0\0\0\0";
	
  memcpy((void *) &(szCommandLine[9]), (void *) Vol_Label, sizeof(Vol_Label));
	
  ec_rc = DosExecPgm( szFailName,   sizeof(szFailName),
                                 EXEC_SYNC,
                                 szCommandLine, (PSZ) NULL,
                                 &resc, "clrbblks.exe" );
	/*
	 * log the result of the DosExecPgm
	 */
  sprintf( message_parm_0, "%ld", ec_rc );
  msgprms[0] = message_parm_0;
  msgprmidx[0] = 0;
  fsck_send_msg( fsck_DOSEXECPGMRC, 0, 1 );
	/*
	 * if the DosExecPgm was successful, log and
	 * return the result of the clrbblks process
	 */
  if( ec_rc == 0 ) {
    sprintf( message_parm_0, "%ld,%ld", resc.codeTerminate, resc.codeResult );
    msgprms[0] = message_parm_0;
    msgprmidx[0] = 0;
    fsck_send_msg( fsck_CLRBBLKSRC, 0, 1 );
    ec_rc = resc.codeResult + resc.codeTerminate;
    }
	
  return( ec_rc );
}                            /* end of exec_clrbdblks()  */
Example #2
0
/*****************************************************************************
 * NAME: adjust_parent
 *
 * FUNCTION: Add an fsck inode extension record to the parent inode's 
 *           fsck inode record so that the directory entry for the
 *           given child will be removed.
 *
 * PARAMETERS:
 *      child_ino        - input - ordinal number of child inode
 *      child_inorecptr  - input - pointer to an fsck record describing the
 *                                 child inode
 *      parent_ino       - input - ordinal number of parent inode
 *
 * NOTES:
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t adjust_parent ( inoidx_t              child_ino,
                                    fsck_inode_recptr child_inorecptr,
                                    inoidx_t               parent_ino
                                   )
{
  retcode_t adjp_rc = FSCK_OK;
  fsck_inode_extptr this_ext;
  fsck_inode_recptr parent_inorecptr;
  int is_aggregate = 0;
  int alloc_ifnull = 0;

  adjp_rc = get_inorecptr( is_aggregate, alloc_ifnull, 
                                    parent_ino, &parent_inorecptr );

  if( (adjp_rc == FSCK_OK) && (parent_inorecptr == NULL) )  {  /* uh oh.... */
    adjp_rc = FSCK_INTERNAL_ERROR_4;
    sprintf( message_parm_0, "%ld", adjp_rc );                                   /* @F1 */
    msgprms[0] = message_parm_0;                                                  /* @F1 */
    msgprmidx[0] = 0;                                                                     /* @F1 */
    sprintf( message_parm_1, "%ld", child_ino );                                 /* @F1 */
    msgprms[1] = message_parm_1;                                                  /* @F1 */
    msgprmidx[1] = 0;                                                                     /* @F1 */
    sprintf( message_parm_2, "%ld", parent_ino );                               /* @F1 */
    msgprms[2] = message_parm_2;                                                  /* @F1 */
    msgprmidx[2] = 0;                                                                     /* @F1 */
    sprintf( message_parm_3, "%ld", 0 );                                           /* @F1 */
    msgprms[3] = message_parm_3;                                                  /* @F1 */
    msgprmidx[3] = 0;                                                                     /* @F1 */
    fsck_send_msg( fsck_INTERNALERROR, 0, 4 );                               /* @F1 */
    }  /* end uh oh.... */

  else if( adjp_rc == FSCK_OK ) {  /* located the parent's inode record */
    adjp_rc = get_inode_extension( &this_ext );
    if( adjp_rc == FSCK_OK )  {  /* got extension */
      this_ext->ext_type = rmv_direntry_extension;
      this_ext->inonum = child_ino;
      this_ext->next = parent_inorecptr->ext_rec;
      this_ext->ino_type = child_inorecptr->inode_type;
      parent_inorecptr->ext_rec = this_ext;
      parent_inorecptr->adj_entries = 1;
      agg_recptr->corrections_needed = 1;
      }  /* end got extension */
    }  /* end located the parent's inode record */

  return( adjp_rc );
}                            /* end of adjust_parent ()  */
Example #3
0
/*****************************************************************************
 * NAME: check_BdBlkLst_FillLevel
 *
 * FUNCTION:	If any of the LVM Bad Block Tables composing the LVM Bad
 *		Block List for this partition is more than 50% full, issue a message.
 *
 * PARAMETERS:  none
 *
 * NOTES:	This routine is called only during autocheck processing.  chkdsk
 *		cannot perform /B processing at that time since the file system
 *		is not yet fully initialized.
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t check_BdBlkLst_FillLevel ( )
{
  retcode_t ccbblfl_rc = FSCK_OK;
  int32 intermed_rc = 0;
  int32 num_tables = 0;
  int32 highest_percent_full = 0;

  intermed_rc = get_LVM_BadBlockList_count( &num_tables );
	

  if( intermed_rc == FSCK_OK ) {
    intermed_rc = examine_LVM_BadBlockLists( num_tables, &highest_percent_full );
    if( intermed_rc == FSCK_OK ) {
      if( highest_percent_full > 50 ) {
        fsck_send_msg( fsck_LVMFOUNDBDBLKS, 0, 0 );
        }
      }
    }
	
  return( ccbblfl_rc );
}                            /* end of check_BdBlkLst_FillLevel()  */
Example #4
0
/*
 * NAME:        pageVal(pno, eor, pmax)
 *
 * FUNCTION:    Read the page into the log buffer pool and call setLogpage
 *              to form consistent log page.
 *
 * RETURNS:     0                       - ok
 *              REFORMAT_ERROR(-3)      - I/O error, reformat the log
 *              MAJOR_ERROR(-2)         - other major errors other than EIO.
 */
pageVal(int pno,        /* page number in log           */
        int *eor,       /* corresponding eor value      */
        int *pmax)      /* pointer to returned page number */
{
        int     rc,
                buf0;           /* logp[] buffer element number         */

        /* Read the page into the log buffer pool.
         */
        if ((buf0 = getLogpage(pno)) < 0)
        {
                sprintf( message_parm_0, "(d) %d", pno  );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = 0;
                sprintf( message_parm_1, "(d) %d", rc  );
                msgprms[1] = message_parm_1;
                msgprmidx[1] = 0;
                fsck_send_msg( lrdo_PVGETPGFAIL, 0, 2 );

                return(buf0);
        }
        return(setLogpage(pno, eor, pmax, buf0));
}
Example #5
0
/*****************************************************************************
 * NAME: reset_parents
 *
 * FUNCTION: Adjust the fsck notations about the inode's parent(s) if 
 *           the parent(s) are corrupt or approved for release.
 *
 * PARAMETERS:
 *      ino_recptr  - input - pointer to an fsck record describing the inode
 *      ino_idx     - input - ordinal number of the inode
 *
 * NOTES:
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t reset_parents ( fsck_inode_recptr ino_recptr,
                          inoidx_t          ino_idx
                         )
{
  retcode_t resps_rc = FSCK_OK;
  fsck_inode_extptr this_ext;
  fsck_inode_extptr rest_of_list;
  int parent_count = 0;
  inoidx_t stored_parent_inonum;
  fsck_inode_recptr parent_inorecptr;
  int aggregate_inode = 0;
  int alloc_ifnull = 0;
    /*
     * if this is a directory with illegal hard links the inode
     * number in the fsck inode record is the one stored in the
     * inode on disk.
     */
  if( (ino_recptr->inode_type == directory_inode) &&
      (ino_recptr->unxpctd_prnts) ) {  /* dir with multiple parents */
       /*
        * Save the value stored in the inode record and then clear it.
        */
    stored_parent_inonum = ino_recptr->parent_inonum;
    ino_recptr->parent_inonum = 0;
    }  /* end dir with multiple parents */
  else {  /* not a dir with multiple parents */
      /*
       * the 1st parent observed is in the inode record.  Any others are
       * in extension records.
       */
    resps_rc = get_inorecptr( aggregate_inode, alloc_ifnull,
                              ino_recptr->parent_inonum, &parent_inorecptr );
    if( (resps_rc == FSCK_OK) && (parent_inorecptr == NULL) ) {
      resps_rc = FSCK_INTERNAL_ERROR_15;
      sprintf( message_parm_0, "%ld", resps_rc );                               /* @F1 */
      msgprms[0] = message_parm_0;                                               /* @F1 */
      msgprmidx[0] = 0;                                                                  /* @F1 */
      sprintf( message_parm_1, "%ld", ino_idx );                                 /* @F1 */
      msgprms[1] = message_parm_1;                                                /* @F1 */
      msgprmidx[1] = 0;                                                                  /* @F1 */
      sprintf( message_parm_2, "%ld", ino_recptr->parent_inonum );     /* @F1 */
      msgprms[2] = message_parm_2;                                               /* @F1 */
      msgprmidx[2] = 0;                                                                  /* @F1 */
      sprintf( message_parm_3, "%ld", 0 );                                         /* @F1 */
      msgprms[3] = message_parm_3;                                                /* @F1 */
      msgprmidx[3] = 0;                                                                  /* @F1 */
      fsck_send_msg( fsck_INTERNALERROR, 0, 4 );                             /* @F1 */
      }
    else if( resps_rc == FSCK_OK ) {
      if( (ino_recptr->parent_inonum == ROOT_I) &&
          (agg_recptr->rootdir_rebuilt)                   ) { /*
			* special case: if the parent is root and root was
			* 		rebuilt, then this is an orphan
			*/
        ino_recptr->parent_inonum = 0;
        ino_recptr->link_count--;
        }  /* end special case: if the parent is root ... */
      else if( (!parent_inorecptr->selected_to_rls) &&
          (!parent_inorecptr->ignore_alloc_blks)  ) { /*
                            * keeping this parent and haven't found the
                            * tree to be corrupt
                            */
        parent_count++;
        }  /* end keeping this parent */
      else {  /* releasing this parent */
        ino_recptr->parent_inonum = 0;
        ino_recptr->link_count--;
        }  /* end releasing this parent */
      }
    }  /* end else not a dir with multiple parents */
      /*
       * detach the extensions list from the inode record
       */
    this_ext = ino_recptr->ext_rec;
    ino_recptr->ext_rec = NULL;
    while( (resps_rc == FSCK_OK ) &&
           (this_ext != NULL) ) { /* there may be more parents */
      rest_of_list = this_ext->next;
      if( this_ext->ext_type != parent_extension ) { /* not a parent */
        this_ext->next = ino_recptr->ext_rec;
        ino_recptr->ext_rec = this_ext;
        }  /* end not a parent */
      else { /* parent extension */
        resps_rc = get_inorecptr( aggregate_inode, alloc_ifnull,
                                  this_ext->inonum, &parent_inorecptr );
        if( (resps_rc == FSCK_OK) && (parent_inorecptr == NULL) ) {
          resps_rc = FSCK_INTERNAL_ERROR_16;
          sprintf( message_parm_0, "%ld", resps_rc );
          msgprms[0] = message_parm_0;                                            /* @F1 */
          msgprmidx[0] = 0;                                                               /* @F1 */
          sprintf( message_parm_1, "%ld", ino_idx );                             /* @F1 */
          msgprms[1] = message_parm_1;                                            /* @F1 */
          msgprmidx[1] = 0;                                                               /* @F1 */
          sprintf( message_parm_2, "%ld", this_ext->inonum );               /* @F1 */
          msgprms[2] = message_parm_2;                                            /* @F1 */
          msgprmidx[2] = 0;                                                               /* @F1 */
          sprintf( message_parm_3, "%ld", 0 );                                     /* @F1 */
          msgprms[3] = message_parm_3;                                            /* @F1 */
          msgprmidx[3] = 0;                                                               /* @F1 */
          fsck_send_msg( fsck_INTERNALERROR, 0, 4 );                          /* @F1 */
          }
        else if( resps_rc == FSCK_OK ) {
          if( (ino_recptr->parent_inonum == ROOT_I) &&
              (agg_recptr->rootdir_rebuilt)                   ) { /*
			* special case: if the parent is root and root was
			* 		rebuilt, then this is an orphan
			*/
            release_inode_extension( this_ext );
            ino_recptr->link_count--;
            }  /* end special case: if the parent is root ... */
          else if( (!parent_inorecptr->selected_to_rls) &&
              (!parent_inorecptr->ignore_alloc_blks) ) { /* keeping this parent */
            parent_count++;
            if( ino_recptr->parent_inonum == 0 )  {
              ino_recptr->parent_inonum = this_ext->inonum;
              release_inode_extension( this_ext );
              }
            else {  /* put it back on the list */
              this_ext->next = ino_recptr->ext_rec;
              ino_recptr->ext_rec = this_ext;
              } /* put it back on the list */
            }  /* end keeping this parent */
          else {  /* releasing this parent */
            release_inode_extension( this_ext );
            ino_recptr->link_count--;
            }  /* end else releasing this parent */
          }
        }  /* end else parent extension */
      this_ext = rest_of_list;
      }  /* end while there may be more parents */
  /*
   * at this point, if there is at least 1 observed parent which
   * is not being released, then a parent inode number is stored in
   * the inode record and any other parents are described in extension
   * records.
   *
   * if this is not a directory inode, we're done.
   *
   * if this is a directory inode, need to recheck for illegal hard
   * links and incorrect parent inode entry.
   */
  if( (resps_rc == FSCK_OK) && (ino_recptr->inode_type == directory_inode) ) {  /*
                               * a directory
                               */
    if( parent_count == 1 )  {  /* 1 parent now */
      if( ino_recptr->unxpctd_prnts )  {  /* entered with multiple links */
        ino_recptr->unxpctd_prnts = 0;  /* reset flag */
        if( ino_recptr->parent_inonum != stored_parent_inonum ) {  /*
                               * Remaining parent doesn't match the one
                               * the on-device inode says owns it.
                               */
          ino_recptr->crrct_prnt_inonum = 1;
          agg_recptr->corrections_needed = 1;
          agg_recptr->corrections_approved = 1;
          }  /* end remaining parent doesn't match the one the ... */
        }  /* end entered with multiple links */
      }  /* end 1 parent now */
    else if( parent_count == 0 )  { /* no parents now */
      ino_recptr->crrct_prnt_inonum = 0;
      ino_recptr->unxpctd_prnts = 0;
      }  /* end no parents now */
    else {  /* multiple parents still */
      ino_recptr->unxpctd_prnts = 1;
      agg_recptr->corrections_needed = 1;
      resps_rc = get_inode_extension( &this_ext );
      if( resps_rc == FSCK_OK ) {  /* got one */
        this_ext->ext_type = parent_extension;
        this_ext->inonum = ino_recptr->parent_inonum;
        this_ext->next = ino_recptr->ext_rec;
        ino_recptr->ext_rec = this_ext;
        ino_recptr->parent_inonum = stored_parent_inonum;
        }  /* end got one */
      }  /* end multiple parents still */
    }  /* end a directory */
  return( resps_rc );
}                            /* end of reset_parents ()  */
Example #6
0
/*****************************************************************************
 * NAME: check_link_counts
 *
 * FUNCTION:  Count links from child directories to their parents.  
 *
 *	      Verify that the link count stored in each in-use inode 
 *	      matches the number of links fsck observed for the inode.
 *
 * PARAMETERS:  none
 *
 * NOTES:
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t check_link_counts ( )
{
  retcode_t clc_rc = FSCK_OK;
  inoidx_t ino_idx;
  int num_parents;
  int invalid_count_seen = 0;
  int low_stored_count_seen = 0;
  char user_reply;
  fsck_inode_extptr this_ext;
  fsck_inode_recptr this_inorec;
  fsck_inode_recptr parent_inorec;
  int done_looking = 0;
  int aggregate_inode = 0;
  int alloc_ifnull = 0;

  struct fsck_ino_msg_info  ino_msg_info;
  fsck_msg_info_ptr msg_info_ptr;

  msg_info_ptr = &ino_msg_info;
  msg_info_ptr->msg_inopfx = fsck_fset_inode;  /* all fileset owned */

    /*
     * count links from child directories to their parents
     *
     * (These can't be counted when the parent-child relationship
     * is observed because that observation occurs while processing
     * the parent and until the child is processed we don't know
     * whether the child is a directory or not.)
     */
  clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec );

  while( (clc_rc == FSCK_OK) && (this_inorec != NULL) ) {
	
    if( (this_inorec->in_use) &&
        (!this_inorec->selected_to_rls) &&
        (!this_inorec->ignore_alloc_blks) &&
        (this_inorec->inode_type == directory_inode) ) {  /*
                               * inode is in use, not being released, and 
				* is type directory
                               */
      this_inorec->link_count++;  /* for the self entry */
      if( (this_inorec->parent_inonum == ROOT_I) &&
          (agg_recptr->rootdir_rebuilt)                   ) { /*
			* special case: if the parent is root and root was
			* 		rebuilt, then don't increment parent
			*/
        if( this_inorec->inonum == ROOT_I ) { /*
			* special case: if this IS the root, then it's link from itself
			* 		to itself DOES count 
			*/
          this_inorec->link_count++; 
          }
        }
      else if( this_inorec->parent_inonum != (ino_t) 0 )  {  /*
                               * not an orphan
                               */
        clc_rc = get_inorecptr( aggregate_inode, alloc_ifnull,
                                this_inorec->parent_inonum, &parent_inorec );
        if( (clc_rc != FSCK_OK) || (parent_inorec == NULL) ) {
          clc_rc = FSCK_INTERNAL_ERROR_13;
          sprintf( message_parm_0, "%ld", clc_rc );                              /* @F1 */
          msgprms[0] = message_parm_0;                                           /* @F1 */
          msgprmidx[0] = 0;                                                              /* @F1 */
          sprintf( message_parm_1, "%ld", ino_idx );                             /* @F1 */
          msgprms[1] = message_parm_1;                                            /* @F1 */
          msgprmidx[1] = 0;                                                               /* @F1 */
          sprintf( message_parm_2, "%ld", this_inorec->parent_inonum ); /* @F1 */
          msgprms[2] = message_parm_2;                                            /* @F1 */
          msgprmidx[2] = 0;                                                               /* @F1 */
          sprintf( message_parm_3, "%ld", 0 );                                     /* @F1 */
          msgprms[3] = message_parm_3;                                            /* @F1 */
          msgprmidx[3] = 0;                                                               /* @F1 */
          fsck_send_msg( fsck_INTERNALERROR, 0, 4 );                         /* @F1 */
          }
        else {
          parent_inorec->link_count++; /*
                               * handle the first (and usually the only)
                               * parent.
                               */
          }
        if( (clc_rc == FSCK_OK) && (this_inorec->ext_rec != NULL) )  {  /*
                               * there might be more parents
                               */
          num_parents = parent_count( this_inorec );
          if( num_parents > 1 ) {  /* directory with illegal links */
            this_inorec->unxpctd_prnts = 1;
            agg_recptr->corrections_needed = 1;
                /*
                 * Create an extension record for the parent inode number
                 * now stored in the child inode record.
                 * When we traverse the aggregate on-disk we'll copy the
                 * stored value into this field of the inode record for
                 * use when displaying paths to the inode.
                 */
            clc_rc = get_inode_extension( &this_ext );
            if( clc_rc == FSCK_OK )  {  /* got extension record */
              this_ext->ext_type = parent_extension;
              this_ext->inonum = this_inorec->parent_inonum;
              this_ext->next = this_inorec->ext_rec;
              this_inorec->ext_rec = this_ext;
              this_inorec->parent_inonum = 0;
              this_ext = this_ext->next;  /* already counted the first
                                   * one, back when it was in the
                                   * workspace inode record itself
                                   */
              while ( (clc_rc == FSCK_OK) &&
                      (this_ext != NULL) ) {  /* exten records to check */
                if( this_ext->ext_type == parent_extension ) {
                  clc_rc = get_inorecptr( aggregate_inode, alloc_ifnull,
                                          this_ext->inonum, &parent_inorec );
                  if( (clc_rc != FSCK_OK) || (parent_inorec == NULL) ) {
                    clc_rc = FSCK_INTERNAL_ERROR_14;
                    sprintf( message_parm_0, "%ld", clc_rc );                    /* @F1 */
                    msgprms[0] = message_parm_0;                                 /* @F1 */
                    msgprmidx[0] = 0;                                                    /* @F1 */
                    sprintf( message_parm_1, "%ld", ino_idx );                   /* @F1 */
                    msgprms[1] = message_parm_1;                                  /* @F1 */
                    msgprmidx[1] = 0;                                                     /* @F1 */
                    sprintf( message_parm_2, "%ld", this_ext->inonum );     /* @F1 */
                    msgprms[2] = message_parm_2;                                  /* @F1 */
                    msgprmidx[2] = 0;                                                     /* @F1 */
                    sprintf( message_parm_3, "%ld", 0 );                           /* @F1 */
                    msgprms[3] = message_parm_3;                                  /* @F1 */
                    msgprmidx[3] = 0;                                                     /* @F1 */
                    fsck_send_msg( fsck_INTERNALERROR, 0, 4 );                /* @F1 */
                    }
                  else {
                    parent_inorec->link_count++;
                    }
                  }
                this_ext = this_ext->next;
                }  /* end while exten records to check */
              }  /* end got extension record */
            }  /* end directory with illegal links */
          }  /* end there might be more parents */
        }  /* end not an orphan */
      }  /* end inode is in use and is type directory */
   
    if( clc_rc == FSCK_OK ) {
      clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
      }
    }  /* end while */

    /*
     * verify that stored link counts match observed link counts
     *
     * We have added each observed link and subtracted the stored
     * count.  If the stored count is correct the result is 0.
     */
  if( clc_rc == FSCK_OK ) {  /* no fatal errors */

    clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec );

    while( (clc_rc == FSCK_OK) && (this_inorec != NULL) && (!done_looking) ) {
	
      if( (this_inorec->in_use) &&   
        (!this_inorec->selected_to_rls) &&
        (!this_inorec->ignore_alloc_blks)  ) {  /*
				* inode is in use and not being released
				*/
        if( this_inorec->link_count != 0 ) {  /* stored
				* link count doesn't match fsck's observations
				*/
          if( this_inorec->parent_inonum == 0 ) { /* inode is an orphan */
            this_inorec->crrct_link_count = 1;
	    }
	  else {  /* not an orphan */
            this_inorec->crrct_link_count = 1;
            if( this_inorec->link_count > 0 ) {
              low_stored_count_seen = 1;
              }
            invalid_count_seen = 1;

            msgprms[0] = message_parm_0;
            msgprmidx[0] = msg_info_ptr->msg_inopfx;
            sprintf( message_parm_1, "%ld", ino_idx );
            msgprms[1] = message_parm_1;
            msgprmidx[1] = 0;
            fsck_send_msg( fsck_BADINOLKCT, 0, 2 );
            }  /* end else not an orphan */
          }  /* end stored link count doesn't match fsck's observations */
        }  /* end inode is in use and not being released */

      if( clc_rc == FSCK_OK ) {
        clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
        }
      }  /* end while */

    if( (clc_rc == FSCK_OK) && (invalid_count_seen) ) {

      if( agg_recptr->processing_readwrite ) {  /* we can fix this */
        agg_recptr->corrections_approved = 1;
        fsck_send_msg( fsck_WILLFIXLINKCTS, 0, 0 );
        }  /* end we can fix this */
      else {  /* no write access */
        if( low_stored_count_seen )  {
          agg_recptr->ag_dirty = 1;
          }  /* end if low_stored_count_seen */
            /*
             * reset all link counts (in the fsck workspace) to
             * zero so that we won't accidentally correct them
             * while doing link count adjustments.
             *
             * (Link count adjustments are side effects of approved
             * repairs.  For example, if a directory inode is
             * released, the link count of its parent directory
             * is decremented.)
             */
        clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec );

        while( (clc_rc == FSCK_OK) && (this_inorec != NULL) ) {
	
          if( this_inorec->in_use ) { /* inode in use  */
            this_inorec->crrct_link_count = 0;
            this_inorec->link_count = 0;
            }  /* end inode in use */

          clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
          }  /* end while */
        fsck_send_msg( fsck_BADLINKCTS, 0, 0 );
        }  /* end no write access */
      }  /* end if invalid_count_seen */
    }  /* end no fatal errors */

  return( clc_rc );
}                              /* end of check_link_counts ()  */
Example #7
0
/*****************************************************************************
 * NAME: check_dir_integrity
 *
 * FUNCTION:  Verify that no directory has more than 1 entry for any
 *            single inode.  If a directory does, then that directory
 *            is corrupt (in Release I of JFS/Warp).
 *
 * PARAMETERS:  none
 *
 * NOTES:  none
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t check_dir_integrity ( )
{
  retcode_t cdi_rc = FSCK_OK;
  inoidx_t ino_idx;
  fsck_inode_recptr this_inorec;
  fsck_inode_recptr that_inorec;
  int aggregate_inode = 0;
  int alloc_ifnull = 0;
  fsck_inode_extptr this_ext;
  fsck_inode_extptr that_ext;
  int dup_parent_detected = 0;

  struct fsck_ino_msg_info  ino_msg_info;
  fsck_msg_info_ptr msg_info_ptr;

  msg_info_ptr = &ino_msg_info;
  msg_info_ptr->msg_inopfx = fsck_fset_inode;  /* all fileset owned */

    /*
     * Verify that no inode has multiple links from the same 
     * directory.
     */
  cdi_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec );

  while( (cdi_rc == FSCK_OK) && 
         (this_inorec != NULL) && 
         (ino_idx < FILESET_OBJECT_I) ) { /*
                               * not interesting until we get past the root inode
                               * and the special fileset inodes.
                               */
    cdi_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
    }  /* end while */

  while( (cdi_rc == FSCK_OK) && (this_inorec != NULL) ) {
	
    if( (this_inorec->in_use) &&
        (!this_inorec->selected_to_rls) )  {  /*
                               * inode in use and not selected to release
                               */
      msg_info_ptr->msg_inonum = ino_idx;
      if( this_inorec->inode_type == directory_inode ) {
	msg_info_ptr->msg_inotyp = fsck_directory;
	}
      else if( this_inorec->inode_type == symlink_inode ) {
	msg_info_ptr->msg_inotyp = fsck_symbolic_link;
	}
      else {  /* a regular file */
	msg_info_ptr->msg_inotyp = fsck_file;
	}

      if( this_inorec->parent_inonum != 0 )  {  /* 
		* at least 1 parent observed by fsck
                */
        if( this_inorec->ext_rec ) {  /* 
		* and maybe more parents have been observed 
		*/
            /*
             * get the first entry in the extensions 
             * list on the inode record
             */
          this_ext = this_inorec->ext_rec;

          while( (cdi_rc == FSCK_OK ) &&
                 (this_ext != NULL) ) { /* there may be more parents */

            if( this_ext->ext_type == parent_extension ) { /* a parent */
              cdi_rc = get_inorecptr( aggregate_inode, alloc_ifnull,
                                      this_ext->inonum,
                                      &that_inorec );
              if( (cdi_rc == FSCK_OK) && 
		  (!that_inorec->selected_to_rls) ) { /* 
			* parent isn't marked for release (yet)
			*/
                dup_parent_detected = 0;
                if( this_ext->inonum == this_inorec->parent_inonum ) {
                  dup_parent_detected = -1;
                  }
                else {  /* need to check for dups in rest of list */
                  that_ext = this_ext->next;
                  while( (!dup_parent_detected) && (that_ext != NULL) ) { 
                    if( that_ext->ext_type == parent_extension ) /*
			* another parent extension
			*/
                    if( this_ext->inonum == that_ext->inonum ) { 
                      dup_parent_detected = -1;
                      }
                    that_ext = that_ext->next;
                    }  /* end while */
                  }  /* end else need to check for dups in rest of list */
                if( dup_parent_detected ) {
			/* 
			 * mark the parent's inode record for release
			 */
                  that_inorec->selected_to_rls = 1;
			/* 
			 * notify the user that the directory is bad
			 */
                  msgprms[0] = message_parm_0;
                  msgprmidx[0] = fsck_directory;
                  msgprms[1] = message_parm_1;
                  msgprmidx[1] = msg_info_ptr->msg_inopfx;
                  sprintf( message_parm_2, "%ld", this_ext->inonum );
                  msgprms[2] = message_parm_2;
                  msgprmidx[2] = 0;
                  sprintf( message_parm_3, "%d", 37 );
                  msgprms[3] = message_parm_3;
                  msgprmidx[3] = 0;
                  fsck_send_msg( fsck_BADKEYS, 0, 4 );
                  }  /* end dup_parent_detected */
                }  /* end parent isn't marked for release (yet) */
              }  /* end a parent */

            this_ext = this_ext->next;
            }  /* end while there may be more parents */
          }  /* end and maybe more parents have been observed */
        }  /* end at least 1 parent observed by fsck */

      }  /* end inode in use and not selected to release  */

    if( cdi_rc == FSCK_OK ) {
      cdi_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
      }
    }  /* end while */

  return( cdi_rc );
}                              /* end of check_dir_integrity ()  */
Example #8
0
/*****************************************************************************
 * NAME: check_connectedness
 *
 * FUNCTION:  Verify that, after approved corrections are made, all inodes
 *            in use will be connected to the root directory tree.  
 *
 * PARAMETERS:  none
 *
 * NOTES:  o A directory inode must have exactly one parent inode.
 *
 *         o A non-directory inode must have at least one parent inode.
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t check_connectedness ( )
{
  retcode_t cc_rc = FSCK_OK;
  inoidx_t ino_idx;
  fsck_inode_extptr this_ext;
  fsck_inode_recptr this_inorec;
  fsck_inode_extptr new_ext;
  char user_reply;
  int aggregate_inode = 0;
  int alloc_ifnull = 0;

  struct fsck_ino_msg_info  ino_msg_info;
  fsck_msg_info_ptr msg_info_ptr;

  msg_info_ptr = &ino_msg_info;
  msg_info_ptr->msg_inopfx = fsck_fset_inode;  /* all fileset owned */

    /*
     * detect orphan inodes, including ones which we're about to
     * orphan by releasing inodes.
     *
     * if any non-orphan inode was flagged as a directory with illegal
     * hard links, see if it's going to be true after we release inodes.
     * If not, make sure the remaining link matches the one stored in
     * the inode.
     */
  cc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec );

  while( (cc_rc == FSCK_OK) && 
         (this_inorec != NULL) && 
         (ino_idx < FILESET_OBJECT_I) ) { /*
                               * not interesting until we get past the root inode
                               * and the special fileset inodes.
                               */
    cc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
    }  /* end while */

  while( (cc_rc == FSCK_OK) && (this_inorec != NULL) ) {
	
    if( (this_inorec->in_use) &&
        (!this_inorec->selected_to_rls) )  {  /*
                               * inode in use and not selected to release
                               */
      msg_info_ptr->msg_inonum = ino_idx;
      if( this_inorec->inode_type == directory_inode ) {
	msg_info_ptr->msg_inotyp = fsck_directory;
	}
      else if( this_inorec->inode_type == symlink_inode ) {
	msg_info_ptr->msg_inotyp = fsck_symbolic_link;
	}
      else {  /* a regular file */
	msg_info_ptr->msg_inotyp = fsck_file;
	}

      if( this_inorec->parent_inonum == 0 )  {  /* no parents were
                               * observed by fsck
                               */
        msgprms[0] = message_parm_0;
        msgprmidx[0] = msg_info_ptr->msg_inopfx;
        sprintf( message_parm_1, "%ld", msg_info_ptr->msg_inonum );
        msgprms[1] = message_parm_1;
        msgprmidx[1] = 0;
        fsck_send_msg( fsck_INONOPATHS, 0, 2 );
        }  /* end no parents were observed by fsck */
      else {  /* at least one parent observed by fsck */
        cc_rc = reset_parents( this_inorec, ino_idx );  /*
                               * make adjustments to child records for
                               * parents which will be released
                               */
        }  /* end else at least one parent observed by fsck */

      if( cc_rc == FSCK_OK ) {  /* nothing fatal */

        if( this_inorec->parent_inonum == 0 )  {  /* unconnected !! */
              /*
               * do not issue a message to inform the user about
               * this condition since it is a side effect of
               * the (approved) release of some other inode(s)
               */
          this_inorec->reconnect = 1;
          agg_recptr->corrections_approved = 1;
          cc_rc = get_inode_extension( &new_ext );
          if( cc_rc == FSCK_OK )  {  /* got an extension record */
            new_ext->ext_type = add_direntry_extension;
            new_ext->inonum = ino_idx;
            new_ext->ino_type = this_inorec->inode_type;
            new_ext->next = agg_recptr->inode_reconn_extens;
            agg_recptr->inode_reconn_extens = new_ext;
            this_inorec->link_count++;  /* increment for the link from
                               * parent after reconnect
                               */
            }  /* end got an extension record */
          }  /* end unconnected !! */

        else {  /* else still connected */

          if( this_inorec->unxpctd_prnts ) {  /* multiple parents */

            cc_rc = display_paths( ino_idx, this_inorec, msg_info_ptr );

            if( cc_rc == FSCK_OK ) {  /* nothing unexpected */

              if( agg_recptr->processing_readwrite ) {  /* we can fix this */
                cc_rc = adjust_parents( this_inorec, ino_idx );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = msg_info_ptr->msg_inopfx;
                sprintf( message_parm_1, "%ld", msg_info_ptr->msg_inonum );
                msgprms[1] = message_parm_1; 
                msgprmidx[1] = 0;
                fsck_send_msg( fsck_WILLFIXDIRWHDLKS, 0, 2 );
                }  /* end we can fix this */
              else {       /* we don't have write access */
                this_inorec->unxpctd_prnts = 0;
                agg_recptr->ag_dirty = 1;
                msgprms[0] = message_parm_0;
                msgprmidx[0] = msg_info_ptr->msg_inopfx;
                sprintf( message_parm_1, "%ld", msg_info_ptr->msg_inonum );
                msgprms[1] = message_parm_1;
                msgprmidx[1] = 0;
                fsck_send_msg( fsck_DIRWHDLKS, 0, 2 );
                }  /* end we don't have write access */
              }  /* end nothing unexpected */
            }  /* end multiple parents */

          else if( (cc_rc == FSCK_OK) && (this_inorec->crrct_prnt_inonum) )  {  /*
                                    * a single parent but not the one
                                    * named in the implied '..' entry
                                    */
            cc_rc = display_paths( ino_idx, this_inorec, msg_info_ptr );

            if( agg_recptr->processing_readwrite ) {  /* we can fix this */
              msgprms[0] = message_parm_0;
              msgprmidx[0] = msg_info_ptr->msg_inopfx;
              sprintf( message_parm_1, "%ld", msg_info_ptr->msg_inonum );
              msgprms[1] = message_parm_1;
              msgprmidx[1] = 0;
              fsck_send_msg( fsck_WILLFIXINCREF, 0, 2 );
              }  /* end we can fix this */
            else {       /* we don't have write access */
              this_inorec->crrct_prnt_inonum = 0;
              agg_recptr->ag_dirty = 1;
              msgprms[0] = message_parm_0;
              msgprmidx[0] = msg_info_ptr->msg_inopfx;
              sprintf( message_parm_1, "%ld", msg_info_ptr->msg_inonum );
              msgprms[1] = message_parm_1;
              msgprmidx[1] = 0;
              fsck_send_msg( fsck_INCINOREF, 0, 2 );
              }  /* end we don't have write access */
            }  /* end a single parent but not the one named....  */
          }  /* end else still connected */
        }  /* end nothing fatal */
      }  /* end inode in use and not selected to release  */

    if( cc_rc == FSCK_OK ) {
      cc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec );
      }
    }  /* end while */

  return( cc_rc );
}                              /* end of check_connectedness ()  */
Example #9
0
/*
 * NAME:        moveWords()
 *
 * FUNCTION:    moves nwords from buffer pool to target. data
 *              is moved in backwards direction starting at offset.
 *              If partial log record is on the previous page,
 *              or we have exhaust the current page (all bytes were read),
 *              the previous page is read into the buffer pool.
 *              On exit buf will point to this page in the buffer pool
 *              and offset to where the move stopped.
 *
 *              Note: the previous page is fetched whenever
 *              the current page is exhausted (all bytes were read)
 *              even if all the words required to satisfy this move
 *              are on the current page.
 *
 * PARAMETERS:  nwords  - number of 4-byte words to move
 *              target  - address of target (begin address)
 *              buf     - index in buffer pool of current page
 *              offset  - initial offset in buffer pool page, this offset
 *                        includes the page head size
 *
 * RETURNS:     = 0             - ok
 *              < 0             - error returned from getLogpage
 */
int32
moveWords(
int32  nwords,  /* number of 4-byte words to move */
int32 *target,  /* address of target (begin address) */
int32 *buf,     /* index in buffer pool of current page */
int32 *offset)  /* initial offset in buffer pool page */
{
        int n,j,words,pno;
        int * ptr;

        j = (*offset - LOGPHDRSIZE)/4 - 1; /* index in log page data area
                                               of first word to move      */
        words  = min(nwords,j + 1);  /* words on this page to move */
        ptr = target + nwords - 1; /* last word of target */
        for (n = 0; n < words; n++)
        {
                *ptr = logp[*buf].data[j];
                j = j - 1;
                ptr = ptr - 1;
        }
        *offset = *offset - 4*words;

        /*
         * If partial log record is on the previous page,
         * or we have read all the log records in the current page,
         * get the previous page
         */

        if ( words != nwords    /* we get less than nwords */
              || j < 0)         /* or exhaust the page, so offset is just */
                                /* the page head, then j < 0              */
        {
                /* get previous page */
                pno = logptr[*buf];
                pno = pno - 1;
                /* if we hit beginning location of the log, go wrapped,
                   read log record from the end location of the log   */
                if (pno == 1) pno = logsize - 1;
                *buf  = getLogpage(pno);
                if (*buf < 0) {
                        sprintf( message_parm_0, "(d) %d", pno  );
                        msgprms[0] = message_parm_0;
                        msgprmidx[0] = 0;
                        sprintf( message_parm_1, "(d) %d", (*buf)  );
                        msgprms[1] = message_parm_1;
                        msgprmidx[1] = 0;
                        fsck_send_msg( lrdo_MWREADFAIL, 0, 2 );

                        return(*buf);
                }
                *offset = LOGPSIZE - LOGPTLRSIZE;
                j = LOGPSIZE/4 - 4 - 1; /* index last word of data area */
                /* move rest of nwords if any. this will never
                exhaust the page.                          */
                for (n = 0; n < nwords - words ; n++) {
                        *ptr = logp[*buf].data[j];
                        j = j - 1;
                        ptr = ptr - 1;
                }
                *offset = *offset - 4*(nwords - words);
        }

        return(0);
}
Example #10
0
 /*
 * NAME:        logRead(logaddr , ld, dataptr)
 *
 * FUNCTION:    reads the log record addressed by logaddr and
 *              returns the address of the preceding log record.
 *
 * PARAMETERS:  logaddr -  address of the end of log record to read
 *                                 Note: log is read backward, so this is
 *                                 the address starting to read
 *              ld      - pointer to a log record descriptor
 *              dataptr - pointer to data buffer
 *
 * RETURNS:     < 0     - there is an i/o error in reading
 *              > 0     - the address of the end of the preceding log record
 */
logRead(
int32    logaddr,       /* address of log record to read */
struct lrd *ld,  /* pointer to a log record descriptor */
char    * dataptr)    /* pointer to buffer.  LOGPSIZE long */
{
        int buf,off,rc,nwords, pno;

        /* get page containing logaddr into log buffer pool
         */
        pno = BTOLOGPN(logaddr);
        if (pno != loglastp)
        {
                loglastp = pno;
                lognumread += 1;
                if (lognumread > logsize - 2)
                {
                        logError(LOGWRAP,0);

                        sprintf( message_parm_0, "(d) %d", lognumread  );
                        msgprms[0] = message_parm_0;
                        msgprmidx[0] = 0;
                        fsck_send_msg( lrdo_LRLOGWRAP, 0, 1 );

                        return(JLOG_LOGWRAP);
                }
        }

        buf = getLogpage(pno);
        if (buf < 0)
        {
                sprintf( message_parm_0, "(d) %d", pno  );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = 0;
                sprintf( message_parm_1, "(d) %d", buf  );
                msgprms[1] = message_parm_1;
                msgprmidx[1] = 0;
                fsck_send_msg( lrdo_LRREADFAIL, 0, 2 );

                return(buf);
        }

        /* read the descriptor */
        off = logaddr & (LOGPSIZE - 1) ;  /* offset just past desc. */
        rc = moveWords(LOGRDSIZE/4, (int32 *)ld, &buf, &off);
        if (rc < 0)
        {
                sprintf( message_parm_0, "(d) %d", rc  );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = 0;
                fsck_send_msg( lrdo_LRMWFAIL1, 0, 1 );
                return(rc);
        }

        /* read the data if there is any */
        if (ld->length > 0)
        {
                if( ld->length > LOGPSIZE ) {                         /* @D1 */
                      rc = READLOGERROR;                              /* @D1 */
                      sprintf( message_parm_0, "(d) %d", pno  );      /* @D1 */
                      msgprms[0] = message_parm_0;                    /* @D1 */
                      msgprmidx[0] = 0;                               /* @D1 */
                      fsck_send_msg( lrdo_LRMWFAIL3, 0, 1 );          /* @D1 */
                      return(rc);                                     /* @D1 */
                      }                                               /* @D1 */

                nwords = (ld->length + 3)/4; /* if length is partial word, still
                                                read it   */
                rc = moveWords(nwords,(int32 *)dataptr,&buf,&off);
                if (rc < 0)
                {
                        sprintf( message_parm_0, "(d) %d", rc  );
                        msgprms[0] = message_parm_0;
                        msgprmidx[0] = 0;
                        fsck_send_msg( lrdo_LRMWFAIL2, 0, 1 );
                        return(rc);
                }
        }

        return(LOGPNTOB(logptr[buf]) + off);
}
Example #11
0
/*
 * NAME:        setLogpage(pno, eor, pmax, buf)
 *
 * FUNCTION:    Forms consistent log page and returns eor and pmax values.
 *
 *              During the first release the following conditions are
 *              assumed:
 *              1) No corrupted write during power failure
 *              2) No split write
 *              3) No out-of-order sector write
 *
 *              If the header and trailer in the page are not equal, a
 *              system crash happened during this page write. It
 *              is reconciled as follows:
 *
 *              1) if h.page != t.page, the smaller value is taken and
 *                 the eor fields set to LOGPHDSIZE.
 *                 reason: This can happen when a old page is over-written
 *                 by a new page and the system crashed. So this page
 *                 should be considered not written.
 *              2) if h.eor != t.eor, the smaller value is taken.
 *                 reason: The last log page was rewritten for each
 *                 commit record. A system crash happened during the
 *                 page rewriting. Since we assume that no corrupted write
 *                 no split write and out-of-order sector write, the
 *                 previous successfuly writing is still good
 *              3) if no record ends on the page (eor = 8), still return it.
 *                 Let the caller determine whether a) a good long log record
 *                 ends on the next log page. or b) it is the first page of the
 *                 last long log record and system was crashed when its second
 *                 page is written.
 *
 *
 * RETURNS:     0                       - ok
 *              REFORMAT_ERROR(-3)      - I/O error, reformat log
 *              MAJOR_ERROR(-2)         - other major error
 */
setLogpage(int32 pno,   /* page number of log           */
        int32 *eor,     /* log header eor to return     */
        int32 *pmax,    /* log header page number to return */
        int32 buf)      /* logp[] index number for page */
{
        int32 diff1, diff2, rc;
        unsigned long  actual;

        /* check that header and trailer are the same
         */
        if ((diff1 = (logp[buf].h.page - logp[buf].t.page)) != 0)
        {       if (diff1 > 0)
                        logp[buf].h.page = logp[buf].t.page;
                else
                        logp[buf].t.page = logp[buf].h.page;

                logp[buf].h.eor = logp[buf].t.eor = LOGPHDRSIZE;
                                                /* empty page */
        }

        if ((diff2 = (logp[buf].h.eor - logp[buf].t.eor)) != 0)
        {       if (diff2 > 0)
                        logp[buf].h.eor = logp[buf].t.eor;
                else
                        logp[buf].t.eor = logp[buf].h.eor;

        }

        /* if any difference write the page out
         */
        if (diff1 || diff2)
        {
                rc = ujfs_rw_diskblocks(logfd,
                        (uint64)(vopen[logminor].logxaddr+LOGPNTOB(pno)),
                                        (unsigned long)LOGPSIZE,
                                        (char *)&logp[buf],
                                        PUT);
                if ( rc != 0 )
                {
                        sprintf( message_parm_0, "(d) %d", pno  );
                        msgprms[0] = message_parm_0;
                        msgprmidx[0] = 0;
                        sprintf( message_parm_1, "(d) %d", rc  );
                        msgprms[1] = message_parm_1;
                        msgprmidx[1] = 0;
                        fsck_send_msg( lrdo_SLPWRITEFAIL, 0, 2 );

                        return(JLOG_WRITEERROR1);
                }
        }

        /*
         * At this point, it is still possible that logp[buf].h.eor
         * is LOGPHDRSIZE, but we return it anyway. The caller will make
         * decision.
         */

        *eor = logp[buf].h.eor;
        *pmax = logp[buf].h.page;

        return (0);
}
Example #12
0
/*
 * NAME:        findEndOfLog()
 *
 * FUNCTION:    Returns the address of the end of the last record in the log.
 *              (i.e. the address of the byte following its descriptor).
 *
 *        Note: At the first release, log page is not written in a ping pong
 *              manner, so the logend is the binary search result
 *
 *              The end of the log is found by finding the page with the
 *              highest page number and for which h.eor == t.eor and
 *              h.eor > 8 (i.e. a record ends on the page).
 *              Page numbers are compared by comparing their difference
 *              with zero (necessary because page numbers are allowed to wrap.)
 *
 * RETURNS:     >0              - byte offset of last record
 *              REFORMAT_ERROR(-3)      - i/o error, reformat the log
 *              MAJOR_ERROR(-2) - other major errors other than EIO.
 */
int32
findEndOfLog()
{

        int32   left, right, pmax, pval, eormax, eorval, k, rc;

        /* binary search for logend
         */
        left = 2;               /* first page containing log records
                                   since page 0 is never used, page 1 is
                                   log superblock */
        right = logsize - 1;    /* last page containing log records */

        if ((rc = pageVal(left, &eormax, &pmax)) < 0)
        {
                sprintf( message_parm_0, "(d) %d", rc  );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = 0;
                fsck_send_msg( lrdo_FEOLPGV1FAIL, 0, 1 );
                return(rc);
        }

        while ((right - left) > 1)
        {
                k = (left + right ) >> 1;
                if ((rc = pageVal(k, &eorval, &pval)) < 0)
                {
                        sprintf( message_parm_0, "(d) %d", rc  );
                        msgprms[0] = message_parm_0;
                        msgprmidx[0] = 0;
                        fsck_send_msg( lrdo_FEOLPGV2FAIL, 0, 1 );
                        return(rc);
                }

                if (pval - pmax > 0 )
                {       left = k;
                        pmax = pval;
                        eormax = eorval;
                }
                else
                        right = k;
        }
        if ((rc = pageVal(right, &eorval, &pval)) < 0)
        {
                sprintf( message_parm_0, "(d) %d", rc  );
                msgprms[0] = message_parm_0;
                msgprmidx[0] = 0;
                fsck_send_msg( lrdo_FEOLPGV3FAIL, 0, 1 );
                return(rc);
        }

        /*
         * the last thing to determine is whether it is the first page of
         * the last long log record and system was crashed when its second
         * page is written. If the eor of the chosen page is LOGPHDRSIZE,
         * then this page contains a partial log record, ( otherwise, the
         * the long log record's second page should be chosen ).
         * This page should be thrown away. its previous page will be
         * the real last log page.
         */

        if (( pval - pmax ) > 0 )
        {
                if (eorval == LOGPHDRSIZE )
                {
                        if ((rc = pageVal(right-1, &eorval, &pval)) < 0)
                        {
                           sprintf( message_parm_0, "(d) %d", rc  );
                           msgprms[0] = message_parm_0;
                           msgprmidx[0] = 0;
                           fsck_send_msg( lrdo_FEOLPGV4FAIL, 0, 1 );
                           return(rc);
                        }
                        return(LOGPNTOB(right-1) + eorval);
                } else
                        return(LOGPNTOB(right) + eorval);
        }
        else  /* pmax will be returned */
        {
                if ( eormax == LOGPHDRSIZE )
                {
                        left = (left == 2) ? logsize -1 : left - 1;
                        if ((rc = pageVal(left, &eormax, &pmax)) < 0)
                        {
                           sprintf( message_parm_0, "(d) %d", rc  );
                           msgprms[0] = message_parm_0;
                           msgprmidx[0] = 0;
                           fsck_send_msg( lrdo_FEOLPGV4AFAIL, 0, 1 );
                           return(rc);
                        }
                }
                return(LOGPNTOB(left) + eormax);
        }

}
Example #13
0
/******************************************************************
 * NAME: 	get_LVM_BadBlockList_count
 *
 * FUNCTION: 	Query the LVM for the number of tables composing) its bad
 *		block list for the file system.
 *
 * PARAMETERS:	none
 *
 * NOTES:
 *
 * RETURNS:
 *      success: 0
 *      failure: something else
 */
int32 get_LVM_BadBlockList_count( int32 *list_count )
{
    int32 glbblc_rc = 0;
	
    DDI_OS2LVM_param LVMpp;
    DDI_OS2LVM_param *pLVMpp = &LVMpp;
    DDI_OS2LVM_data LVMdp;
    DDI_OS2LVM_data *pLVMdp = &LVMdp;
    ULONG ppLen = 0;
    ULONG dpLen = 0;
    int32 		min_bufsize;
    int32 		bufsize = 1024;
    char 		*bufptr = NULL;
    BadBlockInfo	*BB_bufptr = NULL;
    BadBlockTableInfo 	*BBT_bufptr = NULL;
    int32 		tablesize;
    RelocationTable	*RTable = NULL;
    int32       alloc_rc = 0;
    int          I_am_logredo = 0;
	
	/*
	 * initialize the LVM DosDevIOCtl parm and data packets
	 */
    pLVMpp->Command = 0;
    pLVMpp->DriveUnit = 0;
    pLVMpp->TableNumber = 0;
    pLVMpp->LSN = 0;
    pLVMdp->ReturnData = 0;
    pLVMdp->UserBuffer = NULL;
	
	/*
	 * allocate a buffer
	 */
    alloc_rc = alloc_wrksp( bufsize, dynstg_fsckcbblbuf2,
                                     I_am_logredo, (void **) &bufptr );
    if( (bufptr == NULL) || (alloc_rc != FSCK_OK) ) {
	return( FSCK_ENOMEMBDBLK1 );
	}
	
	/*
	 * ask the LVM how many bad block lists it has for the filesystem
	 */
    pLVMpp->Command = GET_BBR_INFO;
    pLVMdp->UserBuffer = bufptr;
    glbblc_rc = DosDevIOCtl( Dev_IOPort,	IOC_DC,	
			    IODC_LV,		(void *) pLVMpp,	
			    sizeof(DDI_OS2LVM_param),
			    &ppLen,		(void *) pLVMdp,	
			    sizeof(DDI_OS2LVM_data),		&dpLen
			    );	
    sprintf( message_parm_0, "%ld", glbblc_rc );
    msgprms[0] = message_parm_0;
    msgprmidx[0] = 0;
    fsck_send_msg( fsck_LVMGETBBLKINFORC, 0, 1 );
	
    if( glbblc_rc != 0 ) {
	return( glbblc_rc );
	}
    else {  /* DosDevIOCtl successful */
	if( pLVMdp->ReturnData != BBR_SUCCESS ) {	/* cat 8, funct 69 failed */
	    glbblc_rc = pLVMdp->ReturnData;
	    }
	else {
	    BB_bufptr = (BadBlockInfo *) bufptr;
	    *list_count = BB_bufptr->TotalTables;
	
	    sprintf( message_parm_0, "%ld", BB_bufptr->TotalTables );
	    msgprms[0] = message_parm_0;
	    msgprmidx[0] = 0;
	    fsck_send_msg( fsck_CLRBBLVMNUMLISTS, 0, 1 );
	    }
	}  /* end else DosDevIOCtl successful */
				
    return( glbblc_rc );
}				/* end get_LVM_BadBlockList_count() */
Example #14
0
/******************************************************************
 * NAME: 	examine_LVM_BadBlockLists
 *
 * FUNCTION: 	Query the LVM for (the set of tables composing) its bad
 *		block list for the file system.  Save the buffers containing
 *		the tables for use populating the JFS Bad Block Inode later.
 *
 * PARAMETERS:	none
 *
 * NOTES:
 *
 * RETURNS:
 *      success: 0
 *      failure: something else
 */
int32 examine_LVM_BadBlockLists( int32 list_count, int32 *max_fill_level )
{
    int32 elbbl_rc = 0;
    int8  buffer_allocated = 0;
    int32 bbl_idx;
    DDI_OS2LVM_param LVMpp;
    DDI_OS2LVM_param *pLVMpp = &LVMpp;
    DDI_OS2LVM_data LVMdp;
    DDI_OS2LVM_data *pLVMdp = &LVMdp;
    ULONG ppLen = 0;
    ULONG dpLen = 0;
    int32 		bufsize = 1024;
    char 		*bufptr = NULL;
    BadBlockTableInfo 	*BBT_bufptr = NULL;
    int32 		num_entries, max_entries;
    int32			this_percent, highest_percent = 0;
    int32       alloc_rc = 0;
    int          I_am_logredo = 0;
	
	/*
	 * initialize the LVM DosDevIOCtl parm and data packets
	 */
    pLVMpp->Command = 0;
    pLVMpp->DriveUnit = 0;
    pLVMpp->TableNumber = 0;
    pLVMpp->LSN = 0;
    pLVMdp->ReturnData = 0;
    pLVMdp->UserBuffer = NULL;
				
	/*
	 * allocate a buffer
	 */
    alloc_rc = alloc_wrksp( bufsize, dynstg_fsckcbblbuf1,
                                     I_am_logredo, (void **) &bufptr );
    if( (bufptr == NULL) || (alloc_rc != FSCK_OK) ) {
      elbbl_rc = FSCK_ENOMEMBDBLK2;
    }
    else {
      buffer_allocated = -1;
      }
	/*
	 *
	 * get info about each of the LVM Bad Block Tables
	 *
	 */
    for( bbl_idx = 0;
	 ( (bbl_idx < list_count) && (elbbl_rc == 0) );
	 bbl_idx++ ) {
		/*
		 * ask the LVM how big this table is.
		 */
	pLVMpp->Command = GET_TBL_SIZE;
	pLVMpp->TableNumber = bbl_idx;
	pLVMdp->ReturnData = 0;
	pLVMdp->UserBuffer = bufptr;
	elbbl_rc =
		DosDevIOCtl( Dev_IOPort,	IOC_DC,	
			     IODC_LV,		(void *) pLVMpp,	
			     sizeof(DDI_OS2LVM_param),
			     &ppLen,		(void *) pLVMdp,	
			     sizeof(DDI_OS2LVM_data),		&dpLen	
			    );	
          sprintf( message_parm_0, "%ld", elbbl_rc );
          msgprms[0] = message_parm_0;
          msgprmidx[0] = 0;
          fsck_send_msg( fsck_LVMGETTBLSIZERC, 0, 1 );
	
	if( elbbl_rc == 0 ) {  /* DosDevIOCtl successful */
	    if( pLVMdp->ReturnData != BBR_SUCCESS ) { /* cat 8, funct 69 failed */
		elbbl_rc = pLVMdp->ReturnData;
		break;
		}
	    else {
		BBT_bufptr = (BadBlockTableInfo *) bufptr;
		num_entries = BBT_bufptr->ActiveRelocations;
		max_entries = BBT_bufptr->MaxRelocationsAllowed;
	
		sprintf( message_parm_0, "%ld", bbl_idx );
		msgprms[0] = message_parm_0;
		msgprmidx[0] = 0;
		sprintf( message_parm_1, "%ld", max_entries );
		msgprms[1] = message_parm_1;
		msgprmidx[1] = 0;
		sprintf( message_parm_2, "%ld", num_entries );
		msgprms[2] = message_parm_2;
		msgprmidx[2] = 0;
		fsck_send_msg( fsck_CLRBBLVMLISTDATA, 0, 3 );
		}
	    }  /* end else DosDevIOCtl successful */
	
		/*
		 *
		 * If the table isn't empty
		 *
		 */
	if( (elbbl_rc == 0) && (num_entries > 0) && (max_entries > 0)) {  /*
				* successful so far and the
				* current table isn't empty
				*/
               this_percent = (num_entries * 100) / max_entries;
               if( this_percent > highest_percent ) {
                 highest_percent = this_percent;
                 }
	    }  /* end successful so far and table not empty */	
	}  /* end for bbl_idx */
			
	/*
	 * free the buffer
	 */
	
    if( elbbl_rc == 0 ) {
      *max_fill_level = highest_percent;
      }
    else {
      *max_fill_level = 0;
      }
	
    return( elbbl_rc );
}				/* end examine_LVM_BadBlockLists() */
Example #15
0
/*****************************************************************************
 * NAME: ClrBdBlkLst_processing
 *
 * FUNCTION:  Invoke the JFS processing to clear the LVM's bad block list.
 *
 * PARAMETERS:  none
 *
 * NOTES:	Starts a child process for the utility.
 *
 * RETURNS:
 *      success: FSCK_OK
 *      failure: something else
 */
retcode_t ClrBdBlkLst_processing ( )
{
  retcode_t kcbbl_rc = FSCK_OK;
  retcode_t intermed_rc = FSCK_OK;
  retcode_t redeterm_rc = FSCK_OK;             //PS21032004
  struct fsckcbbl_record  *cbblrecptr;
  int I_am_logredo = 0;
	
  cbblrecptr = &(agg_recptr->blkmp_ctlptr->cbblrec);
  if( cbblrecptr == NULL ) {	
    if( agg_recptr->blkmp_ctlptr == NULL ) {
      intermed_rc = alloc_wrksp( sizeof(fsck_blk_map_hdr_t),
                                            dynstg_blkmap_hdr, I_am_logredo,	
                                            (void **) &(agg_recptr->blkmp_ctlptr) );
      if( intermed_rc == FSCK_OK ) {
        strncpy( agg_recptr->blkmp_ctlptr->hdr.eyecatcher,
		fbmh_eyecatcher_string,
		strlen(fbmh_eyecatcher_string));  /* fill eyecatcher */
        }
      }
    intermed_rc = blkmap_get_ctl_page ( agg_recptr->blkmp_ctlptr );
    if( intermed_rc == FSCK_OK ) {
      cbblrecptr = &(agg_recptr->blkmp_ctlptr->cbblrec);
      }
    }
  if( cbblrecptr != NULL ) {	
    memcpy( (void *) &(cbblrecptr->eyecatcher), (void *) "*unset**", 8 );
    intermed_rc = blkmap_put_ctl_page ( agg_recptr->blkmp_ctlptr );
    }
	
  fsck_send_msg( fsck_LVMFSNOWAVAIL, 0, 0 );
  fsck_send_msg( fsck_LVMTRNSBBLKSTOJFS, 0, 0 );

	/*
	 * close the file system so clrbblks can get it
	 */
//PS24072004  close_volume();
	
//PS21032004  kcbbl_rc = exec_clrbdblks( );
//PS21032004 Begin
      redeterm_rc = ujfs_redeterminemedia( Dev_IOPort );

      sprintf( message_parm_0, "%ld", redeterm_rc );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      fsck_send_msg( fsck_DEVREDETERMRC, 0, 1 );

      kcbbl_rc = clrbblks( 0, 0, Dev_IOPort, Vol_Label);

      if(( !agg_recptr->parm_options[UFS_CHKDSK_AUTOCHECK] ) &&
         ( !agg_recptr->parm_options[UFS_CHKDSK_CLRBDBLKLST] ))
         {
//          beginformat called unmount -> flush the JFS cache.
        redeterm_rc = ujfs_beginformat( Dev_IOPort );
        sprintf( message_parm_0, "%ld", redeterm_rc );
        msgprms[0] = message_parm_0;
        msgprmidx[0] = 0;
        fsck_send_msg( fsck_DEVBEGINFMTRC, 0, 1 );
     }
	/*
	 * open the file system and get the clrbblks
	 * communication area
	 */
//PS21032004 End
//PS21032004
  open_volume( Vol_Label );
  intermed_rc = blkmap_get_ctl_page ( agg_recptr->blkmp_ctlptr );
  if( intermed_rc == FSCK_OK ) {
    if( memcmp((void *)&(cbblrecptr->eyecatcher),(void *)"*unset**", 8) != 0 ) {
	/*
	 * The eyecatcher field was reset.  there is good reason to
	 * believe that clrbblks processing did actually write to the
	 * record.
	 */
      sprintf( message_parm_0, "%ld", cbblrecptr->cbbl_retcode );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      fsck_send_msg( fsck_CLRBBLKSRC, 0, 1 );
	
      sprintf( message_parm_0, "%ld", cbblrecptr->LVM_lists );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      fsck_send_msg( fsck_CLRBBLVMNUMLISTS, 0, 1 );
	
      sprintf( message_parm_0, "%lld", (cbblrecptr->fs_last_metablk+1) );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      sprintf( message_parm_1, "%lld", (cbblrecptr->fs_first_wspblk-1) );
      msgprms[1] = message_parm_1;
      msgprmidx[1] = 0;
      fsck_send_msg( fsck_CLRBBRANGE, 0, 2 );
	
      sprintf( message_parm_0, "%ld", cbblrecptr->reloc_extents );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      sprintf( message_parm_1, "%ld", cbblrecptr->reloc_blocks );
      msgprms[1] = message_parm_1;
      msgprmidx[1] = 0;
      fsck_send_msg( fsck_CLRBBACTIVITY, 0, 2 );
	
      sprintf( message_parm_0, "%ld", cbblrecptr->total_bad_blocks );
      msgprms[0] = message_parm_0;
      msgprmidx[0] = 0;
      sprintf( message_parm_1, "%ld", cbblrecptr->resolved_blocks );
      msgprms[1] = message_parm_1;
      msgprmidx[1] = 0;
      fsck_send_msg( fsck_CLRBBRESULTS, 0, 2 );
      }
    }
	
  return( kcbbl_rc );
}                            /* end of ClrBdBlkLst_processing()  */