Exemple #1
0
struct dentry *
vnlayer_get_dentry(
    SUPER_T *sb,
    void *fhbits
)
{
    int error;
    VFS_T *vfsp = SBTOVFS(sb);
    VNODE_T *vp;
    MDKI_FID_T *lfidp = fhbits;
    DENT_T *dp;
    CALL_DATA_T cd;

    mdki_linux_init_call_data(&cd);
    error = VFS_VGET(vfsp, &vp, lfidp, &cd);
    if (error == 0) {
        /* rebind if needed */
        if (mfs_rebind_vpp(1, &vp, &cd)) {
            MDKI_VFS_LOG(VFS_LOG_ESTALE,
                      "%s: vp %p rebound\n",
                      __FUNCTION__, vp);
        }
        dp = vnlayer_find_dentry(vp);
        /* always drop vnode's refcount */
        VN_RELE(vp);
    } else {
        dp = ERR_PTR(mdki_errno_unix_to_linux(error));
    }
    mdki_linux_destroy_call_data(&cd);
    return dp;
}
Exemple #2
0
int
vnlayer_linux_statfs(
    DENT_T *dent_p,
    LINUX_STATFS_T *stat_p
)
#endif
{
    int error;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) && !defined(SLES10SP2)
    error = VFS_STATVFS(SBTOVFS(super_p), stat_p);
#else
    error = VFS_STATVFS(SBTOVFS(dent_p->d_sb), stat_p);
#endif
    return (-error);
}
Exemple #3
0
void
vnlayer_put_super(struct super_block *super_p)
{
    int err;
    CALL_DATA_T cd;

    ASSERT_KERNEL_LOCKED();
    ASSERT_SB_LOCKED(super_p);

    mdki_linux_init_call_data(&cd);
    err = VFS_UNMOUNT(SBTOVFS(super_p), &cd);
    mdki_linux_destroy_call_data(&cd);

    if (err != 0) {
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR,
                "Linux file system interface doesn't let vnode/vfs reject unmounts: error %d\n", err);
    }
    return /* mdki_errno_unix_to_linux(err)*/;
}
Exemple #4
0
void
vnlayer_put_super(struct super_block *super_p)
{
    int err;
    CRED_T *cred;

    ASSERT_KERNEL_LOCKED();
    ASSERT_SB_LOCKED(super_p);

    cred = MDKI_GET_UCRED();
    err = VFS_UNMOUNT(SBTOVFS(super_p), cred);
    MDKI_CRFREE(cred);

    if (err != 0) {
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR,
                "Linux file system interface doesn't let vnode/vfs reject unmounts: error %d\n", err);
    }
    return /* mdki_errno_unix_to_linux(err)*/;
}
Exemple #5
0
void
vnlayer_write_super(struct super_block *super_p)
{
    CALL_DATA_T cd;
    int err;

    ASSERT_SB_LOCKED(super_p);

    mdki_linux_init_call_data(&cd);
    err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd);
    mdki_linux_destroy_call_data(&cd);
    /* They rewrote sync_supers so that it won't proceed through their loop
     * until the dirty bit is cleared.
     */
    super_p->s_dirt = 0;
    if (err != 0)
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n",
                __func__, err);
    return /* mdki_errno_unix_to_linux(err) */;
}
Exemple #6
0
void
vnlayer_write_super(struct super_block *super_p)
{
    CRED_T *cred;
    int err;

    ASSERT_SB_LOCKED(super_p);

    cred = MDKI_GET_UCRED();
    err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, cred);
    MDKI_CRFREE(cred);
    /* They rewrote sync_supers so that it won't proceed through their loop
     * until the dirty bit is cleared.
     */
    super_p->s_dirt = 0;
    if (err != 0)
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n",
                __func__, err);
    return /* mdki_errno_unix_to_linux(err) */;
}
Exemple #7
0
int
vnlayer_remount_fs(
    struct super_block *super_p,
    int *flags,
    char *data
)
{
    VFS_T *vfsp = SBTOVFS(super_p);
    VFS_LOG(vfsp, VFS_LOG_ERR,
            "Vnode/VFS does not support remounting of file systems (sb=%p)\n",
            super_p);
    return -EINVAL;
}
Exemple #8
0
    /* They rewrote sync_supers so that it won't proceed through their loop
     * until the dirty bit is cleared.
     */
    super_p->s_dirt = 0;
    if (err != 0)
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n",
                __func__, err);
    return /* mdki_errno_unix_to_linux(err) */;
}
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
int
vnlayer_sync_super(
    struct super_block *super_p, 
    int wait
)
{
    CALL_DATA_T cd;
    int err;

    /* if wait is not allowed, do nothing */
    if (wait == 0) {
        return 0;
    }
    ASSERT_SB_LOCKED(super_p);
    mdki_linux_init_call_data(&cd);
    err = VFS_SYNC(SBTOVFS(super_p), SBTOVFS(super_p), 0, &cd);
    mdki_linux_destroy_call_data(&cd);
    if (err != 0) {
        VFS_LOG(SBTOVFS(super_p), VFS_LOG_ERR, "%s: error %d syncing\n",
                __func__, err);
    }
    return mdki_errno_unix_to_linux(err);
}
Exemple #9
0
int
vnlayer_fill_super(
    SUPER_T *super_p,
    void *data_p,
    int silent
)
{
    INODE_T *ino_p;
    VNODE_T *rootvp;
    VATTR_T va;
    VFS_T *vfsp;
    int err = 0;
    CALL_DATA_T cd;

    ASSERT_KERNEL_LOCKED();             /* sys_mount() */
    ASSERT_SB_MOUNT_LOCKED_W(super_p);

    /* can't assert on mount_sem, we don't have access to it. */

    if (vnlayer_vfs_opvec == NULL) {
        MDKI_VFS_LOG(VFS_LOG_ERR,
                     "%s: VFS operation not set yet "
                     "(no file system module loaded?)\n", __func__);
        err = -ENODATA;
        goto return_NULL;
    }

    if (MDKI_INOISOURS(vnlayer_get_urdir_inode())) {
        /* can't handle this case */
        MDKI_VFS_LOG(VFS_LOG_ERR,
                    "%s: can't handle mounts inside setview.\n", __func__);
        err = -EINVAL;
        goto return_NULL;
    }

    /*
     * The only fields we have coming in are s_type and s_flags.
     */
    /* Verify this */

    super_p->s_blocksize = MVFS_DEF_BLKSIZE;
    super_p->s_blocksize_bits = MVFS_DEF_BLKSIZE_BITS;
    super_p->s_maxbytes = MVFS_DEF_MAX_FILESIZE;
    super_p->s_op = &mvfs_super_ops;
    super_p->s_export_op = &vnlayer_export_ops;
    super_p->dq_op = NULL;
    super_p->s_magic = MVFS_SUPER_MAGIC;

    /*
     * XXX This module is currently restricted to one client file system
     * type at a time, as registered via the vnlayer_vfs_opvec.
     */
    vfsp = KMEM_ALLOC(sizeof(*vfsp), KM_SLEEP);
    if (vfsp == NULL) {
        MDKI_VFS_LOG(VFS_LOG_ERR, "%s failed: no memory\n", __func__);
        SET_SBTOVFS(super_p, NULL);
        err = -ENOMEM;
        goto return_NULL;
    }
    BZERO(vfsp, sizeof(*vfsp));
    SET_VFSTOSB(vfsp, super_p);
    SET_SBTOVFS(super_p, vfsp);
    vfsp->vfs_op = vnlayer_vfs_opvec;
    /* XXX fill in more of vfsp (flag?) */
    if (super_p->s_flags & MS_RDONLY)
        vfsp->vfs_flag |= VFS_RDONLY;
    if (super_p->s_flags & MS_NOSUID)
        vfsp->vfs_flag |= VFS_NOSUID;

    err = vnlayer_linux_mount(vfsp, data_p);

    if (err) {
        goto bailout;
    }

    /*
     * Now create our dentry and set that up in the superblock.  Get
     * the inode from the vnode at the root of the file system, and
     * attach it to a new dentry.
     */
    mdki_linux_init_call_data(&cd);
    err = VFS_ROOT(SBTOVFS(super_p), &rootvp);
    if (err) {
        err = mdki_errno_unix_to_linux(err);
        (void) VFS_UNMOUNT(vfsp,&cd);
        mdki_linux_destroy_call_data(&cd);
        goto bailout;
    }

    ino_p = VTOI(rootvp);

#ifdef CONFIG_FS_POSIX_ACL
    /* If the system supports ACLs, we set the flag in the superblock
     * depending on the ability of the underlying filesystem
     */
    if (vfsp->vfs_flag & VFS_POSIXACL) {
	super_p->s_flags |= MS_POSIXACL;
    }
#endif
    /*
     * Call getattr() to prime this inode with real attributes via the
     * callback to mdki_linux_vattr_pullup()
     */
    VATTR_NULL(&va);
    /* ignore error code, we're committed */
    (void) VOP_GETATTR(rootvp, &va, 0, &cd);

    /* This will allocate a dentry with a name of /, which is
     * what Linux uses in all filesystem roots.  The dentry is
     * also not put on the hash chains because Linux does not
     * hash file system roots.  It finds them through the super
     * blocks.
     */
    super_p->s_root = VNODE_D_ALLOC_ROOT(ino_p);
    if (super_p->s_root) {
        if (VFSTOSB(vnlayer_looproot_vp->v_vfsp) == super_p) {
            /* loopback names are done with regular dentry ops */
            MDKI_SET_DOPS(super_p->s_root, &vnode_dentry_ops);
        } else {
            /*
             * setview names come in via VOB mounts, they're marked
             * with setview dentry ops
             */
            MDKI_SET_DOPS(super_p->s_root, &vnode_setview_dentry_ops);
        }
        super_p->s_root->d_fsdata = NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
        atomic_set(&super_p->s_root->d_count, 1);
#endif
        /* d_alloc_root assumes that the caller will take care of
         * bumping the inode count for the dentry.  So we will oblige
         */
        igrab(ino_p);
    } else {
        VN_RELE(rootvp);
        (void) VFS_UNMOUNT(vfsp,&cd);
        mdki_linux_destroy_call_data(&cd);
        err = -ENOMEM;
        goto bailout;
    }
    mdki_linux_destroy_call_data(&cd);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
    super_p->s_dirt = 1;            /* we want to be called on
                                       write_super/sync() */
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)
    /* write back is delegated to the undelying fs */
    super_p->s_bdi = &noop_backing_dev_info;
#endif
    /*
     * release reference on rootvp--super block holds appropriate
     * references now
     */
    VN_RELE(rootvp);
    return(0);

  bailout:
    MDKI_VFS_LOG(VFS_LOG_ERR,
                 "%s failed: error %d\n", __func__,
                 vnlayer_errno_linux_to_unix(err));
    SET_SBTOVFS(super_p, NULL);
    KMEM_FREE(vfsp, sizeof(*vfsp));
  return_NULL:
    return(err);
}