Following sequence of events can happen.
- Client releases an inode, queues cap release message.
- A 'lookup' reply brings the same inode back, but the reply doesn't
contain inline data because MDS didn't receive the cap release
message and thought client already has up-to-data inline data.
The fix is trigger a getattr if client finds inline_version is zero.
The getattr mask is set to CEPH_STAT_CAP_INLINE_DATA, so that MDS knows
client does not have inline data.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
st->time_warp_seq, st->ctime, st->mtime, st->atime,
st->inline_version, st->inline_data,
issued);
+ } else if (st->inline_version > in->inline_version) {
+ in->inline_data = st->inline_data;
+ in->inline_version = st->inline_version;
}
// move me if/when version reflects fragtree changes.
//bool lazy = f->mode == CEPH_FILE_MODE_LAZY;
+ if (in->inline_version == 0) {
+ int r = _getattr(in, CEPH_STAT_CAP_INLINE_DATA);
+ if (r < 0)
+ return r;
+ assert(in->inline_version > 0);
+ }
+
int have;
int r = get_caps(in, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, &have, -1);
if (r < 0)
// time it.
utime_t start = ceph_clock_now(cct);
+ if (in->inline_version == 0) {
+ int r = _getattr(in, CEPH_STAT_CAP_INLINE_DATA);
+ if (r < 0)
+ return r;
+ assert(in->inline_version > 0);
+ }
+
// copy into fresh buffer (since our write may be resub, async)
bufferptr bp;
if (size > 0) bp = buffer::copy(buf, size);
CEPH_CAP_LINK_SHARED | \
CEPH_CAP_FILE_SHARED | \
CEPH_CAP_XATTR_SHARED)
+#define CEPH_STAT_CAP_INLINE_DATA (CEPH_CAP_FILE_SHARED | \
+ CEPH_CAP_FILE_RD)
#define CEPH_CAP_ANY_SHARED (CEPH_CAP_AUTH_SHARED | \
CEPH_CAP_LINK_SHARED | \
// inline data
version_t inline_version = 0;
bufferlist inline_data;
- if (!cap || (cap->client_inline_version < i->inline_version)) {
+ if (i->inline_version == CEPH_INLINE_NONE) {
+ inline_version = CEPH_INLINE_NONE;
+ } else if ((!cap && !no_caps) ||
+ (cap && cap->client_inline_version < i->inline_version) ||
+ (getattr_caps & CEPH_CAP_FILE_RD)) { // client requests inline data
inline_version = i->inline_version;
inline_data = i->inline_data;
- if (cap)
- cap->client_inline_version = i->inline_version;
}
// nest (do same as file... :/)
<< " xattrv " << e.xattr_version << " len " << xbl.length()
<< dendl;
+ if (inline_data.length() && cap) {
+ if ((cap->pending() | getattr_caps) & CEPH_CAP_FILE_SHARED) {
+ dout(10) << "including inline version " << inline_version << dendl;
+ cap->client_inline_version = inline_version;
+ } else {
+ dout(10) << "dropping inline version " << inline_version << dendl;
+ inline_version = 0;
+ inline_data.clear();
+ }
+ }
+
// include those xattrs?
if (xbl.length() && cap) {
if ((cap->pending() | getattr_caps) & CEPH_CAP_XATTR_SHARED) {
return;
// note which caps are requested, so we return at least a snapshot
- // value for them. (currently this only matters for xattrs)
+ // value for them. (currently this matters for xattrs and inline data)
mdr->getattr_caps = mask;
mds->balancer->hit_inode(ceph_clock_now(g_ceph_context), ref, META_POP_IRD,