Changes codes

1) Changed codes about initializing curl and openSSL
   s3fs before this change called curl_global_init() two times
   with curl_global_cleanup(). After reviewing this processing,
   s3fs calls curl_global_init() one time.
   Then s3fs_check_service function which checks user bucket
   existing is called after calling fuse.
   So this new processing does not have a problem, the codes
   updated.

   And about initializing openSSL(CRYPTO), old s3fs called only
   static locking callback function(ex. CRYPTO_set_locking_callback()).
   Added calling dynamic locking callback function for CRYPTO
   (ex. CRYPTO_set_dynlock_lock_callback()).



git-svn-id: http://s3fs.googlecode.com/svn/trunk@479 df820570-a93a-0410-bd06-b72b767a4274
This commit is contained in:
ggtakec@gmail.com 2013-08-27 08:12:01 +00:00
parent 8111edec61
commit 7ce8135fa9
3 changed files with 237 additions and 150 deletions

View File

@ -130,45 +130,44 @@ const char* BodyData::str(void) const
#define MULTIPART_SIZE 10485760 // 10MB
#define MAX_MULTI_COPY_SOURCE_SIZE 524288000 // 500MB
pthread_mutex_t S3fsCurl::curl_handles_lock;
pthread_mutex_t S3fsCurl::curl_share_lock;
bool S3fsCurl::is_initglobal_done = false;
CURLSH* S3fsCurl::hCurlShare = NULL;
bool S3fsCurl::is_dns_cache = true; // default
long S3fsCurl::connect_timeout = 10; // default
time_t S3fsCurl::readwrite_timeout = 30; // default
int S3fsCurl::retries = 3; // default
bool S3fsCurl::is_public_bucket = false;
string S3fsCurl::default_acl = "private";
bool S3fsCurl::is_use_rrs = false;
bool S3fsCurl::is_use_sse = false;
bool S3fsCurl::is_content_md5 = false;
bool S3fsCurl::is_verbose = false;
string S3fsCurl::AWSAccessKeyId;
string S3fsCurl::AWSSecretAccessKey;
long S3fsCurl::ssl_verify_hostname = 1; // default(original code...)
const EVP_MD* S3fsCurl::evp_md = EVP_sha1();
curltime_t S3fsCurl::curl_times;
curlprogress_t S3fsCurl::curl_progress;
string S3fsCurl::curl_ca_bundle;
mimes_t S3fsCurl::mimeTypes;
int S3fsCurl::max_parallel_cnt = 5; // default
pthread_mutex_t S3fsCurl::curl_handles_lock;
pthread_mutex_t S3fsCurl::curl_share_lock;
pthread_mutex_t* S3fsCurl::crypt_mutex = NULL;
bool S3fsCurl::is_initglobal_done = false;
CURLSH* S3fsCurl::hCurlShare = NULL;
bool S3fsCurl::is_dns_cache = true; // default
long S3fsCurl::connect_timeout = 10; // default
time_t S3fsCurl::readwrite_timeout = 30; // default
int S3fsCurl::retries = 3; // default
bool S3fsCurl::is_public_bucket = false;
string S3fsCurl::default_acl = "private";
bool S3fsCurl::is_use_rrs = false;
bool S3fsCurl::is_use_sse = false;
bool S3fsCurl::is_content_md5 = false;
bool S3fsCurl::is_verbose = false;
string S3fsCurl::AWSAccessKeyId;
string S3fsCurl::AWSSecretAccessKey;
long S3fsCurl::ssl_verify_hostname = 1; // default(original code...)
const EVP_MD* S3fsCurl::evp_md = EVP_sha1();
curltime_t S3fsCurl::curl_times;
curlprogress_t S3fsCurl::curl_progress;
string S3fsCurl::curl_ca_bundle;
mimes_t S3fsCurl::mimeTypes;
int S3fsCurl::max_parallel_cnt = 5; // default
//-------------------------------------------------------------------
// Class methods for S3fsCurl
//-------------------------------------------------------------------
bool S3fsCurl::InitS3fsCurl(const char* MimeFile, bool reinit)
bool S3fsCurl::InitS3fsCurl(const char* MimeFile)
{
if(!reinit){
if(0 != pthread_mutex_init(&S3fsCurl::curl_handles_lock, NULL)){
return false;
}
if(0 != pthread_mutex_init(&S3fsCurl::curl_share_lock, NULL)){
return false;
}
if(!S3fsCurl::InitMimeType(MimeFile)){
return false;
}
if(0 != pthread_mutex_init(&S3fsCurl::curl_handles_lock, NULL)){
return false;
}
if(0 != pthread_mutex_init(&S3fsCurl::curl_share_lock, NULL)){
return false;
}
if(!S3fsCurl::InitMimeType(MimeFile)){
return false;
}
if(!S3fsCurl::InitGlobalCurl()){
return false;
@ -176,26 +175,30 @@ bool S3fsCurl::InitS3fsCurl(const char* MimeFile, bool reinit)
if(!S3fsCurl::InitShareCurl()){
return false;
}
if(!S3fsCurl::InitCryptMutex()){
return false;
}
return true;
}
bool S3fsCurl::DestroyS3fsCurl(bool reinit)
bool S3fsCurl::DestroyS3fsCurl(void)
{
bool result = true;
int result = true;
if(!S3fsCurl::DestroyCryptMutex()){
return false;
}
if(!S3fsCurl::DestroyShareCurl()){
return false;
}
if(!S3fsCurl::DestroyGlobalCurl()){
return false;
}
if(!reinit){
if(0 != pthread_mutex_destroy(&S3fsCurl::curl_share_lock)){
result = false;
}
if(0 != pthread_mutex_destroy(&S3fsCurl::curl_handles_lock)){
result = false;
}
if(0 != pthread_mutex_destroy(&S3fsCurl::curl_share_lock)){
result = false;
}
if(0 != pthread_mutex_destroy(&S3fsCurl::curl_handles_lock)){
result = false;
}
return result;
}
@ -296,6 +299,100 @@ void S3fsCurl::UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* use
}
}
bool S3fsCurl::InitCryptMutex(void)
{
if(S3fsCurl::crypt_mutex){
FPRNNN("crypt_mutex is not NULL, destory it.");
if(!S3fsCurl::DestroyCryptMutex()){
DPRN("Failed to destroy crypt mutex");
return false;
}
}
if(NULL == (S3fsCurl::crypt_mutex = static_cast<pthread_mutex_t*>(malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t))))){
DPRNCRIT("Could not allocate memory for crypt mutex");
return false;
}
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
pthread_mutex_init(&S3fsCurl::crypt_mutex[cnt], NULL);
}
// static lock
CRYPTO_set_locking_callback(S3fsCurl::CryptMutexLock);
CRYPTO_set_id_callback(S3fsCurl::CryptGetThreadid);
// dynamic lock
CRYPTO_set_dynlock_create_callback(S3fsCurl::CreateDynCryptMutex);
CRYPTO_set_dynlock_lock_callback(S3fsCurl::DynCryptMutexLock);
CRYPTO_set_dynlock_destroy_callback(S3fsCurl::DestoryDynCryptMutex);
return true;
}
bool S3fsCurl::DestroyCryptMutex(void)
{
if(!S3fsCurl::crypt_mutex){
return true;
}
CRYPTO_set_dynlock_destroy_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
pthread_mutex_destroy(&S3fsCurl::crypt_mutex[cnt]);
}
free(S3fsCurl::crypt_mutex);
S3fsCurl::crypt_mutex = NULL;
return true;
}
void S3fsCurl::CryptMutexLock(int mode, int pos, const char* file, int line)
{
if(S3fsCurl::crypt_mutex){
if(mode & CRYPTO_LOCK){
pthread_mutex_lock(&S3fsCurl::crypt_mutex[pos]);
}else{
pthread_mutex_unlock(&S3fsCurl::crypt_mutex[pos]);
}
}
}
unsigned long S3fsCurl::CryptGetThreadid(void)
{
return (unsigned long)pthread_self();
}
struct CRYPTO_dynlock_value* S3fsCurl::CreateDynCryptMutex(const char* file, int line)
{
struct CRYPTO_dynlock_value* dyndata;
if(NULL == (dyndata = (struct CRYPTO_dynlock_value*)malloc(sizeof(struct CRYPTO_dynlock_value)))){
return NULL;
}
pthread_mutex_init(&(dyndata->dyn_mutex), NULL);
return dyndata;
}
void S3fsCurl::DynCryptMutexLock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line)
{
if(dyndata){
if(mode & CRYPTO_LOCK){
pthread_mutex_lock(&(dyndata->dyn_mutex));
}else{
pthread_mutex_unlock(&(dyndata->dyn_mutex));
}
}
}
void S3fsCurl::DestoryDynCryptMutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line)
{
if(dyndata){
pthread_mutex_destroy(&(dyndata->dyn_mutex));
free(dyndata);
}
}
// homegrown timeout mechanism
int S3fsCurl::CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{

View File

@ -99,6 +99,12 @@ class S3fsMultiCurl;
//----------------------------------------------
// class S3fsCurl
//----------------------------------------------
// internal use struct for openssl
struct CRYPTO_dynlock_value
{
pthread_mutex_t dyn_mutex;
};
// Class for lapping curl
//
class S3fsCurl
@ -123,29 +129,30 @@ class S3fsCurl
};
// class variables
static pthread_mutex_t curl_handles_lock;
static pthread_mutex_t curl_share_lock;
static bool is_initglobal_done;
static CURLSH* hCurlShare;
static bool is_dns_cache;
static long connect_timeout;
static time_t readwrite_timeout;
static int retries;
static bool is_public_bucket;
static std::string default_acl; // TODO: to enum
static bool is_use_rrs;
static bool is_use_sse;
static bool is_content_md5;
static bool is_verbose;
static std::string AWSAccessKeyId;
static std::string AWSSecretAccessKey;
static long ssl_verify_hostname;
static const EVP_MD* evp_md;
static curltime_t curl_times;
static curlprogress_t curl_progress;
static std::string curl_ca_bundle;
static mimes_t mimeTypes;
static int max_parallel_cnt;
static pthread_mutex_t curl_handles_lock;
static pthread_mutex_t curl_share_lock;
static pthread_mutex_t* crypt_mutex;
static bool is_initglobal_done;
static CURLSH* hCurlShare;
static bool is_dns_cache;
static long connect_timeout;
static time_t readwrite_timeout;
static int retries;
static bool is_public_bucket;
static std::string default_acl; // TODO: to enum
static bool is_use_rrs;
static bool is_use_sse;
static bool is_content_md5;
static bool is_verbose;
static std::string AWSAccessKeyId;
static std::string AWSSecretAccessKey;
static long ssl_verify_hostname;
static const EVP_MD* evp_md;
static curltime_t curl_times;
static curlprogress_t curl_progress;
static std::string curl_ca_bundle;
static mimes_t mimeTypes;
static int max_parallel_cnt;
// variables
CURL* hCurl;
@ -176,8 +183,19 @@ class S3fsCurl
private:
// class methods
static bool InitGlobalCurl(void);
static bool DestroyGlobalCurl(void);
static bool InitShareCurl(void);
static bool DestroyShareCurl(void);
static void LockCurlShare(CURL* handle, curl_lock_data nLockData, curl_lock_access laccess, void* useptr);
static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr);
static bool InitCryptMutex(void);
static bool DestroyCryptMutex(void);
static void CryptMutexLock(int mode, int pos, const char* file, int line);
static unsigned long CryptGetThreadid(void);
static struct CRYPTO_dynlock_value* CreateDynCryptMutex(const char* file, int line);
static void DynCryptMutexLock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line);
static void DestoryDynCryptMutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line);
static int CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
static bool InitMimeType(const char* MimeFile = NULL);
@ -207,12 +225,8 @@ class S3fsCurl
public:
// class methods
static bool InitS3fsCurl(const char* MimeFile = NULL, bool reinit = false);
static bool DestroyS3fsCurl(bool reinit = false);
static bool InitGlobalCurl(void);
static bool DestroyGlobalCurl(void);
static bool InitShareCurl(void);
static bool DestroyShareCurl(void);
static bool InitS3fsCurl(const char* MimeFile = NULL);
static bool DestroyS3fsCurl(void);
static int ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool ow_sse_flg);
static int ParallelGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size);

View File

@ -99,9 +99,6 @@ static bool is_s3fs_gid = false;// default does not set.
static bool is_s3fs_umask = false;// default does not set.
static bool is_remove_cache = false;
// mutex
static pthread_mutex_t *mutex_buf = NULL;
//-------------------------------------------------------------------
// Static functions : prototype
//-------------------------------------------------------------------
@ -134,9 +131,8 @@ static int rename_object(const char* from, const char* to);
static int rename_object_nocopy(const char* from, const char* to);
static int clone_directory_object(const char* from, const char* to);
static int rename_directory(const char* from, const char* to);
static void locking_function(int mode, int n, const char* file, int line);
static unsigned long id_function(void);
static int remote_mountpath_exists(const char* path);
static int s3fs_utility_mode(void);
static int s3fs_check_service(void);
static int check_for_aws_format(void);
static int check_passwd_file_perms(void);
@ -2462,42 +2458,27 @@ static int remote_mountpath_exists(const char* path)
return 0;
}
/**
* OpenSSL locking function.
*
* @param mode lock mode
* @param n lock number
* @param file source file name
* @param line source file line number
* @return none
*/
static void locking_function(int mode, int n, const char* file, int line)
{
if(mode & CRYPTO_LOCK){
pthread_mutex_lock(&mutex_buf[n]);
}else{
pthread_mutex_unlock(&mutex_buf[n]);
}
}
// OpenSSL uniq thread id function.
static unsigned long id_function(void)
{
return (unsigned long)pthread_self();
}
static void* s3fs_init(struct fuse_conn_info* conn)
{
FPRN("init");
LOWSYSLOGPRINT(LOG_ERR, "init $Rev$");
// openssl
mutex_buf = static_cast<pthread_mutex_t*>(malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)));
for (int i = 0; i < CRYPTO_num_locks(); i++){
pthread_mutex_init(&mutex_buf[i], NULL);
// init curl
if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){
fprintf(stderr, "%s: Could not initiate curl library.\n", program_name.c_str());
LOWSYSLOGPRINT(LOG_ERR, "Could not initiate curl library.");
exit(EXIT_FAILURE);
}
// Check Bucket
// If the network is up, check for valid credentials and if the bucket
// exists. skip check if mounting a public bucket
if(!S3fsCurl::IsPublicBucket()){
int result;
if(EXIT_SUCCESS != (result = s3fs_check_service())){
exit(result);
}
}
CRYPTO_set_locking_callback(locking_function);
CRYPTO_set_id_callback(id_function);
// Investigate system capabilities
if((unsigned int)conn->capable & FUSE_CAP_ATOMIC_O_TRUNC){
@ -2507,26 +2488,20 @@ static void* s3fs_init(struct fuse_conn_info* conn)
if(is_remove_cache && !FdManager::DeleteCacheDirectory()){
DPRNINFO("Could not inilialize cache directory.");
}
return 0;
return NULL;
}
static void s3fs_destroy(void*)
{
DPRN("destroy");
// openssl
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
for(int i = 0; i < CRYPTO_num_locks(); i++){
pthread_mutex_destroy(&mutex_buf[i]);
// Destory curl
if(!S3fsCurl::DestroyS3fsCurl()){
DPRN("Could not release curl library.");
}
free(mutex_buf);
mutex_buf = NULL;
// cache
if(is_remove_cache && !FdManager::DeleteCacheDirectory()){
DPRNINFO("Could not remove cache directory.");
DPRN("Could not remove cache directory.");
}
}
@ -2541,6 +2516,38 @@ static int s3fs_access(const char* path, int mask)
return check_object_access(path, mask, NULL);
}
static int s3fs_utility_mode(void)
{
if(!utility_mode){
return EXIT_FAILURE;
}
// init curl
if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){
fprintf(stderr, "%s: Could not initiate curl library.\n", program_name.c_str());
LOWSYSLOGPRINT(LOG_ERR, "Could not initiate curl library.");
return EXIT_FAILURE;
}
printf("Utility Mode\n");
S3fsCurl s3fscurl;
string body;
int result = EXIT_SUCCESS;
if(0 != s3fscurl.MultipartListRequest(body)){
fprintf(stderr, "%s: Could not get list multipart upload.\n", program_name.c_str());
result = EXIT_FAILURE;
}else{
printf("body.text:\n%s\n", body.c_str());
}
// Destory curl
if(!S3fsCurl::DestroyS3fsCurl()){
DPRN("Could not release curl library.");
}
return result;
}
static int s3fs_check_service(void)
{
FPRN("check services.");
@ -3435,33 +3442,8 @@ int main(int argc, char* argv[])
}
*/
// Init curl
if(!S3fsCurl::InitS3fsCurl("/etc/mime.types")){
fprintf(stderr, "%s: Could not initiate curl library.\n", program_name.c_str());
exit(EXIT_FAILURE);
}
// Does the bucket exist?
// if the network is up, check for valid credentials and if the bucket
// exists. skip check if mounting a public bucket
if(!S3fsCurl::IsPublicBucket()){
int result;
if(EXIT_SUCCESS != (result = s3fs_check_service())){
exit(result);
}
}
if(utility_mode){
printf("Utility Mode\n");
S3fsCurl s3fscurl;
string body;
if(0 != s3fscurl.MultipartListRequest(body)){
fprintf(stderr, "%s: Could not get list multipart upload.\n", program_name.c_str());
exit(EXIT_FAILURE);
}
printf("body.text:\n%s\n", body.c_str());
exit(EXIT_SUCCESS);
exit(s3fs_utility_mode());
}
s3fs_oper.getattr = s3fs_getattr;
@ -3496,12 +3478,6 @@ int main(int argc, char* argv[])
s3fs_oper.access = s3fs_access;
s3fs_oper.create = s3fs_create;
// Reinit curl
if(!S3fsCurl::DestroyS3fsCurl(true) || !S3fsCurl::InitS3fsCurl(NULL, true)){
fprintf(stderr, "%s: Could not reinitiate curl library.\n", program_name.c_str());
exit(EXIT_FAILURE);
}
// now passing things off to fuse, fuse will finish evaluating the command line args
fuse_res = fuse_main(custom_args.argc, custom_args.argv, &s3fs_oper, NULL);
fuse_opt_free_args(&custom_args);