Example #1
0
int do_mount(char *spec, char *dir, int mflag, char *opt)
{
	// VERIFY(mflag == 0);

	vfs_t *vfs = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
	if(vfs == NULL)
		return ENOMEM;

	VFS_INIT(vfs, zfs_vfsops, 0);
	VFS_HOLD(vfs);

	struct mounta uap = {
	.spec = spec,
	.dir = dir,
	.flags = mflag | MS_SYSSPACE,
	.fstype = "zfs-fuse",
	.dataptr = "",
	.datalen = 0,
	.optptr = opt,
	.optlen = strlen(opt)
	};

	int ret;
	if ((ret = VFS_MOUNT(vfs, rootdir, &uap, kcred)) != 0) {
		kmem_free(vfs, sizeof(vfs_t));
		return ret;
	}
	/* Actually, optptr is totally ignored by VFS_MOUNT.
	 * So we are going to pass this with fuse_mount_options if possible */
    if (fuse_mount_options == NULL)
        fuse_mount_options = "";
	char real_opts[1024];
	*real_opts = 0;
	if (*fuse_mount_options)
		strcat(real_opts,fuse_mount_options); // comes with a starting ,
	if (*opt)
		sprintf(&real_opts[strlen(real_opts)],",%s",opt);

#ifdef DEBUG
	atomic_inc_32(&mounted);;

	fprintf(stderr, "mounting %s\n", dir);
#endif

	char *fuse_opts = NULL;
	int has_default_perm = 0;
	if (fuse_version() <= 27) {
	if(asprintf(&fuse_opts, FUSE_OPTIONS, spec, real_opts) == -1) {
		VERIFY(do_umount(vfs, B_FALSE) == 0);
		return ENOMEM;
	}
	} else {
	  if(asprintf(&fuse_opts, FUSE_OPTIONS ",big_writes", spec, real_opts) == -1) {
	    VERIFY(do_umount(vfs, B_FALSE) == 0);
	    return ENOMEM;
	  }
	}
	
	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);

	if(fuse_opt_add_arg(&args, "") == -1 ||
	   fuse_opt_add_arg(&args, "-o") == -1 ||
	   fuse_opt_add_arg(&args, fuse_opts) == -1) {
		fuse_opt_free_args(&args);
		free(fuse_opts);
		VERIFY(do_umount(vfs, B_FALSE) == 0);
		return ENOMEM;
	}
	has_default_perm = detect_fuseoption(fuse_opts,"default_permissions");
	free(fuse_opts);

	struct fuse_chan *ch = fuse_mount(dir, &args);

	if(ch == NULL) {
		VERIFY(do_umount(vfs, B_FALSE) == 0);
		return EIO;
	}

	if (has_default_perm)
	    vfs->fuse_attribute = FUSE_VFS_HAS_DEFAULT_PERM;

	struct fuse_session *se = fuse_lowlevel_new(&args, &zfs_operations, sizeof(zfs_operations), vfs);
	fuse_opt_free_args(&args);

	if(se == NULL) {
		VERIFY(do_umount(vfs, B_FALSE) == 0); /* ZFSFUSE: FIXME?? */
		fuse_unmount(dir,ch);
		return EIO;
	}

	fuse_session_add_chan(se, ch);

	if(zfsfuse_newfs(dir, ch) != 0) {
		fuse_session_destroy(se);
		fuse_unmount(dir,ch);
		return EIO;
	}

	return 0;
}
Example #2
0
/*
 * Configure root file system.
 */
int
rootconf(void)
{
	int error;
	struct vfssw *vsw;
	extern void pm_init(void);

	BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
	BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
	BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
	BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));

	/*
	 * Install cluster modules that were only loaded during
	 * loadrootmodules().
	 */
	if (error = clboot_rootconf())
		return (error);

	if (root_is_svm) {
		(void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME);

		BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name));
		BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath));
	}

	/*
	 * Run _init on the root filesystem (we already loaded it
	 * but we've been waiting until now to _init it) which will
	 * have the side-effect of running vsw_init() on this vfs.
	 * Because all the nfs filesystems are lumped into one
	 * module we need to special case it.
	 */
	if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
		if (modload("fs", "nfs") == -1) {
			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
			    rootfs.bo_fstype);
			return (ENXIO);
		}
	} else {
		if (modload("fs", rootfs.bo_fstype) == -1) {
			cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
			    rootfs.bo_fstype);
			return (ENXIO);
		}
	}
	RLOCK_VFSSW();
	vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
	RUNLOCK_VFSSW();
	VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
	VFS_HOLD(rootvfs);

	if (root_is_svm) {
		rootvfs->vfs_flag |= VFS_RDONLY;
	}

	/*
	 * This pm-releated call has to occur before root is mounted since we
	 * need to power up all devices.  It is placed after VFS_INIT() such
	 * that opening a device via ddi_lyr_ interface just before root has
	 * been mounted would work.
	 */
	pm_init();

	if (netboot) {
		if ((error = strplumb()) != 0) {
			cmn_err(CE_CONT, "Cannot plumb network device\n");
			return (error);
		}
	}

	/*
	 * ufs_mountroot() ends up calling getrootdev()
	 * (below) which actually triggers the _init, identify,
	 * probe and attach of the drivers that make up root device
	 * bush; these are also quietly waiting in memory.
	 */
	BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));

	error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
	vfs_unrefvfssw(vsw);
	rootdev = rootvfs->vfs_dev;

	if (error)
		cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
		    rootfs.bo_name, rootfs.bo_fstype);
	else
		cmn_err(CE_CONT, "?root on %s fstype %s\n",
		    rootfs.bo_name, rootfs.bo_fstype);
	return (error);
}
Example #3
0
/*
 * Get/Make vfs structure for given real vfs
 */
static struct vfs *
makelfsnode(struct vfs *vfsp, struct loinfo *li)
{
    struct lfsnode *lfs;
    struct lfsnode *tlfs;

    /*
     * Don't grab any locks for the fast (common) case.
     */
    if (vfsp == li->li_realvfs)
        return (li->li_mountvfs);
    ASSERT(li->li_refct > 0);
    mutex_enter(&li->li_lfslock);
    if ((lfs = lfsfind(vfsp, li)) == NULL) {
        mutex_exit(&li->li_lfslock);
        lfs = kmem_zalloc(sizeof (*lfs), KM_SLEEP);
        mutex_enter(&li->li_lfslock);
        if ((tlfs = lfsfind(vfsp, li)) != NULL) {
            kmem_free(lfs, sizeof (*lfs));
            lfs = tlfs;
            goto found_lfs;
        }
        lfs->lfs_realvfs = vfsp;

        /*
         * Even though the lfsnode is strictly speaking a private
         * implementation detail of lofs, it should behave as a regular
         * vfs_t for the benefit of the rest of the kernel.
         */
        VFS_INIT(&lfs->lfs_vfs, lo_vfsops, (caddr_t)li);
        lfs->lfs_vfs.vfs_fstype = li->li_mountvfs->vfs_fstype;
        lfs->lfs_vfs.vfs_flag =
            ((vfsp->vfs_flag | li->li_mflag) & ~li->li_dflag) &
            INHERIT_VFS_FLAG;
        lfs->lfs_vfs.vfs_bsize = vfsp->vfs_bsize;
        lfs->lfs_vfs.vfs_dev = vfsp->vfs_dev;
        lfs->lfs_vfs.vfs_fsid = vfsp->vfs_fsid;

        if (vfsp->vfs_mntpt != NULL) {
            lfs->lfs_vfs.vfs_mntpt = vfs_getmntpoint(vfsp);
            /* Leave a reference to the mountpoint */
        }

        (void) VFS_ROOT(vfsp, &lfs->lfs_realrootvp);

        /*
         * We use 1 instead of 0 as the value to associate with
         * an idle lfs_vfs.  This is to prevent VFS_RELE()
         * trying to kmem_free() our lfs_t (which is the wrong
         * size).
         */
        VFS_HOLD(&lfs->lfs_vfs);
        lfs->lfs_next = li->li_lfs;
        li->li_lfs = lfs;
        vfs_propagate_features(vfsp, &lfs->lfs_vfs);
    }

found_lfs:
    VFS_HOLD(&lfs->lfs_vfs);
    mutex_exit(&li->li_lfslock);
    return (&lfs->lfs_vfs);
}