Esempio n. 1
0
static int
pipe_root_lookup(struct inode *__node, char *path, struct inode **node_store) {
    assert((path[0] == 'r' || path[0] == 'w') && path[1] == '_');
    struct inode *node[2];
    struct pipe_fs *pipe = fsop_info(vop_fs(__node), pipe);
    lock_pipe(pipe);
    {
        lookup_pipe_nolock(pipe, path + 2, &node[0], &node[1]);
    }
    unlock_pipe(pipe);

    if (path[0] != 'r') {
        struct inode *tmp = node[0];
        node[0] = node[1], node[1] = tmp;
    }

    if (node[1] != NULL) {
        vop_ref_dec(node[1]);
    }
    if (node[0] == NULL) {
        return -E_NOENT;
    }
    *node_store = node[0];
    return 0;
}
Esempio n. 2
0
static int
sfs_rename(struct inode *node, const char *name, struct inode *new_node, const char *new_name) {
    if (strlen(name) > SFS_MAX_FNAME_LEN || strlen(new_name) > SFS_MAX_FNAME_LEN) {
        return -E_TOO_BIG;
    }
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
        return -E_INVAL;
    }
    if (strcmp(new_name, ".") == 0 || strcmp(new_name, "..") == 0) {
        return -E_EXISTS;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode), *newsin = vop_info(new_node, sfs_inode);
    int ret;
    lock_sfs_mutex(sfs);
    {
        if ((ret = trylock_sin(sin)) == 0) {
            if (sin == newsin) {
                ret = sfs_rename1_nolock(sfs, sin, name, new_name);
            }
            else if ((ret = trylock_sin(newsin)) == 0) {
                ret = sfs_rename2_nolock(sfs, sin, name, newsin, new_name);
                unlock_sin(newsin);
            }
            unlock_sin(sin);
        }
    }
    unlock_sfs_mutex(sfs);
    return ret;
}
Esempio n. 3
0
/*
 * sfs_getdirentry - according to the iob->io_offset, calculate the dir entry's slot in disk block,
                     get dir entry content from the disk
 */
static int
sfs_getdirentry(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int ret, slot;
    off_t offset = iob->io_offset;
    if (offset < 0 || offset % sfs_dentry_size != 0) {
        kfree(entry);
        return -E_INVAL;
    }
    if ((slot = offset / sfs_dentry_size) > sin->din->blocks) {
        kfree(entry);
        return -E_NOENT;
    }
    lock_sin(sin);
    if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) {
        unlock_sin(sin);
        goto out;
    }
    unlock_sin(sin);
    ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL);
out:
    kfree(entry);
    return ret;
}
Esempio n. 4
0
// 同步文件块
static int
sfs_sync(struct fs *fs) {
    struct sfs_fs *sfs = fsop_info(fs, sfs);
    lock_sfs_fs(sfs); // 应该是用信号量锁定这个玩意
    {
        list_entry_t *list = &(sfs->inode_list), *le = list;
        while ((le = list_next(le)) != list) {
            struct sfs_inode *sin = le2sin(le, inode_link);
            vop_fsync(info2node(sin, sfs_inode));
        }
    }
    unlock_sfs_fs(sfs);

    int ret;
    if (sfs->super_dirty) {
        sfs->super_dirty = 0;
        if ((ret = sfs_sync_super(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
        if ((ret = sfs_sync_freemap(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
    }
    return 0;
}
Esempio n. 5
0
static int
sfs_namefile(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int ret;
    uint32_t ino;
    char *ptr = iob->io_base + iob->io_resid;
    size_t alen, resid = iob->io_resid - 2;
    
    vop_ref_inc(node);
    while ((ino = sin->ino) != SFS_BLKN_ROOT) {
        struct inode *parent;
        if ((ret = sfs_load_parent(sfs, sin, &parent)) != 0) {
            goto failed;
        }
        vop_ref_dec(node);
        
        node = parent, sin = vop_info(node, sfs_inode);
        assert(ino != sin->ino && sin->din->type == SFS_TYPE_DIR);

        if ((ret = trylock_sin(sin)) != 0) {
            goto failed;
        }
        ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry);
        unlock_sin(sin);

        if (ret != 0) {
            goto failed;
        }

        if ((alen = strlen(entry->name) + 1) > resid) {
            goto failed_nomem;
        }
        resid -= alen, ptr -= alen;
        memcpy(ptr, entry->name, alen - 1);
        ptr[alen - 1] = '/';
    }
    vop_ref_dec(node);
    alen = iob->io_resid - resid - 2;
    ptr = memmove(iob->io_base + 1, ptr, alen);
    ptr[-1] = '/', ptr[alen] = '\0';
    iobuf_skip(iob, alen);
    kfree(entry);
    return 0;

failed_nomem:
    ret = -E_NO_MEM;
failed:
    vop_ref_dec(node);
    kfree(entry);
    return ret;
}
Esempio n. 6
0
static int
sfs_sync(struct fs *fs) {
    struct sfs_fs *sfs = fsop_info(fs, sfs);
    lock_sfs_fs(sfs);
/*
 * Get the sfs_fs from the generic abstract fs.
 *
 * Note that the abstract struct fs, which is all the VFS
 * layer knows about, is actually a member of struct sfs_fs.
 * The pointer in the struct fs points back to the top of the
 * struct sfs_fs - essentially the same object. This can be a
 * little confusing at first.
 *
 * The following diagram may help:
 *
 *     struct sfs_fs        <-----------------\
        *           :                                |
        *           :   sfs_absfs (struct fs)        |   <------\
        *           :      :                         |          |
        *           :      :  various members        |          |
        *           :      :                         |          |
        *           :      :  fs_info(__sfs_info) ---/          |
        *           :      :                             ...|...
        *           :                                   .  VFS  .
        *           :                                   . layer . 
        *           :   other members                    .......
        *           :                                    
        *           :
 *
 * This construct is repeated with inodes and devices and other
 * similar things all over the place in ucore, so taking the
 * time to straighten it out in your mind is worthwhile.
 */
    {
        list_entry_t *list = &(sfs->inode_list), *le = list;
        while ((le = list_next(le)) != list) {
            struct sfs_inode *sin = le2sin(le, inode_link);
            vop_fsync(info2node(sin, sfs_inode));
        }
    }
    unlock_sfs_fs(sfs);

    int ret;
    if (sfs->super_dirty) {
        sfs->super_dirty = 0;
        /* If the superblock needs to be written, write it. */
        if ((ret = sfs_sync_super(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
	/* If the free block map needs to be written, write it. */
        if ((ret = sfs_sync_freemap(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
    }
    return 0;
}
Esempio n. 7
0
static int
pipe_root_create(struct inode *__node, const char *name, bool excl, struct inode **node_store) {
    assert((name[0] == 'r' || name[0] == 'w') && name[1] == '_');
    int ret = 0;
    bool readonly = (name[0] == 'r');
    name += 2;

    struct inode *node[2];
    struct fs *fs = vop_fs(__node);
    struct pipe_fs *pipe = fsop_info(fs, pipe);

    lock_pipe(pipe);

    lookup_pipe_nolock(pipe, name, &node[0], &node[1]);
    if (!readonly) {
        struct inode *tmp = node[0];
        node[0] = node[1], node[1] = tmp;
    }

    if (node[0] != NULL) {
        if (excl) {
            ret = -E_EXISTS, vop_ref_dec(node[0]);
            goto out;
        }
        *node_store = node[0];
        goto out;
    }
    ret = -E_NO_MEM;

    struct pipe_state *state;
    if (node[1] == NULL) {
        if ((state = pipe_state_create()) == NULL) {
            goto out;
        }
    }
    else {
        state = vop_info(node[1], pipe_inode)->state;
        pipe_state_acquire(state);
    }

    struct inode *new_node;
    if ((new_node = pipe_create_inode(fs, name, state, readonly)) == NULL) {
        pipe_state_release(state);
        goto out;
    }

    list_add(&(pipe->pipe_list), &(vop_info(new_node, pipe_inode)->pipe_link));
    ret = 0, *node_store = new_node;

out:
    unlock_pipe(pipe);

    if (node[1] != NULL) {
        vop_ref_dec(node[1]);
    }
    return ret;
}
Esempio n. 8
0
static struct inode *
sfs_get_root(struct fs *fs) {
    struct inode *node;
    int ret;
    if ((ret = sfs_load_inode(fsop_info(fs, sfs), &node, SFS_BLKN_ROOT)) != 0) {
        panic("load sfs root failed: %e", ret);
    }
    return node;
}
Esempio n. 9
0
/* return root inode of filesystem */
static struct inode *ffs_get_root(struct fs *fs)
{
	struct inode *node;
	int ret;
	if ((ret = ffs_load_inode(fsop_info(fs, ffs), &node, "0:/", NULL)) != 0) {
		panic("load ffs root failed: %e", ret);
	}

	return node;
}
static int
sfs_sync(struct fs *fs) {

    // debug
    // int u;
    // kprintf("--- %d ---\n", 1);
    // for (u = _initrd_begin; u < _initrd_end; ++u) {
    //     kprintf("%02x ", *((char *)u));
    // }
    // kprintf("\n");

    struct sfs_fs *sfs = fsop_info(fs, sfs);
    lock_sfs_fs(sfs);
    {
        list_entry_t *list = &(sfs->inode_list), *le = list;
        while ((le = list_next(le)) != list) {
            struct sfs_inode *sin = le2sin(le, inode_link);
            vop_fsync(info2node(sin, sfs_inode));
        }
    }
    unlock_sfs_fs(sfs);

    // kprintf("--- %d ---\n", 2);
    // for (u = _initrd_begin; u < _initrd_end; ++u) {
    //     kprintf("%02x ", *((char *)u));
    // }
    // kprintf("\n");


    int ret;
    if (sfs->super_dirty) {
        sfs->super_dirty = 0;
        if ((ret = sfs_sync_super(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
        if ((ret = sfs_sync_freemap(sfs)) != 0) {
            sfs->super_dirty = 1;
            return ret;
        }
    }

    // kprintf("--- %d ---\n", 3);
    // for (u = _initrd_begin; u < _initrd_end; ++u) {
    //     kprintf("%02x ", *((char *)u));
    // }
    // kprintf("\n");

    swapper_all_block_sync();

    return 0;
}
Esempio n. 11
0
static int
sfs_unmount(struct fs *fs) {
    struct sfs_fs *sfs = fsop_info(fs, sfs);
    if (!list_empty(&(sfs->inode_list))) {
        return -E_BUSY;
    }
    assert(!sfs->super_dirty);
    bitmap_destroy(sfs->freemap);
    kfree(sfs->sfs_buffer);
    kfree(sfs->hash_list);
    kfree(sfs);
    return 0;
}
Esempio n. 12
0
static int
sfs_reclaim(struct inode *node) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    lock_sfs_fs(sfs);

    int ret = -E_BUSY;
    assert(sin->reclaim_count > 0);
    if ((-- sin->reclaim_count) != 0) {
        goto failed_unlock;
    }
    assert(inode_ref_count(node) == 0 && inode_open_count(node) == 0);

    if (sin->din->nlinks == 0) {
        uint32_t nblks;
        for (nblks = sin->din->blocks; nblks != 0; nblks --) {
            sfs_bmap_truncate_nolock(sfs, sin);
        }
    }
    else if (sin->dirty) {
        if ((ret = vop_fsync(node)) != 0) {
            goto failed_unlock;
        }
    }
    
    sfs_remove_links(sin);
    unlock_sfs_fs(sfs);

    if (sin->din->nlinks == 0) {
        sfs_block_free(sfs, sin->ino);
        uint32_t ent;
        if ((ent = sin->din->indirect) != 0) {
            sfs_block_free(sfs, ent);
        }
        if ((ent = sin->din->db_indirect) != 0) {
            int i;
            for (i = 0; i < SFS_BLK_NENTRY; i ++) {
                sfs_bmap_free_sub_nolock(sfs, ent, i);
            }
            sfs_block_free(sfs, ent);
        }
    }
    kfree(sin->din);
    vop_kill(node);
    return 0;

failed_unlock:
    unlock_sfs_fs(sfs);
    return ret;
}
Esempio n. 13
0
/* attempt unmount of filesystem */
static int ffs_unmount(struct fs *fs)
{
	//TODO
	FAT_PRINTF("[ffs_unmount]\n");
	struct ffs_fs *ffs = fsop_info(fs, ffs);
	if (ffs->inode_list->next != NULL) {
		return -E_BUSY;
	}
	kfree(ffs->fatfs);
	kfree(ffs->inode_list);
	kfree(ffs);

	return 0;
}
Esempio n. 14
0
static void
pipe_fs_init(struct fs *fs) {
    struct pipe_fs *pipe = fsop_info(fs, pipe);
    if ((pipe->root = pipe_create_root(fs)) == NULL) {
        panic("pipe: create root inode failed.\n");
    }
    sem_init(&(pipe->pipe_sem), 1);
    list_init(&(pipe->pipe_list));

    fs->fs_sync = pipe_sync;
    fs->fs_get_root = pipe_get_root;
    fs->fs_unmount = pipe_unmount;
    fs->fs_cleanup = pipe_cleanup;
}
Esempio n. 15
0
/* 
 * flush all dirty buffers to disk
 * return 0 if sync successful
 */
static int ffs_sync(struct fs *fs)
{
	//TODO
	return 0;
	FAT_PRINTF("[ffs_sync]\n");
	struct ffs_fs *ffs = fsop_info(fs, ffs);
	struct ffs_inode_list *inode_list = ffs->inode_list;
	while (inode_list->next != NULL) {
		inode_list = inode_list->next;
		vop_fsync(info2node(inode_list->f_inode, ffs_inode));
	}

	return 0;
}
Esempio n. 16
0
static void
sfs_cleanup(struct fs *fs) {
    struct sfs_fs *sfs = fsop_info(fs, sfs);
    uint32_t blocks = sfs->super.blocks, unused_blocks = sfs->super.unused_blocks;
    cprintf("sfs: cleanup: '%s' (%d/%d/%d)\n", sfs->super.info,
            blocks - unused_blocks, unused_blocks, blocks);
    int i, ret;
    for (i = 0; i < 32; i ++) {
        if ((ret = fsop_sync(fs)) == 0) {
            break;
        }
    }
    if (ret != 0) {
        warn("sfs: sync error: '%s': %e.\n", sfs->super.info, ret);
    }
}
Esempio n. 17
0
/*
 * sfs_io - Rd/Wr file. the wrapper of sfs_io_nolock
            with lock protect
 */
static inline int
sfs_io(struct inode *node, struct iobuf *iob, bool write) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    int ret;
    lock_sin(sin);
    {
        size_t alen = iob->io_resid;
        ret = sfs_io_nolock(sfs, sin, iob->io_base, iob->io_offset, &alen, write);
        if (alen != 0) {
            iobuf_skip(iob, alen);
        }
    }
    unlock_sin(sin);
    return ret;
}
Esempio n. 18
0
static int
sfs_mkdir(struct inode *node, const char *name) {
    if (strlen(name) > SFS_MAX_FNAME_LEN) {
        return -E_TOO_BIG;
    }
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
        return -E_EXISTS;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    int ret;
    if ((ret = trylock_sin(sin)) == 0) {
        ret = sfs_mkdir_nolock(sfs, sin, name);
        unlock_sin(sin);
    }
    return ret;
}
Esempio n. 19
0
/*
 * sfs_truncfile : reszie the file with new length
 */
static int
sfs_truncfile(struct inode *node, off_t len) {
    if (len < 0 || len > SFS_MAX_FILE_SIZE) {
        return -E_INVAL;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    struct sfs_disk_inode *din = sin->din;

    int ret = 0;
	//new number of disk blocks of file
    uint32_t nblks, tblks = ROUNDUP_DIV(len, SFS_BLKSIZE);
    if (din->size == len) {
        assert(tblks == din->blocks);
        return 0;
    }

    lock_sin(sin);
	// old number of disk blocks of file
    nblks = din->blocks;
    if (nblks < tblks) {
		// try to enlarge the file size by add new disk block at the end of file
        while (nblks != tblks) {
            if ((ret = sfs_bmap_load_nolock(sfs, sin, nblks, NULL)) != 0) {
                goto out_unlock;
            }
            nblks ++;
        }
    }
    else if (tblks < nblks) {
		// try to reduce the file size
        while (tblks != nblks) {
            if ((ret = sfs_bmap_truncate_nolock(sfs, sin)) != 0) {
                goto out_unlock;
            }
            nblks --;
        }
    }
    assert(din->blocks == tblks);
    din->size = len;
    sin->dirty = 1;

out_unlock:
    unlock_sin(sin);
    return ret;
}
Esempio n. 20
0
static int
sfs_truncfile(struct inode *node, off_t len) {
    if (len < 0 || len > SFS_MAX_FILE_SIZE) {
        return -E_INVAL;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    struct sfs_disk_inode *din = sin->din;
    assert(din->type != SFS_TYPE_DIR);

    int ret = 0;
    uint32_t nblks, tblks = ROUNDUP_DIV(len, SFS_BLKSIZE);
    if (din->fileinfo.size == len) {
        assert(tblks == din->blocks);
        return 0;
    }

    if ((ret = trylock_sin(sin)) != 0) {
        return ret;
    }
    nblks = din->blocks;
    if (nblks < tblks) {
        while (nblks != tblks) {
            if ((ret = sfs_bmap_load_nolock(sfs, sin, nblks, NULL)) != 0) {
                goto out_unlock;
            }
            nblks ++;
        }
    }
    else if (tblks < nblks) {
        while (tblks != nblks) {
            if ((ret = sfs_bmap_truncate_nolock(sfs, sin)) != 0) {
                goto out_unlock;
            }
            nblks --;
        }
    }
    assert(din->blocks == tblks);
    din->fileinfo.size = len;
    sin->dirty = 1;

out_unlock:
    unlock_sin(sin);
    return ret;
}
Esempio n. 21
0
static int
sfs_lookup(struct inode *node, char *path, struct inode **node_store) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    assert(*path != '\0' && *path != '/');
    vop_ref_inc(node);
    do {
        struct sfs_inode *sin = vop_info(node, sfs_inode);
        if (sin->din->type != SFS_TYPE_DIR) {
            vop_ref_dec(node);
            return -E_NOTDIR;
        }

        char *subpath;
  next:
        subpath = sfs_lookup_subpath(path);
        if (strcmp(path, ".") == 0) {
            if ((path = subpath) != NULL) {
                goto next;
            }
            break;
        }

        int ret;
        struct inode *subnode;
        if (strcmp(path, "..") == 0) {
            ret = sfs_load_parent(sfs, sin, &subnode);
        }
        else {
            if (strlen(path) > SFS_MAX_FNAME_LEN) {
                vop_ref_dec(node);
                return -E_TOO_BIG;
            }
            ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL);
        }

        vop_ref_dec(node);
        if (ret != 0) {
            return ret;
        }
        node = subnode, path = subpath;
    } while (path != NULL);
    *node_store = node;
    return 0;
}
Esempio n. 22
0
static int pipe_inode_reclaim(struct inode *node)
{
	struct pipe_inode *pin = vop_info(node, pipe_inode);
	if (pin->name != NULL) {
		struct pipe_fs *pipe = fsop_info(vop_fs(node), pipe);
		lock_pipe(pipe);
		assert(pin->reclaim_count > 0);
		if ((--pin->reclaim_count) != 0 || inode_ref_count(node) != 0) {
			unlock_pipe(pipe);
			return -E_BUSY;
		}
		list_del(&(pin->pipe_link));
		unlock_pipe(pipe);
		kfree(pin->name);
	}
	pipe_state_release(pin->state);
	vop_kill(node);
	return 0;
}
Esempio n. 23
0
static int
sfs_getdirentry(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    off_t offset = iob->io_offset;
    if (offset < 0 || offset % sfs_dentry_size != 0) {
        kfree(entry);
        return -E_INVAL;
    }

    int ret, slot = offset / sfs_dentry_size;
    if (slot >= sin->din->dirinfo.slots + 2) {
        kfree(entry);
        return -E_NOENT;
    }
    switch (slot) {
    case 0:
        strcpy(entry->name, ".");
        break;
    case 1:
        strcpy(entry->name, "..");
        break;
    default:
        if ((ret = trylock_sin(sin)) != 0) {
            goto out;
        }
        ret = sfs_getdirentry_sub_nolock(sfs, sin, slot - 2, entry);
        unlock_sin(sin);
        if (ret != 0) {
            goto out;
        }
    }
    ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL);
out:
    kfree(entry);
    return ret;
}
Esempio n. 24
0
/*
 * sfs_fsync - Force any dirty inode info associated with this file to stable storage.
 */
static int
sfs_fsync(struct inode *node) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    int ret = 0;
    if (sin->dirty) {
        lock_sin(sin);
        {
            if (sin->dirty) {
                sin->dirty = 0;
                if ((ret = sfs_wbuf(sfs, sin->din, sizeof(struct sfs_disk_inode), sin->ino, 0)) != 0) {
                    sin->dirty = 1;
                }
            }
        }
        unlock_sin(sin);
    }
    return ret;
}
Esempio n. 25
0
static int
sfs_fsync(struct inode *node) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    if (sin->din->nlinks == 0 || !sin->dirty) {
        return 0;
    }
    int ret;
    if ((ret = trylock_sin(sin)) != 0) {
        return ret;
    }
    if (sin->dirty) {
        sin->dirty = 0;
        if ((ret = sfs_wbuf(sfs, sin->din, sizeof(struct sfs_disk_inode), sin->ino, 0)) != 0) {
            sin->dirty = 1;
        }
    }
    unlock_sin(sin);
    return ret;
}
Esempio n. 26
0
/*
 * sfs_lookup - Parse path relative to the passed directory
 *              DIR, and hand back the inode for the file it
 *              refers to.
 */
static int
sfs_lookup(struct inode *node, char *path, struct inode **node_store) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    assert(*path != '\0' && *path != '/');
    vop_ref_inc(node);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    if (sin->din->type != SFS_TYPE_DIR) {
        vop_ref_dec(node);
        return -E_NOTDIR;
    }
    struct inode *subnode;
    int ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL);

    vop_ref_dec(node);
    if (ret != 0) {
        return ret;
    }
    *node_store = subnode;
    return 0;
}
Esempio n. 27
0
static int
sfs_link(struct inode *node, const char *name, struct inode *link_node) {
    if (strlen(name) > SFS_MAX_FNAME_LEN) {
        return -E_TOO_BIG;
    }
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
        return -E_EXISTS;
    }
    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if (lnksin->din->type == SFS_TYPE_DIR) {
        return -E_ISDIR;
    }
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    int ret;
    if ((ret = trylock_sin(sin)) == 0) {
        ret = sfs_link_nolock(sfs, sin, lnksin, name);
        unlock_sin(sin);
    }
    return ret;
}
Esempio n. 28
0
/*
 * sfs_reclaim - Free all resources inode occupied . Called when inode is no longer in use.
 */
static int
sfs_reclaim(struct inode *node) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int  ret = -E_BUSY;
    uint32_t ent;
    lock_sfs_fs(sfs);
    assert(sin->reclaim_count > 0);
    if ((-- sin->reclaim_count) != 0 || inode_ref_count(node) != 0) {
        goto failed_unlock;
    }
    if (sin->din->nlinks == 0) {
        if ((ret = vop_truncate(node, 0)) != 0) {
            goto failed_unlock;
        }
    }
    if (sin->dirty) {
        if ((ret = vop_fsync(node)) != 0) {
            goto failed_unlock;
        }
    }
    sfs_remove_links(sin);
    unlock_sfs_fs(sfs);

    if (sin->din->nlinks == 0) {
        sfs_block_free(sfs, sin->ino);
        if ((ent = sin->din->indirect) != 0) {
            sfs_block_free(sfs, ent);
        }
    }
    kfree(sin->din);
    vop_kill(node);
    return 0;

failed_unlock:
    unlock_sfs_fs(sfs);
    return ret;
}
static int
sfs_getdirentry(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if ((entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        // kprintf("%s %s %d -E_NO_MEM\n", __FILE__, __func__, __LINE__);
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int ret, slot;
    off_t offset = iob->io_offset;
    if (offset < 0 || offset % sfs_dentry_size != 0) {
        // kprintf("%s %s %d -E_INVAL\n", __FILE__, __func__, __LINE__);
        kfree(entry);
        return -E_INVAL;
    }
    if ((slot = offset / sfs_dentry_size) > sin->din->blocks) {
        // kprintf("%s %s %d -E_NOENT\n", __FILE__, __func__, __LINE__);
        kfree(entry);
        return -E_NOENT;
    }
    lock_sin(sin);
    if ((ret = sfs_getdirentry_sub_nolock(sfs, sin, slot, entry)) != 0) {
        unlock_sin(sin);
        // kprintf("%s %s %d can not find!!! slot is %d\n", __FILE__, __func__, __LINE__, slot);
        goto out;
    }
    unlock_sin(sin);
    // kprintf("sfs_getdirentry\n");
    ret = iobuf_move(iob, entry->name, sfs_dentry_size, 1, NULL);
out:
    kfree(entry);
    return ret;
}
Esempio n. 30
0
static int
sfs_do_mount(struct device *dev, struct fs **fs_store) {

/*
 * Make sure SFS on-disk structures aren't messed up
 */
    static_assert(SFS_BLKSIZE >= sizeof(struct sfs_super));
    static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_inode));
    static_assert(SFS_BLKSIZE >= sizeof(struct sfs_disk_entry));

/*
 * We can't mount on devices with the wrong sector size.
 *
 * (Note: for all intents and purposes here, "sector" and
 * "block" are interchangeable terms. Technically a filesystem
 * block may be composed of several hardware sectors, but we
 * don't do that in sfs.)
 */
    if (dev->d_blocksize != SFS_BLKSIZE) {
        return -E_NA_DEV;
    }

    /* allocate fs structure */
    struct fs *fs;
    if ((fs = alloc_fs(sfs)) == NULL) {
        return -E_NO_MEM;
    }

    /* get sfs from fs.fs_info.__sfs_info */
    struct sfs_fs *sfs = fsop_info(fs, sfs);
    sfs->dev = dev;

    int ret = -E_NO_MEM;

    void *sfs_buffer;
    if ((sfs->sfs_buffer = sfs_buffer = kmalloc(SFS_BLKSIZE)) == NULL) {
        goto failed_cleanup_fs;
    }

    /* load and check sfs's superblock */
    if ((ret = sfs_init_read(dev, SFS_BLKN_SUPER, sfs_buffer)) != 0) {
        goto failed_cleanup_sfs_buffer;
    }

    ret = -E_INVAL;

    struct sfs_super *super = sfs_buffer;

    /* Make some simple sanity checks */
    if (super->magic != SFS_MAGIC) {
        cprintf("sfs: wrong magic in superblock. (%08x should be %08x).\n",
                super->magic, SFS_MAGIC);
        goto failed_cleanup_sfs_buffer;
    }
    if (super->blocks > dev->d_blocks) {
        cprintf("sfs: fs has %u blocks, device has %u blocks.\n",
                super->blocks, dev->d_blocks);
        goto failed_cleanup_sfs_buffer;
    }
    super->info[SFS_MAX_INFO_LEN] = '\0';
    sfs->super = *super;

    ret = -E_NO_MEM;

    uint32_t i;

    /* alloc and initialize hash list */
    list_entry_t *hash_list;
    if ((sfs->hash_list = hash_list = kmalloc(sizeof(list_entry_t) * SFS_HLIST_SIZE)) == NULL) {
        goto failed_cleanup_sfs_buffer;
    }
    for (i = 0; i < SFS_HLIST_SIZE; i ++) {
        list_init(hash_list + i);
    }

    /* load and check freemap (free space bitmap in disk) */
    struct bitmap *freemap;
    uint32_t freemap_size_nbits = sfs_freemap_bits(super);
    if ((sfs->freemap = freemap = bitmap_create(freemap_size_nbits)) == NULL) {
        goto failed_cleanup_hash_list;
    }
    uint32_t freemap_size_nblks = sfs_freemap_blocks(super);
    if ((ret = sfs_init_freemap(dev, freemap, SFS_BLKN_FREEMAP, freemap_size_nblks, sfs_buffer)) != 0) {
        goto failed_cleanup_freemap;
    }

    uint32_t blocks = sfs->super.blocks, unused_blocks = 0;
    for (i = 0; i < freemap_size_nbits; i ++) {
        if (bitmap_test(freemap, i)) {
            unused_blocks ++;
        }
    }
    assert(unused_blocks == sfs->super.unused_blocks);

    /* and other fields */
    sfs->super_dirty = 0;
    sem_init(&(sfs->fs_sem), 1);
    sem_init(&(sfs->io_sem), 1);
    sem_init(&(sfs->mutex_sem), 1);
    list_init(&(sfs->inode_list));
    cprintf("sfs: mount: '%s' (%d/%d/%d)\n", sfs->super.info,
            blocks - unused_blocks, unused_blocks, blocks);

    /* Set up abstract fs calls */
    fs->fs_sync = sfs_sync;
    fs->fs_get_root = sfs_get_root;
    fs->fs_unmount = sfs_unmount;
    fs->fs_cleanup = sfs_cleanup;

    *fs_store = fs;
    return 0;

failed_cleanup_freemap:
    bitmap_destroy(freemap);
failed_cleanup_hash_list:
    kfree(hash_list);
failed_cleanup_sfs_buffer:
    kfree(sfs_buffer);
failed_cleanup_fs:
    kfree(fs);
    return ret;
}