예제 #1
0
/*
 * See the comment in vnode.h for what is expected of this function.
 *
 * When this function returns, the inode refcount of the unlinked file
 * should be decremented.
 *
 * You probably want to use s5_remove_dirent().
 */
static int
s5fs_unlink(vnode_t *dir, const char *name, size_t namelen)
{
    KASSERT(dir->vn_ops->mkdir != NULL);

    kmutex_lock(&dir->vn_mutex);
    int ret = s5_remove_dirent(dir, name, namelen);
    kmutex_unlock(&dir->vn_mutex);
    return ret;
}
예제 #2
0
/*
 * See the comment in vnode.h for what is expected of this function.
 *
 * When this function returns, the inode refcount on the parent should be
 * decremented (since ".." in the removed directory no longer references
 * it). Remember that the directory must be empty (except for "." and
 * "..").
 *
 * You probably want to use s5_find_dirent() and s5_remove_dirent().
 */
static int
s5fs_rmdir(vnode_t *parent, const char *name, size_t namelen)
{
    KASSERT(!(namelen == 1 && name[0] == '.'));
    KASSERT(!(namelen == 2 && name[0] == '.' && name[1] == '.'));
    KASSERT(parent->vn_ops->rmdir != NULL);

    kmutex_lock(&parent->vn_mutex);

    int ino = s5_find_dirent(parent, name, namelen);

    /* we check in do_rmdir to make sure the directory exists */
    KASSERT(ino != -ENOENT);

    if (ino < 0){
        dbg(DBG_S5FS, "error finding child dir to delete\n");
        kmutex_unlock(&parent->vn_mutex);
        return ino;
    }

    vnode_t *child = vget(VNODE_TO_S5FS(parent)->s5f_fs, ino);
    kmutex_lock(&child->vn_mutex);

    int dot_lookup_res = s5_find_dirent(child, ".", 1);
    int dotdot_lookup_res = s5_find_dirent(child, "..", 2);

    KASSERT(dot_lookup_res != -ENOENT && dotdot_lookup_res != -ENOENT);

    if (dot_lookup_res < 0 || dotdot_lookup_res < 0){
        dbg(DBG_S5FS, "error reading dirents of directory to delete\n");
        kmutex_unlock(&child->vn_mutex);
        kmutex_unlock(&parent->vn_mutex);
        return (dot_lookup_res < 0) ? dot_lookup_res : dotdot_lookup_res;
    }

    KASSERT((unsigned) child->vn_len >= 2 * sizeof(s5_dirent_t));

    if ((unsigned) child->vn_len > 2 * sizeof(s5_dirent_t)){
        vput(child);
        kmutex_unlock(&child->vn_mutex);
        kmutex_unlock(&parent->vn_mutex);
        return -ENOTEMPTY;
    }

    vput(child);

    VNODE_TO_S5INODE(parent)->s5_linkcount--;
    s5_dirty_inode(VNODE_TO_S5FS(parent), VNODE_TO_S5INODE(parent));

    kmutex_unlock(&child->vn_mutex);
    kmutex_unlock(&parent->vn_mutex);
    return s5_remove_dirent(parent, name, namelen);
}
예제 #3
0
/*
 * s5fs_unlink:
 * s5fs_unlink removes the link to the vnode in dir specified by name
 * param *dir: the parent's vnode
 * param *name: name string
 * param namelen: the length of the name
 * return: 0 on success, and negative number on a variety of errors
 */
static int
s5fs_unlink(vnode_t *dir, const char *name, size_t namelen)
{
    dbg(DBG_S5FS, "{\n");
    
    KASSERT(dir != NULL);
    KASSERT(name != NULL);
    KASSERT(namelen <= S5_NAME_LEN-1);
    
    kmutex_lock(&dir->vn_mutex);
    
    int ret = 0;
    
    if ((ret = s5_remove_dirent(dir, name, namelen)) < 0)
    {
        kmutex_unlock(&dir->vn_mutex);
        return ret;
    }
    
    kmutex_unlock(&dir->vn_mutex);
    dbg(DBG_S5FS, "}\n");
    
    return ret;
}
예제 #4
0
/*
 * s5fs_rmdir:
 * s5fs_rmdir removes the directory called name from dir. the directory
 * to be removed must be empty (except for . and .. of course).
 * param *parent: the pointer to the parent dir of the name specified
 * param *name: name string
 * param namelen: the length of the name string
 * return: 0 on success; negative numbers on a variety of errors
 */
static int
s5fs_rmdir(vnode_t *parent, const char *name, size_t namelen)
{
    dbg(DBG_S5FS, "{\n");
    
    KASSERT(parent != NULL);
    KASSERT(name != NULL);
    KASSERT(namelen <= NAME_LEN - 1);
    KASSERT((uint32_t)parent->vn_len == VNODE_TO_S5INODE(parent)->s5_size);
    
    kmutex_lock(&parent->vn_mutex);
    
    int inode_number = 0;
    if ((inode_number = s5_find_dirent(parent, name, namelen)) < 0)
    {
        kmutex_unlock(&parent->vn_mutex);
        /* Need vput? */
        return inode_number;
    }
    
    /* May block here */
    vnode_t* vn = vget(parent->vn_fs, inode_number);
    KASSERT(vn != NULL);
    
    if (!S_ISDIR(vn->vn_mode))
    {
        /* May block here */
        vput(vn);
        kmutex_unlock(&parent->vn_mutex);
        return -ENOTDIR;
    }
    
    /* Check empty */
    if (VNODE_TO_S5INODE(vn)->s5_size > sizeof(dirent_t)*2)
    {
        vput(vn);
        kmutex_unlock(&parent->vn_mutex);
        return -ENOTEMPTY;
    }
    
    int ret;
    if ((ret = s5_remove_dirent(parent, name, namelen)) < 0)
    {
        /* May block here */
        vput(vn);
        kmutex_unlock(&parent->vn_mutex);
        return ret;
    }
    /* Decrease the linkcount because .. is removed */
    s5_inode_t* parent_inode = VNODE_TO_S5INODE(parent);
    parent_inode->s5_linkcount--;
    s5_dirty_inode(VNODE_TO_S5FS(parent), parent_inode);
    
    /* May block here */
    vput(vn);
    kmutex_unlock(&parent->vn_mutex);
    
    dbg(DBG_S5FS, "}\n");
    
    return ret;
}