ceph: update wanted caps after resuming stale session
mds contains an optimization, it does not re-issue stale caps if client does not want any cap. A special case of the optimization is that client wants some caps, but skipped updating 'wanted'. For this case, client needs to update 'wanted' when stale session get renewed. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
@@ -657,6 +657,9 @@ void ceph_add_cap(struct inode *inode,
|
|||||||
session->s_nr_caps++;
|
session->s_nr_caps++;
|
||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
} else {
|
} else {
|
||||||
|
if (cap->cap_gen < session->s_cap_gen)
|
||||||
|
cap->issued = cap->implemented = CEPH_CAP_PIN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* auth mds of the inode changed. we received the cap export
|
* auth mds of the inode changed. we received the cap export
|
||||||
* message, but still haven't received the cap import message.
|
* message, but still haven't received the cap import message.
|
||||||
@@ -3065,21 +3068,6 @@ static void handle_cap_grant(struct inode *inode,
|
|||||||
inode->i_size);
|
inode->i_size);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* auth mds of the inode changed. we received the cap export message,
|
|
||||||
* but still haven't received the cap import message. handle_cap_export
|
|
||||||
* updated the new auth MDS' cap.
|
|
||||||
*
|
|
||||||
* "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message
|
|
||||||
* that was sent before the cap import message. So don't remove caps.
|
|
||||||
*/
|
|
||||||
if (ceph_seq_cmp(seq, cap->seq) <= 0) {
|
|
||||||
WARN_ON(cap != ci->i_auth_cap);
|
|
||||||
WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id));
|
|
||||||
seq = cap->seq;
|
|
||||||
newcaps |= cap->issued;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If CACHE is being revoked, and we have no dirty buffers,
|
* If CACHE is being revoked, and we have no dirty buffers,
|
||||||
* try to invalidate (once). (If there are dirty buffers, we
|
* try to invalidate (once). (If there are dirty buffers, we
|
||||||
@@ -3099,6 +3087,24 @@ static void handle_cap_grant(struct inode *inode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (was_stale)
|
||||||
|
cap->issued = cap->implemented = CEPH_CAP_PIN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* auth mds of the inode changed. we received the cap export message,
|
||||||
|
* but still haven't received the cap import message. handle_cap_export
|
||||||
|
* updated the new auth MDS' cap.
|
||||||
|
*
|
||||||
|
* "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing a message
|
||||||
|
* that was sent before the cap import message. So don't remove caps.
|
||||||
|
*/
|
||||||
|
if (ceph_seq_cmp(seq, cap->seq) <= 0) {
|
||||||
|
WARN_ON(cap != ci->i_auth_cap);
|
||||||
|
WARN_ON(cap->cap_id != le64_to_cpu(grant->cap_id));
|
||||||
|
seq = cap->seq;
|
||||||
|
newcaps |= cap->issued;
|
||||||
|
}
|
||||||
|
|
||||||
/* side effects now are allowed */
|
/* side effects now are allowed */
|
||||||
cap->cap_gen = session->s_cap_gen;
|
cap->cap_gen = session->s_cap_gen;
|
||||||
cap->seq = seq;
|
cap->seq = seq;
|
||||||
@@ -3549,9 +3555,9 @@ retry:
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (target < 0) {
|
if (target < 0) {
|
||||||
__ceph_remove_cap(cap, false);
|
if (cap->mds_wanted | cap->issued)
|
||||||
if (!ci->i_auth_cap)
|
|
||||||
ci->i_ceph_flags |= CEPH_I_CAP_DROPPED;
|
ci->i_ceph_flags |= CEPH_I_CAP_DROPPED;
|
||||||
|
__ceph_remove_cap(cap, false);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1232,13 +1232,13 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
|
|||||||
dout("removing cap %p, ci is %p, inode is %p\n",
|
dout("removing cap %p, ci is %p, inode is %p\n",
|
||||||
cap, ci, &ci->vfs_inode);
|
cap, ci, &ci->vfs_inode);
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
|
if (cap->mds_wanted | cap->issued)
|
||||||
|
ci->i_ceph_flags |= CEPH_I_CAP_DROPPED;
|
||||||
__ceph_remove_cap(cap, false);
|
__ceph_remove_cap(cap, false);
|
||||||
if (!ci->i_auth_cap) {
|
if (!ci->i_auth_cap) {
|
||||||
struct ceph_cap_flush *cf;
|
struct ceph_cap_flush *cf;
|
||||||
struct ceph_mds_client *mdsc = fsc->mdsc;
|
struct ceph_mds_client *mdsc = fsc->mdsc;
|
||||||
|
|
||||||
ci->i_ceph_flags |= CEPH_I_CAP_DROPPED;
|
|
||||||
|
|
||||||
if (ci->i_wrbuffer_ref > 0 &&
|
if (ci->i_wrbuffer_ref > 0 &&
|
||||||
READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
|
READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN)
|
||||||
invalidate = true;
|
invalidate = true;
|
||||||
@@ -1355,6 +1355,12 @@ static void remove_session_caps(struct ceph_mds_session *session)
|
|||||||
dispose_cap_releases(session->s_mdsc, &dispose);
|
dispose_cap_releases(session->s_mdsc, &dispose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RECONNECT,
|
||||||
|
RENEWCAPS,
|
||||||
|
FORCE_RO,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wake up any threads waiting on this session's caps. if the cap is
|
* wake up any threads waiting on this session's caps. if the cap is
|
||||||
* old (didn't get renewed on the client reconnect), remove it now.
|
* old (didn't get renewed on the client reconnect), remove it now.
|
||||||
@@ -1365,23 +1371,34 @@ static int wake_up_session_cb(struct inode *inode, struct ceph_cap *cap,
|
|||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||||
|
unsigned long ev = (unsigned long)arg;
|
||||||
|
|
||||||
if (arg) {
|
if (ev == RECONNECT) {
|
||||||
spin_lock(&ci->i_ceph_lock);
|
spin_lock(&ci->i_ceph_lock);
|
||||||
ci->i_wanted_max_size = 0;
|
ci->i_wanted_max_size = 0;
|
||||||
ci->i_requested_max_size = 0;
|
ci->i_requested_max_size = 0;
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
} else if (ev == RENEWCAPS) {
|
||||||
|
if (cap->cap_gen < cap->session->s_cap_gen) {
|
||||||
|
/* mds did not re-issue stale cap */
|
||||||
|
spin_lock(&ci->i_ceph_lock);
|
||||||
|
cap->issued = cap->implemented = CEPH_CAP_PIN;
|
||||||
|
/* make sure mds knows what we want */
|
||||||
|
if (__ceph_caps_file_wanted(ci) & ~cap->mds_wanted)
|
||||||
|
ci->i_ceph_flags |= CEPH_I_CAP_DROPPED;
|
||||||
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
|
}
|
||||||
|
} else if (ev == FORCE_RO) {
|
||||||
}
|
}
|
||||||
wake_up_all(&ci->i_cap_wq);
|
wake_up_all(&ci->i_cap_wq);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wake_up_session_caps(struct ceph_mds_session *session,
|
static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
|
||||||
int reconnect)
|
|
||||||
{
|
{
|
||||||
dout("wake_up_session_caps %p mds%d\n", session, session->s_mds);
|
dout("wake_up_session_caps %p mds%d\n", session, session->s_mds);
|
||||||
iterate_session_caps(session, wake_up_session_cb,
|
iterate_session_caps(session, wake_up_session_cb,
|
||||||
(void *)(unsigned long)reconnect);
|
(void *)(unsigned long)ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1466,7 +1483,7 @@ static void renewed_caps(struct ceph_mds_client *mdsc,
|
|||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
|
|
||||||
if (wake)
|
if (wake)
|
||||||
wake_up_session_caps(session, 0);
|
wake_up_session_caps(session, RENEWCAPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2847,7 +2864,7 @@ static void handle_session(struct ceph_mds_session *session,
|
|||||||
spin_lock(&session->s_cap_lock);
|
spin_lock(&session->s_cap_lock);
|
||||||
session->s_readonly = true;
|
session->s_readonly = true;
|
||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
wake_up_session_caps(session, 0);
|
wake_up_session_caps(session, FORCE_RO);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CEPH_SESSION_REJECT:
|
case CEPH_SESSION_REJECT:
|
||||||
@@ -3339,7 +3356,7 @@ static void check_new_map(struct ceph_mds_client *mdsc,
|
|||||||
pr_info("mds%d recovery completed\n", s->s_mds);
|
pr_info("mds%d recovery completed\n", s->s_mds);
|
||||||
kick_requests(mdsc, i);
|
kick_requests(mdsc, i);
|
||||||
ceph_kick_flushing_caps(mdsc, s);
|
ceph_kick_flushing_caps(mdsc, s);
|
||||||
wake_up_session_caps(s, 1);
|
wake_up_session_caps(s, RECONNECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,15 @@
|
|||||||
|
|
||||||
/* The first 8 bits are reserved for old ceph releases */
|
/* The first 8 bits are reserved for old ceph releases */
|
||||||
#define CEPHFS_FEATURE_MIMIC 8
|
#define CEPHFS_FEATURE_MIMIC 8
|
||||||
|
#define CEPHFS_FEATURE_REPLY_ENCODING 9
|
||||||
|
#define CEPHFS_FEATURE_RECLAIM_CLIENT 10
|
||||||
|
#define CEPHFS_FEATURE_LAZY_CAP_WANTED 11
|
||||||
|
|
||||||
#define CEPHFS_FEATURES_ALL { \
|
#define CEPHFS_FEATURES_CLIENT_SUPPORTED { \
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, \
|
0, 1, 2, 3, 4, 5, 6, 7, \
|
||||||
CEPHFS_FEATURE_MIMIC, \
|
CEPHFS_FEATURE_MIMIC, \
|
||||||
|
CEPHFS_FEATURE_LAZY_CAP_WANTED, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CEPHFS_FEATURES_CLIENT_SUPPORTED CEPHFS_FEATURES_ALL
|
|
||||||
#define CEPHFS_FEATURES_CLIENT_REQUIRED {}
|
#define CEPHFS_FEATURES_CLIENT_REQUIRED {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user