summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_file.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/rgw/rgw_file.h')
-rw-r--r--src/rgw/rgw_file.h76
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 */