#include #include #include #include "log.h" #include "fsal.h" #include "config_parsing.h" #include "FSAL/fsal_commonlib.h" #include "fsal_internal.h" #include "FSAL/fsal_init.h" #include "gsh_config.h" #include "fsal_stats.h" #include "fsal_types.h" #include "pnfs_utils.h" #include "nfs_exports.h" #include "ncsf_convert.h" #include "export.h" #include #include static const char myname[] = "NCDFS"; /** @struct NCDSS * @brief my module private storage * fs_info表示默认配置信息 */ struct ncdss_fsal_module NCSF_FS = { .module = { .fs_info = { .maxfilesize = INT64_MAX, .maxlink = 1024, .maxnamelen = 1024, .maxpathlen = 1024, .no_trunc = true, .chown_restricted = true, .case_insensitive = true, .case_preserving = true, .link_support = true, .symlink_support = true, .lock_support = true, .lock_support_async_block = true, .named_attr = true, .unique_handles = true, .acl_support = FSAL_ACLSUPPORT_ALLOW | FSAL_ACLSUPPORT_DENY, .cansettime = true, .homogenous = true, .supported_attrs = NCDSS_SUPPORTED_ATTRIBUTES, .maxread = FSAL_MAXIOSIZE, .maxwrite = FSAL_MAXIOSIZE, .umask = 0, .auth_exportpath_xdev = true, #if 0 /** not working with pNFS */ .delegations = FSAL_OPTION_FILE_READ_DELEG, #endif .pnfs_mds = true, .pnfs_ds = true, .fsal_trace = true, .fsal_grace = false, .link_supports_permission_checks = true, .expire_time_parent = 60, } } }; /** @struct ncdss_params * @brief Configuration items */ static struct config_item ncdss_params[] = { /* At the moment NCSF doesn't support WRITE delegations */ CONF_ITEM_ENUM_BITS("Delegations", FSAL_OPTION_FILE_READ_DELEG, FSAL_OPTION_FILE_DELEGATIONS, deleg_types, fsal_staticfsinfo_t, delegations), CONFIG_EOL }; /** @struct ncdss_param * @brief Configuration block */ static struct config_block ncdss_param = { .dbus_interface_name = "org.ganesha.nfsd.config.fsal.ncdfs", .blk_desc.name = "NCDFS", .blk_desc.type = CONFIG_BLOCK, .blk_desc.u.blk.init = noop_conf_init, .blk_desc.u.blk.params = ncdss_params, .blk_desc.u.blk.commit = noop_conf_commit }; static int log_to_ncdss(log_header_t headers, void *private, log_levels_t level, struct display_buffer *buffer, char *compstr, char *message) { FILE *stream = private; int rc; char *msg = buffer->b_start; int len; len = display_buffer_len(buffer); /* Add newline to end of buffer */ buffer->b_start[len] = '\n'; buffer->b_start[len + 1] = '\0'; switch (headers) { case LH_NONE: msg = message; break; case LH_COMPONENT: msg = compstr; break; case LH_ALL: msg = buffer->b_start; break; default: msg = "Somehow header level got messed up!!"; } rc = fputs(msg, stream); if (rc != EOF) rc = fflush(stream); /* Remove newline from buffer */ buffer->b_start[len] = '\0'; if (rc == EOF) return -1; else return 0; } /** @fn static fsal_status_t init_config(struct fsal_module *fsal_hdl, * config_file_t config_struct, struct config_error_type *err_type) * @brief must be called with a reference taken (via lookup_fsal) */ static fsal_status_t init_config(struct fsal_module *nf_module, config_file_t config_struct, struct config_error_type *err_type) { int rc; struct ncdss_fsal_module *myself = container_of(nf_module, struct ncdss_fsal_module, module); LogDebug(COMPONENT_FSAL, "NCSF module setup."); (void) load_config_from_parse(config_struct, &ncdss_param, myself, true, err_type); LogDebug(COMPONENT_FSAL, "NCSF load_config_from_parse."); if (!config_error_is_harmless(err_type)) return fsalstat(ERR_FSAL_INVAL, 0); LogDebug(COMPONENT_FSAL, "NCSF config_error_is_harmless."); display_fsinfo(&myself->module); LogFullDebug(COMPONENT_FSAL, "Supported attributes constant = 0x%" PRIx64, NCDSS_SUPPORTED_ATTRIBUTES); rc = create_log_facility(myname, log_to_ncdss, NIV_FULL_DEBUG, LH_COMPONENT, NULL); if (rc != 0) { LogCrit(COMPONENT_FSAL, "Could not create NCSF logger (%s)", strerror(-rc)); return fsalstat(ERR_FSAL_INVAL, 0); } if (nf_module->fs_info.fsal_trace) { rc = enable_log_facility(myname); if (rc != 0){ LogCrit(COMPONENT_FSAL, "Could not enable named NCSF logger (%s)", strerror(-rc)); return fsalstat(ERR_FSAL_INVAL, 0); } } rc = disable_log_facility(myname); if (rc != 0){ LogCrit(COMPONENT_FSAL, "Could not disable NCSF logger (%s)", strerror(-rc)); return fsalstat(ERR_FSAL_INVAL, 0); } LogDebug(COMPONENT_FSAL, "NCSF disable_log_facility."); return fsalstat(ERR_FSAL_NO_ERROR, 0); } static struct config_item export_params[] = { CONF_ITEM_NOOP("name"), CONF_ITEM_STR("user", 0, MAXUIDLEN, NULL, ncdss_fsal_export, user), CONF_ITEM_STR("fs_name", 0, NAME_MAX, NULL, ncdss_fsal_export, fs_name), CONF_ITEM_STR("password", 0, MAXSECRETLEN, NULL, ncdss_fsal_export, password), CONF_ITEM_BOOL("ignore_mode_change", false, ncdss_fsal_export, ignore_mode_change), CONFIG_EOL }; static struct config_block export_param = { .dbus_interface_name = "org.ganesha.nfsd.config.fsal.ncdfs-export%d", .blk_desc.name = "FSAL", .blk_desc.type = CONFIG_BLOCK, .blk_desc.u.blk.init = noop_conf_init, .blk_desc.u.blk.params = export_params, .blk_desc.u.blk.commit = noop_conf_commit }; static fsal_status_t ncdss_create_export(struct fsal_module *fsal_hdl, void *parse_node, struct config_error_type *err_type, const struct fsal_up_vector *up_ops) { /* The status code to return */ fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 }; struct ncdss_fsal_export *ncdss_export = NULL; struct ncdss_filesystem *ncdss_fs = NULL; struct nstat *buf = NULL; char *szError = NULL; NCSF *ncsf = NULL; int rc = 0; ncdss_export = gsh_calloc(1, sizeof(struct ncdss_fsal_export)); glist_init(&ncdss_export->filesystems); LogDebug(COMPONENT_FSAL, "In args: export id = %d, op_ctx export id = %d", ncdss_export->export.export_id, op_ctx->ctx_export->export_id); // status.minor = fsal_internal_version(); // LogInfo(COMPONENT_FSAL, "NCSF get version is %d options 0x%X id %d", // status.minor, // op_ctx->export_perms ? op_ctx->export_perms->options : 0, // op_ctx->ctx_export->export_id); fsal_export_init(&ncdss_export->export); ncdss_export_ops_init(&ncdss_export->export.exp_ops); /* 加载 FSAL export默认参数配置 */ if(parse_node) { rc = load_config_from_node(parse_node, &export_param, ncdss_export, true, err_type); if (rc != 0) { LogCrit(COMPONENT_FSAL, "Incorrect or missing parameters for export %s", op_ctx->ctx_export->fullpath); status.major = ERR_FSAL_INVAL; free_export_ops(&ncdss_export->export); gsh_free(ncdss_export); return status; } } // enable_delegations(ncdss_export); status.minor = fsal_attach_export(fsal_hdl, &ncdss_export->export.exports); if (status.minor != 0) { status.major = posix2fsal_error(status.minor); free_export_ops(&ncdss_export->export); gsh_free(ncdss_export); return status; } ncdss_export->export.up_ops = up_ops; ncdss_export->export.fsal = fsal_hdl; LogDebug(COMPONENT_FSAL, "NCSF create export init1.user = %s, password = %s", ncdss_export->user, ncdss_export->password); if(ninit(ncsf, szError) != 0) { LogCrit(COMPONENT_FSAL, "NCSF sinit failed... szError=%s," " user %s fail login", szError, ncdss_export->user); return fsalstat(ERR_FSAL_INVAL, 0); } LogDebug(COMPONENT_FSAL, "NCSF create export init2."); ncdss_fs->ncdss_fd->ncfs_info = ncsf; ncdss_fs->ncdss_fd->file_type.dir = nopendir(op_ctx->ctx_export->fullpath, ncsf); ncdss_fs->ncdss_fd->file_type.file = NULL; ncdss_fs->ncdss_fd->file_type.symlink = NULL; ncdss_fs->ncdss_fd->creds.caller_uid = op_ctx->creds->caller_uid; ncdss_fs->ncdss_fd->creds.caller_garray = op_ctx->creds->caller_garray; ncdss_fs->ncdss_fd->creds.caller_gid = op_ctx->creds->caller_gid; ncdss_fs->ncdss_fd->creds.caller_glen = op_ctx->creds->caller_glen; ncdss_export->root_fs->private_data = ncdss_fs; if(ncdss_claim_filesystem(ncdss_fs->fs, &ncdss_export->export) != 0) { ncdss_unclaim_filesystem(ncdss_fs->fs); fsal_detach_export(fsal_hdl, &ncdss_export->export.exports); LogCrit(COMPONENT_FSAL, "NCSF sinit failed, ncdss claim filesystem"); return fsalstat(ERR_FSAL_INVAL, 0); } LogDebug(COMPONENT_FSAL, "NCSF create export init status claim filesystem"); /* if the nodeid has not been obtained, get it now */ if (!g_nodeid) { if (nstat(op_ctx->ctx_export->fullpath, buf, ncsf) == 0) { g_nodeid = buf->d_id; LogFullDebug(COMPONENT_FSAL, "node id %d", g_nodeid); } else { ncdss_unclaim_filesystem(ncdss_fs->fs); fsal_detach_export(fsal_hdl, &ncdss_export->export.exports); LogCrit(COMPONENT_FSAL, "get node id failed %d", g_nodeid); return fsalstat(ERR_FSAL_INVAL, 0); } } LogDebug(COMPONENT_FSAL, "In args: fullpath = %s, filesystem path = %s", op_ctx->ctx_export->fullpath, ncdss_fs->fs->path); if (ncdss_export->export.exp_ops.fs_supports(&ncdss_export->export, fso_pnfs_ds_supported)) { struct fsal_pnfs_ds *pds = NULL; status = fsal_hdl->m_ops.fsal_pnfs_ds(fsal_hdl, parse_node, &pds); if (status.major != ERR_FSAL_NO_ERROR) ncdss_unexport_filesystems(ncdss_export); /* special case: server_id matches export_id */ pds->id_servers = op_ctx->ctx_export->export_id; pds->mds_export = op_ctx->ctx_export; pds->mds_fsal_export = op_ctx->fsal_export; if (!pnfs_ds_insert(pds)) { LogCrit(COMPONENT_CONFIG, "Server id %d already in use.", pds->id_servers); status.major = ERR_FSAL_EXIST; fsal_pnfs_ds_fini(pds); gsh_free(pds); ncdss_unexport_filesystems(ncdss_export); return fsalstat(ERR_FSAL_INVAL, 0); } LogInfo(COMPONENT_FSAL, "ncdss_fsal_create: pnfs ds was enabled for [%s]", op_ctx->ctx_export->fullpath); } if (ncdss_export->export.exp_ops.fs_supports(&ncdss_export->export, fso_pnfs_mds_supported)) { LogDebug(COMPONENT_PNFS, "glusterfs_fsal_create: pnfs mds was " "enabled for [%s]", op_ctx->ctx_export->fullpath); export_ops_pnfs(&ncdss_export->export.exp_ops); } ncdss_export->use_acl = !op_ctx_export_has_option(EXPORT_OPTION_DISABLE_ACL); return fsalstat(ERR_FSAL_NO_ERROR, 0); } /** TOODO * @brief Describe a NCDSS striping pattern * * At present, we support a files based layout only. The CRUSH * striping pattern is a-periodic * * @param[in] export_pub Public export handle * @param[out] da_addr_body Stream we write the result to * @param[in] type Type of layout that gave the device * @param[in] deviceid The device to look up * * @return Valid error codes in RFC 5661, p. 365. */ static nfsstat4 ncdss_getdeviceinfo(struct fsal_module *fsal_hdl, XDR *da_addr_body, const layouttype4 type, const struct pnfs_deviceid *deviceid) { /* The position before any bytes are sent to the stream */ // size_t da_beginning; // size_t ds_buffer; // /* The total length of the XDR-encoded da_addr_body */ // size_t da_length; // int rc; // int errsv; return NFS4_OK; } /** * @brief Size of the buffer needed for a ds_addr * * This one is huge, due to the striping pattern. * * @param[in] export_pub Public export handle * * @return Size of the buffer needed for a ds_addr */ size_t ncdss_fs_da_addr_size(struct fsal_module *fsal_hdl) { return 0x20000; } /** @fn MODULE_INIT void ncdss_init(void) * @brief Module initialization. * * Called by dlopen() to register the module * keep a private pointer to me in myself */ MODULE_INIT void ncdss_init(void) { struct fsal_module *myself = &NCSF_FS.module; LogDebug(COMPONENT_FSAL, "ncdfs module registering."); if (register_fsal(myself, myname, FSAL_MAJOR_VERSION, FSAL_MINOR_VERSION, FSAL_ID_NCDFS) != 0) { fprintf(stderr, "NCDFS module failed to register"); return; } /** Set up module operations */ myself->m_ops.fsal_pnfs_ds_ops = pnfs_ds_ops_init; myself->m_ops.create_export = ncdss_create_export; myself->m_ops.init_config = init_config; myself->m_ops.getdeviceinfo = ncdss_getdeviceinfo; myself->m_ops.fs_da_addr_size = ncdss_fs_da_addr_size; #ifdef USE_DBUS myself->m_ops.fsal_extract_stats = fsal_ncdss_extract_stats; #endif myself->m_ops.fsal_reset_stats = fsal_ncdss_reset_stats; /* Initialize the fsal_obj_handle ops for FSAL NCDSS */ ncdss_handle_ops_init(&NCSF_FS.handle_ops); ncdss_handle_ops_init(&NCSF_FS.handle_ops_with_pnfs); handle_ops_pnfs(&NCSF_FS.handle_ops_with_pnfs); } /** @fn MODULE_FINI void ncdss_unload(void) * @brief unload module */ MODULE_FINI void ncdss_unload(void) { release_log_facility(myname); if (unregister_fsal(&NCSF_FS.module) != 0){ LogCrit(COMPONENT_FSAL, "NCSF module failed to unregister"); return; } LogDebug(COMPONENT_FSAL, "FSAL NCDFS unloaded"); }