[alt.sources] Bugfix/Questions re fsanalyze

paddock@mybest.UUCP (Steve Paddock) (01/24/88)

I'm not at all sure, but I suspect that I have found a bug in
fsanalyze, recently posted to comp.sources.misc.  

To demonstrate the bug, mkfs a file system where the gap cyl
information is specified on the command line; in specific, for a 
CDC Wren II in a 3B2 this is 9 162, representing interblock gap
of 9 x 512 byte blocks and 162 blocks/cylinder.

Copy two files onto this new partition, at least one large, unmount it 
and run fsanalyze on the partition.  Fsanalyze will show each file
to be 100% fragmented.  Given that the free list was just created,
optimized for the parameters given, this is not an expected outcome.
(See man dcopy, fsck, mkfs).

As a further example cpio a directory structure onto a newly created
file system.  Fsanalyze will show 100% fragmentation.  If we use fsdb,
we see that in fact, the blocks of the file are (in general) 
evenly placed placed at GAP separation where GAP is the 
value entered in mkfs expressed in physical blocks, in this specific case 
9/2 for a file system with 1024 byte blocks on the disk.

I modified a beta version of fsanalyze to display the offset between
the value the program expected in order to not find fragmentation and
the values found.  Adjusting for the interblock gap and bytes per
cylinder caused the variance to approximate 0.  This would have been
closer if the gap was an even number.

A test of a modified fsanalyze yielded 8.23% fragmentation on a newly 
created file system, as opposed to 100% from the stock program.

I enclose a context diff which includes GAP and CYL as defines, and
adjusts for them in calculating whether a fragement exists.  A more
refined approach would be to either find that info in the superblock
(it is there; fsck -s accesses it, as does dcopy)  or to accept
them as a command line parameter.  I just deal with one kind of disk, so
this works for me.  I embodied Larry Cipriani's patch #1 in this code.

I'm not claiming wizard status, and arrived at my answers and code
empirically; if it's wrong please explain by posting or mail if you prefer.
Sarcasm, save for Santa Claus.

I also added simple code to print the nodename and pass the 
top ten malefactors as arguments, along with the device name, 
to ncheck, to print out the names of the highly fragmented files, 
using a -n option.  This is included in the patch below as well.

Steve Paddock (ut-emx!mybest!paddock or uunet!bigtex!helps!mybest!paddock)
512-477-9736 Best Printing Co,  Austin, Texas  78767

-----------------------------------------CUT HERE----------

*** fsanalyze.c
--- fsanalyze.c.or
**************
*** 77,89
  
  # define BLK_SIZE	512		/* block size */
  # define IBLK 		2		/* block number of first i-node */
- # define GAP		5		/* ideal block gap for disk
- 					 * 5 for CDC WrenII 72MB
- 					 * test on a new clean f/s...
- 					*/
- # define CYL		-81		/* cylinder leap
- 					 * -81 for CDC WrenII 72MB
- 					*/
  
  # define I_BLOCK_FACTOR	32		/* number of i-nodes per block */
  
--- 77,82 -----
  
  # define BLK_SIZE	512		/* block size */
  # define IBLK 		2		/* block number of first i-node */
  
  # define I_BLOCK_FACTOR	32		/* number of i-nodes per block */
  
**************
*** 91,96
   * file mode definitions
   */
  # define FILE_TYPE(a) 	((a)->di_mode & S_IFMT)
  
  /* Larry Cipriani's patch applied to line below */
  
--- 84,90 -----
   * file mode definitions
   */
  # define FILE_TYPE(a) 	((a)->di_mode & S_IFMT)
+ # define IS_SPECIAL(a)	(((a) & S_IFMT == S_IFBLK) || ((a) & S_IFMT == S_IFCHR) || ((a) & S_IFMT == S_IFIFO))
  
  /*
   * basic definitions
**************
*** 92,101
   */
  # define FILE_TYPE(a) 	((a)->di_mode & S_IFMT)
  
- /* Larry Cipriani's patch applied to line below */
- 
- # define IS_SPECIAL(a)	((((a) & S_IFMT) == S_IFBLK) || (((a) & S_IFMT) == S_IFCHR) || (((a) & S_IFMT) == S_IFIFO))
- 
  /*
   * basic definitions
   */
--- 86,91 -----
  # define FILE_TYPE(a) 	((a)->di_mode & S_IFMT)
  # define IS_SPECIAL(a)	(((a) & S_IFMT == S_IFBLK) || ((a) & S_IFMT == S_IFCHR) || ((a) & S_IFMT == S_IFIFO))
  
  /*
   * basic definitions
   */
**************
*** 166,172
  					 * examined */
  boolean override	 = FALSE;	/* override bad fs test */
  
- boolean ncheck		 = FALSE;	/* show file names using ncheck */
  
  
  /*
--- 156,161 -----
  					 * examined */
  boolean override	 = FALSE;	/* override bad fs test */
  
  
  /*
   * interface to system error messages
**************
*** 168,174
  
  boolean ncheck		 = FALSE;	/* show file names using ncheck */
  
- 
  /*
   * interface to system error messages
   */
--- 157,162 -----
  boolean override	 = FALSE;	/* override bad fs test */
  
  
  /*
   * interface to system error messages
   */
**************
*** 182,188
   */
  void usage(){
  	printf ("File System analyzer - v2.01\n");
! 	printf ("Usage:\n   fsan [-[deino]] special [file] ...\n");
  	printf ("\n\tIf the [file] argument(s) are missing, the entire\n");
  	printf ("\tfile system is scanned.  Otherwise, only the specified\n");
  	printf ("\tfiles are examined.  Valid flag are:\n\n");
--- 170,176 -----
   */
  void usage(){
  	printf ("File System analyzer - v2.01\n");
! 	printf ("Usage:\n   fsanalyze [-[deio]] special [file] ...\n");
  	printf ("\n\tIf the [file] argument(s) are missing, the entire\n");
  	printf ("\tfile system is scanned.  Otherwise, only the specified\n");
  	printf ("\tfiles are examined.  Valid flag are:\n\n");
**************
*** 189,195
  	printf ("\td\tdisplay i-node numbers as they are examined\n");
  	printf ("\te\treport file size inconsistencies\n");
  	printf ("\ti\treport data block double and triple indirection\n");
- 	printf ("\tn\tcall ncheck on top 10 files\n");
  	printf ("\to\toverride error checking on file system argument\n");
  	exit(1);
  	}
--- 177,182 -----
  	printf ("\td\tdisplay i-node numbers as they are examined\n");
  	printf ("\te\treport file size inconsistencies\n");
  	printf ("\ti\treport data block double and triple indirection\n");
  	printf ("\to\toverride error checking on file system argument\n");
  	exit(1);
  	}
**************
*** 294,311
  						debug = TRUE;
  						break;
  
! 					/* override bad fs test */
! 				case 'o':
! 					override = TRUE;
! 					break;
! 
! 					/* call ncheck on top ten */
! 				case 'n':
! 					ncheck = TRUE;
! 					break;
! 				default:
! 					fprintf (stderr, "illegal option : %c\n", *cp);
! 					usage();
  					}
  				}
  			}
--- 281,293 -----
  						debug = TRUE;
  						break;
  
! 						/* override bad fs test */
! 					case 'o':
! 						override = TRUE;
! 						break;
! 					default:
! 						fprintf (stderr, "illegal option : %c\n", *cp);
! 						usage();
  					}
  				}
  			}
**************
*** 435,441
  		data->data_blocks++;
  		data->total_blocks++;
  		data->potential_seeks++;
! 		if (new_pos != pos + GAP && new_pos != pos + CYL - GAP ){
  			data->seeks++;
  			}
  		pos = new_pos;
--- 417,423 -----
  		data->data_blocks++;
  		data->total_blocks++;
  		data->potential_seeks++;
! 		if (new_pos != pos + 1){
  			data->seeks++;
  			}
  		pos = new_pos;
**************
*** 466,472
  	 * data blocks
  	 */
  	data->potential_seeks++;
! 	if (block != cur_pos + GAP && block != cur_pos + CYL - GAP ){
  		data->seeks++;
  		}
  
--- 448,454 -----
  	 * data blocks
  	 */
  	data->potential_seeks++;
! 	if (block != cur_pos + 1){
  		data->seeks++;
  		}
  
**************
*** 522,528
  	 * data blocks
  	 */
  	data->potential_seeks++;
! 	if (block != cur_pos + GAP && block != cur_pos + CYL - GAP ){
  		data->seeks++;
  		}
  
--- 504,510 -----
  	 * data blocks
  	 */
  	data->potential_seeks++;
! 	if (block != cur_pos + 1){
  		data->seeks++;
  		}
  
**************
*** 600,606
  		data->data_blocks++;
  		data->total_blocks++;
  		data->potential_seeks++;
! 		if (new_pos != pos + GAP && new_pos != pos + CYL - GAP ){	/* out of sequence ? */
  			data->seeks++;
  			}
  		pos = new_pos;
--- 582,588 -----
  		data->data_blocks++;
  		data->total_blocks++;
  		data->potential_seeks++;
! 		if (new_pos != pos + 1){	/* out of sequence ? */
  			data->seeks++;
  			}
  		pos = new_pos;
**************
*** 768,777
  						 * that have more than 10
  						 * blocks */
  
- 	int ncheckstat;				/* exit stat of fsstat */
- 	char nbuffer[256];			/* cmd line for fsstat */
- 	char obuffer[256];			/* cmd line for fsstat */
- 
  	/*
  	 * calculate percentages for report
  	 */
--- 750,755 -----
  						 * that have more than 10
  						 * blocks */
  
  	/*
  	 * calculate percentages for report
  	 */
**************
*** 787,797
  	/*
  	 * print out report
  	 */
! 	printf("\n\n");
! 	fflush(stdout);
! 	sprintf (obuffer, "echo Node: `/bin/uname -a`");
! 	system (obuffer);
! 	printf ("File system name = \"%.6s\", Volume name = \"%.6s\"\n",
  		super.s_fname, super.s_fpack);
  	printf ("File system logical block size = %d bytes\n", 512 * fs_type);
  	printf ("Volume Size = %ld blocks (%ld bytes)\n",
--- 765,771 -----
  	/*
  	 * print out report
  	 */
! 	printf ("\n\nFile system name = \"%.6s\", Volume name = \"%.6s\"\n",
  		super.s_fname, super.s_fpack);
  	printf ("File system logical block size = %d bytes\n", 512 * fs_type);
  	printf ("Volume Size = %ld blocks (%ld bytes)\n",
**************
*** 796,803
  	printf ("File system logical block size = %d bytes\n", 512 * fs_type);
  	printf ("Volume Size = %ld blocks (%ld bytes)\n",
  		super.s_fsize, super.s_fsize * 512L * fs_type);
! 	printf ("\t%d blocks reserved for super block and inodes\n", super.s_isize);
! 	printf ("\t%d blocks reserved for data\n", 
  		super.s_fsize - super.s_isize);
  	printf ("Total inodes = %d\n", num_inodes);
  	printf ("%.2f%% inodes used (%ld used, %ld free)\n", 
--- 770,777 -----
  	printf ("File system logical block size = %d bytes\n", 512 * fs_type);
  	printf ("Volume Size = %ld blocks (%ld bytes)\n",
  		super.s_fsize, super.s_fsize * 512L * fs_type);
! 	printf ("\t%u blocks reserved for super block and inodes\n", super.s_isize);
! 	printf ("\t%lu blocks reserved for data\n", 
  		super.s_fsize - super.s_isize);
  	printf ("Total inodes = %d\n", num_inodes);
  	printf ("%.2f%% inodes used (%ld used, %ld free)\n", 
**************
*** 833,841
  					file_log[i+5].fragm*100);
  				}
  			printf ("\n");
- 			fflush(stdout);
- 			
- 
  			}
  		else break;
  		}
--- 807,812 -----
  					file_log[i+5].fragm*100);
  				}
  			printf ("\n");
  			}
  		else break;
  		}
**************
*** 839,861
  			}
  		else break;
  		}
- 
- 	if (ncheck == TRUE){
- 	printf("\n\n");
- 	sprintf (nbuffer,"/etc/ncheck -i %6d %6d %6d %6d %6d %6d \
- %6d %6d %6d %6d, %s ", file_log[0].inode,
- 	file_log[1].inode,
- 	file_log[2].inode,
- 	file_log[3].inode,
- 	file_log[4].inode,
- 	file_log[5].inode,
- 	file_log[6].inode,
- 	file_log[7].inode,
- 	file_log[8].inode,
- 	file_log[9].inode,
- 	special);
- 	ncheckstat = system (nbuffer);
- 	}
  	}
  
  /*
--- 810,815 -----
  			}
  		else break;
  		}
  	}
  
  /*




-- 
Steve Paddock (ut-emx!mybest!paddock or uunet!bigtex!helps!mybest!paddock)