@@ -2798,7 +2798,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
void *inline_data, u32 inline_len,
struct ceph_buffer *xattr_buf,
struct ceph_mds_session *session,
- struct ceph_cap *cap, int issued)
+ struct ceph_cap *cap, int issued,
+ struct timespec *btime, u64 change_attr)
__releases(ci->i_ceph_lock)
__releases(mdsc->snap_rwsem)
{
@@ -2864,11 +2865,14 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
__check_cap_issue(ci, cap, newcaps);
+ inode->i_version = max(change_attr, inode->i_version);
+
if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
(issued & CEPH_CAP_AUTH_EXCL) == 0) {
inode->i_mode = le32_to_cpu(grant->mode);
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
+ ci->i_btime = *btime;
dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode,
from_kuid(&init_user_ns, inode->i_uid),
from_kgid(&init_user_ns, inode->i_gid));
@@ -3480,6 +3484,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
void *snaptrace;
size_t snaptrace_len;
void *p, *end;
+ u16 hdr_version;
+ struct timespec btime = {};
+ u64 change_attr = 0;
dout("handle_caps from mds%d\n", mds);
@@ -3499,7 +3506,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
snaptrace_len = le32_to_cpu(h->snap_trace_len);
p = snaptrace + snaptrace_len;
- if (le16_to_cpu(msg->hdr.version) >= 2) {
+ hdr_version = le16_to_cpu(msg->hdr.version);
+ if (hdr_version >= 2) {
u32 flock_len;
ceph_decode_32_safe(&p, end, flock_len, bad);
if (p + flock_len > end)
@@ -3507,7 +3515,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
p += flock_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 3) {
+ if (hdr_version >= 3) {
if (op == CEPH_CAP_OP_IMPORT) {
if (p + sizeof(*peer) > end)
goto bad;
@@ -3519,7 +3527,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
}
}
- if (le16_to_cpu(msg->hdr.version) >= 4) {
+ if (hdr_version >= 4) {
ceph_decode_64_safe(&p, end, inline_version, bad);
ceph_decode_32_safe(&p, end, inline_len, bad);
if (p + inline_len > end)
@@ -3528,7 +3536,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
p += inline_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 8) {
+ if (hdr_version >= 8) {
u64 flush_tid;
u32 caller_uid, caller_gid;
u32 osd_epoch_barrier;
@@ -3549,6 +3557,13 @@ void ceph_handle_caps(struct ceph_mds_session *session,
}
}
+ if (hdr_version >= 9) {
+ ceph_decode_need(&p, end, sizeof(struct ceph_timespec), bad);
+ ceph_decode_timespec(&btime, p);
+ p += sizeof(struct ceph_timespec);
+ ceph_decode_64_safe(&p, end, change_attr, bad);
+ }
+
/* lookup ino */
inode = ceph_find_inode(sb, vino);
ci = ceph_inode(inode);
@@ -3604,7 +3619,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
&cap, &issued);
handle_cap_grant(mdsc, inode, h, &pool_ns,
inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ msg->middle, session, cap, issued, &btime,
+ change_attr);
if (realm)
ceph_put_snap_realm(mdsc, realm);
goto done_unlocked;
@@ -3628,7 +3644,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
issued |= __ceph_caps_dirty(ci);
handle_cap_grant(mdsc, inode, h, &pool_ns,
inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ msg->middle, session, cap, issued, &btime,
+ change_attr);
goto done_unlocked;
case CEPH_CAP_OP_FLUSH_ACK:
@@ -529,6 +529,9 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
capsnap->mode = inode->i_mode;
capsnap->uid = inode->i_uid;
capsnap->gid = inode->i_gid;
+ capsnap->btime = ci->i_btime;
+
+ capsnap->change_attr = inode->i_version;
if (dirty & CEPH_CAP_XATTR_EXCL) {
__ceph_build_xattrs_blob(ci);
@@ -173,10 +173,13 @@ struct ceph_cap_snap {
umode_t mode;
kuid_t uid;
kgid_t gid;
+ struct timespec btime;
struct ceph_buffer *xattr_blob;
u64 xattr_version;
+ u64 change_attr;
+
u64 size;
struct timespec mtime, atime, ctime;
u64 time_warp_seq;
Signed-off-by: Jeff Layton <jlayton@redhat.com> --- fs/ceph/caps.c | 31 ++++++++++++++++++++++++------- fs/ceph/snap.c | 3 +++ fs/ceph/super.h | 3 +++ 3 files changed, 30 insertions(+), 7 deletions(-)