Skip to content

Commit 04a6509

Browse files
committed
Merge PR ceph#51661 into reef
* refs/pull/51661/head: Revert "mds: fix client isn't responding to mclientcaps(revoke)" Reviewed-by: Xiubo Li <[email protected]>
2 parents 614d7fa + 217cb70 commit 04a6509

File tree

4 files changed

+54
-126
lines changed

4 files changed

+54
-126
lines changed

src/mds/Capability.cc

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@
1818

1919
#include "common/Formatter.h"
2020

21-
#define dout_context g_ceph_context
22-
#define dout_subsys ceph_subsys_mds
23-
#undef dout_prefix
24-
#define dout_prefix *_dout << "Capability "
25-
2621

2722
/*
2823
* Capability::Export
@@ -181,45 +176,6 @@ client_t Capability::get_client() const
181176
return session ? session->get_client() : client_t(-1);
182177
}
183178

184-
int Capability::confirm_receipt(ceph_seq_t seq, unsigned caps) {
185-
int was_revoking = (_issued & ~_pending);
186-
if (seq == last_sent) {
187-
_revokes.clear();
188-
_issued = caps;
189-
// don't add bits
190-
_pending &= caps;
191-
192-
// if the revoking is not totally finished just add the
193-
// new revoking caps back.
194-
if (was_revoking && revoking()) {
195-
CInode *in = get_inode();
196-
dout(10) << "revocation is not totally finished yet on " << *in
197-
<< ", the session " << *session << dendl;
198-
_revokes.emplace_back(_pending, last_sent, last_issue);
199-
calc_issued();
200-
}
201-
} else {
202-
// can i forget any revocations?
203-
while (!_revokes.empty() && _revokes.front().seq < seq)
204-
_revokes.pop_front();
205-
if (!_revokes.empty()) {
206-
if (_revokes.front().seq == seq)
207-
_revokes.begin()->before = caps;
208-
calc_issued();
209-
} else {
210-
// seq < last_sent
211-
_issued = caps | _pending;
212-
}
213-
}
214-
215-
if (was_revoking && _issued == _pending) {
216-
item_revoking_caps.remove_myself();
217-
item_client_revoking_caps.remove_myself();
218-
maybe_clear_notable();
219-
}
220-
return was_revoking & ~_issued; // return revoked
221-
}
222-
223179
bool Capability::is_stale() const
224180
{
225181
return session ? session->is_stale() : false;

src/mds/Capability.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,52 @@ class Capability : public Counter<Capability> {
182182
inc_last_seq();
183183
return last_sent;
184184
}
185-
int confirm_receipt(ceph_seq_t seq, unsigned caps);
185+
int confirm_receipt(ceph_seq_t seq, unsigned caps) {
186+
int was_revoking = (_issued & ~_pending);
187+
if (seq == last_sent) {
188+
_revokes.clear();
189+
_issued = caps;
190+
// don't add bits
191+
_pending &= caps;
192+
} else {
193+
// can i forget any revocations?
194+
while (!_revokes.empty() && _revokes.front().seq < seq)
195+
_revokes.pop_front();
196+
if (!_revokes.empty()) {
197+
if (_revokes.front().seq == seq)
198+
_revokes.begin()->before = caps;
199+
calc_issued();
200+
} else {
201+
// seq < last_sent
202+
_issued = caps | _pending;
203+
}
204+
}
205+
206+
if (was_revoking && _issued == _pending) {
207+
item_revoking_caps.remove_myself();
208+
item_client_revoking_caps.remove_myself();
209+
maybe_clear_notable();
210+
}
211+
return was_revoking & ~_issued; // return revoked
212+
}
213+
// we may get a release racing with revocations, which means our revokes will be ignored
214+
// by the client. clean them out of our _revokes history so we don't wait on them.
215+
void clean_revoke_from(ceph_seq_t li) {
216+
bool changed = false;
217+
while (!_revokes.empty() && _revokes.front().last_issue <= li) {
218+
_revokes.pop_front();
219+
changed = true;
220+
}
221+
if (changed) {
222+
bool was_revoking = (_issued & ~_pending);
223+
calc_issued();
224+
if (was_revoking && _issued == _pending) {
225+
item_revoking_caps.remove_myself();
226+
item_client_revoking_caps.remove_myself();
227+
maybe_clear_notable();
228+
}
229+
}
230+
}
186231
ceph_seq_t get_mseq() const { return mseq; }
187232
void inc_mseq() { mseq++; }
188233

src/mds/Locker.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4066,6 +4066,13 @@ void Locker::_do_cap_release(client_t client, inodeno_t ino, uint64_t cap_id,
40664066
new C_Locker_RetryCapRelease(this, client, ino, cap_id, mseq, seq));
40674067
return;
40684068
}
4069+
if (seq != cap->get_last_issue()) {
4070+
dout(7) << " issue_seq " << seq << " != " << cap->get_last_issue() << dendl;
4071+
// clean out any old revoke history
4072+
cap->clean_revoke_from(seq);
4073+
eval_cap_gather(in);
4074+
return;
4075+
}
40694076
remove_client_cap(in, cap);
40704077
}
40714078

src/test/libcephfs/multiclient.cc

Lines changed: 1 addition & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,12 @@
1515
#include "gtest/gtest.h"
1616
#include "include/compat.h"
1717
#include "include/cephfs/libcephfs.h"
18-
#include <dirent.h>
1918
#include <errno.h>
2019
#include <fcntl.h>
2120
#include <unistd.h>
2221
#include <sys/types.h>
2322
#include <sys/stat.h>
24-
#include <thread>
23+
#include <dirent.h>
2524
#ifdef __linux__
2625
#include <sys/xattr.h>
2726
#endif
@@ -99,82 +98,3 @@ TEST(LibCephFS, MulticlientHoleEOF) {
9998
ceph_shutdown(ca);
10099
ceph_shutdown(cb);
101100
}
102-
103-
static void write_func(bool *stop)
104-
{
105-
struct ceph_mount_info *cmount;
106-
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
107-
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
108-
ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
109-
ASSERT_EQ(ceph_mount(cmount, "/"), 0);
110-
111-
char name[20];
112-
snprintf(name, sizeof(name), "foo.%d", getpid());
113-
int fd = ceph_open(cmount, name, O_CREAT|O_RDWR, 0644);
114-
ASSERT_LE(0, fd);
115-
116-
int buf_size = 4096;
117-
char *buf = (char *)malloc(buf_size);
118-
if (!buf) {
119-
*stop = true;
120-
printf("write_func failed to allocate buffer!");
121-
return;
122-
}
123-
memset(buf, 1, buf_size);
124-
125-
while (!(*stop)) {
126-
int i;
127-
128-
// truncate the file size to 4096 will set the max_size to 4MB.
129-
ASSERT_EQ(0, ceph_ftruncate(cmount, fd, 4096));
130-
131-
// write 4MB + extra 64KB data will make client to trigger to
132-
// call check_cap() to report new size. And if MDS is revoking
133-
// the Fsxrw caps and we are still holding the Fw caps and will
134-
// trigger tracker#57244.
135-
for (i = 0; i < 1040; i++) {
136-
ASSERT_EQ(ceph_write(cmount, fd, buf, buf_size, 0), buf_size);
137-
}
138-
}
139-
140-
ceph_shutdown(cmount);
141-
}
142-
143-
static void setattr_func(bool *stop)
144-
{
145-
struct ceph_mount_info *cmount;
146-
ASSERT_EQ(ceph_create(&cmount, NULL), 0);
147-
ASSERT_EQ(ceph_conf_read_file(cmount, NULL), 0);
148-
ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
149-
ASSERT_EQ(ceph_mount(cmount, "/"), 0);
150-
151-
char name[20];
152-
snprintf(name, sizeof(name), "foo.%d", getpid());
153-
int fd = ceph_open(cmount, name, O_CREAT|O_RDWR, 0644);
154-
ASSERT_LE(0, fd);
155-
156-
while (!(*stop)) {
157-
// setattr will make the MDS to acquire xlock for the filelock and
158-
// force to revoke caps from clients
159-
struct ceph_statx stx = {.stx_size = 0};
160-
ASSERT_EQ(ceph_fsetattrx(cmount, fd, &stx, CEPH_SETATTR_SIZE), 0);
161-
}
162-
163-
ceph_shutdown(cmount);
164-
}
165-
166-
TEST(LibCephFS, MulticlientRevokeCaps) {
167-
std::thread thread1, thread2;
168-
bool stop = false;
169-
int wait = 60; // in second
170-
171-
thread1 = std::thread(write_func, &stop);
172-
thread2 = std::thread(setattr_func, &stop);
173-
174-
printf(" Will run test for %d seconds!\n", wait);
175-
sleep(wait);
176-
stop = true;
177-
178-
thread1.join();
179-
thread2.join();
180-
}

0 commit comments

Comments
 (0)