diff options
Diffstat (limited to 'src/rgw/rgw_file.h')
-rw-r--r-- | src/rgw/rgw_file.h | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index e2395be3a56..9af81ed322f 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -239,6 +239,15 @@ namespace rgw { void clear_state(); + void advance_mtime() { + /* intended for use on directories, fast-forward mtime so as to + * ensure a new, higher value for the change attribute */ + lock_guard guard(mtx); + /* sets ctime as well as mtime, to avoid masking updates should + * ctime inexplicably hold a higher value */ + set_times(real_clock::now()); + } + boost::variant<file, directory> variant_type; uint16_t depth; @@ -349,6 +358,8 @@ namespace rgw { switch (fh.fh_type) { case RGW_FS_TYPE_DIRECTORY: state.unix_mode = RGW_RWXMODE|S_IFDIR; + /* virtual directories are always invalid */ + advance_mtime(); break; case RGW_FS_TYPE_FILE: state.unix_mode = RGW_RWMODE|S_IFREG; @@ -420,8 +431,12 @@ namespace rgw { if (mask & RGW_SETATTR_ATIME) state.atime = st->st_atim; - if (mask & RGW_SETATTR_MTIME) - state.mtime = st->st_mtim; + + if (mask & RGW_SETATTR_MTIME) { + if (fh.fh_type != RGW_FS_TYPE_DIRECTORY) + state.mtime = st->st_mtim; + } + if (mask & RGW_SETATTR_CTIME) state.ctime = st->st_ctim; } @@ -437,18 +452,10 @@ namespace rgw { st->st_mode = state.unix_mode; -#ifdef HAVE_STAT_ST_MTIMESPEC_TV_NSEC - st->st_atimespec = state.atime; - st->st_mtimespec = state.mtime; - st->st_ctimespec = state.ctime; -#else - st->st_atim = state.atime; - st->st_mtim = state.mtime; - st->st_ctim = state.ctime; -#endif - switch (fh.fh_type) { case RGW_FS_TYPE_DIRECTORY: + /* virtual directories are always invalid */ + advance_mtime(); st->st_nlink = state.nlink; break; case RGW_FS_TYPE_FILE: @@ -467,6 +474,16 @@ namespace rgw { break; } +#ifdef HAVE_STAT_ST_MTIMESPEC_TV_NSEC + st->st_atimespec = state.atime; + st->st_mtimespec = state.mtime; + st->st_ctimespec = state.ctime; +#else + st->st_atim = state.atime; + st->st_mtim = state.mtime; + st->st_ctim = state.ctime; +#endif + return 0; } @@ -1205,10 +1222,13 @@ namespace rgw { RGWFileHandle::FHCache::FLAG_LOCK); /* LATCHED */ if (! fh) { + if (unlikely(fhk == root_fh.fh.fh_hk)) { + /* lookup for root of this fs */ + fh = &root_fh; + goto out; + } lsubdout(get_context(), rgw, 0) - << __func__ << " handle lookup failed <" - << fhk.fh_hk.bucket << "," << fhk.fh_hk.object << ">" - << "(need persistent handles)" + << __func__ << " handle lookup failed " << fhk << dendl; goto out; } @@ -1286,12 +1306,14 @@ public: uint64_t* ioff; size_t ix; uint32_t d_count; + bool rcb_eof; // caller forced early stop in readdir cycle RGWListBucketsRequest(CephContext* _cct, RGWUserInfo *_user, RGWFileHandle* _rgw_fh, rgw_readdir_cb _rcb, void* _cb_arg, RGWFileHandle::readdir_offset& _offset) : RGWLibRequest(_cct, _user), rgw_fh(_rgw_fh), offset(_offset), - cb_arg(_cb_arg), rcb(_rcb), ioff(nullptr), ix(0), d_count(0) { + cb_arg(_cb_arg), rcb(_rcb), ioff(nullptr), ix(0), d_count(0), + rcb_eof(false) { using boost::get; @@ -1364,6 +1386,7 @@ public: << " dirent=" << ent.bucket.name << " call count=" << ix << dendl; + rcb_eof = true; return; } ++ix; @@ -1397,7 +1420,7 @@ public: << " is_truncated: " << is_truncated << dendl; } - return !is_truncated; + return !is_truncated && !rcb_eof; } }; /* RGWListBucketsRequest */ @@ -1417,12 +1440,14 @@ public: uint64_t* ioff; size_t ix; uint32_t d_count; + bool rcb_eof; // caller forced early stop in readdir cycle RGWReaddirRequest(CephContext* _cct, RGWUserInfo *_user, RGWFileHandle* _rgw_fh, rgw_readdir_cb _rcb, void* _cb_arg, RGWFileHandle::readdir_offset& _offset) : RGWLibRequest(_cct, _user), rgw_fh(_rgw_fh), offset(_offset), - cb_arg(_cb_arg), rcb(_rcb), ioff(nullptr), ix(0), d_count(0) { + cb_arg(_cb_arg), rcb(_rcb), ioff(nullptr), ix(0), d_count(0), + rcb_eof(false) { using boost::get; @@ -1533,12 +1558,13 @@ public: << " (" << sref << ")" << "" << dendl; - if(! this->operator()(sref, next_marker, RGW_FS_TYPE_FILE)) { + if (! this->operator()(sref, next_marker, RGW_FS_TYPE_FILE)) { /* caller cannot accept more */ lsubdout(cct, rgw, 5) << "readdir rcb failed" << " dirent=" << sref.data() << " call count=" << ix << dendl; + rcb_eof = true; return; } ++ix; @@ -1579,7 +1605,15 @@ public: return; } - this->operator()(sref, next_marker, RGW_FS_TYPE_DIRECTORY); + if (! this->operator()(sref, next_marker, RGW_FS_TYPE_DIRECTORY)) { + /* caller cannot accept more */ + lsubdout(cct, rgw, 5) << "readdir rcb failed" + << " dirent=" << sref.data() + << " call count=" << ix + << dendl; + rcb_eof = true; + return; + } ++ix; } } @@ -1599,7 +1633,7 @@ public: << " is_truncated: " << is_truncated << dendl; } - return !is_truncated; + return !is_truncated && !rcb_eof; } }; /* RGWReaddirRequest */ |