-
Notifications
You must be signed in to change notification settings - Fork 280
cephfs: add support for cephfs file block diff api #1191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This pull request now has conflicts with the target branch. |
b1f1a36 to
d844f5a
Compare
|
@anoopcs9 PTAL |
cephfs/block_diff.go
Outdated
| // struct ceph_file_blockdiff_changedblocks* blocks); | ||
| // | ||
| // void ceph_free_file_blockdiff_buffer(struct ceph_file_blockdiff_changedblocks* blocks); | ||
| func (info *FileBlockDiffInfo) ReadFileBlockDiff() (bool, *FileBlockDiffChangedBlocks, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any case where the bool is true and the pointer is nil? If not the bool seems a bit redundant. Is there something I'm overlooking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@phlogistonjohn, no we don't have such a case.
bool will be true if there are more changed blocks entries and is such a case the pointer will never be nil.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, it seems like we can then simply the return types by dropping the boolean and having the callers test for nil/non-nil in all the cases that were previously using the boolean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pointer points to the current set of changed blocks (nil on error), while the boolean clearly indicates if more entries remain. Without the boolean, callers would need to infer that from the pointer and error, which makes the flow less clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, it seems like we can then simply the return types by dropping the boolean and having the callers test for nil/non-nil in all the cases that were previously using the boolean.
The boolean is used by cephfs function to indicate if the user needs to call ReadFileBlockDiff again for more entries.
We should preserve the behavior intended by cephfs team here.
@vshankar had pointed to this test case in ceph repo so that I could understand the intended usage.
Hope it helps clear the confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, I'm even more confused. There's no boolean in the api we're wrapping it returns ret (an int) and info (input) and blocks (output) arguments.
No bool there at all.
Without the boolean, callers would need to infer that from the pointer and error, which makes the flow less clear
This doesn't seem right to me. Error indicates error, period. At that point the loop should stop and handle the error. If error is not nil the other return value(s) are irrelevant. If there is no error then the client can check the nil-ity of the blocks value or not to determine if the loop needs to continue or not. The extra bool value is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ret(an int) indicated by r is used in the following manner:
r > 0: there will be more changed blocks returned in the next callr == 0: no more changed blocks to be returnedr < 0: there's an errorr
It is confusing but that's how the return value of the function ceph_file_blockdiff is meant to be used.
The following is testcase for this function from https://github.com/ceph/ceph/blob/060b69c6605d88ad06bd1a3b81697abff2bd4ca5/src/test/libcephfs/snapdiff.cc#L410-L430
r = 1;
while (r > 0) {
ceph_file_blockdiff_changedblocks blocks;
r = ceph_file_blockdiff(&info, &blocks);
if (r < 0) {
std::cerr << " Failed to get next changed block, ret:" << r << std::endl;
return r;
}
int nr_blocks = blocks.num_blocks;
struct cblock *b = blocks.b;
while (nr_blocks > 0) {
std::cout << " == [" << b->offset << "~" << b->len << "] == " << std::endl;
if (expected) {
expected->erase(b->offset, b->len);
}
++b;
--nr_blocks;
}
ceph_free_file_blockdiff_buffer(&blocks);
}
In go-ceph implementation to make it simpler,
a boolean is used to indicate if the next function call needs to be made or not.
if ret < 0 {
return false, nil, getError(ret)
}
// if ret == 0 indicates there is no more entries after this call.
noMoreEntries = (ret == 0)
Again,
We should preserve the behavior intended by cephfs team here.
Making any change to the behavior at this go-ceph binding layer may lead to unexpected behavior later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if we go for an extra round I hope we’ll discover that num_blocks is 0 and/or b is NULL which I guess is what John was hinting at.
just another thought: Can we think of a More() method to basically return whether more processing is required or not? Let's say we have a boolean noMoreEntries inside FileBlockDiffInfo which is set to true during init and subsequently updated during read based on the return code for ceph_file_blockdiff() inside ReadFileBlockDiff().
cephfs/block_diff.go
Outdated
| // struct ceph_file_blockdiff_changedblocks* blocks); | ||
| // | ||
| // void ceph_free_file_blockdiff_buffer(struct ceph_file_blockdiff_changedblocks* blocks); | ||
| func (info *FileBlockDiffInfo) ReadFileBlockDiff() (bool, *FileBlockDiffChangedBlocks, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, I'm even more confused. There's no boolean in the api we're wrapping it returns ret (an int) and info (input) and blocks (output) arguments.
No bool there at all.
Without the boolean, callers would need to infer that from the pointer and error, which makes the flow less clear
This doesn't seem right to me. Error indicates error, period. At that point the loop should stop and handle the error. If error is not nil the other return value(s) are irrelevant. If there is no error then the client can check the nil-ity of the blocks value or not to determine if the loop needs to continue or not. The extra bool value is redundant.
47aa6ad to
8120dc3
Compare
8120dc3 to
bbfe44c
Compare
1fe9669 to
9a3b95f
Compare
|
rebased the PR now. |
cephfs/block_diff.go
Outdated
| // struct ceph_file_blockdiff_changedblocks* blocks); | ||
| // | ||
| // void ceph_free_file_blockdiff_buffer(struct ceph_file_blockdiff_changedblocks* blocks); | ||
| func (info *FileBlockDiffInfo) ReadFileBlockDiff() (bool, *FileBlockDiffChangedBlocks, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, if we go for an extra round I hope we’ll discover that num_blocks is 0 and/or b is NULL which I guess is what John was hinting at.
just another thought: Can we think of a More() method to basically return whether more processing is required or not? Let's say we have a boolean noMoreEntries inside FileBlockDiffInfo which is set to true during init and subsequently updated during read based on the return code for ceph_file_blockdiff() inside ReadFileBlockDiff().
966d203 to
6d97db5
Compare
|
@anoopcs9, addressed your reviews. |
6d97db5 to
854dafb
Compare
242586b to
7585456
Compare
7585456 to
68d3c9e
Compare
|
@Mergifyio rebase |
✅ Branch has been successfully rebased |
68d3c9e to
9f96506
Compare
9f96506 to
cc80de5
Compare
|
This pull request now has conflicts with the target branch. |
cc80de5 to
1f7a031
Compare
anoopcs9
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, your latest update seems to have overwritten the space/tab alignment fixes I had pushed earlier. Please make sure that you fetch the latest version from PR before making any changes.
7402a21 to
faaf936
Compare
0c6bd7f to
289b473
Compare
anoopcs9
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve added a comment about the extra care needed for struct ceph_file_blockdiff_result.
Thanks for your patience over the past months, it’s really appreciated.
|
@Mergifyio rebase |
✅ Branch has been successfully rebased |
289b473 to
08e4fe5
Compare
|
@Mergifyio rebase |
This commit adds support for cephfs file block diff APIs which gives a list of changed blocks with in a file between two snapshots. Co-authored-by: Praveen M <[email protected]> Signed-off-by: Rakshith R <[email protected]>
✅ Branch has been successfully rebased |
08e4fe5 to
21934d9
Compare
phlogistonjohn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, thanks
Merge Queue Status✅ The pull request has been merged at 21934d9 This pull request spent 6 seconds in the queue, with no time running CI. Required conditions to merge
|
cephfs: add support for cephfs file block diff api
This commit adds support for cephfs file block diff
APIs which gives a list of changed blocks with in a
file between two snapshots.
Checklist
//go:build ceph_previewmake api-updateto record new APIsNew or infrequent contributors may want to review the go-ceph Developer's Guide including the section on how we track API Status and the API Stability Plan.
The go-ceph project uses mergify. View the mergify command guide for information on how to interact with mergify. Add a comment with
@Mergifyiorebaseto rebase your PR when github indicates that the PR is out of date with the base branch.