Пример #1
0
/**
 * This should allocate memory for sf_inode_info, compute a unique inode
 * number, get an inode from vfs, initialize inode info, instantiate
 * dentry.
 *
 * @param parent        inode entry of the directory
 * @param dentry        directory cache entry
 * @param path          path name
 * @param info          file information
 * @param handle        handle
 * @returns 0 on success, Linux error code otherwise
 */
static int sf_instantiate(struct inode *parent, struct dentry *dentry,
                          SHFLSTRING *path, PSHFLFSOBJINFO info, SHFLHANDLE handle)
{
    int err;
    ino_t ino;
    struct inode *inode;
    struct sf_inode_info *sf_new_i;
    struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb);

    TRACE();
    BUG_ON(!sf_g);

    sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
    if (!sf_new_i)
    {
        LogRelFunc(("could not allocate inode info.\n"));
        err = -ENOMEM;
        goto fail0;
    }

    ino = iunique(parent->i_sb, 1);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    inode = iget_locked(parent->i_sb, ino);
#else
    inode = iget(parent->i_sb, ino);
#endif
    if (!inode)
    {
        LogFunc(("iget failed\n"));
        err = -ENOMEM;
        goto fail1;
    }

    sf_init_inode(sf_g, inode, info);
    sf_new_i->path = path;
    SET_INODE_INFO(inode, sf_new_i);
    sf_new_i->force_restat = 1;
    sf_new_i->force_reread = 0;

    d_instantiate(dentry, inode);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    unlock_new_inode(inode);
#endif

    /* Store this handle if we leave the handle open. */
    sf_new_i->handle = handle;
    return 0;

fail1:
    kfree(sf_new_i);

fail0:
    return err;

}
Пример #2
0
static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
    struct sf_glob_info *sf_g;
    struct vbsf_mount_info_new *info;
    struct sf_inode_info *sf_i;
    struct inode *iroot;
    SHFLFSOBJINFO fsinfo;
    int err;

    printk(KERN_DEBUG "ENTER: sf_remount_fs\n");
    sf_g = GET_GLOB_INFO(sb);
    BUG_ON(!sf_g);
    BUG_ON(data[0] != 0);
    info = (struct vbsf_mount_info_new *)data;
    BUG_ON(   info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
           || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
           || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2);

    sf_g->uid = info->uid;
    sf_g->gid = info->gid;
    sf_g->ttl = info->ttl;
    sf_g->dmode = info->dmode;
    sf_g->fmode = info->fmode;
    sf_g->dmask = info->dmask;
    sf_g->fmask = info->fmask;

    iroot = ilookup(sb, 0);
    if (!iroot)
    {
        printk(KERN_DEBUG "can't find root inode\n");
        return -ENOSYS;
    }
    sf_i = GET_INODE_INFO(iroot);
    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
    BUG_ON(err != 0);
    sf_init_inode(sf_g, iroot, &fsinfo);
    /*unlock_new_inode(iroot);*/
    printk(KERN_DEBUG "LEAVE: sf_remount_fs\n");
    return 0;
#else
    return -ENOSYS;
#endif
}
Пример #3
0
static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
    struct sf_glob_info *sf_g;
    struct sf_inode_info *sf_i;
    struct inode *iroot;
    SHFLFSOBJINFO fsinfo;
    int err;

    sf_g = GET_GLOB_INFO(sb);
    BUG_ON(!sf_g);
    if (data && data[0] != 0)
    {
        struct vbsf_mount_info_new *info =
            (struct vbsf_mount_info_new *)data;
        if (   info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
            && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
            && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2)
        {
            sf_g->uid = info->uid;
            sf_g->gid = info->gid;
            sf_g->ttl = info->ttl;
            sf_g->dmode = info->dmode;
            sf_g->fmode = info->fmode;
            sf_g->dmask = info->dmask;
            sf_g->fmask = info->fmask;
        }
    }

    iroot = ilookup(sb, 0);
    if (!iroot)
        return -ENOSYS;

    sf_i = GET_INODE_INFO(iroot);
    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
    BUG_ON(err != 0);
    sf_init_inode(sf_g, iroot, &fsinfo);
    /*unlock_new_inode(iroot);*/
    return 0;
#else
    return -ENOSYS;
#endif
}
Пример #4
0
/* this is called directly as iop on 2.4, indirectly as dop
   [sf_dentry_revalidate] on 2.4/2.6, indirectly as iop through
   [sf_getattr] on 2.6. the job is to find out whether dentry/inode is
   still valid. the test is failed if [dentry] does not have an inode
   or [sf_stat] is unsuccessful, otherwise we return success and
   update inode attributes */
int sf_inode_revalidate(struct dentry *dentry)
{
    int err;
    struct sf_glob_info *sf_g;
    struct sf_inode_info *sf_i;
    SHFLFSOBJINFO info;

    TRACE();
    if (!dentry || !dentry->d_inode)
    {
        LogFunc(("no dentry(%p) or inode(%p)\n", dentry, dentry->d_inode));
        return -EINVAL;
    }

    sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb);
    sf_i = GET_INODE_INFO(dentry->d_inode);

#if 0
    printk("%s called by %p:%p\n",
            sf_i->path->String.utf8,
            __builtin_return_address (0),
            __builtin_return_address (1));
#endif

    BUG_ON(!sf_g);
    BUG_ON(!sf_i);

    if (!sf_i->force_restat)
    {
        if (jiffies - dentry->d_time < sf_g->ttl)
            return 0;
    }

    err = sf_stat(__func__, sf_g, sf_i->path, &info, 1);
    if (err)
        return err;

    dentry->d_time = jiffies;
    sf_init_inode(sf_g, dentry->d_inode, &info);
    return 0;
}
Пример #5
0
/**
 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
 * wants to read super_block.
 *
 * calls [sf_glob_alloc] to map the folder and allocate global
 * information structure.
 *
 * initializes [sb], initializes root inode and dentry.
 *
 * should respect [flags]
 */
static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
{
    int err;
    struct dentry *droot;
    struct inode *iroot;
    struct sf_inode_info *sf_i;
    struct sf_glob_info *sf_g;
    SHFLFSOBJINFO fsinfo;
    struct vbsf_mount_info_new *info;

    TRACE();
    if (!data)
    {
        LogFunc(("no mount info specified\n"));
        return -EINVAL;
    }

    info = data;

    if (flags & MS_REMOUNT)
    {
        LogFunc(("remounting is not supported\n"));
        return -ENOSYS;
    }

    err = sf_glob_alloc(info, &sf_g);
    if (err)
        goto fail0;

    sf_i = kmalloc(sizeof (*sf_i), GFP_KERNEL);
    if (!sf_i)
    {
        err = -ENOMEM;
        LogRelFunc(("could not allocate memory for root inode info\n"));
        goto fail1;
    }

    sf_i->handle = SHFL_HANDLE_NIL;
    sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
    if (!sf_i->path)
    {
        err = -ENOMEM;
        LogRelFunc(("could not allocate memory for root inode path\n"));
        goto fail2;
    }

    sf_i->path->u16Length = 1;
    sf_i->path->u16Size = 2;
    sf_i->path->String.utf8[0] = '/';
    sf_i->path->String.utf8[1] = 0;

    err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
    if (err)
    {
        LogFunc(("could not stat root of share\n"));
        goto fail3;
    }

    sb->s_magic = 0xface;
    sb->s_blocksize = 1024;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
    /* Required for seek/sendfile.
     *
     * Must by less than or equal to INT64_MAX despite the fact that the
     * declaration of this variable is unsigned long long. See determination
     * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
     * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
     * page cache into account and is the suggested limit. */
# if defined MAX_LFS_FILESIZE
    sb->s_maxbytes = MAX_LFS_FILESIZE;
# else
    sb->s_maxbytes = 0x7fffffffffffffffULL;
# endif
#endif
    sb->s_op = &sf_super_ops;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    iroot = iget_locked(sb, 0);
#else
    iroot = iget(sb, 0);
#endif
    if (!iroot)
    {
        err = -ENOMEM;  /* XXX */
        LogFunc(("could not get root inode\n"));
        goto fail3;
    }

    if (sf_init_backing_dev(sf_g))
    {
        err = -EINVAL;
        LogFunc(("could not init bdi\n"));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
        unlock_new_inode(iroot);
#endif
        goto fail4;
    }

    sf_init_inode(sf_g, iroot, &fsinfo);
    SET_INODE_INFO(iroot, sf_i);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
    unlock_new_inode(iroot);
#endif

    droot = d_alloc_root(iroot);
    if (!droot)
    {
        err = -ENOMEM;  /* XXX */
        LogFunc(("d_alloc_root failed\n"));
        goto fail5;
    }

    sb->s_root = droot;
    SET_GLOB_INFO(sb, sf_g);
    return 0;

fail5:
    sf_done_backing_dev(sf_g);

fail4:
    iput(iroot);

fail3:
    kfree(sf_i->path);

fail2:
    kfree(sf_i);

fail1:
    sf_glob_free(sf_g);

fail0:
    return err;
}
Пример #6
0
/**
 * This is called when vfs failed to locate dentry in the cache. The
 * job of this function is to allocate inode and link it to dentry.
 * [dentry] contains the name to be looked in the [parent] directory.
 * Failure to locate the name is not a "hard" error, in this case NULL
 * inode is added to [dentry] and vfs should proceed trying to create
 * the entry via other means. NULL(or "positive" pointer) ought to be
 * returned in case of success and "negative" pointer on error
 */
static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
                                , unsigned int flags
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
                                , struct nameidata *nd
#endif
                               )
{
    int err;
    struct sf_inode_info *sf_i, *sf_new_i;
    struct sf_glob_info *sf_g;
    SHFLSTRING *path;
    struct inode *inode;
    ino_t ino;
    SHFLFSOBJINFO fsinfo;

    TRACE();
    sf_g = GET_GLOB_INFO(parent->i_sb);
    sf_i = GET_INODE_INFO(parent);

    BUG_ON(!sf_g);
    BUG_ON(!sf_i);

    err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    if (err)
        goto fail0;

    err = sf_stat(__func__, sf_g, path, &fsinfo, 1);
    if (err)
    {
        if (err == -ENOENT)
        {
            /* -ENOENT: add NULL inode to dentry so it later can be
               created via call to create/mkdir/open */
            kfree(path);
            inode = NULL;
        }
        else
            goto fail1;
    }
    else
    {
        sf_new_i = kmalloc(sizeof(*sf_new_i), GFP_KERNEL);
        if (!sf_new_i)
        {
            LogRelFunc(("could not allocate memory for new inode info\n"));
            err = -ENOMEM;
            goto fail1;
        }
        sf_new_i->handle = SHFL_HANDLE_NIL;
        sf_new_i->force_reread = 0;

        ino = iunique(parent->i_sb, 1);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
        inode = iget_locked(parent->i_sb, ino);
#else
        inode = iget(parent->i_sb, ino);
#endif
        if (!inode)
        {
            LogFunc(("iget failed\n"));
            err = -ENOMEM;          /* XXX: ??? */
            goto fail2;
        }

        SET_INODE_INFO(inode, sf_new_i);
        sf_init_inode(sf_g, inode, &fsinfo);
        sf_new_i->path = path;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
        unlock_new_inode(inode);
#endif
    }

    sf_i->force_restat = 0;
    dentry->d_time = jiffies;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
    d_set_d_op(dentry, &sf_dentry_ops);
#else
    dentry->d_op = &sf_dentry_ops;
#endif
    d_add(dentry, inode);
    return NULL;

fail2:
    kfree(sf_new_i);

fail1:
    kfree(path);

fail0:
    return ERR_PTR(err);
}