Thread: Trouble Updating Free Inodes Count on Ext2 FS

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    2

    Trouble Updating Free Inodes Count on Ext2 FS

    We're working on a tricky project and C is not my forte but we are trying to update the number of free inodes and blocks in an ext2 filesystem. These values are contained in the Super and Group Descriptor Blocks. The function that is causing problems gets the super block from an image of a floppy disk filesystem and creates a super block struct out of the buffer it is read into. That struct has an element called s_free_inodes_count that we are trying to update.

    When ever I run the code on my ubuntu (ext4) machine the program segfaults but on my teammates' machines it runs fine. There is not a lot of information online about this subject I'm not sure why it would be segfaulting, any advice would be greatly appreciated.

    The function that segfaults is below.
    Code:
    void decFreeInodes(int device) {
    	SUPER *superBlockPtr;
    	char *buffer;
    	getBlock(device, 1, buffer); //get super block from disk
    	superBlockPtr = (ext2_super_block *) buffer;
    	superBlockPtr->s_free_inodes_count--;    //SEGFAULTS HERE
    	putBlock(device, 1, buffer);  //write super block back to disk
    }//decFreeInodes
    Where getBlock and putBlock simply search to a block on the filesystem and read the block into a buffer as follows:
    Code:
    void getBlock(int device, int blockNum, char *buf) {
      printf("getting block: %d from device: %d\n", blockNum, dev);
      lseek( device, (long)(blockNum * BLOCK_SIZE), 0 );
      read( device, buf, BLOCK_SIZE);
    }//get block
    
    void putBlock(int device, int blockNum, char *buf) {
      printf("putting block %d to device %d\n", blockNum, dev);
      lseek(device, (long)(blockNum * BLOCK_SIZE), 0);
      write(device, buf, BLOCK_SIZE);
    }//put block

  2. #2
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Not really sure about the data types in your program but here are a few things I would look out for:

    1) superBlockPtr = (ext2_super_block *) buffer;

    Can you make this cast successfuly since superBlockPtr is of type SUPER* and buffer is of type ???

    2)If 1) is wrong then superBlockPtr->s_free_inodes_count--; can be explained because the pointer is not pointing anywhere valid when you are trying to do this.

  3. #3
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    Quote Originally Posted by scurtis View Post
    We're working on a tricky project and C is not my forte but we are trying to update the number of free inodes and blocks in an ext2 filesystem. These values are contained in the Super and Group Descriptor Blocks. The function that is causing problems gets the super block from an image of a floppy disk filesystem and creates a super block struct out of the buffer it is read into. That struct has an element called s_free_inodes_count that we are trying to update.

    When ever I run the code on my ubuntu (ext4) machine the program segfaults but on my teammates' machines it runs fine. There is not a lot of information online about this subject I'm not sure why it would be segfaulting, any advice would be greatly appreciated.

    The function that segfaults is below.
    Code:
    void decFreeInodes(int device) {
    	SUPER *superBlockPtr;
    	char *buffer;
    	getBlock(device, 1, buffer); //get super block from disk
    	superBlockPtr = (ext2_super_block *) buffer;
    	superBlockPtr->s_free_inodes_count--;    //SEGFAULTS HERE
    	putBlock(device, 1, buffer);  //write super block back to disk
    }//decFreeInodes
    Despite what you might think you can't simply assign a char pointer to a struct pointer (or whatever SUPER is unless its a void * or a char *) using the assignment operator (=).

    You will first need to allocate some space for superblockPTR to point to, then parse buffer and copy pieces of it into the SUPER struct members in the appropriate way

    Here is a short example (unchecked/typed here)
    Code:
    typedef struct super_ SUPER;
    
    struct super_ {
      long s_free_inodes_count;
      long address, offset;  /* just guessing i dont know what you have in here */
      ...
      ...
    };
    
    
    {
      SUPER * block;
      char * buffer;
      getBlock(device, 1, buffer);
      block = malloc(sizeof(*block));
      /* error checking */
      parseBlock(buffer,block); /* this function parses the parts of buffer and copies them into blocks
        members, i don't know how you would do this as I don't know what buffer looks like */
    ...
    ...
    /* destroy any malloc'd members*/
    /* now free what block was pointing to */
      free(block);
    }
    That is the idea, although really you should have getBlock call parseBlock and getBlock should return a pointer to a SUPER already containing the block, ...suprised it doesn't return anything

  4. #4
    Banned
    Join Date
    May 2007
    Location
    Berkeley, CA
    Posts
    329
    Quote Originally Posted by nonpuz View Post
    Despite what you might think you can't simply assign a char pointer to a struct pointer (or whatever SUPER is unless its a void * or a char *) using the assignment operator (=).

    You will first need to allocate some space for superblockPTR to point to, then parse buffer and copy pieces of it into the SUPER struct members in the appropriate way
    Depending on the situation, you could maybe do a "shallow copy".

    Code:
    #include <stdio.h>
    
    struct points
    {
      int x;
      int y;
    } euclidean;
    
    int main(void)
    {
      struct points polar;
      euclidean.x = 1;
      euclidean.y = 2;
    
      printf("Euclidean -->x: %d and y: %d\n" , euclidean.x, euclidean.y);
    
      polar = euclidean;
    
      printf("Polar -->x: %d and y: %d\n" , polar.x, polar.y);
    
      return 0;
    }
    [cd@localhost oakland]$ ./astruct
    Euclidean -->x: 1 and y: 2
    Polar -->x: 1 and y: 2
    [cd@localhost oakland]$

  5. #5
    Registered User
    Join Date
    Apr 2010
    Posts
    2
    Thanks for the responses,

    I was trying to make the code more understandable and didn't change the type of the superBlockPtr. The SUPER type is just the struct ext2_super_block type renamed.

    So what we are doing (and the strange part is that the same exact code works fine in other functions) is creating an ext2_super_block struct out of the char *buffer. By type casting the char *buffer to the ext2_super_block type it fills out the struct just fine.

    The ext2_super_block struct is from the standard library "linux/ext2_fs.h" and has the main elements:
    Code:
    struct ext2_super_block {
      u32  s_inodes_count;       // total number of inodes
      u32  s_blocks_count;       // total number of blocks   
      u32  s_free_blocks_count;  // current number of free blocks
      u32  s_free_inodes_count;  // current number of free inodes 
      u32  s_first_data_block;   // first data block in this group
      u32  s_blocks_per_group;   // 8192 blocks per group 
      //... many more non-essential fields
    }
    EDIT: Right after I posted this I was looking at the other places this code worked and I realized that the buffer needs to be a character array, having the buffer be a char *, I wasn't allocating space for the buffer when I read a block into it. Thanks again for the responses!

  6. #6
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    Quote Originally Posted by Overworked_PhD View Post
    Depending on the situation, you could maybe do a "shallow copy".

    Code:
    #include <stdio.h>
    
    struct points
    {
      int x;
      int y;
    } euclidean;
    
    int main(void)
    {
      struct points polar;
      euclidean.x = 1;
      euclidean.y = 2;
    
      printf("Euclidean -->x: %d and y: %d\n" , euclidean.x, euclidean.y);
    
      polar = euclidean;
    
      printf("Polar -->x: %d and y: %d\n" , polar.x, polar.y);
    
      return 0;
    }
    How does assigning one object of the same type to another object of the same type relate to trying to set a struct anything * to a char * ? The only time that is going to work successfully is if the first member in struct anything is a char *.


    EDIT @op: of course you can also cast explicitly to a certain pointer type if you simply want to access that data through a different type...which appears to be the case in this after showing the definition of ext2_super_block
    Last edited by nonpuz; 04-19-2010 at 07:58 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Trouble with two two dimensional arrays
    By scmurphy64 in forum C Programming
    Replies: 5
    Last Post: 12-06-2009, 06:57 PM
  2. How to read a txt file into an array
    By Hitsugaya_KK in forum C Programming
    Replies: 49
    Last Post: 08-22-2009, 02:22 PM
  3. Help needed with backtracking
    By sjalesho in forum C Programming
    Replies: 1
    Last Post: 11-09-2003, 06:28 PM

Tags for this Thread