turbonfs/inc/aznfsc.h (163 lines of code) (raw):

#ifndef __AZNFSC_H__ #define __AZNFSC_H__ #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <limits.h> #include <assert.h> #ifdef ENABLE_NO_FUSE #include "nofuse.h" #else #define FUSE_USE_VERSION 312 #include <fuse3/fuse_lowlevel.h> #include <fuse3/fuse.h> #include <linux/fuse.h> #endif #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" #include "aznfsc_config.h" #include "log.h" #include "util.h" using namespace aznfsc; // Max block size for a Blob (100MB). #define AZNFSC_MAX_BLOCK_SIZE (100 * 1024 * 1024) // Min/Max values for various aznfsc_cfg options. #define AZNFSCFG_NCONNECT_MIN 1 #define AZNFSCFG_NCONNECT_MAX 256 #define AZNFSCFG_TIMEO_MIN 100 #define AZNFSCFG_TIMEO_MAX 6000 #define AZNFSCFG_RSIZE_MIN 1048576 #define AZNFSCFG_RSIZE_MAX AZNFSC_MAX_BLOCK_SIZE #define AZNFSCFG_WSIZE_MIN 1048576 #define AZNFSCFG_WSIZE_MAX AZNFSC_MAX_BLOCK_SIZE static_assert(AZNFSCFG_WSIZE_MAX == AZNFSCFG_RSIZE_MAX); #define AZNFSCFG_READDIR_MIN 8192 #define AZNFSCFG_READDIR_MAX 4194304 #define AZNFSCFG_READAHEAD_KB_MIN 128 #define AZNFSCFG_READAHEAD_KB_MAX 1048576 #define AZNFSCFG_READAHEAD_KB_DEF 16384 #define AZNFSCFG_FUSE_MAX_BG_MIN 1 #define AZNFSCFG_FUSE_MAX_BG_MAX 65536 #define AZNFSCFG_FUSE_MAX_BG_DEF 4096 #define AZNFSCFG_FUSE_MAX_THR_MIN -1 // Implies fuse default. #define AZNFSCFG_FUSE_MAX_THR_MAX 65536 #define AZNFSCFG_FUSE_MAX_IDLE_THR_MIN -1 // Implies fuse default. #define AZNFSCFG_FUSE_MAX_IDLE_THR_MAX INT_MAX #define AZNFSCFG_CACHE_MAX_MB_MIN 512 #define AZNFSCFG_CACHE_MAX_MB_MAX (10 * 1024 * 1024) // Default value for percentage of total RAM to be used for cache. #define AZNFSCFG_CACHE_MAX_MB_PERCENT_DEF 60 #define AZNFSCFG_FILECACHE_MAX_GB_MIN 1 #define AZNFSCFG_FILECACHE_MAX_GB_MAX (1024 * 1024) #define AZNFSCFG_FILECACHE_MAX_GB_DEF (1024) #define AZNFSCFG_RETRANS_MIN 1 #define AZNFSCFG_RETRANS_MAX 100 #define AZNFSCFG_ACTIMEO_MIN 1 #define AZNFSCFG_ACTIMEO_MAX 3600 #define AZNFSCFG_LOOKUPCACHE_NONE 1 #define AZNFSCFG_LOOKUPCACHE_POS 2 #define AZNFSCFG_LOOKUPCACHE_ALL 3 #define AZNFSCFG_LOOKUPCACHE_DEF AZNFSCFG_LOOKUPCACHE_ALL // W/o jumbo blocks, 5TiB is the max file size we can support. #define AZNFSC_MAX_FILE_SIZE (50'000ULL * AZNFSC_MAX_BLOCK_SIZE) /* * Max fuse_opcode enum value. * This keeps increasing with newer fuse versions, but we don't want it * to be the exact maximum, we just want it to be more than all the opcodes * that we support. */ #define FUSE_OPCODE_MAX FUSE_LSEEK /* * fuse_reply_iov() uses writev() for sending the iov over to the fuse * device. writev() can accept max 1024 sized vector, and fuse_reply_iov() * uses the first element of the vector for conveying the req id and status, * so we cannot convey more than 1023 vector elements through fuse_reply_iov(). */ #define FUSE_REPLY_IOV_MAX_COUNT (1023) /* * In paranoid builds, also enable pressure points (aka error injection). */ #ifdef ENABLE_PARANOID #define ENABLE_PRESSURE_POINTS extern double inject_err_prob_pct_def; #endif /** * Enum for defining the various consistency levels we support. * Ref details in sample-config.yaml. */ enum class consistency_t { INVALID = 0, SOLOWRITER, STANDARDNFS, AZUREMPA, }; /** * This structure holds the entire aznfsclient configuration that controls the * behaviour of the aznfsclient fuse program. These config variables can be * configured in many ways, allowing user to conveniently express their default * configuration and allowing easy overrides for some as needed. * * Here are the various ways these config values are populated: * 1. Most configs have default values. * Note: Some of the config variables pertain to user details and cannot * have default values. * 2. Convenient place for defining config variables which don't need to be * changed often is the config.yaml file that user can provide with the * --config-file=./config.yaml cmdline option to aznfsclient. * These override the defaults. * 3. Some but not all config variables can be set using environment variables. * These override the variables set by config.yaml and the default. * 4. Most config variables can be set using specific command line options to * aznfsclient. * These have the highest preference and will override the variables set * by environment variables, config.yaml and the default. * * Note: This MUST not contains C++ object types as members as fuse parser * writes into those members. For char* members fuse also allocates * memory. * An exception to this are the fields in the "Aggregates" section. * These are not set by fuse parser but are stored for convenience. */ typedef struct aznfsc_cfg { // config.yaml file path specified using --config-file= cmdline option. const char *config_yaml = nullptr; // Enable debug logging? bool debug = false; /************************************************* ** Mount path ** ** Identify the server and the export to mount ** *************************************************/ /* * Storage account and container to mount and the optional cloud suffix. * The share path mounted is: * <account>.<cloud_suffix>:/<account>/<container> */ const char *account = nullptr; const char *container = nullptr; const char *cloud_suffix = nullptr; /************************************************* ** Misc ** *************************************************/ /********************************************************************** ** Auth config ** **********************************************************************/ /* * Whether auth should be performed. If this is set to true, tenant id, * subscription id and authtype should be set. */ bool auth = false; /********************************************************************** ** Mount options ** ** These are deliberately named after the popular NFS mount options ** **********************************************************************/ /* * NFS and Mount port to use. * If this is non-zero, portmapper won't be contacted. * Note that Blob NFS uses the same port for Mount and NFS, hence we have * just one config. */ int port = -1; // Number of connections to be established to the server. int nconnect = -1; // Maximum size of read request. int rsize = -1; // Maximum size of write request. int wsize = -1; /* * Number of times the request will be retransmitted to the server when no * response is received, before the "server not responding" message is * logged and further recovery is attempted. */ int retrans = -1; /* * Time in deci-seconds we will wait for a response before retrying the * request. */ int timeo = -1; /* * Regular file and directory attribute cache timeout min and max values. * min value specifies the minimum time in seconds that we cache the * corresponding file type's attributes before we request fresh attributes * from the server. A successful attribute revalidation (i.e., mtime * remains unchanged) doubles the attribute timeout (up to * acregmax/acdirmax for file/directory), while a failed revalidation * resets it to acregmin/acdirmin. * If actimeo is specified it overrides all ac{reg|dir}min/ac{reg|dir}max * and the single actimeo value is used as the min and max attribute cache * timeout values for both file and directory types. */ int acregmin = -1; int acregmax = -1; int acdirmin = -1; int acdirmax = -1; int actimeo = -1; // Whether to cache positive/negative lookup responses. const char *lookupcache = nullptr; int lookupcache_int = AZNFSCFG_LOOKUPCACHE_DEF; // Maximum number of readdir entries that can be requested in a single call. int readdir_maxcount = -1; // Readahead size in KB. int readahead_kb = -1; // Fuse max_background config value. int fuse_max_background = -1; // Fuse max_threads config value. int fuse_max_threads = -1; // Fuse max_idle_threads config value. int fuse_max_idle_threads = -1; // Whether to use TLS or not. const char *xprtsec = nullptr; // Whether to disable OOM killing for the aznfsclient process. bool oom_kill_disable = true; /************************************************* ** Cconsistency config ** *************************************************/ const char *consistency = nullptr; consistency_t consistency_int = consistency_t::INVALID; /* * Convenience shortcuts for consistency mode check. */ bool consistency_solowriter = false; bool consistency_standardnfs = false; bool consistency_azurempa = false; /************************************************* ** Cache config ** *************************************************/ struct { struct { /* * Userspace attribute/lookup cache. * To disable kernel attribute cache set actimeo to 0. */ struct { bool enable = true; } user; } attr; struct { /* * Kernel readdir cache. */ struct { bool enable = true; } kernel; /* * Userspace readdir cache. * This cannot be disabled currently. */ struct { const bool enable = true; // Max userspace readdir cache size in MB. int max_size_mb = -1; } user; } readdir; struct { /* * Kernel data/page cache. */ struct { bool enable = true; } kernel; /* * Userspace data cache. * This cannot be disabled as we need it for performing any IO * operation. */ struct { const bool enable = true; // Max userspace data cache size in MB. int max_size_mb = -1; } user; } data; } cache; struct { bool enable = false; // Directory where file caches will be persisted. const char *cachedir = nullptr; // Max filecache size in GB. int max_size_gb = -1; } filecache; /************************************************* ** System related config ** *************************************************/ struct { /* * If set, stable writes will be forced, else we start with unstable * write and fallback to stable in case of non-append write pattern. */ bool force_stable_writes = true; /* * Resolve server name before reconnect, else connect to the last * resolved IP. */ bool resolve_before_reconnect = true; /* * How should we behave when a retransmitted RPC fails possibly due to * lack of federated DRC at the server. */ struct { /* * REMOVE/RMDIR failing with NFS3ERR_NOENT must be treated as * success. */ bool remove_noent_as_success = true; /* * CREATE/MKNOD/MKDIR/SYMLINK failing with NFS3ERR_EXIST must be * treated as success. */ bool create_exist_as_success = true; /* * RENAME failing with NFS3ERR_NOENT must be treated as success. */ bool rename_noent_as_success = true; } nodrc; } sys; /* * TODO: * - Add auth related config. * - Add perf related config, * - Add hard/soft mount option, * e.g., amount of RAM used for staging writes, etc. */ /************************************************************************** ** Aggregates ** ** These store composite config variables formed from other config ** ** variables which were set as options using aznfsc_opts. ** ** These aggregate membets MUST NOT be set as options using aznfsc_opts,** ** as these can be C++ objects. ** **************************************************************************/ std::string server; std::string export_path; /** * Local mountpoint. * This is not present in the config file, but is taken from the * cmdline. */ std::string mountpoint; /** * Parse config_yaml if set by cmdline --config-file= */ bool parse_config_yaml(); /** * Set default values for options not yet assigned. * This must be called after fuse_opt_parse() and parse_config_yaml() * assign config values from command line and the config yaml file. * Also sanitizes various values. * Returns false if it cannot set default value for one or more config. */ bool set_defaults_and_sanitize(); } aznfsc_cfg_t; extern struct aznfsc_cfg aznfsc_cfg; #endif /* __AZNFSC_H__ */