Ticket #7433: improve_integration.patch

File improve_integration.patch, 5.5 KB (added by idefix, 13 years ago)

Improve integration of BFS FUSE module, allowing it to act as a mount-helper

  • src/tools/fs_shell/fuse.cpp

     
    414414
    415415
    416416static int
    417 fssh_fuse_session(const char* device, const char* mntPoint, const char* fsName)
     417mount_volume(const char* device, const char* mntPoint, const char* fsName)
    418418{
    419419    // Mount the volume in the root FS.
    420420    fssh_dev_t fsDev = _kern_mount(kMountPoint, device, fsName, 0, NULL, 0);
     
    440440            isErr ? "unknown" : info.volume_name,
    441441            mntPoint);
    442442    }
     443   
     444    return 0;
     445}
    443446
    444     // Run the fuse_main() loop.
    445     const char* argv[13];
    446     int fuseArgCount = 0;
    447447
    448     argv[fuseArgCount++] = (const char*)"bfs_fuse";
    449     argv[fuseArgCount++] = mntPoint;
    450     argv[fuseArgCount++] = (const char*)"-s";
    451     if (gIsDebug)
    452         argv[fuseArgCount++] = (const char*)"-d";
    453 
    454     initialiseFuseOps(&gFUSEOperations);
    455 
    456     int ret = fuse_main(fuseArgCount, (char**)argv, &gFUSEOperations, NULL);
    457 
     448static int
     449unmount_volume(const char* device, const char* mntPoint)
     450{
    458451    // Unmount the volume again.
    459452    // Avoid a "busy" vnode.
    460453    _kern_setcwd(-1, "/");
    461454    fssh_status_t error = _kern_unmount(kMountPoint, 0);
    462455    if (error != FSSH_B_OK) {
    463456        if (gIsDebug)
    464             fprintf(stderr, "Error: Unmounting FS failed: %s\n", fssh_strerror(error));
     457            fprintf(stderr, "Error: Unmounting FS failed: %s\n",
     458                fssh_strerror(error));
    465459        else
    466             syslog(LOG_INFO, "Error: Unmounting FS failed: %s", fssh_strerror(error));
     460            syslog(LOG_INFO, "Error: Unmounting FS failed: %s",
     461                fssh_strerror(error));
    467462        return 1;
    468463    }
    469464
    470465    if (!gIsDebug)
    471466        syslog(LOG_INFO, "UnMounted %s from %s", device, mntPoint);
     467   
     468    return 0;
     469}
    472470
    473     return ret;
     471
     472static int
     473fssh_fuse_session(const char* device, const char* mntPoint, const char* fsName,
     474    struct fuse_args& fuseArgs)
     475{
     476    int ret;
     477   
     478    ret = mount_volume(device, mntPoint, fsName);
     479    if (ret != 0)
     480        return ret;
     481   
     482    char* fuseOptions = NULL;
     483
     484    // default FUSE options
     485    char* fsNameOption = NULL;
     486    if (fuse_opt_add_opt(&fuseOptions, "allow_other") < 0
     487        || asprintf(&fsNameOption, "fsname=%s", device) < 0
     488        || fuse_opt_add_opt(&fuseOptions, fsNameOption) < 0) {
     489        unmount_volume(device, mntPoint);
     490        return 1;
     491    }
     492
     493    struct stat sbuf;
     494    if ((stat(device, &sbuf) == 0) && S_ISBLK(sbuf.st_mode)) {
     495        int blkSize = 512;
     496        fssh_dev_t volumeID = get_volume_id();
     497        if (volumeID >= 0) {
     498            fssh_fs_info info;
     499            if (_kern_read_fs_info(volumeID, &info) == FSSH_B_OK)
     500                blkSize = info.block_size;
     501        }
     502
     503        char* blkSizeOption = NULL;
     504        if (fuse_opt_add_opt(&fuseOptions, "blkdev") < 0
     505            || asprintf(&blkSizeOption, "blksize=%i", blkSize) < 0
     506            || fuse_opt_add_opt(&fuseOptions, blkSizeOption) < 0) {
     507            unmount_volume(device, mntPoint);
     508            return 1;
     509        }
     510    }
     511
     512    // Run the fuse_main() loop.
     513    if (fuse_opt_add_arg(&fuseArgs, "-s") < 0
     514        || fuse_opt_add_arg(&fuseArgs, "-o") < 0
     515        || fuse_opt_add_arg(&fuseArgs, fuseOptions) < 0) {
     516        unmount_volume(device, mntPoint);
     517        return 1;
     518    }
     519
     520    initialiseFuseOps(&gFUSEOperations);
     521
     522    int res = fuse_main(fuseArgs.argc, fuseArgs.argv, &gFUSEOperations, NULL);
     523
     524    ret = unmount_volume(device, mntPoint);
     525    if (ret != 0)
     526        return ret;
     527
     528    return res;
    474529}
    475530
    476531
     
    488543}
    489544
    490545
    491 int
    492 main(int argc, const char* const* argv)
     546struct FsConfig {
     547    const char* device;
     548    const char* mntPoint;
     549};
     550
     551
     552enum {
     553    KEY_DEBUG,
     554    KEY_HELP
     555};
     556
     557
     558static int
     559process_options(void* data, const char* arg, int key, struct fuse_args* outArgs)
    493560{
    494     // eat options
    495     int argi = 1;
    496     while (argi < argc && argv[argi][0] == '-') {
    497         const char* arg = argv[argi++];
    498         if (strcmp(arg, "--help") == 0) {
    499             print_usage_and_exit(argv[0]);
    500         } else if (strcmp(arg, "-d") == 0) {
     561    struct FsConfig* config = (FsConfig*) data;
     562
     563    switch (key) {
     564        case FUSE_OPT_KEY_NONOPT:
     565            if (!config->device) {
     566                config->device = arg;
     567                return 0;
     568                    // don't pass the device path to fuse_main()
     569            } else if (!config->mntPoint)
     570                config->mntPoint = arg;
     571            else
     572                print_usage_and_exit(outArgs->argv[0]);
     573            break;
     574        case KEY_DEBUG:
    501575            gIsDebug = true;
    502         } else {
    503             print_usage_and_exit(argv[0]);
    504         }
     576            break;
     577        case KEY_HELP:
     578            print_usage_and_exit(outArgs->argv[0]);
    505579    }
    506580
    507     // get device
    508     if (argi >= argc)
    509         print_usage_and_exit(argv[0]);
    510     const char* device = argv[argi++];
    511     // get mountpoint
    512     if (argi >= argc)
    513         print_usage_and_exit(argv[0]);
    514     const char* mntPoint = argv[argi++];
    515     // more parameters are excess
    516     if (argi < argc)
    517         print_usage_and_exit(argv[0]);
     581    return 1;
     582}
    518583
     584
     585int
     586main(int argc, char* argv[])
     587{
     588    struct fuse_args fuseArgs = FUSE_ARGS_INIT(argc, argv);
     589    struct FsConfig config;
     590    memset(&config, 0, sizeof(config));
     591    const struct fuse_opt fsOptions[] = {
     592        FUSE_OPT_KEY("uhelper=",    FUSE_OPT_KEY_DISCARD),
     593            // fuse_main() throws an error about this unknown option
     594            // TODO: do not use fuse_main to mount filesystem, instead use
     595            // fuse_mount, fuse_new, fuse_set_signal_handlers and fuse_loop
     596        FUSE_OPT_KEY("-d",          KEY_DEBUG),
     597        FUSE_OPT_KEY("-h",          KEY_HELP),
     598        FUSE_OPT_KEY("--help",      KEY_HELP),
     599        FUSE_OPT_END
     600    };
     601
     602    if (fuse_opt_parse(&fuseArgs, &config, fsOptions, process_options) < 0)
     603        return 1;
     604
    519605    if (!modules[0]) {
    520606        fprintf(stderr, "Error: Couldn't find FS module!\n");
    521607        return 1;
     
    527613            fssh_strerror(error));
    528614        return error;
    529615    }
     616
    530617    const char* fsName = modules[0]->name;
    531     return fssh_fuse_session(device, mntPoint, fsName);
     618    return fssh_fuse_session(config.device, config.mntPoint, fsName, fuseArgs);
    532619}
    533620