Skip to content

Commit a00caf8

Browse files
Merge pull request ceph#57099 from ceph/wip-lusov-quiesce-await-eperm
mds/quiesce: db: quiesce-await should EPERM if a set is past QS_QUIESCED Reviewed-by: Patrick Donnelly <[email protected]>
2 parents 4a592ad + fd88b52 commit a00caf8

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

doc/cephfs/fs-volumes.rst

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,15 +1024,41 @@ Note that the commands above are all non-blocking. If we want to wait for the qu
10241024
to reach the `QUIESCED` state, we should await it at some point. ``--await`` can be given
10251025
along with other arguments to let the system know our intention.
10261026

1027-
Technically, there are two types of await: `quiesce await` and `release await`. The former
1028-
is the default, and the latter can only be achieved with ``--release`` present in the argument list.
1029-
To avoid confision, it is not permitted to issue a `quiesce await` when the set is already `RELEASING`
1030-
or `RELEASED`. Trying to ``--release`` a set that is not `QUIESCED` is an ``EPERM`` error as well, regardless
1031-
of whether await is requested alongside. However, it's not an error to `release await`
1032-
an already released set, or to `quiesce await` a `QUIESCED` one.
1033-
1034-
When awaiting, one may also specify a maximum duration that they would like this await request to block for,
1035-
not affecting the two intrinsic timeouts discussed above. If the target awaited state isn't reached
1027+
There are two types of await: `quiesce await` and `release await`. The former is the default,
1028+
and the latter can only be achieved with ``--release`` present in the argument list.
1029+
To avoid confision, it is not permitted to issue a `quiesce await` when the set is not `QUIESCING`.
1030+
Trying to ``--release`` a set that is not `QUIESCED` is an ``EPERM`` error as well, regardless
1031+
of whether await is requested alongside. However, it's not an error to `release await`
1032+
an already released set, or to `quiesce await` a `QUIESCED` one - those are successful no-ops.
1033+
1034+
Since a set is awaited after the application of the ``--await``-augmented command, the await operation
1035+
may mask a successful result with its own error. A good example is trying to cancel-await a set:
1036+
1037+
.. prompt:: bash $ auto
1038+
1039+
$ ceph fs quiesce fs1 --set-id set1 --cancel --await
1040+
{
1041+
// ...
1042+
"sets": {
1043+
"set1": {
1044+
// ...
1045+
"state": {
1046+
"name": "CANCELED",
1047+
"age": 0
1048+
},
1049+
// ...
1050+
}
1051+
}
1052+
}
1053+
Error EPERM:
1054+
1055+
Although ``--cancel`` will succeed syncrhonously for a set in an active state, awaiting a canceled
1056+
set is not permitted, hence this call will result in an ``EPERM``. This is deliberately different from
1057+
returning a ``EINVAL`` error, denoting an error on the user's side, to simplify the system's behavior
1058+
when ``--await`` is requested. As a result, it's also a simpler model for the user to work with.
1059+
1060+
When awaiting, one may specify a maximum duration that they would like this await request to block for,
1061+
orthogonally to the two intrinsic set timeouts discussed above. If the target awaited state isn't reached
10361062
within the specified duration, then ``EINPROGRESS`` is returned. For that, one should use the argument
10371063
``--await-for=<seconds>``. One could think of ``--await`` as equivalent to ``--await-for=Infinity``.
10381064
While it doesn't make sense to specify both arguments, it is not considered an error. If

src/mds/QuiesceDbManager.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,12 +623,13 @@ int QuiesceDbManager::leader_process_request(RequestContext* req_ctx)
623623
}
624624

625625
if (request.await) {
626+
// quiesce-await is only allowed for sets that are quiescing or quiesced.
626627
// this check may have a false negative for a quiesced set
627628
// that will be released in another request in the same batch
628629
// in that case, this await will be enqueued but then found and completed
629630
// with the same error in `leader_upkeep_awaits`
630-
if ((set.is_releasing() || set.is_released()) && !request.is_release()) {
631-
dout(2) << dset("can't quiesce-await a set that was released (") << set.rstate.state << ")" << dendl;
631+
if (set.rstate.state > QS_QUIESCED && !request.is_release()) {
632+
dout(2) << dset("can't quiesce-await a set in the state: ") << set.rstate.state << dendl;
632633
return EPERM;
633634
}
634635

@@ -1055,7 +1056,7 @@ QuiesceTimeInterval QuiesceDbManager::leader_upkeep_awaits()
10551056
break;
10561057
case QS_EXPIRED:
10571058
case QS_TIMEDOUT:
1058-
rc = ETIMEDOUT;
1059+
rc = ETIMEDOUT;
10591060
break;
10601061
case QS_QUIESCED:
10611062
rc = 0; // fallthrough

src/test/mds/TestQuiesceDb.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,13 +1010,12 @@ TEST_F(QuiesceDbTest, InterruptedQuiesceAwait)
10101010
EXPECT_EQ(ERR(ECANCELED), await3.wait_result());
10111011
EXPECT_EQ(ERR(ECANCELED), await4.wait_result());
10121012

1013-
// awaiting a set in a terminal state should immediately
1014-
// complete with the corresponding error
1015-
ASSERT_EQ(ERR(ECANCELED), run_request([](auto& r) {
1013+
// awaiting a set in a terminal state should be illegal
1014+
EXPECT_EQ(ERR(EPERM), run_request([](auto& r) {
10161015
r.set_id = "set1";
10171016
r.await = sec(100);
10181017
}));
1019-
ASSERT_EQ(ERR(ETIMEDOUT), run_request([](auto& r) {
1018+
EXPECT_EQ(ERR(EPERM), run_request([](auto& r) {
10201019
r.set_id = "set2";
10211020
r.await = sec(100);
10221021
}));
@@ -1082,7 +1081,7 @@ TEST_F(QuiesceDbTest, RepeatedQuiesceAwait) {
10821081

10831082
EXPECT_EQ(QS_EXPIRED, last_request->response.sets.at("set1").rstate.state);
10841083

1085-
EXPECT_EQ(ERR(ETIMEDOUT), run_request([](auto& r) {
1084+
EXPECT_EQ(ERR(EPERM), run_request([](auto& r) {
10861085
r.set_id = "set1";
10871086
r.await = sec(0.1);
10881087
}));

0 commit comments

Comments
 (0)