Skip to content

Commit 7bbb936

Browse files
author
yongqingliu
committed
Merge branch 'v1.0.21' into 'master' (merge request !5)
v1.0.21 Merge branch 'v1.0.21' into 'v1.0.21' (merge request !4) enable content md5 by default
2 parents eefae4d + d7f9d38 commit 7bbb936

File tree

10 files changed

+314
-18
lines changed

10 files changed

+314
-18
lines changed

src/.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"files.associations": {
3+
"string": "cpp",
4+
"iosfwd": "cpp"
5+
}
6+
}

src/curl.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ storage_class_t S3fsCurl::storage_class = STANDARD;
294294
sseckeylist_t S3fsCurl::sseckeys;
295295
std::string S3fsCurl::ssekmsid = "";
296296
sse_type_t S3fsCurl::ssetype = SSE_DISABLE;
297-
bool S3fsCurl::is_content_md5 = false;
297+
bool S3fsCurl::is_content_md5 = true;
298298
bool S3fsCurl::is_verbose = false;
299299
string S3fsCurl::COSAccessKeyId;
300300
string S3fsCurl::COSSecretAccessKey;
@@ -2974,8 +2974,16 @@ int S3fsCurl::UploadMultipartPostSetup(const char* tpath, int part_num, string&
29742974

29752975
string strMD5;
29762976
if(S3fsCurl::is_content_md5){
2977-
strMD5 = md5base64;
2978-
requestHeaders = curl_slist_sort_insert(requestHeaders, "Content-MD5", strMD5.c_str());
2977+
unsigned char *md5raw = s3fs_md5_fd(partdata.fd, partdata.startpos, partdata.size);
2978+
if(md5raw == NULL){
2979+
S3FS_PRN_ERR("Could not make md5 for file(part %d)", part_num);
2980+
return -EIO;
2981+
}
2982+
partdata.etag = s3fs_hex_lower(md5raw, get_md5_digest_length());
2983+
char* md5base64p = s3fs_base64(md5raw, get_md5_digest_length());
2984+
requestHeaders = curl_slist_sort_insert(requestHeaders, "Content-MD5", md5base64p);
2985+
delete[] md5base64p;
2986+
delete[] md5raw;
29792987
}
29802988

29812989
if(!S3fsCurl::IsPublicBucket()){

src/fdcache.cpp

Lines changed: 152 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,49 @@ bool CacheFileStat::Open(void)
200200
return true;
201201
}
202202

203+
bool CacheFileStat::RenameCacheFileStat(const char* oldpath, const char* newpath)
204+
{
205+
if(!oldpath || '\0' == oldpath[0] || !newpath || '\0' == newpath[0]){
206+
return false;
207+
}
208+
209+
// stat path
210+
std::string old_filestat;
211+
std::string new_filestat;
212+
if(!CacheFileStat::MakeCacheFileStatPath(oldpath, old_filestat, false) || !CacheFileStat::MakeCacheFileStatPath(newpath, new_filestat, false)){
213+
return false;
214+
}
215+
216+
// check new stat path
217+
struct stat st;
218+
if(0 == stat(new_filestat.c_str(), &st)){
219+
// new stat path is existed, then unlink it.
220+
if(-1 == unlink(new_filestat.c_str())){
221+
S3FS_PRN_ERR("failed to unlink new cache file stat path(%s) by errno(%d).", new_filestat.c_str(), errno);
222+
return false;
223+
}
224+
}
225+
226+
// check old stat path
227+
if(0 != stat(old_filestat.c_str(), &st)){
228+
// old stat path is not existed, then nothing to do any more.
229+
return true;
230+
}
231+
232+
// create parent dir
233+
CacheFileStat::MakeCacheFileStatPath(newpath, new_filestat, true);
234+
// link and unlink
235+
if(-1 == link(old_filestat.c_str(), new_filestat.c_str())){
236+
S3FS_PRN_ERR("failed to link old cache file stat path(%s) to new cache file stat path(%s) by errno(%d).", old_filestat.c_str(), new_filestat.c_str(), errno);
237+
return false;
238+
}
239+
if(-1 == unlink(old_filestat.c_str())){
240+
S3FS_PRN_ERR("failed to unlink old cache file stat path(%s) by errno(%d).", old_filestat.c_str(), errno);
241+
return false;
242+
}
243+
return true;
244+
}
245+
203246
bool CacheFileStat::Release(void)
204247
{
205248
if(-1 == fd){
@@ -410,6 +453,11 @@ bool PageList::FindUnloadedPage(off_t start, off_t& resstart, size_t& ressize) c
410453

411454
size_t PageList::GetTotalUnloadedPageSize(off_t start, size_t size) const
412455
{
456+
if(0 == size){
457+
if(start < Size()){
458+
size = Size() - start;
459+
}
460+
}
413461
size_t restsize = 0;
414462
off_t next = static_cast<off_t>(start + size);
415463
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
@@ -620,7 +668,7 @@ int FdEntity::FillFile(int fd, unsigned char byte, size_t size, off_t start)
620668
FdEntity::FdEntity(const char* tpath, const char* cpath)
621669
: is_lock_init(false), refcnt(0), path(SAFESTRPTR(tpath)), cachepath(SAFESTRPTR(cpath)),
622670
fd(-1), pfile(NULL), is_modify(false), size_orgmeta(0), upload_id(""), mp_start(0), mp_size(0),
623-
is_meta_pending(false)
671+
is_meta_pending(false), is_no_disk_space_flushed(false)
624672
{
625673
try{
626674
pthread_mutexattr_t attr;
@@ -843,6 +891,55 @@ int FdEntity::Open(headers_t* pmeta, ssize_t size, time_t time)
843891
return 0;
844892
}
845893

894+
//
895+
// Rename file path.
896+
//
897+
// This method sets the FdManager::fent map registration key to fentmapkey.
898+
//
899+
// [NOTE]
900+
// This method changes the file path of FdEntity.
901+
// Old file is deleted after linking to the new file path, and this works
902+
// without problem because the file descriptor is not affected even if the
903+
// cache file is open.
904+
// The mirror file descriptor is also the same. The mirror file path does
905+
// not need to be changed and will remain as it is.
906+
//
907+
bool FdEntity::RenamePath(const std::string& newpath, std::string& fentmapkey) {
908+
AutoLock auto_lock(&fdent_lock);
909+
if(!cachepath.empty()){
910+
// has cache path
911+
912+
// make new cache path
913+
std::string newcachepath;
914+
if(!FdManager::MakeCachePath(newpath.c_str(), newcachepath, true)){
915+
S3FS_PRN_ERR("failed to make cache path for object(%s).", newpath.c_str());
916+
return false;
917+
}
918+
919+
// rename cache file
920+
if(-1 == rename(cachepath.c_str(), newcachepath.c_str())){
921+
S3FS_PRN_ERR("failed to rename old cache path(%s) to new cache path(%s) by errno(%d).", cachepath.c_str(), newcachepath.c_str(), errno);
922+
return false;
923+
}
924+
925+
// link and unlink cache file stat
926+
if(!CacheFileStat::RenameCacheFileStat(path.c_str(), newpath.c_str())){
927+
S3FS_PRN_ERR("failed to rename cache file stat(%s to %s).", path.c_str(), newpath.c_str());
928+
return false;
929+
}
930+
fentmapkey = newpath;
931+
cachepath = newcachepath;
932+
}else{
933+
// does not have cache path
934+
fentmapkey.erase();
935+
FdManager::MakeRandomTempPath(newpath.c_str(), fentmapkey);
936+
}
937+
// set new path
938+
path = newpath;
939+
940+
return true;
941+
}
942+
846943
// [NOTE]
847944
// This method is called from olny nocopapi functions.
848945
// So we do not check disk space for this option mode, if there is no enough
@@ -1069,7 +1166,12 @@ int FdEntity::Load(off_t start, size_t size)
10691166
}else{
10701167
// single request
10711168
S3fsCurl s3fscurl;
1072-
result = s3fscurl.GetObjectRequest(path.c_str(), fd, (*iter)->offset, need_load_size);
1169+
if(0 < need_load_size){
1170+
S3fsCurl s3fscurl;
1171+
result = s3fscurl.GetObjectRequest(path.c_str(), fd, (*iter)->offset, need_load_size);
1172+
}else{
1173+
result = 0;
1174+
}
10731175
}
10741176
if(0 != result){
10751177
break;
@@ -1398,6 +1500,10 @@ int FdEntity::RowFlush(const char* tpath, bool force_sync)
13981500
backup = S3fsCurl::SetReadwriteTimeout(120);
13991501
}
14001502
result = S3fsCurl::ParallelMultipartUploadRequest(tpath ? tpath : path.c_str(), orgmeta, fd);
1503+
if (result != 0) {
1504+
S3FS_PRN_ERR("failed to flush object(errno=%d)", result);
1505+
return result;
1506+
}
14011507
if(0 != backup){
14021508
S3fsCurl::SetReadwriteTimeout(backup);
14031509
}
@@ -1414,8 +1520,19 @@ int FdEntity::RowFlush(const char* tpath, bool force_sync)
14141520

14151521
}else{
14161522
S3FS_PRN_INFO3("[path=%s][fd=%d] already being upload", path.c_str(), fd);
1523+
if (is_no_disk_space_flushed) {
1524+
// 磁盘空间不够,进入的顺序写模式只能往cos上传一次
1525+
S3FS_PRN_ERR("not enough disk space for writting file, allocate more space[path=%s].", path.c_str());
1526+
return -EIO;
1527+
}
1528+
is_no_disk_space_flushed = true;
14171529
// upload rest data
14181530
if(0 < mp_size){
1531+
// 磁盘空间不够,进入的顺序写模式要求为新写入的文件,或者长度比原有的更长
1532+
if (mp_start + mp_size < pagelist.Size()) {
1533+
S3FS_PRN_ERR("not enough disk space for writting file[path=%s].", path.c_str());
1534+
return -EIO;
1535+
}
14191536
if(0 != (result = NoCacheMultipartPost(fd, mp_start, mp_size))){
14201537
S3FS_PRN_ERR("failed to multipart post(start=%zd, size=%zu) for file(%d).", mp_start, mp_size, fd);
14211538
return result;
@@ -1548,6 +1665,7 @@ ssize_t FdEntity::Write(const char* bytes, off_t start, size_t size)
15481665
}
15491666
}else{
15501667
// alreay start miltipart uploading
1668+
15511669
}
15521670

15531671
// Writing
@@ -1564,6 +1682,11 @@ ssize_t FdEntity::Write(const char* bytes, off_t start, size_t size)
15641682

15651683
// check multipart uploading
15661684
if(0 < upload_id.length()){
1685+
// sequence write mode check offset
1686+
if (start != mp_start) {
1687+
S3FS_PRN_ERR("failed to write file [path=%s], make sure you have enough disk space.");
1688+
return -EIO;
1689+
}
15671690
mp_size += static_cast<size_t>(wsize);
15681691
if(static_cast<size_t>(S3fsCurl::GetMultipartSize()) <= mp_size){
15691692
// over one multipart size
@@ -2051,18 +2174,42 @@ FdEntity* FdManager::ExistOpen(const char* path, int existfd, bool ignore_existf
20512174
return ent;
20522175
}
20532176

2054-
void FdManager::Rename(const std::string &from, const std::string &to)
2177+
bool FdManager::Rename(const std::string &from, const std::string &to)
20552178
{
20562179
AutoLock auto_lock(&FdManager::fd_manager_lock);
20572180
fdent_map_t::iterator iter = fent.find(from);
2181+
if(fent.end() == iter && !FdManager::IsCacheDir()){
2182+
// If the cache directory is not specified, s3fs opens a temporary file
2183+
// when the file is opened.
2184+
// Then if it could not find a entity in map for the file, s3fs should
2185+
// search a entity in all which opened the temporary file.
2186+
//
2187+
for(iter = fent.begin(); iter != fent.end(); ++iter){
2188+
if((*iter).second && (*iter).second->IsOpen() && 0 == strcmp((*iter).second->GetPath(), from.c_str())){
2189+
break; // found opened fd in mapping
2190+
}
2191+
}
2192+
}
20582193
if(fent.end() != iter){
20592194
// found
20602195
S3FS_PRN_DBG("[from=%s][to=%s]", from.c_str(), to.c_str());
20612196
FdEntity* ent = (*iter).second;
20622197
fent.erase(iter);
2063-
ent->SetPath(to);
2064-
fent[to] = ent;
2198+
// rename path and caches in fd entity
2199+
string fentmapkey;
2200+
if(!ent->RenamePath(to, fentmapkey)){
2201+
S3FS_PRN_ERR("Failed to rename FdEntity obejct for %s to %s", from.c_str(), to.c_str());
2202+
return false;
2203+
}
2204+
if (fentmapkey.size() <= 0) {
2205+
S3FS_PRN_ERR("invalid rename object status from %s to %s", from.c_str(), to.c_str());
2206+
return false;
2207+
}
2208+
2209+
// set new fd entity to map
2210+
fent[fentmapkey] = ent;
20652211
}
2212+
return true;
20662213
}
20672214

20682215
bool FdManager::Close(FdEntity* ent)

src/fdcache.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class CacheFileStat
3838
public:
3939
static bool DeleteCacheFileStat(const char* path);
4040
static bool CheckCacheFileStatTopDir(void);
41+
static bool RenameCacheFileStat(const char* oldpath, const char* newpath);
4142

4243
explicit CacheFileStat(const char* tpath = NULL);
4344
~CacheFileStat();
@@ -98,7 +99,6 @@ class PageList
9899
bool FindUnloadedPage(off_t start, off_t& resstart, size_t& ressize) const;
99100
size_t GetTotalUnloadedPageSize(off_t start = 0, size_t size = 0) const; // size=0 is checking to end of list
100101
int GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start = 0, size_t size = 0) const; // size=0 is checking to end of list
101-
102102
bool Serialize(CacheFileStat& file, bool is_output);
103103
void Dump(void);
104104
};
@@ -127,6 +127,7 @@ class FdEntity
127127
off_t mp_start; // start position for no cached multipart(write method only)
128128
size_t mp_size; // size for no cached multipart(write method only)
129129
bool is_meta_pending;
130+
bool is_no_disk_space_flushed;
130131
private:
131132
static size_t max_prefetch_bytes;
132133
private:
@@ -152,7 +153,7 @@ class FdEntity
152153
int Dup(void);
153154

154155
const char* GetPath(void) const { return path.c_str(); }
155-
void SetPath(const std::string &newpath) { path = newpath; }
156+
bool RenamePath(const std::string& newpath, std::string& fentmapkey);
156157
int GetFd(void) const { return fd; }
157158

158159
bool GetStats(struct stat& st);
@@ -225,7 +226,7 @@ class FdManager
225226
FdEntity* GetFdEntity(const char* path, int existfd = -1);
226227
FdEntity* Open(const char* path, headers_t* pmeta = NULL, ssize_t size = -1, time_t time = -1, bool force_tmpfile = false, bool is_create = true);
227228
FdEntity* ExistOpen(const char* path, int existfd = -1, bool ignore_existfd = false);
228-
void Rename(const std::string &from, const std::string &to);
229+
bool Rename(const std::string &from, const std::string &to);
229230
bool Close(FdEntity* ent);
230231
bool ChangeEntityToTempPath(FdEntity* ent, const char* path);
231232
static bool SetTmpDir(const char* dir);

src/openssl_auth.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,45 @@ unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
271271
return result;
272272
}
273273

274+
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size)
275+
{
276+
MD5_CTX md5ctx;
277+
off_t bytes;
278+
unsigned char* result;
279+
280+
if(-1 == size){
281+
struct stat st;
282+
if(-1 == fstat(fd, &st)){
283+
return NULL;
284+
}
285+
size = st.st_size;
286+
}
287+
288+
MD5_Init(&md5ctx);
289+
290+
for(off_t total = 0; total < size; total += bytes){
291+
const off_t len = 512;
292+
char buf[len];
293+
bytes = len < (size - total) ? len : (size - total);
294+
bytes = pread(fd, buf, bytes, start + total);
295+
if(0 == bytes){
296+
// end of file
297+
break;
298+
}else if(-1 == bytes){
299+
// error
300+
S3FS_PRN_ERR("file read error(%d)", errno);
301+
return NULL;
302+
}
303+
MD5_Update(&md5ctx, buf, bytes);
304+
}
305+
306+
result = new unsigned char[get_md5_digest_length()];
307+
MD5_Final(result, &md5ctx);
308+
309+
return result;
310+
}
311+
312+
274313
//-------------------------------------------------------------------
275314
// Utility Function for SHA256
276315
//-------------------------------------------------------------------

0 commit comments

Comments
 (0)