Ejemplo n.º 1
0
__private_extern__
void
fuse_internal_vnode_disappear(vnode_t vp, vfs_context_t context, int how)
{   
    int err = 0;

    fuse_vncache_purge(vp);

    if (how != REVOKE_NONE) {
        err = fuse_internal_revoke(vp, REVOKEALL, context, how);
        if (err) {
            IOLog("MacFUSE: disappearing act: revoke failed (%d)\n", err);
        }

        err = vnode_recycle(vp);
        if (err) {
            IOLog("MacFUSE: disappearing act: recycle failed (%d)\n", err);
        }
    }
}
Ejemplo n.º 2
0
__private_extern__
void
fuse_internal_vnode_disappear(vnode_t vp, vfs_context_t context, int how)
{   
    int err = 0;

    fuse_vncache_purge(vp);

    if (how != REVOKE_NONE) {
        err = fuse_internal_revoke(vp, REVOKEALL, context, how);
        if (err) {
            IOLog("MacFUSE: disappearing act: revoke failed (%d)\n", err);
        }

#if __LP64__
        /* Checking whether the vnode is in the process of being recycled
         * to avoid the 'vnode reclaim in progress' kernel panic.
         *
         * Obviously this is a quick fix done without much understanding of
         * the code flow of a recycle operation, but it seems that we
         * shouldn't call this again if a recycle operation was the reason
         * that we got here.
         */
        if(!vnode_isrecycled(vp)) {
#endif
            err = vnode_recycle(vp);
            if (err) {
                IOLog("MacFUSE: disappearing act: recycle failed (%d)\n", err);
            }
#if __LP64__
        }
        else {
                IOLog("MacFUSE: Avoided 'vnode reclaim in progress' kernel "
                        "panic. What now?\n");
        }
#endif
    }
}
Ejemplo n.º 3
0
int
fuse_notify_inval_entry(struct fuse_data *data, struct fuse_iov *iov) {
    int err = 0;

    struct fuse_notify_inval_entry_out fnieo;
    char name[FUSE_MAXNAMLEN + 1];
    void *next;

    HNodeRef dhp;
    vnode_t dvp;
    vnode_t vp;
    struct componentname cn;

    next = fuse_abi_out(fuse_notify_inval_entry_out, DTOABI(data), iov->base,
                        &fnieo);
    if (fnieo.namelen > iov->len - ((char *)next - (char *)iov->base)) {
        return EINVAL;
    }
    if (fnieo.namelen > FUSE_MAXNAMLEN) {
        return ENAMETOOLONG;
    }
    memcpy(name, next, fnieo.namelen);
    name[fnieo.namelen] = '\0';

    err = (int)HNodeLookupRealQuickIfExists(data->fdev, (ino_t)fnieo.parent,
                                            0 /* fork index */, &dhp, &dvp);
    if (err) {
        return err;
    }
    assert(dvp != NULL);

    /*
     * We have to look up the vnode for the specified name in the vnode cache,
     * to purge it from the cache.
     *
     * Note: Without flag MAKEENTRY cache_lookup does not return the vnode.
     */
    memset(&cn, 0, sizeof(cn));
    cn.cn_nameiop = LOOKUP;
    cn.cn_flags = MAKEENTRY;
    cn.cn_namelen = fnieo.namelen;
    cn.cn_nameptr = name;

    fuse_nodelock_lock(VTOFUD(dvp), FUSEFS_EXCLUSIVE_LOCK);

    err = fuse_vncache_lookup(dvp, &vp, &cn);
    switch (err) {
    case -1:
        /* positive match */
        err = 0;
        fuse_vncache_purge(vp);
        vnode_put(vp);
    case 0:
        /* no match in cache */
        break;
    case ENOENT:
    /* negative match */
    default:
        goto out;
    }

    fuse_invalidate_attr(dvp);
    FUSE_KNOTE(dvp, NOTE_ATTRIB);

out:
    fuse_nodelock_unlock(VTOFUD(dvp));

    vnode_put(dvp);
    return err;
}
Ejemplo n.º 4
0
/* ioctl */
__private_extern__
int
fuse_internal_ioctl_avfi(vnode_t vp, __unused vfs_context_t context,
                         struct fuse_avfi_ioctl *avfi)
{
    int ret = 0;
    uint32_t hint = 0;

    if (!avfi) {
        return EINVAL;
    }

    if (avfi->cmd & FUSE_AVFI_MARKGONE) {

        /*
         * TBD
         */
        return EINVAL;
    }

    /* The result of this /does/ alter our return value. */
    if (avfi->cmd & FUSE_AVFI_UBC) {
        int ubc_flags = avfi->ubc_flags & (UBC_PUSHDIRTY  | UBC_PUSHALL |
                                           UBC_INVALIDATE | UBC_SYNC);
        if (ubc_msync(vp, (off_t)0, ubc_getsize(vp), (off_t*)0,
                      ubc_flags) == 0) {
            /* failed */
            ret = EINVAL; /* don't really have a good error to return */
        }
    }

    if (avfi->cmd & FUSE_AVFI_UBC_SETSIZE) {
        if (VTOFUD(vp)->filesize != avfi->size) {
            hint |= NOTE_WRITE;
            if (avfi->size > VTOFUD(vp)->filesize) {
                hint |= NOTE_EXTEND;
            }
            VTOFUD(vp)->filesize = avfi->size;
            ubc_setsize(vp, avfi->size);
        }
        (void)fuse_invalidate_attr(vp);
    }

    /* The result of this doesn't alter our return value. */
    if (avfi->cmd & FUSE_AVFI_PURGEATTRCACHE) {
        hint |= NOTE_ATTRIB;
        (void)fuse_invalidate_attr(vp);
    }

    /* The result of this doesn't alter our return value. */
    if (avfi->cmd & FUSE_AVFI_PURGEVNCACHE) {
        (void)fuse_vncache_purge(vp);
    }

    if (avfi->cmd & FUSE_AVFI_KNOTE) {
        hint |= avfi->note;
    }

    if (hint) {
        FUSE_KNOTE(vp, hint);
    }

    return ret;
}
Ejemplo n.º 5
0
/*
 * Because of the vagaries of how a filehandle can be used, we try not to
 * be too smart in here (we try to be smart elsewhere). It is required that
 * you come in here only if you really do not have the said filehandle--else
 * we panic.
 *
 * This function should be called with fufh_mtx mutex locked.
 */
int
fuse_filehandle_get(vnode_t       vp,
                    vfs_context_t context,
                    fufh_type_t   fufh_type,
                    int           mode)
{
    struct fuse_dispatcher  fdi;
    struct fuse_open_in    *foi;
    struct fuse_open_out   *foo;
    struct fuse_filehandle *fufh;
    struct fuse_vnode_data *fvdat = VTOFUD(vp);

    int err    = 0;
    int oflags = 0;
    int op     = FUSE_OPEN;

    fuse_trace_printf("fuse_filehandle_get(vp=%p, fufh_type=%d, mode=%x)\n",
                      vp, fufh_type, mode);

    fufh = &(fvdat->fufh[fufh_type]);

    if (FUFH_IS_VALID(fufh)) {
        panic("fuse4x: filehandle_get called despite valid fufh (type=%d)",
              fufh_type);
        /* NOTREACHED */
    }

    /*
     * Note that this means we are effectively FILTERING OUT open() flags.
     */
    oflags = fuse_filehandle_xlate_to_oflags(fufh_type);

    if (vnode_isdir(vp)) {
        op = FUSE_OPENDIR;
        if (fufh_type != FUFH_RDONLY) {
            log("fuse4x: non-rdonly fufh requested for directory\n");
            fufh_type = FUFH_RDONLY;
        }
    }

    fuse_dispatcher_init(&fdi, sizeof(*foi));
    fuse_dispatcher_make_vp(&fdi, op, vp, context);

    if (vnode_islnk(vp) && (mode & O_SYMLINK)) {
        oflags |= O_SYMLINK;
    }

    foi = fdi.indata;
    foi->flags = oflags;

    OSIncrementAtomic((SInt32 *)&fuse_fh_upcall_count);
    if ((err = fuse_dispatcher_wait_answer(&fdi))) {
        const char *vname = vnode_getname(vp);
        if (err == ENOENT) {
            /*
             * See comment in fuse_vnop_reclaim().
             */
            cache_purge(vp);
        }
        log("fuse4x: filehandle_get: failed for %s "
              "(type=%d, err=%d, caller=%p)\n",
              (vname) ? vname : "?", fufh_type, err,
               __builtin_return_address(0));
        if (vname) {
            vnode_putname(vname);
        }
        if (err == ENOENT) {
            fuse_vncache_purge(vp);
        }
        return err;
    }
    OSIncrementAtomic((SInt32 *)&fuse_fh_current);

    foo = fdi.answer;

    fufh->fh_id = foo->fh;
    fufh->open_count = 1;
    fufh->open_flags = oflags;
    fufh->fuse_open_flags = foo->open_flags;

    fuse_ticket_drop(fdi.ticket);

    return 0;
}