Exemple #1
0
static errval_t do_single_unmap(struct pmap_arm *pmap, genvaddr_t vaddr,
                                size_t pte_count, bool delete_cap)
{
    errval_t err;
    struct vnode *pt = find_ptable(pmap, vaddr);
    if (pt) {
        // analog to do_single_map we use 10 bits for tracking pages in user space -SG
        struct vnode *page = find_vnode(pt, ARM_USER_L2_OFFSET(vaddr));
        if (page && page->u.frame.pte_count == pte_count) {
            err = vnode_unmap(pt->u.vnode.cap, page->u.frame.cap,
                              page->entry, page->u.frame.pte_count);
            if (err_is_fail(err)) {
                DEBUG_ERR(err, "vnode_unmap");
                return err_push(err, LIB_ERR_VNODE_UNMAP);
            }

            // Free up the resources
            if (delete_cap) {
                err = cap_destroy(page->u.frame.cap);
                if (err_is_fail(err)) {
                    return err_push(err, LIB_ERR_PMAP_DO_SINGLE_UNMAP);
                }
            }
            remove_vnode(pt, page);
            slab_free(&pmap->slab, page);
        }
        else {
            return LIB_ERR_PMAP_FIND_VNODE;
        }
    }

    return SYS_ERR_OK;
}
Exemple #2
0
static status_t
nfs4_remove_dir(fs_volume* volume, fs_vnode* parent, const char* name)
{
	VnodeToInode* vti = reinterpret_cast<VnodeToInode*>(parent->private_node);
	TRACE("volume = %p, parent = %" B_PRIi64 ", name = %s", volume, vti->ID(),
		name);

	VnodeToInodeLocker _(vti);
	Inode* inode = vti->Get();
	if (inode == NULL)
		return B_ENTRY_NOT_FOUND;

	ino_t id;
	status_t result = inode->Remove(name, NF4DIR, &id);
	if (result != B_OK)
		return result;

	result = acquire_vnode(volume, id);
	if (result == B_OK) {
		result = get_vnode(volume, id, reinterpret_cast<void**>(&vti));
		ASSERT(result == B_OK);

		if (vti->Unlink(inode->fInfo.fNames, name))
			remove_vnode(volume, id);

		put_vnode(volume, id);
		put_vnode(volume, id);
	}

	return B_OK;
}
Exemple #3
0
// RemoveVNode
status_t
Volume::RemoveVNode(Node *node)
{
	if (fMounted)
		return remove_vnode(GetID(), node->GetID());
	status_t error = NodeRemoved(node);
	if (error == B_OK)
		delete node;
	return error;
}
Exemple #4
0
status_t
Inode::Unlink(Transaction& transaction)
{
	uint32 numLinks = fNode.NumLinks();
	TRACE("Inode::Unlink(): Current links: %lu\n", numLinks);

	if (numLinks == 0)
		return B_BAD_VALUE;

	if ((IsDirectory() && numLinks == 2) || (numLinks == 1))  {
		fUnlinked = true;

		TRACE("Inode::Unlink(): Putting inode in orphan list\n");
		ino_t firstOrphanID;
		status_t status = fVolume->SaveOrphan(transaction, fID, firstOrphanID);
		if (status != B_OK)
			return status;

		if (firstOrphanID != 0) {
			Vnode firstOrphan(fVolume, firstOrphanID);
			Inode* nextOrphan;

			status = firstOrphan.Get(&nextOrphan);
			if (status != B_OK)
				return status;

			fNode.SetNextOrphan(nextOrphan->ID());
		} else {
			// Next orphan link is stored in deletion time
			fNode.deletion_time = 0;
		}

		fNode.num_links = 0;

		status = remove_vnode(fVolume->FSVolume(), fID);
		if (status != B_OK)
			return status;
	} else
		fNode.SetNumLinks(--numLinks);

	return WriteBack(transaction);
}
Exemple #5
0
static status_t
nfs4_rename(fs_volume* volume, fs_vnode* fromDir, const char* fromName,
	fs_vnode* toDir, const char* toName)
{
	VnodeToInode* fromVti
		= reinterpret_cast<VnodeToInode*>(fromDir->private_node);
	VnodeToInode* toVti = reinterpret_cast<VnodeToInode*>(toDir->private_node);
	TRACE("volume = %p, fromDir = %" B_PRIi64 ", toDir = %" B_PRIi64 ","	\
		" fromName = %s, toName = %s", volume, fromVti->ID(), toVti->ID(),	\
		fromName, toName);

	VnodeToInodeLocker _from(fromVti);
	Inode* fromInode = fromVti->Get();
	if (fromInode == NULL)
		return B_ENTRY_NOT_FOUND;


	VnodeToInodeLocker _to(toVti);
	Inode* toInode = toVti->Get();
	if (toInode == NULL)
		return B_ENTRY_NOT_FOUND;

	ino_t id;
	ino_t oldID;
	status_t result = Inode::Rename(fromInode, toInode, fromName, toName, false,
		&id, &oldID);
	if (result != B_OK)
		return result;

	VnodeToInode* vti;

	if (oldID != 0) {
		// we have overriden an inode
		result = acquire_vnode(volume, oldID);
		if (result == B_OK) {
			result = get_vnode(volume, oldID, reinterpret_cast<void**>(&vti));
			ASSERT(result == B_OK);
			if (vti->Unlink(toInode->fInfo.fNames, toName))
				remove_vnode(volume, oldID);

			put_vnode(volume, oldID);
			put_vnode(volume, oldID);
		}
	}

	result = get_vnode(volume, id, reinterpret_cast<void**>(&vti));
	if (result == B_OK) {
		Inode* child = vti->Get();
		if (child == NULL) {
			put_vnode(volume, id);
			return B_ENTRY_NOT_FOUND;
		}

		unremove_vnode(volume, id);
		child->fInfo.fNames->RemoveName(fromInode->fInfo.fNames, fromName);
		child->fInfo.fNames->AddName(toInode->fInfo.fNames, toName);
		put_vnode(volume, id);
	}

	return B_OK;
}
Exemple #6
0
void remove_empty_vnodes(struct pmap_x86 *pmap, struct vnode *root,
                         uint32_t entry, size_t len)
{
    errval_t err;
    uint32_t end_entry = entry + len;
    for (struct vnode *n = root->u.vnode.children; n; n = n->next) {
        if (n->entry >= entry && n->entry < end_entry) {
            // sanity check and skip leaf entries
            if (!n->is_vnode) {
                continue;
            }
            // here we know that all vnodes we're interested in are
            // page tables
            assert(n->is_vnode);
            if (n->u.vnode.children) {
                remove_empty_vnodes(pmap, n, 0, PTABLE_SIZE);
            }

            // unmap
            err = vnode_unmap(root->u.vnode.cap, n->mapping);
            if (err_is_fail(err)) {
                debug_printf("remove_empty_vnodes: vnode_unmap: %s\n",
                        err_getstring(err));
            }

            // delete mapping cap first: underlying cap needs to exist for
            // this to work properly!
            err = cap_delete(n->mapping);
            if (err_is_fail(err)) {
                debug_printf("remove_empty_vnodes: cap_delete (mapping): %s\n",
                        err_getstring(err));
            }
            err = pmap->p.slot_alloc->free(pmap->p.slot_alloc, n->mapping);
            if (err_is_fail(err)) {
                debug_printf("remove_empty_vnodes: slot_free (mapping): %s\n",
                        err_getstring(err));
            }
            // delete capability
            err = cap_delete(n->u.vnode.cap);
            if (err_is_fail(err)) {
                debug_printf("remove_empty_vnodes: cap_delete (vnode): %s\n",
                        err_getstring(err));
            }
            if (!capcmp(n->u.vnode.cap, n->u.vnode.invokable)) {
                // invokable is always allocated in our cspace
                err = cap_destroy(n->u.vnode.invokable);
                if (err_is_fail(err)) {
                    debug_printf("remove_empty_vnodes: cap_delete (vnode.invokable): %s\n",
                        err_getstring(err));

                }
            }
            err = pmap->p.slot_alloc->free(pmap->p.slot_alloc, n->u.vnode.cap);
            if (err_is_fail(err)) {
                debug_printf("remove_empty_vnodes: slot_free (vnode): %s\n",
                        err_getstring(err));
            }

            // remove vnode from list
            remove_vnode(root, n);
            slab_free(&pmap->slab, n);
        }
    }
}
Exemple #7
0
// RemoveVNode
status_t
Volume::RemoveVNode(vnode_id vnid)
{
	return remove_vnode(fVolumeManager->GetID(), vnid);
}
Exemple #8
0
static int
rootfs_rename(void *_ns, void *_olddir, const char *oldname, void *_newdir,
                    const char *newname)
{
    nspace      *ns;
    vnode       *olddir, *newdir;
    int         err;
    vnode       *vn, *nvn, *pvn, *avn;
    char        *p;

    ns = (nspace *) _ns;
    olddir = (vnode *) _olddir;
    newdir = (vnode *) _newdir;

    LOCK(ns->lock);
    if (!MY_S_ISDIR(olddir->mode) || !MY_S_ISDIR(newdir->mode)) {
        err = ENOTDIR;
        goto error1;
    }
    
    /*
    find (olddir, oldname)
    */

    if (!strcmp(oldname, ".") || !strcmp(oldname, "..")) {
        err = EPERM;
        goto error1;
    }

    vn = olddir->head;
    while (vn) {
        if (!strcmp(vn->name, oldname))
            break;
        vn = vn->next;
    }
    if (!vn) {
        err = ENOENT;
        goto error1;
    }

    /*
    look for (newdir, newname)
    */

    if (!strcmp(newname, ".") || !strcmp(newname, "..")) {
        err = EPERM;
        goto error1;
    }

    nvn = newdir->head;
    while (nvn) {
        if (!strcmp(nvn->name, newname))
            break;
        nvn = nvn->next;
    }

    /*
    don't do anything if old and new are the same
    */

    if (vn == nvn)
        goto exit;

    /*
    make sure new is not a subdirectory of old
    */

    avn = newdir;
    while (avn != ns->root) {
        avn = avn->parent;
        if (avn == olddir) {
            err = EINVAL;
            goto error1;
        }
    }

    if (strlen(newname) > strlen(vn->name)) {
        p = (char *) realloc(vn->name, strlen(newname)+1);
        if (!p) {
            err = ENOMEM;
            goto error1;
        }
    } else
        p = vn->name;

    /*
    if (newdir, newname) exists, remove it from the name space
    */

    if (nvn) {

    /*
    make sure it is not the root and it is not empty
    */

        if (nvn == nvn->ns->root) {
            err = EBUSY;
            goto error1;
        }
        if (MY_S_ISDIR(nvn->mode) && nvn->head) {
            err = ENOTEMPTY;
            goto error1;
        }

        err = get_vnode(ns->nsid, nvn->vnid, (void *)&nvn);
        if (err)
            goto error1;

        err = remove_vnode(ns->nsid, nvn->vnid);
        if (err)
            goto error1;

        if (nvn->prev)
            nvn->prev->next = nvn->next;
        else
            nvn->parent->head = nvn->next;
        if (nvn->next)
            nvn->next->prev = nvn->prev;
        nvn->prev = nvn->next = NULL;

        put_vnode(ns->nsid, nvn->vnid);
    }

    if (vn->prev)
        vn->prev->next = vn->next;
    else
        vn->parent->head = vn->next;
    if (vn->next)
        vn->next->prev = vn->prev;

    pvn = NULL;
    nvn = newdir->head;
    while (nvn && (strcmp(newname, nvn->name) > 0)) {
        pvn = nvn;
        nvn = nvn->next;
    }
    vn->next = nvn;
    if (nvn)
        nvn->prev = vn;
    vn->prev = pvn;
    if (pvn)
        pvn->next = vn;
    else
        newdir->head = vn;

    vn->parent = newdir;
    newdir->mtime = olddir->mtime = time(NULL);
    strcpy(p, newname);
    vn->name = p;

exit:
    UNLOCK(ns->lock);
    return 0;

error1:
    UNLOCK(ns->lock);
    return err;
}
Exemple #9
0
static int
do_unlink(nspace *ns, vnode *dir, const char *name, bool isdir)
{
    int         err;
    vnode       *vn;

    LOCK(ns->lock);
    if (!MY_S_ISDIR(dir->mode)) {
        err = ENOTDIR;
        goto error1;
    }
    
    /*
    can't delete '..' and '.'
    */

    if (!strcmp(name, "..") || !strcmp(name, ".")) {
        err = EINVAL;
        goto error1;
    }
        
    /*
    lookup the name in the directory        
    */

    vn = dir->head;
    while (vn) {
        if (!strcmp(vn->name, name))
            break;
        vn = vn->next;
    }
    
    /*
    if it was not found, report an error.
    */

    if (!vn) {
        err = ENOENT;
        goto error1;
    }

    /*
    ensure it is of the appropriate type.
    */

    if (isdir && !(vn->mode & MY_S_IFDIR)) {
        err = ENOTDIR;
        goto error1;
    }

    if (!isdir && (vn->mode & MY_S_IFDIR)) {
        err = EISDIR;
        goto error1;
    }
        
    /*
    make sure it is not the root
    */

    if (vn == vn->ns->root) {
        err = EBUSY;
        goto error1;
    }

    /*
    if it is a directory, make sure it is empty
    */

    if (MY_S_ISDIR(vn->mode) && vn->head) {
        err = ENOTEMPTY;
        goto error1;
    }

    err = get_vnode(ns->nsid, vn->vnid, (void *)&vn);
    if (err)
        goto error1;

    err = remove_vnode(ns->nsid, vn->vnid);
    if (err)
        goto error1;

    if (vn->prev)
        vn->prev->next = vn->next;
    else
        vn->parent->head = vn->next;
    if (vn->next)
        vn->next->prev = vn->prev;
    vn->prev = vn->next = NULL;
    vn->removed = TRUE;
    dir->mtime = time(NULL);

    put_vnode(ns->nsid, vn->vnid);

    UNLOCK(ns->lock);

    return 0;

error1:
    UNLOCK(ns->lock);
    return err;
}