@@ -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+
203246bool 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
411454size_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)
620668FdEntity::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
20682215bool FdManager::Close (FdEntity* ent)
0 commit comments