Fixed a bug that mounting with ksmid specified to fail

This commit is contained in:
Takeshi Nakatani 2024-02-12 02:39:02 +00:00 committed by Andrew Gaul
parent fa2bcfc60d
commit e89adf6633
3 changed files with 47 additions and 13 deletions

View File

@ -3611,7 +3611,7 @@ int S3fsCurl::GetObjectRequest(const char* tpath, int fd, off_t start, off_t siz
return result;
}
int S3fsCurl::CheckBucket(const char* check_path, bool compat_dir)
int S3fsCurl::CheckBucket(const char* check_path, bool compat_dir, bool force_no_sse)
{
S3FS_PRN_INFO3("check a bucket path(%s)%s.", (check_path && 0 < strlen(check_path)) ? check_path : "", compat_dir ? " containing compatible directory paths" : "");
@ -3661,7 +3661,7 @@ int S3fsCurl::CheckBucket(const char* check_path, bool compat_dir)
bodydata.clear();
// SSE
if(S3fsCurl::GetSseType() != sse_type_t::SSE_DISABLE){
if(!force_no_sse && S3fsCurl::GetSseType() != sse_type_t::SSE_DISABLE){
std::string ssevalue;
if(!AddSseRequestHead(S3fsCurl::GetSseType(), ssevalue, false)){
S3FS_PRN_WARN("Failed to set SSE header, but continue...");

View File

@ -360,7 +360,7 @@ class S3fsCurl
int PutRequest(const char* tpath, headers_t& meta, int fd);
int PreGetObjectRequest(const char* tpath, int fd, off_t start, off_t size, sse_type_t ssetype, const std::string& ssevalue);
int GetObjectRequest(const char* tpath, int fd, off_t start = -1, off_t size = -1);
int CheckBucket(const char* check_path, bool compat_dir);
int CheckBucket(const char* check_path, bool compat_dir, bool force_no_sse);
int ListBucketRequest(const char* tpath, const char* query);
int PreMultipartPostRequest(const char* tpath, headers_t& meta, std::string& upload_id, bool is_copy);
int CompleteMultipartPostRequest(const char* tpath, const std::string& upload_id, etaglist_t& parts);

View File

@ -4398,6 +4398,23 @@ static bool check_endpoint_error(const char* pbody, size_t len, std::string& exp
return true;
}
static bool check_invalid_sse_arg_error(const char* pbody, size_t len)
{
if(!pbody){
return false;
}
std::string code;
if(!simple_parse_xml(pbody, len, "Code", code) || code != "InvalidArgument"){
return false;
}
std::string argname;
if(!simple_parse_xml(pbody, len, "ArgumentName", argname) || argname != "x-amz-server-side-encryption"){
return false;
}
return true;
}
static bool check_error_message(const char* pbody, size_t len, std::string& message)
{
message.clear();
@ -4439,8 +4456,11 @@ static int s3fs_check_service()
S3fsCurl s3fscurl;
int res;
if(0 > (res = s3fscurl.CheckBucket(get_realpath("/").c_str(), support_compat_dir))){
bool force_no_sse = false;
while(0 > (res = s3fscurl.CheckBucket(get_realpath("/").c_str(), support_compat_dir, force_no_sse))){
// get response code
bool do_retry = false;
long responseCode = s3fscurl.GetLastResponseCode();
// check wrong endpoint, and automatically switch endpoint
@ -4450,6 +4470,8 @@ static int s3fs_check_service()
const std::string* body = s3fscurl.GetBodyData();
std::string expectregion;
std::string expectendpoint;
// Check if any case can be retried
if(check_region_error(body->c_str(), body->size(), expectregion)){
// [NOTE]
// If endpoint is not specified(using us-east-1 region) and
@ -4483,10 +4505,9 @@ static int s3fs_check_service()
s3host = "https://s3-" + endpoint + ".amazonaws.com";
}
// retry to check
// Retry with changed host
s3fscurl.DestroyCurlHandle();
res = s3fscurl.CheckBucket(get_realpath("/").c_str(), support_compat_dir);
responseCode = s3fscurl.GetLastResponseCode();
do_retry = true;
}else{
S3FS_PRN_CRIT("The bucket region is not '%s'(default), it is correctly '%s'. You should specify endpoint(%s) option.", endpoint.c_str(), expectregion.c_str(), expectregion.c_str());
@ -4500,23 +4521,36 @@ static int s3fs_check_service()
S3FS_PRN_CRIT("S3 service returned PermanentRedirect with %s (current is url(%s) and endpoint(%s)). You need to specify correct endpoint option.", expectendpoint.c_str(), s3host.c_str(), endpoint.c_str());
}
return EXIT_FAILURE;
}else if(check_invalid_sse_arg_error(body->c_str(), body->size())){
// SSE argument error, so retry it without SSE
S3FS_PRN_CRIT("S3 service returned InvalidArgument(x-amz-server-side-encryption), so retry without adding x-amz-server-side-encryption.");
// Retry without sse parameters
s3fscurl.DestroyCurlHandle();
do_retry = true;
force_no_sse = true;
}
}
// retry signature v2
if(0 > res && (responseCode == 400 || responseCode == 403) && S3fsCurl::GetSignatureType() == signature_type_t::V2_OR_V4){
// Try changing signature from v4 to v2
//
// [NOTE]
// If there is no case to retry with the previous checks, and there
// is a chance to retry with signature v2, prepare to retry with v2.
//
if(!do_retry && (responseCode == 400 || responseCode == 403) && S3fsCurl::GetSignatureType() == signature_type_t::V2_OR_V4){
// switch sigv2
S3FS_PRN_CRIT("Failed to connect by sigv4, so retry to connect by signature version 2. But you should to review url and endpoint option.");
S3fsCurl::SetSignatureType(signature_type_t::V2_ONLY);
// retry to check with sigv2
s3fscurl.DestroyCurlHandle();
res = s3fscurl.CheckBucket(get_realpath("/").c_str(), support_compat_dir);
responseCode = s3fscurl.GetLastResponseCode();
do_retry = true;
S3fsCurl::SetSignatureType(signature_type_t::V2_ONLY);
}
// check errors(after retrying)
if(0 > res && responseCode != 200 && responseCode != 301){
if(!do_retry && responseCode != 200 && responseCode != 301){
// parse error message if existed
std::string errMessage;
const std::string* body = s3fscurl.GetBodyData();