Project

General

Profile

Actions

Bug #64659

open

mds: switch to using xlists instead of elists

Added by Dhairya Parmar about 2 months ago. Updated 9 days ago.

Status:
New
Priority:
Normal
Category:
Correctness/Safety
Target version:
-
% Done:

0%

Source:
Development
Tags:
Backport:
Regression:
No
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Component(FS):
MDS
Labels (FS):
Pull request ID:
Crash signature (v1):
Crash signature (v2):

Description

elist(size_t o) : _head(NULL), item_offset(o) {}
~elist() { 
  ceph_assert(_head.empty());
}

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0]. Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

while the `xlist` is comparatively simple:

xlist() : _front(0), _back(0), _size(0) {}
~xlist() { 
  ceph_assert(_size == 0);
  ceph_assert(_front == 0);
  ceph_assert(_back == 0);
}

Only MDS code makes use of elists as of now, I think it will be a good step to refactor MDS code to make use of xlist which will help prevent bugs like [0], make code simpler and efficient.

[0] https://tracker.ceph.com/issues/64008
[1] https://tracker.ceph.com/issues/64008#note-9


Related issues 1 (1 open0 closed)

Related to CephFS - Bug #64008: mds: CInode::item_caps used in two different listsPending BackportDhairya Parmar

Actions
Actions #1

Updated by Patrick Donnelly about 2 months ago

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

This is not a bug or a desirable change.

Actions #2

Updated by Venky Shankar about 2 months ago

  • Assignee set to Dhairya Parmar
Actions #3

Updated by Dhairya Parmar about 2 months ago

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

This is not a bug or a desirable change.

Actions #4

Updated by Patrick Donnelly about 2 months ago

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

Actions #5

Updated by Patrick Donnelly about 2 months ago

  • Related to Bug #64008: mds: CInode::item_caps used in two different lists added
Actions #6

Updated by Dhairya Parmar about 2 months ago

Patrick Donnelly wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

So when these elists are replaced with xlists, there is no need keep track of "is this ::item used anywhere", since there isn't any dependency I find relevant to offsets in xlist.h. Take a look at this [0], this makes it so easy to use these items. Why not do the same with the MDS code

[0] https://github.com/ceph/ceph/blob/1c7f8b2488b936d525e344e7fb215be9e99916d2/src/client/MetaRequest.h#L66-L69

Actions #7

Updated by Venky Shankar about 2 months ago

Dhairya Parmar wrote:

Patrick Donnelly wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

So when these elists are replaced with xlists, there is no need keep track of "is this ::item used anywhere", since there isn't any dependency I find relevant to offsets in xlist.h.

Are you sure? Could you explain this with an example?

Actions #8

Updated by Dhairya Parmar about 2 months ago

Venky Shankar wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

So when these elists are replaced with xlists, there is no need keep track of "is this ::item used anywhere", since there isn't any dependency I find relevant to offsets in xlist.h.

Are you sure? Could you explain this with an example?

Take a look at `item_revoking_caps` and `revoking_caps` in locker code. `revoking_caps` makes use of the item `item_revoking_caps` but since it is xlist which by definition doesn't need offset to be provided at the time of initialisation therefore there is no need of making sure there isn't any other linkage of `item_revoking_caps`.

circling to issue of tracker 64008 - if `inodes_with_caps` was an xlist, we dont need this initialisation [0]

[0] https://github.com/ceph/ceph/blob/fce2ded2fdb0b2b9aebc75ee28bf2fc0aa3d99ab/src/mds/SnapRealm.cc#L63

Actions #9

Updated by Venky Shankar about 1 month ago

Dhairya Parmar wrote:

Venky Shankar wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

So when these elists are replaced with xlists, there is no need keep track of "is this ::item used anywhere", since there isn't any dependency I find relevant to offsets in xlist.h.

Are you sure? Could you explain this with an example?

Take a look at `item_revoking_caps` and `revoking_caps` in locker code. `revoking_caps` makes use of the item `item_revoking_caps` but since it is xlist which by definition doesn't need offset to be provided at the time of initialisation therefore there is no need of making sure there isn't any other linkage of `item_revoking_caps`.

So, you are telling using xlist would avoid bugs like the one mentioned in #64008? What stops me from doing:

xlist<A*> list1;
xlist<A*>::item item1;
xlist<A*>::item item2;

list1.push_back(item1);
list1.push_back(item2);

?

Actions #10

Updated by Dhairya Parmar about 1 month ago

Venky Shankar wrote:

Dhairya Parmar wrote:

Venky Shankar wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

Dhairya Parmar wrote:

Patrick Donnelly wrote:

working with elist might lead to severe consequences at times if the same class member is used to initialise multiple elists e.g. [0].

That problem also exists for xlist.

Not only one needs to be highly careful while working with elist but it also induces space overhead where one might need to construct an extra elist to feed its offset the created elist so that no two elists make use of same elist.

It's the offset of the elist<T>::item that determines which list it belongs to. The offset for the ::item is fed to the elist() when it is constructed.

We do have structures like CInode which are part of multiple elist. Please do more research.

So structures being part of multiple elists is not a problem but using the same link/offset in multiple elists is?

Yes. (It can be anyway. You would need guarantees that the ::item can only be used in one of the lists at any given time.)

So when these elists are replaced with xlists, there is no need keep track of "is this ::item used anywhere", since there isn't any dependency I find relevant to offsets in xlist.h.

Are you sure? Could you explain this with an example?

Take a look at `item_revoking_caps` and `revoking_caps` in locker code. `revoking_caps` makes use of the item `item_revoking_caps` but since it is xlist which by definition doesn't need offset to be provided at the time of initialisation therefore there is no need of making sure there isn't any other linkage of `item_revoking_caps`.

So, you are telling using xlist would avoid bugs like the one mentioned in #64008? What stops me from doing:

[...]

?

Yes, I think it should. Exactly, if we make this across all the MDS code, we would not need to make initializations like `need_snapflush_inodes(member_offset(CInode, item_to_flush)), mds(m), mdcache(c) {}`

Actions #11

Updated by Dhairya Parmar 9 days ago

@Venky Shankar any thoughts on this?

Actions

Also available in: Atom PDF