@@ -131,7 +131,6 @@ static int rename_object(const char* from, const char* to, bool update_ctime);
131131static int rename_object_nocopy (const char * from, const char * to, bool update_ctime);
132132static int clone_directory_object (const char * from, const char * to, bool update_ctime);
133133static int rename_directory (const char * from, const char * to);
134- static int remote_mountpath_exists (const char * path);
135134static void free_xattrs (xattrs_t & xattrs);
136135static bool parse_xattr_keyval (const std::string& xattrpair, std::string& key, PXATTRVAL& pval);
137136static size_t parse_xattrs (const std::string& strxattrs, xattrs_t & xattrs);
@@ -396,26 +395,7 @@ static int get_object_attribute(const char* path, struct stat* pstbuf, headers_t
396395 s3fscurl.DestroyCurlHandle ();
397396
398397 // if not found target path object, do over checking
399- if (-EPERM == result){
400- // [NOTE]
401- // In case of a permission error, it exists in directory
402- // file list but inaccessible. So there is a problem that
403- // it will send a HEAD request every time, because it is
404- // not registered in the Stats cache.
405- // Therefore, even if the file has a permission error, it
406- // should be registered in the Stats cache. However, if
407- // the response without modifying is registered in the
408- // cache, the file permission will be 0644(umask dependent)
409- // because the meta header does not exist.
410- // Thus, set the mode of 0000 here in the meta header so
411- // that ossfs can print a permission error when the file
412- // is actually accessed.
413- // It is better not to set meta header other than mode,
414- // so do not do it.
415- //
416- (*pheader)[" x-oss-meta-mode" ] = str (0 );
417-
418- }else if (0 != result){
398+ if (0 != result){
419399 if (overcheck){
420400 // when support_compat_dir is disabled, strpath maybe have "_$folder$".
421401 if (' /' != *strpath.rbegin () && std::string::npos == strpath.find (" _$folder$" , 0 )){
@@ -467,7 +447,7 @@ static int get_object_attribute(const char* path, struct stat* pstbuf, headers_t
467447 // If the file is listed but not allowed access, put it in
468448 // the positive cache instead of the negative cache.
469449 //
470- if (0 != result && -EPERM != result ){
450+ if (0 != result){
471451 // finally, "path" object did not find. Add no object cache.
472452 strpath = path; // reset original
473453 StatCache::getStatCacheData ()->AddNoObjectCache (strpath);
@@ -3031,24 +3011,6 @@ static int list_bucket(const char* path, S3ObjList& head, const char* delimiter,
30313011 return 0 ;
30323012}
30333013
3034- static int remote_mountpath_exists (const char * path)
3035- {
3036- struct stat stbuf;
3037- int result;
3038-
3039- S3FS_PRN_INFO1 (" [path=%s]" , path);
3040-
3041- // getattr will prefix the path with the remote mountpoint
3042- if (0 != (result = get_object_attribute (" /" , &stbuf, NULL ))){
3043- return result;
3044- }
3045- if (!S_ISDIR (stbuf.st_mode )){
3046- return -ENOTDIR;
3047- }
3048- return 0 ;
3049- }
3050-
3051-
30523014static void free_xattrs (xattrs_t & xattrs)
30533015{
30543016 for (xattrs_t ::iterator iter = xattrs.begin (); iter != xattrs.end (); ++iter){
@@ -3777,7 +3739,7 @@ static int s3fs_check_service()
37773739
37783740 S3fsCurl s3fscurl;
37793741 int res;
3780- if (0 > (res = s3fscurl.CheckBucket (" /" ))){
3742+ if (0 > (res = s3fscurl.CheckBucket (get_realpath ( " /" ). c_str () ))){
37813743 // get response code
37823744 long responseCode = s3fscurl.GetLastResponseCode ();
37833745
@@ -3828,7 +3790,9 @@ static int s3fs_check_service()
38283790 } else {
38293791 s3host = " http://" + expecthost;
38303792 }
3831- // extract region from host for sigv4
3793+ // extract region from host for sigv4
3794+ // The region of the government cloud/financial cloud may not be derived from the domain name
3795+ // https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.13ad12c1N7PoaV
38323796 if (!strncasecmp (expecthost.c_str (), " oss-" , 4 )){
38333797 std::size_t found;
38343798 if ((found = expecthost.find_first_of (" ." )) != std::string::npos) {
@@ -3838,18 +3802,11 @@ static int s3fs_check_service()
38383802 }
38393803 // retry to check with new host
38403804 s3fscurl.DestroyCurlHandle ();
3841- res = s3fscurl.CheckBucket (" /" );
3805+ res = s3fscurl.CheckBucket (get_realpath ( " /" ). c_str () );
38423806 responseCode = s3fscurl.GetLastResponseCode ();
38433807 }
38443808 }
38453809
3846- // retry to check with mount prefix
3847- if (300 <= responseCode && responseCode < 500 && !mount_prefix.empty ()){
3848- s3fscurl.DestroyCurlHandle ();
3849- res = s3fscurl.CheckBucket (get_realpath (" /" ).c_str ());
3850- responseCode = s3fscurl.GetLastResponseCode ();
3851- }
3852-
38533810 // try signature v2
38543811 /*
38553812 if(0 > res && (responseCode == 400 || responseCode == 403) && S3fsCurl::GetSignatureType() == V1_OR_V4){
@@ -3864,35 +3821,39 @@ static int s3fs_check_service()
38643821 }
38653822 */
38663823 // check errors(after retrying)
3824+ // [NOTE]
3825+ // When mounting a bucket, an error code is returned and the mount fails.
3826+ // However, when mounting a prefix, success should be returned if the prefix does not exist.
3827+ //
38673828 if (0 > res && responseCode != 200 && responseCode != 301 ){
38683829 // parse error message if existed
38693830 std::string errMessage;
38703831 const std::string* body = s3fscurl.GetBodyData ();
38713832 check_error_message (body->c_str (), body->size (), errMessage);
3872-
3833+ bool is_failure = true ;
38733834 if (responseCode == 400 ){
38743835 S3FS_PRN_CRIT (" Failed to check bucket and directory for mount point : Bad Request(host=%s, message=%s)" , s3host.c_str (), errMessage.c_str ());
38753836 }else if (responseCode == 403 ){
38763837 S3FS_PRN_CRIT (" Failed to check bucket and directory for mount point : Invalid Credentials(host=%s, message=%s)" , s3host.c_str (), errMessage.c_str ());
3877- }else if (responseCode == 404 ){
3878- S3FS_PRN_CRIT (" Failed to check bucket and directory for mount point : Bucket or directory not found(host=%s, message=%s)" , s3host.c_str (), errMessage.c_str ());
3838+ }else if (responseCode == 404 ) {
3839+ std::string value;
3840+ if (simple_parse_xml (body->c_str (), body->size (), " Code" , value)) {
3841+ if (value == " NoSuchBucket" ) {
3842+ S3FS_PRN_CRIT (" Failed to check bucket : Bucket not found(host=%s, message=%s)" , s3host.c_str (), errMessage.c_str ());
3843+ } else {
3844+ is_failure = false ;
3845+ }
3846+ }
38793847 }else {
38803848 S3FS_PRN_CRIT (" Failed to check bucket and directory for mount point : Unable to connect(host=%s, message=%s)" , s3host.c_str (), errMessage.c_str ());
38813849 }
3882- return EXIT_FAILURE;
3883- }
3884- }
3885- s3fscurl.DestroyCurlHandle ();
3886-
3887- // make sure remote mountpath exists and is a directory
3888- if (!mount_prefix.empty ()){
3889- if (remote_mountpath_exists (mount_prefix.c_str ()) != 0 ){
3890- S3FS_PRN_CRIT (" remote mountpath %s not found." , mount_prefix.c_str ());
3891- return EXIT_FAILURE;
3850+ if (is_failure) {
3851+ return EXIT_FAILURE;
3852+ }
38923853 }
38933854 }
38943855 S3FS_MALLOCTRIM (0 );
3895-
3856+
38963857 return EXIT_SUCCESS;
38973858}
38983859
@@ -4407,8 +4368,34 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar
44074368 max_dirty_data = size;
44084369 return 0 ;
44094370 }
4371+ if (is_prefix (arg, " free_space_ratio=" )){
4372+ int ratio = static_cast <int >(cvt_strtoofft (strchr (arg, ' =' ) + sizeof (char ), /* base=*/ 10 ));
4373+ if (FdManager::GetEnsureFreeDiskSpace ()!=0 ){
4374+ S3FS_PRN_EXIT (" option free_space_ratio conflicts with ensure_diskfree, please set only one of them." );
4375+ return -1 ;
4376+ }
4377+ if (ratio < 0 || ratio > 100 ){
4378+ S3FS_PRN_EXIT (" option free_space_ratio must between 0 to 100, which is: %d" , ratio);
4379+ return -1 ;
4380+ }
4381+ off_t dfsize = FdManager::GetTotalDiskSpaceByRatio (ratio);
4382+ S3FS_PRN_INFO (" Free space ratio set to %d %%, ensure the available disk space is greater than %.3f MB" , ratio, static_cast <double >(dfsize) / 1024 / 1024 );
4383+ if (dfsize < S3fsCurl::GetMultipartSize ()){
4384+ S3FS_PRN_WARN (" specified size to ensure disk free space is smaller than multipart size, so set multipart size to it." );
4385+ dfsize = S3fsCurl::GetMultipartSize ();
4386+ }
4387+ FdManager::SetEnsureFreeDiskSpace (dfsize);
4388+ return 0 ;
4389+ }
44104390 if (is_prefix (arg, " ensure_diskfree=" )){
44114391 off_t dfsize = cvt_strtoofft (strchr (arg, ' =' ) + sizeof (char ), /* base=*/ 10 ) * 1024 * 1024 ;
4392+
4393+ if (FdManager::GetEnsureFreeDiskSpace ()!=0 ){
4394+ S3FS_PRN_EXIT (" option free_space_ratio conflicts with ensure_diskfree, please set only one of them." );
4395+ return -1 ;
4396+ }
4397+ S3FS_PRN_INFO (" Set and ensure the available disk space is greater than %.3f MB." , static_cast <double >(dfsize) / 1024 / 1024 );
4398+
44124399 if (dfsize < S3fsCurl::GetMultipartSize ()){
44134400 S3FS_PRN_WARN (" specified size to ensure disk free space is smaller than multipart size, so set multipart size to it." );
44144401 dfsize = S3fsCurl::GetMultipartSize ();
@@ -5078,12 +5065,16 @@ int main(int argc, char* argv[])
50785065
50795066 // check free disk space
50805067 if (!FdManager::IsSafeDiskSpace (NULL , S3fsCurl::GetMultipartSize () * S3fsCurl::GetMaxParallelCount ())){
5081- S3FS_PRN_EXIT (" There is no enough disk space for used as cache(or temporary) directory by s3fs." );
5082- S3fsCurl::DestroyS3fsCurl ();
5083- s3fs_destroy_global_ssl ();
5084- destroy_parser_xml_lock ();
5085- delete ps3fscred;
5086- exit (EXIT_FAILURE);
5068+ // clean cache dir and retry
5069+ S3FS_PRN_WARN (" No enough disk space for ossfs, try to clean cache dir" );
5070+ FdManager::get ()->CleanupCacheDir ();
5071+ if (!FdManager::IsSafeDiskSpaceWithLog (nullptr , S3fsCurl::GetMultipartSize () * S3fsCurl::GetMaxParallelCount ())){
5072+ S3fsCurl::DestroyS3fsCurl ();
5073+ s3fs_destroy_global_ssl ();
5074+ destroy_parser_xml_lock ();
5075+ delete ps3fscred;
5076+ exit (EXIT_FAILURE);
5077+ }
50875078 }
50885079
50895080 // check readdir_optimize
@@ -5101,6 +5092,11 @@ int main(int argc, char* argv[])
51015092 S3FS_PRN_INFO (" Readdir optimize, flag(%d, %lld)" , is_refresh_fakemeta, static_cast <long long int >(readdir_check_size));
51025093 }
51035094
5095+ // try to check s3fs service
5096+ if (EXIT_SUCCESS != s3fs_check_service ()) {
5097+ exit (EXIT_FAILURE);
5098+ }
5099+
51045100 s3fs_oper.getattr = s3fs_getattr;
51055101 s3fs_oper.readlink = s3fs_readlink;
51065102 s3fs_oper.mknod = s3fs_mknod;
0 commit comments