示例#1
0
文件: gosfs.c 项目: khwang18c/CMSC412
void Double_Indirect_Set_Helper(struct Block_Device *dev, GOSFSsuperblock *super,
                                int *array, int index, int blockNum) {
    int *arr = Safe_Calloc(PAGE_SIZE);
    int *empty = Safe_Calloc(PAGE_SIZE);
    int newBlock = 0;

    if (array[index/INT_ARR_SIZE] == 0) {
        newBlock = Find_First_Free_Bit(&super->bitmap, super->size);
        Set_Bit(&super->bitmap, newBlock);
        array[index/INT_ARR_SIZE] = newBlock;
        GOSFS_Block_Write(dev, newBlock, empty);
    } 

    GOSFS_Block_Read(dev, array[index/INT_ARR_SIZE], arr); 
    arr[index % INT_ARR_SIZE] = blockNum; 
    GOSFS_Block_Write(dev, blockNum, empty);
    GOSFS_Block_Write(dev, array[index/INT_ARR_SIZE], arr);

    Free(empty);
    Free(arr);
}
示例#2
0
int main() {
  void *bitset = Create_Bit_Set(100);
  assert(Find_First_Free_Bit(bitset,100) == 0);
  Set_Bit(bitset, 0);
  assert(Find_First_Free_Bit(bitset,100) == 1);
  Set_Bit(bitset, 1);
  assert(Find_First_Free_Bit(bitset,100) == 2);
  Set_Bit(bitset, 3);
  assert(Find_First_Free_Bit(bitset,100) == 2);
  Set_Bit(bitset, 4);
  Set_Bit(bitset, 5);
  Set_Bit(bitset, 6);
  Set_Bit(bitset, 7);
  assert(Find_First_Free_Bit(bitset,100) == 2);
  Set_Bit(bitset, 2);
  assert(Find_First_Free_Bit(bitset,100) == 8);
  Clear_Bit(bitset, 2);
  assert(Find_First_Free_Bit(bitset,100) == 2);
}
示例#3
0
文件: gosfs.c 项目: khwang18c/CMSC412
int Double_Indirect_Helper(struct Block_Device *dev, GOSFSsuperblock *super,
                            int *array, int index) {
    int blockNum = 0;
    int tempBlock = 0;
    int *arr = Safe_Calloc(PAGE_SIZE);
    int *empty = Safe_Calloc(PAGE_SIZE);

    if (array[index/INT_ARR_SIZE] == 0) {
        blockNum = 0;
        /* Allocate block for double indirect */
        tempBlock = Find_First_Free_Bit(&super->bitmap, super->size);
        Set_Bit(&super->bitmap, tempBlock);
        array[index/INT_ARR_SIZE] = tempBlock;
        GOSFS_Block_Write(dev, array[index/INT_ARR_SIZE], empty);
    } else {
        GOSFS_Block_Read(dev, array[index/INT_ARR_SIZE], arr);
        blockNum = arr[index % INT_ARR_SIZE];
    }
    Free(empty);
    Free(arr);
    return blockNum;
}
示例#4
0
文件: gosfs.c 项目: khwang18c/CMSC412
/*
 * Create a directory named by given path.
 */
int GOSFS_Create_Directory(struct Mount_Point *mountPoint, const char *path) {
    int rc = 0;
    int blockNum = 0; // The GOSFS block the fileNode(file or dir) exists in
    int newBlock = 0;
    int index = 0;
    char name[MAX_NAME_SIZE] = {};
    bool found = 0;
    GOSFSfileNode *currNode = 0;
    GOSFSsuperblock *super = (GOSFSsuperblock *)mountPoint->fsData;
    GOSFSptr *gosfsEntry = Safe_Calloc(sizeof(GOSFSptr));
    GOSFSdirectory *currDir = Safe_Calloc(PAGE_SIZE);

    /* Grab the root directory from the disk */
    GOSFS_Block_Read(mountPoint->dev, super->rootDir, currDir);
    blockNum = super->rootDir;

    /* Create all of the directories in the path if they don't exist */
    while (*path != 0) {
        memset(name, '\0', MAX_NAME_SIZE);
        memset(gosfsEntry, '\0', sizeof(GOSFSptr));
        newBlock = 0;
        currNode = 0;
        Get_Next_Name_In_Path(&path, name);
        found = GOSFS_Lookup(currDir, name, blockNum, gosfsEntry);

        /* If last element in path exists then fail */
        if (found == true && *path == 0) {
            rc = EEXIST;
            goto fail;
        }

        /* If anything in path is a file then fail */
        if (found == true && gosfsEntry->node.isDirectory == 0) {
            rc = ENOTDIR;
            goto fail;
        }
        
        /* If entry is a directory, then go into it */
        if (found == true && gosfsEntry->node.isDirectory == 1) {
            blockNum = gosfsEntry->node.blocks[0];
            GOSFS_Block_Read(mountPoint->dev, blockNum, currDir);
            continue;
        }

        /* If entry does not exist, then make it */
        if (found == false) {
            /* Find the next open spot in the directory */
            for (index = 0; index < MAX_FILES_PER_DIR; index++) {
                currNode = &currDir->files[index];
                if (currNode->isUsed == 0) {
                    /* Allocate new GOSFS block for new dir */
                    newBlock = Find_First_Free_Bit(&super->bitmap, super->size);
                    Set_Bit(&super->bitmap, newBlock);

                    /* Set up new dir */
                    memcpy(currNode->name, name, MAX_NAME_SIZE);  
                    currNode->size = MAX_FILES_PER_DIR;
                    currNode->isUsed = 1;
                    currNode->isDirectory = 1;
                    currNode->blocks[0] = newBlock;

                    /* Write changes to the curr dir back to disk */
                    GOSFS_Block_Write(mountPoint->dev, blockNum, currDir);

                    memset(currDir, '\0', PAGE_SIZE); // new curr dir empty
                    
                    GOSFS_Block_Write(mountPoint->dev, newBlock, currDir);
                    blockNum = newBlock;
                    
                    break;
                }
                /* If no more room in curr dir */
                if ((index + 1) == MAX_FILES_PER_DIR) {
                    rc = ENOMEM;
                    goto fail;
                }
            }
                      
        }

    }

    /* Write super block back to disk */
    GOSFS_Block_Write(mountPoint->dev, 0, super);

  fail:
  done:
    Free(currDir);
    Free(gosfsEntry);
    return rc;
  
}
示例#5
0
文件: gosfs.c 项目: khwang18c/CMSC412
/*
 * Gets the next block num we need to write to. Also handles setting blocks 
 * array in the node to the new block num
 */
int Get_Blocknum_To_Write(struct File *file) {
    int blockNum = 0;
    int tempBlock = 0;
    int index = ((int)file->filePos) / PAGE_SIZE; 
    int *array = Safe_Calloc(PAGE_SIZE);
    void *empty = Safe_Calloc(PAGE_SIZE);
    GOSFSptr *entry = (GOSFSptr *)file->fsData;
    GOSFSfileNode *node = &entry->node;
    GOSFSsuperblock *super = (GOSFSsuperblock *)file->mountPoint->fsData;
    struct Block_Device *dev = file->mountPoint->dev;

    /* Return the block num we need to write to, or 0 if it doesn't exist */
    if (index < SINGLE_BLOCK) {
        blockNum = node->blocks[index];
    } else if (index > SINGLE_MIN_INDEX && index < SINGLE_MAX_INDEX) {
        if (node->blocks[SINGLE_BLOCK] == 0) {
            blockNum = 0;
            /* Allocate new block for single indirect */
            tempBlock = Find_First_Free_Bit(&super->bitmap, super->size); 
            Set_Bit(&super->bitmap, tempBlock);
            node->blocks[SINGLE_BLOCK] = tempBlock;
            GOSFS_Block_Write(dev, tempBlock, empty);
        } else {
            GOSFS_Block_Read(dev, node->blocks[SINGLE_BLOCK], array);
            blockNum = array[index - SINGLE_BLOCK];
        }
    } else {
        if (node->blocks[DBL_BLOCK] == 0) {
            blockNum = 0;
            /* Allocate new block for double indirect */
            tempBlock = Find_First_Free_Bit(&super->bitmap, super->size);
            Set_Bit(&super->bitmap, tempBlock);
            node->blocks[DBL_BLOCK] = tempBlock;
            GOSFS_Block_Write(dev, tempBlock, empty);
        } else {
            GOSFS_Block_Read(dev, node->blocks[DBL_BLOCK], array);
            blockNum = Double_Indirect_Helper(dev, super, array, index - SINGLE_MAX_INDEX);
            GOSFS_Block_Write(dev, node->blocks[DBL_BLOCK], array); // In case array changed 
        }
    }

    /* If it does not exist than we need to allocate a new block */
    if (blockNum == 0) {
        blockNum = Find_First_Free_Bit(&super->bitmap, super->size);
        Set_Bit(&super->bitmap, blockNum); // Set the super bit map
        if (index < SINGLE_BLOCK) {
            node->blocks[index] = blockNum;    
            GOSFS_Block_Write(dev, node->blocks[index], empty);
        } else if (index > SINGLE_MIN_INDEX && index < SINGLE_MAX_INDEX) {
            GOSFS_Block_Read(dev, node->blocks[SINGLE_BLOCK], array);
            array[index - SINGLE_BLOCK] = blockNum;
            GOSFS_Block_Write(dev, blockNum, empty); // Write empty array back
            GOSFS_Block_Write(dev, node->blocks[SINGLE_BLOCK], array); // Write change back
        } else {
            GOSFS_Block_Read(dev, node->blocks[DBL_BLOCK], array);
            Double_Indirect_Set_Helper(dev, super, array, index - SINGLE_MAX_INDEX, blockNum); 
            GOSFS_Block_Write(dev, node->blocks[DBL_BLOCK], array);
        }
    }

    Free(empty);
    Free(array);
    return blockNum;
}
示例#6
0
/*
 * Create a directory named by given path.
 */
int GOSFS_Create_Directory(struct Mount_Point *mountPoint, const char *path) {
    GOSFSinstance *instance = (GOSFSinstance *) mountPoint->fsData;
    GOSFSfileNode *filePtr = 0;
    GOSFSdirectory *dir, *newDir;
    char *file = path, *nextSlash;
    int rc, offset, i;
    uint_t parentBlock;

    /* Malloc data for file node and directory */
    newDir = Malloc(sizeof(GOSFSdirectory));
    dir = Malloc(sizeof(GOSFSdirectory));
    if (dir == 0 || newDir == 0)
        goto memfail;

    /* Point to the root directory and read in contents... */
    parentBlock = instance->superblock->rootDirPointer;
    readGOSFSBlock(instance->dev, parentBlock, dir, sizeof(GOSFSdirectory));

    /* Iterate until there are no remaining slashes */
    while ((nextSlash = strchr(file + 1, '/'))) {
        /* Ignores leading '/' character */
        file += 1;
        offset = nextSlash - file;

        filePtr = lookupFileInDirectory(dir, file, offset);
        if (!filePtr) {
            /* Need to create a directory */
            /* Make sure name is not too long */
            if (offset >= sizeof(dir->files[0].name))
                goto fail;

            /* First find a free spot in the directory */
            for (i = 0; i < MAX_FILES_PER_DIR; i++) {
                if (!dir->files[i].isUsed) {
                    offset = i;
                    break;
                }
            }
            if (offset == -1)
                /* No free space in directory */
                goto fail;

            /* Now set up the file node at that point */
            filePtr = &dir->files[i];
            memset(filePtr, '\0', sizeof(GOSFSfileNode));
            filePtr->isUsed = true;
            filePtr->isDirectory = true;
            memcpy(filePtr->name, file, offset);

            /* Allocate an empty block for this directory */
            rc = Find_First_Free_Bit(instance->superblock->freeBlocks,
                    instance->superblock->size);
            if (rc < 0)
                goto fail;

            Set_Bit(instance->superblock->freeBlocks, rc);

            /* Clear out this new directory */
            memset(newDir, '\0', sizeof(GOSFSdirectory));

            filePtr->blocks[0] = rc;
            rc = writeGOSFSBlock(instance->dev, rc, newDir,
                    sizeof(GOSFSdirectory));
            if (rc < 0)
                goto fail;

            /* Now write out the updated parent directory to disk */
            rc = writeGOSFSBlock(instance->dev, parentBlock, dir,
                    sizeof(GOSFSdirectory));
            if (rc < 0)
                goto fail;
        }
        if (!filePtr->isDirectory)
            goto fail;

        /* Read in the directory this file node represents */
        parentBlock = filePtr->blocks[0];
        rc = readGOSFSBlock(instance->dev, parentBlock, dir,
                sizeof(GOSFSdirectory));
        if (rc < 0)
            goto fail;

        file = nextSlash;
    }
    file += 1;

    /* Make sure this doesn't exist */
    filePtr = lookupFileInDirectory(dir, file, strlen(file));
    if (filePtr)
        goto fail;

    /* Create the final directory */
    /* Make sure name is not too long */
    if (strlen(file) >= sizeof(dir->files[0].name))
        goto fail;

    /* First find a free spot in the directory */
    for (i = 0; i < MAX_FILES_PER_DIR; i++) {
        if (!dir->files[i].isUsed) {
            offset = i;
            break;
        }
    }
    if (offset == -1)
        /* No free space in directory */
        goto fail;

    /* Now set up the file node at that point */
    filePtr = &dir->files[i];
    memset(filePtr, '\0', sizeof(GOSFSfileNode));
    filePtr->isUsed = true;
    filePtr->isDirectory = true;
    memcpy(filePtr->name, file, strlen(file));

    /* Allocate an empty block for this directory */
    rc = Find_First_Free_Bit(instance->superblock->freeBlocks,
            instance->superblock->size);
    if (rc < 0)
        goto fail;

    Set_Bit(instance->superblock->freeBlocks, rc);

    /* Clear out this new directory */
    memset(newDir, '\0', sizeof(GOSFSdirectory));

    filePtr->blocks[0] = rc;
    rc = writeGOSFSBlock(instance->dev, rc, newDir, sizeof(GOSFSdirectory));
    if (rc < 0)
        goto fail;

    /* Now write out the updated directory to disk */
    rc = writeGOSFSBlock(instance->dev, parentBlock, dir,
            sizeof(GOSFSdirectory));
    if (rc < 0)
        goto fail;

    /* Write out the updated superblock */
    rc = writeGOSFSBlock(instance->dev, GOSFS_SUPERBLOCK, instance->superblock,
            sizeof(GOSFSsuperblock));
    if (rc < 0)
        goto fail;

    Free(dir);
    return 0;

    memfail: rc = ENOMEM;
    goto fail;
    fail: if (dir)
        Free(dir);
    return rc;
}
示例#7
0
/* Grows a file by one block (from the end position) and, if necessary,
 * allocates indirect or double indirect blocks to contain this
 * new block.
 */
static int growFile(struct File *file) {
    GOSFSinstance *instance = (GOSFSinstance *) file->mountPoint->fsData;
    GOSFSsuperblock *superblock = instance->superblock;
    GOSFSptr *filePtr = (GOSFSptr *) file->fsData;
    GOSFSfileNode *node = &filePtr->node;
    GOSFSdirectory *dir;
    ulong_t nextBlock = file->endPos / GOSFS_BLOCK_SIZE;
    char *buf;
    int *indirect = 0, *doubleIndirect = 0;
    int rc, newBlock;

    buf = Malloc(GOSFS_BLOCK_SIZE);
    indirect = Malloc(GOSFS_BLOCK_SIZE);
    doubleIndirect = Malloc(GOSFS_BLOCK_SIZE);
    dir = Malloc(sizeof(GOSFSdirectory));
    if (!buf || !indirect || !doubleIndirect || !dir)
        goto memfail;

    if (nextBlock < INDIRECT_BLOCK_START) {
        /* This is a simple direct block */
        rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
        if (rc < 0)
            goto fail;

        node->blocks[nextBlock] = rc;
        newBlock = rc;
    } else if (nextBlock < DOUBLE_INDIRECT_BLOCK_START) {
        /* Check for indirect block existence */
        if (node->blocks[INDIRECT_BLOCK] == 0) {
            /* Need to create indirect block */
            rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
            if (rc < 0)
                goto fail;

            /* Update (cached) file node */
            node->blocks[INDIRECT_BLOCK] = rc;
            newBlock = rc;

            /* Write out zero-filled block */
            memset(buf, '\0', GOSFS_BLOCK_SIZE);
            rc
                    = writeGOSFSBlock(instance->dev, newBlock, buf,
                            GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;

            /* Claim bit */
            Set_Bit(superblock->freeBlocks, newBlock);

            /* "Read" indirect block by copying it to array */
            memcpy(indirect, buf, GOSFS_BLOCK_SIZE);
        } else {
            /* Read in indirect block */
            rc = readGOSFSBlock(instance->dev, node->blocks[INDIRECT_BLOCK],
                    indirect, GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;
        }

        rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
        if (rc < 0)
            goto fail;

        /* Update block array */
        indirect[nextBlock - INDIRECT_BLOCK_START] = rc;
        newBlock = rc;

        /* Write out updated block array to disk */
        rc = writeGOSFSBlock(instance->dev, node->blocks[INDIRECT_BLOCK],
                indirect, GOSFS_BLOCK_SIZE);
        if (rc < 0)
            goto fail;
    } else if (nextBlock < MAX_BLOCK) {
        /* Check for indirect block existence */
        if (node->blocks[DOUBLE_INDIRECT_BLOCK] == 0) {
            /* Need to create indirect block */
            rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
            if (rc < 0)
                goto fail;

            /* Update (cached) file node */
            node->blocks[DOUBLE_INDIRECT_BLOCK] = rc;
            newBlock = rc;

            /* Write out zero-filled block */
            memset(buf, '\0', GOSFS_BLOCK_SIZE);
            rc
                    = writeGOSFSBlock(instance->dev, newBlock, buf,
                            GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;

            /* Claim bit */
            Set_Bit(superblock->freeBlocks, newBlock);

            /* "Read" indirect block by copying it to array */
            memcpy(indirect, buf, GOSFS_BLOCK_SIZE);
        } else {
            /* Read in indirect block */
            rc = readGOSFSBlock(instance->dev,
                    node->blocks[DOUBLE_INDIRECT_BLOCK], indirect,
                    GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;
        }

        /* Check for double indirect block existence */
        if (indirect[(nextBlock - DOUBLE_INDIRECT_BLOCK_START)
                / (GOSFS_BLOCK_SIZE / sizeof(int))] == 0) {
            /* Need to create second indirect block */
            rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
            if (rc < 0)
                goto fail;

            /* Update indirect block */
            indirect[(nextBlock - DOUBLE_INDIRECT_BLOCK_START)
                    / (GOSFS_BLOCK_SIZE / sizeof(int))] = rc;
            newBlock = rc;

            Set_Bit(superblock->freeBlocks, newBlock);

            /* Write out zero-filled block */
            memset(buf, '\0', GOSFS_BLOCK_SIZE);
            rc
                    = writeGOSFSBlock(instance->dev, newBlock, buf,
                            GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;

            /* Write out updated indirect block */
            rc = writeGOSFSBlock(instance->dev,
                    node->blocks[DOUBLE_INDIRECT_BLOCK], indirect,
                    GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;

            /* "Read" double indirect block by copying array */
            memcpy(doubleIndirect, buf, GOSFS_BLOCK_SIZE);
        } else {
            /* Read in double indirect block */
            rc = indirect[(nextBlock - DOUBLE_INDIRECT_BLOCK_START)
                    / (GOSFS_BLOCK_SIZE / sizeof(int))];
            rc = readGOSFSBlock(instance->dev, rc, doubleIndirect,
                    GOSFS_BLOCK_SIZE);
            if (rc < 0)
                goto fail;
        }

        /* Now finally we can allocate a block for the double indirect layer */
        rc = Find_First_Free_Bit(superblock->freeBlocks, superblock->size);
        if (rc < 0)
            goto fail;

        doubleIndirect[(nextBlock - DOUBLE_INDIRECT_BLOCK_START)
                % (GOSFS_BLOCK_SIZE / sizeof(int))] = rc;
        newBlock = rc;

        /* Write out updated double indirect block */
        rc = indirect[(nextBlock - DOUBLE_INDIRECT_BLOCK_START)
                / (GOSFS_BLOCK_SIZE / sizeof(int))];
        rc = writeGOSFSBlock(instance->dev, rc, doubleIndirect,
                GOSFS_BLOCK_SIZE);
        if (rc < 0)
            goto fail;
    } else {
        /* This would be triple indirect and above */
        rc = EINVALID;
        goto fail;
    }

    /* Now update file node on disk */
    rc = readGOSFSBlock(instance->dev, filePtr->blockNum, dir,
            sizeof(GOSFSdirectory));
    if (rc < 0)
        goto fail;
    memcpy(&dir->files[filePtr->offset], node, sizeof(GOSFSfileNode));
    rc = writeGOSFSBlock(instance->dev, filePtr->blockNum, dir,
            sizeof(GOSFSdirectory));

    Set_Bit(superblock->freeBlocks, newBlock);

    /* Now update superblock */
    rc = writeGOSFSBlock(instance->dev, GOSFS_SUPERBLOCK, superblock,
            sizeof(GOSFSsuperblock));
    if (rc < 0)
        goto fail;

    Free(buf);
    Free(indirect);
    Free(doubleIndirect);
    Free(dir);
    return newBlock;

    memfail: rc = ENOMEM;
    goto fail;
    fail: if (buf)
        Free(buf);
    if (indirect)
        Free(indirect);
    if (doubleIndirect)
        Free(doubleIndirect);
    if (dir)
        Free(dir);
    return rc;
}