⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mount.c

📁 be文件系统实现的源码
💻 C
字号:
/*  This file contains the code that will create a file system, mount  a file system and unmount a file system.    THIS CODE COPYRIGHT DOMINIC GIAMPAOLO.  NO WARRANTY IS EXPRESSED   OR IMPLIED.  YOU MAY USE THIS CODE AND FREELY DISTRIBUTE IT FOR  NON-COMMERCIAL USE AS LONG AS THIS NOTICE REMAINS ATTACHED.  FOR COMMERCIAL USE, CONTACT DOMINIC GIAMPAOLO (dbg@be.com).  Dominic Giampaolo  dbg@be.com*/#include "myfs.h"#ifndef min_c#define min_c(a, b) (((a) < (b)) ? (a) : (b))#endif /* min_c */myfs_info *myfs_create_fs(char *device, char *name, int block_size, char *opts){    int        dev_block_size, bshift, warned = 0;    char      *ptr;    fs_off_t   num_dev_blocks;    myfs_info *myfs;    if ((block_size % sizeof(myfs_inode)) != 0) {        printf("ERROR: inode size %d is not an even divisor of the block "               "size %d\n", sizeof(myfs_inode), block_size);        printf("       check myfs.h for more details and info.\n");        return NULL;    }    if (name == NULL)        name = "untitled";    for(ptr=name; *ptr; ptr++) {        if (*ptr == '/') {            if (warned == 0) {                fprintf(stderr, "Volume name: %s contains the '/' character. "                        "They are being converted to '-' for safety.\n", name);                warned = 1;            }            *ptr = '-';        }    }    if (block_size < 512) {        printf("minimum block size is 512 bytes\n");        block_size = 512;    }    for(bshift=0; bshift < sizeof(int)*8; bshift++)        if ((1 << bshift) == block_size)            break;    if (bshift >= sizeof(int)*8) {        printf("block_size %d is not a power of two!\n", block_size);        return NULL;    }            myfs = (myfs_info *)calloc(1, sizeof(myfs_info));    if (myfs == NULL) {        printf("can't allocate mem for myfs_info struct\n");        return NULL;    }    myfs->fd = -1;    myfs->nsid = (nspace_id)myfs;   /* we can only do this when creating */        myfs->dsb.magic1 = SUPER_BLOCK_MAGIC1;    myfs->dsb.magic2 = SUPER_BLOCK_MAGIC2;    myfs->dsb.magic3 = SUPER_BLOCK_MAGIC3;    myfs->dsb.fs_byte_order = MYFS_BIG_ENDIAN;  /* checked when mounting */    myfs->sem = create_sem(MAX_READERS, "myfs_sem");    if (myfs->sem < 0) {        printf("can't create semaphore!\n");        goto cleanup;    }            myfs->fd = open(device, O_RDWR);    if (myfs->fd < 0) {        printf("can't open device %s\n", device);        goto cleanup;    }    dev_block_size = get_device_block_size(myfs->fd);    num_dev_blocks = get_num_device_blocks(myfs->fd);    if (block_size < dev_block_size) {        printf("warning: fs block size too small, set to device block size %d\n",               dev_block_size);        block_size = dev_block_size;    }    if ((block_size % dev_block_size) != 0) {        printf("error: block size %d is not an even multiple of ",               block_size);        printf("device block size %d\n", dev_block_size);        goto cleanup;    }    myfs->dsb.block_size       = block_size;    myfs->dsb.block_shift      = bshift;    myfs->dev_block_conversion = block_size / dev_block_size;    myfs->dev_block_size       = dev_block_size;    myfs->dsb.num_blocks       = num_dev_blocks / myfs->dev_block_conversion;    init_cache_for_device(myfs->fd, num_dev_blocks / myfs->dev_block_conversion);    if (init_tmp_blocks(myfs) != 0) {        printf("init_tmp_blocks failed\n");        goto cleanup;    }    if (myfs_create_storage_map(myfs) != 0) {        printf("create storage map failed\n");        goto cleanup;    }        if (myfs_create_inodes(myfs) != 0) {        printf("create inodes failed\n");        goto cleanup;    }    if (myfs_create_journal(myfs) != 0) {        printf("create journal failed\n");        goto cleanup;    }    if (myfs_create_root_dir(myfs) != 0) {        printf("create root dir failed\n");        goto cleanup;    }    strncpy(myfs->dsb.name, name,            min_c(sizeof(myfs->dsb.name) - 1, strlen(name)));    /* now it's finally safe to write this */    if (write_super_block(myfs) != 0) {        printf("creating superblock failed\n");        goto cleanup;    }        return myfs;cleanup:    if (myfs) {        /* making the file system failed so make sure block zero is bogus */        if (myfs->fd >= 0) {            static char block[4096];            memset(block, 0xff, sizeof(block));            write_blocks(myfs, 0, block, 1);        }        myfs_shutdown_storage_map(myfs);        myfs_shutdown_inodes(myfs);        myfs_shutdown_journal(myfs);        shutdown_tmp_blocks(myfs);        close(myfs->fd);        delete_sem(myfs->sem);        free(myfs);    }       return NULL;}static intsuper_block_is_sane(myfs_info *myfs){    fs_off_t num_dev_blocks;    int block_size;    if (myfs->dsb.magic1 != SUPER_BLOCK_MAGIC1 ||        myfs->dsb.magic2 != SUPER_BLOCK_MAGIC2 ||        myfs->dsb.magic3 != SUPER_BLOCK_MAGIC3) {        printf("warning: super block magic numbers are wrong:\n");        printf("0x%x (0x%x) 0x%x (0x%x) 0x%x (0x%x)\n",               myfs->dsb.magic1, SUPER_BLOCK_MAGIC1,               myfs->dsb.magic2, SUPER_BLOCK_MAGIC2,               myfs->dsb.magic3, SUPER_BLOCK_MAGIC3);        return 0;            }    if ((myfs->dsb.block_size % myfs->dev_block_size) != 0) {        printf("warning: fs block size %d not a multiple of ",                myfs->dsb.block_size);        printf(" device block size %d\n", myfs->dev_block_size);        return 0;    }    block_size = get_device_block_size(myfs->fd);    if (block_size == 0) {        printf("warning: could not fetch block size\n");        return 0;    }    /* make sure that the partition is as big as the super block       says it is */    num_dev_blocks = get_num_device_blocks(myfs->fd);    if (myfs->dsb.num_blocks * myfs->dsb.block_size >                num_dev_blocks * block_size) {        printf("warning: fs blocks %lx larger than device blocks %lx\n",                myfs->dsb.num_blocks * (myfs->dsb.block_size/block_size),                num_dev_blocks);        return 0;    }    if (myfs->dsb.block_size != (1 << myfs->dsb.block_shift)) {        int i;                printf("warning: block_shift %d does not match block size %d\n",               myfs->dsb.block_shift, myfs->dsb.block_size);        if (myfs->dsb.block_shift > 8 && myfs->dsb.block_shift < 16) {            printf("setting block_size to %d\n", (1 << myfs->dsb.block_shift));            myfs->dsb.block_size = (1 << myfs->dsb.block_shift);        } else {            for(i=0; i < sizeof(int) * 8; i++)                if ((1 << i) == myfs->dsb.block_size)                    break;            if (i >= sizeof(int) * 8 || i > 16) {                printf("neither block_size nor block_shift make sense!\n");                return 0;            }            myfs->dsb.block_shift = i;            printf("setting block_shift to %d\n", i);        }    }    return 1;}intmyfs_mount(nspace_id nsid, const char *device, ulong flags,                    void *parms, size_t len, void **data, vnode_id *vnid){    int        ret = 0, oflags = O_RDWR;    char       buff[128];    myfs_info  *myfs;    myfs = (myfs_info *)calloc(1, sizeof(myfs_info));    if (myfs == NULL) {        printf("no memory for myfs structure!\n");        return ENOMEM;    }    myfs->nsid = nsid;    *data = (void *)myfs;    sprintf(buff, "myfs:%s", device);    myfs->sem = create_sem(MAX_READERS, buff);    if (myfs->sem < 0) {        printf("could not create myfs sem!\n");        ret = ENOMEM;        goto error0;    }        myfs->fd = open(device, oflags);    if (myfs->fd < 0) {        printf("could not open %s to try and mount a myfs\n", device);        ret = ENODEV;        goto error1;    }    if (read_super_block(myfs) != 0) {        printf("could not read super block on device %s\n", device);        ret = EBADF;        goto error2;    }            if (super_block_is_sane(myfs) == 0) {        printf("bad super block\n");        ret = EBADF;        goto error2;    }    if ((myfs->dsb.block_size % sizeof(myfs_inode)) != 0) {        printf("ERROR: inode size %d is not an even divisor of the block "               "size %d\n", sizeof(myfs_inode), myfs->dsb.block_size);        printf("       check myfs.h for more details and info.\n");        ret = EINVAL;        goto error2;    }    if (init_cache_for_device(myfs->fd, myfs->dsb.num_blocks) != 0) {        printf("could not initialize cache access for fd %d\n", myfs->fd);        ret = EBADF;        goto error2;    }    if (init_tmp_blocks(myfs) != 0) {        printf("could not init tmp blocks\n");        ret = ENOMEM;        goto error2;    }    if (myfs_init_journal(myfs) != 0) {        printf("could not initialize the journal\n");        ret = EBADF;        goto error3;    }    if (myfs_init_inodes(myfs) != 0) {        printf("could not initialize inodes\n");        ret = ENOMEM;        goto error5;    }    if (myfs_init_storage_map(myfs) != 0) {        printf("could not initialize the storage map\n");        ret = EBADF;        goto error6;    }    *vnid = myfs->dsb.root_inum;    if (myfs_read_vnode(myfs, *vnid, 0, (void **)&myfs->root_dir) != 0) {        printf("could not read root dir inode\n");        ret = EBADF;        goto error7;    }    if (new_vnode(myfs->nsid, *vnid, (void *)myfs->root_dir) != 0) {        printf("could not initialize a vnode for the root directory!\n");        ret = ENOMEM;        goto error7;    }    return 0; error7:    myfs_shutdown_storage_map(myfs); error6:    myfs_shutdown_inodes(myfs); error5:    myfs_shutdown_journal(myfs); error3:    shutdown_tmp_blocks(myfs); error2:    remove_cached_device_blocks(myfs->fd, NO_WRITES);    close(myfs->fd); error1:    delete_sem(myfs->sem); error0:    memset(myfs, 0xff, sizeof(*myfs));   /* yeah, I'm paranoid */    free(myfs);    return ret;}/*   note that the order in which things are done here is *very*   important. don't mess with it unless you know what you're doing*/   intmyfs_unmount(void *ns){    myfs_info *myfs = (myfs_info *)ns;        if (myfs == NULL)        return EINVAL;        sync_journal(myfs);    myfs_shutdown_storage_map(myfs);    myfs_shutdown_inodes(myfs);    /*       have to do this after the above steps because the above steps       might actually have to do transactions    */    sync_journal(myfs);    remove_cached_device_blocks(myfs->fd, ALLOW_WRITES);    myfs_shutdown_journal(myfs);    write_super_block(myfs);    shutdown_tmp_blocks(myfs);    close(myfs->fd);        if (myfs->sem > 0)        delete_sem(myfs->sem);    memset(myfs, 0xff, sizeof(*myfs));   /* trash it just to be sure */    free(myfs);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -