Flush file when opening second fd

Previously when s3fs had dirty local data and an application opened a
second fd it would remove the stat cache entry, query S3 for the size
which was still zero, then reinitialize FdEntry with this incorrect
size.  Instead flush local data to S3 so this query works.  It is
possible that a more involved patch could do this with a less
heavyweight approach but this requires changing open.  This does not
completely fix git clone but allows it to proceed further.  Also make
some cache methods const-correct.  References #839.
This commit is contained in:
Andrew Gaul 2019-05-05 09:05:28 +09:00
parent 511d223468
commit c596441f58
4 changed files with 24 additions and 8 deletions

View File

@ -220,7 +220,7 @@ void StatCache::Clear()
S3FS_MALLOCTRIM(0);
}
bool StatCache::GetStat(string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce)
bool StatCache::GetStat(const string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce)
{
bool is_delete_cache = false;
string strpath = key;

View File

@ -65,7 +65,7 @@ class StatCache
~StatCache();
void Clear(void);
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
// Truncate stat cache
bool TruncateCache(void);
@ -93,19 +93,19 @@ class StatCache
}
// Get stat cache
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true, bool* pisforce = NULL) {
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true, bool* pisforce = NULL) {
return GetStat(key, pst, meta, overcheck, NULL, pisforce);
}
bool GetStat(std::string& key, struct stat* pst, bool overcheck = true) {
bool GetStat(const std::string& key, struct stat* pst, bool overcheck = true) {
return GetStat(key, pst, NULL, overcheck, NULL, NULL);
}
bool GetStat(std::string& key, headers_t* meta, bool overcheck = true) {
bool GetStat(const std::string& key, headers_t* meta, bool overcheck = true) {
return GetStat(key, NULL, meta, overcheck, NULL, NULL);
}
bool HasStat(std::string& key, bool overcheck = true) {
bool HasStat(const std::string& key, bool overcheck = true) {
return GetStat(key, NULL, NULL, overcheck, NULL, NULL);
}
bool HasStat(std::string& key, const char* etag, bool overcheck = true) {
bool HasStat(const std::string& key, const char* etag, bool overcheck = true) {
return GetStat(key, NULL, NULL, overcheck, etag, NULL);
}

View File

@ -2143,7 +2143,13 @@ static int s3fs_open(const char* _path, struct fuse_file_info* fi)
// clear stat for reading fresh stat.
// (if object stat is changed, we refresh it. then s3fs gets always
// stat when s3fs open the object).
StatCache::getStatCacheData()->DelStat(path);
if(StatCache::getStatCacheData()->HasStat(path)){
// flush any dirty data so that subsequent stat gets correct size
if((result = s3fs_flush(_path, fi)) != 0){
S3FS_PRN_ERR("could not flush(%s): result=%d", path, result);
}
StatCache::getStatCacheData()->DelStat(path);
}
int mask = (O_RDONLY != (fi->flags & O_ACCMODE) ? W_OK : R_OK);
if(0 != (result = check_parent_object_access(path, X_OK))){

View File

@ -547,6 +547,15 @@ function test_concurrency {
rm -f `seq 100`
}
function test_open_second_fd {
describe "read from an open fd"
rm -f ${TEST_TEXT_FILE}
RESULT=$( (echo foo ; wc -c < ${TEST_TEXT_FILE} >&2) 2>& 1>${TEST_TEXT_FILE})
if [ "$RESULT" -ne 4 ]; then
echo "size mismatch, expected: 4, was: ${RESULT}"
return 1
fi
}
function add_all_tests {
add_tests test_append_file
@ -574,6 +583,7 @@ function add_all_tests {
add_tests test_write_after_seek_ahead
add_tests test_overwrite_existing_file_range
add_tests test_concurrency
add_tests test_open_second_fd
}
init_suite